Files
esh-pfi-infrastructure/configs/restic/vm-esh-nas
vh 76a0768fdb restic: drop scheduled forget across all 6 hosts
Forget against an --append-only rest-server fails every night (delete
ops blocked). The resulting daily failure cluttered service status and
logs without ever actually retiring old snapshots. Schedule is now
removed from the forget block in all six profiles; the keep-daily /
keep-weekly / keep-monthly / keep-yearly policy remains so manual
invocations (during prune ceremonies, when --append-only is
temporarily off) honor the intended retention.

Files:
  configs/restic/ana-docker/profiles.yaml
  configs/restic/ana-ml2/profiles.yaml
  configs/restic/nh3-docker/profiles.yaml
  configs/restic/esh-docker-vm/profiles.yaml
  configs/restic/vm-esh-nas/profiles.yaml
  configs/restic/nh3-dev/profiles.yaml

Each file has an inline comment marking why the schedule was dropped
so a future reader doesn't re-add it thinking it was an oversight.

STATUS.md: removed the "install Backrest nightly-restart timer" line
item. User confirmed the UI timeout hits even at startup, so periodic
restart wouldn't actually help. Root cause remains deferred.
2026-04-21 17:00:23 -07:00
..

restic / vm-esh-nas

Second Docker host at the ESH home lab — a VM on esh-pve-nas. Covered two ways:

  • VM image via Proxmox vzdump on esh-pve-nas (5/5 covered).
  • File-level restic (this config). Cross-site — writes to the Anaheim rest-server at 10.250.50.70:8000/vm-esh-nas/ since the ESH site has no local rest-server.

What's backed up

Path Purpose
/opt/docker Compose files (~56 KB — tiny)
/etc Host config
/root Root's scripts, ssh keys, history
/home User home dirs (lkraven, nas, user)
/var/lib/docker/volumes beszel-agent, dozzle-agent, dockge state

What's critically excluded

/mnt/{share,music,books,media} — NFS mounts from 10.0.50.50 holding ~400 TB of media/share content. Protected at the NAS layer, not here. The exclude-patterns in profiles.yaml are a safety net — the source list already doesn't include /mnt/* — but doubly-excluded so a careless future edit can't nuke the repo by pulling in 100 TB.

Also excluded: docker internals, logs/pids, per-user browser and shell caches.

No pre-backup hook needed

Same as nh3-docker — no relational DBs on this host. SQLite in agent volumes is WAL-mode + low-traffic; raw restic capture restores cleanly.

Deploy (one-time setup)

1. Install restic (not present on this host)

ssh -t vm-esh-nas 'sudo apt update && sudo apt install -y restic'
# or use the upstream binary if a newer version is needed:
#   curl -sfL https://github.com/restic/restic/releases/latest/download/restic_*_linux_amd64.bz2 | ...

2. Add the client entry to the Anaheim rest-server .htpasswd

If not already present from an earlier pass:

# The repo dir is on NFS from the Debian NAS (10.250.50.50) exported with
# root_squash, so sudo gets denied writes. It is owned by lkraven:lkraven,
# so append as lkraven directly — no sudo needed.
ssh ana-docker '
  docker run --rm httpd:2.4-alpine htpasswd -nbB vm-esh-nas "<PW>" \
    >> /mnt/backup/restic/repo/ana/.htpasswd
'

Heads-up: the password is in your shell history after this runs. Scrub with history -d <line> or history -c.

Sanity check the file ownership afterward:

ssh ana-docker 'ls -la /mnt/backup/restic/repo/ana/.htpasswd'
# expect: -rw------- 1 lkraven lkraven ...

3. Install restic creds on vm-esh-nas

ssh -t vm-esh-nas '
  sudo install -d -o root -g root -m 0700 /etc/restic /var/lib/restic
'

# REST URL — paste from password manager (Enter, Ctrl-D)
ssh -t vm-esh-nas 'sudo bash -c "cat > /etc/restic/restic.env && chmod 600 /etc/restic/restic.env"'
# paste: RESTIC_REPOSITORY=rest:http://vm-esh-nas:<HTPASSWD-PW>@10.250.50.70:8000/vm-esh-nas/

# Encryption passphrase — paste from password manager (Enter, Ctrl-D)
ssh -t vm-esh-nas 'sudo bash -c "cat > /etc/restic/password && chmod 600 /etc/restic/password"'

4. Init the repo

ssh -t vm-esh-nas '
  sudo bash -c "
    set -a; . /etc/restic/restic.env; set +a
    restic init
  "
'
# Type passphrase twice at the prompt — same one you just installed.

5. Verify

ssh -t vm-esh-nas '
  sudo bash -c "
    set -a; . /etc/restic/restic.env; set +a
    RESTIC_PASSWORD_FILE=/etc/restic/password restic snapshots
  "
'
# expect: no snapshots found

6. Install resticprofile

ssh -t vm-esh-nas '
  curl -sfL https://raw.githubusercontent.com/creativeprojects/resticprofile/master/install.sh \
    | sudo sh -s -- -b /usr/local/bin &&
  /usr/local/bin/resticprofile version
'

7. Deploy the profile

scp configs/restic/vm-esh-nas/profiles.yaml vm-esh-nas:/tmp/profiles.yaml

ssh -t vm-esh-nas '
  sudo install -o root -g root -m 0644 /tmp/profiles.yaml /etc/restic/profiles.yaml &&
  rm /tmp/profiles.yaml &&
  sudo resticprofile --config /etc/restic/profiles.yaml show
'

8. Enable timers + first backup

ssh -t vm-esh-nas '
  sudo resticprofile --config /etc/restic/profiles.yaml schedule --all &&
  sudo resticprofile --config /etc/restic/profiles.yaml backup --verbose
'

Expected size: small, likely <500 MB. This host is light — a few agent volumes + compose files + home dirs. If the first snapshot is above 2 GB, check for anything unexpected in /home or /var/lib/docker/volumes before accepting.

Memory ceiling worth watching: vm-esh-nas has only 3.8 GB RAM. The min-memory: 100 global in profiles.yaml already protects against OOM during restic's packing phase, but monitor the first backup for any sign of restic choking on large files.

Restoring

ssh -t vm-esh-nas '
  sudo bash -c "
    set -a; . /etc/restic/restic.env; set +a
    RESTIC_PASSWORD_FILE=/etc/restic/password \
      restic restore --target /tmp/restore latest --path /opt/docker
  "
'

Recreating the repo

Same pattern as ana-ml2 — see configs/restic/ana-ml2/README.md "Recreating the repo" section. Repo path on ana-docker is /mnt/backup/restic/repo/ana/vm-esh-nas/.