Prime bootstrapped infra-ops on vm-esh-nas with playbooks/bootstrap-infra-ops-user.yaml. It got the fleet-pinned uid/gid 850, NOPASSWD sudo with log_output, the docker group and a 0700 home. That let playbooks/restic-repository-file.yaml migrate the last restic host: the live profile matched the repo's pre-change sha, its units no longer carry the URL, its secrets are vaulted, and the live and repo profiles now match (a5ea75ea). All eight restic hosts are clean. The staged helper script is gone, both from Prime's home on the host and from the repo. The docs that described vm-esh-nas as lkraven-only are updated.
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/.