# /etc/nginx/sites-available/valuefrontier # 完整配置 - Next.js只处理特定页面,其他全部导向React应用 # WebSocket 连接升级映射 map $http_upgrade $connection_upgrade { default upgrade; '' close; } # HTTP (端口 80) 服务器块: 负责将所有HTTP请求重定向到HTTPS server { listen 80; server_name valuefrontier.cn www.valuefrontier.cn; # 这一段是为了让Certbot自动续期时能正常工作 location /.well-known/acme-challenge/ { root /var/www/html; } location ~ \.txt$ { root /var/www/valuefrontier.cn; add_header Content-Type "text/plain"; } location / { # 301永久重定向到安全的HTTPS版本 return 301 https://$host$request_uri; } } # HTTPS (端口 443) 服务器块: 处理所有加密流量和实际的应用逻辑 server { listen 443 ssl http2; server_name valuefrontier.cn www.valuefrontier.cn; # --- SSL 证书配置 --- ssl_certificate /etc/letsencrypt/live/valuefrontier.cn/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/valuefrontier.cn/privkey.pem; # ============================================ # SEO 文件配置(robots.txt + sitemap.xml) # 优先级最高,放在最前面 # ============================================ # robots.txt - 精确匹配(优先级最高) location = /robots.txt { root /var/www/valuefrontier; add_header Content-Type "text/plain; charset=utf-8"; add_header Cache-Control "public, max-age=3600"; # 缓存 1 小时 access_log off; # 减少日志记录 } # sitemap.xml - 精确匹配 location = /sitemap.xml { root /var/www/valuefrontier; add_header Content-Type "application/xml; charset=utf-8"; add_header Cache-Control "public, max-age=3600"; # 缓存 1 小时 access_log off; } # --- 为React应用提供静态资源 --- location /static/ { alias /var/www/valuefrontier.cn/static/; expires 1y; add_header Cache-Control "public, immutable"; add_header Access-Control-Allow-Origin *; } location ~ \.txt$ { root /var/www/valuefrontier.cn; add_header Content-Type "text/plain"; } location /manifest.json { alias /var/www/valuefrontier.cn/manifest.json; add_header Content-Type "application/json"; } location /favicon.ico { alias /var/www/valuefrontier.cn/favicon.ico; } # --- Next.js 专用静态资源 (已废弃,保留以防需要回滚) --- # location /_next/ { # proxy_pass http://127.0.0.1:3000; # 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; # expires 1y; # add_header Cache-Control "public, immutable"; # } # --- 后端API反向代理 --- location /api/ { proxy_pass http://127.0.0.1:5001; 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; } location /socket.io/ { proxy_pass http://127.0.0.1:5001; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; 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_connect_timeout 7d; proxy_send_timeout 7d; proxy_read_timeout 7d; proxy_buffering off; } # ============================================ # 实时行情 WebSocket 代理(灵活屏功能) # ============================================ # 上交所实时行情 WebSocket location /ws/sse { proxy_pass http://49.232.185.254:8765; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $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_connect_timeout 7d; proxy_send_timeout 7d; proxy_read_timeout 7d; proxy_buffering off; } # 深交所实时行情 WebSocket location /ws/szse { proxy_pass http://222.128.1.157:8765; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $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_connect_timeout 7d; proxy_send_timeout 7d; proxy_read_timeout 7d; proxy_buffering off; } location /mcp/ { proxy_pass http://127.0.0.1:8900/; 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 on; proxy_connect_timeout 75s; proxy_send_timeout 300s; proxy_read_timeout 300s; gzip off; add_header X-Accel-Buffering no; add_header 'Access-Control-Allow-Origin' '$http_origin' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With' always; add_header 'Access-Control-Allow-Credentials' 'true' always; if ($request_method = 'OPTIONS') { return 204; } } # 概念板块API代理 location /concept-api/ { proxy_pass http://222.128.1.157:16801/; 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 Access-Control-Allow-Origin *; proxy_set_header Access-Control-Allow-Methods "GET, POST, OPTIONS"; proxy_set_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range"; proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; } # Elasticsearch API代理(价值论坛) location /es-api/ { proxy_pass http://222.128.1.157:19200/; 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; # CORS 配置 add_header 'Access-Control-Allow-Origin' '*' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS, HEAD' always; add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always; add_header 'Access-Control-Allow-Credentials' 'true' always; # 处理 OPTIONS 预检请求 if ($request_method = 'OPTIONS') { return 204; } # 超时设置 proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; # 禁用缓冲以支持流式响应 proxy_buffering off; } # 拜特桌面API代理 (bytedesk) location /bytedesk/ { proxy_pass http://43.143.189.195/; 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; add_header 'Access-Control-Allow-Origin' '*' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always; add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always; add_header 'Access-Control-Allow-Credentials' 'true' always; if ($request_method = 'OPTIONS') { return 204; } proxy_connect_timeout 120s; proxy_send_timeout 120s; proxy_read_timeout 120s; } # 2. WebSocket代理(必需!) location /websocket { proxy_pass http://43.143.189.195/websocket; 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_connect_timeout 86400s; proxy_send_timeout 86400s; proxy_read_timeout 86400s; } # iframe 内部资源代理(Bytedesk 聊天窗口的 CSS/JS) location /chat/ { proxy_pass http://43.143.189.195/chat/; 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; # ✨ 自动替换响应内容中的 IP 地址为域名(解决 Mixed Content) sub_filter 'http://43.143.189.195' 'https://valuefrontier.cn'; sub_filter_once off; # 替换所有匹配项 sub_filter_types text/css text/javascript application/javascript application/json; # CORS 头部 add_header 'Access-Control-Allow-Origin' '*' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always; add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always; add_header 'Access-Control-Allow-Credentials' 'true' always; if ($request_method = 'OPTIONS') { return 204; } # 超时设置 proxy_connect_timeout 120s; proxy_send_timeout 120s; proxy_read_timeout 120s; } # Bytedesk 配置接口代理 location /config/ { proxy_pass http://43.143.189.195/config/; 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; # CORS 头部 add_header 'Access-Control-Allow-Origin' '*' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always; add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always; if ($request_method = 'OPTIONS') { return 204; } # 超时设置 proxy_connect_timeout 120s; proxy_send_timeout 120s; proxy_read_timeout 120s; } # Bytedesk 上传文件代理 location ^~ /uploads/ { proxy_pass http://43.143.189.195/uploads/; 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_valid 200 1d; expires 1d; add_header Cache-Control "public, max-age=86400"; } # Bytedesk 文件访问代理(仅 2025 年文件) location ^~ /file/2025/ { proxy_pass http://43.143.189.195/file/2025/; 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_valid 200 1d; expires 1d; add_header Cache-Control "public, max-age=86400"; add_header Access-Control-Allow-Origin *; } # Visitor API 代理(Bytedesk 初始化接口) location /visitor/ { proxy_pass http://43.143.189.195/visitor/; 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; # ✨ 禁用压缩(让 sub_filter 能处理 JSON) proxy_set_header Accept-Encoding ""; # ✨ 替换 JSON 响应中的 IP 地址为域名 sub_filter 'http://43.143.189.195' 'https://valuefrontier.cn'; sub_filter_once off; sub_filter_types application/json; add_header 'Access-Control-Allow-Origin' '*' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With' always; if ($request_method = 'OPTIONS') { return 204; } proxy_connect_timeout 120s; proxy_send_timeout 120s; proxy_read_timeout 120s; } location = /stomp { proxy_pass http://43.143.189.195/api/websocket; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $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; add_header 'Access-Control-Allow-Origin' '*' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always; add_header 'Access-Control-Allow-Credentials' 'true' always; if ($request_method = 'OPTIONS') { return 204; } proxy_connect_timeout 7d; proxy_send_timeout 7d; proxy_read_timeout 7d; proxy_buffering off; } location /stomp/ { proxy_pass http://43.143.189.195/api/websocket/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $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; add_header 'Access-Control-Allow-Origin' '*' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always; add_header 'Access-Control-Allow-Credentials' 'true' always; if ($request_method = 'OPTIONS') { return 204; } proxy_connect_timeout 7d; proxy_send_timeout 7d; proxy_read_timeout 7d; proxy_buffering off; } # 6. 头像和静态资源(解决404问题) location ^~ /avatars/ { proxy_pass http://43.143.189.195/uploads/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; # 缓存静态资源 proxy_cache_valid 200 1d; proxy_cache_bypass $http_cache_control; } # 7. Bytedesk所有其他资源 location /assets/ { proxy_pass http://43.143.189.195/assets/; proxy_set_header Host $host; expires 1d; add_header Cache-Control "public, immutable"; } # 新闻搜索API代理 location /news-api/ { proxy_pass http://222.128.1.157:21891/; 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 Access-Control-Allow-Origin *; proxy_set_header Access-Control-Allow-Methods "GET, POST, OPTIONS"; proxy_set_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range"; proxy_connect_timeout 90s; proxy_send_timeout 90s; proxy_read_timeout 90s; } # 研报搜索API代理 location /report-api/ { proxy_pass http://222.128.1.157:8811/; 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 Access-Control-Allow-Origin *; proxy_set_header Access-Control-Allow-Methods "GET, POST, OPTIONS"; proxy_set_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range"; proxy_connect_timeout 120s; proxy_send_timeout 120s; proxy_read_timeout 120s; } # 商品分类树数据API代理(数据浏览器) location /category-api/ { proxy_pass http://222.128.1.157:18827/; 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; # CORS 配置 add_header 'Access-Control-Allow-Origin' '*' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always; # 处理 OPTIONS 预检请求 if ($request_method = 'OPTIONS') { return 204; } # 超时设置(数据量大,需要较长超时时间) proxy_connect_timeout 120s; proxy_send_timeout 120s; proxy_read_timeout 120s; # 缓冲配置(支持大响应体) proxy_buffering on; proxy_buffer_size 128k; proxy_buffers 8 256k; proxy_busy_buffers_size 512k; } # --- 新的静态官网静态资源(优先级最高) --- # 使用 ^~ 前缀确保优先匹配,不被后面的规则覆盖 location ^~ /css/ { root /var/www/valuefrontier; expires 1y; add_header Cache-Control "public, immutable"; } location ^~ /js/ { root /var/www/valuefrontier; expires 1y; add_header Cache-Control "public, immutable"; } location ^~ /img/ { root /var/www/valuefrontier; expires 1y; add_header Cache-Control "public, immutable"; } location ^~ /videos/ { root /var/www/valuefrontier; expires 1y; add_header Cache-Control "public, immutable"; } location ^~ /fonts/ { root /var/www/valuefrontier; expires 1y; add_header Cache-Control "public, immutable"; } # 官网HTML页面 location ~ ^/(conversational-ai|customizable-workflows|integration|docs|sign-in|sign-up|reset-password)\.html$ { root /var/www/valuefrontier; try_files $uri =404; } # 官网首页 - 静态HTML location = / { root /var/www/valuefrontier; try_files /index.html =404; } # --- React 应用 (默认 catch-all) --- # 所有其他路径都导向React应用 # 包括: /home, /community, /concepts, /limit-analyse, /stocks 等 location / { root /var/www/valuefrontier.cn; index index.html index.htm; # 所有SPA路由都返回index.html让React处理 try_files $uri $uri/ /index.html; # 为静态资源添加缓存头 location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { expires 1y; add_header Cache-Control "public, immutable"; add_header Access-Control-Allow-Origin *; } } } # ========================================================== # api.valuefrontier.cn - 服务器配置块 (START) # ========================================================== server { if ($host = api.valuefrontier.cn) { return 301 https://$host$request_uri; } # managed by Certbot listen 80; server_name api.valuefrontier.cn; # <--- 明确指定域名 # 这一段是为了让Certbot自动续期时能正常工作 location /.well-known/acme-challenge/ { root /var/www/html; } # 将所有到 api 域名的 HTTP 请求重定向到 HTTPS location / { return 301 https://$host$request_uri; } } server { listen 443 ssl http2; server_name api.valuefrontier.cn; # <--- 明确指定域名 # --- SSL 证书配置 --- # Certbot 会自动填充这里,但我们可以先写上占位符 ssl_certificate /etc/letsencrypt/live/api.valuefrontier.cn/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/api.valuefrontier.cn/privkey.pem; # managed by Certbot # (推荐) 包含通用的SSL安全配置 # include /etc/letsencrypt/options-ssl-nginx.conf; # ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # --- API 反向代理 --- location / { # 假设你的API后端运行在本地的8080端口 # 请修改为你API服务的真实地址和端口 proxy_pass http://127.0.0.1:8080; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; 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.valuefrontier.cn - 服务器配置块 (END) # ==========================================================