Files
argento/CLAUDE.md
T
2026-04-14 17:51:04 -04:00

4.1 KiB

CLAUDE.md

What this repo is

Git-based provisioning and recovery repo for the "argento" home server (Rocky Linux 9, ZFS, Docker). The repo lives at /opt/argento/ on the server and contains the actual running configs. This dev copy at ~/dev/argento is where edits happen, then files are manually copied to the server.

Recovery steps are in RUNBOOK.md. Repo overview and workflows are in README.md.

Architecture notes not in the docs

  • Docker shared network: Created by the nginx compose file. All Docker apps that nginx proxies to join this network as external: true. If nginx compose hasn't been started, other apps will fail with "network shared not found".
  • nginx variable upstreams: nginx.conf uses resolver 127.0.0.11 (Docker DNS). Confs that proxy to container names use set $upstream_<name> variables so nginx resolves at request time, not startup. Without this, one down container prevents nginx from starting at all.
  • host.docker.internal: Used for services running on the host network (Jellyfin, Cockpit). Requires extra_hosts: ["host.docker.internal:host-gateway"] in nginx's compose.yaml.
  • Jellyfin uses host network: Needs direct access to NVIDIA GPU for hardware transcoding. Proxied via host.docker.internal:8096.
  • Cockpit (argento.timothykim.net): Runs directly on the host (not Docker) on port 9090 with self-signed TLS. The nginx conf inlines security headers instead of including security-headers.inc because Cockpit's internal iframes break with X-Frame-Options: DENY. Cockpit has a known bug where font files return 404 — this is not a proxy issue.
  • Minecraft HTTP-only: HTTPS causes WebSocket/CORS errors with the MCSManager daemon. No cert issued for this domain.
  • SSL cert issuance chicken-and-egg: On fresh recovery, certs don't exist so SSL confs can't load. The .hold pattern moves SSL confs aside, starts nginx with HTTP-only confs, issues certs, then restores SSL confs.
  • SELinux is enforcing: Caused issues with samba (symlinks blocked, parent directory traversal blocked). Don't use symlinks for config files — use the sync-system.sh copy approach instead.
  • Secrets in .env files: All secrets (DB passwords, API keys, tokens) live in .env files under each app's docker/<app>/ directory on the server. These are gitignored (**/.env in root .gitignore). The .env files are included in the USB backup. If the backup is lost, all secrets can be recreated from Bitwarden. The system/msmtprc in the repo has its password REDACTED -- the real one is only on the server.
  • ZFS parent dataset mountpoints: Pools have parent datasets (e.g., nextcloud, threeteras) that create mountpoints like /mnt/nextcloud. These are empty and expected — do not delete them.
  • msmtp: Replaces sendmail for cron MAILTO and smartd email alerts. Configured via /etc/msmtprc (Fastmail SMTP). The symlink /usr/sbin/sendmail -> /usr/bin/msmtp is set up in recovery step 2.
  • Beszel agent: System monitoring agent that reports to the beszel hub on hantim (beszel.hantim.net). Uses host network, listens on port 45876. No nginx proxy — it's not a web app.
  • hantim-server: Sister repo with similar nginx/certbot patterns. Located at ~/dev/hantim-server. Useful as reference for deploy patterns.

Remotes

  • origin: Gitea on argento (private). No offsite mirror — disaster recovery relies on the USB backup's copy of the Gitea bare repo.

Working preferences

  • Don't edit compose files in this repo — Timothy edits those directly on the server. Compose changes here get rejected.
  • Comments in config files should explain the real WHY for this specific app, not generic descriptions of what a directive does.
  • Don't add redundant documentation. If something is already on disk (e.g., crontab contents), don't repeat it in the docs.
  • Keep docs linear and non-confusing. Avoid branching flows that duplicate steps.
  • When proposing config changes, explain the flags/options — Timothy wants to understand what he's committing, not blindly trust it.
  • No emojis in any files.
  • Verify suggestions actually work before confidently recommending them. If unsure, say so.