🛡️ Nginx 域名证书配置与多域名代理完全指南 (优化版)
1. 核心架构与目录规划
合理的目录结构是管理多域名的基础。建议采用模块化设计,将配置与证书分离。
1.1 推荐目录结构
为了便于维护和备份,建议使用如下结构:
bash
nginx/
├── conf/ # Nginx 配置文件目录
│ ├── nginx.conf # 主配置文件
│ ├── ssl/ # SSL 证书专用目录
│ │ ├── xxx.abc.com.pem
│ │ ├── xxx.abc.com.key
│ │ └── ... # 多个域名证书
│ └── conf.d/ # 虚拟主机配置目录 (模块化)
│ ├── xxx.abc.com.conf
│ └── yyy.def.com.conf
├── logs/ # 日志目录 (建议挂载外部)
└── html/ # 静态资源目录 (可选)
1.2 主配置文件优化 (nginx.conf)
核心在于引入 conf.d 目录,确保自动加载所有子配置。
nginx
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
use epoll; # 高并发优化
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 日志格式优化
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'rt=$request_time uct="$upstream_connect_time" '
'uht="$upstream_header_time" urt="$upstream_response_time"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on; # 提升传输效率
tcp_nodelay on;
keepalive_timeout 65;
# 安全与性能参数
client_max_body_size 20M; # 允许上传文件大小
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
# ⭐ 核心加载指令 ⭐
include /etc/nginx/conf.d/*.conf;
}
💡 优化点 :增加了
gzip压缩、client_max_body_size上传限制以及更详细的日志格式,便于排查问题。
2. SSL 证书配置与安全加固
2.1 证书准备
将下载的证书文件放入 nginx/conf/ssl/ 目录。
- 文件类型 :
.pem或.crt:证书文件(包含公钥和证书链)。.key:私钥文件(切勿泄露)。
2.2 基础 HTTPS 配置模板
创建文件 nginx/conf/conf.d/your-domain.com.conf。
nginx
server {
listen 443 ssl http2; # 开启 HTTP/2 提升性能
server_name your-domain.com www.your-domain.com;
# SSL 证书路径 (基于 conf 目录的相对路径)
ssl_certificate ssl/your-domain.com.pem;
ssl_certificate_key ssl/your-domain.com.key;
# SSL 会话与协议优化
ssl_session_timeout 5m;
ssl_protocols TLSv1.2 TLSv1.3; # 禁用老旧不安全的 TLSv1/TLSv1.1
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4:!DH:!DHE;
ssl_prefer_server_ciphers on;
# HSTS 强制 HTTPS (生产环境建议开启)
# add_header Strict-Transport-Security "max-age=31536000" always;
# 默认处理
location / {
return 401; # 或者指向具体的前端目录 root /usr/share/nginx/html;
}
}
2.3 HTTP 自动跳转 HTTPS (SEO 友好)
在同一个配置文件或单独创建 redirect.conf 中添加:
nginx
server {
listen 80;
server_name your-domain.com www.your-domain.com;
# 301 永久重定向,利于搜索引擎收录
return 301 https://$server_name$request_uri;
}
3. 多域名代理实战场景
Nginx 的强大之处在于可以根据域名将流量分发到不同的后端服务(如 Docker 容器、本地端口)。
3.1 场景一:API 接口代理
将 api.example.com 的请求转发到内网 9007 端口。
nginx
location /api/ {
# 修复 Host 头,防止后端应用获取到 localhost
proxy_set_header Host $http_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; # 告知后端原始协议 (https)
# ⭐ 关键:proxy_pass 末尾的 / 决定了路径重写方式 ⭐
# 方式1: 结尾带/ (路径剥离)
# 请求: https://api.example.com/api/users -> 转发: http://localhost:9007/api/users
proxy_pass http://localhost:9007/;
# 方式2: 结尾不带/ (路径透传)
# proxy_pass http://localhost:9007/api/;
# 请求: https://api.example.com/api/users -> 转发: http://localhost:9007/api/api/users (容易出错)
# 超时设置
proxy_connect_timeout 30s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
}
3.2 场景二:多服务混合代理
在一个配置文件中处理前端静态资源、API 和 WebSocket。
nginx
# 文件: app.example.com.conf
server {
listen 443 ssl;
server_name app.example.com;
# ... SSL 配置省略 ...
# 1. 前端 SPA 应用 (Vue/React)
location / {
proxy_pass http://localhost:3000; # 前端开发服务器
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
# 2. 后端 API
location /api/ {
proxy_pass http://localhost:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# 3. WebSocket 服务 (必须特殊配置)
location /ws/ {
proxy_pass http://localhost:8081/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; # 升级协议头
proxy_set_header Connection "upgrade"; # 升级连接
proxy_set_header Host $host;
}
}
4. 运维与故障排查
4.1 配置检查与重载
Nginx 支持平滑重启,无需中断服务。
bash
# 1. 检查配置文件语法 (非常重要!)
nginx -t
# 2. 如果语法正确,重载配置
nginx -s reload
# 3. 或者使用 Docker 命令
# docker exec nginx-container nginx -s reload
4.2 常见错误速查表
| 错误现象 | 可能原因 | 解决方案 |
|:---------------------------------------------|:----------------|:-----------------------------------------------------------------|--------------------------------------|
| 400 Bad Request / 403 Forbidden | 请求头过大或 Host 不匹配 | 检查 proxy_set_header Host 是否正确;增加 large_client_header_buffers |
| 502 Bad Gateway | 后端服务未启动或端口错误 | 检查 proxy_pass 的 IP 和端口是否可达;确认后端服务状态 |
| SSL_ERROR_BAD_CERT_DOMAIN | 证书域名不匹配 | 确保证书是为当前访问的域名签发的;检查 server_name |
| nginx: [emerg] bind() to 0.0.0.0:80 failed | 端口被占用 | 运行 `netstat -tlnp | grep :80` 查看占用进程并 kill,或修改 Nginx 端口 |
| Permission denied (证书) | 文件权限问题 | 确保 Nginx 用户 (如 nginx 或 www-data) 有读取 .key 文件的权限 |
4.3 Docker Compose 部署示例
如果你使用 Docker,这是推荐的部署方式:
yaml
version: '3'
services:
nginx:
image: nginx:alpine
container_name: nginx-proxy
ports:
- "80:80"
- "443:443"
volumes:
# 挂载配置文件
- ./nginx/conf/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/conf/conf.d:/etc/nginx/conf.d
# 挂载证书 (敏感数据)
- ./nginx/conf/ssl:/etc/nginx/ssl
# 挂载日志 (方便查看)
- ./nginx/logs:/var/log/nginx
# 特权模式 (仅在需要监听 80/443 且宿主机端口冲突时考虑,通常不需要)
# privileged: true
restart: always
5. 总结与最佳实践
通过上述配置,你构建了一个企业级的 Nginx 代理网关:
- 模块化管理 :通过
conf.d实现了"一个域名一个文件",新增服务只需新增配置文件,无需修改主配置。 - 安全合规:强制 HTTPS、HTTP/2、安全的加密套件配置。
- 全场景覆盖:支持普通 HTTP 代理、WebSocket 代理以及静态资源服务。
- 可观测性:详细的日志格式包含上游响应时间,便于性能分析。
建议 :在生产环境中,建议使用 Certbot 配合 Let's Encrypt 实现证书的自动申请与续期,避免证书过期导致服务中断。