torrentvpn stack — 36 containers from one compose file, plus one that is not¶
~/torrentvpn/docker-compose.yml (34 services) + .env. Every service's config lives in ~/torrentvpn/<service>/. samba-nas is not from compose — it was docker run and the compose samba service has drifted from it.
Why this shape¶
One stack dir so one backup script (docker-backup.sh) and one rescue archive cover everything. VPN isolation is by network namespace: qBittorrent runs inside gluetun's, so torrent traffic cannot leave except through the tunnel.
Shape¶
Services by group (compose line numbers, 09-08):
- VPN + downloads: gluetun:2 (NordVPN; qbittorrent:40 uses network_mode: service:gluetun), unpackerr:58, rar-extractor:636, prowlarr:184, flaresolverr:265
- Media: plex:93 (/mnt/storage/{movies,tv,anime,kids-*}), jellyfin:280 (/mnt/storage:/data:ro), tautulli:557, tdarr:572 + tdarr-node:592 (no libraries configured — item 16 note), bazarr:212, overseerr:125
- *arr: radarr:139, sonarr:154, sonarr-anime:169, recyclarr:198
- Photos: immich-server:456, immich-machine-learning:481, immich-postgres:438, immich-redis:451 → immich
- Network: pihole:357 (dns.lan, resolves *.lan), npm:527 (npm.lan:81, proxies *.lan), wg-easy:327 (wg.lan; wg-docker-watchdog.timer restarts it every minute if stopped), duckdns:542
- Secrets: vaultwarden (end of file; vault.embeddedera.com via NPM, HTTPS only) → vaultwarden
- MRP/inventory: inventree-db/cache/server/worker/proxy (end of file; erp.lan via NPM, LAN-only for now) → inventree
- Ops: homer:381 (dashboard; vpn-check writes its VPN tile), portainer:503, uptime-kuma:514, dozzle:427, glances:411, scrutiny:690, filebrowser:393 (files.lan, /mnt/storage as /srv/media), mosquitto:674
- samba:615 — ghost. Binds /mnt/storage/Storage-snapshots; the live samba-nas binds /mnt/disk1/Storage-snapshots and serves EmbeddedEra. docker compose up -d would recreate it wrong.
Rules:
- Never a bare docker compose up -d. Always name the service: docker compose up -d scrutiny. Stop/start samba-nas by name with docker stop/start.
- Recreate gluetun and qbittorrent together or qbittorrent loses its network.
- gluetun's ICMP health probe fails forever on NordVPN; gf fixes it (HEALTH_TARGET is the wrong variable name on this build).
- Radarr/Sonarr/Sonarr-anime: removeCompletedDownloads=false and removeFailedDownloads=false — this is the safety interlock that prevents the 09-03 incident. DBs backed up as *.db.bak.incident-20260903.
- .env is 0600; the only off-box copy is env.gpg on the rescue USB.
Leftovers in the dir: 12 docker-compose.yml.bak* copies, prowlarr-broken-2025* ×4, immich-backup-20251205-*, snapraid-webui/, h5ai/, homeassistant/, jellystat/, openvpn/ — config dirs with no running container.
Connected to¶
- owns: every container's config dir; the
.env - owned-by: host/machine
- joins: storage/mergerfs-pool (all media binds), storage/rescue-usb (nightly archive of this dir), automation/alerting
If you change this¶
- Hits:
docker-backup.shsnapshot contents (skipsVideos media immich wireguard-wg_confs docker-backups+ caches) · the rescue archive · Pi-hole/NPM entries if a hostname changes · homerconfig.ymllinks · the *arr interlock if you touch a download client. - Does not hit: SnapRAID, mergerfs, rsnapshot, precious.
Surfaces¶
| Surface | Role |
|---|---|
dps alias |
docker ps table |
Portainer (portainer.lan), Dozzle (logs) |
UI |
docker-backup.sh 01:00 |
rsync of config dirs → /mnt/storage/docker-backups/snapshots/ (7 kept); log /var/log/docker-backup.log (832 MB, unrotated) |
See¶
- Source:
/home/angel/torrentvpn/docker-compose.yml·/usr/local/bin/docker-backup.sh·~/.local/bin/gf