Names the deployed instance slpsoftware, not the software itself
SlpModularCms is the product; slpsoftware.nl is the customer running it - the first one, and a fine stand-in for what a real deployment looks like. Renamed the directories, systemd units, and backup paths accordingly. Left the backup script's own filename alone since the already-committed deploy-scp.yaml calls it by that exact name.
This commit is contained in:
+33
-27
@@ -4,6 +4,12 @@
|
||||
directory, `systemd --user` unit, and local port. Domains: `test.slpsoftware.nl` (test),
|
||||
`slpsoftware.nl` (production).
|
||||
|
||||
**Naming note**: directories, systemd units and the website-upload path below are named
|
||||
`slpsoftware` — the **customer/instance** running SlpModularCms (this repo's software), not the
|
||||
software itself. SlpModularCms can host multiple customers; `slpsoftware` is this one — the first,
|
||||
and the owner's own site. A future second customer on the same Pi would get its own instance name
|
||||
throughout, following the same pattern.
|
||||
|
||||
---
|
||||
|
||||
## 1. One-Time Host Setup
|
||||
@@ -35,7 +41,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/slpsoftware/<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 +72,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/slpsoftware/<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/slpsoftware/<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/slpsoftware/<env>
|
||||
ln -s /mnt/storage1/www/html/slpsoftware/<env> ~/apps/slpsoftware/<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/slpsoftware/<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,15 +98,15 @@ 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/slpsoftware/<env>/shared/env
|
||||
chmod 600 ~/apps/slpsoftware/<env>/shared/env
|
||||
```
|
||||
Contents (fill in real values — this file is never read by the workflow, only by the systemd unit
|
||||
below):
|
||||
```ini
|
||||
ASPNETCORE_ENVIRONMENT=Production
|
||||
ASPNETCORE_URLS=http://localhost:<port>
|
||||
ConnectionStrings__DefaultConnection=Server=127.0.0.1,1433;User ID=<user>;Password=<password>;Database=SlpModularCms<Env>;TrustServerCertificate=True
|
||||
ConnectionStrings__DefaultConnection=Server=127.0.0.1,1433;User ID=<user>;Password=<password>;Database=SlpSoftware<Env>;TrustServerCertificate=True
|
||||
JwtSettings__Secret=<secure-long-random-secret>
|
||||
JwtSettings__Issuer=SlpModularCms
|
||||
JwtSettings__Audience=SlpModularCmsPortal
|
||||
@@ -120,16 +126,16 @@ gate only catches drift between the frontend build and that Gitea variable; it c
|
||||
so keeping the two in sync is a manual discipline, not something enforced automatically.
|
||||
|
||||
### 1.6 systemd User Units
|
||||
Create `~/.config/systemd/user/slpmodularcms-test.service`:
|
||||
Create `~/.config/systemd/user/slpsoftware-test.service`:
|
||||
```ini
|
||||
[Unit]
|
||||
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/slpsoftware/test/current
|
||||
ExecStart=/usr/bin/dotnet %h/apps/slpsoftware/test/current/SlpModularCms.Api.dll
|
||||
EnvironmentFile=%h/apps/slpsoftware/test/shared/env
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
KillSignal=SIGINT
|
||||
@@ -138,14 +144,14 @@ TimeoutStopSec=20
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
```
|
||||
And `~/.config/systemd/user/slpmodularcms-production.service` — identical, with `test` replaced by
|
||||
And `~/.config/systemd/user/slpsoftware-production.service` — identical, with `test` replaced by
|
||||
`production` throughout (including the port inside `shared/env`).
|
||||
|
||||
Enable both (does not start them yet — nothing is deployed there until the first CI run):
|
||||
```bash
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user enable slpmodularcms-test.service
|
||||
systemctl --user enable slpmodularcms-production.service
|
||||
systemctl --user enable slpsoftware-test.service
|
||||
systemctl --user enable slpsoftware-production.service
|
||||
```
|
||||
|
||||
### 1.7 nginx Routing
|
||||
@@ -177,12 +183,12 @@ feature — assumed already handled the same way the reference project's domains
|
||||
|
||||
### 1.8 Database Backup Credentials (§ 4 depends on this)
|
||||
```bash
|
||||
touch ~/.config/slpmodularcms-db-backup.env
|
||||
chmod 600 ~/.config/slpmodularcms-db-backup.env
|
||||
touch ~/.config/slpsoftware-db-backup.env
|
||||
chmod 600 ~/.config/slpsoftware-db-backup.env
|
||||
```
|
||||
```ini
|
||||
DB_SERVER=127.0.0.1,1433
|
||||
DB_NAME=SlpModularCmsProduction
|
||||
DB_NAME=SlpSoftwareProduction
|
||||
DB_USER=<a-login-with-backup-database-permission>
|
||||
DB_PASSWORD=<password>
|
||||
```
|
||||
@@ -202,10 +208,10 @@ 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` |
|
||||
| `SERVICE_NAME_TEST` | variable | `slpmodularcms-test.service` |
|
||||
| `SERVICE_NAME_PRODUCTION` | variable | `slpmodularcms-production.service` |
|
||||
| `DEPLOY_PATH_TEST` | variable | `/home/gitea-workflow/apps/slpsoftware/test` |
|
||||
| `DEPLOY_PATH_PRODUCTION` | variable | `/home/gitea-workflow/apps/slpsoftware/production` |
|
||||
| `SERVICE_NAME_TEST` | variable | `slpsoftware-test.service` |
|
||||
| `SERVICE_NAME_PRODUCTION` | variable | `slpsoftware-production.service` |
|
||||
| `HEALTH_CHECK_URL_TEST` | variable | `https://test.slpsoftware.nl/health` |
|
||||
| `HEALTH_CHECK_URL_PRODUCTION` | variable | `https://slpsoftware.nl/health` |
|
||||
| `VITE_SENTRY_DSN` | variable | Sentry DSN (shared, not sensitive — safe in the client bundle) |
|
||||
@@ -223,7 +229,7 @@ Already built (U5/U6) — this is the read-only walkthrough for whoever operates
|
||||
2. `publish-test` runs (and `publish-production`, only if `workflow_dispatch` with the flag)
|
||||
3. `deploy-test` (always, if gates pass) calls `deploy-scp.yaml`, which uploads into a new
|
||||
`releases/{timestamp}/`, links `shared/wwwroot-web` in, switches `current`, restarts
|
||||
`slpmodularcms-test.service`, verifies `https://test.slpsoftware.nl/health`, then prunes old
|
||||
`slpsoftware-test.service`, verifies `https://test.slpsoftware.nl/health`, then prunes old
|
||||
releases (only test — `run_db_backup: false`)
|
||||
4. `deploy-production` (only with the flag) does the same, plus a database backup first
|
||||
(`run_db_backup: true`) — see § 4
|
||||
@@ -246,7 +252,7 @@ part of this repository, so no DB credential ever reaches Gitea):
|
||||
set -euo pipefail
|
||||
|
||||
ENVIRONMENT="${1:?Usage: backup-slpmodularcms-db.sh <environment>}"
|
||||
CREDENTIALS_FILE="$HOME/.config/slpmodularcms-db-backup.env"
|
||||
CREDENTIALS_FILE="$HOME/.config/slpsoftware-db-backup.env"
|
||||
|
||||
if [[ ! -f "$CREDENTIALS_FILE" ]]; then
|
||||
echo "Missing $CREDENTIALS_FILE — see deployment-instructions.md § 1.8" >&2
|
||||
@@ -256,7 +262,7 @@ fi
|
||||
source "$CREDENTIALS_FILE"
|
||||
: "${DB_SERVER:?}" "${DB_NAME:?}" "${DB_USER:?}" "${DB_PASSWORD:?}"
|
||||
|
||||
BACKUP_DIR="$HOME/backups/slpmodularcms/${ENVIRONMENT}"
|
||||
BACKUP_DIR="$HOME/backups/slpsoftware/${ENVIRONMENT}"
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
TIMESTAMP=$(date -u +%Y%m%d%H%M%S)
|
||||
BACKUP_FILE="$BACKUP_DIR/${DB_NAME}-${TIMESTAMP}.bak"
|
||||
@@ -278,7 +284,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/slpsoftware/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).
|
||||
|
||||
|
||||
+3
-3
@@ -16,10 +16,10 @@ 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/slpsoftware/<env>/releases
|
||||
ls -1t # confirm which directory is the previous, working release
|
||||
ln -sfn ~/apps/slpmodularcms/<env>/releases/<previous-timestamp> ~/apps/slpmodularcms/<env>/current
|
||||
systemctl --user restart slpmodularcms-<env>.service
|
||||
ln -sfn ~/apps/slpsoftware/<env>/releases/<previous-timestamp> ~/apps/slpsoftware/<env>/current
|
||||
systemctl --user restart slpsoftware-<env>.service
|
||||
curl -f https://<env-domain>/health # confirm the rollback itself is healthy
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user