docs(launch): execute-ready initial-deployment runbook
All checks were successful
Build & Push Docker Images / lint (push) Successful in 2m55s
Build & Push Docker Images / build-and-push (push) Successful in 8m51s

Locked decisions (Postgres=own, deploy dir /root/docker-compose/pn-crm, DB/Redis localhost-only), prerequisites checklist, ordered gated phases (recon -> CRM -> data -> Documenso -> website cutover), rollback anchors.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-02 17:50:42 +02:00
parent 44b004fa8f
commit 2a4dadd5a7

View File

@@ -307,3 +307,72 @@ SMTP + alert recipients stay until `WEBSITE_INQUIRY_EMAILS_DISABLED` is set.
- residential templates plus a new contact-form alert template, hooked into
`/api/public/website-inquiries`. New website env vars documented above. CRM
tsc-clean + unit test added; website berth/UTM vue-tsc-clean. Nothing deployed.
- 2026-06-02 (later): in-app notifications for website submissions + the
structured notification-recipient resolver (emails/users/roles/everyone,
backward-compatible) + the admin recipient-picker UI all shipped on the
`feat/website-intake-email-ownership` branch (CRM repo). Contact-form client
confirmation added on BOTH the website (gated by `WEBSITE_INQUIRY_EMAILS_DISABLED`)
and the CRM (gated by `website_intake_email_enabled`). tsc-clean; full vitest
suite (1570) green. Picker live browser-verify pending a dev server. Branch is
4 commits ahead of `main`, not merged, not pushed.
---
## Initial Deployment Runbook — execute-ready (assembled 2026-06-02)
> The single ordered checklist for go-live; detailed step content is in Phase 1
> / Phase 2 above + Initiative 5 (`launch-readiness.md`). **Guardrail stands: no
> prod-server mutation without per-action approval; reads/recon are free.** Per
> Matt (2026-06-02): assemble ALL inputs + the full plan before executing
> anything, including recon.
### Locked decisions
- **CRM Postgres:** OWN — compose-default `postgres:16`, isolated `pgdata`.
- **Deploy dir:** `/root/docker-compose/pn-crm/` (matches the other compose folders).
- **DB/Redis exposure:** bind to `127.0.0.1` ONLY — no public ports (the Documenso
`5432` public-exposure + brute-force lesson; the R1 port scan confirms).
- **Initial image:** include the email-ownership work — merge
`feat/website-intake-email-ownership` -> `main` -> push -> CI builds -> pull.
It is all flag-OFF by default, so it ships dormant + safe. (Alternative on
record: deploy `main` as-is, merge before the website cutover flip.)
### Prerequisites — gather BEFORE executing
| Need | For | Status |
| -------------------------------------------------------- | ---------------------------------------- | ------------------------ |
| SSH `stefan@45.142.177.246:22022` (key) | all recon + deploy | have |
| prod root pass (`su`) | docker / nginx / certbot | VERIFY (creds file) |
| Gitea registry pull token | `docker login` -> pull crm images | NEED (generate) |
| `WEBSITE_INTAKE_SECRET` (shared) | CRM `.env` + website `CRM_INTAKE_SECRET` | generate at P1 |
| Documenso API token + webhook secret | CRM `.env` (login `matt@portnimara.com`) | NEED |
| MinIO creds (endpoint/key/secret/bucket) for the new CRM | CRM `.env` storage | confirm (creds §3) |
| Legacy MinIO read creds | EOI backfill (D2) | NEED |
| Website-server root pass | Phase 4 env wiring | you provide at that step |
| Maintenance window | Documenso restart | schedule |
### Ordered steps (each gated)
- **Phase 0 [recon]** R1 port scan (external + internal listeners) · R2 NocoDB +
Documenso drift vs the 2026-06-01 pull · R3 fresh read-only Documenso `pg_dump`
-> re-run the `1.13.1->2.11.0` clone dry-run (final "won't break" check).
- **Phase 1 [APPROVAL]** P1 prod `.env` -> P2 `/root/docker-compose/pn-crm`
(localhost-bound DB/Redis) -> P3 nginx (HTTP-first) -> P4
`certbot --nginx -d crm.portnimara.com` -> P5 `docker login` + pull + up -> P6
schema + seed port/admin -> P7 verify (health, login, berths, socket.io).
- **Phase 2 [APPROVAL]** D1 load migrated data -> D2 MinIO EOI backfill -> D3
reconcile counts.
- **Phase 3 [APPROVAL · VITAL · together]** backups (pg_dump + cold volume
snapshot + cert + MinIO inventory, off-box) -> staged `1.13.1->2.0.0->2.11.0`
-> verify (login, existing envelope renders, test send, webhook reaches CRM,
CRM stays on v1 API) -> rollback ready.
- **Phase 4 [APPROVAL]** website env wiring on the other server -> cutover flips
(`CRM_INTAKE_URL`/`SECRET` on; then `website_intake_email_enabled` ON +
`WEBSITE_INQUIRY_EMAILS_DISABLED=1`; then `CRM_BERTHS_ENABLED=1`).
### Rollback anchors
- CRM: `docker compose -f docker-compose.prod.yml down` — the pn-crm stack is
isolated (own Postgres), zero impact on the other apps on the box.
- Documenso: revert the image tag + restore the cold volume snapshot / pg_dump.
- Website: unset the `CRM_*` env vars -> instant revert to NocoDB + website email.