From 229cee2f318b95ad28a7b0998ff7b1bca9429739 Mon Sep 17 00:00:00 2001 From: Ducky Date: Tue, 15 Aug 2023 04:49:27 +0100 Subject: [PATCH] various --- .gitignore | 12 ++ etc/systemd/system/sh.zio.backup.service | 7 + .../{zio-backup.timer => sh.zio.backup.timer} | 5 +- etc/systemd/system/zio-backup.service | 7 - usr/local/bin/sh.zio.backup | 199 ++++++++++++++++++ usr/local/bin/zio-backup | 25 ++- usr/local/libexec/zio/helpers/bash.sh | 116 ++++++++++ 7 files changed, 350 insertions(+), 21 deletions(-) create mode 100644 etc/systemd/system/sh.zio.backup.service rename etc/systemd/system/{zio-backup.timer => sh.zio.backup.timer} (53%) delete mode 100644 etc/systemd/system/zio-backup.service create mode 100755 usr/local/bin/sh.zio.backup create mode 100644 usr/local/libexec/zio/helpers/bash.sh diff --git a/.gitignore b/.gitignore index 235367d..64fc86a 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,8 @@ # /etc/systemd/system/ !/etc/systemd/system/ /etc/systemd/system/* +!/etc/systemd/system/sh.zio.backup.service +!/etc/systemd/system/sh.zio.backup.timer !/etc/systemd/system/zio-backup.service !/etc/systemd/system/zio-backup.timer @@ -41,6 +43,7 @@ # /usr/local/bin/ !/usr/local/bin/ /usr/local/bin/* +!/usr/local/bin/sh.zio.backup !/usr/local/bin/zio-backup !/usr/local/bin/zio-libvirt-port-forward !/usr/local/bin/zio-update-caddy @@ -50,3 +53,12 @@ !/usr/local/libexec/ /usr/local/libexec/* !/usr/local/libexec/zio-helpers + +# /usr/local/libexec/zio/ +!/usr/local/libexec/zio/ +/usr/local/libexec/zio/* + +# /usr/local/libexec/zio/helpers/ +!/usr/local/libexec/zio/helpers/ +/usr/local/libexec/zio/helpers/* +!/usr/local/libexec/zio/helpers/bash.sh diff --git a/etc/systemd/system/sh.zio.backup.service b/etc/systemd/system/sh.zio.backup.service new file mode 100644 index 0000000..4497f65 --- /dev/null +++ b/etc/systemd/system/sh.zio.backup.service @@ -0,0 +1,7 @@ +[Unit] +Description=sh.zio.backup + +[Service] +User=root +Group=root +ExecStart=/usr/local/bin/sh.zio.backup diff --git a/etc/systemd/system/zio-backup.timer b/etc/systemd/system/sh.zio.backup.timer similarity index 53% rename from etc/systemd/system/zio-backup.timer rename to etc/systemd/system/sh.zio.backup.timer index da9650c..4230345 100644 --- a/etc/systemd/system/zio-backup.timer +++ b/etc/systemd/system/sh.zio.backup.timer @@ -1,10 +1,9 @@ [Unit] -Description=Zio Backup (daily) +Description=sh.zio.backup [Timer] -OnCalendar=daily +OnCalendar=*-*-* 03:00 AccuracySec=1m -RandomizedDelaySec=1h Persistent=true [Install] diff --git a/etc/systemd/system/zio-backup.service b/etc/systemd/system/zio-backup.service deleted file mode 100644 index be5f232..0000000 --- a/etc/systemd/system/zio-backup.service +++ /dev/null @@ -1,7 +0,0 @@ -[Unit] -Description=Zio Backup - -[Service] -User=root -Group=root -ExecStart=/usr/local/bin/zio-backup diff --git a/usr/local/bin/sh.zio.backup b/usr/local/bin/sh.zio.backup new file mode 100755 index 0000000..fbff5ff --- /dev/null +++ b/usr/local/bin/sh.zio.backup @@ -0,0 +1,199 @@ +#!/usr/bin/env bash + +if [[ "$(realpath "$(dirname "$(realpath -s "$0")")/../../../")" == "/" ]]; then + . /usr/local/libexec/zio/helpers/bash.sh +else + . "$(dirname "$(realpath -s "$0")")/../libexec/zio/helpers/bash.sh" +fi + +backup_scripts_dir="$(get_config_dir "sh.zio.backup")/scripts" +cache_dir="/var/cache/sh.zio.backup/restic" +secrets_dir="$(get_config_dir "sh.zio.backup")/secrets" +host="$(hostname -s)" +restic_path="" +restic_repo_file="$secrets_dir/restic-repo" +restic_repo_passwd_file="$secrets_dir/restic-repo-passwd" + +function download_restic() { + restic_version="$1" + + restic_download_url="https://github.com/restic/restic/releases/download/v${restic_version}/restic_${restic_version}_linux_amd64.bz2" + restic_path="/tmp/restic-$restic_version" + restic_archive_path="${restic_path}_$(date +%s).${restic_download_url##*.}" + + say info "Downloading Restic ($restic_version)..." + + rm -f "$restic_path" + + curl -L -s -o "$restic_archive_path" "$restic_download_url" + bzip2 -dc "$restic_archive_path" > "$restic_path" + rm -f "$restic_archive_path" + + chmod +x "$restic_path" + + if [[ ! "$(echo "$("$restic_path" version)")" == "restic $restic_version"* ]]; then + die "Unexpected output from '$restic_path version'" + fi +} + +function invoke_restic() { + command="$1" + args="${@:2}" + + case "$(cat "$restic_repo_file")" in + "b2"*) + b2_account_id_file="$secrets_dir/b2-account-id" + b2_account_key_file="$secrets_dir/b2-account-key" + + test_file "$b2_account_id_file" + test_file "$b2_account_key_file" + + export B2_ACCOUNT_ID="$(cat "$b2_account_id_file")" + export B2_ACCOUNT_KEY="$(cat "$b2_account_key_file")" + ;; + *) + die "Repository unsupported ("$(cat "$restic_repo_file")")" + ;; + esac + + + if [[ -z $command ]]; then + say warning "No command specified. Not running" + elif [[ $command == "self-update" ]]; then + say warning "Command 'self-update' not supported. Not running" + else + "$restic_path" \ + --cache-dir "$cache_dir" \ + --cleanup-cache \ + --password-file "$restic_repo_passwd_file" \ + --repo "$(cat $restic_repo_file)" \ + $command $args + fi +} + +function backup_dir() { + path="$1" + args="${@:2}" + + if [[ ! -d "$path" ]]; then + say warning "'$path' does not exist. Not backing up" + else + say info "Backing up: $path ➔ $(cat $restic_repo_file)" + + invoke_restic \ + backup \ + --iexclude "__MACOSX" \ + --iexclude ".cache" \ + --iexclude ".DS_Store" \ + --iexclude "cache" \ + --iexclude "CachedData" \ + --iexclude "CachedExtensionVSIXs" \ + --iexclude "Code Cache" \ + --iexclude "GPUCache" \ + --iexclude "GrSharedCache" \ + --iexclude "ShaderCache" \ + --iexclude "system-cache" \ + --iexclude "thumbs.db" \ + --iexclude "tmp" \ + --exclude "containers/storage/overlay" \ + --exclude "containers/storage/overlay-containers" \ + --exclude "containers/storage/overlay-images" \ + --exclude "containers/storage/overlay-layers" \ + --exclude-if-present ".nobackup" \ + --host "$host" \ + $args "$path" + fi +} + +function forget_backup() { + timeframe="$1" + + if [[ -z $timeframe ]]; then + timeframe="0y0m7d0h" + fi + + say info "Forgetting: $timeframe ($host)" + + invoke_restic \ + forget \ + --keep-within "$timeframe" \ + --host "$host" +} + +function prune_backup() { + say info "Pruning" + + invoke_restic \ + prune \ + --dry-run +} + +function start_service() { + service="$1" + + say info "Starting service: $service" + systemctl start $service +} + +function stop_service() { + service="$1" + + say info "Stopping service: $service" + systemctl stop $service +} + +test_root +test_prog "bzip2" +test_prog "curl" +test_prog "grep" +test_prog "hostname" + +mkdir -p "$backup_scripts_dir" +mkdir -p "$cache_dir" +mkdir -p "$secrets_dir" + +chmod -R 711 "$secrets_dir" + +download_restic 0.16.0 + +test_file "$restic_repo_file" +test_file "$restic_repo_passwd_file" + +say info "Running backup scripts..." + +if ! [[ "$(ls -A $backup_scripts_dir)" ]]; then + die "No scripts found in '$backup_scripts_dir'" +fi + +for backup_script in $backup_scripts_dir/*; do + backup_script_filename="$(basename "$backup_script")" + backup_script_name="${backup_script_filename%.*}" + backup_script_name_length="${#backup_script_name}" + + say primary "-[$backup_script_name]$(repeat "-" $((80-3-$backup_script_name_length)))" + chmod +x "$backup_script" + + export -f backup_dir + export -f die + export -f forget_backup + export -f get_config_dir + export -f invoke_restic + export -f prune_backup + export -f say + export -f start_service + export -f stop_service + export -f test_file + export backup_scripts_dir + export cache_dir + export host + export restic_repo_file + export restic_repo_passwd_file + export restic_path + export secrets_dir + + "$backup_scripts_dir/$backup_script_filename" +done + +say primary "$(repeat "-" 80)" + +#sudo rm -f "$restic_path" diff --git a/usr/local/bin/zio-backup b/usr/local/bin/zio-backup index a864e43..47004fe 100755 --- a/usr/local/bin/zio-backup +++ b/usr/local/bin/zio-backup @@ -11,12 +11,13 @@ function restic_exec() { args="${@:2}" if [[ -z $command ]]; then - say_warn "No command specified. Not running." + say_warn "No command specified. Not running" else - restic \ - --password-file "$passwd_file" \ - --repo "$repo" \ - $command $args + say "Running restic!" + #restic \ + # --password-file "$passwd_file" \ + # --repo "$repo" \ + # $command $args fi } @@ -25,13 +26,15 @@ function backup() { args="${@:2}" if [[ ! -d $path ]]; then - warn "'$path' does not exist. Not backing up." + say warning "'$path' does not exist. Not backing up" else - for exclude in "${excludes[@]}" - do - args+=" --iexclude \"$exclude\"" - done - + say info "Backing up: $path" + + #for exclude in "${excludes[@]}" + #do + # args+=" --iexclude \"$exclude\"" + #done + restic_exec \ backup \ --iexclude "__MACOSX" \ diff --git a/usr/local/libexec/zio/helpers/bash.sh b/usr/local/libexec/zio/helpers/bash.sh new file mode 100644 index 0000000..97e3dcc --- /dev/null +++ b/usr/local/libexec/zio/helpers/bash.sh @@ -0,0 +1,116 @@ +#!/usr/bin/env bash + +function die() { + say error "$@" + exit 255 +} + +function get_config_dir() { + prog="$1" + + config_dir="" + + if [[ ! -z $prog ]]; then + config_dir="/etc/zio/$prog" + else + config_dir="/etc/zio" + fi + + if [[ ! -d "$config_dir" ]]; then + mkdir -p "$config_dir" + fi + + echo "$config_dir" +} + +function podman_exec() { + container="$1" + command="${@:2}" + podman exec -it $container "$command" +} + +function repeat() { + string="$1" + amount=$2 + + if ! [[ -n $amount ]]; then + amount=20 + fi + + eval "for i in {1..$amount}; do echo -n "$1"; done" +} + +function say() { + color="" + message="${@:2}" + output="" + prefix="" + style="0" + + if [[ "$2" != "" ]]; then + message="$2" + type="$1" + else + message="$1" + fi + + case $1 in + debug) + color="35" + prefix="Debug" + ;; + error) + color="31" + prefix="Error" + style="1" + ;; + info) + color="34" + style="1" + ;; + primary) + color="37" + style="1" + ;; + warning) + color="33" + style="1" + ;; + *|default) + color="0" + message="$@" + ;; + esac + + if [[ $prefix == "" ]]; then + output="\033[${style};${color}m${message}\033[0m" + else + output="\033[1;${color}m${prefix}" + + if [[ $message == "" ]]; then + output+="!" + else + output+=": \033[${style};${color}m${message}\033[0m" + fi + + output+="\033[0m" + fi + + echo -e "$output" +} + +function test_file() { + if [[ ! -f "$1" ]]; then + die "'$1' does not exist" + fi +} + +function test_root() { + if [[ ! $(id -u) = 0 ]]; then + die "Unauthorized (are you root?)" + fi +} + +function test_prog() { + [[ ! $(command -v "$1") ]] && die "'$1' not installed" +}