Files
docs-alpha.jayfield.org/scripts/clients/vlda-01/README.md
T
jensandClaude Sonnet 5 e9b51dbffe Check in scripts/configs, organized and documented by host OS
Every script/config built this session (sanity-check, attacker-check,
the Gitea backup pipeline on both ends) now lives in this repo as
reference copies, not just described in prose - previously they only
existed on the live servers.

Split into scripts/alpha/ (Ubuntu 24.04.4 LTS) and
scripts/clients/vlda-01/ (Unraid 7.3.2), each with its own README
stating the exact OS/kernel and a file-by-file map to deployed paths,
since a script written for one host's conventions doesn't just work
unchanged on the other - the vlda-01 README in particular documents
the persistence gotchas that actually broke earlier attempts (RAM-
backed root filesystem, VFAT /boot with no execute bit, Unassigned
Device auto-mount). Root README.md now links directly to these files
from each relevant section instead of only describing them.

Explicitly not included: the dedicated SSH private key vlda-01 uses to
authenticate to alpha - noted in clients/vlda-01/README.md to
regenerate rather than ever commit one.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-26 17:21:05 +02:00

62 lines
4.4 KiB
Markdown

# Scripts running on `vlda-01`
**OS**: Unraid `7.3.2`, kernel `6.18.38-Unraid`. **Very different
persistence model from Ubuntu/`alpha`** — this tripped up the first version
of every script here, so it's worth stating plainly before anything else:
- `/` and `/usr` are RAM-backed (`rootfs` / an `overlay` on top of the
read-only squashfs image loaded from the boot USB stick). **Anything
written there — a plain crontab, a script dropped in `/usr/local/sbin`
— is silently gone on the next reboot.** Only `/boot` (the actual USB
stick, mounted read/write as a normal filesystem) survives.
- `/boot` is **VFAT**, which has no concept of a Unix execute bit at all.
A script stored there can never be `chmod +x`'d in any way that sticks —
don't try to `exec` it directly from another script; invoke it via
`bash <path>` instead. (The **User Scripts** plugin itself handles this
correctly when it runs a script *through the plugin* — it copies the
content to a RAM-backed tmp location and `chmod +x`s that copy before
running it — but a script invoking *another* script directly, as the
`-onboot` wrapper here does, has to work around it manually.)
- Real, persistent storage lives on the array (`/mnt/user/...`) or on
**Unassigned Devices** — extra disks attached but not part of the
protected array, mounted at `/mnt/disks/<label>` — which is where these
backups actually land. An Unassigned Device is **not guaranteed to
already be mounted** when a script runs; see `gitea-backup-pull`'s own
handling of this below.
- Scheduled tasks persist via the **User Scripts** plugin (already
installed, already used for this box's other maintenance), which stores
scripts under `/boot/config/plugins/user.scripts/scripts/<name>/` and
scheduling in `/boot/config/plugins/user.scripts/schedule.json` — both
on the persistent USB stick. `update_cron` folds the JSON's cron-style
entries into the live `/etc/cron.d/root` at every boot; `"frequency":
"boot"` entries instead run once via the plugin's own `disks_mounted`
array-start event hook, **not** through cron at all.
- SSH keys under `/root/.ssh` needed no special persistence handling —
Unraid already auto-mirrors that whole directory to
`/boot/config/ssh/root/` on its own.
## Files, and where they're actually deployed
| File here | Deployed path | Purpose |
|---|---|---|
| `user-scripts/gitea-backup-pull/script` | `/boot/config/plugins/user.scripts/scripts/gitea-backup-pull/script` | Pulls new `gitea-dump` archives from `alpha` via the restricted `giteabackup` SFTP account, verifies each one's sha256 checksum, deletes both files on `alpha` only after a confirmed match, prunes its own local retention (30). Resolves and mounts the `WSD2L840` Unassigned Device itself first — see the script's own header comment for the full reasoning. |
| `user-scripts/gitea-backup-pull/description` | `.../gitea-backup-pull/description` | Shown in the User Scripts UI. |
| `user-scripts/gitea-backup-pull-onboot/script` | `.../gitea-backup-pull-onboot/script` | One-line wrapper: `bash`-invokes the script above. Exists only because `schedule.json` supports one schedule per script *path* — this is how the "also run once at every restart" requirement was added alongside the existing daily `03:30` schedule without disturbing it. |
| `user-scripts/gitea-backup-pull-onboot/description` | `.../gitea-backup-pull-onboot/description` | Shown in the User Scripts UI. |
| `user-scripts/schedule.json` | `/boot/config/plugins/user.scripts/schedule.json` | **Whole file, as deployed** — includes entries for this box's *other*, pre-existing scheduled maintenance (`delete_dangling_images`, `rc.fancontrol`, etc.) that predate this project and aren't described elsewhere in this repo. Only the `gitea-backup-pull` and `gitea-backup-pull-onboot` entries near the bottom belong to this project. |
## Redeploying from this checked-in copy
```bash
# on vlda-01:
mkdir -p /boot/config/plugins/user.scripts/scripts/gitea-backup-pull
mkdir -p /boot/config/plugins/user.scripts/scripts/gitea-backup-pull-onboot
# copy script/description files into place from this repo, then:
cp /boot/config/plugins/user.scripts/schedule.json /tmp/user.scripts/schedule.json
/usr/local/sbin/update_cron
```
The dedicated ed25519 keypair this depends on (`/root/.ssh/gitea-backup/`,
authorized on `alpha`'s `giteabackup` account) is **not** in this repo —
regenerate it and re-authorize the new public key on `alpha` rather than
ever committing a private key here.