# Borg Backup

- [Borg Backup](#borg-backup)
  - [Install Borg](#install-borg)
  - [Set up a laptop or workstation client](#set-up-a-laptop-or-workstation-client)
  - [Set up a new server client](#set-up-a-new-server-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

<https://borgbackup.readthedocs.io/en/stable/deployment/central-backup-server.html#user-and-group>

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 laptop or workstation client

For backing up your laptop or personal account.

1. On your personal account, set up the borg connection

    ```bash
    export BACKUP_HOST="borg.reeselink.com"

    ssh-keygen -C ${USER}@${HOSTNAME} -f ~/.ssh/id_${BACKUP_HOST}

    cat <<EOF >> ~/.ssh/config
    Host ${BACKUP_HOST}
        Hostname ${BACKUP_HOST}
        IdentityFile ~/.ssh/id_${BACKUP_HOST}
        User backup
        Port 22
    EOF

    echo "export CLIENT_FQDN=${USER}.${HOSTNAME}.reeselink.com"
    echo "export SSH_PUBKEY=\"$(cat ~/.ssh/id_${BACKUP_HOST}.pub)\""
    ```

2. On the borg backup server as the backup user:

    ```bash
    # Use echo from above
    export CLIENT_FQDN=
    export SSH_PUBKEY=

    # Create the authkey entry to restrict the user's access to the borg repo folder
    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 the directory
    mkdir repos/${CLIENT_FQDN}
    ```

3. On your personal account, create the repo and your first backup

    ```bash
    # Do not include the first / in the path
    export PATH_TO_BACKUP=home/${USER}
    export BACKUP_HOST="borg.reeselink.com"
    export BORG_REPO=${BACKUP_HOST}:home

    # If not initialized, do that now
    borg init --encryption none $BORG_REPO
    borg list

    # Run backup and timestamp it
    borg create \
    --verbose \
    --filter AME \
    --list \
    --stats \
    --progress \
    --show-rc \
    --compression lz4 \
    --exclude-caches \
    ${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)
    # First, cd to the location you want to extract to
    cd ~
    # Then, extract to that location. --strip-components takes the first n items off a path
    borg extract --dry-run --list --strip-components 2 $BORG_REPO::my-files home/USERNAME
    ```

## Set up a new server 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 <<EOF >> ~/.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
mkdir /home/backup/repos/${CLIENT_FQDN}
chown -R backup:backup /home/backup/repos/${CLIENT_FQDN}
```

## 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/foobar
exclude_dirs: []
keep_daily: 7
keep_weekly: 4
keep_monthly: 1
stop_services: []
stop_user_services:
  - foobar
```

```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 3dserver \
active/systemd_borg/install_backup.yaml \
-e "@active/systemd_borg/secrets/$var_file"
done
```

## Check backup service logs

```bash
export SERVER_SSH_NAME=
ssh $SERVER_SSH_NAME 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") \
/
```
