commit 9d0039f9e49150fc86e4a7c4dcb3067af438ec28 Author: Eric Renfro Date: Sun Dec 3 02:09:46 2023 -0500 Initial commit :rocket: diff --git a/profiles.toml b/profiles.toml new file mode 100644 index 0000000..17ae95f --- /dev/null +++ b/profiles.toml @@ -0,0 +1,131 @@ +version = "1" + +[global] + # ionice is available on Linux only + ionice = false + ionice-class = 2 + ionice-level = 6 + # priority is using priority class on windows, and "nice" on unixes + priority = "low" + # run 'snapshots' when no command is specified when invoking resticprofile + default-command = "snapshots" + # initialize a repository if none exist at location + initialize = false + # resticprofile won't start a profile if there's less than 100MB of RAM available + min-memory = 100 + +# a group is a profile that will call all profiles one by one +[groups] + # when starting a backup on profile "full-backup", + # it will run the "system" backup profile + full-backup = [ "system" ] + +# Default profile when not specified on the command line (-n or --name) +# There's no default inheritance from the 'default' profile, +# you can use the 'inherit' flag if needed +[default] + # you can use a relative path, it will be relative to the configuration file + repository = "s3:http://mega.home.ld:9000/vm-backups/FIXME/" + #insecure-tls = true + password-file = "key" + initialize = false + # will run these scripts before and after each command (including 'backup') + #run-before = "mount /backup" + #run-after = "umount /backup" + # if a restic command fails, the run-after won't be running + # add this parameter to run the script in case of a failure + #run-after-fail = "umount /backup" + + # add environment variables + [default.env] + TMPDIR = "/tmp" + AWS_DEFAULT_REGION = "ca-east-1" + AWS_ACCESS_KEY_ID = "FIXME" + AWS_SECRET_ACCESS_KEY = "FIXME" + +# New profile named 'home' +[system] + inherit = "default" + initialize = false + # LOCAL lockfile so you cannot run the same profile more than once at a time + # (it's totally independent of the restic locks on the repository) + #lock = "/tmp/resticprofile-home.lock" + + # 'backup' command of profile 'home' + [system.backup] + # files with no path are relative to the configuration file + exclude-file = [ "system-excludes", "excludes" ] + exclude-if-present = [ ".nobackup" ] + exclude-caches = true + one-file-system = false + tag = [ "system" ] + source = [ + "/home", + "/root", + "/etc", + "/var/log", + "/usr/local", + "/var/spool/cron", + "/srv", + "/opt" + ] + # ignore restic warnings when files cannot be read + no-error-on-warning = true + # run every day at midnight + schedule = "03:00" + schedule-permission = "system" + schedule-lock-wait = "2h" + # System Scripts + run-before = [ + "~/.config/resticprofile/scripts/os before" + ] + # Copy to Borgbase: + run-after = [ + "resticprofile system.copy" + ] + # Clean up: + run-finally = [ + "~/.config/resticprofile/scripts/os after" + ] + + lock = "/tmp/resticprofile-system.backup.lock" + + # retention policy for profile home + # retention is a special section that run the "forget" command + # before or after a backup + [system.retention] + before-backup = false + after-backup = true + keep-hourly = 2 + keep-daily = 14 + keep-weekly = 26 + keep-monthly = 12 + keep-within = "3h" + keep-tag = [ "forever" ] + prune = false + # tag can be a boolean ('true' meaning to copy tag set from 'backup') + # or a custom set of tags. + # Default is 'false', meaning that tags are NOT used. + tag = true + # host can be a boolean ('true' meaning current hostname) + # or a string to specify a different hostname + host = true + + [system.prune] + schedule = "Sun 05:00" + schedule-permission = "system" + schedule-lock-wait = "2h" + + [system.copy] + after-backup = true + initialize = true + initialize-copy-chunker-params = true + repository = "rest:https://FIXME.repo.borgbase.com" + password-file = "key" + lock = "/tmp/resticprofile-system.copy.lock" + +[borgbase] + #inherit = "home" + inherit = "default" + initialize = false + repository = "rest:https://FIXME.repo.borgbase.com" diff --git a/scripts/consul b/scripts/consul new file mode 100755 index 0000000..3925e86 --- /dev/null +++ b/scripts/consul @@ -0,0 +1,31 @@ +#!/bin/bash + +restoreDir=/etc/restore +consulDir="$restoreDir/consul" + + +hook_check() { + if [[ -d "$consulDir" ]]; then + rm -rf "$consulDir" || exit 1 + fi +} + +hook_pre() { + hook_check + mkdir -p "$consulDir" || exit 1 + pushd "$restoreDir" || exit 2 + + consul snapshot save "$consulDir/consul.snap" + + popd || exit 2 +} + +hook_post() { + rm -rf "$consulDir" || exit 1 +} + +case "$1" in + before_check) hook_check;; + before_backup) hook_pre;; + after_backup) hook_post;; +esac diff --git a/scripts/flatpak b/scripts/flatpak new file mode 100755 index 0000000..fa1e428 --- /dev/null +++ b/scripts/flatpak @@ -0,0 +1,35 @@ +#!/bin/bash + +restoreDir="/etc/restore" + +hook_pre() { + mkdir -p "$restoreDir" || exit 1 + pushd "$restoreDir" || exit 2 + + which flatpak || exit 0 + + flatpak list --columns=application --app > flatpaks.lst + + cat > restore-flatpak.sh < "${giteaDir}/gitea-dump-${backupDate}.tar.xz" +} + +hook_post() { + rm -rf "$giteaDir" || exit 1 +} + +case "$1" in + before_backup) hook_pre;; + after_backup) hook_post;; +esac diff --git a/scripts/openldap b/scripts/openldap new file mode 100755 index 0000000..bf3032e --- /dev/null +++ b/scripts/openldap @@ -0,0 +1,64 @@ +#!/bin/bash + +restoreDir=/etc/restore +ldapDir="$restoreDir/openldap" + +hook_pre() { + if [[ -d "$ldapDir" ]]; then + rm -rf "$ldapDir" || exit 1 + fi + mkdir -p "$ldapDir" || exit 1 + pushd "$restoreDir" || exit 2 + + slapcat -n 0 -l "$ldapDir/config.ldif" + slapcat -n 1 -l "$ldapDir/data.ldif" + + cat > ldaprestore.sh </dev/null +} + +hook_pre() { + if ! is_bin_in_path aptitude; then + echo "aptitude needs to be installed for backups to work properly." + exit 1 + fi + + if ! is_bin_in_path rsync; then + echo "rsync needs to be installed for backups to work properly." + exit 1 + fi + + mkdir -p "$restoreDir" || exit 1 + pushd "$restoreDir" || exit 2 + + dpkg --get-selections > Package.list + aptitude search --disable-columns -F%p '~i!~M!~v' > InstallOnly.list + #apt-key exportall > /etc/restore/Repo.keys + cp -a /etc/apt/sources.list "$restoreDir/" + rsync -avhHi /etc/apt/sources.list.d "$restoreDir/" + rsync -avhHi /etc/apt/trusted.gpg.d "$restoreDir/" + [[ -d /etc/apt/keyrings ]] && rsync -avhHi /etc/apt/keyrings "$restoreDir/" + + cat > restore.sh </dev/null || install+=" rsync" +dpkg-query -s 'aptitude' &>/dev/null || install+=" aptitude" +dpkg-query -s 'borgbackup' &>/dev/null || install+=" borgbackup" +dpkg-query -s 'borgmatic' &>/dev/null || install+=" borgmatic" +dpkg-query -s 'apt-transport-https' &>/dev/null || install+=" apt-transport-https" + +if [[ -n "\$install" ]]; then + apt -y install \$install +fi + +echo " * Enabling 32-bit packages" +grep ':i386' InstallOnly.list &>/dev/null && dpkg --add-architecture i386 + +echo " * Restoring repositories and keys" +cp -a sources.list /etc/apt/sources.list +rsync --ignore-existing -raz sources.list.d/ /etc/apt/sources.list.d/ +rsync --ignore-existing -raz trusted.gpg.d/ /etc/apt/trusted.gpg.d/ +[[ -d keyrings ]] && rsync --ignore-existing -raz keyrings/ /etc/apt/keyrings/ + +apt update + +failinstall="" +flatpak=0 + +echo " * Gathering installed packages" +#xargs aptitude --schedule-only install < InstallOnly.list +while read p; do + if [[ "\$p" = "flatpak" ]]; then + flatpak=1 + fi + + dpkg-query -s "\$p" &>/dev/null + if [[ "\$?" -eq 1 ]]; then + aptitude --schedule-only install "\$p" + if [[ "\$?" -ne 0 ]]; then + if [[ -z "\$failinstall" ]]; then + failinstall+="\$p" + else + failinstall+=", \$p" + fi + fi + fi +done < InstallOnly.list + +echo "Packages that failed to schedule for install:" +echo "\$failinstall" + +echo " * Restoring installed packages (please confirm)" +aptitude install + +if [[ "\$flatpak" -eq 1 ]]; then + echo " * Adding flatpak repo: Flathub" + flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo +fi + +echo "Packages that failed to schedule for install:" +echo "\$failinstall" +EOF + chmod ug+rx restore.sh + popd || exit 2 +} + +hook_post() { + : +} + + +case "$1" in + before_backup) hook_pre || exit $?;; + after_backup) hook_post || exit $?;; +esac diff --git a/scripts/os_fedora b/scripts/os_fedora new file mode 100755 index 0000000..7b0f1ff --- /dev/null +++ b/scripts/os_fedora @@ -0,0 +1,33 @@ +#!/bin/bash + +restoreDir="/etc/restore" + +hook_pre() { + mkdir -p "$restoreDir" || exit 1 + pushd "$restoreDir" || exit 2 + + rpm -qa | sort > Package.versions.list + rpm -qa --queryformat '%{NAME}.%{ARCH}\n' | sort > Package.list + + cat > restore.sh < "pkglist.txt" + comm -13 <(pacman -Qqdt | sort) <(pacman -Qqdtt | sort) > optdeplist.txt + pacman -Qqem > foreignpkglist.txt + + cat > restore.sh < restore.sh < Packages.list + + popd || exit 2 +} + +hook_post() { + : +} + +case "$1" in + before_backup) hook_pre;; + after_backup) hook_post;; +esac diff --git a/scripts/os_suse b/scripts/os_suse new file mode 100755 index 0000000..4de7eb7 --- /dev/null +++ b/scripts/os_suse @@ -0,0 +1,33 @@ +#!/bin/bash + +restoreDir="/etc/restore" + +hook_pre() { + mkdir -p "$restoreDir" || exit 1 + pushd "$restoreDir" || exit 2 + + rpm -qa | sort > Package.versions.list + rpm -qa --queryformat '%{NAME}\n' | sort > Package.list + + cat > restore.sh <" + exit 1 +fi + +while [ $# -gt 1 ]; do + case $1 in + --args) + runargs=$2 + shift 2 + break + ;; + --list) + list=1 + shift + break + ;; + --test) + test=1 + shift + break + ;; + --) + # -- end of options + shift + break + ;; + *) + # directory + break + ;; + esac +done + +if [ ! -d $1 ]; then + echo "Not a directory: $1" + exit 1 +fi + +if [ -f /etc/sysconfig/run-parts ]; then + . /etc/sysconfig/run-parts +fi + +# Ignore *~ and *, scripts +for i in $(LC_ALL=C; echo ${1%/}/*[^~,]) ; do + [ -d $i ] && continue + # Don't run *.{rpmsave,rpmorig,rpmnew,swp,cfsaved} scripts + [ "${i%.cfsaved}" != "${i}" ] && continue + [ "${i%.rpmsave}" != "${i}" ] && continue + [ "${i%.rpmorig}" != "${i}" ] && continue + [ "${i%.rpmnew}" != "${i}" ] && continue + [ "${i%.swp}" != "${i}" ] && continue + [ "${i%,v}" != "${i}" ] && continue + + # jobs.deny prevents specific files from being executed + # jobs.allow prohibits all non-named jobs from being run. + # can be used in conjunction but there's no reason to do so. + if [ -r $1/jobs.deny ]; then + grep -q "^$(basename $i)$" $1/jobs.deny && continue + fi + if [ -r $1/jobs.allow ]; then + grep -q "^$(basename $i)$" $1/jobs.allow || continue + fi + + if [ -e $i ]; then + if [ -r $1/whitelist ]; then + grep -q "^$(basename $i)$" $1/whitelist && continue + fi + + if [ ${list:-0} = 1 ]; then + echo $i; + elif [ -x $i ]; then + if [ ${test:-0} = 1 ]; then + echo $i; + continue + fi + if [ "$RANDOMIZE" != "" ]; then + let "rtime = $RANDOM" + if [ "$RANDOMTIME" != "" ]; then + let "rtime %= $RANDOMTIME" + else + let "rtime %= 300" + fi + sleep $rtime + fi + + # run executable files + echo "run-parts[$$]" "($1) starting $(basename $i)" + $i $runargs 2>&1 + echo "run-parts[$$]" "($1) finished $(basename $i)" + fi + fi +done + +exit 0 diff --git a/scripts/vaultwarden b/scripts/vaultwarden new file mode 100755 index 0000000..5bd3231 --- /dev/null +++ b/scripts/vaultwarden @@ -0,0 +1,26 @@ +#!/bin/bash + +restoreDir=/etc/restore +vaultwardenDir="$restoreDir/vaultwarden" + +hook_pre() { + if [[ -d "$vaultwardenDir" ]]; then + rm -rf "$vaultwardenDir" || exit 1 + fi + + test -x "$(which sqlite3)" || exit 2 + backupDate=$(date +"%Y-%m-%d") + vaultwardenHome=$(getent passwd vaultwarden | cut -f6 -d:) + + mkdir -p "$vaultwardenDir" + sqlite3 "${vaultwardenHome}/data/db.sqlite3" ".backup '${vaultwardenDir}/db-${backupDate}.sqlite3'" +} + +hook_post() { + rm -rf "$vaultwardenDir" || exit 1 +} + +case "$1" in + before_backup) hook_pre;; + after_backup) hook_post;; +esac