# 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.