Infrastructure
Infrastructure
Section titled “Infrastructure”Status: Operational reference.
Cross-references: DEPLOYMENT.md (general deployment), WORKER_DEPLOYMENT.md (worker-specific details), SECURITY.md (secret management).
- Runtime: Cloudflare Workers (JavaScript / Container binding)
- Database: Supabase PostgreSQL
- CI/CD: Forgejo Actions
- Deployment target:
gondolier.dev(Workers Dev + custom domains)
Secrets management
Section titled “Secrets management”All sensitive values are stored in OpenBao under the KV v2 path
secret/data/gondolier/backend and are fetched keylessly via Forgejo Actions
OIDC (JWT-based authentication to an OpenBao forgejo-actions auth role).
Tokens are never committed, never printed to logs, and are masked with
::add-mask:: before being exported to the workflow environment.
Secret keys
Section titled “Secret keys”| Key | Purpose | Generation |
|---|---|---|
CLOUDFLARE_API_TOKEN |
Wrangler authentication (Cloudflare API access) | Admin-provided |
CREDENTIAL_MASTER_KEY |
Envelope encryption master key for tenant forge tokens | openssl rand -base64 32 |
CONTAINER_AUTH_SECRET |
Auth token for LeaseDO → ShuntContainer internal dispatch | openssl rand -hex 32 |
SUPABASE_URL |
Supabase project URL (e.g. https://xxx.supabase.co) |
Admin-provided |
SUPABASE_SERVICE_ROLE_KEY |
Supabase service role API key | Admin-provided |
STUB_JWT_SECRET |
JWT signing secret (HS256) — replace before production auth | openssl rand -hex 32 |
STUB_CLIENT_ID |
OAuth client ID (stub) — replace before production auth | openssl rand -hex 16 |
Required vs optional keys
Section titled “Required vs optional keys”The deploy workflow enforces three required keys — it will fail if any are missing from OpenBao after the ensure step:
CLOUDFLARE_API_TOKENCREDENTIAL_MASTER_KEYCONTAINER_AUTH_SECRET
The remaining keys (SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY, STUB_JWT_SECRET,
STUB_CLIENT_ID) are read from OpenBao and exported to the workflow environment
but are not enforced as hard-required at the script level. The ensure step
generates missing STUB_JWT_SECRET and STUB_CLIENT_ID automatically. If
SUPABASE_URL or SUPABASE_SERVICE_ROLE_KEY are absent they must be provided
by an admin (the ensure step refuses to generate them).
OIDC role requirement
Section titled “OIDC role requirement”The deploy job authenticates to OpenBao using a Forgejo Actions OIDC token.
The role name defaults to gondolier-ci and can be overridden via the
bao_role workflow_dispatch input. The role must be configured in OpenBao
with:
forgejo-actionsauth method enabled- A role named
gondolier-ci(or custom name) withbound_audiencesset toopenbao - read permission on
secret/data/gondolier/backend - write permission on
secret/data/gondolier/backend(for the self-heal step)
Provisisoning secrets
Section titled “Provisisoning secrets”Secrets must be provisioned in OpenBao before the first deploy:
- Connect to the OpenBao UI or CLI.
- Navigate to (or create) the path
secret/data/gondolier/backend. - Create the KV v2 secret with all required keys and their values.
- Verify the keys are visible in the OpenBao secret version history.
The deploy workflow includes an ensure step that will auto-generate any missing optional keys on the first run. Required keys that are absent after the ensure step will cause the job to fail with a clear error listing the missing keys.
Cloudflare account secrets (optional)
Section titled “Cloudflare account secrets (optional)”If you want wrangler to store secrets in the Cloudflare account (not just as workflow env vars), run once after provisioning the workflow env secrets:
wrangler secret put CREDENTIAL_MASTER_KEYwrangler secret put CONTAINER_AUTH_SECRETwrangler secret put SUPABASE_URLwrangler secret put SUPABASE_SERVICE_ROLE_KEYwrangler secret put STUB_JWT_SECRETwrangler secret put STUB_CLIENT_IDThis is optional — the CI/CD deploy path uses workflow env vars, not account-level secrets.
CI/CD pipelines
Section titled “CI/CD pipelines”CI — .forgejo/workflows/ci.yaml
Section titled “CI — .forgejo/workflows/ci.yaml”Triggers: push to main, pull_request to main.
Jobs (in execution order):
- vet —
go veton all Go packages - test —
go test -raceon unit tests - build —
go buildon all targets - workers-check —
wrangler deploy --dry-run(validates JS + Container binding) - merge-queue-gate — re-runs vet + test + build on staging ref (shunt MQ gate)
All jobs run on the laputacloudco runner.
Deploy — .forgejo/workflows/deploy.yaml
Section titled “Deploy — .forgejo/workflows/deploy.yaml”Triggers: push to main (post-merge, after shunt queues and merges),
or manual workflow_dispatch.
Jobs:
- validate-go — same vet, test, build gates as CI
- validate-workers —
wrangler deploy --dry-runwith Docker CLI - deploy — OIDC login → fetch secrets from OpenBao
secret/data/gondolier/backend→ self-heal missing keys →wrangler login+wrangler deployto production
The deploy job has an if guard: it runs only on push to main or
when a manual dispatch targets main specifically. It does not run
on pull_request events.
The deploy job includes:
enable-openid-connect: true(viapermissions: id-token: write)- A secret-fetch step that authenticates to OpenBao keylessly using the
Forgejo Actions OIDC JWT and the
gondolier-cirole. - An ensure/self-heal step that generates missing optional keys and writes them back to OpenBao if the role has write permission.
- Required-key validation:
CLOUDFLARE_API_TOKEN,CREDENTIAL_MASTER_KEY, andCONTAINER_AUTH_SECRETmust be present or the job fails.
Infrastructure as code
Section titled “Infrastructure as code”No IaC tooling yet. Provisioning is manual:
- Cloudflare Worker created via
wrangler init/wrangler deploy - KV namespace created via
wrangler kv:namespace create - Supabase project with tables created via migrations
- DNS configured in Cloudflare dashboard
Runners
Section titled “Runners”All Forgejo Actions workflows run on the laputacloudco runner,
which is a DinD-capable Linux host. Docker CLI is installed at runtime
(pinned version 27.5.1 with SHA256 verification) for the Workers
Container binding.
The runner must also provide:
python3— JSON parsing forfetch-valid-json.shand secret scriptsopenssl— key generation forCREDENTIAL_MASTER_KEY,CONTAINER_AUTH_SECRET,STUB_JWT_SECRET,STUB_CLIENT_ID
Operational runbooks
Section titled “Operational runbooks”Worker rollback
Section titled “Worker rollback”wrangler versions listwrangler versions rollback <version>Log tailing
Section titled “Log tailing”wrangler tailVerify deploy success
Section titled “Verify deploy success”After deploy, check the Workers dashboard:
https://dash.cloudflare.com → Workers → gondolier → Versions.
Or CLI:
wrangler versions list --limit=3Secret rotation
Section titled “Secret rotation”- Generate new secret value.
- Update the Forgejo Actions secret.
- Update the Cloudflare account secret (if using account secrets):
wrangler secret put NEW_NAME - Redeploy: merge a trivial commit or trigger
workflow_dispatch.