Fixes the account model deploy setup got wrong
webadmin turned out to be FTP-only and belongs to whoever uploads customer websites, not to this pipeline. Switched to a separate deploy account with its own home-directory paths, well away from where the other sites live, and made the persistent website symlink cross into webadmin's territory instead of the other way around.
This commit is contained in:
+68
-20
@@ -14,12 +14,34 @@ assumes already exists — `deploy-scp.yaml` (U6) never creates any of it.
|
||||
### 1.1 Prerequisites
|
||||
- .NET 10 runtime installed on the Pi (ASM-03) — the publish is framework-dependent
|
||||
(`infrastructure-design.md` § 1), so the Pi needs the runtime, not the full SDK
|
||||
- SSH access for the deploy user, password auth for now (matches the reference project;
|
||||
SSH-key migration remains a documented future step, same as there)
|
||||
- `sqlcmd` installed, for the backup script (§ 4) — e.g. `mssql-tools18` / `unixodbc` on Debian-based
|
||||
Raspberry Pi OS
|
||||
|
||||
### 1.2 Enable Lingering (INFRA-U6-01 — do this first, easy to forget)
|
||||
### 1.2 Account Model (revised — `webadmin` is not the deploy account)
|
||||
|
||||
Clarified during Deployment Setup: `webadmin` is the FileZilla/SFTP account website-workspace
|
||||
authors use to upload customer sites under `/mnt/storage1/www/html/` (`WEBSITE_WORKSPACE.md`'s
|
||||
role) — it cannot SSH in, and should **stay** SFTP-only. `deploy-scp.yaml` needs a real SSH shell
|
||||
(for `mkdir`, `ln -sfn`, `systemctl --user restart`, the backup script), which is a different kind
|
||||
of access than FileZilla uses.
|
||||
|
||||
**Preferred**: create a separate, dedicated account for the deploy pipeline — e.g.
|
||||
`slpmodularcms-deploy` (rename freely; nothing in the workflow hardcodes this name, it only reads
|
||||
`PI_MAIN_USERNAME`). This keeps the two roles cleanly apart, matching your stated preference.
|
||||
```bash
|
||||
sudo useradd -m -s /bin/bash slpmodularcms-deploy
|
||||
sudo passwd slpmodularcms-deploy
|
||||
```
|
||||
**Fallback, only if a new account genuinely isn't feasible** (e.g. a hosting provider that doesn't
|
||||
allow arbitrary new system accounts): grant `webadmin` SSH shell access instead
|
||||
(`sudo usermod -s /bin/bash webadmin`, plus enabling SSH password/key auth for it if currently
|
||||
blocked at the `sshd_config` level). This merges the two roles onto one account — acceptable as a
|
||||
fallback, but worth revisiting later, since it means a website-workspace author's FTP credential
|
||||
would also be able to run shell commands on the Pi.
|
||||
|
||||
The rest of this document uses `<deploy-user>` — substitute whichever of the two you actually use.
|
||||
|
||||
### 1.3 Enable Lingering (INFRA-U6-01 — do this first, easy to forget)
|
||||
```bash
|
||||
sudo loginctl enable-linger <deploy-user>
|
||||
```
|
||||
@@ -29,15 +51,38 @@ common "Failed to connect to bus" error `systemctl --user` can throw when invoke
|
||||
non-interactive SSH command — lingering keeps the user's systemd instance (and `XDG_RUNTIME_DIR`)
|
||||
running independent of any login session.
|
||||
|
||||
### 1.3 Directory Skeleton
|
||||
Run once per environment (`test`, `production`):
|
||||
### 1.4 Directory Skeleton
|
||||
|
||||
Deliberately placed under `<deploy-user>`'s **own home directory**, not under
|
||||
`/mnt/storage1/www/html/` — since it's now a separate account from `webadmin`, there is no reason
|
||||
for the CMS's own release/current/shared structure to live anywhere near the other websites at all,
|
||||
which directly avoids interfering with them (as you asked in Q2):
|
||||
|
||||
```bash
|
||||
mkdir -p ~/apps/slpmodularcms-<env>/releases
|
||||
mkdir -p ~/apps/slpmodularcms-<env>/shared/wwwroot-web
|
||||
```
|
||||
|
||||
`current` is created by the first deploy itself (`ln -sfn`) — don't pre-create it.
|
||||
|
||||
### 1.4 Runtime Configuration File
|
||||
**`shared/wwwroot-web` is the one exception** — it must resolve to wherever `webadmin` actually
|
||||
uploads *this* customer's website via FileZilla, e.g. `/mnt/storage1/www/html/slpmodularcms-<env>/`
|
||||
(adjust the exact folder name to whatever convention the other sites under `html/` already use, if
|
||||
one exists). Rather than a plain directory, make it a symlink across accounts:
|
||||
|
||||
```bash
|
||||
mkdir -p ~/apps/slpmodularcms-<env>
|
||||
ln -s /mnt/storage1/www/html/slpmodularcms-<env> ~/apps/slpmodularcms-<env>/shared/wwwroot-web
|
||||
```
|
||||
|
||||
`deploy-scp.yaml`'s existing logic (`releases/{ts}/wwwroot/web -> ../../../shared/wwwroot-web`)
|
||||
needs no changes for this — it only ever resolves the symlink chain, it doesn't care how many hops
|
||||
that chain has. What **does** need attention: `<deploy-user>` needs read + traverse permission on
|
||||
`/mnt/storage1/www/html/slpmodularcms-<env>/` and its parent directories, which `webadmin` owns.
|
||||
Simplest fix: put both accounts in a shared group (e.g. `webshared`), `chgrp -R webshared` that
|
||||
folder, and make sure webadmin's FTP server creates new uploads group-readable (`g+rx`, not just
|
||||
owner-readable) — a one-time permission setup, not something either pipeline touches per deploy.
|
||||
|
||||
### 1.5 Runtime Configuration File
|
||||
One file per environment, **outside** the release directory so it survives every switch:
|
||||
```bash
|
||||
touch ~/apps/slpmodularcms-<env>/shared/env
|
||||
@@ -63,11 +108,11 @@ occupies them. `ASPNETCORE_ENVIRONMENT=Production` is used for **both** environm
|
||||
should be true for anything reachable at a real domain, including test.
|
||||
|
||||
**`SecurityHeaders__AllowedScriptOrigins__0` / `_AllowedConnectOrigins__0` must exactly match** the
|
||||
Gitea variables `SECURITY_ALLOWED_SCRIPT_ORIGINS_TEST` / `_PRODUCTION` (see § 3) — REF-U5-01's CI
|
||||
Gitea variables `SECURITY_ALLOWED_SCRIPT_ORIGINS_TEST` / `_PRODUCTION` (see § 1.9) — REF-U5-01's CI
|
||||
gate only catches drift between the frontend build and that Gitea variable; it cannot see this file,
|
||||
so keeping the two in sync is a manual discipline, not something enforced automatically.
|
||||
|
||||
### 1.5 systemd User Units
|
||||
### 1.6 systemd User Units
|
||||
Create `~/.config/systemd/user/slpmodularcms-test.service`:
|
||||
```ini
|
||||
[Unit]
|
||||
@@ -96,7 +141,7 @@ systemctl --user enable slpmodularcms-test.service
|
||||
systemctl --user enable slpmodularcms-production.service
|
||||
```
|
||||
|
||||
### 1.6 nginx Routing
|
||||
### 1.7 nginx Routing
|
||||
The existing reverse proxy (`infrastructure-design.md` § 1, § 4) needs a server block per domain,
|
||||
routing to the matching local port:
|
||||
```nginx
|
||||
@@ -123,7 +168,7 @@ server {
|
||||
TLS certificate provisioning (e.g. certbot) is existing host operations, out of scope for this
|
||||
feature — assumed already handled the same way the reference project's domains are.
|
||||
|
||||
### 1.7 Database Backup Credentials (§ 4 depends on this)
|
||||
### 1.8 Database Backup Credentials (§ 4 depends on this)
|
||||
```bash
|
||||
touch ~/.config/slpmodularcms-db-backup.env
|
||||
chmod 600 ~/.config/slpmodularcms-db-backup.env
|
||||
@@ -134,21 +179,24 @@ DB_NAME=SlpModularCmsProduction
|
||||
DB_USER=<a-login-with-backup-database-permission>
|
||||
DB_PASSWORD=<password>
|
||||
```
|
||||
Kept **separate** from `shared/env` (§ 1.4) deliberately — the backup script needs its own
|
||||
Kept **separate** from `shared/env` (§ 1.5) deliberately — the backup script needs its own
|
||||
credential, ideally scoped to just `BACKUP DATABASE` permission rather than the application's own
|
||||
data-access login.
|
||||
|
||||
### 1.8 Gitea Actions Variables and Secrets
|
||||
Set once, in this repository's Gitea Actions settings:
|
||||
### 1.9 Gitea Actions Variables and Secrets
|
||||
Set once, in this repository's Gitea Actions settings. This is exactly where the real path lives —
|
||||
`deploy-scp.yaml` never hardcodes it, it only reads `${{ vars.DEPLOY_PATH_TEST }}` /
|
||||
`${{ vars.DEPLOY_PATH_PRODUCTION }}`, so changing the path later is a variable edit, not a workflow
|
||||
change:
|
||||
|
||||
| Name | Kind | Value |
|
||||
|---|---|---|
|
||||
| `PI_MAIN_ADDRESS` | secret | the Pi's address |
|
||||
| `PI_MAIN_PORT` | secret | SSH port |
|
||||
| `PI_MAIN_USERNAME` | secret | deploy user |
|
||||
| `PI_MAIN_PASSWORD` | secret | deploy user's password |
|
||||
| `DEPLOY_PATH_TEST` | variable | `/home/<user>/apps/slpmodularcms-test` |
|
||||
| `DEPLOY_PATH_PRODUCTION` | variable | `/home/<user>/apps/slpmodularcms-production` |
|
||||
| `PI_MAIN_USERNAME` | secret | `<deploy-user>` — the new dedicated account (§ 1.2), **not** `webadmin` |
|
||||
| `PI_MAIN_PASSWORD` | secret | `<deploy-user>`'s password |
|
||||
| `DEPLOY_PATH_TEST` | variable | `/home/<deploy-user>/apps/slpmodularcms-test` |
|
||||
| `DEPLOY_PATH_PRODUCTION` | variable | `/home/<deploy-user>/apps/slpmodularcms-production` |
|
||||
| `SERVICE_NAME_TEST` | variable | `slpmodularcms-test.service` |
|
||||
| `SERVICE_NAME_PRODUCTION` | variable | `slpmodularcms-production.service` |
|
||||
| `HEALTH_CHECK_URL_TEST` | variable | `https://test.slpsoftware.nl/health` |
|
||||
@@ -156,7 +204,7 @@ Set once, in this repository's Gitea Actions settings:
|
||||
| `VITE_SENTRY_DSN` | variable | Sentry DSN (shared, not sensitive — safe in the client bundle) |
|
||||
| `VITE_UMAMI_SCRIPT_URL` | variable | Umami script host (shared) |
|
||||
| `VITE_UMAMI_WEBSITE_ID_TEST` / `_PRODUCTION` | variable | per-environment Umami website ID |
|
||||
| `SECURITY_ALLOWED_SCRIPT_ORIGINS_TEST` / `_PRODUCTION` | variable | **must match** § 1.4's `SecurityHeaders__AllowedScriptOrigins__0` for that environment |
|
||||
| `SECURITY_ALLOWED_SCRIPT_ORIGINS_TEST` / `_PRODUCTION` | variable | **must match** § 1.5's `SecurityHeaders__AllowedScriptOrigins__0` for that environment |
|
||||
|
||||
---
|
||||
|
||||
@@ -194,7 +242,7 @@ ENVIRONMENT="${1:?Usage: backup-slpmodularcms-db.sh <environment>}"
|
||||
CREDENTIALS_FILE="$HOME/.config/slpmodularcms-db-backup.env"
|
||||
|
||||
if [[ ! -f "$CREDENTIALS_FILE" ]]; then
|
||||
echo "Missing $CREDENTIALS_FILE — see deployment-instructions.md § 1.7" >&2
|
||||
echo "Missing $CREDENTIALS_FILE — see deployment-instructions.md § 1.8" >&2
|
||||
exit 1
|
||||
fi
|
||||
# shellcheck source=/dev/null
|
||||
|
||||
@@ -25,6 +25,14 @@ procedure.
|
||||
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.
|
||||
|
||||
**Account model (revised at Deployment Setup)**: the Pi's existing `webadmin` account is FileZilla/
|
||||
SFTP-only, used by website-workspace authors uploading customer sites under
|
||||
`/mnt/storage1/www/html/` (`WEBSITE_WORKSPACE.md`'s role) — it cannot SSH in and stays that way. The
|
||||
deploy pipeline uses a **separate, dedicated** SSH-capable account instead
|
||||
(`deployment-instructions.md` § 1.2), so the two roles never overlap on one credential. Deploy paths
|
||||
live under that account's own home directory, not under `html/` — this was a deliberate choice to
|
||||
avoid the CMS's release/current/shared structure interfering with the other websites hosted there.
|
||||
|
||||
## Rationale for What's Documented Here vs. Already Decided
|
||||
|
||||
| Already decided (Construction) | Documented here (Operations) |
|
||||
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
# Deployment Setup — Clarification Questions
|
||||
|
||||
You mentioned `/mnt/storage1/www/html/` as the real path convention, and that `webadmin` (the
|
||||
FileZilla account) cannot log in via SSH. `deploy-scp.yaml` (built in U6) needs more than file
|
||||
transfer — it runs `mkdir`, `ln -sfn`, `systemctl --user restart`, and the backup script over an SSH
|
||||
**shell** command, not just SFTP. That needs a genuinely different kind of access than FileZilla
|
||||
uses, so I want to confirm rather than guess.
|
||||
|
||||
## Question 1: Which Account Should the Deploy Pipeline Use?
|
||||
|
||||
A) `webadmin` is the only account that exists for this Pi's web content — grant it SSH **shell**
|
||||
access (not just SFTP) so the deploy workflow can use it
|
||||
B) There's a different, existing account with full SSH shell access already (e.g. whatever the
|
||||
reference `SlpSoftware` project's working pipeline uses) — reuse that one for
|
||||
`PI_MAIN_USERNAME`, keep `webadmin` purely for FileZilla/manual use
|
||||
C) Create a brand-new dedicated account for the deploy pipeline, separate from both `webadmin` and
|
||||
whatever the reference project uses
|
||||
D) Other (please describe after [Answer]: tag below)
|
||||
|
||||
[Answer]: C, dit is het mooiste, maar is dta haalbaar. Anders terugvallen naar optie A
|
||||
|
||||
## Question 2: Directory Placement Under `/mnt/storage1/www/html/`
|
||||
|
||||
`deployment-instructions.md` currently assumes `~/apps/slpmodularcms-<env>/` as the deploy path —
|
||||
that needs to change to match this Pi's real convention. What should the two environments' paths be?
|
||||
|
||||
A) `/mnt/storage1/www/html/slpmodularcms-test/` and `/mnt/storage1/www/html/slpmodularcms-production/`
|
||||
— siblings, same naming pattern I already used
|
||||
B) A different naming convention is already used for other sites under `html/` — describe the
|
||||
pattern to follow after [Answer]: below
|
||||
C) Not sure yet — pick reasonable names, I'll rename if it clashes with something already there
|
||||
|
||||
X) Other (please describe after [Answer]: tag below)
|
||||
|
||||
[Answer]: X, zou de deploy path niet in de variabelen moeten staan van gitea? En dan vanuit daar bepalen waar de boel komt? Het is eventueel mogelijk een los pad aan te geven naast de html-map zodat het niet in de weg gaat zitten met de (andere) websites
|
||||
|
||||
## Question 3: Does `webadmin`'s FileZilla Access Relate to the Website Workspace Contract?
|
||||
|
||||
`WEBSITE_WORKSPACE.md` (U7) describes how a separate website-workspace author deploys the public
|
||||
site into `wwwroot/web/`. Is `webadmin`/FileZilla actually **that** role — the account a website
|
||||
builder uses to upload the customer's site — rather than the account meant to run the CMS's own
|
||||
deploy pipeline?
|
||||
|
||||
A) Yes — `webadmin` is for website-workspace authors (FTPS into `wwwroot/web/`), completely separate
|
||||
from whatever account runs the CI/CD deploy pipeline
|
||||
B) No — `webadmin` was meant to be used for everything, including the CMS deploy pipeline itself
|
||||
C) Not decided yet / don't know
|
||||
|
||||
X) Other (please describe after [Answer]: tag below)
|
||||
|
||||
[Answer]: X, zoals in vraag 1 aangegeven zou het het beste zijn als webadmin is voor het uploaden van websites via filezilla en dat er een apart pipeline gebruiker is.
|
||||
Reference in New Issue
Block a user