diff --git a/scripts/ci/preview_nginx.conf.template b/scripts/ci/preview_nginx.conf.template new file mode 100644 index 000000000..2b420eda5 --- /dev/null +++ b/scripts/ci/preview_nginx.conf.template @@ -0,0 +1,226 @@ +# ============================================================ +# 预览环境 Nginx 配置模板 +# 支持 *.preview.xiaoxiajianji.com 通配符子域名 +# +# 使用方法: +# 1. 将本文件复制到 Nginx 配置目录(如 /etc/nginx/conf.d/preview.conf) +# 2. 根据实际情况修改域名和 API 地址 +# 3. 运行 nginx -t 测试配置 +# 4. 运行 nginx -s reload 重载配置 +# +# 前置条件: +# - DNS 已配置 *.preview.xiaoxiajianji.com 指向本服务器 +# - 预览根目录已创建:/var/www/preview/ +# - 每个 PR 的静态文件放在 /var/www/preview/pr-{N}/ 下 +# ============================================================ + +# ---- 变量定义 ---- +# 从子域名中提取 PR 号(如 pr-123.preview -> pr-123) +map $host $preview_pr { + default ""; + ~^(?pr-\d+)\.preview\.xiaoxiajianji\.com$ $pr; +} + +# ---- HTTP 服务器(80端口) ---- +server { + listen 80; + server_name *.preview.xiaoxiajianji.com; + + # 根目录根据子域名动态映射 + root /var/www/preview/$preview_pr; + + # 索引文件 + index index.html; + + # 字符集 + charset utf-8; + + # 访问日志 + access_log /var/log/nginx/preview_access.log; + error_log /var/log/nginx/preview_error.log warn; + + # 如果子域名格式不正确,返回404 + if ($preview_pr = "") { + return 404; + } + + # 如果预览目录不存在,返回404 + if (!-d $document_root) { + return 404; + } + + # ---- API 反向代理到 staging 环境 ---- + location /api/ { + proxy_pass https://staging-api.xiaoxiajianji.com/api/; + proxy_http_version 1.1; + + # 请求头设置 + proxy_set_header Host staging-api.xiaoxiajianji.com; + 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 30s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + + # 缓冲设置 + proxy_buffering on; + proxy_buffer_size 4k; + proxy_buffers 8 4k; + + # 重定向跟随 + proxy_redirect off; + + # WebSocket 支持(如需要,取消注释) + # proxy_set_header Upgrade $http_upgrade; + # proxy_set_header Connection "upgrade"; + } + + # ---- 生成文件代理(如需要) ---- + # location /generated-files/ { + # proxy_pass https://staging-api.xiaoxiajianji.com/generated-files/; + # proxy_http_version 1.1; + # proxy_set_header Host staging-api.xiaoxiajianji.com; + # 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; + # } + + # ---- 静态资源缓存 ---- + location /assets/ { + expires 7d; + add_header Cache-Control "public, max-age=604800, immutable"; + try_files $uri =404; + } + + # ---- SPA 路由支持 ---- + location / { + try_files $uri $uri/ /index.html; + } + + # ---- 安全相关响应头 ---- + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + + # ---- 禁止隐藏文件访问 ---- + location ~ /\. { + deny all; + access_log off; + log_not_found off; + } + + # ---- 禁止敏感文件访问 ---- + location ~* \.(env|log|sql|bak|swp|tmp|zip|tar|gz)$ { + deny all; + access_log off; + log_not_found off; + } +} + +# ============================================================ +# HTTPS 服务器配置(可选,需要 SSL 证书) +# +# 推荐使用 Let's Encrypt 通配符证书: +# certbot certonly --dns-xxx -d "*.preview.xiaoxiajianji.com" +# +# 启用方法:取消下方注释,并修改证书路径 +# ============================================================ +# +# server { +# listen 443 ssl http2; +# server_name *.preview.xiaoxiajianji.com; +# +# # SSL 证书配置 +# ssl_certificate /etc/letsencrypt/live/preview.xiaoxiajianji.com/fullchain.pem; +# ssl_certificate_key /etc/letsencrypt/live/preview.xiaoxiajianji.com/privkey.pem; +# +# # SSL 安全配置 +# 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; +# ssl_session_cache shared:SSL:10m; +# ssl_session_timeout 10m; +# ssl_session_tickets off; +# +# # OCSP Stapling +# ssl_stapling on; +# ssl_stapling_verify on; +# +# # 根目录根据子域名动态映射 +# root /var/www/preview/$preview_pr; +# +# # 索引文件 +# index index.html; +# +# # 字符集 +# charset utf-8; +# +# # 访问日志 +# access_log /var/log/nginx/preview_ssl_access.log; +# error_log /var/log/nginx/preview_ssl_error.log warn; +# +# # 如果子域名格式不正确,返回404 +# if ($preview_pr = "") { +# return 404; +# } +# +# # 如果预览目录不存在,返回404 +# if (!-d $document_root) { +# return 404; +# } +# +# # API 反向代理到 staging 环境 +# location /api/ { +# proxy_pass https://staging-api.xiaoxiajianji.com/api/; +# proxy_http_version 1.1; +# proxy_set_header Host staging-api.xiaoxiajianji.com; +# 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 30s; +# proxy_send_timeout 60s; +# proxy_read_timeout 60s; +# proxy_buffering on; +# proxy_buffer_size 4k; +# proxy_buffers 8 4k; +# } +# +# # 静态资源缓存 +# location /assets/ { +# expires 7d; +# add_header Cache-Control "public, max-age=604800, immutable"; +# try_files $uri =404; +# } +# +# # SPA 路由支持 +# location / { +# try_files $uri $uri/ /index.html; +# } +# +# # 安全相关响应头 +# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; +# add_header X-Frame-Options "SAMEORIGIN" always; +# add_header X-Content-Type-Options "nosniff" always; +# add_header X-XSS-Protection "1; mode=block" always; +# add_header Referrer-Policy "strict-origin-when-cross-origin" always; +# +# # 禁止隐藏文件访问 +# location ~ /\. { +# deny all; +# access_log off; +# log_not_found off; +# } +# +# # 禁止敏感文件访问 +# location ~* \.(env|log|sql|bak|swp|tmp|zip|tar|gz)$ { +# deny all; +# access_log off; +# log_not_found off; +# } +# }