20. Web 服务配置
本章介绍 RHEL 9 上 Apache(httpd)和 Nginx 两大主流 Web 服务器的安装与核心配置:虚拟主机、HTTPS、反向代理与负载均衡。Web 服务是业务应用层的入口,也是第 21 章数据库和后续服务集成的前端层。
20.1 前提条件
- 已完成第三阶段全部配置(第 15–19 章)。
- 通过 SecureCRT(SSH 端口 2222)以
ops用户、密钥认证方式登录192.168.1.100,执行sudo -i切换至 root 环境。 - SELinux 处于 Enforcing 模式,firewalld 已启用(第 12 章)。
- 官方仓库和 EPEL 仓库已启用(第 7 章)。
本章全局参数
| 参数 | 值 |
|---|---|
| 主机名 / IP | linuxdc / 192.168.1.100 |
| 虚拟主机域名 | site1.linuxdc.local |
| 反向代理后端 | 192.168.1.101:8080 |
| 负载均衡后端池 | 192.168.1.101:80、192.168.1.102:80 |
Apache 与 Nginx 端口冲突
Apache 和 Nginx 默认均监听 80/443 端口,不能同时绑定同一端口。本章先完整配置 Apache,再停止 Apache 后演示 Nginx 配置,避免端口冲突。
20.2 Apache 配置
20.2.1 安装与启动
dnf install -y httpd mod_ssl
systemctl enable --now httpd
systemctl status httpd
开放防火墙:
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
创建默认测试页面:
echo "<h1>Hello from Apache on linuxdc</h1>" > /var/www/html/index.html
# 修复 SELinux 上下文
restorecon -Rv /var/www/html/
验证:
curl http://localhost
curl http://192.168.1.100
检查点
curl http://192.168.1.100 返回 Hello from Apache on linuxdc。
20.2.2 配置虚拟主机
虚拟主机使单台服务器托管多个域名站点,是企业多站点部署的标准方式。
# 创建站点目录
mkdir -p /var/www/site1/html
echo "<h1>Site1 - linuxdc</h1>" > /var/www/site1/html/index.html
# 设置目录所有者与 SELinux 上下文
chown -R apache:apache /var/www/site1/
semanage fcontext -a -t httpd_sys_content_t "/var/www/site1(/.*)?"
restorecon -Rv /var/www/site1/
创建虚拟主机配置文件:
tee /etc/httpd/conf.d/site1.conf << 'EOF'
<VirtualHost *:80>
ServerName site1.linuxdc.local
ServerAlias www.site1.linuxdc.local
DocumentRoot /var/www/site1/html
<Directory /var/www/site1/html>
Options -Indexes +FollowSymLinks
AllowOverride None
Require all granted
</Directory>
ErrorLog /var/log/httpd/site1-error.log
CustomLog /var/log/httpd/site1-access.log combined
</VirtualHost>
EOF
# 验证配置语法(有错误时会报告具体行号)
apachectl configtest
systemctl reload httpd
添加本地 DNS 解析并验证:
echo "192.168.1.100 site1.linuxdc.local" >> /etc/hosts
curl http://site1.linuxdc.local
检查点
curl http://site1.linuxdc.local 返回 Site1 - linuxdc。
20.2.3 配置 HTTPS
自签名证书(实验环境):
# 生成 RSA 2048 位自签名证书(有效期 365 天)
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/pki/tls/private/linuxdc.key \
-out /etc/pki/tls/certs/linuxdc.crt \
-subj "/CN=site1.linuxdc.local/O=linuxdc/C=CN"
# 设置私钥权限
chmod 600 /etc/pki/tls/private/linuxdc.key
创建 SSL 虚拟主机配置:
tee /etc/httpd/conf.d/site1-ssl.conf << 'EOF'
<VirtualHost *:443>
ServerName site1.linuxdc.local
DocumentRoot /var/www/site1/html
SSLEngine on
SSLCertificateFile /etc/pki/tls/certs/linuxdc.crt
SSLCertificateKeyFile /etc/pki/tls/private/linuxdc.key
# 安全加固:禁用不安全协议和弱密码套件
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite HIGH:!aNULL:!MD5:!3DES
<Directory /var/www/site1/html>
Require all granted
</Directory>
ErrorLog /var/log/httpd/site1-ssl-error.log
CustomLog /var/log/httpd/site1-ssl-access.log combined
</VirtualHost>
EOF
apachectl configtest && systemctl reload httpd
# -k 参数跳过自签名证书验证
curl -k https://site1.linuxdc.local
生产环境:Let's Encrypt 免费证书
生产环境(需公网域名和 80/443 可达):
dnf install -y certbot python3-certbot-apache
certbot --apache -d your-domain.com
systemctl enable --now certbot-renew.timer
certbot-renew.timer 每天自动检查并在到期前 30 天续期,实现证书免运维管理。
20.2.4 HTTP 强制跳转 HTTPS
生产环境中,所有 HTTP 请求应自动重定向到 HTTPS:
# 修改 site1.conf,在 <VirtualHost *:80> 内添加重定向
tee /etc/httpd/conf.d/site1.conf << 'EOF'
<VirtualHost *:80>
ServerName site1.linuxdc.local
ServerAlias www.site1.linuxdc.local
# 永久重定向(301)到 HTTPS
RewriteEngine on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</VirtualHost>
EOF
apachectl configtest && systemctl reload httpd
验证重定向:
# -L 跟随重定向,-I 只显示响应头
curl -LI http://site1.linuxdc.local 2>&1 | grep -E "HTTP|Location"
20.3 Nginx 配置
20.3.1 安装与启动
停止 Apache 以释放 80/443 端口:
systemctl stop httpd
systemctl disable httpd
安装并启动 Nginx:
dnf install -y nginx
systemctl enable --now nginx
systemctl status nginx
创建测试页面:
echo "<h1>Hello from Nginx on linuxdc</h1>" > /usr/share/nginx/html/index.html
restorecon -Rv /usr/share/nginx/html/
# 验证配置语法
nginx -t
curl http://localhost
检查点
nginx -t 输出 syntax is ok 和 test is successful;curl http://localhost 返回正确内容。
20.3.2 配置反向代理
将外部请求转发至后端应用服务器(192.168.1.101:8080):
tee /etc/nginx/conf.d/proxy.conf << 'EOF'
server {
listen 80;
server_name proxy.linuxdc.local;
location / {
proxy_pass http://192.168.1.101:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 10s;
proxy_read_timeout 30s;
proxy_send_timeout 30s;
}
}
EOF
nginx -t && systemctl reload nginx
SELinux 允许 Nginx 发起出站网络连接(反向代理必须配置):
setsebool -P httpd_can_network_connect on
# 验证布尔值已设置
getsebool httpd_can_network_connect
20.3.3 配置负载均衡
tee /etc/nginx/conf.d/lb.conf << 'EOF'
upstream backend_pool {
least_conn; # 最少连接算法(默认 round-robin)
server 192.168.1.101:80 weight=2; # 权重 2,承载更多流量
server 192.168.1.102:80 weight=1;
keepalive 16; # 保持后端长连接,减少握手开销
}
server {
listen 80;
server_name lb.linuxdc.local;
location / {
proxy_pass http://backend_pool;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Connection ""; # keepalive 必须清空 Connection 头
}
}
EOF
nginx -t && systemctl reload nginx
Nginx 负载均衡算法说明:
| 算法 | 指令 | 适用场景 |
|---|---|---|
| 轮询(默认) | 无需指定 | 各后端处理能力相近 |
| 权重轮询 | weight=N |
后端服务器性能差异明显 |
| 最少连接 | least_conn |
请求处理时间差异大 |
| IP 哈希 | ip_hash |
需要会话粘滞(同一 IP 固定后端) |
20.4 常见问题与排查
| 问题现象 | 排查步骤 |
|---|---|
| httpd / nginx 启动失败 | apachectl configtest 或 nginx -t;journalctl -u httpd -n 30 |
| 80 端口被占用 | ss -tulnp | grep :80 找出占用进程 |
| 访问返回 403 Forbidden | 检查目录权限;ls -lZ /var/www/;restorecon -Rv 修复 SELinux 上下文 |
| SELinux 阻止反向代理连接 | setsebool -P httpd_can_network_connect on |
| 虚拟主机配置未生效 | apachectl -S 查看虚拟主机解析结果;确认 DNS 或 /etc/hosts 解析正确 |
| HTTPS 证书错误 | 确认证书路径正确;openssl x509 -in /etc/pki/tls/certs/linuxdc.crt -text -noout 查看证书信息 |
# Apache 综合诊断
apachectl -S # 虚拟主机解析情况
tail -f /var/log/httpd/error_log # 错误日志实时追踪
# Nginx 综合诊断
journalctl -u nginx -f # 系统日志实时追踪
tail -f /var/log/nginx/error.log # Nginx 错误日志
20.5 实践任务
- 登录
linuxdc(SecureCRT 端口 2222,ops用户,密钥认证,sudo -i切换 root)。 - 安装 Apache,创建测试页面,验证
curl http://192.168.1.100返回正确内容。 - 配置虚拟主机
site1.linuxdc.local,添加/etc/hosts解析,验证访问。 - 配置自签名 HTTPS,验证
curl -k https://site1.linuxdc.local正常返回。 - 配置 HTTP → HTTPS 重定向,用
curl -LI验证 301 跳转。 - 停止 Apache,安装 Nginx,配置反向代理,执行
nginx -t验证语法。 - 配置 upstream 负载均衡块,执行
nginx -t确认语法无误。
20.6 自测问题
Q1:Apache 配置修改后,应使用 reload 还是 restart?
配置修改后优先使用 systemctl reload httpd(等同于 apachectl graceful)。reload 让主进程重读配置并通知工作进程在处理完当前请求后平滑替换,不中断已有连接,业务零感知。restart 先停止再启动进程,所有正在处理的请求会被强制中断。生产环境应始终优先使用 reload,restart 仅用于需要重新加载共享库(如安装 mod_ssl)等特殊场景。
Q2:Nginx 反向代理为何必须执行 setsebool -P httpd_can_network_connect on?
SELinux 默认不允许 httpd_t 类型进程(含 Nginx)主动发起对外网络连接,此限制可防止被攻陷的 Web 进程横向扩展。反向代理需要 Nginx 主动连接后端服务器,属于出站连接,必须通过此布尔值显式授权。未设置时,连接被 SELinux 静默拒绝,/var/log/audit/audit.log 中出现 avc: denied 记录,但错误页面仅显示 502 Bad Gateway,排查时容易误认为是网络问题。
Q3:Nginx upstream 中 least_conn 与默认 round-robin 的本质区别是什么?
round-robin 按顺序轮流分发请求,不考虑后端当前的连接负载,适合请求处理时间相近的场景;least_conn 将新请求发往当前活跃连接数最少的后端,适合请求处理时间差异大的场景(如大文件下载与普通 API 混合),能更均衡地利用后端资源,避免慢请求堆积在某台后端导致过载。
20.7 章节总结
本章完成了 RHEL 9 上 Apache 和 Nginx 的核心配置:虚拟主机(多站点托管)、HTTPS(自签名证书与 Let's Encrypt 自动续期)、HTTP 强制跳转 HTTPS(301 重定向)、Nginx 反向代理(含 SELinux 授权)与加权负载均衡(least_conn 算法)。重点强调了每次配置变更后使用 apachectl configtest / nginx -t 验证语法,以及优先使用 reload 而非 restart 的生产最佳实践。