NGINX 配置指南
本指南提供了Nginx 配置要点和最佳实践,作为参考。
NGINX (发音为 "engine-x") 是一款 HTTP Web 服务器、反向代理、内容缓存、负载均衡器、TCP/UDP 代理服务器和邮件代理服务器,在 2-clause BSD 许可协议下发行,具有高性能、高可靠性、丰富的模块化支持和简单易用的优势。
一、Nginx 配置原则
在设计和实施 Nginx 配置时,以下原则至关重要:
- 模块化 (Modularity): 不要把所有配置都堆在一个文件里。采用
include
指令将不同服务(如网站A、网站B)、不同功能(如 SSL 配置参数、公共代理头)的配置拆分成独立的、可管理的片段文件。这提升了配置的可读性和维护性。 - 安全性 (Security): Nginx 是应用的第一层防御。应确保配置遵循最小权限原则,强制使用 HTTPS,并实施适当的访问控制和错误信息处理策略。
- 高性能 (Performance): Nginx 生而为快。充分利用 Nginx 的静态文件服务能力、缓存机制、Gzip 压缩等特性,以最小化系统资源消耗并优化响应速度。
- 可观测性 (Observability): 格式规范的日志配置是排查问题、分析流量和快速定位问题的基础。
- 幂等性 (Idempotency): 建议使用版本控制管理 Nginx 配置文件,确保配置变更可追溯、可回滚,并保证部署的一致性。
二、Nginx 核心配置结构
通常,Nginx 的配置由 nginx.conf
文件和其通过 include
指令引入的其他配置文件组成。
2.1 nginx.conf
- 全局配置
该文件定义 Nginx 服务器的全局行为和核心模块参数。通常位于/usr/local/nginx/conf
、/etc/nginx
或 /usr/local/etc/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
块定义了一个虚拟主机,监听特定的端口和域名。
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 匹配规则来处理请求。匹配顺序遵循特定优先级:
=
精确匹配:优先级最高。^~
前缀匹配:一旦匹配成功,立即停止搜索 regex 匹配。~
或~*
:正则表达式匹配(~
区分大小写,~*
不区分大小写),按配置顺序匹配。- 无修饰符前缀匹配:前缀匹配,选择最长匹配。
/
通用匹配:所有其他匹配失败时的默认处理。
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
示例:
# 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 可作为多个后端应用实例的负载均衡器。
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 可以在内存或磁盘上缓存后端响应,从而显著提高重复请求的性能。
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 限制请求方法
location / {
# 只允许 GET, HEAD, POST 请求。
if ($request_method !~ ^(GET|HEAD|POST)$ ) {
return 405; # 方法不允许
}
# ...
}
3.4.2 限制并发连接和请求速率
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
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 ok
和 test 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 解决方案集成。