4、HTTP服务器配置:Nginx/Apache配置引导文件下载、虚拟主机设置、访问控制

HTTP服务器是网络启动协议栈里的“分发中心”。说白了,客户端(比如刚开机的裸机)通过DHCP拿到IP和下一个服务器地址后,就得靠HTTP来拉取引导文件、内核、initrd甚至整个操作系统镜像。

我这些年折腾过不少HTTP服务器,从轻量级的Nginx到功能全面的Apache,各有各的脾气。今天咱们就聊聊怎么把它们配成网络启动的“粮仓”。

4.1 为什么选HTTP而不是TFTP?

很多老教程还在用TFTP,但我在实际项目中吃过它的亏。TFTP只有UDP的69端口,传输效率低,文件大小限制在32MB左右,而且没有认证和加密。你想想看,一个现代Linux内核加initrd动不动就几十MB,TFTP根本扛不住。

HTTP的优势很明显:

  • 无文件大小限制——几GB的ISO镜像也能传
  • 传输效率高——TCP拥塞控制,支持多线程下载
  • 访问控制灵活——IP白名单、用户认证、HTTPS加密
  • 虚拟主机支持——一台服务器服务多个启动场景
我的建议: 新项目直接上HTTP。如果非要兼容老设备,可以HTTP+TFTP双栈,但默认走HTTP。

4.2 Nginx配置:轻量高效的首选

我个人习惯用Nginx做网络启动服务器。它内存占用小,并发能力强,配置语法也简洁。下面是一个典型的PXE引导文件下载配置。

4.2.1 基础配置:引导文件下载

server {
    listen 80;
    server_name boot.example.com;

    # 引导文件根目录
    root /var/www/pxe;

    # 默认索引文件
    index index.html;

    # 日志配置
    access_log /var/log/nginx/pxe_access.log;
    error_log /var/log/nginx/pxe_error.log;

    # 静态文件服务
    location / {
        try_files $uri $uri/ =404;
        autoindex on;
        autoindex_exact_size off;
        autoindex_localtime on;
    }

    # 特定文件类型缓存控制
    location ~* \.(efi|img|iso|kernel|initrd)$ {
        add_header Cache-Control "no-cache, no-store, must-revalidate";
        add_header Pragma "no-cache";
        add_header Expires 0;
    }
}

这里有个关键点:缓存控制。网络启动文件经常更新,如果客户端缓存了旧版本,启动就会失败。所以我强制关闭了这些文件的缓存。

注意: 生产环境中,autoindex on 可能会暴露目录结构。如果担心安全问题,可以关闭自动索引,只允许通过已知路径访问。

4.2.2 虚拟主机设置:多场景隔离

我在一个项目中需要同时服务三个环境:生产、测试、灾备。用虚拟主机来隔离,清晰又安全。

# 生产环境
server {
    listen 80;
    server_name pxe.prod.example.com;
    root /var/www/pxe/prod;

    location / {
        allow 10.0.0.0/8;
        allow 172.16.0.0/12;
        deny all;
    }
}

# 测试环境
server {
    listen 80;
    server_name pxe.test.example.com;
    root /var/www/pxe/test;

    location / {
        allow 10.0.0.0/8;
        allow 192.168.0.0/16;
        deny all;
    }
}

# 灾备环境
server {
    listen 80;
    server_name pxe.dr.example.com;
    root /var/www/pxe/dr;

    location / {
        allow 10.0.0.0/8;
        deny all;
    }
}

每个虚拟主机绑定不同的域名,DHCP服务器根据客户端MAC或子网分配不同的next-server地址。这样测试环境怎么折腾都不会影响生产。

4.2.3 访问控制:IP白名单与限速

网络启动服务器不能对全网开放,否则谁都能来拉你的内核文件。我一般用IP白名单+连接限速双重保护。

server {
    listen 80;
    server_name pxe.internal.example.com;

    root /var/www/pxe;

    # IP白名单
    location / {
        allow 10.0.0.0/8;
        allow 172.16.0.0/12;
        allow 192.168.0.0/16;
        deny all;
    }

    # 限速:每个连接最大1MB/s,防止带宽被占满
    location /images/ {
        limit_rate 1m;
        limit_conn per_ip 5;
    }

    # 小文件不限速
    location /boot/ {
        limit_rate 0;
    }
}

我曾经遇到过一个问题:几百台机器同时启动,Nginx默认的连接数限制被瞬间打满。后来加了 limit_conn 和 limit_rate,情况就好多了。

4.3 Apache配置:功能全面的备选方案

