# argento Configuration and recovery repo for the argento home server. This repo is the runbook -- it contains the actual config files and documents the manual steps between them. - Rocky Linux 9 on NVMe - ZFS storage (2 pools: `nextcloud` mirror, `threeteras` raidz2) - Docker apps behind nginx reverse proxy - Daily USB backup via rsync ## Repo structure ``` scripts/ Backup, cert issuance, health monitoring, system config sync docker/ Docker app configs (compose files, nginx confs) nginx/ Reverse proxy + SSL termination nextcloud/ Nextcloud + PostgreSQL gitea/ Gitea + CI runner jellyfin/ Media server garage/ S3-compatible storage minecraft/ MCSManager immich/ Immich photo server + PostgreSQL beszel-agent/ System monitoring agent (reports to beszel.hantim.net) smb/ Samba share (ZFS mountpoint, not in git) system/ System config snapshots (smb.conf, sanoid.conf, firewalld, etc.) ``` ## Key files | File | Purpose | |------|---------| | `RUNBOOK.md` | Full recovery steps, top to bottom | | `scripts/backup.sh` | Daily USB backup (DB dumps + rsync) | | `scripts/issue-cert.sh` | Issue SSL certs via certbot webroot | | `scripts/disk-health-check.sh` | SMART, ZFS, disk space monitoring (daily alerts + weekly reports via cron) | | `scripts/sync-system.sh` | Auto-sync system configs to git | | `system/tracked-configs` | Maps system config paths to repo paths | | `docker/nginx/conf.d/_template.conf.example` | Template for new nginx app confs | ## Workflows **Compose files** -- edit in `/opt/argento/`, apply, commit: ```bash cd /opt/argento/docker/ vim compose.yaml docker compose up -d git add . && git commit && git push ``` **System configs** -- edit in place, auto-synced daily: ```bash vim /etc/samba/smb.conf systemctl restart smb # sync-system.sh runs via cron, or run manually: /opt/argento/scripts/sync-system.sh ``` **Nginx configs** -- edit in repo, reload: ```bash vim /opt/argento/docker/nginx/conf.d/.conf docker exec nginx nginx -t docker exec nginx nginx -s reload git add . && git commit && git push ``` **Updating an app (Diun notification received):** Diun emails when a watched image has a new digest on the registry. The email names the image (e.g. `postgres:17-alpine`), not the container. To find which container uses it: ```bash docker ps --filter "ancestor=:" --format '{{.Names}}' ``` Then apply the update from that app's directory: ```bash cd /opt/argento/docker/ docker compose pull docker compose up -d docker ps # verify container is healthy ``` Then smoke-test the app (open the UI, or `curl -I https://`). Caveats before pulling: - Diun only reports that a digest changed -- it does not say the update is safe. For apps with schema migrations (Nextcloud, Immich, Gitea, Postgres), skim the release notes first. - For major version bumps, run `./scripts/backup.sh` manually before pulling so the USB has a fresh snapshot. - Postgres major version bumps (e.g. 17 -> 18) cannot reuse the old data dir -- a plain `compose up -d` will fail to start. See [RUNBOOK.md](RUNBOOK.md#maintenance-postgres-major-version-upgrade). - After several updates, reclaim disk with `docker image prune -f`. **Apps with a local Dockerfile:** Some compose files build their image locally instead of pulling a tagged one: | App | Service | Base image | Why | |-----|---------|-----------|-----| | `nextcloud` | `nextcloud` | `nextcloud:latest` | Adds smbclient + ffmpeg | | `minecraft` | `daemon` | `githubyumao/mcsmanager-daemon:latest` | Adds Temurin 25 JRE | For these, plain `docker compose pull` fails on the buildable service ("pull access denied"). Use one of: ```bash docker compose pull --ignore-buildable # pull only registry-backed services docker compose build --pull # rebuild, refreshing the FROM base docker compose up -d --build # build + pull + recreate, one shot ``` Diun caveat: Diun watches the running container's image reference. Since these run as local images (e.g. `mcsmanager-daemon-java25`), the registry lookup has nothing to compare against -- **Diun will not notify when the base image updates**. Refresh these manually on your own cadence with `docker compose build --pull && docker compose up -d`. **Adding a new app:** 1. Create `docker//compose.yaml` with `container_name` and `shared` network 2. `docker compose up -d` 3. `./scripts/issue-cert.sh ` 4. `cp docker/nginx/conf.d/_template.conf.example docker/nginx/conf.d/.conf` and fill in placeholders 5. `docker exec nginx nginx -t && docker exec nginx nginx -s reload` 6. Commit and push ## Recovery See [RUNBOOK.md](RUNBOOK.md) for full disaster recovery steps. ## What's protected where | Data | Protection | Recovery | |------|-----------|----------| | Configs (compose, nginx, system) | Git (Gitea bare repo on USB backup) | `git clone` from USB | | Nextcloud files | ZFS mirror + sanoid snapshots + USB | `rsync` from USB | | Media library | ZFS raidz2 + sanoid snapshots + USB | `rsync` from USB | | Nextcloud DB (PostgreSQL) | ZFS dataset + `pg_dumpall` + USB | `rsync` from USB | | Immich library (photos/videos) | ZFS raidz2 + sanoid snapshots + USB | `rsync` from USB | | Immich DB (PostgreSQL) | `pg_dumpall` + USB | `rsync` from USB | | Garage S3 data | 2-node replication + USB | Replication or USB | | Gitea repos + DB | SQLite `.backup` + USB | `rsync` from USB | | Secrets (.env files) | USB backup + Bitwarden | `rsync` from USB, or recreate from Bitwarden | | SSL certificates | Re-issued from Let's Encrypt | `./scripts/issue-cert.sh` |