feat: expose storyforge through public cloud gateway

This commit is contained in:
kris
2026-03-23 17:52:09 +08:00
parent aeccea585e
commit 841985c0d2
7 changed files with 238 additions and 1 deletions

View File

@@ -0,0 +1,37 @@
# StoryForge `test.hyzq.net/storyforge` 公网入口
当前公网接入不是把执行链整体迁到云服务器,而是:
1. 云服务器 `nginx` 提供 `https://test.hyzq.net/storyforge/`
2. 本机 `collector-service` 继续承接业务与局域网执行引擎
3. 本机 `Web V4` 静态服务继续承接前端
4. 本机通过 SSH 反向隧道把这两个入口桥接到云服务器
## 端口映射
- 云服务器 `127.0.0.1:18181` -> 本机 `127.0.0.1:8081`
- 云服务器 `127.0.0.1:18191` -> 本机 `127.0.0.1:3918`
## 本机常驻服务
- `com.storyforge.collector`
- `com.storyforge.web-v4`
- `com.storyforge.cloud-bridge`
## 云服务器 `nginx` 路由
- `/storyforge/` -> `127.0.0.1:18191`
- `/storyforge/v2/*` -> `127.0.0.1:18181`
- `/storyforge/openapi.json` -> `127.0.0.1:18181/openapi.json`
- `/storyforge/healthz` -> `127.0.0.1:18181/healthz`
## 当前优点
- 不需要把 `cutvideo / huobao / NAS live-recorder / 本机模型` 全部搬上云
- 公网入口统一
- 本机现网能力不需要改造即可对外开放
## 当前限制
- 本机桥接断开时,公网入口不可用
- 这是公网 staging / 私有运营入口,更接近“公网可访问的现网桥接”,不是最终完全云原生部署

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.storyforge.cloud-bridge</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/ssh</string>
<string>-N</string>
<string>-i</string>
<string>/Users/kris/.ssh/id_ed25519_kylin188</string>
<string>-o</string>
<string>BatchMode=yes</string>
<string>-o</string>
<string>ExitOnForwardFailure=yes</string>
<string>-o</string>
<string>ServerAliveInterval=30</string>
<string>-o</string>
<string>ServerAliveCountMax=3</string>
<string>-o</string>
<string>StrictHostKeyChecking=no</string>
<string>-o</string>
<string>UserKnownHostsFile=/Users/kris/.ssh/known_hosts</string>
<string>-R</string>
<string>127.0.0.1:18181:127.0.0.1:8081</string>
<string>-R</string>
<string>127.0.0.1:18191:127.0.0.1:3918</string>
<string>ubuntu@111.231.132.51</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/Users/kris/code/StoryForge/data/collector/cloud-bridge.log</string>
<key>StandardErrorPath</key>
<string>/Users/kris/code/StoryForge/data/collector/cloud-bridge.log</string>
</dict>
</plist>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.storyforge.web-v4</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/python3</string>
<string>-m</string>
<string>http.server</string>
<string>3918</string>
<string>--bind</string>
<string>127.0.0.1</string>
<string>--directory</string>
<string>/Users/kris/code/StoryForge/web/storyforge-web-v4</string>
</array>
<key>WorkingDirectory</key>
<string>/Users/kris/code/StoryForge/web/storyforge-web-v4</string>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/Users/kris/code/StoryForge/data/collector/web-v4.log</string>
<key>StandardErrorPath</key>
<string>/Users/kris/code/StoryForge/data/collector/web-v4.log</string>
</dict>
</plist>

View File

@@ -0,0 +1,101 @@
location = /storyforge {
auth_basic off;
return 301 /storyforge/;
}
location = /storyforge/healthz {
auth_basic off;
proxy_pass http://127.0.0.1:18181/healthz;
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;
}
location = /storyforge/openapi.json {
auth_basic off;
proxy_pass http://127.0.0.1:18181/openapi.json;
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;
}
location = /storyforge/api/v1/app/update/latest {
auth_basic off;
proxy_pass http://127.0.0.1:18181/api/v1/app/update/latest;
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;
}
location ^~ /storyforge/downloads/ {
auth_basic off;
proxy_pass http://127.0.0.1:18181/downloads/;
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_read_timeout 300s;
proxy_send_timeout 300s;
}
location ^~ /storyforge/v2/ {
auth_basic off;
proxy_pass http://127.0.0.1:18181/v2/;
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_read_timeout 300s;
proxy_send_timeout 300s;
proxy_buffering off;
}
location ^~ /storyforge/docs {
auth_basic off;
rewrite ^/storyforge(/docs.*)$ $1 break;
proxy_pass http://127.0.0.1:18181;
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_read_timeout 300s;
proxy_send_timeout 300s;
proxy_buffering off;
}
location ^~ /storyforge/redoc {
auth_basic off;
rewrite ^/storyforge(/redoc.*)$ $1 break;
proxy_pass http://127.0.0.1:18181;
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_read_timeout 300s;
proxy_send_timeout 300s;
proxy_buffering off;
}
location ^~ /storyforge/ {
auth_basic off;
rewrite ^/storyforge/?(.*)$ /$1 break;
proxy_pass http://127.0.0.1:18191;
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_read_timeout 300s;
proxy_send_timeout 300s;
proxy_buffering off;
}