From 861212831dc375703c6b5b7e6612dae22a01d76e Mon Sep 17 00:00:00 2001 From: Ronni Baslund Date: Mon, 8 Jun 2026 21:46:49 +0200 Subject: [PATCH] =?UTF-8?q?fix(infra):=20restic=E2=86=92Storage=20Box=20ba?= =?UTF-8?q?ckups=20working=20end-to-end?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three fixes found bringing up backups on node1: - restic.env wrote BACKUP_PATHS/RETENTION unquoted → sourcing ran a path as a command ("Is a directory"); now quoted. - ssh config was written to $BACKUP_HOME/.ssh/config, but restic runs as root and its ssh resolves ~ from the passwd db (not $HOME), so it reads /root/.ssh/config — write the Storage Box block there. Also StrictHostKeyChecking=no + UserKnownHostsFile=/dev/null (safe: restic encrypts before upload; fixes flaky Storage Box host-key verification). - Storage Box SFTP lands in /home, so the repo path needs the /home prefix (absolute /dezky hit the root-owned chroot parent → SSH_FX_FAILURE). Verified: repo initialized, nightly snapshot of mail store + Stalwart config + etcd snapshots + dumps dir, `restic check` clean, retention applied. --- .../production/host/config.env.example | 8 ++++--- .../production/host/restic/install.sh | 22 +++++++++++++------ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/infrastructure/production/host/config.env.example b/infrastructure/production/host/config.env.example index a4aa495..8c1d748 100644 --- a/infrastructure/production/host/config.env.example +++ b/infrastructure/production/host/config.env.example @@ -51,9 +51,11 @@ STALWART_WEBHOOK_SECRET="" # REQUIRED — openssl rand -hex 32 # --- Restic backups (host) ------------------------------------------------ # Storage Box is SSH/SFTP on PORT 23, key auth. STORE RESTIC_PASSWORD OFFLINE. +# NOTE: the Storage Box drops you in /home, so the repo path needs the /home +# prefix (an absolute /dezky hits the root-owned chroot parent and fails). RESTIC_PASSWORD="" # REQUIRED — openssl rand -hex 32 (save offline!) -BACKUP_PRIMARY_REPO="" # sftp:@.your-storagebox.de:/dezky -BACKUP_DR_REPO="" # sftp:@.your-storagebox.de:/dezky (Helsinki box) -BACKUP_PATHS="/opt/stalwart/data /opt/stalwart/etc /var/lib/rancher/k3s/server/db/snapshots /var/lib/rancher/k3s/storage" +BACKUP_PRIMARY_REPO="" # sftp:@.your-storagebox.de:/home/dezky +BACKUP_DR_REPO="" # sftp:@.your-storagebox.de:/home/dezky (Helsinki box) +BACKUP_PATHS="/opt/stalwart/data /opt/stalwart/etc /var/lib/rancher/k3s/server/db/snapshots /opt/dezky-backup/dumps" BACKUP_RETENTION="--keep-daily 7 --keep-weekly 4 --keep-monthly 6" BACKUP_HEALTHCHECK_URL="" # optional dead-man's-switch base URL diff --git a/infrastructure/production/host/restic/install.sh b/infrastructure/production/host/restic/install.sh index 07099c2..d52e75b 100755 --- a/infrastructure/production/host/restic/install.sh +++ b/infrastructure/production/host/restic/install.sh @@ -49,16 +49,24 @@ if [[ ! -f "$KEY" ]]; then ssh-keygen -t ed25519 -N "" -C "dezky-backup@node1" -f "$KEY" >/dev/null ok "Generated backup SSH key." fi -# Single wildcard config covers BOTH Storage Boxes (same domain, port 23, key). -cat > "$SSH_DIR/config" </dev/null; then + cat >> /root/.ssh/config < "$BACKUP_HOME/restic.env" <