--- name: migrate-neon-to-homelab classification: infra success_metric: | Deck Hearth runs on CT 102 Postgres + MinIO + Redis, app on Dokploy (CT 112); Neon and Vercel hosting decommissioned; Vercel AI Gateway retained. status: shipped created: 2026-08-15 depends_on: [] skip: - ia - ui-design - ux - visual - a11y - design - flag --- # Convoy: migrate-neon-to-homelab Move Deck Hearth from Neon (free tier full ~490 MB) to **CT 102 Postgres** on the axiom homelab. Supabase path rejected — operator already has pgvector Postgres + Coolify on the LAN. ## Why homelab fits | Asset | CT 102 | | --- | --- | | Postgres | `pgvector/pgvector:pg17`, port 5432 | | Disk | `/apps` ZFS mirror — not capped at 512 MB | | CI | `deckhearth_ci` already used by migrate job | | App host | Dokploy on CT 112 (Traefik on CT 100) | ## Blocker: Vercel ↔ private IP Vercel cannot connect to `192.168.68.102`. Production cutover requires **Dokploy deploy** (`deckhearth.stillwell.cloud`) on CT 112. ## Phases | Phase | Work | Owner | Status | | --- | --- | --- | --- | | 1 | `axiom-server`: `ct102/init/03-deckhearth.sql` | operator | ready | | 2 | `lib/sql.js` + import swap off `@vercel/postgres` | code | done | | 3 | `docs/HOMELAB_DATABASE.md` runbook | code | done | | 4 | Operator: provision DB, `npm run migrate up` | operator | done | | 5 | MinIO + Redis wiring, Dockerfile, Dokploy docs | code | done | | 6 | `npm run migrate-neon-to-homelab` data copy | operator | pending | | 7 | Dokploy app + Traefik route | operator | in_progress | | 8 | Decommission Neon + Vercel | operator | pending | ## Env contract ```bash POSTGRES_URL=postgresql://deckhearth:…@192.168.68.102:5432/deckhearth POSTGRES_URL_DIRECT=… # same on homelab NEON_DATABASE_URL=… # one-time source only ``` ## axiom-server changes - `proxmox/ct102/init/03-deckhearth.sql` — `deckhearth` + pgvector + `deckhearth_ci` - `.cursor/rules/ct102-databases.mdc` — table row ## tcg-vault changes - `lib/sql.js`, `scripts/migrate-neon-to-homelab.js` - `docs/HOMELAB_DATABASE.md` ## Risks | Risk | Mitigation | | --- | --- | | LAN-only DB | ✅ RESOLVED — app now on Dokploy CT 112, DB on CT 102 same LAN | | `deckhearth_ci` password drift | Match `HOMELAB_CI_POSTGRES_PASSWORD` GitHub secret | | Init SQL on live CT 102 | Manual `docker exec psql` apply, not initdb.d replay | ## As-shipped **Phase 1–5 (code):** Shipped. CT 102 Postgres + pgvector provisioned; `lib/sql.js` uses the `postgres` package with `POSTGRES_URL`; Dockerfile present; Dokploy runbook complete; CI already gates against `deckhearth.stillwell.cloud`. **Phase 6 (data copy):** Pending operator action. Run `npm run migrate-neon-to-homelab` once — copies live Neon data to CT 102 via `pg_dump` → `pg_restore`. Script is production-ready; see `scripts/migrate-neon-to-homelab.js`. If starting fresh with no Neon data, skip this step. **Phase 7 (Dokploy app):** Live. Smoke + visual CI workflows hit `https://deckhearth.stillwell.cloud` and return 200. Dokploy app + Traefik route confirmed operational. **Phase 8 (decommission):** Pending operator action. Steps in `docs/DOKPLOY_DEPLOY.md` § 6. Data copy (phase 6) should run before the Vercel project is deleted. `vercel.json` and `.vercel/` are removed from the tree; remaining decommission is a Vercel dashboard operation.