Infrastructure design for U6: single Pi split by directory not port, systemd --user services instead of sudo, a releases/current/shared layout that keeps the customer website outside every atomic switch, and a health check through the existing reverse proxy before pruning anything. Flags that user-level systemd needs enable-linger or the service dies the moment the deploy SSH session closes.
9.3 KiB
Infrastructure Design Plan — U6 Deploy Workflow
Prerequisite note (deliberate deviation)
Functional Design and NFR Design are skipped for U6 per the execution plan (unit-of-work.md,
aidlc-state.md) — U6 is a Pipeline-type unit (YAML, no C# logic), and its behavioural contract is
already fully specified by FR-02, FR-03, FR-04, FR-06, FR-08, FR-20, ASM-01, ASM-03, ASM-04, D-02,
D-05, D-09, D-26, D-27 and the U5↔U6 shared-interface constraint in
unit-of-work-dependency.md ("U5 with U6 — one interface, two files"). Infrastructure Design is the
right entry point: it maps that contract onto an actual host layout.
Steps
- Step 1: Analyze design artifacts (requirements.md §§ Decisions/FR/ASM, unit-of-work.md U6,
unit-of-work-dependency.md, reference project
.gitea/workflows/atK:\Development\SlpSoftware\Projects\SlpSoftware) - Step 2: Create this plan
- Step 3: Generate context-appropriate questions (below)
- Step 4: Store plan (this file)
- Step 5: Notify user in chat
- Step 6: Collect and analyze answers (12/12 answered, no contradictions — Q1/Q10 initially looked like a conflict, same-port two-instance clash, resolved: port assignment is a host/nginx-level fact outside the workflow's concern, so "directory-only" split is consistent)
- Step 7: Generate infrastructure design artifacts (
infrastructure-design.md,deployment-architecture.md) - Step 8: Present completion message
- Step 9: Wait for explicit approval
- Step 10: Record approval and update progress
What the reference project (SlpSoftware) already establishes — not re-asked
- Reusable
workflow_calldeploy workflow, invoked withsecrets: inherit sshpass+scpin a plain shell step (container SCP actions fail on the Podman runner with a 409 attach error) — D-05- A
configjob that turnsenv:values into job outputs, because theenvcontext is unavailable inside a reusable workflow'swith:block - Gitea Actions variables for paths/environment names, secrets for host/credentials
(
PI_MAIN_HOST,PI_MAIN_PORT,PI_MAIN_USERNAME,PI_MAIN_PASSWORD— reusable per ASM-07)
None of that needs to be re-decided. What the reference project does not cover — because it only
ever uploads a static dist/ folder to a fixed path — is everything below: this unit publishes a
running .NET process, must switch releases atomically without a moment of downtime for the
customer's website, must back up a database first, and must be able to restart the process and prove
it came back healthy.
Category: Deployment Environment
Question 1
Is production the same Raspberry Pi as test (different port/directory), or a second, separate Pi?
A) Same Pi, different port and directory per environment B) Separate Pi per environment C) Not decided yet — design for either (parameterize host via Gitea variables/secrets, don't assume)
Answer: A, but only a different directory
Question 2
What OS architecture is the Pi running, for the dotnet publish runtime identifier?
A) linux-arm64 (Raspberry Pi 4/5, 64-bit OS)
B) linux-arm (32-bit OS)
C) linux-x64 (not a Pi / emulated)
D) Other (please describe after Answer: tag below)
Answer: A, but I might need a windows package later as well for other client API's. For now it is on the Pi
Category: Compute Infrastructure
Question 3
How is the published process managed/restarted on the Pi (ASM-03 assumes systemd)?
A) systemd service, one unit per environment (e.g. slpmodularcms-test.service,
slpmodularcms-production.service), restarted via sudo systemctl restart <unit> over SSH
B) systemd service, but restart is a manual/documented step, not automated in the workflow
C) Some other process manager (pm2, supervisor, a custom script) — describe below
D) Other (please describe after Answer: tag below)
Answer: A, but if there are better or more convenient ways to manage .net processes let me know
Question 4
Passwordless sudo systemctl restart for the deploy user — is that already configured, or does it
need to be part of the one-time host setup documented in Operations?
A) Already configured
B) Needs to be added — document it as a one-time host-setup step in Operations
C) Avoid sudo entirely — run the app as the deploy user's own systemd user service
(systemctl --user restart), no elevation needed
D) Other (please describe after Answer: tag below)
Question 5
Should the workflow publish (dotnet publish -r <RID> --self-contained ...) framework-dependent
or self-contained?
A) Self-contained (Pi doesn't need a separately-installed .NET runtime; larger artifact) B) Framework-dependent (assumes .NET 10 runtime already installed on the Pi, per ASM-03; smaller artifact) C) Other (please describe after Answer: tag below)
Category: Storage Infrastructure
Question 6
Release directory layout on the host, given deploy_path as the single input (FR-02) — how should
releases/, the atomic current pointer, and the persistent wwwroot/web/ be arranged underneath
it?
A) {deploy_path}/releases/{timestamp-or-sha}/ per release, {deploy_path}/current symlink switched
atomically to point at one release, {deploy_path}/shared/wwwroot-web/ persistent and
symlinked into each new release as wwwroot/web
B) Same as A, but the persistent website content lives at a path outside deploy_path entirely
(e.g. a fixed host path unrelated to the deploy target), to make it structurally impossible for
any future workflow change to prune it by mistake
C) Other (please describe after Answer: tag below)
Question 7
How many previous releases should be retained after pruning (FR-06: "at least the previous one")?
A) 2 (current + 1 previous) B) 3 (current + 2 previous) C) 5 D) Other (please describe after Answer: tag below)
Question 8
Database backup before production deploy (FR-20) — is it automatable from the Gitea runner over SSH (ASM-04 assumes the database is reachable from the application, not necessarily from the runner)?
A) Automatable: the deploy workflow runs a backup command over SSH on the Pi itself (e.g.
sqlcmd/sqlpackage or a SQL Server backup script already on the host), before the atomic switch
B) Not automatable from the runner: emit a clear, verifiable manual step in the deployment
instructions instead (FR-20's documented fallback), and the workflow does not attempt it
C) Not sure yet — design the workflow with an explicit backup step that can be a placeholder script
the user fills in during Operations
D) Other (please describe after Answer: tag below)
Category: Networking Infrastructure
Question 9
Post-switch health verification (FR-06 implies confirming the restart succeeded) — how should the
workflow check /health?
A) curl from the Gitea runner against the environment's public HTTPS URL
B) curl executed on the Pi itself over the same SSH connection, against localhost:<port>
(works even if the public URL is only reachable through a reverse proxy not yet configured, and
doesn't depend on external DNS/TLS)
C) Both — localhost check on the Pi first, then a public-URL check as a secondary confirmation
D) Other (please describe after Answer: tag below)
Question 10
Is there an existing reverse proxy (nginx, as in the reference project) in front of this application, or does Kestrel serve requests directly?
A) Kestrel serves directly on a fixed port per environment (e.g. 5000 test, 5001 production) —
no reverse proxy for this app
B) Existing nginx reverse proxy in front, forwarding to Kestrel on a local port
C) Not decided yet / out of scope for this workflow — document the assumption and let Operations
confirm the real topology
D) Other (please describe after Answer: tag below)
Category: Monitoring Infrastructure
Question 11
If the post-switch health check (Question 9) fails, what should the workflow do?
A) Fail the job loudly (red pipeline) but leave the atomic switch as-is — no automatic rollback;
manual rollback via Operations' documented procedure
B) Automatically re-point current back to the previous release and restart, then fail the job
C) Other (please describe after Answer: tag below)
Category: Shared Infrastructure
Question 12
Gitea Actions variable/secret naming for the deploy target — reuse the reference project's
PI_MAIN_* secrets (ASM-07), or introduce project-specific names since this repo has its own
test and production paths on the same or a different host?
A) Reuse PI_MAIN_HOST / PI_MAIN_PORT / PI_MAIN_USERNAME / PI_MAIN_PASSWORD as-is (same
values already configured for the reference repo, since it's the same Pi)
B) New, project-scoped secrets (e.g. SLPMODULARCMS_PI_HOST, etc.) even if the values happen to be
identical today, so the two repositories' deploy targets can diverge independently later
C) Other (please describe after Answer: tag below)
Answer: A, but rename PI_MAIN_HOST to PI_MAIN_ADDRESS
Self-Validation
- Every question uses lettered multiple-choice options
- Every question ends in an explicit
Otheroption - Every question has an
[Answer]:tag - No process/approval question is included here (those stay in chat)