Add production Jenkins release pipelines
This commit is contained in:
76
deploy/env/api-server.env.example
vendored
Normal file
76
deploy/env/api-server.env.example
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
# 复制到 /etc/genarrative/api-server.env 后再填入真实生产值。
|
||||
# 该文件只能保存在生产服务器,不进入构建产物,不提交真实密钥。
|
||||
|
||||
GENARRATIVE_ENV=production
|
||||
GENARRATIVE_API_HOST=127.0.0.1
|
||||
GENARRATIVE_API_PORT=8082
|
||||
GENARRATIVE_API_LOG=info,tower_http=info
|
||||
|
||||
GENARRATIVE_ADMIN_USERNAME=
|
||||
GENARRATIVE_ADMIN_PASSWORD=
|
||||
GENARRATIVE_ADMIN_TOKEN_TTL_SECONDS=14400
|
||||
GENARRATIVE_INTERNAL_API_SECRET=CHANGE_ME_FOR_PRODUCTION
|
||||
|
||||
GENARRATIVE_JWT_ISSUER=genarrative-production
|
||||
GENARRATIVE_JWT_SECRET=CHANGE_ME_FOR_PRODUCTION
|
||||
GENARRATIVE_JWT_ACCESS_TOKEN_TTL_SECONDS=7200
|
||||
AUTH_REFRESH_COOKIE_NAME=genarrative_refresh_session
|
||||
AUTH_REFRESH_SESSION_TTL_DAYS=30
|
||||
AUTH_REFRESH_COOKIE_PATH=/api/auth
|
||||
AUTH_REFRESH_COOKIE_SAME_SITE=Lax
|
||||
AUTH_REFRESH_COOKIE_SECURE=true
|
||||
GENARRATIVE_AUTH_STORE_PATH=/var/lib/genarrative/auth/auth-store.json
|
||||
GENARRATIVE_DEV_PASSWORD_ENTRY_AUTO_REGISTER_ENABLED=false
|
||||
|
||||
GENARRATIVE_SPACETIME_SERVER_URL=http://127.0.0.1:3000
|
||||
GENARRATIVE_SPACETIME_DATABASE=genarrative-prod
|
||||
GENARRATIVE_SPACETIME_TOKEN=
|
||||
GENARRATIVE_SPACETIME_POOL_SIZE=8
|
||||
GENARRATIVE_SPACETIME_PROCEDURE_TIMEOUT_SECONDS=45
|
||||
|
||||
GENARRATIVE_LLM_PROVIDER=openai-compatible
|
||||
GENARRATIVE_LLM_BASE_URL=
|
||||
GENARRATIVE_LLM_API_KEY=
|
||||
GENARRATIVE_LLM_MODEL=
|
||||
GENARRATIVE_RPG_LLM_WEB_SEARCH_ENABLED=false
|
||||
GENARRATIVE_CREATION_AGENT_LLM_WEB_SEARCH_ENABLED=false
|
||||
|
||||
DASHSCOPE_BASE_URL=https://dashscope.aliyuncs.com/api/v1
|
||||
DASHSCOPE_API_KEY=
|
||||
DASHSCOPE_IMAGE_MODEL=wan2.7-image
|
||||
DASHSCOPE_IMAGE_REQUEST_TIMEOUT_MS=150000
|
||||
DASHSCOPE_CHARACTER_VISUAL_MODEL=wan2.7-image-pro
|
||||
DASHSCOPE_CHARACTER_IMAGE_SEQUENCE_MODEL=wan2.7-image-pro
|
||||
DASHSCOPE_CHARACTER_REFERENCE_VIDEO_MODEL=wan2.7-r2v
|
||||
DASHSCOPE_CHARACTER_MOTION_TRANSFER_MODEL=wan2.2-animate-move
|
||||
DASHSCOPE_CHARACTER_VIDEO_REQUEST_TIMEOUT_MS=420000
|
||||
|
||||
SMS_AUTH_ENABLED=false
|
||||
SMS_AUTH_PROVIDER=aliyun
|
||||
ALIYUN_SMS_ACCESS_KEY_ID=
|
||||
ALIYUN_SMS_ACCESS_KEY_SECRET=
|
||||
ALIYUN_SMS_ENDPOINT=dypnsapi.aliyuncs.com
|
||||
ALIYUN_SMS_SIGN_NAME=
|
||||
ALIYUN_SMS_TEMPLATE_CODE=
|
||||
ALIYUN_SMS_TEMPLATE_PARAM_KEY=code
|
||||
ALIYUN_SMS_COUNTRY_CODE=86
|
||||
|
||||
WECHAT_AUTH_ENABLED=false
|
||||
WECHAT_AUTH_PROVIDER=real
|
||||
WECHAT_APP_ID=
|
||||
WECHAT_APP_SECRET=
|
||||
WECHAT_CALLBACK_PATH=/api/auth/wechat/callback
|
||||
WECHAT_REDIRECT_PATH=/
|
||||
WECHAT_AUTHORIZE_ENDPOINT=https://open.weixin.qq.com/connect/qrconnect
|
||||
WECHAT_ACCESS_TOKEN_ENDPOINT=https://api.weixin.qq.com/sns/oauth2/access_token
|
||||
WECHAT_USER_INFO_ENDPOINT=https://api.weixin.qq.com/sns/userinfo
|
||||
WECHAT_STATE_TTL_MINUTES=15
|
||||
|
||||
ALIYUN_OSS_BUCKET=
|
||||
ALIYUN_OSS_ENDPOINT=oss-cn-shanghai.aliyuncs.com
|
||||
ALIYUN_OSS_ACCESS_KEY_ID=
|
||||
ALIYUN_OSS_ACCESS_KEY_SECRET=
|
||||
ALIYUN_OSS_READ_EXPIRE_SECONDS=600
|
||||
ALIYUN_OSS_POST_EXPIRE_SECONDS=600
|
||||
ALIYUN_OSS_POST_MAX_SIZE_BYTES=20971520
|
||||
ALIYUN_OSS_SUCCESS_ACTION_STATUS=200
|
||||
101
deploy/nginx/genarrative.conf
Normal file
101
deploy/nginx/genarrative.conf
Normal file
@@ -0,0 +1,101 @@
|
||||
# 生产域名需要在部署前替换为真实域名,并由 certbot 或等价流程写入 HTTPS 证书配置。
|
||||
server {
|
||||
listen 80;
|
||||
server_name genarrative.example.com;
|
||||
|
||||
location /.well-known/acme-challenge/ {
|
||||
root /var/www/html;
|
||||
}
|
||||
|
||||
location / {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name genarrative.example.com;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/genarrative.example.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/genarrative.example.com/privkey.pem;
|
||||
|
||||
root /srv/genarrative/web;
|
||||
index index.html;
|
||||
|
||||
include /etc/nginx/snippets/genarrative-maintenance.conf;
|
||||
|
||||
location ^~ /admin/api/ {
|
||||
default_type application/json;
|
||||
|
||||
if ($genarrative_maintenance) {
|
||||
return 503 '{"ok":false,"error":{"code":"MAINTENANCE","message":"服务维护中"}}';
|
||||
}
|
||||
|
||||
proxy_pass http://127.0.0.1:8082/admin/api/;
|
||||
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-Request-Id $request_id;
|
||||
}
|
||||
|
||||
location = /admin {
|
||||
return 301 /admin/;
|
||||
}
|
||||
|
||||
location ^~ /admin/assets/ {
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location ^~ /admin/ {
|
||||
error_page 503 /maintenance.html;
|
||||
|
||||
if ($genarrative_maintenance) {
|
||||
return 503;
|
||||
}
|
||||
|
||||
try_files $uri $uri/ /admin/index.html;
|
||||
}
|
||||
|
||||
location ^~ /assets/ {
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
# 生产公网不再暴露旧一体化 API、生成资源代理和健康检查入口。
|
||||
location ~ ^/(api|generated-|healthz) {
|
||||
return 404;
|
||||
}
|
||||
|
||||
# SpacetimeDB 只开放 TypeScript SDK 运行所需的最小公网路由。
|
||||
location ~ ^/v1/database/[^/]+/subscribe$ {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "Upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_read_timeout 3600s;
|
||||
}
|
||||
|
||||
location ^~ /v1/identity {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "Upgrade";
|
||||
proxy_set_header Host $host;
|
||||
}
|
||||
|
||||
location ^~ /v1/ {
|
||||
return 404;
|
||||
}
|
||||
|
||||
location / {
|
||||
error_page 503 /maintenance.html;
|
||||
|
||||
if ($genarrative_maintenance) {
|
||||
return 503;
|
||||
}
|
||||
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
}
|
||||
12
deploy/nginx/snippets/genarrative-maintenance.conf
Normal file
12
deploy/nginx/snippets/genarrative-maintenance.conf
Normal file
@@ -0,0 +1,12 @@
|
||||
# 维护模式由发布脚本或人工运维通过固定文件控制。
|
||||
# 文件存在时,普通页面展示维护页,管理 API 返回 503。
|
||||
set $genarrative_maintenance 0;
|
||||
if (-f /var/lib/genarrative/maintenance/enabled) {
|
||||
set $genarrative_maintenance 1;
|
||||
}
|
||||
|
||||
location = /maintenance.html {
|
||||
root /srv/genarrative/web;
|
||||
add_header Cache-Control "no-store";
|
||||
internal;
|
||||
}
|
||||
26
deploy/systemd/genarrative-api.service
Normal file
26
deploy/systemd/genarrative-api.service
Normal file
@@ -0,0 +1,26 @@
|
||||
[Unit]
|
||||
Description=Genarrative Rust API Server
|
||||
After=network-online.target spacetimedb.service
|
||||
Wants=network-online.target
|
||||
Requires=spacetimedb.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=genarrative
|
||||
Group=genarrative
|
||||
WorkingDirectory=/opt/genarrative/current
|
||||
EnvironmentFile=/etc/genarrative/api-server.env
|
||||
ExecStart=/opt/genarrative/current/api-server
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
KillSignal=SIGINT
|
||||
TimeoutStopSec=30
|
||||
|
||||
# api-server 只读发布目录,运行态写入必须显式落到环境变量指定的服务端私有目录。
|
||||
NoNewPrivileges=true
|
||||
PrivateTmp=true
|
||||
ProtectSystem=full
|
||||
ReadWritePaths=/opt/genarrative /var/lib/genarrative
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
23
deploy/systemd/spacetimedb.service
Normal file
23
deploy/systemd/spacetimedb.service
Normal file
@@ -0,0 +1,23 @@
|
||||
[Unit]
|
||||
Description=SpacetimeDB Server
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=spacetimedb
|
||||
Group=spacetimedb
|
||||
WorkingDirectory=/stdb
|
||||
ExecStart=/stdb/spacetime --root-dir=/stdb start --listen-addr=127.0.0.1:3000
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
LimitNOFILE=1048576
|
||||
|
||||
# 生产库只监听本机端口,由 Nginx 暴露最小客户端路由。
|
||||
NoNewPrivileges=true
|
||||
PrivateTmp=true
|
||||
ProtectSystem=full
|
||||
ReadWritePaths=/stdb
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Reference in New Issue
Block a user