1. 为什么需要Nginx多域名多证书配置?
在真实的线上环境中,我们经常会遇到这样的需求场景:一个服务器需要同时承载多个业务系统,每个系统都有独立的域名和SSL证书。比如一家电商公司可能同时运营主站、移动端、商家后台、开放平台等多个服务,每个服务都需要独立的域名(如www.example.com、m.example.com、seller.example.com、api.example.com)和对应的HTTPS证书。
传统做法是为每个服务单独部署一台服务器,这显然会造成资源浪费和管理成本上升。而Nginx作为高性能的反向代理服务器,其虚拟主机(Server Block)功能可以完美解决这个问题——通过单实例Nginx同时监听80和443端口,根据访问的域名不同,将请求路由到不同的上游服务,并自动匹配对应的SSL证书。
这种架构的优势主要体现在三个方面:
- 硬件成本节约:减少服务器数量,降低IDC费用
- 运维效率提升:统一入口管理,避免多实例配置同步问题
- 性能优化:复用Nginx的epoll高并发模型,避免多进程资源竞争
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 基础环境准备与Nginx安装
2.1 服务器基础要求
推荐使用Linux系统(如CentOS 7+/Ubuntu 20.04+),配置建议:
- 至少2核CPU、4GB内存(证书较多时需要更高内存)
- 开启80/443端口防火墙规则
- 域名已完成DNS解析指向服务器IP
注意:生产环境强烈建议禁用HTTP/1.0,在nginx.conf的http块中添加
proxy_http_version 1.1;
2.2 Nginx安装最佳实践
以CentOS为例,推荐通过官方仓库安装最新稳定版:
bash复制# 添加Nginx官方仓库
cat > /etc/yum.repos.d/nginx.repo <<EOF
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/\$releasever/\$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
EOF
# 安装并设置开机自启
yum install -y nginx
systemctl enable --now nginx
验证安装:
bash复制nginx -v
# 应输出类似:nginx version: nginx/1.25.3
3. 多域名多证书配置实战
3.1 证书准备与管理
假设我们需要配置以下三个服务:
- 主站 - www.example.com
- 管理后台 - admin.example.com
- API服务 - api.example.com
推荐证书存放结构:
code复制/etc/nginx/ssl/
├── www.example.com/
│ ├── fullchain.pem
│ └── privkey.pem
├── admin.example.com/
│ ├── fullchain.pem
│ └── privkey.pem
└── api.example.com/
├── fullchain.pem
└── privkey.pem
证书权限设置(关键安全步骤):
bash复制chmod 600 /etc/nginx/ssl/*/privkey.pem
chown -R nginx:nginx /etc/nginx/ssl
3.2 核心配置详解
在/etc/nginx/conf.d/下创建独立配置文件(示例为api.conf):
nginx复制server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name api.example.com;
# 证书配置
ssl_certificate /etc/nginx/ssl/api.example.com/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/api.example.com/privkey.pem;
# SSL优化参数
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
# 反向代理配置
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# WebSocket支持
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# 静态文件缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
}
# HTTP跳转HTTPS
server {
listen 80;
listen [::]:80;
server_name api.example.com;
return 301 https://$host$request_uri;
}
3.3 配置复用技巧
对于多个相似服务,可以使用Nginx的map功能实现配置复用。在nginx.conf的http块中添加:
nginx复制map $host $backend_port {
hostnames;
default 3000;
www.example.com 8080;
admin.example.com 8081;
api.example.com 3000;
}
map $host $ssl_cert_path {
hostnames;
default /etc/nginx/ssl/default/fullchain.pem;
www.example.com /etc/nginx/ssl/www.example.com/fullchain.pem;
admin.example.com /etc/nginx/ssl/admin.example.com/fullchain.pem;
api.example.com /etc/nginx/ssl/api.example.com/fullchain.pem;
}
map $host $ssl_key_path {
hostnames;
default /etc/nginx/ssl/default/privkey.pem;
www.example.com /etc/nginx/ssl/www.example.com/privkey.pem;
admin.example.com /etc/nginx/ssl/admin.example.com/privkey.pem;
api.example.com /etc/nginx/ssl/api.example.com/privkey.pem;
}
然后server配置可以简化为:
nginx复制server {
listen 443 ssl http2;
server_name ~^(?<domain>.+)$;
ssl_certificate $ssl_cert_path;
ssl_certificate_key $ssl_key_path;
location / {
proxy_pass http://127.0.0.1:$backend_port;
# ...其他proxy配置
}
}
4. 高级优化与故障排查
4.1 OCSP Stapling配置
提升HTTPS握手效率的关键配置:
nginx复制ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/ssl/ca-bundle.pem; # 需要包含中间证书
resolver 8.8.8.8 1.1.1.1 valid=300s;
resolver_timeout 5s;
验证OCSP状态:
bash复制openssl s_client -connect example.com:443 -status -servername example.com < /dev/null 2>&1 | grep -i "OCSP response"
4.2 常见问题排查
问题1:证书不匹配错误(SSL_ERROR_BAD_CERT_DOMAIN)
- 检查证书的SAN(Subject Alternative Name)是否包含当前域名
- 使用命令验证:
openssl x509 -in fullchain.pem -text -noout | grep -A1 "Subject Alternative Name"
问题2:Nginx报错"SSL: error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch"
- 确保证书和私钥匹配:
bash复制openssl x509 -noout -modulus -in fullchain.pem | openssl md5 openssl rsa -noout -modulus -in privkey.pem | openssl md5 - 两个MD5值必须相同
问题3:HSTS配置注意事项
- 一旦启用需谨慎,浏览器会强制HTTPS:
nginx复制add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; - 测试阶段建议设置较短有效期:
nginx复制add_header Strict-Transport-Security "max-age=300";
4.3 性能监控指标
关键监控项及获取方式:
| 指标 | 获取命令/位置 | 健康阈值 |
|---|---|---|
| 活跃连接数 | `nginx -T 2>/dev/null | grep active` |
| SSL握手失败率 | Nginx error_log 搜索"SSL_do_handshake" | < 0.1% |
| 证书过期时间 | openssl x509 -enddate -noout -in cert.pem |
> 30天 |
| 上游响应时间 | 在log_format中添加$upstream_response_time | < 500ms |
5. 自动化与持续维护
5.1 证书自动续期
使用Certbot实现自动化:
bash复制# 安装Certbot
yum install -y certbot python3-certbot-nginx
# 为多个域名申请证书(需提前配置好DNS解析)
certbot --nginx -d www.example.com -d admin.example.com -d api.example.com
# 设置自动续期
echo "0 3 * * * /usr/bin/certbot renew --quiet --post-hook 'systemctl reload nginx'" | crontab -
5.2 配置版本化管理
推荐配置管理方案:
- 使用Git管理
/etc/nginx/目录bash复制cd /etc git init git add nginx/ git commit -m "Initial Nginx config" - 添加pre-commit钩子检查语法:
bash复制cat > /etc/nginx/.git/hooks/pre-commit <<'EOF' #!/bin/sh if ! nginx -t; then echo "Nginx config test failed!" exit 1 fi EOF chmod +x /etc/nginx/.git/hooks/pre-commit
5.3 灰度发布策略
通过Nginx实现按比例分流:
nginx复制split_clients "${remote_addr}${http_user_agent}" $variant {
50% "v1";
50% "v2";
}
server {
location / {
if ($variant = "v2") {
proxy_pass http://new_backend;
}
proxy_pass http://default_backend;
}
}
在实际运维中,我发现最容易被忽视的是SSL会话票据的定期轮换。建议在nginx.conf中添加:
nginx复制ssl_session_ticket_key /etc/nginx/ssl/ticket.key;
并定期(如每周)通过以下命令更新密钥:
bash复制openssl rand 80 > /etc/nginx/ssl/ticket.key
systemctl reload nginx
