Prerequisites
The backend Docker image is already building via CI (docker.yml workflow) to ghcr.io/crewcircle/localmate-backend:latest. Every push to main that touches backend/** triggers a new image build.
Steps to deploy
Phase A — Provision infrastructure
- Populate
.env.local in CrewCircle monorepo with CC_* credentials (see packages/account-setup/.env.example)
- Auth Doppler CLI:
doppler login
- Run Pulumi provisioner:
cd packages/infra
./bin/newproject local-biz-au "Local Mate" "AU SMB automation suite" 19900
This provisions: Supabase project (Singapore), Doppler config + secrets, Stripe product+price, GitHub repo, Sentry project, Cloudflare DNS records.
- Verify
packages/infra/registry.json contains local-biz-au
Phase B — Apply database migrations
- Get Supabase connection string from Doppler:
doppler secrets get SUPABASE_URL --project local-biz-au --config prod
- Apply all 7 migrations from
supabase/migrations/ to the Supabase project via Supabase dashboard SQL editor or psql
Phase C — Deploy backend on Coolify
- Spin up a DigitalOcean droplet in Sydney region (
syd1)
- Install Coolify on the droplet:
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash
- In Coolify dashboard:
- New Application → Connect GitHub repo
crewcircle/localmate
- Set Root Directory:
backend/
- OR: Use prebuilt image
ghcr.io/crewcircle/localmate-backend:latest (faster, less RAM)
- Set domain:
api.localmate.crewcircle.co
- Add environment variable:
DOPPLER_TOKEN=<service token from doppler configs tokens create --project local-biz-au --config prod>
- Deploy — Coolify handles SSL via Lets Encrypt
Phase D — DNS for backend
Add another CNAME in Cloudflare (same zone as issue #1):
| Type |
Name |
Target |
Proxied |
| CNAME |
api.localmate |
<coolify-droplet-IP-or-domain> |
❌ (DNS-only, Coolify handles SSL) |
Or use an A record pointing to the DigitalOcean droplet IP.
Phase E — Verify
Current state
- ✅ Backend Docker image builds and pushes to GHCR automatically via CI
- ✅ Dockerfile verified (Python 3.11-slim, uv sync, uvicorn on :8000)
- ✅ docker-compose.yml exists for local development
- ⏸️ Blocked on user provisioning infrastructure (Pulumi + DO droplet + Doppler auth)
See DEPLOY.md in the repo for full details.
Prerequisites
The backend Docker image is already building via CI (
docker.ymlworkflow) toghcr.io/crewcircle/localmate-backend:latest. Every push tomainthat touchesbackend/**triggers a new image build.Steps to deploy
Phase A — Provision infrastructure
.env.localin CrewCircle monorepo with CC_* credentials (seepackages/account-setup/.env.example)doppler loginpackages/infra/registry.jsoncontainslocal-biz-auPhase B — Apply database migrations
doppler secrets get SUPABASE_URL --project local-biz-au --config prodsupabase/migrations/to the Supabase project via Supabase dashboard SQL editor orpsqlPhase C — Deploy backend on Coolify
syd1)curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bashcrewcircle/localmatebackend/ghcr.io/crewcircle/localmate-backend:latest(faster, less RAM)api.localmate.crewcircle.coDOPPLER_TOKEN=<service token from doppler configs tokens create --project local-biz-au --config prod>Phase D — DNS for backend
Add another CNAME in Cloudflare (same zone as issue #1):
api.localmate<coolify-droplet-IP-or-domain>Or use an A record pointing to the DigitalOcean droplet IP.
Phase E — Verify
GET https://api.localmate.crewcircle.co/healthreturns{"status":"ok","project":"local-biz-au"}https://api.localmate.crewcircle.co/webhooks/stripehttps://api.localmate.crewcircle.co/webhooks/inbound-reviewCurrent state
See
DEPLOY.mdin the repo for full details.