Skip to content

feat(deploy): add Caddy single entrypoint - #24

Open
kaikanertan wants to merge 4 commits into
astaxie:mainfrom
kaikanertan:feat/remote-access
Open

feat(deploy): add Caddy single entrypoint#24
kaikanertan wants to merge 4 commits into
astaxie:mainfrom
kaikanertan:feat/remote-access

Conversation

@kaikanertan

Copy link
Copy Markdown

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

  • Deployment:
    • Add a Caddy gateway that serves the admin console and proxies /api/* and
      /v1/* to the internal TokenHub backend.
    • Expose only TOKENHUB_GATEWAY_PORT; remove host port mappings from the
      frontend, backend, and PostgreSQL services.
    • Add stable image names for frontend and backend build services.
    • Clarify the relationship between TOKENHUB_GATEWAY_PORT and
      TOKENHUB_PUBLIC_BASE_URL in the environment example.
  • Frontend:
    • Use an empty relative API base URL by default so requests remain
      same-origin through Caddy.
    • Remove the runtime frontend API base URL environment setting from the
      production image.
  • Documentation:
    • Update English, Simplified Chinese, and Japanese deployment guides for the
      Caddy single-entrypoint topology and intranet deployment example.

Type of Change

  • Bug fix
  • New feature
  • Refactor or maintenance
  • Documentation
  • Deployment or configuration

Verification

  • Backend: gofmt on changed Go files, go test ./..., and go vet ./...
  • Frontend: npm run typecheck and npm run build
  • SDK smoke tests against a compatible backend
  • Docker Compose configuration rendered successfully
  • Other focused or manual verification described below

Verification details:

  • docker compose --env-file deploy/.env.example -f deploy/docker-compose.yml config --quiet
    completed successfully.
  • docker compose --env-file deploy/.env.example -f deploy/docker-compose.postgres.yml config --quiet
    completed successfully.
  • Verified rendered Compose configurations publish ports only for
    tokenhub-gateway; frontend and backend services have no host port mapping.
  • ./deploy/install_test.sh completed successfully.
  • ./node_modules/.bin/tsc --noEmit completed successfully.
  • npm run build completed successfully.
  • npm run typecheck could not complete because the repository is missing
    frontend/scripts/check-source-lines.mjs; direct TypeScript checking passed.
  • Backend checks were not run because no Go files changed. An attempted
    go test ./... && go vet ./... could not download the required Go 1.26
    toolchain due to a network timeout.
  • SDK smoke tests were skipped because no compatible running backend with the
    required test environment was available.
  • Full Caddy runtime smoke testing was not run because this environment does
    not have permission to access the Docker socket.

Compatibility, Security, and Operations

  • OpenAI-compatible /v1 API impact: /v1/* remains available with unchanged
    paths through the Caddy gateway. Direct backend host-port access is removed.
  • Security or credential-handling impact: no credential handling changes.
    The backend is no longer directly exposed on a host port in Compose
    deployments.
  • Database, environment, or deployment impact: replace
    TOKENHUB_BACKEND_PORT and TOKENHUB_FRONTEND_PORT with
    TOKENHUB_GATEWAY_PORT. Set TOKENHUB_PUBLIC_BASE_URL to the externally
    reachable gateway URL using the same port. Keep
    NEXT_PUBLIC_API_BASE_URL empty.
  • Rollout and rollback considerations: allow the gateway TCP port through the
    host firewall before rollout. Existing clients using direct backend host-port
    access must migrate to the gateway /v1 URL. Roll back by deploying the
    previous Compose configuration and restoring the former port mappings.

Checklist

  • Tests were added or updated for behavior changes, or the reason they are unnecessary is documented.
  • No credentials, local .env files, databases, backups, or runtime logs are included.
  • Environment variable changes are synchronized across examples, Compose, start.sh, and deployment documentation where applicable.
  • Shared user-facing behavior is documented consistently in English, Simplified Chinese, and Japanese where applicable.
  • data/model-catalog.yaml remains tracked and catalog changes were reviewed where applicable.
  • git diff --check passes.

AnxForever and others added 4 commits July 23, 2026 10:16
两个修复,解决 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 部署配置和环境变量示例

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 ?? "";
Comment thread deploy/Caddyfile
@@ -0,0 +1,5 @@
:80 {
@backend path /api/* /v1/*
reverse_proxy @backend tokenhub-backend:8080
Comment on lines +6490 to +6501
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)
@astaxie

astaxie commented Jul 24, 2026

Copy link
Copy Markdown
Owner

check the copilot reviews

@astaxie astaxie left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants