Skip to content

NGINX 配置指南

本指南提供了Nginx 配置要点和最佳实践,作为参考。

NGINX (发音为 "engine-x") 是一款 HTTP Web 服务器、反向代理、内容缓存、负载均衡器、TCP/UDP 代理服务器和邮件代理服务器,在 2-clause BSD 许可协议下发行,具有高性能、高可靠性、丰富的模块化支持和简单易用的优势。

一、Nginx 配置原则

在设计和实施 Nginx 配置时,以下原则至关重要:

  1. 模块化 (Modularity): 不要把所有配置都堆在一个文件里。采用 include 指令将不同服务(如网站A、网站B)、不同功能(如 SSL 配置参数、公共代理头)的配置拆分成独立的、可管理的片段文件。这提升了配置的可读性和维护性。
  2. 安全性 (Security): Nginx 是应用的第一层防御。应确保配置遵循最小权限原则,强制使用 HTTPS,并实施适当的访问控制和错误信息处理策略。
  3. 高性能 (Performance): Nginx 生而为快。充分利用 Nginx 的静态文件服务能力、缓存机制、Gzip 压缩等特性,以最小化系统资源消耗并优化响应速度。
  4. 可观测性 (Observability): 格式规范的日志配置是排查问题、分析流量和快速定位问题的基础。
  5. 幂等性 (Idempotency): 建议使用版本控制管理 Nginx 配置文件,确保配置变更可追溯、可回滚,并保证部署的一致性。

二、Nginx 核心配置结构

通常,Nginx 的配置由 nginx.conf 文件和其通过 include指令引入的其他配置文件组成。

2.1 nginx.conf - 全局配置

该文件定义 Nginx 服务器的全局行为和核心模块参数。通常位于/usr/local/nginx/conf/etc/nginx/usr/local/etc/nginx 之一。

nginx
# user 指令设置 Nginx worker 进程的运行用户和用户组。
# 生产环境通常使用非特权用户,例如 'www-data' 或 'nginx'。
user www-data; 

# worker_processes 定义了 Nginx worker 进程的数量。
# 通常设置为 auto,让 Nginx 自动检测 CPU 核心数并启动相应数量的 worker 进程。
# 手动设置时,通常将其配置为 CPU 核心数。
worker_processes auto; 

# error_log 指定了错误日志的路径和级别。
# 级别从低到高:debug, info, notice, warn, error, crit, alert, emerg。
# 生产环境通常使用 'warn' 或 'error' 级别。
error_log /var/log/nginx/error.log warn; 

# pid 文件路径,存储主进程的进程 ID。
pid /run/nginx.pid; 

# load_module 指令用于加载动态链接模块 (例如 Nginx Plus 或第三方模块)。
# 示例:load_module modules/ngx_http_foo_module.so;

events {
    # worker_connections 定义单个 worker 进程可以同时处理的最大连接数。
    # 此值与 worker_processes 共同决定 Nginx 的最大并发连接数 (worker_processes * worker_connections)。
    # 操作系统级别的 ulimit 也需要相应调整。
    worker_connections 1024; 
    
    # multi_accept on 允许 worker 进程一次性接受所有新连接,而不是一个一个地接受。
    # 在高并发场景下可以提高性能。
    multi_accept on;
}

