feat(deploy): add Caddy single entrypoint - #24
Conversation
两个修复,解决 WorkBuddy 等 AI 工具通过 TokenHub 代理后无响应返回的问题 (astaxie#19): 1. CORS 预检响应动态回显 Access-Control-Request-Headers 中声明的全部请求头, 而非硬编码仅允许 authorization 和 content-type。WorkBuddy 等工具发送 api-key 等自定义头时,浏览器 CORS 检查不再拦截。 2. 流式 SSE 响应在数据发送前显式调用 WriteHeader(200),确保 HTTP 状态行 先于数据到达,提升客户端解析兼容性。 Closes astaxie#19
解决远程浏览器请求自身 localhost 导致管理后台 API 访问失败的问题。 技术方案: - 通过 Caddy 同源代理管理 API 和 OpenAI 兼容 API - 前端使用相对 API 路径,不再固化服务器 IP - 仅公开网关端口,前后端保持在 Docker 内部网络 影响范围:Compose 部署、前端 API 基地址和部署文档 BREAKING CHANGE: 不再公开后端和前端原有宿主机端口 迁移方法:使用 TOKENHUB_GATEWAY_PORT 访问统一网关入口
将网关端口与公共访问地址放在一起说明, 避免内网部署时遗漏端口同步配置。 为前后端构建服务指定镜像名称, 便于复用已构建镜像执行部署。 影响范围:Docker Compose 部署配置和环境变量示例
There was a problem hiding this comment.
Pull request overview
Adds Caddy as the single Compose entrypoint and switches the admin console to same-origin API requests.
Changes:
- Proxies
/api/*and/v1/*through Caddy. - Removes direct service port exposure and updates deployment documentation.
- Modifies backend streaming and CORS behavior.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
frontend/features/admin/core/types.tsx |
Defaults API requests to same-origin paths. |
frontend/Dockerfile |
Removes the runtime backend URL default. |
deploy/Caddyfile |
Defines frontend and backend proxy routing. |
deploy/docker-compose.yml |
Adds the SQLite deployment gateway. |
deploy/docker-compose.postgres.yml |
Adds the PostgreSQL deployment gateway. |
deploy/.env.example |
Documents gateway environment settings. |
docs/deployment.md |
Updates English deployment guidance. |
docs/zh-CN/deployment.md |
Updates Chinese deployment guidance. |
docs/ja/deployment.md |
Updates Japanese deployment guidance. |
backend/internal/server/http.go |
Changes streaming headers and CORS preflight handling. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| export const defaultBaseURL = | ||
| process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080"; | ||
| export const defaultBaseURL = process.env.NEXT_PUBLIC_API_BASE_URL ?? ""; |
|
|
||
| export const defaultBaseURL = | ||
| process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080"; | ||
| export const defaultBaseURL = process.env.NEXT_PUBLIC_API_BASE_URL ?? ""; |
| @@ -0,0 +1,5 @@ | |||
| :80 { | |||
| @backend path /api/* /v1/* | |||
| reverse_proxy @backend tokenhub-backend:8080 | |||
| allowHeaders := "authorization,content-type" | ||
| if reqHeaders := r.Header.Get("access-control-request-headers"); reqHeaders != "" { | ||
| seen := map[string]bool{"authorization": true, "content-type": true} | ||
| for _, h := range strings.Split(reqHeaders, ",") { | ||
| h = strings.ToLower(strings.TrimSpace(h)) | ||
| if h != "" && !seen[h] { | ||
| allowHeaders += "," + h | ||
| seen[h] = true | ||
| } | ||
| } | ||
| } | ||
| w.Header().Set("access-control-allow-headers", allowHeaders) |
|
check the copilot reviews |
astaxie
left a comment
There was a problem hiding this comment.
Maintainer review status: this PR is not merge-ready. GitHub reports merge conflicts and no current checks, and the four unresolved current-head Copilot findings remain blocking: relative same-origin Base URLs break the OAuth URL helpers, persisted legacy sessions are not migrated, the Caddy topology does not configure trusted proxy CIDRs, and the unrelated backend CORS/streaming changes are outside the stated and tested scope. Please rebase on main, resolve those findings, update the PR template and verification section, and rerun the full applicable checks.
Summary
Enable remote intranet access without embedding a server-specific backend URL
in the frontend image. The browser now uses same-origin API paths through a
single Caddy gateway, preventing remote clients from calling their own
localhost.Related Issue
N/A
Changes
/api/*and/v1/*to the internal TokenHub backend.TOKENHUB_GATEWAY_PORT; remove host port mappings from thefrontend, backend, and PostgreSQL services.
TOKENHUB_GATEWAY_PORTandTOKENHUB_PUBLIC_BASE_URLin the environment example.same-origin through Caddy.
production image.
Caddy single-entrypoint topology and intranet deployment example.
Type of Change
Verification
gofmton changed Go files,go test ./..., andgo vet ./...npm run typecheckandnpm run buildVerification details:
docker compose --env-file deploy/.env.example -f deploy/docker-compose.yml config --quietcompleted successfully.
docker compose --env-file deploy/.env.example -f deploy/docker-compose.postgres.yml config --quietcompleted successfully.
tokenhub-gateway; frontend and backend services have no host port mapping../deploy/install_test.shcompleted successfully../node_modules/.bin/tsc --noEmitcompleted successfully.npm run buildcompleted successfully.npm run typecheckcould not complete because the repository is missingfrontend/scripts/check-source-lines.mjs; direct TypeScript checking passed.go test ./... && go vet ./...could not download the required Go 1.26toolchain due to a network timeout.
required test environment was available.
not have permission to access the Docker socket.
Compatibility, Security, and Operations
/v1API impact:/v1/*remains available with unchangedpaths through the Caddy gateway. Direct backend host-port access is removed.
The backend is no longer directly exposed on a host port in Compose
deployments.
TOKENHUB_BACKEND_PORTandTOKENHUB_FRONTEND_PORTwithTOKENHUB_GATEWAY_PORT. SetTOKENHUB_PUBLIC_BASE_URLto the externallyreachable gateway URL using the same port. Keep
NEXT_PUBLIC_API_BASE_URLempty.host firewall before rollout. Existing clients using direct backend host-port
access must migrate to the gateway
/v1URL. Roll back by deploying theprevious Compose configuration and restoring the former port mappings.
Checklist
.envfiles, databases, backups, or runtime logs are included.start.sh, and deployment documentation where applicable.data/model-catalog.yamlremains tracked and catalog changes were reviewed where applicable.git diff --checkpasses.