From fe30677a465322e0cc5b5d69f3769ed821ac0382 Mon Sep 17 00:00:00 2001 From: Alex Palaistras Date: Mon, 1 Apr 2024 13:41:32 +0100 Subject: [PATCH] Deprecate generic container volume backup/restore Previously, all container volumes initialized via the `container-volume` service would have local rotating backups performed by pushing `tar` archives to the `/var/lib/backups/coreos-home-server` directory. This proved to be a simple and effective mechanism for storing historic volume state locally; however, the use-case for historic backup is usually data loss, either partial (e.g. by deleting files inadvertently) or complete (e.g. by loss of disk), which is likely better mitigated by more concrete mechanisms of retention. In addition, this need to store historic volume state locally, in its totality, proved to be a barrier for performing partial backups, which is an issue especially for larger volumes. This commit deprecates this simple, generic volume backup/restore mechanism, and instead has us rely directly on Rclone reading from the volume in question. --- host/base/service/container-volume-backup | 52 ------------------- .../systemd/container-volume-backup@.service | 15 ------ .../systemd/container-volume-restore@.service | 16 ------ host/base/systemd/container-volume@.service | 2 - host/virtual/virtual.env | 2 +- .../before-rclone.conf | 3 -- .../before-rclone.conf | 3 -- .../container-volume@.service.d/rclone.conf | 2 + .../systemd/rclone-pull-volume@.service | 15 ++++++ service/rclone/systemd/rclone-pull@.service | 15 ------ .../systemd/rclone-push-volume@.service | 14 +++++ .../rclone/systemd/rclone-push-volume@.timer | 2 +- service/rclone/systemd/rclone-push@.service | 14 ----- 13 files changed, 33 insertions(+), 122 deletions(-) delete mode 100755 host/base/service/container-volume-backup delete mode 100644 host/base/systemd/container-volume-backup@.service delete mode 100644 host/base/systemd/container-volume-restore@.service delete mode 100644 service/rclone/systemd/container-volume-backup@.service.d/before-rclone.conf delete mode 100644 service/rclone/systemd/container-volume-restore@.service.d/before-rclone.conf create mode 100644 service/rclone/systemd/container-volume@.service.d/rclone.conf create mode 100644 service/rclone/systemd/rclone-pull-volume@.service delete mode 100644 service/rclone/systemd/rclone-pull@.service create mode 100644 service/rclone/systemd/rclone-push-volume@.service rename host/base/systemd/container-volume-backup@.timer => service/rclone/systemd/rclone-push-volume@.timer (62%) delete mode 100644 service/rclone/systemd/rclone-push@.service diff --git a/host/base/service/container-volume-backup b/host/base/service/container-volume-backup deleted file mode 100755 index 5f3419f..0000000 --- a/host/base/service/container-volume-backup +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env bash -# -# Archive all files in source directory into destination directory. - -set -euo pipefail - -# Parse command-line arguments. -unset SRCDIR DESTDIR BASENAME - -while getopts 's:d:n:' arg; do - case "${arg}" in - s) SRCDIR="${OPTARG}" ;; - d) DESTDIR="${OPTARG}" ;; - n) BASENAME="${OPTARG}-" ;; - *) echo "Unknown argument '${arg}' given. Exiting." >&2 && exit 1 ;; - esac -done - -# Check and return true if source files are newer than any archive already created. -function archive-should-update() { - local latest="${DESTDIR}/${BASENAME}latest.tar.gz" - - if ! test -e "${latest}"; then - return 0 - elif test "$(find "${SRCDIR}" -type f -newer "${latest}" -print -quit | wc -l)" -gt 0; then - return 0 - fi - - return 1 -} - -# Create compressed archive for source path into destination path for pre-defined, date-based name. -function archive-create() { - local name="${BASENAME}$(date +%w%H)" - - # Create uncompressed archive for source path and compress separately to ensure minimal blocking. - tar --verbose --create --file "${DESTDIR}/${name}.tar" --directory "${SRCDIR}" . - gzip --force "${DESTDIR}/${name}.tar" - - # Point the latest archive to a "special" name for future use. - (cd /backup && ln --symbolic --force "${name}.tar.gz" "${BASENAME}latest.tar.gz") -} - -# Entry-point for script. Create tar archive for source directory into destination directory, checking -# for any changes since last run, and ensuring files are archived correctly for subsequent restore. -function main() { - if archive-should-update "${SRCDIR}" "${DESTDIR}"; then - archive-create "${SRCDIR}" "${DESTDIR}" - fi -} - -main "$@" diff --git a/host/base/systemd/container-volume-backup@.service b/host/base/systemd/container-volume-backup@.service deleted file mode 100644 index cbf1e6e..0000000 --- a/host/base/systemd/container-volume-backup@.service +++ /dev/null @@ -1,15 +0,0 @@ -[Unit] -Description=Backup for Container Volume %I - -[Service] -Type=oneshot -SyslogIdentifier=%N -ExecStartPre=/bin/install --mode 0700 --directory %S/backups/coreos-home-server/%i -ExecStart=/bin/podman run --replace --rm --name %p-%i --entrypoint /opt/container-volume-backup \ - --volume %i:/data:z,ro \ - --volume %E/coreos-home-server/base/service:/opt:z,ro \ - --volume %S/backups/coreos-home-server/%i:/backup:z \ - docker.io/debian:bullseye-slim -s /data -d /backup -n "%i" - -[Install] -WantedBy=multi-user.target diff --git a/host/base/systemd/container-volume-restore@.service b/host/base/systemd/container-volume-restore@.service deleted file mode 100644 index ce02c42..0000000 --- a/host/base/systemd/container-volume-restore@.service +++ /dev/null @@ -1,16 +0,0 @@ -[Unit] -Description=Restore from Backup for Container Volume %I -ConditionFileNotEmpty=%S/backups/coreos-home-server/%i/%i-latest.tar.gz - -[Service] -Type=oneshot -SyslogIdentifier=%N -ExecStart=/bin/podman run --replace --rm --name %p-%i --entrypoint /bin/bash \ - --volume %i:/data:z \ - --volume %S/backups/coreos-home-server/%i:/backup:z,ro \ - docker.io/debian:bullseye-slim -c \ - 'test -n "$(ls -A /data)" && echo "Volume %i is not empty, skipping." && exit 0; \ - tar --verbose --extract --file "/backup/%i-latest.tar.gz" --directory /data' - -[Install] -WantedBy=multi-user.target diff --git a/host/base/systemd/container-volume@.service b/host/base/systemd/container-volume@.service index ab83847..71d3eb5 100644 --- a/host/base/systemd/container-volume@.service +++ b/host/base/systemd/container-volume@.service @@ -1,7 +1,5 @@ [Unit] Description=Container Volume for %I -Wants=container-volume-restore@%i.service container-volume-backup@%i.timer -After=container-volume-restore@%i.service [Service] Type=oneshot diff --git a/host/virtual/virtual.env b/host/virtual/virtual.env index 77f6008..c41b669 100644 --- a/host/virtual/virtual.env +++ b/host/virtual/virtual.env @@ -37,7 +37,7 @@ RSPAMD_CONTROLLER_PASSWORD=password # Configuration for Rclone. RCLONE_REMOTE_TYPE=local -RCLONE_REMOTE_PATH=/data/rclone +RCLONE_REMOTE_PATH=/local RCLONE_CRYPT_PASSWORD=3NYQAySloaAVy4CxtVkAset0mz9KDlhT RCLONE_CRYPT_SALT=jqsQXp_MPwBPIzw69TkmSp7ScuA diff --git a/service/rclone/systemd/container-volume-backup@.service.d/before-rclone.conf b/service/rclone/systemd/container-volume-backup@.service.d/before-rclone.conf deleted file mode 100644 index c1c10e2..0000000 --- a/service/rclone/systemd/container-volume-backup@.service.d/before-rclone.conf +++ /dev/null @@ -1,3 +0,0 @@ -[Unit] -Wants=rclone-push@var-lib-backups-coreos\x2dhome\x2dserver-%i.service -Before=rclone-push@var-lib-backups-coreos\x2dhome\x2dserver-%i.service diff --git a/service/rclone/systemd/container-volume-restore@.service.d/before-rclone.conf b/service/rclone/systemd/container-volume-restore@.service.d/before-rclone.conf deleted file mode 100644 index 62f2376..0000000 --- a/service/rclone/systemd/container-volume-restore@.service.d/before-rclone.conf +++ /dev/null @@ -1,3 +0,0 @@ -[Unit] -Wants=rclone-pull@var-lib-backups-coreos\x2dhome\x2dserver-%i.service -Before=rclone-pull@var-lib-backups-coreos\x2dhome\x2dserver-%i.service diff --git a/service/rclone/systemd/container-volume@.service.d/rclone.conf b/service/rclone/systemd/container-volume@.service.d/rclone.conf new file mode 100644 index 0000000..c59a21a --- /dev/null +++ b/service/rclone/systemd/container-volume@.service.d/rclone.conf @@ -0,0 +1,2 @@ +[Unit] +Wants=rclone-push-volume@%i.timer diff --git a/service/rclone/systemd/rclone-pull-volume@.service b/service/rclone/systemd/rclone-pull-volume@.service new file mode 100644 index 0000000..8b1e47d --- /dev/null +++ b/service/rclone/systemd/rclone-pull-volume@.service @@ -0,0 +1,15 @@ +[Unit] +Description=Rclone Pull for Volume %I +Wants=container-build@rclone.service container-volume@%i.service +After=container-build@rclone.service container-volume@%i.service + +[Service] +Type=oneshot +SyslogIdentifier=%N +Environment=SOURCE=crypt:%i +ExecCondition=/bin/bash -c 'test -n "$(ls --almost-all $(podman volume mount %i))"; status=$?; podman volume unmount %i; exit $status' +ExecStartPre=/bin/install --mode 0700 -d %S/backups/coreos-home-server/%i +ExecStart=/bin/podman run --rm --env-file %E/coreos-home-server/rclone/rclone.env --user root --volume %i:/mnt:z --volume %S/backups/coreos-home-server/%i:/local:z localhost/rclone:latest sync ${SOURCE} /mnt + +[Install] +WantedBy=multi-user.target diff --git a/service/rclone/systemd/rclone-pull@.service b/service/rclone/systemd/rclone-pull@.service deleted file mode 100644 index 56dd178..0000000 --- a/service/rclone/systemd/rclone-pull@.service +++ /dev/null @@ -1,15 +0,0 @@ -[Unit] -Description=Rclone Pull for /%I -Wants=container-build@rclone.service -After=container-build@rclone.service -ConditionDirectoryNotEmpty=!/%I - -[Service] -Type=oneshot -SyslogIdentifier=%N -Environment=SOURCE=crypt:%i -ExecStartPre=/bin/install --mode 0700 -d /%I -ExecStart=/bin/podman run --rm --env-file %E/coreos-home-server/rclone/rclone.env --user root --volume /%I:/data:z localhost/rclone:latest sync ${SOURCE} /data - -[Install] -WantedBy=multi-user.target diff --git a/service/rclone/systemd/rclone-push-volume@.service b/service/rclone/systemd/rclone-push-volume@.service new file mode 100644 index 0000000..5134b81 --- /dev/null +++ b/service/rclone/systemd/rclone-push-volume@.service @@ -0,0 +1,14 @@ +[Unit] +Description=Rclone Push for Volume %I +Wants=container-build@rclone.service +After=container-build@rclone.service + +[Service] +Type=oneshot +SyslogIdentifier=%N +Environment=DESTINATION=crypt:%i +ExecStartPre=/bin/install --mode 0700 -d %S/backups/coreos-home-server/%i +ExecStart=/bin/podman run --rm --env-file %E/coreos-home-server/rclone/rclone.env --user root --volume %i:/mnt:z,ro --volume %S/backups/coreos-home-server/%i:/local:z localhost/rclone:latest sync /mnt ${DESTINATION} + +[Install] +WantedBy=multi-user.target diff --git a/host/base/systemd/container-volume-backup@.timer b/service/rclone/systemd/rclone-push-volume@.timer similarity index 62% rename from host/base/systemd/container-volume-backup@.timer rename to service/rclone/systemd/rclone-push-volume@.timer index f7f87ab..1d6cd91 100644 --- a/host/base/systemd/container-volume-backup@.timer +++ b/service/rclone/systemd/rclone-push-volume@.timer @@ -1,5 +1,5 @@ [Unit] -Description=Scheduled Backup for Container Volume %i +Description=Scheduled Rclone Push for Volume %I [Timer] OnCalendar=02:00 diff --git a/service/rclone/systemd/rclone-push@.service b/service/rclone/systemd/rclone-push@.service deleted file mode 100644 index 862eb07..0000000 --- a/service/rclone/systemd/rclone-push@.service +++ /dev/null @@ -1,14 +0,0 @@ -[Unit] -Description=Rclone Push for /%I -Wants=container-build@rclone.service -After=container-build@rclone.service -ConditionDirectoryNotEmpty=/%I - -[Service] -Type=oneshot -SyslogIdentifier=%N -Environment=DESTINATION=crypt:%i -ExecStart=/bin/podman run --rm --env-file %E/coreos-home-server/rclone/rclone.env --user root --volume /%I:/data:z localhost/rclone:latest sync /data ${DESTINATION} - -[Install] -WantedBy=multi-user.target