虽然我偏爱Nginx,但Apache在某些场景下更合适。比如你需要复杂的URL重写规则,或者要集成LDAP认证,Apache的模块化架构就很有优势。

4.3.1 基础配置:引导文件下载

<VirtualHost *:80>
    ServerName pxe.example.com
    DocumentRoot /var/www/pxe

    <Directory /var/www/pxe>
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>

    # 关闭缓存
    <FilesMatch "\.(efi|img|iso|kernel|initrd)$">
        Header set Cache-Control "no-cache, no-store, must-revalidate"
        Header set Pragma "no-cache"
        Header set Expires 0
    </FilesMatch>

    ErrorLog ${APACHE_LOG_DIR}/pxe_error.log
    CustomLog ${APACHE_LOG_DIR}/pxe_access.log combined
</VirtualHost>

4.3.2 虚拟主机与访问控制

Apache的虚拟主机配置和Nginx思路一样,但语法更啰嗦一些。不过它的 mod_authz_host 模块在IP控制上很灵活。

<VirtualHost *:80>
    ServerName pxe.prod.example.com
    DocumentRoot /var/www/pxe/prod

    <Directory /var/www/pxe/prod>
        Options Indexes FollowSymLinks
        AllowOverride None

        # IP白名单
        Require ip 10.0.0.0/8
        Require ip 172.16.0.0/12
        Require ip 192.168.0.0/16
        # 拒绝其他所有
        Require all denied
    </Directory>
</VirtualHost>
关键区别: Apache的 Require 指令是叠加的——多个 Require ip 之间是“或”关系,而 Require all denied 是最终屏障。Nginx的 allow/deny 则是顺序匹配,先匹配先生效。

4.4 目录结构规范

不管用哪种服务器,目录结构一定要清晰。我习惯这样组织:

/var/www/pxe/
├── boot/               # 引导文件(grub.efi, shim.efi等)
│   ├── grubx64.efi
│   └── shimx64.efi
├── images/             # 操作系统镜像
│   ├── ubuntu-22.04/
│   ├── centos-9/
│   └── debian-12/
├── kernel/             # 内核和initrd
│   ├── vmlinuz-5.15.0
│   └── initrd.img-5.15.0
├── config/             # 引导配置文件
│   ├── grub.cfg
│   └── ipxe.cfg
└── iso/                # ISO镜像(用于iPXE直接启动)
    ├── ubuntu-22.04.iso
    └── centos-9.iso

这个结构的好处是:权限控制可以细化到目录级别。比如 boot/ 目录只允许特定IP访问,images/ 目录可以限速,config/ 目录只读。

4.5 性能调优要点

参数 Nginx Apache 说明
最大连接数 worker_connections 1024 MaxRequestWorkers 256 根据并发客户端数调整
超时时间 send_timeout 60s Timeout 60 网络启动时客户端可能较慢
文件描述符 worker_rlimit_nofile 65535 RLimitFile 65535 大并发场景必须调高
KeepAlive keepalive_timeout 65 KeepAlive On 建议开启,减少连接建立开销

嗯,这里要注意:不要盲目调大参数。我见过有人把 worker_connections 设成 65535,结果内存直接爆了。要根据实际硬件和并发量来算。

4.6 知识体系总览

下面这张图把HTTP服务器配置的核心逻辑串起来了。从DHCP拿到next-server开始,到客户端最终拉取文件启动,每一步都离不开HTTP服务器的正确配置。

HTTP服务器配置核心逻辑 DHCP分配next-server 客户端HTTP请求 虚拟主机匹配 访问控制(IP白名单) 文件服务(root目录) 限速 & 缓存控制 客户端成功启动 关键配置项 • 监听端口(80/443) • 服务器名称(域名) • 文档根目录 • 日志路径 常见陷阱 • 缓存未关闭导致旧文件 • 权限配置错误 • 连接数限制过低 • 防火墙未放行端口

从图上能看出来,整个流程是串行的——任何一个环节出问题,客户端都启动不了。我排查问题时,就按这个顺序一步步查:DHCP有没有给对地址?HTTP能不能通?虚拟主机匹配上了吗?IP白名单有没有拦住?文件路径对不对?

我的调试技巧: 在客户端用 curl -v http://pxe-server/boot/grubx64.efi 测试连通性。如果返回404,先检查文件路径;如果返回403,查访问控制;如果卡住不动,查防火墙和限速配置。

好了,HTTP服务器配置这块就聊到这儿。记住一个原则:先通后优。先把文件能正常下载跑通,再慢慢调性能和安全。别一上来就搞HTTPS、限速、虚拟主机一大堆,出了问题反而不好定位。