Skip to content

Deployment Guide

Status: Authoritative deployment reference.

Cross-references: ARCHITECTURE.md (infrastructure stack), SECURITY.md (secret injection).

  • Cloudflare account with Workers enabled
  • Supabase account with a project
  • Domain registered (e.g. gondolier.dev)
  • wrangler CLI installed (npm install -g wrangler)
  • Node.js 20+
  • Go 1.24+ (optional, for local builds)
Terminal window
wrangler init gondolier --type javascript
name = "gondolier"
compatibility_date = "2026-08-03"
workers_dev = true
main = "index.mjs"
[durable_objects]
bindings = [{ name = "LEASE_DO", class_name = "LeaseDO" }]
[[migrations]]
tag = "v1"
new_sqlite_classes = ["LeaseDO"]
[[kv_namespaces]]
binding = "RATE_LIMIT_KV"
id = "<kv-namespace-id>"
[triggers]
crons = ["*/5 * * * *"]
Terminal window
wrangler kv:namespace create RATE_LIMIT_KV
# Copy the namespace ID into wrangler.toml

The LeaseDO class is defined in lease-do.mjs and exported from index.mjs. No additional migration steps needed — the [[migrations]] section in wrangler.toml handles it.

Terminal window
wrangler secret put GONDOLIER_MASTER_KEY
wrangler secret put SUPABASE_URL
wrangler secret put SUPABASE_SERVICE_ROLE_KEY
wrangler secret put ADMIN_KEY

Secrets: See SECURITY.md for the full list of secrets and their purposes. Never commit secrets to the repo.

Create a new Supabase project at gondolier.supabase.co.

RLS is enabled by default on new Supabase projects. Verify:

-- For each table, ensure RLS is enabled:
ALTER TABLE tenants ENABLE ROW LEVEL SECURITY;
ALTER TABLE forge_connections ENABLE ROW LEVEL SECURITY;
ALTER TABLE managed_repos ENABLE ROW LEVEL SECURITY;
ALTER TABLE audit_log ENABLE ROW LEVEL SECURITY;
Terminal window
# Install Supabase CLI
npm install -g supabase
# Login
supabase login
# Link to project
supabase link --project-ref <project-ref>
# Apply migrations
supabase db push

Or manually:

Terminal window
psql -h <supabase-host> -U postgres -d postgres < migrations/001_base_tables.sql
psql -h <supabase-host> -U postgres -d postgres < migrations/002_user_accounts.sql
psql -h <supabase-host> -U postgres -d postgres < migrations/003_billing.sql
Terminal window
supabase gen types typescript --project-id <ref> > src/db/types.ts

Deploy the sell site (site/) to Cloudflare Pages:

Terminal window
# Option 1: Via CLI
wrangler pages deploy site/ --project-name=gondolier-site
# Option 2: Via GitHub
# Connect repo → Cloudflare Pages → build command: none (static HTML)
# Publish directory: site/

Deploy the dashboard (templates/dashboard.html rendered by the Worker):

Terminal window
# Option 1: Via CLI
wrangler pages deploy templates/ --project-name=gondolier-dashboard
# Option 2: Via GitHub
# Connect repo → Cloudflare Pages → build command: none
# Publish directory: templates/
# Sell site (Cloudflare Pages)
gondolier.dev. CNAME <pages-site-id>.pages.dev
# Worker API
api.gondolier.dev. CNAME <worker>.gondolier.<user>.workers.dev
# (or point gondolier.dev directly if using Workers Dev)

Note: DNS proxy (orange cloud) must be OFF for Workers routes that handle TLS. Cloudflare Pages uses its own TLS certificates.

Forgejo Actions (.forgejo/workflows/ci.yaml)

Section titled “Forgejo Actions (.forgejo/workflows/ci.yaml)”

The CI workflow runs on PR and main:

name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
vet:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.24'
- run: go vet ./...
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.24'
- run: go test ./...
build:
runs-on: ubuntu-latest
needs: [vet, test]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.24'
- run: go build ./cmd/gondolier

The mq/** push trigger runs the shunt merge queue gate. This is the required status that shunt checks before allowing a queued PR to merge.

Terminal window
wrangler deploy --env preview
Terminal window
wrangler deploy
Terminal window
wrangler deploy --dry-run --outdir=dist/
Terminal window
# List versions
wrangler versions list
# Rollback to specific version
wrangler versions rollback <version>

Migrations are forward-only. To rollback:

-- Manual rollback (run on Supabase)
DROP TABLE IF EXISTS audit_log CASCADE;
DROP TABLE IF EXISTS managed_repos CASCADE;
DROP TABLE IF EXISTS forge_connections CASCADE;
DROP TABLE IF EXISTS tenants CASCADE;
-- Re-run previous migration
psql ... < migrations/000_previous.sql

Never drop tables in production without a backup. Always run migrations on a fresh database first to verify the rollback path.

If DNS changes break routing:

Terminal window
# Revert CNAME records to previous values
# Cloudflare DNS → Records → Edit → Restore previous value

Access via the Cloudflare dashboard at dash.cloudflare.com → Workers → gondolier → Analytics.

The wrangler.toml enables observability:

[observability]
enabled = true
head_sampling_rate = 1

Logs are available at:

Terminal window
wrangler tail
GET https://gondolier.dev/healthz → 200 OK
GET https://gondolier.dev/readyz → 200 OK