#!/bin/bash # A script to perform daily/weekly/monthly backups using Borg # Set pruning DAILY_KEEP=7 WEEKLY_KEEP=2 MONTHLY_KEEP=3 # Update Package list if hash apt-get 2>/dev/null; then dpkg-query -f '${binary:Package}\n' -W > ~/packages.txt elif hash pacman 2>/dev/null; then pacman -Qq > ~/packages.txt else echo "Distro needs to be added to package dump check" fi # Be sure perms are set properly on this file!!! export BORG_PASSCOMMAND="cat $HOME/scripts/.borg-pass" LOCAL=$(hostname --short) REPO=/mnt/mountpoint/backups HOST=$(hostname) DATE=$(date +'%m-%d-%Y_%H:%M') # Was originally used, not now. Keeping for possible re-use. Note: Does not include /opt or /etc COMMON_ROOT_EXCLUDES="--exclude /bin --exclude /core --exclude /lib --exclude /lib64 --exclude /lost+found --exclude /mnt --exclude /proc --exclude /run --exclude /snap --exclude /tmp --exclude /var --exclude /boot --exclude /dev --exclude /lib32 --exclude /libx32 --exclude /media --exclude /root --exclude /sbin --exclude /srv --exclude /sys --exclude /usr" COMMON_HOME_EXCLUDES="--exclude /home/*/.cache --exclude /home/*/.ccache --exclude /home/lost+found --exclude *.img --exclude *.iso" BORG_OPTS="--stats --compression lz4" export BORG_RELOCATED_REPO_ACCESS_IS_OK=no export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=no case $HOSTNAME in (gamesrv) # Backup /home and minecraft srvs (in /opt/minecraft) # Loop through all servers dirs=(/opt/minecraft/*) for dir in "${dirs[@]}" do # Get just the name, not path for systemd unit dir=${dir//"/opt/minecraft/"} # If running, stop the server # Note: systemd unit properly handles the save-all and graceful stop of the server. if ( systemctl is-active --quiet minecraft@$dir.service); then # Note: Added the specific start/stop for each server to sudoers for nopass sudo systemctl stop minecraft@$dir.service mkdir -p ~/minecraft_copies cp -r /opt/minecraft/$dir ~/minecraft_copies sudo systemctl start minecraft@$dir.service else # Otherwise, just copy mkdir -p ~/minecraft_copies cp -r /opt/minecraft/$dir ~/minecraft_copies fi done # Loop through all factorio servers dirs=(/opt/factorio/*) for dir in "${dirs[@]}" do # Get just the name, not path for systemd unit dir=${dir//"/opt/factorio/"} # If running, stop the server # Note: systemd unit properly handles the save-all and graceful stop of the server. if ( systemctl is-active --quiet factorio@$dir.service); then # Note: Added the specific start/stop for each server to sudoers for nopass sudo systemctl stop factorio@$dir.service mkdir -p ~/factorio_copies cp -r /opt/factorio/$dir ~/factorio_copies sudo systemctl start factoriot@$dir.service else # Otherwise, just copy mkdir -p ~/factorio_copies cp -r /opt/factorio/$dir ~/factorio_copies fi done # NOTE: cannot spec two directories. Have to use shared parent directory. borg create -v $BORG_OPTS $REPO::$HOST-$DATE /home \ $COMMON_HOME_EXCLUDES \ # Log to journalctl 2>&1 ;; (media-srv) # Stop all containers docker stop $(docker ps -aq) borg create -v $BORG_OPTS $REPO::$HOST-$DATE /home \ $COMMON_HOME_EXCLUDES \ # Log to journalctl 2>&1 # Start all containers docker start $(docker ps -aq) ;; (progdev) ### Prep Gitea # Backup gitea: LFS, DB, configs, repos CONTAINER=gitea HOST_BACKUP_DIR="/home/dev/docker/container_backups/gitea" HOST_GIT_REPO_DIR="/home/dev/docker/gitea/git/repositories" TEMP_DIR="~/tmp" GITEA_DATA_FILENAME="gitea_backup.zip" HOST_BACKUP_FILE="$HOST_BACKUP_DIR/$GITEA_DATA_FILENAME" # Back up to temp files then copy on success to prevent syncing incomplete/bad files CONTAINER_BACKUP_FILE_TEMP="$TEMP_DIR/gitea_dump_temp.zip" docker exec -u "$id -u" -i $(docker ps -qf "name=$CONTAINER") bash -c "rm -f $CONTAINER_BACKUP_FILE_TEMP" docker exec -u "$id -u" -i $(docker ps -qf "name=$CONTAINER") bash -c "/app/gitea/gitea dump --skip-log --file $CONTAINER_BACKUP_FILE_TEMP" # copy this into backup folder (in container) docker cp $CONTAINER:$CONTAINER_BACKUP_FILE_TEMP $HOST_BACKUP_FILE # Backup with Borg borg create -v $BORG_OPTS $REPO::$HOST-$DATE /home \ $COMMON_HOME_EXCLUDES \ # Log to journalctl 2>&1 ;; (fevm) # Nginx cp /etc/nginx/nginx.conf ~/backup_confs/nginx_confs cp -r /etc/nginx/conf.d/ ~/backup_confs/nginx_confs # Fail2Ban cp -r /etc/fail2ban/ ~/backup_confs/fail2ban_confs # Backup with Borg borg create -v $BORG_OPTS $REPO::$HOST-$DATE /home \ $COMMON_HOME_EXCLUDES \ # Log to journalctl 2>&1 ;; (commbox) # Matrix Synapse cp -r /etc/matrix-synapse ~/backups/matrix-synapse # Postgres Database # get variables source .matrix-vars.sh # If matrix-synapse is running, we need to stop it before stopping postgres if ( systemctl is-active --quiet matrix-synapse.service); then sudo systemctl stop matrix-synapse.service if ( systemctl is-active --quiet noah-psql.service); then sudo systemctl stop noah-psql.service PGPASSWORD="${dbPassword}" pg_dump "${matrixDatabase}" -h localhost -p 5432 -U "${dbUser}" -f ~/backups/postgres/pg.sql sudo systemctl start noah-psql.service else PGPASSWORD="${dbPassword}" pg_dump "${matrixDatabase}" -h localhost -p 5432 -U "${dbUser}" -f ~/backups/postgres/pg.sql fi sudo systemctl start matrix-synapse.service # Even if matrix-synapse isn't running, still backup the database else if ( systemctl is-active --quiet noah-psql.service); then sudo systemctl stop noah-psql.service PGPASSWORD="${dbPassword}" pg_dump "${matrixDatabase}" -h localhost -p 5432 -U "${dbUser}" -f ~/backups/postgres/pg.sql sudo systemctl start noah-psql.service else PGPASSWORD="${dbPassword}" pg_dump "${matrixDatabase}" -h localhost -p 5432 -U "${dbUser}" -f ~/backups/postgres/pg.sql fi fi # Backup with Borg borg create -v $BORG_OPTS $REPO::$HOST-$DATE /home \ $COMMON_HOME_EXCLUDES \ # Log to journalctl 2>&1 ;; (NovaArchSys) # Backup with Borg borg create -v $BORG_OPTS $REPO::$HOST-$DATE /home \ $COMMON_HOME_EXCLUDES \ # Log to journalctl 2>&1 ;; (netbox) # Stop all containers docker stop $(docker ps -aq) borg create -v $BORG_OPTS $REPO::$HOST-$DATE /home \ $COMMON_HOME_EXCLUDES \ # Log to journalctl 2>&1 # Start all containers docker start $(docker ps -aq) ;; (monbox) # Stop all containers docker stop $(docker ps -aq) borg create -v $BORG_OPTS $REPO::$HOST-$DATE /home \ $COMMON_HOME_EXCLUDES \ # Log to journalctl 2>&1 # Start all containers docker start $(docker ps -aq) ;; esac # Unset passphrase and exit on error. Pretty sure the unset is unneeded here. if [ "$?" = "1" ] ; then export BORG_PASSCOMMAND="" echo "Error on create" exit 1 fi echo "Backup for $DATE complete." # Keep 7 daily backups, 2 weekly backups, and 3 monthly ones borg prune -v --list $REPO --keep-daily=$DAILY_KEEP --keep-weekly=$WEEKLY_KEEP --keep-monthly=$MONTHLY_KEEP if [ "$?" = "1" ] ; then export BORG_PASSCOMMAND="" echo "Error on prune" exit 1 fi #Unset the passphrase. Again, pretty sure the unset is unneeded. BORG_PASSCOMMAND="" echo "Backup and pruning successfully completed." exit 0