Nests environments under one slpmodularcms folder instead of siblings

Applies to both the app's own release tree and the website upload
path - slpmodularcms/test and slpmodularcms/production side by side
under one parent, not two separately-named directories. Service unit
names stay hyphenated; those aren't folders.
This commit is contained in:
2026-07-28 21:43:37 +02:00
parent 25a3de0f1f
commit 843253888e
3 changed files with 28 additions and 17 deletions
@@ -1312,3 +1312,14 @@ by Infrastructure Design. U5 carries REF-U3-01's Umami origin gate plus FR-21 an
**Context**: OPERATIONS — Deployment Setup, consistency fix before final approval
---
## Deployment Setup — Nested Directory Structure
**Timestamp**: 2026-07-28T04:15:00Z
**User Input**: "is het ook mogelijk een mappenstructuur te doen met slpsoftware/<env> in paats van slpsoftware-<env>? Dus dat er binnen een slpsoftware-map mappen komen voor elke environment? Zowel voor de ~/apps/slpmodularcms als voor de frontendsen de www/hhtml mappen?"
**AI Response**: "Changed the directory convention throughout deployment-instructions.md and rollback-plan.md from sibling slpmodularcms-<env> directories to a nested slpmodularcms/<env> structure, for both ~/apps/slpmodularcms/<env>/ and /mnt/storage1/www/html/slpmodularcms/<env>/, including the backup directory for consistency. Left systemd unit filenames (slpmodularcms-test.service / slpmodularcms-production.service) and the SERVICE_NAME_TEST/_PRODUCTION Gitea variables hyphenated, since those are service names, not directories, and the request was specifically about folder structure."
**Context**: OPERATIONS — Deployment Setup, directory naming convention change before final approval
---
@@ -35,7 +35,7 @@ sudo useradd -m -s /bin/bash gitea-workflow
sudo passwd gitea-workflow
```
Each project deploying through this account gets its own subdirectory under its home (§ 1.4 already
namespaces by project: `~/apps/slpmodularcms-<env>/`), so one generic account can serve multiple
namespaces by project: `~/apps/slpmodularcms/<env>/`), so one generic account can serve multiple
projects without their release trees colliding.
**Fallback, only if no SSH-capable account exists at all and creating one genuinely isn't feasible**
@@ -66,25 +66,25 @@ for the CMS's own release/current/shared structure to live anywhere near the oth
which directly avoids interfering with them (as you asked in Q2):
```bash
mkdir -p ~/apps/slpmodularcms-<env>/releases
mkdir -p ~/apps/slpmodularcms/<env>/releases
```
`current` is created by the first deploy itself (`ln -sfn`) — don't pre-create it.
**`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>/`
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
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: `gitea-workflow` needs read + traverse permission on
`/mnt/storage1/www/html/slpmodularcms-<env>/` and its parent directories, which `webadmin` owns.
`/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.
@@ -92,8 +92,8 @@ owner-readable) — a one-time permission setup, not something either pipeline t
### 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
chmod 600 ~/apps/slpmodularcms-<env>/shared/env
touch ~/apps/slpmodularcms/<env>/shared/env
chmod 600 ~/apps/slpmodularcms/<env>/shared/env
```
Contents (fill in real values — this file is never read by the workflow, only by the systemd unit
below):
@@ -127,9 +127,9 @@ Description=SlpModularCms API (test)
After=network.target
[Service]
WorkingDirectory=%h/apps/slpmodularcms-test/current
ExecStart=/usr/bin/dotnet %h/apps/slpmodularcms-test/current/SlpModularCms.Api.dll
EnvironmentFile=%h/apps/slpmodularcms-test/shared/env
WorkingDirectory=%h/apps/slpmodularcms/test/current
ExecStart=/usr/bin/dotnet %h/apps/slpmodularcms/test/current/SlpModularCms.Api.dll
EnvironmentFile=%h/apps/slpmodularcms/test/shared/env
Restart=on-failure
RestartSec=5
KillSignal=SIGINT
@@ -202,8 +202,8 @@ change:
| `PI_MAIN_PORT` | secret | SSH port |
| `PI_MAIN_USERNAME` | secret | `gitea-workflow` — the generic, host-wide deploy account (§ 1.2), **not** `webadmin`; reuse the reference project's if it already has one |
| `PI_MAIN_PASSWORD` | secret | `gitea-workflow`'s password |
| `DEPLOY_PATH_TEST` | variable | `/home/gitea-workflow/apps/slpmodularcms-test` |
| `DEPLOY_PATH_PRODUCTION` | variable | `/home/gitea-workflow/apps/slpmodularcms-production` |
| `DEPLOY_PATH_TEST` | variable | `/home/gitea-workflow/apps/slpmodularcms/test` |
| `DEPLOY_PATH_PRODUCTION` | variable | `/home/gitea-workflow/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` |
@@ -256,7 +256,7 @@ fi
source "$CREDENTIALS_FILE"
: "${DB_SERVER:?}" "${DB_NAME:?}" "${DB_USER:?}" "${DB_PASSWORD:?}"
BACKUP_DIR="$HOME/backups/slpmodularcms-${ENVIRONMENT}"
BACKUP_DIR="$HOME/backups/slpmodularcms/${ENVIRONMENT}"
mkdir -p "$BACKUP_DIR"
TIMESTAMP=$(date -u +%Y%m%d%H%M%S)
BACKUP_FILE="$BACKUP_DIR/${DB_NAME}-${TIMESTAMP}.bak"
@@ -278,7 +278,7 @@ chmod +x ~/scripts/backup-slpmodularcms-db.sh
```bash
~/scripts/backup-slpmodularcms-db.sh production
```
Confirm a `.bak` file appears under `~/backups/slpmodularcms-production/` and that `sqlcmd` didn't
Confirm a `.bak` file appears under `~/backups/slpmodularcms/production/` and that `sqlcmd` didn't
silently fail (the script uses `set -euo pipefail`, so a real SQL error does propagate as a non-zero
exit — which fails the calling `deploy-scp.yaml` step, correctly blocking the deploy).
@@ -16,9 +16,9 @@ failed deploy never leaves fewer than two releases on disk.
No rebuild needed. Over SSH, on the Pi:
```bash
cd ~/apps/slpmodularcms-<env>/releases
cd ~/apps/slpmodularcms/<env>/releases
ls -1t # confirm which directory is the previous, working release
ln -sfn ~/apps/slpmodularcms-<env>/releases/<previous-timestamp> ~/apps/slpmodularcms-<env>/current
ln -sfn ~/apps/slpmodularcms/<env>/releases/<previous-timestamp> ~/apps/slpmodularcms/<env>/current
systemctl --user restart slpmodularcms-<env>.service
curl -f https://<env-domain>/health # confirm the rollback itself is healthy
```