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.
This commit is contained in:
parent
3cdf8b8c98
commit
fe30677a46
|
@ -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 "$@"
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
|||
[Unit]
|
||||
Wants=rclone-push-volume@%i.timer
|
|
@ -0,0 +1,15 @@
|
|||
[Unit]
|
||||
Description=Rclone Pull for Volume %I
|
||||
Wants=[email protected] container-volume@%i.service
|
||||
After=[email protected] 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
|
|
@ -1,15 +0,0 @@
|
|||
[Unit]
|
||||
Description=Rclone Pull for /%I
|
||||
Wants=[email protected]
|
||||
After=[email protected]
|
||||
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
|
|
@ -0,0 +1,14 @@
|
|||
[Unit]
|
||||
Description=Rclone Push for Volume %I
|
||||
Wants=[email protected]
|
||||
After=[email protected]
|
||||
|
||||
[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
|
|
@ -1,5 +1,5 @@
|
|||
[Unit]
|
||||
Description=Scheduled Backup for Container Volume %i
|
||||
Description=Scheduled Rclone Push for Volume %I
|
||||
|
||||
[Timer]
|
||||
OnCalendar=02:00
|
|
@ -1,14 +0,0 @@
|
|||
[Unit]
|
||||
Description=Rclone Push for /%I
|
||||
Wants=[email protected]
|
||||
After=[email protected]
|
||||
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
|
Loading…
Reference in New Issue