Files
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
..

Scripts running on alpha.jayfield.org

OS: Ubuntu 24.04.4 LTS (Noble Numbat), kernel 6.8.0-136-generic (upgraded from 22.04 on 2026-07-26 — see TODO.md in the repo root for the full rollout). Standard Ubuntu conventions throughout: systemd for services, /etc/cron.d/ for scheduled jobs, a normal persistent root filesystem — none of the "does this survive a reboot?" caveats that clients/vlda-01/ needs.

Files, and where they're actually deployed

File here Deployed path Purpose
sanity-check.sh /usr/local/sbin/sanity-check.sh Post-boot/post-change health check across the whole stack (DNS/DNSSEC, mail, MariaDB, fail2ban, Apache vhosts, Docker containers, Gitea). See root README.md's "Post-boot sanity check".
sanity-check.service /etc/systemd/system/sanity-check.service Runs sanity-check.sh once per boot (systemctl enabled), After= the relevant services plus a 10s settle delay.
attacker-check.py /usr/local/sbin/attacker-check.py Weekly fail2ban log analysis — per-IP/per-jail CSVs for trend analysis, plus distributed-scan and regular-timing-evasion detection. See root README.md's "Weekly attacker summary".
cron.d/attacker-check /etc/cron.d/attacker-check Runs attacker-check.py weekly, Sunday 06:00.
gitea-backup.sh /usr/local/sbin/gitea-backup.sh Nightly gitea dump + sha256 checksum, ACL'd for the giteabackup pull account, pruned to 14 as a safety net. See root README.md's "Gitea backup to vlda-01".
cron.d/gitea-backup /etc/cron.d/gitea-backup Runs gitea-backup.sh nightly, 02:30.

Permissions as deployed (not preserved by git)

Git doesn't track exact ownership/mode the way these need to run as — set these explicitly on (re-)deploy:

sudo chown root:root /usr/local/sbin/{sanity-check.sh,attacker-check.py,gitea-backup.sh}
sudo chmod 750 /usr/local/sbin/{sanity-check.sh,attacker-check.py,gitea-backup.sh}
sudo chown root:root /etc/cron.d/{attacker-check,gitea-backup} /etc/systemd/system/sanity-check.service
sudo chmod 644 /etc/cron.d/{attacker-check,gitea-backup} /etc/systemd/system/sanity-check.service

gitea-backup.sh additionally depends on:

  • The giteabackup system account, its chrooted-SFTP sshd config (reuses the existing Match Group sftp block — no new sshd_config needed, just add the user to the sftp group), and the rw bind mount at /var/sftp/giteabackup/backups (see root README.md for the full ACL/permission model — this is not just "make the script executable and it works", the restricted account is load-bearing for the whole design).