Deployment setup - the parts the workflow deliberately left out

Host setup checklist, real domains and ports, the database backup
script the deploy workflow only ever invokes, and a rollback plan.
Also drafted the FTPS switch procedure for whenever production moves
off the Pi, with a note that shared hosting is likely IIS-based -
that's a bigger change than swapping the transport.
This commit is contained in:
2026-07-28 19:07:26 +02:00
parent 9ab30fe2a6
commit cf80f827ae
6 changed files with 550 additions and 0 deletions
@@ -0,0 +1,57 @@
# Deployment Plan
**Date**: 2026-07-28
**Decided at**: Deployment Setup, per `deployment-setup-plan.md` (Q1 = A, Q2 = A)
## Method
Gitea Actions CI/CD, already built in Construction:
- `.gitea/workflows/continuous_integration.yaml` (U5) — six blocking gates, then a per-environment
`dotnet publish`, then invokes the deploy workflow
- `.gitea/workflows/deploy-scp.yaml` (U6) — reusable `workflow_call` workflow: backup (production
only) → upload → link persistent website → atomic switch → restart → health check → prune
This stage does not change that mechanism — it documents the operational side Construction
deliberately left out: host setup, real domains, the database backup script, and the rollback
procedure.
## Environments
| Environment | Host | Domain | Trigger |
|---|---|---|---|
| Test | Raspberry Pi (`linux-arm64`) | `test.slpsoftware.nl` | Automatic on push to `master`, or any `workflow_dispatch` |
| Production | Same Pi, separate directory | `slpsoftware.nl` | Only `workflow_dispatch` with `deploy_production = true` |
Same physical host for both (per `infrastructure-design.md` § 1) — separated by directory,
`systemd --user` unit, and local port, never by anything the workflow manages directly.
## Rationale for What's Documented Here vs. Already Decided
| Already decided (Construction) | Documented here (Operations) |
|---|---|
| Atomic switch mechanism, retention count, transport | Real domains, real ports |
| `deploy-scp.yaml`'s step sequence | The one-time host setup that sequence assumes already exists |
| That a DB backup step runs before production deploys | The actual backup script's content |
| That `transport` is reserved for FTPS (D-02, NFR-09) | What actually changes operationally when that day comes |
## Automation Level
Fully automated for test (push to `master` → live on `test.slpsoftware.nl` with no human step).
Production requires an explicit, manual `workflow_dispatch` run with the flag checked — this manual
trigger **is** the approval gate (D-09); no separate approval workflow step exists or is needed.
## Rollback Strategy
Summarized here; full procedure in `rollback-plan.md`. Two releases are always retained
(`infrastructure-design.md` § 3), so rolling back is a re-point-and-restart, never a rebuild, for the
most recent deploy. Migrations are required to be forward-compatible and non-destructive (D-26), so
redeploying an older commit remains valid further back than just one release.
## Secrets and Configuration
Per D-16, runtime configuration lives in **host** environment variables that the workflow never
writes — see `deployment-instructions.md` § "Runtime Configuration" for the full list and where it
lives on the host (a single `shared/env` file per environment, outside the swapped release
directory, `chmod 600`). Gitea Actions secrets are limited to what the workflow itself needs to
reach the host: SSH credentials (`PI_MAIN_*`). No application secret is ever a Gitea secret or
variable.