# esh-ml1 restic: backs up augaman's face gallery (and the deployed compose dir) # to rest-server-ana. Config + rationale: configs/restic/esh-ml1/. # # Run: scripts/elway esh-ml1 --playbook playbooks/esh-ml1-restic.yaml # # PRE-REQUISITE, NOT DONE HERE (secrets never live in this repo): seed the two # root-only secret files from the vault, and the rest-server-ana htpasswd entry # for user `esh-ml1`. The exact commands are in configs/restic/esh-ml1/README.md. # The "Secrets are seeded" step below halts the run if they are missing. # # Idempotent: a second run should report ok/skipped everywhere except the # re-uploads and the schedule refresh. vars: resticprofile_version: 0.33.1 resticprofile_sha256: 5fecd20de21811a750a4d61e841b2258fdf018bbfffad136c96078df27b452df steps: - name: Install restic (Debian 12 package, 0.14.0, same as esh-docker-vm and esh-vm-db) sudo: true shell: DEBIAN_FRONTEND=noninteractive apt-get install -y -q restic when: "! command -v restic >/dev/null" - name: Install resticprofile {{ resticprofile_version }} (pinned, sha256-checked) sudo: true shell: | set -eu tmp=$(mktemp -d) trap 'rm -rf "$tmp"' EXIT tgz="resticprofile_{{ resticprofile_version }}_linux_amd64.tar.gz" curl -fsSL -o "$tmp/$tgz" "https://github.com/creativeprojects/resticprofile/releases/download/v{{ resticprofile_version }}/$tgz" echo "{{ resticprofile_sha256 }} $tmp/$tgz" | sha256sum -c - tar -xzf "$tmp/$tgz" -C "$tmp" resticprofile install -o root -g root -m 0755 "$tmp/resticprofile" /usr/local/bin/resticprofile when: "! /usr/local/bin/resticprofile version 2>/dev/null | grep -q 'version {{ resticprofile_version }} '" - name: Directories (stage is root-only; its augaman subdir belongs to the container user 10001) sudo: true shell: | set -eu install -d -o root -g root -m 0755 /etc/restic install -d -o root -g root -m 0700 /var/lib/restic/stage install -d -o 10001 -g 10001 -m 0700 /var/lib/restic/stage/augaman when: "! sudo -n sh -c 'test \"$(stat -c %U:%a /var/lib/restic/stage)\" = root:700 && test \"$(stat -c %u:%a /var/lib/restic/stage/augaman)\" = 10001:700 && test -d /etc/restic'" - name: Secrets are seeded (password + repository, root 0400) sudo: true shell: | set -eu for f in /etc/restic/password /etc/restic/repository; do test -s "$f" || { echo "missing $f: seed it from the vault (configs/restic/esh-ml1/README.md)"; exit 1; } test "$(stat -c %U:%a "$f")" = root:400 || { echo "$f must be root 0400"; exit 1; } done changed_when: "false" - name: restic understands --repository-file shell: restic --help | grep -q -- --repository-file changed_when: "false" - name: Upload profiles.yaml sudo: true upload: src: configs/restic/esh-ml1/profiles.yaml dest: /etc/restic/profiles.yaml mode: "0644" - name: Upload pre-backup.sh sudo: true upload: src: configs/restic/esh-ml1/pre-backup.sh dest: /etc/restic/pre-backup.sh mode: "0755" - name: Initialise the repository (once) sudo: true shell: resticprofile --no-ansi --config /etc/restic/profiles.yaml --name default init when: "! sudo -n restic --repository-file /etc/restic/repository --password-file /etc/restic/password cat config >/dev/null 2>&1" - name: Install the systemd timers sudo: true shell: resticprofile --no-ansi --config /etc/restic/profiles.yaml --name default schedule verify: - name: Backup and check timers are active shell: systemctl is-active --quiet resticprofile-backup@profile-default.timer && systemctl is-active --quiet resticprofile-check@profile-default.timer changed_when: "false" # The units must EXIST before "no match" means anything: a grep over a path that # is not there also "finds nothing". `rest:http` is the exact form the leak takes # on the env-file hosts (seen in esh-docker-vm's unit, 2026-09-27). - name: No repository URL (and so no rest-server password) in the generated units shell: | set -eu d=/etc/systemd/system for u in resticprofile-backup@profile-default.service resticprofile-check@profile-default.service; do test -f "$d/$u" || { echo "missing unit $u"; exit 1; } if grep -q 'rest:http' "$d/$u"; then echo "$u embeds the repository URL"; exit 1; fi done changed_when: "false" - name: pre-backup.sh parses shell: bash -n /etc/restic/pre-backup.sh changed_when: "false"