Deployment¶
Hosting topology¶
| Component | Platform | Detail |
|---|---|---|
| Reply daemon + outreach cron jobs | DigitalOcean droplet (2 vCPU/4GB, nyc3 region) via Coolify | Built from deploy/Dockerfile |
| Warehouse | DigitalOcean Managed Postgres | See Warehouse Schema |
| client-api | Vercel | Public bulk-sync feed, no git auto-deploy — redeploy requires vercel deploy --prod --cwd client-api |
| internal-api | Vercel | Internal-only, successor to a retired extension-api/ project |
| Landing page | Vercel | landing/ |
Deprecated
The Chrome extension's backend (extension-api/) was retired. Its Vercel project is
not automatically torn down and needs manual decommissioning if not already done.
Needs verification
The droplet's specific size (2 vCPU/4GB) and region (nyc3) should be confirmed against the live DigitalOcean dashboard before being relied on for capacity planning — these can change without a corresponding doc update.
Access¶
- SSH to the droplet (key-based; the DigitalOcean cloud firewall must allow the connecting IP).
- Coolify UI runs on the droplet (same firewall restriction); credentials live in the team password manager.
- Coolify's own API is reachable from the VPS only (loopback), used by a wrapper script for deploy/log operations.
Deploy procedure¶
Note
There is no auto-deploy webhook — every deploy is manually triggered.
- Merge to
main. - Trigger a deploy via the Coolify UI (app → Deploy) or the wrapper script over SSH.
- Coolify pulls
main, builds the Docker image (~4–5 minutes, most of it the Playwright/Chromium layer), and swaps the running container. - Verify the boot log shows the expected startup sequence (senders config loaded, cron scheduler started, reply daemon started).
Warning
A failed build can leave the old container running with an identical-looking healthy log. Always confirm via the Coolify UI's Deployments tab that the container's build timestamp actually changed — don't rely on the logs looking fine.
Shadow / safe-staging mode¶
If the sender-pool secret isn't configured, the container boots in cron-only mode with no reply daemon — a safe default for staging.
To safely test a risky change:
- Run the already-built image as a throwaway container with send-enabling environment variables scrubbed, or
- Duplicate the Coolify app with a scrubbed-env staging copy.
Rollback¶
- Normal (bad code, infra fine): revert the commit on
mainand redeploy, or use Coolify's "redeploy previous successful deployment." The data volume and environment are untouched by a rollback. - To stop the stack entirely: stop the running container via SSH/docker.
Danger
Never run the stopped stack alongside any secondary/fallback deployment target at the same time — that risks double-sending outreach messages.
The Windows scrape box (separate deploy surface)¶
A separate Windows machine runs Task Scheduler jobs for the paid/manual pipeline stages
(weekly enrichment, unit refresh) — see Scheduled Jobs for the task
list. It's registered via a PowerShell registration script and reads its own local .env
file (distinct from the Coolify environment — see
Environment Variables & Secrets).
Logs & data¶
- Container logs via
docker logs. - Per-job logs persist across deploys under a path on the Docker data volume.
- The
communicationstable in Postgres (see Warehouse Schema) is the ledger of record for all outreach; the data volume additionally holds working files (page-fetch cache, dead-domain list, form-probe records) that survive redeploys.