Deploy¶
Phase 1 + Phase 2-2a deployment on HK-133 (lab.flytoex.net,
45.145.229.197, ssh port 43475).
Topology¶
Internet ──:443/:80──> Caddy ──> /admin/proxy/* ── basic_auth ──> relay:7080 (web, bridge-internal)
├ /admin/* ─────────────────> common:8081 (admin HTTP surface)
├ /api/v1/* ─────────────────> common:8080 (business REST/SSE -- ADR-0002)
└ everything else ──────────────── > logistics:8080 (REST)
└─> common:9090 (gRPC, compose bridge)
Internet ──:7000/:7001/:13000-13099──> relay (bridge) ── tunnel ── flyto-proxy (alibaba VPC, 2-2b, not yet deployed)
└─> internal DB / HTTP / SSH
hub.flytoex.netresolves to HK-133 (grey cloud, DNS-only)- Caddy auto-provisions Let's Encrypt certs on first request
- All services on the compose-default bridge network
commongRPC:9090and admin HTTP:8081both not exposed to the host -- only reachable through Caddy or fromlogisticsover the compose bridgerelayweb:7080is not in composeports:, so Caddy (reverse_proxy relay:7080) is the only external ingress. Tunnel ports:7000/:7001plus the rule-listen range:13000-13099ARE host-exposed, because alibaba-side proxies connect to:7000and external callers hit the per-rule listen ports that relay binds at runtime.ForwardRule.listen_portvalues in proxy configs must fall in13000-13099; outside that range needs adocker-compose.ymlupdate and redeploy.
First-time install on HK-133¶
ssh -p 43475 root@45.145.229.197
git clone https://git.flytoex.net/yuanwei/Flyto-Agent.git /opt/flyto
cd /opt/flyto/deploy
# After v0.1.0-alpha tag is pushed and Gitea Actions finishes the build:
docker compose pull
docker compose up -d
docker compose logs -f caddy # watch LE cert issuance
Verify round-trip:
curl https://hub.flytoex.net/health
# => {"status":"STATUS_UNSPECIFIED","version":"","tenantId":""}
# STATUS_UNSPECIFIED is expected in dev mode (no auth, no tenant in ctx).
# Once OIDC is wired, the same call with a valid bearer returns SERVING.
Admin HTTP surface on common (observability only, not business traffic):
curl https://hub.flytoex.net/admin/health # => {"status":"ok"}
curl https://hub.flytoex.net/admin/version # => {"version":"v0.1.0-alpha.X"}
curl https://hub.flytoex.net/admin/tenant # => {"tenant_id":"","subject":""} in dev
# /admin/tenant requires a bearer token once OIDC is wired; in dev it echoes
# empty strings. /admin/health and /admin/version are always open.
Business REST/SSE on common (ADR-0002 -- engine consumption surface):
# Health on the business listener (separate from /admin/health, but same shape)
curl https://hub.flytoex.net/api/v1/health # => {"status":"ok","timestamp":...}
# Streaming agent run (SSE; requires ANTHROPIC_API_KEY in deploy/.env)
curl -N https://hub.flytoex.net/api/v1/agent/run \
-H 'Authorization: Bearer <oidc-jwt>' \
-H 'Content-Type: application/json' \
-d '{"prompt":"hello"}'
# => streaming text/event-stream chunks (text_delta / tool_use / done)
# Caddy passes SSE through with flush_interval -1; expect first chunk in ms.
Relay web console (flyto-proxy):
# Browser: open https://hub.flytoex.net/admin/proxy/ and enter basic_auth
# credentials (see the "Gitea Actions secrets" section below for where the
# hash is stored; plaintext user/password are in flysafe).
# curl with basic_auth:
curl -u yuanwei:<password> https://hub.flytoex.net/admin/proxy/api/proxies
# => [] (empty until an alibaba-side proxy connects -- that is Phase 2-2b)
Gitea Actions secrets¶
Go to https://git.flytoex.net/yuanwei/Flyto-Agent/-/settings/actions/secrets
and add:
| Secret | Value |
|---|---|
REGISTRY_USER |
yuanwei |
REGISTRY_TOKEN |
Personal Access Token with write:package scope |
ADMIN_BASIC_AUTH_HASH |
caddy hash-password output for the /admin/proxy/* basic_auth account. Plaintext credentials live in flysafe. |
FLYTO_PROXY_TOKEN |
Shared token between relay and the alibaba-side flyto-proxy (64-hex, openssl rand -hex 32). Same value must be baked into the alibaba proxy config. |
Generate the PAT at https://git.flytoex.net/-/user/settings/applications.
Note: GITEA_* / GITHUB_* prefixes are reserved by Actions; use
REGISTRY_* / ADMIN_* / FLYTO_*.
Release flow¶
Tag push triggers .gitea/workflows/release.yml:
- Build
git.flytoex.net/yuanwei/flyto-agent-common:<version> - Build
git.flytoex.net/yuanwei/flyto-agent-logistics:<version> - Push both plus
:latestto Gitea registry
Tag push now triggers auto-deploy via the deploy workflow job (SSH to
HK-133, docker compose pull + up -d). Manual roll (skipping the deploy
job) is only needed for troubleshooting:
Deploy secrets in the Gitea repo: DEPLOY_HOST, DEPLOY_PORT,
DEPLOY_USER, DEPLOY_SSH_KEY (ed25519 key pair; pub already in
/root/.ssh/authorized_keys on HK-133, keyed by
flyto-deploy@gitea-actions).
Production mode (OIDC)¶
Once an OIDC issuer is available, override the common service command:
services:
common:
command:
- "--grpc-addr=:9090"
- "--http-addr=:8081"
- "--rest-addr=:8080"
- "--oidc-issuer=https://auth.flytoex.net/realms/flyto"
- "--oidc-audience=flyto-platform"
- "--oidc-tenant-claim=tenant_id"
Rolling back to dev mode = remove the last three --oidc-* flags. Leaving
--http-addr empty is also legal and disables the admin surface entirely
(e.g. for single-purpose gRPC-only builds). Leaving --rest-addr empty
disables business REST/SSE without affecting gRPC + admin paths -- the
ANTHROPIC_API_KEY ${...:?...} requirement still triggers, so set the env
var to any non-empty placeholder when deploying without business REST.