Borg Backup: best practice

Hi.
Neben Backup für ganze VMs oder LVMs/snapshots gibt es Situationen, wo man einzelne Backups erstellen will/sollte.

Um Borg Backup zu nutzen, kann man es auf eine Computer installieren oder wiederum dafür docker verwenden (z.B. um das grundsystem frei von Software zu halten).

Als Ziel kann man lokale oder remote (auch borg-installationen) Verzeichnisse/„Repos“ angeben.

Anleitungen gibt es zu Hauf:

Was findet ihr, ist best practice? Ich poste mal mein Setup.

VG, Tobias

Beispielimplementation: Borg Backup mit Hilfe von docker (compose)

  • Docker-Container-Up-to-Date-Security: Mir gefällt bei den Borg Backups (im Internet) via Docker oft nicht, dass irgendwelche docker-container verwendet werden, daher baue ich mein Image selbst aufbauend auf einem vertrauten Image (debian:stable-slim).
  • Regelmäßigkeit Außerdem: man braucht Borg ja eigentlich nicht ständig, aber regelmäßig (über einen scheduler wie cron. Man kann jetzt einen docker-container bauen, der ständig läuft und cron enthält. Mag ich auch nicht. Ich nehme dafür cron auf dem System.
  • docker vs docker compose Außerdem: eigentlich braucht man docker-compose dafür nicht. Es reicht ja ein docker -v /srv/backup:/srv/target exec|run... usw. Aber ich mag dann doch lieber docker-compose.yml, selbst wenn der Dockercontainer ein Zombie ist.
  • Flexibilität und Dokumentation: Das Elegante an einer Lösung über docker compose: ich kann beliebige „hooks“ noch einfügen, wenn ich mag, z.B. wenn man einen datenbank-container dumpen will, wenn man container anhalten mag, wenn man lokale Backupstrategien nutzen will (z.B. bei mailcow/helper-scripts/backup_and_restore.sh). Ich habe (außer der cron-links) alle Config in der Nähe des docker-compose.yml. Da kann ich mich noch später erinnern, wie es funktioniert:

Beispielhafte docker-struktur:

/srv/docker/app1
/srv/docker/app2
+-          app2/grossercache
/srv/docker/borgbackup
+-          borgbackup/Dockerfile
+-          borgbackup/borgbackup.sh
+-          borgbackup/borg-localbackup-cron
/srv/docker/docker-compose.yml
/etc/nginx/

backup-target (lokal)

Ums einfach zu halten, gibt es jetzt nur ein lokales Backup auf dem docker-host nach /srv/backup, aber das kann auch ein remote Backup sein…
Dafür muss das Target in den docker-container des borgbackups gemountet werden. Bei einem remote backup müsste man stattdessen noch die ssh-key Geschichte implementieren.

/srv/backup ->   borgbackup-container (/srv/target)

backup-quellen

  • sind z.B. die verschiedenen docker-apps, aber auch alles was ich sonst noch will. Die müssen natürlich auch im docker-container als volumes auftauchen
/srv/docker/app1 -> borgbackup-container (/source/app1)
...
/etc/nginx -> borgbackup-container (/source/nginx)

borg-backup container

borgbackup/Dockerfile:

FROM debian:stable-slim

RUN apt update && apt full-upgrade -y && apt install -y borgbackup && rm -rf /var/lib/apt/lists/*

docker-compose.yml

(kein version: mehr für neueres docker compose)

services:

## app1
  app1:
    image: app/app1
    ...

## app2
  app2:
    image: app/app2
    volumes:
      - ./app2/grossercache:/cache

## Borg Backup
## docs: https://borgbackup.readthedocs.io/en/1.2-maint/quickstart.html
  borgbackup:
    image: linuxmuster/borgbackup:latest
    build:
      dockerfile: Dockerfile
      context: ./borgbackup
    container_name: borgbackup
    command: tail -f /dev/null
    restart: always
    volumes:
      - /srv/backup:/srv/target
      - ./borgbackup/borgbackup.sh:/borgbackup.sh
      - ./app1:/source/app1:ro
      - ./app2:/source/app2:ro
      - /etc/nginx:/source/nginx:ro
      - ./borgbackup:/source/borgbackup:ro
    environment:
      BORG_PASSPHRASE: 'XYZl0ngandsecurepa_55_phrasea&&123'
      BORG_REPO: /srv/target
      BORG_DISPLAY_PASSPHRASE: 
      X_BORG_REPONAME: meinserver
      X_BORG_EXCLUDES: -e */app2/grossercache
      X_BORG_PATHS: "/source/app1 /source/app2 /source/borgbackup"
      #oder:
      #X_BORGBACKUPCMD: borg create --stats --progress --compression lz4 --verbose -e '*/app2/grossercache' "::meinserver-{now}" /source/app1 /source/app2 /source/borgbackup /source/nginx

container erstellen/update + starten/erneuern

docker compose build
docker compose up -d borgbackup

borg backup testen

docker compose run borgbackup borg help

borg backup initialisieren

docker compose run borgbackup borg init -e repokey

borg backup manuell starten / auflisten /etc.

docker compose run borgbackup borg create --verbose '::testarchivname' /source/app1
docker compose run borgbackup borg list ::testarchivname
usw...

automatisierung über borgbackup.sh

borgbackup/borgbackup.sh:
Eigentlich Copy+Paste von Quick Start — Borg - Deduplicating Archiver 1.2.9.dev5 documentation mit nur ein paar Änderungen beim Befehl „create“ und „prune“.

#!/bin/sh                                                                                                                                                     
#eval $X_BORGBACKUPCMD                                                                                                                                  
#exit 0                                                                                                                                                       
# see https://borgbackup.readthedocs.io/en/1.2-maint/quickstart.html#automating-backups                                                                       

# some helpers and error handling:                                                                                                                            
info() { printf "\n%s %s\n\n" "$( date )" "$*" >&2; }
trap 'echo $( date ) Backup interrupted >&2; exit 2' INT TERM

info "Starting backup"

borg create \
     --stats --progress \
     --verbose \
     --compression lz4 \
     $X_BORG_EXCLUDES \
     "::${X_BORG_REPONAME}-{now}" \
     $X_BORG_PATHS

backup_exit=$?

<snip>
     --glob-archives "${X_BORG_REPONAME}-*"     \
<snip>

Wer will, kann auch statt des Scripts einen kompletten borg-Befehl in eine ENV-Variable wie z.B. X_BORGBACKUPCMD in die docker-compose.yml packen und diesen dann „eval“ ausführen, siehe auskommentierte Versionen oben.

regelmäßiges Ausführen via cronjob

borgbackup/borg-localbackup-cron

#!/bin/bash                                                                                                                                                   
set -e
cd /srv/docker
docker compose run borgbackup /borgbackup.sh

und das verlinkt man z.B. hier:

cd /etc/cron.daily/
ln -s /srv/docker/borgbackup/borg-localbackup-cron

TODO

Viel Spaß damit, wer darauf Bock hat.

P.S. bei mir (privat) macht dieses Setup jetzt Backups für

  • mein Photo-Repo: immich,
  • meinen Mailserver: mailcow,
  • meine Nextcloud: nextcloud/data + sql
  • meine nginx-reverse-proxy-konfig (inkl. letsencrypt) und natürlich borgbackup selbst :slight_smile:

edit 1: cron-jobs dürfen keine Endung haben (kein „.“ im Namen).

Ergänzung:

1 „Gefällt mir“