http {
    # include 指令用于引入其他配置文件。
    # 最佳实践是把大部分 server 相关的配置放在 conf.d 或 sites-enabled 目录下,并通过 include 引入。
    include /etc/nginx/mime.types; # 提供 MIME 类型映射,确保静态文件能正确识别和传输。
    default_type application/octet-stream; # 未匹配 MIME 类型时的默认值。

    # log_format 定义访问日志的格式,main 格式为常用配置。
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    # access_log 定义了访问日志的路径和使用的日志格式。
    access_log /var/log/nginx/access.log main; 

    # sendfile 指令开启后,Nginx 会使用 sendfile() 系统调用来传输文件,
    # 减少 CPU 拷贝,直接在内核态完成数据传输,提高静态文件服务的性能。
    sendfile on; 
    
    # tcp_nopush 指令只在 sendfile 开启时有效。
    # 开启后,Nginx 会在响应头和首个数据包一起发送,或者在数据包填满后发送,减少网络包的数量,提高传输效率。
    tcp_nopush on; 
    
    # tcp_nodelay 指令在保持长连接时非常有用。
    # 开启后,Nginx 不会缓冲数据,而是立即发送,减少网络延迟(尤其适用于小数据包)。
    tcp_nodelay on; 

    # keepalive_timeout 设置客户端连接的保持活动时间。
    # 在这个时间内,客户端可以发送多个请求,减少重新建立连接的开销。
    keepalive_timeout 65; 

    # gzip 压缩配置,用于压缩文本内容,减少传输大小,提高加载速度。
    gzip on;
    gzip_vary on; # 告诉代理服务器客户端可以接受 gzipped 版本。
    gzip_proxied any; # 即使是代理请求也进行压缩。
    gzip_comp_level 6; # 压缩级别,1-9,6是平衡值。
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; # 需要压缩的 MIME 类型。

    # 配置服务器名称的哈希桶大小,以优化大量 server_name 的查找。
    server_names_hash_bucket_size 64; 

    # FastCGI 相关配置(如果使用 PHP-FPM 等)。这里只是占位,具体配置在 server 块内部。
    # include fastcgi_params; 

    # 另一个关键的 include 指令,用于引入所有独立的站点配置文件。
    # 通常会将每个网站的配置放在 /etc/nginx/conf.d/*.conf 或 /etc/nginx/sites-enabled/* 文件中。
    include /etc/nginx/conf.d/*.conf; 
}

2.2 server 块 - 虚拟主机配置

每个 server 块定义了一个虚拟主机,监听特定的端口和域名。

nginx
server {
    # 监听 80 端口,用于 HTTP 请求。
    listen 80; 
    # 监听 443 端口,并开启 SSL/TLS,用于 HTTPS 请求。
    listen 443 ssl http2; 

    # server_name 定义了匹配请求的域名。可以有多个,支持通配符和正则表达式。
    server_name example.com www.example.com; 
    # server_name 通配符示例 *.example.com ,可以匹配 api.example.com, docs.example.com
    # server_name 正则示例 ~^(www.)?example.com$,可以匹配 www.example.com 和 example.com

    # (HTTPS 配置,如果 listen 443 ssl)
    # ssl_certificate 定义 SSL 证书的路径。
    ssl_certificate /path/to/your/certificate.crt; 
    # ssl_certificate_key 定义 SSL 私钥的路径。
    ssl_certificate_key /path/to/your/private.key; 
    # 包含通用的 SSL 配置,例如选择传输协议、密码套件等。
    include /etc/nginx/snippets/ssl-params.conf; # 推荐分离为单独文件

    # 根目录,当请求无法匹配到 location 块时,或 location 块没有指定 root 时,使用此路径。
    root /var/www/example.com/html; 
    # 默认索引文件,当请求的是目录时,会尝试查找这些文件。
    index index.html index.htm index.nginx-debian.html; 

    # (可选) HTTP 到 HTTPS 的重定向:通常在独立的 80 端口 server 块中配置。
    # server {
    #     listen 80;
    #     server_name example.com www.example.com;
    #     return 301 https://$host$request_uri;
    # }

    # ... location 块 ...
}

2.3 location 块 - 路径匹配配置

location 块根据 URI 匹配规则来处理请求。匹配顺序遵循特定优先级:

  1. = 精确匹配:优先级最高。
  2. ^~ 前缀匹配:一旦匹配成功,立即停止搜索 regex 匹配。
  3. ~~* :正则表达式匹配(~ 区分大小写,~* 不区分大小写),按配置顺序匹配。
  4. 无修饰符前缀匹配:前缀匹配,选择最长匹配。
  5. / 通用匹配:所有其他匹配失败时的默认处理。
nginx
server {
    # ...

    location / {
        # 尝试按照顺序查找文件,如果找到则返回,如果未找到,则作为内部重定向,将请求转发到 @fallback 命名 location 块。
        # 对于单页应用 (SPA) 非常有用,确保所有路径都指向 index.html。
        try_files $uri $uri/ /index.html; 
    }

    location /api/ {
        # 反向代理请求到后端服务。
        proxy_pass http://backend_cluster; # 定义一个 upstream 块来指向后端服务器
        
        # 重要的代理头,确保后端服务获取到真实的客户端 IP、请求协议和 Host。
        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_buffering 可以降低延迟,但会增加 Nginx 内存使用。
        # proxy_buffering off; 
        
        # 代理超时时间设置。
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }

    # 精确匹配 favicon.ico
    location = /favicon.ico {
        log_not_found off; # 不记录 404 错误
        access_log off;
    }

    # 静态文件(图片、CSS、JS)
    location ~* \.(jpg|jpeg|gif|png|css|js|ico|woff|woff2|ttf|svg|eot)$ {
        root /var/www/example.com/html;
        expires 30d; # 浏览器缓存 30 天
        # add_header Cache-Control 缓存控制策略
        # 设置 Cache-Control "no-cache", 需要进行协商缓存,发送请求到服务器确认是否使用缓存
        # 设置 Cache-Control "no-store", 禁止使用缓存,每一次都要重新请求数据
        # 设置 Cache-Control "public", 可以被所有的用户缓存,包括终端用户和CDN中间代理服务器
        # 设置 Cache-Control "private", 只能被终端用户的浏览器缓存,不允许CDN等中继缓存服务器
        add_header Cache-Control "public, no-transform";
        access_log off; # 不记录静态文件访问日志,减少 I/O
    }

    # 处理错误页面
    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;
    location = /50x.html { # 将内部重定向的请求映射到实际文件
        root /usr/share/nginx/html;
    }
}

三、关键特性与高级配置

3.1 SSL/TLS 配置(安全和性能)

推荐将 SSL/TLS 相关的公共参数配置在一个独立的 snippets 文件中。

/etc/nginx/snippets/ssl-params.conf 示例:

nginx
# SSL 会话缓存,提高性能。
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off; # 禁用会话票证,安全性更高

# 优先使用服务器的密码套件顺序,而不是客户端的。
ssl_prefer_server_ciphers on;
# 选择安全且高性能的密码套件(定期更新此列表)。
ssl_ciphers 'ECDHE+AESGCM:ECDHE+CHACHA20:DHE+AESGCM:DHE+CHACHA20:ECDH+AES256:DH+AES256:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS:!ARC4';

# 启用 OCSP Stapling,减少客户端验证证书的时间。
ssl_stapling on;
ssl_stapling_verify on;
# 指向一个可信的 DNS 解析器(如 Google 或 Cloudflare)。
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

# 减少 SSL/TLS 握手延迟。
ssl_protocols TLSv1.2 TLSv1.3;

# 开启 HSTS(HTTP Strict Transport Security),强制浏览器只使用 HTTPS 访问。
# max-age 设置为一年,inclucdeSubDomains 包含所有子域名。
# preload 允许站点被预加载到浏览器 HSTS 列表中。仅在你确认所有子域名都会使用 HTTPS 后才添加。
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; 

# X-Frame-Options 防御点击劫持。
add_header X-Frame-Options "SAMEORIGIN" always;
# X-Content-Type-Options 防止 MIME 嗅探攻击。
add_header X-Content-Type-Options "nosniff" always;
# Content-Security-Policy(CSP)是一种强大的安全策略,但配置复杂,需根据应用实际情况调整。
# add_header Content-Security-Policy "default-src 'self'; script-src 'self' www.google-analytics.com;" always;
# Referrer-Policy 控制 Referer 信息的发送。
add_header Referrer-Policy "no-referrer-when-downgrade" always;

3.2 负载均衡(Upstream)

在多个应用实例之间进行负载均衡是一种常用的优化资源利用率(optimizing resource utilization)、最大化吞吐量(maximizing throughput)、减少延迟(reducing latency)并确保容错配置的技术。

Nginx 可作为多个后端应用实例的负载均衡器。

nginx
http {
    # 定义后端服务器组。
    upstream backend_cluster {
        # Round Robin 轮询 (默认): 依次向集群中的服务器分发请求,同时考虑服务器的权重(weight)。权重:weight=N 表示给服务器分配的权重,权重越高,分发的请求越多。无 weight参数时权重默认为1。
        server 192.168.1.100:8000 weight=3;
        server 192.168.1.101:8000;
        server 192.168.1.102:8000;

        # ip_hash: 确保来自同一客户端的请求总是发送到同一台服务器,适用于会话保持。
        # ip_hash; 

        # least_conn: 总是把请求分发到连接数最少的服务器。
        # least_conn;
    
        # hash: 请求根据用户定义的哈希键值均匀分布在所有上游服务器上。
        # 可选 consistent 参数启用 ketama 一致性哈希负载均衡。
        # hash $request_uri consistent;

        # fail_timeout=10s: 在 10 秒内,如果有 max_fails 次连续失败,则认为服务器宕机。
        # max_fails=3: 在 fail_timeout 时间内,如果请求失败次数达到 3 次,则不再将请求转发到此服务器。
        # down: 标记服务器永久不可用。临时下线服务器时使用。
        # backup: 备用服务器,只有当所有主服务器都不可用时才使用。
        # server 192.168.1.103:8000 max_fails=3 fail_timeout=30s;
        # server 192.168.1.104:8000 backup
        # server 192.168.1.104:8000 down;
    }

    server {
        # ...
        location /api/ {
            proxy_pass http://backend_cluster; # 指向 upstream 定义的组名
            # ... 其他 proxy_set_header 配置 ...
        }
    }
}

3.3 缓存(Cache)

Nginx 可以在内存或磁盘上缓存后端响应,从而显著提高重复请求的性能。

nginx
http {
    # 定义缓存区域。
    # keys_zone=my_cache:10m: 为缓存键名分配 10MB 的内存空间。
    # inactive=60m: 60分钟内未访问的缓存项将被删除。
    # max_size=10g: 磁盘缓存的最大大小。
    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m inactive=60m max_size=10g;

    server {
        # ...

        location /static/ {
            # 开启此 location 的缓存。
            proxy_cache my_cache;
            # 定义缓存键(通常包含 Host、URI 和请求参数)。
            proxy_cache_key "$scheme$request_method$host$request_uri";
            # 缓存 1 小时。
            proxy_cache_valid 200 302 1h; 
            # 即使后端响应了 "Set-Cookie" 头也缓存。
            proxy_ignore_headers Cache-Control Expires Set-Cookie; 
            # 如果后端不可用,使用过期的缓存。
            proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
            # 在响应头中添加缓存状态,便于调试。
            add_header X-Proxy-Cache $upstream_cache_status;
            
            proxy_pass http://backend_cluster;
        }
    }
}

3.4 安全增强

除了 SSL/TLS 和 HSTS,Nginx 还支持其他安全机制。

3.4.1 限制请求方法

nginx
location / {
    # 只允许 GET, HEAD, POST 请求。
    if ($request_method !~ ^(GET|HEAD|POST)$ ) {
        return 405; # 方法不允许
    }
    # ...
}

3.4.2 限制并发连接和请求速率

nginx
http {
    # 定义基于 IP 地址的并发连接数限制。
    # zone=per_ip:10m: 创建一个名为 per_ip 的共享内存区域,大小为 10MB。
    # 1: 允许每个 IP 地址一个客户端连接。
    limit_conn_zone $binary_remote_addr zone=per_ip:10m; 

    # 定义请求速率限制。
    # rate=5r/s: 允许每个 IP 地址每秒 5 个请求。
    # burst=10: 允许突发请求 10 个,超出此限制的请求会被延迟处理。
    # nodelay: 如果请求可以被延迟,立即处理它们,而不是等待,但计数器会根据延迟请求进行更新。
    limit_req_zone $binary_remote_addr zone=per_req:10m rate=5r/s burst=10 nodelay; 

    server {
        # ...
        location /api/login {
            limit_req zone=per_req; # 应用请求速率限制
            limit_conn per_ip 1;    # 限制并发连接为 1
            proxy_pass http://auth_backend;
        }
    }
}

3.4.3 屏蔽恶意 User-Agent

nginx
server {
    # ...
    # 阻止常见的恶意机器人或扫描工具。
    if ($http_user_agent ~* (SemrushBot|AhrefsBot|DotBot|YandexBot|MJ12bot) ) {
        return 403; # 禁止访问
    }
    # ...
}

3.5 性能优化指令

  • client_max_body_size: 设置客户端请求的最大主体大小,防止上传大文件耗尽资源。client_max_body_size 100M;
  • open_file_cache: 缓存打开的文件描述符信息,减少文件系统 I/O。open_file_cache max=100000 inactive=20s; open_file_cache_valid 30s; open_file_cache_min_uses 2; open_file_cache_errors on;
  • aio threads;: 开启异步 I/O,但在某些场景下(如处理大量慢速磁盘操作)配合 sendfile off; 效果更佳。
  • output_buffers: 调整输出缓冲区大小,优化传输效率。output_buffers 1 128k;

四、测试与故障排除

4.1 语法检查

在重新加载 Nginx 配置前,执行语法检查是必不可少的步骤。 sudo nginx -t 如果配置无误,将返回 syntax is oktest is successful

4.2 重启/重载配置

  • 平滑重载 (推荐): sudo nginx -s reload (不中断现有连接)
  • 停止后启动: sudo nginx -s stop 后紧接 sudo nginx (或 sudo systemctl start nginx / sudo service nginx start)
  • 强制重启: sudo systemctl restart nginx (或 sudo service nginx restart,会中断现有连接)

4.3 日志分析

  • 访问日志 (access.log): 记录所有请求,用于流量分析和行为分析。
  • 错误日志 (error.log): 记录 Nginx 自身的错误、警告,以及代理后端(如 PHP-FPM)的错误。这是问题排查的首要依据。
  • 调试日志 (debug):nginx.conf 中设置 error_log /var/log/nginx/error.log debug; 可开启详细调试信息,但在生产环境应谨慎使用,仅在临时排查特定问题时启用。

4.4 常用排查命令

  • sudo systemctl status nginx / sudo service nginx status:检查 Nginx 服务状态。
  • sudo netstat -tlnp | grep nginx:检查 Nginx 监听的端口。
  • sudo tail -f /var/log/nginx/access.log:实时查看访问日志。
  • sudo tail -f /var/log/nginx/error.log:实时查看错误日志。
  • curl -svo /dev/null https://your-domain.com:使用 curl 模拟客户端请求,查看详细的请求/响应过程,包括 SSL 握手信息。
  • nginx -V:查看 Nginx 版本和编译参数,确认安装了哪些模块,确认 Nginx 文件位置。

五、持续学习与拓展

  • Nginx Unit: Nginx 团队推出的另一个产品,用于应用服务器和静态文件服务,与 Nginx 互补。
  • Kubernetes Ingress Controller: 在容器化环境中,Nginx 作为 Ingress Controller 的应用是主流。了解其配置方式 (Ingress 资源 YAML) 同样重要。
  • QUIC/HTTP/3: 了解最新的传输协议如何在 Nginx 中配置和优化。
  • Web Application Firewall (WAF) 集成: 对于高级安全需求,考虑将 Nginx 与 ModSecurity 等 WAF 解决方案集成。

总访问量
总访问人数 人次