Nginx 是全球最流行的 Web 服务器,支撑着超过 30% 的网站。无论你需要提供静态文件、设置反向代理、配置 SSL 还是在多个后端之间进行负载均衡,本全面的 Nginx 配置指南提供了可直接使用的生产级示例。每个配置块都包含详细的注释说明。
Nginx 基础
Nginx(发音为 "engine-x")是一个高性能的 HTTP 服务器、反向代理和负载均衡器。其事件驱动架构以极少的内存处理数千个并发连接。主配置文件通常位于 /etc/nginx/nginx.conf,站点配置位于 /etc/nginx/conf.d/ 或 /etc/nginx/sites-available/。
# Main configuration file structure
# /etc/nginx/nginx.conf
user nginx;
worker_processes auto; # One worker per CPU core
error_log /var/log/nginx/error.log warn;
pid /run/nginx.pid;
events {
worker_connections 1024; # Max connections per worker
multi_accept on; # Accept multiple connections at once
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Logging format
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
access_log /var/log/nginx/access.log main;
sendfile on; # Efficient file transfer
tcp_nopush on; # Optimize TCP packets
tcp_nodelay on; # Disable Nagle's algorithm
keepalive_timeout 65; # Keep connections alive
types_hash_max_size 2048;
# Include site configurations
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}静态站点配置
最简单也最常见的用例:直接从磁盘提供 HTML、CSS、JavaScript 和图片文件。此配置包含缓存头以获得最佳性能。
# Static website configuration
# /etc/nginx/conf.d/static-site.conf
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
# Document root
root /var/www/example.com/html;
index index.html index.htm;
# Main location block
location / {
try_files $uri $uri/ =404;
}
# Cache static assets aggressively
location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, immutable";
access_log off;
}
# Cache HTML files with shorter duration
location ~* \.html$ {
expires 1h;
add_header Cache-Control "public, must-revalidate";
}
# Deny access to hidden files (.htaccess, .git, etc.)
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# Custom error pages
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
}反向代理配置
反向代理位于客户端和后端应用(Node.js、Python、Go 等)之间,转发请求并返回响应。这是 Web 应用最常见的生产部署方式。
# Reverse proxy to Node.js/Python/Go application
# /etc/nginx/conf.d/app-proxy.conf
server {
listen 80;
server_name app.example.com;
# Max upload size
client_max_body_size 50M;
# Proxy all requests to the backend application
location / {
proxy_pass http://127.0.0.1:3000;
# Pass the real client IP to the backend
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;
# WebSocket support (for Socket.IO, etc.)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# Buffering settings
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
}
# Serve static files directly (bypass the backend)
location /static/ {
alias /var/www/app/static/;
expires 30d;
add_header Cache-Control "public, immutable";
}
# Health check endpoint
location /health {
proxy_pass http://127.0.0.1:3000/health;
access_log off;
}
access_log /var/log/nginx/app.access.log;
error_log /var/log/nginx/app.error.log;
}SSL/TLS 配置
使用 HTTPS 保护你的站点是现代 Web 开发的必备要求。此配置使用 Let's Encrypt 证书,遵循当前 TLS 安全最佳实践,包括强加密套件和 HSTS。
# SSL/TLS configuration with Let's Encrypt
# /etc/nginx/conf.d/ssl-site.conf
# Redirect all HTTP traffic to HTTPS
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
# Let's Encrypt ACME challenge
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# 301 permanent redirect to HTTPS
location / {
return 301 https://$server_name$request_uri;
}
}
# HTTPS server block
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
# Let's Encrypt certificate paths
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# SSL session settings
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
# Modern TLS configuration (TLS 1.2 + 1.3 only)
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# OCSP Stapling (faster certificate verification)
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# HSTS (force HTTPS for 2 years, including subdomains)
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
root /var/www/example.com/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
access_log /var/log/nginx/example.com.ssl.access.log;
error_log /var/log/nginx/example.com.ssl.error.log;
}SPA(React/Vue/Angular)配置
单页应用使用客户端路由,这意味着所有路由必须回退到 index.html。此配置正确处理了这一点,同时也高效地提供静态资源。
# SPA configuration (React, Vue, Angular, Next.js static export)
# /etc/nginx/conf.d/spa.conf
server {
listen 80;
server_name spa.example.com;
root /var/www/spa/dist;
index index.html;
# The key directive for SPAs: fallback to index.html
# This ensures client-side routing works correctly
location / {
try_files $uri $uri/ /index.html;
}
# Cache JavaScript and CSS bundles (with hash in filename)
location ~* \.(js|css)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
# Cache images, fonts, and media
location ~* \.(jpg|jpeg|png|gif|ico|svg|webp|avif|woff|woff2|ttf|eot|mp4|webm)$ {
expires 30d;
add_header Cache-Control "public";
access_log off;
}
# Do NOT cache index.html (always serve the latest version)
location = /index.html {
expires -1;
add_header Cache-Control "no-store, no-cache, must-revalidate";
}
# API proxy (forward /api requests to the backend)
location /api/ {
proxy_pass http://127.0.0.1:4000;
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;
}
# Deny access to source maps in production
location ~* \.map$ {
deny all;
}
}负载均衡
将传入流量分配到多个后端服务器,以实现高可用性和更好的性能。Nginx 开箱支持多种负载均衡算法。
# Load balancing across multiple backend servers
# /etc/nginx/conf.d/load-balancer.conf
# Define backend server group
upstream app_servers {
# Round-robin (default) - requests distributed evenly
server 10.0.0.1:3000;
server 10.0.0.2:3000;
server 10.0.0.3:3000;
# Mark a server as backup (used only when others are down)
server 10.0.0.4:3000 backup;
# Health check: mark server down after 3 failed attempts
# max_fails=3 fail_timeout=30s (default)
}
# Weighted load balancing (send more traffic to powerful servers)
upstream app_weighted {
server 10.0.0.1:3000 weight=5; # Gets 5x the traffic
server 10.0.0.2:3000 weight=3; # Gets 3x the traffic
server 10.0.0.3:3000 weight=1; # Gets 1x the traffic
}
# Least connections (send to the server with fewest active requests)
upstream app_least_conn {
least_conn;
server 10.0.0.1:3000;
server 10.0.0.2:3000;
server 10.0.0.3:3000;
}
# IP hash (same client always goes to same server - sticky sessions)
upstream app_ip_hash {
ip_hash;
server 10.0.0.1:3000;
server 10.0.0.2:3000;
server 10.0.0.3:3000;
}
server {
listen 80;
server_name lb.example.com;
location / {
proxy_pass http://app_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Connection keep-alive to backends
proxy_http_version 1.1;
proxy_set_header Connection "";
}
# Simple health check endpoint
location /nginx-health {
access_log off;
return 200 "OK";
add_header Content-Type text/plain;
}
}安全头
HTTP 安全头保护你的站点免受点击劫持、XSS 和内容注入等常见攻击。这些头应添加到每个生产 Nginx 配置中。
# Security headers configuration
# Add these inside your server {} block or create a snippet
# /etc/nginx/snippets/security-headers.conf
# Include with: include /etc/nginx/snippets/security-headers.conf;
# Prevent clickjacking: deny embedding in iframes
add_header X-Frame-Options "SAMEORIGIN" always;
# Prevent MIME-type sniffing
add_header X-Content-Type-Options "nosniff" always;
# Enable XSS protection (legacy browsers)
add_header X-XSS-Protection "1; mode=block" always;
# Control referrer information sent with requests
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Content Security Policy (customize based on your needs)
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.example.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; connect-src 'self' https://api.example.com; frame-ancestors 'self';" always;
# Permissions Policy (formerly Feature-Policy)
add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), interest-cohort=()" always;
# Prevent information leakage
add_header X-Permitted-Cross-Domain-Policies "none" always;
# HSTS (only add if you have SSL configured)
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# Hide Nginx version number
server_tokens off;Gzip 压缩
启用 Gzip 压缩可将传输响应的大小减少多达 90%,显著提升页面加载速度。此配置压缩所有文本类型的内容。
# Gzip compression configuration
# Add inside the http {} block in nginx.conf
# Enable gzip compression
gzip on;
# Minimum file size to compress (skip tiny files)
gzip_min_length 256;
# Compression level (1-9, higher = more CPU, smaller files)
# Level 6 is a good balance between compression ratio and CPU usage
gzip_comp_level 6;
# Number and size of compression buffers
gzip_buffers 16 8k;
# Compress responses for HTTP/1.0 clients too
gzip_http_version 1.0;
# Compress all text-based content types
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/x-javascript
application/xml
application/xml+rss
application/atom+xml
application/vnd.ms-fontobject
font/opentype
font/ttf
image/svg+xml
image/x-icon;
# Add Vary: Accept-Encoding header (important for caching proxies)
gzip_vary on;
# Disable gzip for old IE browsers
gzip_disable "MSIE [1-6]\.";
# Enable gzip for proxied requests too
gzip_proxied any;速率限制
速率限制保护你的服务器免受滥用、暴力攻击和 DDoS。Nginx 的 limit_req 模块使用漏桶算法控制请求速率。
# Rate limiting configuration
# Define zones in the http {} block, apply in server/location blocks
# ── Define rate limit zones (in http {} block) ──
# General rate limit: 10 requests/second per IP
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
# Strict rate limit for login/auth: 5 requests/minute per IP
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
# API rate limit: 30 requests/second per IP
limit_req_zone $binary_remote_addr zone=api:10m rate=30r/s;
# Rate limit by server name (protect against virtual host abuse)
limit_req_zone $server_name zone=per_server:10m rate=100r/s;
# ── Apply rate limits (in server {} block) ──
server {
listen 80;
server_name api.example.com;
# Custom error page for rate-limited requests
error_page 429 = @rate_limited;
location @rate_limited {
default_type application/json;
return 429 '{"error": "Too many requests. Please try again later."}';
}
# General pages: allow burst of 20, no delay for first 10
location / {
limit_req zone=general burst=20 nodelay;
limit_req_status 429;
proxy_pass http://127.0.0.1:3000;
}
# Login endpoint: strict rate limiting
location /api/auth/login {
limit_req zone=login burst=3 nodelay;
limit_req_status 429;
proxy_pass http://127.0.0.1:3000;
}
# API endpoints: higher limit with burst
location /api/ {
limit_req zone=api burst=50 nodelay;
limit_req_status 429;
proxy_pass http://127.0.0.1:3000;
}
# Whitelist certain IPs from rate limiting
# geo $limit {
# default 1;
# 10.0.0.0/8 0; # Internal network
# 192.168.0.0/16 0; # Local network
# }
# map $limit $limit_key {
# 0 "";
# 1 $binary_remote_addr;
# }
# limit_req_zone $limit_key zone=custom:10m rate=10r/s;
}常用指令参考
以下是最常用的 Nginx 指令及其说明的快速参考。
| 指令 | 说明 |
|---|---|
| worker_processes | 工作进程数(设置为 auto 则等于 CPU 核数) |
| worker_connections | 每个工作进程的最大同时连接数 |
| server_name | 此 server 块响应的域名 |
| listen | 监听的端口和协议 |
| root | 文件服务的根目录 |
| index | 目录请求的默认文件 |
| location | 匹配请求 URI 以应用特定配置 |
| proxy_pass | 将请求转发到后端服务器 |
| try_files | 按顺序尝试提供文件,最后回退到最后一个选项 |
| ssl_certificate | SSL 证书文件路径 |
| ssl_certificate_key | SSL 私钥文件路径 |
| add_header | 添加自定义 HTTP 响应头 |
| gzip | 启用或禁用 gzip 压缩 |
| expires | 设置静态资源的 Cache-Control max-age |
| upstream | 定义一组后端服务器用于负载均衡 |
| limit_req_zone | 定义速率限制的共享内存区域 |
| error_page | 为特定状态码定义自定义错误页面 |
| access_log | 访问日志的路径和格式 |
| error_log | 错误日志的路径和级别 |
| client_max_body_size | 客户端请求体的最大允许大小 |
| sendfile | 启用使用内核 sendfile 的高效文件传输 |
常见问题
Nginx 和 Apache 有什么区别?
Nginx 使用事件驱动的异步架构,以较低的内存占用高效处理大量并发连接。Apache 传统上使用每连接一个进程或线程的模型,在高负载下消耗更多内存。Nginx 在提供静态内容和作为反向代理方面表现出色,而 Apache 提供更多内置模块和 .htaccess 支持。许多生产环境使用 Nginx 作为 Apache 前面的反向代理。
如何在重载前测试 Nginx 配置?
在重载前始终运行 "nginx -t"。此命令会解析配置文件并检查语法错误而不实际应用更改。如果测试通过,可以安全地使用 "nginx -s reload" 或 "systemctl reload nginx" 重载。在生产环境中切勿不测试就重启 Nginx。
如何使用 Let's Encrypt 设置 SSL 证书?
安装 Certbot 并运行 "certbot --nginx -d yourdomain.com"。Certbot 会自动获取证书并修改你的 Nginx 配置。它还会通过 cron 或 systemd 定时器设置自动续期。证书存储在 /etc/letsencrypt/live/yourdomain.com/。
"proxy_set_header X-Real-IP $remote_addr" 有什么作用?
当 Nginx 作为反向代理时,后端应用看到的是 Nginx 的 IP 而不是客户端 IP。X-Real-IP 头将原始客户端 IP 传递给后端,使你的应用能正确记录真实访客 IP、按用户限速和进行地理定位。
如何在 Nginx 中将 HTTP 重定向到 HTTPS?
创建一个监听 80 端口的单独 server 块,返回 301 重定向:"return 301 https://$server_name$request_uri;"。这确保所有 HTTP 流量被永久重定向到安全的 HTTPS 版本。
try_files 指令是什么?为什么对 SPA 很重要?
try_files 指令告诉 Nginx 按顺序检查文件是否存在并提供第一个找到的文件。对于 SPA,"try_files $uri $uri/ /index.html" 首先尝试提供请求的确切文件,然后查找目录,最后回退到 index.html。这很重要因为 SPA 的路由如 /about 或 /dashboard 并不对应磁盘上的实际文件。
这些 Nginx 配置涵盖了最常见的生产场景。重载前始终使用 "nginx -t" 测试配置,并定期监控访问日志和错误日志以尽早发现问题。