正在加载文档...
文档内容较大,正在处理中,请稍候
正在加载文档...
文档内容较大,正在处理中,请稍候
本文档详细说明了 Nginx 的常用配置参数以及针对项目中各个应用的具体配置示例,包括:
doc-next-ts:Next.js 文档站(端口 8081)react-antd-webpack:React 前端应用(端口 8080)node-express-mysql:Node.js 后端 API 服务(端口 8888)# /etc/nginx/nginx.conf
# 用户和组
user nginx;
worker_processes auto; # 工作进程数,auto 表示自动检测 CPU 核心数
error_log /var/log/nginx/error.log warn; # 错误日志
pid /var/run/nginx.pid; # PID 文件
# 事件模块
events {
worker_connections 1024; # 每个工作进程的最大连接数
use epoll; # 使用 epoll 事件模型(Linux)
multi_accept on; # 允许一个工作进程同时接受多个连接
}
# HTTP 模块
http {
include /etc/nginx/mime.types; # MIME 类型
default_type application/octet-stream; # 默认 MIME 类型
# 日志格式
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 数据包传输
tcp_nodelay on; # 禁用 Nagle 算法
keepalive_timeout 65; # Keep-Alive 超时时间
types_hash_max_size 2048; # MIME 类型哈希表大小
# 包含站点配置
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}server {
listen 80; # 监听端口
listen [::]:80; # IPv6 监听端口
server_name example.com www.example.com; # 域名
root /var/www/html; # 网站根目录
index index.html index.htm; # 默认索引文件
# 字符编码
charset utf-8;
# 访问日志
access_log /var/log/nginx/example.com-access.log;
error_log /var/log/nginx/example.com-error.log;
}server {
listen 443 ssl http2; # HTTPS 监听,启用 HTTP/2
listen [::]:443 ssl http2;
server_name example.com www.example.com;
# SSL 证书配置
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
# SSL 配置优化
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# HSTS(可选)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
root /var/www/html;
index index.html;
}# 精确匹配(优先级最高)
location = / {
# 只匹配 "/"
}
# 前缀匹配(最长匹配优先)
location /api/ {
# 匹配 "/api/" 开头的所有路径
}
# 正则匹配(区分大小写)
location ~ \.php$ {
# 匹配以 ".php" 结尾的文件
}
# 正则匹配(不区分大小写)
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
# 匹配图片和样式文件
}
# 优先前缀匹配
location ^~ /static/ {
# 匹配 "/static/" 开头,优先级高于正则匹配
}location /api/ {
# 代理到后端服务
proxy_pass http://127.0.0.1:8888/; # 注意末尾的 "/"
# 请求头设置
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 支持
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# 超时设置
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# 缓冲设置
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
proxy_busy_buffers_size 8k;
}| 指令 | 说明 | 示例 |
|---|---|---|
listen |
监听端口 | listen 80; |
server_name |
服务器名称(域名) | server_name example.com; |
root |
网站根目录 | root /var/www/html; |
index |
默认索引文件 | index index.html; |
try_files |
尝试文件顺序 | try_files $uri $uri/ /index.html; |
proxy_pass |
反向代理目标 | proxy_pass http://127.0.0.1:8888; |
proxy_set_header |
设置代理请求头 | proxy_set_header Host $host; |
add_header |
添加响应头 | add_header X-Frame-Options "SAMEORIGIN"; |
expires |
缓存过期时间 | expires 1y; |
deny |
拒绝访问 | deny all; |
allow |
允许访问 | allow 192.168.1.0/24; |
http {
# 启用 Gzip 压缩
gzip on;
gzip_vary on;
# 最小压缩文件大小(小于此大小的文件不压缩)
gzip_min_length 1024;
# 压缩级别(1-9,数字越大压缩率越高,但 CPU 消耗越大)
gzip_comp_level 6;
# 压缩类型
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml+rss
application/rss+xml
font/truetype
font/opentype
application/vnd.ms-fontobject
image/svg+xml;
# 禁用压缩的 User-Agent(兼容旧浏览器)
gzip_disable "msie6";
# 压缩缓冲区大小
gzip_buffers 16 8k;
}http {
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_comp_level 6;
# 启用压缩的 HTTP 版本
gzip_http_version 1.1;
# 压缩类型(更完整的列表)
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml
application/xml+rss
application/rss+xml
application/atom+xml
image/svg+xml
font/truetype
font/opentype
application/vnd.ms-fontobject
application/x-font-ttf
application/x-font-opentype
application/x-font-truetype;
# 压缩代理请求
gzip_proxied any;
# 压缩缓冲区
gzip_buffers 16 8k;
# 禁用压缩
gzip_disable "msie6";
}Brotli 需要安装 Nginx Brotli 模块:
# Ubuntu/Debian
sudo apt-get install nginx-module-brotli
# CentOS/RHEL
sudo yum install nginx-mod-http-brotli
# 或者从源码编译(需要 --add-module)
./configure --add-module=/path/to/ngx_brotlihttp {
# 加载 Brotli 模块(如果需要)
# load_module modules/ngx_http_brotli_filter_module.so;
# load_module modules/ngx_http_brotli_static_module.so;
# 启用 Brotli 压缩
brotli on;
brotli_comp_level 6; # 压缩级别(1-11,默认 6)
brotli_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml
application/xml+rss
application/rss+xml
application/atom+xml
image/svg+xml
font/truetype
font/opentype
application/vnd.ms-fontobject
application/x-font-ttf
application/x-font-opentype
application/x-font-truetype;
# 最小压缩文件大小
brotli_min_length 1024;
# 压缩窗口大小(10-24,默认 22)
brotli_window 512k;
}http {
# Gzip 配置(作为后备)
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript
application/json application/javascript application/xml;
# Brotli 配置(优先使用)
brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css text/xml text/javascript
application/json application/javascript application/xml;
brotli_min_length 1024;
}说明:现代浏览器优先使用 Brotli,不支持 Brotli 的浏览器会使用 Gzip。
server {
# 防止点击劫持
add_header X-Frame-Options "SAMEORIGIN" always;
# XSS 保护
add_header X-XSS-Protection "1; mode=block" always;
# 防止 MIME 类型嗅探
add_header X-Content-Type-Options "nosniff" always;
# Referrer 策略
add_header Referrer-Policy "no-referrer-when-downgrade" always;
# 内容安全策略(根据实际需求调整)
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
# 权限策略
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
}# 禁止访问隐藏文件
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# 禁止访问备份文件
location ~* \.(bak|backup|old|orig|save|tmp)$ {
deny all;
access_log off;
log_not_found off;
}
# IP 白名单
location /admin/ {
allow 192.168.1.0/24;
allow 10.0.0.0/8;
deny all;
}# 静态资源长期缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
# HTML 文件不缓存
location ~* \.html$ {
expires -1;
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
}http {
# 定义缓存路径
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=api_cache:10m
max_size=100m inactive=60m use_temp_path=off;
server {
location /api/ {
proxy_pass http://127.0.0.1:8888/;
# 启用缓存
proxy_cache api_cache;
proxy_cache_valid 200 60m;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_background_update on;
# 缓存键
proxy_cache_key "$scheme$request_method$host$request_uri";
# 添加缓存状态头
add_header X-Cache-Status $upstream_cache_status;
}
}
}# /etc/nginx/sites-available/doc-next-ts.conf
server {
listen 80;
listen [::]:80;
server_name www.wladmin.cn wladmin.cn; # 根据实际域名修改
# 重定向到 HTTPS(如果使用 HTTPS)
# return 301 https://$server_name$request_uri;
# 日志配置
access_log /var/log/nginx/doc-next-ts-access.log;
error_log /var/log/nginx/doc-next-ts-error.log;
# 字符编码
charset utf-8;
# 安全头部
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
# Gzip 压缩
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_comp_level 6;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml
application/xml+rss
application/rss+xml
application/atom+xml
image/svg+xml
font/truetype
font/opentype
application/vnd.ms-fontobject
application/x-font-ttf
application/x-font-opentype
application/x-font-truetype;
# Brotli 压缩(如果已安装模块)
# brotli on;
# brotli_comp_level 6;
# brotli_types text/plain text/css text/xml text/javascript
# application/json application/javascript application/xml;
# brotli_min_length 1024;
# Next.js 静态资源缓存(_next/static)
location /_next/static/ {
proxy_pass http://127.0.0.1:8081;
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_cache_bypass $http_upgrade;
# 长期缓存
expires 365d;
add_header Cache-Control "public, immutable";
access_log off;
}
# 图片资源缓存
location ~* \.(jpg|jpeg|png|gif|ico|svg|webp)$ {
proxy_pass http://127.0.0.1:8081;
proxy_http_version 1.1;
proxy_set_header Host $host;
expires 30d;
add_header Cache-Control "public";
access_log off;
}
# Favicon 精确匹配
location = /favicon.ico {
proxy_pass http://127.0.0.1:8081;
access_log off;
log_not_found off;
expires 1y;
add_header Cache-Control "public, immutable";
}
# Next.js 应用代理
location / {
proxy_pass http://127.0.0.1:8081;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
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_cache_bypass $http_upgrade;
# 超时设置
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# HTML 文件不缓存
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
add_header Pragma "no-cache" always;
add_header Expires "0" always;
}
# 健康检查
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
# 禁止访问隐藏文件
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# 禁止访问备份文件
location ~* \.(bak|backup|old|orig|save|tmp)$ {
deny all;
access_log off;
log_not_found off;
}
# 错误页面
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
}server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.wladmin.cn wladmin.cn;
# SSL 证书配置(使用 Let's Encrypt 或其他证书)
ssl_certificate /etc/letsencrypt/live/wladmin.cn/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/wladmin.cn/privkey.pem;
# SSL 配置优化
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
# HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# 其他配置同上(省略)
# ...
}
# HTTP 重定向到 HTTPS
server {
listen 80;
listen [::]:80;
server_name www.wladmin.cn wladmin.cn;
return 301 https://$server_name$request_uri;
}当 node-express-mysql 作为独立的 API 服务时,可以使用独立的域名或子域名:
# /etc/nginx/sites-available/api-node-express-mysql.conf
server {
listen 80;
listen [::]:80;
server_name api.wladmin.cn api.example.com; # API 域名
# 日志配置
access_log /var/log/nginx/api-access.log;
error_log /var/log/nginx/api-error.log;
# 字符编码
charset utf-8;
# 允许的请求体大小(文件上传需要)
client_max_body_size 50M;
# 安全头部
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
# Gzip 压缩
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_comp_level 6;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml
application/xml+rss
application/rss+xml
application/atom+xml;
# Brotli 压缩(如果已安装模块)
# brotli on;
# brotli_comp_level 6;
# brotli_types text/plain text/css text/xml text/javascript
# application/json application/javascript application/xml;
# brotli_min_length 1024;
# SSE 连接支持(Server-Sent Events)
location /sse/ {
proxy_pass http://127.0.0.1:8888;
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_buffering off;
proxy_cache off;
chunked_transfer_encoding off;
# SSE 需要较长的超时时间
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
# API 代理
location / {
proxy_pass http://127.0.0.1:8888;
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-Client-Type $http_x_client_type;
proxy_set_header X-Client-Page $http_x_client_page;
proxy_set_header X-Client-Id $http_x_client_id;
proxy_set_header X-File-Hash $http_x_file_hash;
# 超时设置
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# 缓冲设置
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
proxy_busy_buffers_size 8k;
# 不缓存 API 响应(API 响应通常不应该被缓存)
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
add_header Pragma "no-cache" always;
add_header Expires "0" always;
}
# 健康检查
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
# 禁止访问隐藏文件
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
}server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name api.wladmin.cn api.example.com;
# SSL 证书配置
ssl_certificate /etc/letsencrypt/live/api.wladmin.cn/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.wladmin.cn/privkey.pem;
# SSL 配置优化
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
# HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# 其他配置同上(省略)
# ...
}
# HTTP 重定向到 HTTPS
server {
listen 80;
listen [::]:80;
server_name api.wladmin.cn api.example.com;
return 301 https://$server_name$request_uri;
}如果不想使用独立的 API 域名,可以在前端项目的 Nginx 配置中添加 API 代理:
# 在 doc-next-ts 或 react-antd-webpack 的 Nginx 配置中添加
server {
# ... 其他配置 ...
# API 代理
location /api/ {
proxy_pass http://127.0.0.1:8888/; # 注意末尾的 "/"
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-Client-Type $http_x_client_type;
proxy_set_header X-Client-Page $http_x_client_page;
proxy_set_header X-Client-Id $http_x_client_id;
# SSE 支持
proxy_set_header Connection '';
proxy_buffering off;
proxy_cache off;
chunked_transfer_encoding off;
# 超时设置
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# SSE 连接(如果需要)
location /sse/ {
proxy_pass http://127.0.0.1:8888;
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_buffering off;
proxy_cache off;
chunked_transfer_encoding off;
# SSE 需要较长的超时时间
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
}react-antd-webpack 是使用 Webpack 构建的 React SPA 应用,需要配置静态文件服务和 API 代理:
# /etc/nginx/sites-available/react-antd-webpack.conf
server {
listen 80;
listen [::]:80;
server_name www.example.com example.com; # 根据实际域名修改
# 日志配置
access_log /var/log/nginx/react-antd-webpack-access.log;
error_log /var/log/nginx/react-antd-webpack-error.log;
# 字符编码
charset utf-8;
# 网站根目录(Webpack 构建后的 dist 目录)
root /www/wwwroot/react-antd-webpack/dist;
index index.html;
# 安全头部
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
# Gzip 压缩
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_comp_level 6;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml
application/xml+rss
application/rss+xml
application/atom+xml
image/svg+xml
font/truetype
font/opentype
application/vnd.ms-fontobject
application/x-font-ttf
application/x-font-opentype
application/x-font-truetype;
# Brotli 压缩(如果已安装模块)
# brotli on;
# brotli_comp_level 6;
# brotli_types text/plain text/css text/xml text/javascript
# application/json application/javascript application/xml
# image/svg+xml font/truetype font/opentype;
# brotli_min_length 1024;
# 静态资源长期缓存(带版本号的文件)
location ~* \.(js|css)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
# 图片资源缓存
location ~* \.(jpg|jpeg|png|gif|ico|svg|webp|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public";
access_log off;
}
# Favicon
location = /favicon.ico {
access_log off;
log_not_found off;
expires 1y;
add_header Cache-Control "public, immutable";
}
# API 代理(代理到后端服务)
location /api/ {
proxy_pass http://127.0.0.1:8888/; # 注意末尾的 "/"
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-Client-Type $http_x_client_type;
proxy_set_header X-Client-Page $http_x_client_page;
proxy_set_header X-Client-Id $http_x_client_id;
# 超时设置
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# 不缓存 API 响应
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
}
# SSE 连接支持
location /sse/ {
proxy_pass http://127.0.0.1:8888;
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_buffering off;
proxy_cache off;
chunked_transfer_encoding off;
# SSE 需要较长的超时时间
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
# SPA 路由支持(所有路由都返回 index.html)
location / {
try_files $uri $uri/ /index.html;
# HTML 文件不缓存
if ($uri ~* \.html$) {
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
add_header Pragma "no-cache" always;
add_header Expires "0" always;
}
}
# 健康检查
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
# 禁止访问隐藏文件
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# 禁止访问备份文件
location ~* \.(bak|backup|old|orig|save|tmp)$ {
deny all;
access_log off;
log_not_found off;
}
# 错误页面
error_page 404 /index.html; # SPA 应用,404 也返回 index.html
error_page 500 502 503 504 /50x.html;
}server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.example.com example.com;
# SSL 证书配置
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# SSL 配置优化
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
# HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# 其他配置同上(省略)
# ...
}
# HTTP 重定向到 HTTPS
server {
listen 80;
listen [::]:80;
server_name www.example.com example.com;
return 301 https://$server_name$request_uri;
}如果所有项目部署在同一服务器上,可以使用以下统一配置:
# /etc/nginx/sites-available/wladmin.conf
# ==================== 文档站(doc-next-ts)====================
server {
listen 80;
listen [::]:80;
server_name www.wladmin.cn wladmin.cn;
# 日志配置
access_log /var/log/nginx/doc-access.log;
error_log /var/log/nginx/doc-error.log;
charset utf-8;
# 安全头部
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
# Gzip + Brotli
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript
application/json application/javascript application/xml;
# brotli on;
# brotli_comp_level 6;
# brotli_types text/plain text/css text/xml text/javascript
# application/json application/javascript application/xml;
# brotli_min_length 1024;
# Next.js 静态资源
location /_next/static/ {
proxy_pass http://127.0.0.1:8081;
proxy_http_version 1.1;
proxy_set_header Host $host;
expires 365d;
add_header Cache-Control "public, immutable";
access_log off;
}
# Next.js 应用(动态内容,不缓存)
location / {
proxy_pass http://127.0.0.1:8081;
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_cache off;
proxy_buffering off;
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
add_header Pragma "no-cache" always;
add_header Expires "0" always;
# 禁用 Nginx 代理缓存
proxy_no_cache 1;
proxy_cache_bypass 1;
}
# API 路由(不缓存)
location /api/ {
proxy_pass http://127.0.0.1:8081;
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;
# API 不缓存
proxy_cache off;
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
}
}
# ==================== 前端应用(react-antd-webpack)====================
server {
listen 80;
listen [::]:80;
server_name admin.wladmin.cn admin.example.com;
access_log /var/log/nginx/admin-access.log;
error_log /var/log/nginx/admin-error.log;
charset utf-8;
root /www/wwwroot/react-antd-webpack/dist;
index index.html;
# 安全头部
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
# Gzip + Brotli
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript
application/json application/javascript application/xml;
# brotli on;
# brotli_comp_level 6;
# brotli_types text/plain text/css text/xml text/javascript
# application/json application/javascript application/xml;
# brotli_min_length 1024;
# 静态资源缓存
location ~* \.(js|css|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
# API 代理
location /api/ {
proxy_pass http://127.0.0.1:8888/;
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-Client-Type $http_x_client_type;
proxy_set_header X-Client-Page $http_x_client_page;
proxy_set_header X-Client-Id $http_x_client_id;
}
# SSE 连接
location /sse/ {
proxy_pass http://127.0.0.1:8888;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header Connection '';
proxy_buffering off;
proxy_cache off;
chunked_transfer_encoding off;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
# SPA 路由
location / {
try_files $uri $uri/ /index.html;
}
}
# ==================== API 服务(node-express-mysql)====================
server {
listen 80;
listen [::]:80;
server_name api.wladmin.cn api.example.com;
access_log /var/log/nginx/api-access.log;
error_log /var/log/nginx/api-error.log;
charset utf-8;
client_max_body_size 50M;
# 安全头部
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
# Gzip + Brotli
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript
application/json application/javascript application/xml;
# brotli on;
# brotli_comp_level 6;
# brotli_types text/plain text/css text/xml text/javascript
# application/json application/javascript application/xml;
# brotli_min_length 1024;
# SSE 连接
location /sse/ {
proxy_pass http://127.0.0.1:8888;
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_buffering off;
proxy_cache off;
chunked_transfer_encoding off;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
# API 代理
location / {
proxy_pass http://127.0.0.1:8888;
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-Client-Type $http_x_client_type;
proxy_set_header X-Client-Page $http_x_client_page;
proxy_set_header X-Client-Id $http_x_client_id;
proxy_set_header X-File-Hash $http_x_file_hash;
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
}
}# 方法一:使用 apt 安装(推荐)
sudo apt-get update
sudo apt-get install nginx-module-brotli
# 安装后需要在 nginx.conf 中加载模块
# load_module modules/ngx_http_brotli_filter_module.so;
# load_module modules/ngx_http_brotli_static_module.so;# 方法一:使用 yum 安装
sudo yum install nginx-mod-http-brotli
# 安装后需要在 nginx.conf 中加载模块
# load_module modules/ngx_http_brotli_filter_module.so;
# load_module modules/ngx_http_brotli_static_module.so;# 下载 Brotli 模块
cd /tmp
git clone https://github.com/google/ngx_brotli.git
cd ngx_brotli
git submodule update --init
# 下载 Nginx 源码
cd /tmp
wget http://nginx.org/download/nginx-1.24.0.tar.gz
tar -xzf nginx-1.24.0.tar.gz
cd nginx-1.24.0
# 配置编译选项
./configure \
--prefix=/etc/nginx \
--sbin-path=/usr/sbin/nginx \
--modules-path=/usr/lib/nginx/modules \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/var/run/nginx.pid \
--lock-path=/var/run/nginx.lock \
--add-module=/tmp/ngx_brotli
# 编译和安装
make
sudo make installhttp {
# 启用 Brotli 压缩
brotli on;
# 压缩级别(1-11)
# 1: 最快,压缩率最低
# 6: 平衡(推荐)
# 11: 最慢,压缩率最高
brotli_comp_level 6;
# 压缩类型(MIME 类型)
brotli_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml
application/xml+rss
application/rss+xml
application/atom+xml
image/svg+xml
font/truetype
font/opentype
application/vnd.ms-fontobject
application/x-font-ttf
application/x-font-opentype
application/x-font-truetype;
# 最小压缩文件大小(字节)
# 小于此大小的文件不压缩
brotli_min_length 1024;
# 压缩窗口大小(10-24,默认 22)
# 窗口越大,压缩率越高,但内存消耗越大
brotli_window 512k;
# 启用 Brotli 静态文件支持(需要 ngx_http_brotli_static_module)
# 如果存在预压缩的 .br 文件,直接使用
brotli_static on;
}Nginx 会自动根据浏览器支持情况选择压缩方式:
配置示例:
http {
# Gzip 配置(作为后备)
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript
application/json application/javascript application/xml;
# Brotli 配置(优先使用)
brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css text/xml text/javascript
application/json application/javascript application/xml;
brotli_min_length 1024;
}如果使用 brotli_static on,可以预先压缩静态文件:
# 安装 brotli 工具
# Ubuntu/Debian
sudo apt-get install brotli
# CentOS/RHEL
sudo yum install brotli
# 压缩文件
brotli -k -q 6 file.js
# 生成 file.js.br
# 批量压缩
find /www/wwwroot/dist -type f \( -name "*.js" -o -name "*.css" \) -exec brotli -k -q 6 {} \;http {
# 工作进程数(auto 表示自动检测 CPU 核心数)
worker_processes auto;
# 每个工作进程的最大连接数
events {
worker_connections 1024;
use epoll; # Linux 使用 epoll
multi_accept on; # 一次接受多个连接
}
# 高效文件传输
sendfile on;
tcp_nopush on; # 优化 TCP 数据包传输
tcp_nodelay on; # 禁用 Nagle 算法
# Keep-Alive 超时时间
keepalive_timeout 65;
keepalive_requests 100; # 每个连接的最大请求数
# 客户端请求体大小限制
client_max_body_size 50M;
# 客户端请求头缓冲区大小
client_header_buffer_size 1k;
large_client_header_buffers 4 16k;
# 文件上传临时目录
client_body_temp_path /var/cache/nginx/client_temp;
# 打开文件缓存
open_file_cache max=10000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
}location /api/ {
proxy_pass http://127.0.0.1:8888;
# 请求头设置
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;
# HTTP 版本
proxy_http_version 1.1;
# 超时设置
proxy_connect_timeout 60s; # 连接超时
proxy_send_timeout 60s; # 发送超时
proxy_read_timeout 60s; # 读取超时
# 缓冲设置
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
proxy_busy_buffers_size 8k;
proxy_temp_file_write_size 8k;
# 禁用缓冲(用于流式响应,如 SSE)
# proxy_buffering off;
# proxy_cache off;
# chunked_transfer_encoding off;
# 重试设置
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
proxy_next_upstream_tries 3;
proxy_next_upstream_timeout 10s;
}# 日志格式定义
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;
access_log off; # 禁用访问日志(用于静态资源)
# 错误日志
error_log /var/log/nginx/error.log warn; # warn, error, crit
error_log /var/log/nginx/error.log debug; # 调试模式(仅开发环境)
# 日志轮转(使用 logrotate)
# /etc/logrotate.d/nginx原因:后端服务未启动或无法连接
排查步骤:
# 1. 检查后端服务是否运行
pm2 list
# 或
ps aux | grep node
# 2. 检查端口是否监听
netstat -tlnp | grep 8888
# 或
lsof -i :8888
# 3. 检查防火墙
sudo ufw status
sudo firewall-cmd --list-all
# 4. 测试后端服务
curl http://127.0.0.1:8888/health
# 5. 查看 Nginx 错误日志
tail -f /var/log/nginx/error.log解决方案:
# 启动后端服务
cd /www/wwwroot/node-express-mysql
pm2 start ecosystem.config.js --env production
# 检查 Nginx 配置
sudo nginx -t
# 重启 Nginx
sudo systemctl restart nginx原因:后端服务响应超时
解决方案:
location /api/ {
proxy_pass http://127.0.0.1:8888;
# 增加超时时间
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}原因:上传文件大小超过限制
解决方案:
# 增加请求体大小限制
client_max_body_size 50M; # 根据实际需求调整原因:SPA 路由未正确配置
解决方案:
location / {
try_files $uri $uri/ /index.html;
}# 检查配置文件语法
sudo nginx -t
# 检查配置文件并显示配置路径
sudo nginx -T
# 重新加载配置(不中断服务)
sudo nginx -s reload
# 重启 Nginx
sudo systemctl restart nginx
# 查看 Nginx 状态
sudo systemctl status nginx
# 查看 Nginx 版本和编译信息
nginx -V# 实时查看访问日志
tail -f /var/log/nginx/access.log
# 实时查看错误日志
tail -f /var/log/nginx/error.log
# 查看最近的错误
tail -n 100 /var/log/nginx/error.log
# 统计访问量
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
# 统计状态码
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
# 查看慢请求
awk '$NF > 1 {print $0}' /var/log/nginx/access.log# 查看 Nginx 进程
ps aux | grep nginx
# 查看连接数
netstat -an | grep :80 | wc -l
# 查看 Nginx 状态(需要启用 stub_status)
curl http://127.0.0.1/nginx_status
# 压力测试
ab -n 1000 -c 10 http://example.com/# Ubuntu/Debian
sudo apt-get update
sudo apt-get install nginx
# CentOS/RHEL
sudo yum install nginx
# 启动 Nginx
sudo systemctl start nginx
sudo systemctl enable nginx# 创建配置文件
sudo nano /etc/nginx/sites-available/doc-next-ts.conf
# 创建符号链接
sudo ln -s /etc/nginx/sites-available/doc-next-ts.conf /etc/nginx/sites-enabled/
# 检查配置
sudo nginx -t
# 重新加载配置
sudo nginx -s reload# 安装 Certbot
sudo apt-get install certbot python3-certbot-nginx
# 获取证书
sudo certbot --nginx -d www.wladmin.cn -d wladmin.cn
# 自动续期测试
sudo certbot renew --dry-run# 编辑 logrotate 配置
sudo nano /etc/logrotate.d/nginx
# 配置内容
/var/log/nginx/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
postrotate
[ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
endscript
}假设服务器目录结构:
/www/wwwroot/
├── doc-next-ts/ # Next.js 文档站
│ ├── .next/
│ ├── node_modules/
│ └── ...
├── react-antd-webpack/ # React 前端应用
│ └── dist/ # Webpack 构建输出
└── node-express-mysql/ # Node.js 后端服务
├── index.js
└── ...部署步骤:
# 1. 构建前端应用
cd /www/wwwroot/react-antd-webpack
npm run build
# 2. 启动后端服务
cd /www/wwwroot/node-express-mysql
pm2 start ecosystem.config.js --env production
# 3. 启动文档站
cd /www/wwwroot/doc-next-ts
pm2 start ecosystem.config.js --env production
# 4. 配置 Nginx
sudo nano /etc/nginx/sites-available/wladmin.conf
# 复制上面的多项目统一配置
# 5. 启用配置
sudo ln -s /etc/nginx/sites-available/wladmin.conf /etc/nginx/sites-enabled/
# 6. 检查并重载
sudo nginx -t
sudo nginx -s reload仅供参考