Files
vf_react/valuefrontier
2025-11-15 09:50:55 +08:00

529 lines
19 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# /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;
# --- 为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;
}
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";
}
# 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;
}
# --- 新的静态官网静态资源(优先级最高) ---
# 使用 ^~ 前缀确保优先匹配,不被后面的规则覆盖
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)
# ==========================================================