🛡️ Nginx 域名证书配置与多域名代理完全指南


🛡️ 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 代理网关:

  1. 模块化管理 :通过 conf.d 实现了"一个域名一个文件",新增服务只需新增配置文件,无需修改主配置。
  2. 安全合规:强制 HTTPS、HTTP/2、安全的加密套件配置。
  3. 全场景覆盖:支持普通 HTTP 代理、WebSocket 代理以及静态资源服务。
  4. 可观测性:详细的日志格式包含上游响应时间,便于性能分析。

建议 :在生产环境中,建议使用 Certbot 配合 Let's Encrypt 实现证书的自动申请与续期,避免证书过期导致服务中断。

相关推荐
paul_chen212 小时前
Vite + Vue SPA 在子路径部署(内外网访问+Nginx 反向代理)
前端·vue.js·nginx
刘~浪地球2 小时前
Nginx + Tomcat 整合实战(四):会话管理与共享详解
运维·nginx·tomcat
刘~浪地球2 小时前
Nginx + Tomcat 整合实战(一):基础环境搭建与整合入门
nginx·tomcat·firefox
为爱停留2 小时前
HTTPS 域名访问与 Nginx 全链路说明
网络协议·nginx·https
he___H3 小时前
Nginx+lua+openresty
nginx·lua·openresty
刘~浪地球4 小时前
Nginx + Tomcat 整合实战(三):负载均衡与集群部署
nginx·tomcat·负载均衡
灰阳阳15 小时前
Dockerfile实践-构建Nginx镜像
运维·nginx·docker·dockerfile
ywlovecjy1 天前
macOs安装docker且在docker上部署nginx+php
nginx·macos·docker
tumeng07111 天前
Linux(CentOS)安装 Nginx
linux·nginx·centos