server { listen 443 ssl; http2 on; server_name ; # 替换为你的域名 gzip on; gzip_proxied any; gzip_comp_level 6; gzip_min_length 1k; gzip_vary on; gzip_types text/plain text/css application/json application/javascript application/x-javascript text/javascript application/xml application/xml+rss image/svg+xml application/manifest+json; # 静态资源强缓存 location ~* ^/assets/.*\.(js|css|woff2?|ttf|eot|svg|png|jpe?g|gif|ico|webp|json|map)$ { proxy_pass http://127.0.0.1:9443; 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; add_header Cache-Control "public, max-age=31536000, immutable"; } include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; location /api/events.mux { proxy_pass http://127.0.0.1:9443; 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_read_timeout 86400s; proxy_send_timeout 86400s; } location /api/events.host { proxy_pass http://127.0.0.1:9443; 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_read_timeout 86400s; proxy_send_timeout 86400s; } # better-sidebar 终端 WS —— 缺升级头则握手失败(浏览器报 …/sidebar/ws/agent-terminals failed) location ^~ /sidebar/ws/ { proxy_pass http://127.0.0.1:9443; 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_read_timeout 86400s; proxy_send_timeout 86400s; } # Authelia 门户(同域子路径挂载,server.path=auth) location = /auth { return 301 /auth/; } location ^~ /auth/ { proxy_pass http://127.0.0.1:9091; 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; # P4:「邀请码注册」入口已内置于 Authelia 门户登录表单(重置密码行左侧, # 由 tools/authelia_register_link_patch.py 对 authelia 二进制的等长补丁提供), # 不再需要 sub_filter 悬浮按钮注入 } # 主路由:必须显式转发 Host! # nginx 默认会把 Host 改成 proxy_pass 里的 127.0.0.1:3088($proxy_host), # dsh 的 /api 信任围栏会校验 Origin 的 host == Host 的 host, # 浏览器带 Origin: https://dsh.example.com 而后端看到 Host: 127.0.0.1:3088 # → 所有 /api 请求 403。 location / { proxy_pass http://127.0.0.1:9443; 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_set_header X-Forwarded-Port $server_port; # sub_filter 手机端缩放 proxy_set_header Accept-Encoding ""; sub_filter 'name="viewport" content="width=device-width, initial-scale=1"' 'name="viewport" content="width=device-width, initial-scale=0.7"'; sub_filter_once on; } 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 Strict-Transport-Security "max-age=31536000; includeSubDomains" always; server_tokens off; ssl_certificate /etc/letsencrypt/live//fullchain.pem; ssl_certificate_key /etc/letsencrypt/live//privkey.pem; } # ────────────────────────────────────────────────────────────────────────────── # 公开站点(P11,同一文件内第二个 server 块)—— 匿名静态发布,无鉴权。 # dsh-tenancy 插件在独立端口(默认 127.0.0.1:3089)服务 # pub.example.com// → ~/dsh///dist # 只读、不走 Caddy/Authelia(构建产物本身就是公开内容)。 # server_name 替换为你的公开站点域名,并同步插件配置 publicSitesHosts(建议) # 与 install.sh 的 PUBLIC_DOMAIN。 # # ⚠ 保持「独立 server 块」形态:公开站点 URL 是两段路径 //。 # 若改在上方 dsh vhost 内用两段正则(如 location ~ ^/[A-Za-z0-9_-]+/[^/]+…) # 分流到 3089,dsh 插件自身的两段路由(/deepseek-balance/settings、 # /footer-order/settings、/plugins//client.js 等)会被一并劫持 → # 侧栏余额读数、插件设置卡片、插件客户端 bundle 全部失效。 # 确需内联时,必须为每个插件路由前缀加 ^~ 前缀豁免(^~ 优先于正则)回 9443, # 且豁免 location 要写成【不带尾斜杠】的 location ^~ /deepseek-balance {…}: # nginx 对「以斜杠结尾的 prefix location + proxy_pass」会在请求 URI 恰为该 # 前缀但缺尾斜杠时直接 301 补斜杠(带斜杠的写法会把本体的 GET /deepseek-balance # 301 到 /deepseek-balance/ → 404,单段路由照样全灭)。 # ────────────────────────────────────────────────────────────────────────────── server { listen 443 ssl; http2 on; server_name pub.example.com; # 替换为你的公开站点域名 gzip on; gzip_proxied any; gzip_comp_level 6; gzip_min_length 1k; gzip_vary on; gzip_types text/plain text/css application/json application/javascript application/x-javascript text/javascript application/xml application/xml+rss image/svg+xml application/manifest+json; location / { proxy_pass http://127.0.0.1:3089; # 与插件 publicSitesPort 一致 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; } add_header X-Content-Type-Options nosniff always; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; server_tokens off; ssl_certificate /etc/letsencrypt/live//fullchain.pem; ssl_certificate_key /etc/letsencrypt/live//privkey.pem; }