#!/usr/bin/env bash
# SPDX-FileCopyrightText: 2022 Patrick Spek
#
# SPDX-License-Identifier: AGPL-3.0-or-later
subcommand() {
# Retrieve the passphrase used by Borg
BORG_PASSPHRASE="$(config "bashtard.backup.key")"
if [[ -z "$BORG_PASSPHRASE" ]]
then
emerg "$BASHTARD_NAME/backup" "No backup key configured"
return 3
fi
export BORG_PASSPHRASE
# Run backups for all configured elements, if none were explicitly
# specified
if (( $# < 1 ))
then
debug "$BASHTARD_NAME/backup" "Retrieving elements from config"
while read -r element
do
set -- "$@" "$(config "$element")"
done < <(config_subkeys "bashtard.backup.elements")
fi
# If there are still no configured elements, this is a good time to
# return an error instead
if (( $# < 1 ))
then
emerg "$BASHTARD_NAME/backup" "No elements to back up"
return 3
fi
# Loop over all repositories, and run backup functions for each of them
while read -r key
do
index="$(awk -F. '{ print $NF }' <<< "$key")"
for element in "$@"
do
"backup_$element" "$index"
done
info "$BASHTARD_NAME/backup/$index" "Backups completed"
done < <(config_subkeys "bashtard.backup.repositories")
}
backup_filesystem() {
local index=$1 ; shift
local borg
local cmd_create
local cmd_prune
local indexes
borg="$(config "bashtard.backup.borg.command" "borg")"
remote="$(config "bashtard.backups.borg.remote_paths.$index" "borg")"
repo="$(config "bashtard.backup.repositories.$index")"
if ! command -v "$borg" > /dev/null 2>&1
then
emerg "$BASHTARD_NAME/backup/$index" "The backup command depends on '$borg' being installed and available in your \$PATH"
return 4
fi
# Prune old backups
info "$BASHTARD_NAME/backup/$index" "Pruning filesystem backups in $repo"
cmd_prune=(
"$borg" "prune"
"--keep-daily" "$(config "bashtard.backup.keep.daily" 7)"
"--keep-weekly" "$(config "bashtard.backup.keep.weekly" 4)"
"--keep-monthly" "$(config "bashtard.backup.keep.monthly" 6)"
"--keep-yearly" "$(config "bashtard.backup.keep.yearly" 1)"
"--prefix" "{fqdn}-"
"--remote-path" "$remote"
"$repo/hostfs"
)
notice "$BASHTARD_NAME/backup/$index" "> ${cmd_prune[*]}"
${cmd_prune[@]}
# Create new backups
info "$BASHTARD_NAME/backup/$index" "Writing new filesystem backup to $repo"
cmd_create=(
"$borg" "create"
"--one-file-system"
"--remote-path" "$remote"
"$repo/hostfs::{fqdn}-$(datetime)"
)
# Add all paths to the command
while read -r path
do
cmd_create+=("$(config "$path")")
done < <(config_subkeys "bashtard.backup.fs.paths")
notice "$BASHTARD_NAME/backup/$index" "> ${cmd_create[*]}"
${cmd_create[@]}
}
backup_database_postgresql() {
local index=$1 ; shift
local borg
local remote
local repo
if ! command -v "psql" > /dev/null 2>&1
then
emerg "$BASHTARD_NAME/backup/$index" "The backup command depends on 'psql' being installed and available in your \$PATH"
return 4
fi
if ! command -v "pg_dump" > /dev/null 2>&1
then
emerg "$BASHTARD_NAME/backup/$index" "The backup command depends on 'pg_dump' being installed and available in your \$PATH"
return 4
fi
PGPASSWORD="$(config "bashtard.backup.db.postgresql.password" "")"
PGUSER="$(config "bashtard.backup.db.postgresql.user" "postgres")"
borg="$(config "bashtard.backup.borg.command" "borg")"
remote="$(config "bashtard.backups.borg.remote_paths.$index" "borg")"
repo="$(config "bashtard.backup.repositories.$index")"
[[ $PGPASSWORD == "" ]] && export PGPASSWORD
export PGUSER
while read -r database
do
[[ $database == "postgres" ]] && continue
[[ $database =~ template* ]] && continue
# Prune old backups
info "$BASHTARD_NAME/backup/$index" "Pruning PostgreSQL backups of $database in $repo"
$borg prune \
--keep-daily "$(config "bashtard.backup.keep.daily" 7)" \
--keep-weekly "$(config "bashtard.backup.keep.weekly" 4)" \
--keep-monthly "$(config "bashtard.backup.keep.monthly" 6)" \
--keep-yearly "$(config "bashtard.backup.keep.yearly" 1)" \
--prefix "$database-" \
--remote-path "$remote" \
"$repo/postgresql-$database"
# Create new backups
info "$BASHTARD_NAME/backup/$index" "Writing new PostgreSQL backup of $database to $repo"
pg_dump "$database" \
| borg create \
--remote-path "$remote" \
"$repo/postgresql-$database::$database-$(datetime)"
done < <(psql -AXt -d template1 -c "SELECT datname FROM pg_database")
}