aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--manifests/borg.pp4
-rw-r--r--templates/borg.sh.erb70
-rw-r--r--templates/duplicity.sh.erb2
3 files changed, 67 insertions, 9 deletions
diff --git a/manifests/borg.pp b/manifests/borg.pp
index a1d82e8..39d4576 100644
--- a/manifests/borg.pp
+++ b/manifests/borg.pp
@@ -7,7 +7,9 @@ define backup::borg(
$user = $::hostname,
$host = "${title}.${::domain}",
$encryption = 'repokey',
- $keyfile = '',
+ $keyfile = '${title}',
+ $gpgkey = false,
+ $gpgpass = false,
$order = 95,
$periodic_check = absent,
$password,
diff --git a/templates/borg.sh.erb b/templates/borg.sh.erb
index 736ad4f..f64cf4e 100644
--- a/templates/borg.sh.erb
+++ b/templates/borg.sh.erb
@@ -1,29 +1,42 @@
#!/bin/bash
+#
+# Borg backup procedure for Backupninja
# Adapted from https://borgbackup.readthedocs.io/en/stable/quickstart.html#automating-backups
+#
+# Parameters
export SSH_SERVER="<%= @user %>@<%= @host %>"
export SSH_PORT="<%= @port %>"
-
export HOSTNAME=`cat /etc/hostname`
+# Set the repository
# Setting this, so the repo does not need to be given on the commandline:
export BORG_REPO=ssh://$SSH_SERVER:$SSH_PORT//var/backups/remote/$HOSTNAME/borg
+# Set the passphrase
# Setting this, so you won't be asked for your repository passphrase:
export BORG_PASSPHRASE='<%= @password %>'
-# or this to ask an external program to supply the passphrase:
+
+# Optional OpenPGP encryption for the keyfile
+GPG_KEY="<%= @gpgkey %>"
+GPG_PASS='<%= @gpgpass %>'
+
+# Setting the password command
+# This allows to ask an external program to supply the passphrase:
#export BORG_PASSCOMMAND='pass show backup'
# Custom keyfile support
if [ "<%= @encryption %>" == "keyfile" ] && [ ! -z "<%= @keyfile %>" ]; then
- if [ ! -e "<%= @keyfile %>" ]; then
- fatal "Keyfile not found: <%= @keyfile %>. Please create it manually."
- fi
+ # Borg does not support providing a pre-generate key file anymore
+ # Details at https://github.com/borgbackup/borg/issues/7047
+ #if [ ! -e "<%= @keyfile %>" ]; then
+ # fatal "Keyfile not found: <%= @keyfile %>. Please create it manually."
+ #fi
export BORG_KEY_FILE="<%= @keyfile %>"
fi
-# some helpers and error handling:
+# Error handling
#info() { printf "\n%s %s\n\n" "$( date )" "$*" >&2; }
trap 'info $( date ) Backup interrupted >&2; exit 2' INT TERM
@@ -82,9 +95,11 @@ info "Pruning repository..."
# limit prune's operation to this machine's archives and not apply to
# other machines' archives also:
+# Warning: "--prefix" has been deprecated. Use "--glob-archives 'yourprefix*'" (-a) instead.
+#--prefix '{hostname}-' \
borg prune \
--list \
- --prefix '{hostname}-' \
+ --glob-archives '{hostname}-*' \
--show-rc \
--keep-daily <%= @keepdaily %> \
--keep-weekly <%= @keepweekly %> \
@@ -96,6 +111,43 @@ borg prune \
# fatal "Error pruning repository"
#fi
+# Have an OpenPGP-encrypted copy of the keyfile
+#
+# This is not ideal, but it's the workaround for configuration management.
+#
+# Borg does not support using pre-generated keys anymore (as of 2024-05-16), so
+# we need an alternative way to access the repository keys if the original
+# system becomes unavailable.
+#
+# The solution is to OpenPGP-encrypt the key file and upload it to the server,
+# assuming that the operators have pre-generated the OpenPGP key and have a copy
+# of it. They can use the same OpenPGP key used for Duplicity backups.
+#
+# The level of protection for the key will then be as strong as the OpenPGP key.
+#
+# Check also https://github.com/borgbackup/borg/issues/7047
+# https://borgbackup.readthedocs.io/en/latest/faq.html#how-important-is-the-home-config-borg-directory
+if [ "<%= @encryption %>" == "keyfile" ] && [ ! -z "<%= @keyfile %>" ]; then
+ if [ ! -z "$GPG_KEY" ] && [ ! -z "$GPG_PASS" ]; then
+ info "Backing up the OpenPGP-encrypted repository key into the remote destination..."
+
+ echo $GPG_PASS | gpg --passphrase-fd 0 --armor --encrypt \
+ --recipient $GPG_KEY --default-key \
+ --output $BORG_KEY_FILE.asc \
+ --yes \
+ $GPG_KEY $BORG_KEY_FILE
+
+ gpg_exit=$?
+
+ chmod 600 $BORG_KEY_FILE.asc
+
+ scp -o Port=$SSH_PORT $BORG_KEY_FILE.asc \
+ $SSH_SERVER:/var/backups/remote/$HOSTNAME/borg/keyfile.asc
+
+ gpg_copy_exit=$?
+ fi
+fi
+
# Use highest exit code as global exit code
global_exit=$(( backup_exit > prune_exit ? backup_exit : prune_exit ))
@@ -110,3 +162,7 @@ fi
if [ "${global_exit}" != "0" ]; then
fatal "Error completing borg action: exit code ${global_exit}"
fi
+
+if [ "${gpg_exit}" != "0" ] || [ "${gpg_copy_exit}" != "0" ]; then
+ fatal "Error backing the GPG-encrypted copy of the keyfile into the remote repository"
+fi
diff --git a/templates/duplicity.sh.erb b/templates/duplicity.sh.erb
index 846f9de..bd03808 100644
--- a/templates/duplicity.sh.erb
+++ b/templates/duplicity.sh.erb
@@ -41,7 +41,7 @@ else
# it's important to let $EXCLUDE come before $INCLUDE to
# have greater precedence; see duplicity(1) for more info
- duplicity -v6 --full-if-older-than $FULL_IF_OLDER_THAN \
+ duplicity --full-if-older-than $FULL_IF_OLDER_THAN \
--tempdir $TMP --encrypt-key $ENCRYPT_KEY --sign-key $SIGN_KEY \
--exclude $TMP $EXCLUDE $INCLUDE --exclude '**' / file:////$BACKUP_FOLDER