docs(launch): execute-ready initial-deployment runbook
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:
@@ -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
|
- residential templates plus a new contact-form alert template, hooked into
|
||||||
`/api/public/website-inquiries`. New website env vars documented above. CRM
|
`/api/public/website-inquiries`. New website env vars documented above. CRM
|
||||||
tsc-clean + unit test added; website berth/UTM vue-tsc-clean. Nothing deployed.
|
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.
|
||||||
|
|||||||
Reference in New Issue
Block a user