适用读者:从零基础到中级运维 / 后端工程师 覆盖平台:Linux(Ubuntu / CentOS)与 Windows 11 重点:反向代理、静态站点、HTTPS、负载均衡、性能调优
目录
- Nginx 是什么
- 安装
- 目录结构与常用命令
- 配置文件结构
- server 与 location
- 静态站点配置
- 反向代理
- 负载均衡
- HTTPS / TLS
- 常用功能片段
- 日志
- 性能调优
- 安全加固
- Docker 中使用 Nginx
- 常见问题排查
- 完整示例配置
1. Nginx 是什么
Nginx("engine x")是高性能 HTTP / 反向代理 / 邮件代理 服务器。
主要用途:
- 静态文件服务器(HTML / JS / CSS / 图片 / 视频)
- 反向代理(前端流量 → 后端应用,常配 Spring Boot、Node、Python 等)
- 负载均衡(多个上游节点)
- API 网关 / SSL 终结 / 限流 / 缓存
特点:事件驱动、单线程多 worker、内存占用小、配置简洁。
2. 安装
2.1 Ubuntu / Debian
sudo apt-get update
sudo apt-get install -y nginx
sudo systemctl enable --now nginx
nginx -v
2.2 CentOS / Rocky
sudo yum install -y epel-release
sudo yum install -y nginx
sudo systemctl enable --now nginx
2.3 官方仓库(Linux,版本最新)
sudo apt-get install -y curl gnupg2 ca-certificates lsb-release
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
https://nginx.org/packages/ubuntu `lsb_release -cs` nginx" | \
sudo tee /etc/apt/sources.list.d/nginx.list
sudo apt-get update && sudo apt-get install -y nginx
2.4 Windows
- 访问 nginx.org/en/download…,下载 stable 版 zip
- 解压到例如
C:\nginx - 双击
nginx.exe启动;浏览器访问http://localhost - 常用命令(在
C:\nginx目录中以管理员 PowerShell / CMD 执行):
.\nginx.exe # 启动
.\nginx.exe -s stop # 立即停止
.\nginx.exe -s quit # 优雅停止
.\nginx.exe -s reload # 重载配置
.\nginx.exe -s reopen # 重新打开日志
.\nginx.exe -t # 测试配置
Windows 版功能与稳定性都不如 Linux,生产强烈推荐 Linux;Windows 仅适合本地开发或对接 IIS 之外的场景。
2.5 Docker(推荐)
docker run -d --name web -p 80:80 nginx:1.27-alpine
详见第 14 节。
3. 目录结构与常用命令
3.1 默认目录(Ubuntu apt 安装)
/etc/nginx/ 配置目录
├── nginx.conf 主配置
├── conf.d/ 额外的 server 配置(推荐放这里)
├── sites-available/ 可用站点(Debian/Ubuntu 风格)
├── sites-enabled/ 已启用站点(软链到 available)
├── snippets/ 可复用片段
├── modules-enabled/
└── mime.types
/var/log/nginx/ 日志(access.log / error.log)
/var/www/html/ 默认站点根目录
/usr/share/nginx/html/ 某些发行版默认根目录
3.2 服务管理
sudo systemctl start nginx
sudo systemctl stop nginx
sudo systemctl restart nginx
sudo systemctl reload nginx # 推荐!热加载,不中断连接
sudo systemctl status nginx
sudo systemctl enable nginx # 开机自启
sudo nginx -t # 测试配置(部署前必做)
sudo nginx -T # 测试并打印渲染后的完整配置
sudo nginx -s reload # 等价于 systemctl reload
sudo nginx -s stop # 强制停止
sudo nginx -s quit # 优雅停止
sudo nginx -V # 版本 + 编译参数(看支持哪些模块)
3.3 修改配置后的标准流程
sudo nginx -t && sudo nginx -s reload
4. 配置文件结构
# /etc/nginx/nginx.conf
user www-data; # worker 进程用户
worker_processes auto; # 通常 = CPU 核数
pid /run/nginx.pid;
error_log /var/log/nginx/error.log warn;
events {
worker_connections 1024; # 单 worker 最大连接数
use epoll; # Linux 高性能事件模型
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"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off; # 隐藏版本号
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
# 引入子配置
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
层级:main → events → http → server → location。
5. server 与 location
5.1 server 块
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com; # 域名(可多个,可通配 *.example.com)
root /var/www/example;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
listen 常见写法:
listen 80; # 所有 IP:80
listen 127.0.0.1:80; # 仅本机
listen 80 default_server; # 默认 server(请求未匹配任何 server_name 时走它)
listen 443 ssl http2; # HTTPS + HTTP/2
listen 443 ssl;
http2 on; # nginx 1.25+ 推荐写法
5.2 location 匹配优先级
| 修饰符 | 含义 | 优先级 |
|---|---|---|
= | 精确匹配 | 1(最高) |
^~ | 前缀匹配,命中后不再正则 | 2 |
~ / ~* | 正则(区分 / 不区分大小写) | 3 |
/ | 普通前缀匹配 | 4 |
location = /favicon.ico { access_log off; log_not_found off; }
location ^~ /static/ { expires 30d; }
location ~* \.(jpg|png|gif|webp)$ { expires 7d; }
location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; }
location / { try_files $uri $uri/ /index.html; }
6. 静态站点配置
6.1 普通静态站点
server {
listen 80;
server_name static.example.com;
root /var/www/static;
index index.html;
location / {
try_files $uri $uri/ =404;
}
# 静态资源长缓存
location ~* \.(?:css|js|woff2?|ttf|otf|svg|png|jpg|jpeg|gif|webp|ico)$ {
expires 30d;
add_header Cache-Control "public, immutable";
access_log off;
}
}
6.2 SPA(Vue / React)
前端路由刷新后 404 的标准修复:
server {
listen 80;
server_name app.example.com;
root /var/www/spa;
index index.html;
location / {
try_files $uri $uri/ /index.html; # 关键:fallback 到 index.html
}
# index.html 不缓存,否则发版后老用户拿不到新版本
location = /index.html {
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
location ~* \.(?:css|js|woff2?|png|jpg|svg)$ {
expires 365d;
add_header Cache-Control "public, immutable";
}
}
7. 反向代理
7.1 最小反向代理
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://127.0.0.1:8080; # 注意结尾斜杠的差异
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;
}
}
7.2 关于 proxy_pass 末尾斜杠
location /api/ {
proxy_pass http://backend; # 请求 /api/users → 转发为 /api/users
}
location /api/ {
proxy_pass http://backend/; # 请求 /api/users → 转发为 /users(去掉了 /api/)
}
加斜杠 = 替换前缀;不加 = 拼接。容易踩坑,记牢这个规则。
7.3 完整代理参数(推荐基线)
location / {
proxy_pass http://app_upstream;
proxy_http_version 1.1;
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_set_header X-Forwarded-Host $host;
proxy_connect_timeout 5s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
proxy_buffering on;
proxy_buffers 8 16k;
proxy_buffer_size 16k;
# WebSocket 必备
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
# 配合 WebSocket 的 connection_upgrade 变量
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
7.4 大文件上传
client_max_body_size 100m;
client_body_buffer_size 256k;
proxy_request_buffering off; # 大文件直连后端,不在 nginx 缓冲
8. 负载均衡
8.1 上游池 upstream
upstream app_upstream {
# 算法(默认轮询):
# ip_hash; # 同 IP 每次到同一节点
# least_conn; # 最少连接
# hash $request_uri consistent;
server 10.0.0.11:8080 weight=3;
server 10.0.0.12:8080 weight=1;
server 10.0.0.13:8080 backup; # 主节点都挂了才用
server 10.0.0.14:8080 max_fails=3 fail_timeout=30s;
keepalive 32; # 与后端的长连接池
}
server {
listen 80;
location / {
proxy_pass http://app_upstream;
proxy_http_version 1.1;
proxy_set_header Connection ""; # 配合 keepalive
}
}
8.2 健康检查
开源版仅被动检查(max_fails / fail_timeout)。
主动健康检查需要 Nginx Plus 或第三方模块(如 nginx_upstream_check_module)。
8.3 四层(TCP/UDP)负载均衡
需要在主配置(不是 http 块内)加 stream:
stream {
upstream mysql_pool {
server 10.0.0.21:3306;
server 10.0.0.22:3306;
}
server {
listen 3306;
proxy_pass mysql_pool;
}
}
9. HTTPS / TLS
9.1 自签证书(仅测试)
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/nginx/ssl/self.key \
-out /etc/nginx/ssl/self.crt \
-subj "/CN=localhost"
9.2 Let's Encrypt(生产免费)
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com
sudo certbot renew --dry-run # 测试自动续期
certbot 会自动改 Nginx 配置加上 ssl 段。
9.3 推荐 HTTPS 配置
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$host$request_uri; # 强制跳 HTTPS
}
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on; # nginx 1.25+
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# 现代化(兼容性中等)
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;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 8.8.8.8 valid=300s;
resolver_timeout 5s;
# HSTS(确认全站 HTTPS 后再开)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
root /var/www/example;
index index.html;
}
10. 常用功能片段
10.1 重定向
return 301 https://$host$request_uri;
return 302 /maintenance.html;
rewrite ^/old/(.*)$ /new/$1 permanent;
10.2 防盗链
location ~* \.(jpg|png|gif|mp4)$ {
valid_referers none blocked example.com *.example.com;
if ($invalid_referer) { return 403; }
}
10.3 限流(Rate Limit)
http {
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
}
server {
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
limit_conn conn_limit 5;
proxy_pass http://backend;
}
}
10.4 IP 黑白名单
location /admin/ {
allow 192.168.1.0/24;
allow 10.0.0.0/8;
deny all;
proxy_pass http://admin;
}
10.5 基本鉴权(Basic Auth)
sudo apt-get install -y apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd admin
location /private/ {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
}
10.6 CORS
location /api/ {
if ($request_method = OPTIONS) {
add_header Access-Control-Allow-Origin "$http_origin" always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
add_header Access-Control-Allow-Headers "Authorization, Content-Type" always;
add_header Access-Control-Allow-Credentials "true" always;
add_header Access-Control-Max-Age 86400;
return 204;
}
add_header Access-Control-Allow-Origin "$http_origin" always;
add_header Access-Control-Allow-Credentials "true" always;
proxy_pass http://backend;
}
10.7 gzip / brotli 压缩
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_comp_level 5;
gzip_types
text/plain text/css text/xml application/json
application/javascript application/xml+rss
image/svg+xml font/woff2;
10.8 缓存代理结果
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=app_cache:10m max_size=1g inactive=60m use_temp_path=off;
server {
location / {
proxy_cache app_cache;
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_use_stale error timeout updating;
add_header X-Cache-Status $upstream_cache_status;
proxy_pass http://backend;
}
}
10.9 简单维护页
location / {
return 503;
}
error_page 503 @maintenance;
location @maintenance {
root /var/www/maintenance;
try_files /index.html =503;
}
11. 日志
11.1 自定义日志格式
log_format json_combined escape=json '{'
'"time_local":"$time_iso8601",'
'"remote_addr":"$remote_addr",'
'"x_forwarded_for":"$http_x_forwarded_for",'
'"request":"$request",'
'"status":$status,'
'"body_bytes_sent":$body_bytes_sent,'
'"request_time":$request_time,'
'"upstream_response_time":"$upstream_response_time",'
'"http_referer":"$http_referer",'
'"http_user_agent":"$http_user_agent"'
'}';
access_log /var/log/nginx/access.log json_combined;
11.2 按域名分文件
server {
server_name api.example.com;
access_log /var/log/nginx/api.access.log main;
error_log /var/log/nginx/api.error.log warn;
}
11.3 日志轮转
Linux 通常装好就有 /etc/logrotate.d/nginx,默认每天切割保留 14 天。可按需修改。
12. 性能调优
12.1 worker
worker_processes auto;
worker_rlimit_nofile 65535;
events {
worker_connections 10240;
use epoll;
multi_accept on;
}
理论最大并发 ≈ worker_processes * worker_connections / 2(反代场景每个连接占 2 个 fd)。
系统层面也要调:
# /etc/security/limits.conf
* soft nofile 65535
* hard nofile 65535
# /etc/sysctl.conf
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.ip_local_port_range = 1024 65535
12.2 keepalive
http {
keepalive_timeout 65;
keepalive_requests 1000;
}
upstream backend {
server 10.0.0.11:8080;
keepalive 64;
}
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
12.3 sendfile / 缓冲
sendfile on;
tcp_nopush on;
tcp_nodelay on;
client_body_buffer_size 16k;
client_max_body_size 100m;
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;
12.4 静态资源压缩 + 缓存
见 10.7、6.2 节。
13. 安全加固
# 隐藏版本号
server_tokens off;
# 隐藏 server 头(需要 ngx_headers_more 模块)
# more_clear_headers 'Server';
# 安全响应头
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=()" always;
# add_header Content-Security-Policy "default-src 'self'" always; # 视项目而定
# 拒绝可疑 method
if ($request_method !~ ^(GET|HEAD|POST|PUT|DELETE|OPTIONS)$) { return 405; }
# 屏蔽常见探测路径
location ~ /\.(?:git|env|svn|hg) { deny all; }
location ~ ~$ { deny all; }
其他建议:
- 用专门的低权限用户(
user www-data;) - 关掉不必要的模块(编译时)
- 后端只监听内网;前置 Nginx 监听公网
- 配 fail2ban 自动封 IP
- 定期
nginx -V跟版本,及时升级 CVE
14. Docker 中使用 Nginx
14.1 命令式
docker run -d --name web \
-p 80:80 -p 443:443 \
-v $(pwd)/nginx.conf:/etc/nginx/nginx.conf:ro \
-v $(pwd)/conf.d:/etc/nginx/conf.d:ro \
-v $(pwd)/html:/usr/share/nginx/html:ro \
-v $(pwd)/certs:/etc/nginx/certs:ro \
-v $(pwd)/logs:/var/log/nginx \
--restart=unless-stopped \
nginx:1.27-alpine
热更新配置:
docker exec web nginx -t && docker exec web nginx -s reload
14.2 Compose 示例
services:
nginx:
image: nginx:1.27-alpine
ports: ["80:80","443:443"]
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./conf.d:/etc/nginx/conf.d:ro
- ./certs:/etc/nginx/certs:ro
- ./html:/usr/share/nginx/html:ro
- ./logs:/var/log/nginx
restart: unless-stopped
healthcheck:
test: ["CMD","wget","-q","--spider","http://localhost/"]
interval: 30s
timeout: 5s
retries: 3
14.3 K8s 中作为 Ingress Controller
参见 Kubernetes操作手册.md 第 9 节。Nginx 也常被部署为独立的 Deployment 提供网关能力。
15. 常见问题排查
| 现象 | 排查 |
|---|---|
| 改配置不生效 | nginx -t 确认语法;nginx -s reload;浏览器强刷或换无痕 |
| 502 Bad Gateway | 后端没起、端口错、proxy_pass 写错;error.log 看 connect failed |
| 504 Gateway Timeout | 后端慢,调大 proxy_read_timeout |
| 413 Request Entity Too Large | 调大 client_max_body_size |
| 静态文件 403 | 目录权限;SELinux;/var/www 父目录 nginx 用户没 x 权限 |
拿到的 $remote_addr 是 LB 内网 IP | 用 $http_x_forwarded_for 或配 set_real_ip_from / real_ip_header |
| HTTPS 浏览器警告 | 证书域名不匹配;中间证书没拼到 fullchain;时间不对 |
| WebSocket 连不上 | 缺少 Upgrade / Connection 头和 proxy_http_version 1.1 |
| 跨域失败 | 看 OPTIONS 预检是否被代理拦截;CORS 头是否丢失 |
| 长连接没生效 | 后端 keepalive 没开;Connection 头没清空 |
real_ip 配置示例:
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
16. 完整示例配置
16.1 单站点 + HTTPS + 反代后端 + SPA + 静态资源
# /etc/nginx/conf.d/example.conf
upstream api_backend {
server 127.0.0.1:8080;
keepalive 32;
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# HTTP → HTTPS
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
# HTTPS 主站
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_cache shared:SSL:10m;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
client_max_body_size 50m;
root /var/www/example/dist;
index index.html;
# API 反代
location /api/ {
proxy_pass http://api_backend/; # 注意末尾 /,会去掉 /api/ 前缀
proxy_http_version 1.1;
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_set_header Connection "";
proxy_read_timeout 60s;
}
# WebSocket
location /ws/ {
proxy_pass http://api_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_read_timeout 3600s;
}
# 静态资源缓存
location ~* \.(?:css|js|woff2?|ttf|svg|png|jpg|jpeg|gif|webp|ico)$ {
expires 365d;
add_header Cache-Control "public, immutable";
access_log off;
}
# SPA fallback
location / {
try_files $uri $uri/ /index.html;
}
location = /index.html {
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
# 屏蔽敏感文件
location ~ /\.(?:git|env|svn|hg) { deny all; }
}
sudo nginx -t && sudo nginx -s reload
配套阅读:Docker操作手册.md、DockerCompose操作手册.md、Kubernetes操作手册.md;进阶请看 Nginx生产化手册.md。