# Borg Backup - [Borg Backup](#borg-backup) - [Install Borg](#install-borg) - [Set up a new root client](#set-up-a-new-root-client) - [Create a Backup Service](#create-a-backup-service) - [Check backup service logs](#check-backup-service-logs) - [Run a Manual Backup](#run-a-manual-backup) - [Back up and Entire System](#back-up-and-entire-system) ## Install Borg User: backup Group: backup Shell: /bin/bash (or other capable to run the borg serve command) Home: /home/backup ```bash dnf install borgbackup useradd backup mkdir /home/backup/.ssh touch /home/backup/.ssh/authorized_keys chown -R backup:backup /home/backup/.ssh ``` ## Set up a new root client Backups will be run as the root user. Generate them an SSH key to On the server as root: ```bash export BACKUP_HOST="borg.reeselink.com" ssh-keygen -C root@${HOSTNAME} -f ~/.ssh/id_${BACKUP_HOST} cat <> ~/.ssh/config Host ${BACKUP_HOST} Hostname ${BACKUP_HOST} IdentityFile ~/.ssh/id_${BACKUP_HOST} User backup Port 22 EOF ``` Now on borg.reeselink.com as root: ```bash export CLIENT_FQDN="fqdn.reeseapps.com" export SSH_PUBKEY="ssh-rsa abcd1234 backup@fqdn.something.com" export BORG_COMMAND="cd /home/backup/repos/${CLIENT_FQDN}; borg serve --restrict-to-path /home/backup/repos/${CLIENT_FQDN}" export AUTHKEY_ENTRY="command=\"${BORG_COMMAND}\",restrict ${SSH_PUBKEY}" echo $AUTHKEY_ENTRY >> /home/backup/.ssh/authorized_keys ``` ## Create a Backup Service Create your vars file in `secrets/host_vars.yaml` ```yaml repo_name: my_repo borg_user: backup borg_host: borg.reeselink.com borg_passphrase: "" backup_dirs: - /home exclude_dirs: [] keep_daily: 7 keep_weekly: 4 keep_monthly: 1 stop_services: [] stop_user_services: - gitea - postgres ``` ```bash # Update all existing backup services for podman for var_file in $(ls active/systemd_borg/secrets); do ansible-playbook \ -i ansible/inventory.yaml \ -l podman \ active/systemd_borg/install_backup.yaml \ -e "@active/systemd_borg/secrets/$var_file" done ``` ## Check backup service logs ```bash ssh podman journalctl -u 'backup-*' -f ``` ## Run a Manual Backup ```bash borg list borg.reeselink.com:home # Do not include the first / in the path export PATH_TO_BACKUP=home/ducoterra export BORG_REPO=borg.reeselink.com:home # If not initialized, do that now borg init --encryption none $BORG_REPO # Run backup and timestamp it borg create \ --verbose \ --filter AME \ --list \ --stats \ --progress \ --show-rc \ --compression lz4 \ --exclude-caches \ -e "pp:/${PATH_TO_BACKUP}/.cache" \ -e "re:^${PATH_TO_BACKUP}/\.var/app/[^/]+/cache/" \ -e "CACHEDIR.TAG" \ -e "pp:/${PATH_TO_BACKUP}/.local/share/gnome-boxes" \ -e "pp:/${PATH_TO_BACKUP}/.var/app/org.gnome.Boxes" \ -e "pp:/${PATH_TO_BACKUP}/.var/app/org.gnome.BoxesDevel" \ -e "pp:/${PATH_TO_BACKUP}/.local/share/bottles" \ -e "pp:/${PATH_TO_BACKUP}/.var/app/com.usebottles.bottles" \ -e "pp:/${PATH_TO_BACKUP}/.local/share/libvirt" \ -e "pp:/${PATH_TO_BACKUP}/.config/libvirt" \ -e "pp:/${PATH_TO_BACKUP}/.local/share/containers" \ -e "pp:/${PATH_TO_BACKUP}/.local/share/docker" \ -e "pp:/${PATH_TO_BACKUP}/.npm" \ -e "pp:/${PATH_TO_BACKUP}/.ollama" \ -e "pp:/${PATH_TO_BACKUP}/Downloads" \ -e "pp:/${PATH_TO_BACKUP}/Nextcloud" \ ${BORG_REPO}::$(date +"%F-%H-%M-%S") \ /${PATH_TO_BACKUP} # Mount a borg archive borg mount $BORG_REPO::2025-05-14-00-44-05 /mnt/ # Restore a borg archive to a location (dry run) borg extract --dry-run --list --strip-components 1 $BORG_REPO::my-files home/USERNAME ``` ### Back up and Entire System ```bash export BORG_REPO=borg.reeselink.com:root borg create \ --verbose \ --filter AME \ --list \ --stats \ --progress \ --show-rc \ --compression lz4 \ --exclude root/.cache \ --exclude var/lib/docker \ --exclude var/lib/containers \ --exclude usr/share/ollama \ --exclude home \ --exclude proc \ --exclude dev \ --exclude sys \ --exclude tmp \ --exclude .snapshots \ ${BORG_REPO}::$(date +"%F-%H-%M-%S") \ / ```