add example config sit & prod

This commit is contained in:
Haitao Pan 2025-10-07 18:57:48 +08:00
parent f6d93323f7
commit 60789efbf2
9 changed files with 2707 additions and 0 deletions

View File

@ -0,0 +1,151 @@
# ==============================================
# XControl Homepage — Production (Dynamic Render)
# Structure: Nginx → Node.js(3000) → Go(8080/8090)
# ==============================================
server {
listen 80;
server_name www.svc.plus global-homepage.svc.plus;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name www.svc.plus global-homepage.svc.plus;
ssl_certificate /etc/ssl/svc.plus.pem;
ssl_certificate_key /etc/ssl/svc.plus.rsa.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# ===============================
# 基本安全头(推荐保持)
# ===============================
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header Referrer-Policy "strict-origin-when-cross-origin";
add_header X-XSS-Protection "1; mode=block";
# ===============================
# API 反向代理
# ===============================
# 优先匹配认证服务
location ^~ /api/auth/ {
proxy_pass http://127.0.0.1:8080;
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/ 请求转 server 服务
location ^~ /api/ {
proxy_pass http://127.0.0.1:8090;
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;
}
# AskAI 接口限流 (保持 Lua 逻辑不变)
location = /api/askai {
access_by_lua_block {
local redis = require "resty.redis"
local r = redis:new()
r:set_timeout(200)
local ok, err = r:connect("127.0.0.1", 6379)
if not ok then
ngx.log(ngx.ERR, "Redis connect error: ", err)
return ngx.exit(500)
end
local user = ngx.var.arg_user or ngx.var.remote_addr
local today = os.date("%Y%m%d")
local key = "limit:user:" .. user .. ":" .. today
local count, err = r:incr(key)
if count == 1 then r:expire(key, 86400) end
if count > 200 then
ngx.status = 429
ngx.header["Content-Type"] = "text/plain; charset=utf-8"
ngx.say("Too Many Requests: daily limit reached")
return ngx.exit(429)
end
}
proxy_pass http://127.0.0.1:8090;
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;
}
# ===============================
# 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;
access_log off;
expires 7d;
add_header Cache-Control "public, max-age=31536000, immutable";
}
location = /favicon.ico {
proxy_pass http://127.0.0.1:3000;
}
location / {
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;
proxy_set_header Cookie $http_cookie;
proxy_pass_header Set-Cookie;
# WebSocket 支持 (Next.js HMR / API routes)
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# 可选:微缓存 SSR 页面(减少 Node 负载)
# proxy_cache ssr_cache;
# proxy_cache_key $scheme$host$request_uri;
# proxy_cache_valid 200 10s;
# proxy_cache_valid 404 1s;
# add_header X-Cache $upstream_cache_status;
}
# ===============================
# 隐藏文件保护
# ===============================
location ~ /\. {
deny all;
}
# ===============================
# 性能优化gzip 压缩
# ===============================
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
gzip_min_length 1024;
gzip_proxied any;
gzip_comp_level 6;
}

View File

@ -0,0 +1,18 @@
-- init.sql
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE IF NOT EXISTS documents (
id BIGSERIAL PRIMARY KEY,
repo TEXT NOT NULL,
path TEXT NOT NULL,
chunk_id INT NOT NULL,
content TEXT NOT NULL,
embedding VECTOR(1024),
metadata JSONB
);
CREATE INDEX IF NOT EXISTS documents_embedding_idx
ON documents USING hnsw (embedding vector_cosine_ops);
CREATE INDEX IF NOT EXISTS idx_documents_metadata
ON documents USING gin (metadata);

View File

@ -0,0 +1,77 @@
server {
listen 80;
server_name dev.svc.plus dev-homepage.svc.plus;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name dev.svc.plus dev-homepage.svc.plus;
ssl_certificate /etc/ssl/svc.plus.pem;
ssl_certificate_key /etc/ssl/svc.plus.rsa.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
# ================================
# Next.js 静态资源 (_next/static/*)
# ================================
location /_next/static/ {
proxy_pass http://127.0.0.1:3001;
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;
# 静态文件可缓存一年
access_log off;
expires 7d;
add_header Cache-Control "public, max-age=31536000, immutable";
}
# ================================
# Public 静态资源 (favicon, images)
# ================================
location /public/ {
alias /var/www/XControl/ui/homepage/public/;
access_log off;
expires 30d;
add_header Cache-Control "public, max-age=2592000";
}
# ================================
# API / SSR 页面
# ================================
location / {
proxy_pass http://127.0.0.1:3001;
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 Cookie $http_cookie;
proxy_pass_header Set-Cookie;
# WebSocket 支持 (Next.js HMR, API)
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# 禁止访问隐藏文件
location ~ /\. {
deny all;
}
# ================================
# 性能优化:开启 gzip 压缩
# ================================
gzip on;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
gzip_min_length 1024;
gzip_proxied any;
gzip_comp_level 6;
}

2361
example/sit/redis.conf Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,49 @@
global:
redis:
addr: "127.0.0.1:6379"
password: ""
vectordb:
pgurl: "postgres://shenlan:password@127.0.0.1:5432/shenlan"
datasources:
- name: Xstream
repo: https://github.com/svc-design/Xstream
path: docs
- name: documents
repo: https://github.com/svc-design/documents
path: /
- name: XControl
repo: https://github.com/svc-design/XControl
path: docs
sync:
repo:
proxy: socks5://127.0.0.1:1080 # 仅在同步仓库时使用代理
models:
embedder:
provider: "huggingface_hub"
models: "bge-m3"
endpoint: "http://127.0.0.1:9000/v1/embeddings"
generator:
provider: "ollama"
models:
- 'gemma3:4b'
endpoint: "http://127.0.0.1:11434/v1/chat/completions"
embedding:
max_batch: 64
dimension: 1024 #维度
max_chars: 8000
rate_limit_tpm: 120000
chunking:
embed_toc: true
max_tokens: 800
overlap_tokens: 80
prefer_heading_split: true
include_exts: [".md", ".mdx"]
ignore_dirs: [".git", "node_modules", "dist", "build"]
api:
askai:
timeout: 100
retries: 3

View File

@ -0,0 +1,51 @@
global:
redis:
addr: "127.0.0.1:6379"
password: ""
vectordb:
pgurl: "postgres://shenlan:password@127.0.0.1:5432/postgres"
datasources:
- name: Xstream
repo: https://github.com/svc-design/Xstream
path: docs
- name: XControl
repo: https://github.com/svc-design/XControl
path: docs
- name: documents
repo: https://github.com/svc-design/documents
path: /
sync:
repo:
proxy: socks5://127.0.0.1:1080 # 仅在同步仓库时使用代理
provider:
- name: ollama
endpoint: http://localhost:11434
models:
- 'gpt-oss:20b'
- name: chutes
endpoint: https://llm.chutes.ai/v1
token: "cpk_xxxxxxxxxxxxxxxxxx"
models:
- 'moonshotai/Kimi-K2-Instruct'
embedding:
endpoint: https://chutes-baai-bge-m3.chutes.ai/embed
token: "cpk_xxxxxxxxxxxxxxxxxx"
dimension: 0 # 0 = 首次响应自动探测维度
rate_limit_tpm: 120000
max_batch: 64
max_chars: 8000
chunking:
max_tokens: 800
overlap_tokens: 80
prefer_heading_split: true
include_exts: [".md", ".mdx"]
ignore_dirs: [".git", "node_modules", "dist", "build"]
embed_toc: true
api:
askai:
timeout: 100
retries: 3