Skip to content

Deploy backend to Coolify (DigitalOcean Sydney) at api.localmate.crewcircle.co #2

Description

@rprabhat

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

  1. Populate .env.local in CrewCircle monorepo with CC_* credentials (see packages/account-setup/.env.example)
  2. Auth Doppler CLI: doppler login
  3. 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.
  4. Verify packages/infra/registry.json contains local-biz-au

Phase B — Apply database migrations

  1. Get Supabase connection string from Doppler: doppler secrets get SUPABASE_URL --project local-biz-au --config prod
  2. Apply all 7 migrations from supabase/migrations/ to the Supabase project via Supabase dashboard SQL editor or psql

Phase C — Deploy backend on Coolify

  1. Spin up a DigitalOcean droplet in Sydney region (syd1)
  2. Install Coolify on the droplet: curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash
  3. 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>
  4. 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

  • GET https://api.localmate.crewcircle.co/health returns {"status":"ok","project":"local-biz-au"}
  • APScheduler jobs visible in logs
  • Stripe webhook endpoint configured at https://api.localmate.crewcircle.co/webhooks/stripe
  • GBP webhook endpoint configured at https://api.localmate.crewcircle.co/webhooks/inbound-review

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions