aboutsummaryrefslogtreecommitdiffstats
path: root/templates
diff options
context:
space:
mode:
authorJan Tuomi <jan@jantuomi.fi>2025-09-30 10:33:29 +0300
committerJan Tuomi <jan@jantuomi.fi>2025-09-30 10:33:29 +0300
commit2d60e237ca3d21ba48f3fcbd7d94b7c597282049 (patch)
treec76fc322ea69dc5563401c64706d34efe1aadc94 /templates
parentd9ce013dda51ad1a1905e2acc7476ea1744be6e0 (diff)
Implement daily backups
Diffstat (limited to 'templates')
-rw-r--r--templates/etc_crontab.j23
-rw-r--r--templates/usr_local_bin_backup.sh.j248
2 files changed, 51 insertions, 0 deletions
diff --git a/templates/etc_crontab.j2 b/templates/etc_crontab.j2
index a6c48e4..6632294 100644
--- a/templates/etc_crontab.j2
+++ b/templates/etc_crontab.j2
@@ -23,3 +23,6 @@ PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
# Update dynamic DNS
*/1 * * * * root logto -e /var/log/do_dyndns.err /usr/local/bin/do_dyndns.sh
+
+# Take backups every day at 3:05 AM
+5 3 * * * root logto /var/log/backup /usr/local/bin/backup
diff --git a/templates/usr_local_bin_backup.sh.j2 b/templates/usr_local_bin_backup.sh.j2
new file mode 100644
index 0000000..1286b93
--- /dev/null
+++ b/templates/usr_local_bin_backup.sh.j2
@@ -0,0 +1,48 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+KEYFILE="/root/.ssh/backup"
+DATASET="{{ backup_zfs_dataset }}"
+USER="{{ backup_ssh_user }}"
+HOST="{{ backup_ssh_host }}"
+KEEP=10
+
+# END OF CONFIG
+
+HOST_DIR=backup
+DATE="$(date +%Y-%m-%d-%H-%M-%S%z | tr '+' '-')"
+SNAPSHOT="${DATASET}@${DATE}"
+TARGET="${HOST}/${HOST_DIR}/${SNAPSHOT}.enc"
+
+echo "Taking snapshot \"$SNAPSHOT\""
+(set -x; zfs snapshot "$SNAPSHOT")
+
+echo "Snapshot created"
+echo "Encrypting snapshot and backing up to target \"${TARGET}\""
+
+(set -x; zfs send "$SNAPSHOT" | age -e -i "$KEYFILE" | curl --key "$KEYFILE" -u ${USER}: -T - "sftp://${TARGET}")
+
+echo "Getting listing of existing backups"
+# Note: sorting only produces a time-ordered list inside one timezone
+# This is fine because we're only taking a snapshot every day, so the timezone issue is not relevant
+BACKUPS=$(set -x; echo "ls ${HOST_DIR}" | sftp -i "${KEYFILE}" "${USER}@${HOST}" 2>/dev/null | tail -n +2 | sort)
+COUNT=$(set -x; echo $BACKUPS | wc -w | awk '{print $1}')
+
+if [ ! "$COUNT" -gt "$KEEP" ]; then
+ echo "Acceptable number of backups on remote, no need to prune"
+ echo "Done"
+ exit 0
+fi
+
+echo "Pruning old backups, keeping latest ${KEEP}"
+for BACKUP in $BACKUPS; do
+ if [ ! "$COUNT" -gt "$KEEP" ]; then
+ echo "Acceptable number of backups on remote, no need to prune"
+ break
+ fi
+
+ (set -x; echo "rm ${BACKUP}" | sftp -i "${KEYFILE}" "${USER}@${HOST}")
+ COUNT=$((COUNT - 1))
+done
+
+echo "Done"