Linux: BorgBackup

BorgBackup oder kurz Borg ist ein Fork der Attic Backup-Software und wie Attic eine deduplizierende Backup-Anwwendung.

Installation

sudo aptitude install borgbackup borgbackup-doc

Zusätzlich Download des eigenständigen Binary in der gleichen Version, um BorgBackup z. B. von einem USB-Stick zu starten und der begleitenden Dokumentation.

Kommandos

Repository erstellen

Repository-Verzeichnis reponame ohne Verschlüsselung (-e none) erstellen, das die Backup-Archive enthält:

borg init -v --show-rc --umask nnnn -e none /pfad/reponame

Verschlüsselung

Im obigen Kommando wird das Repository unverschlüsselt erstellt, da es auf einem bereits verschlüssleten Volume angelegt wird. Für Backups, die zu unverschlüsselten Datenträgern übertragen werden bzw. auf ihnen gespeichert werden, bietet sich die Aktivierung der Verschlüsselung an:

Modus Anmerkungen
-e repokey|repokey-blake2 Schlüssel wird mit AES-CTR-256+HMAC-SHA256 oder AES-CTR-256+BLAKE2b-256 in der Konfigurationsdatei im Repository gespeichert
-e keyfile|keyfile-blake2 Schlüssel wird mit AES-CTR-256+HMAC-SHA256 oder AES-CTR-256+BLAKE2b-256 als Schlüsseldatei im Borg Konfigurationsverzeichnis (BORG_KEYS_DIR/BORG_KEY_FILE bzw. ~/.config/borg/keys/keydatei) gespeichert

Repository löschen

Repository-Verzeichnis mit allen Backup-Archiven löschen:

borg delete -v --show-rc --umask nnnn /pfad/reponame

Backup erstellen

Backup name im Repository-Verzeichnis erstellen:

borg create -v --show-rc --umask nnnn -s -p --exclude-caches -x /pfad/reponame::name[-{now:%d%m%y}] /pfad1/ /pfadN/ -e 'muster' --exclude-from /pfad/musterdatei

Repository/Backups prüfen & reparieren

Allgemein

borg check -v --show-rc /pfad/reponame

Repository

borg check -v --show-rc --repository-only /pfad/reponame

Backup

borg check -v --show-rc --archives-only /pfad/reponame[::name]

Reparatur

borg check -v --show-rc --umask nnnn --[repository/archives]-only --repair /pfad/reponame[::name]

Locks aufheben

borg break-lock -v --show-rc --umask nnnn /pfad/reponame

Falls bei Operationen Fehlermeldungen auftreten, die sich auf Lockfiles im Repository oder Cache beziehen.

Backup umbenennen

borg list /pfad/reponame
borg rename -v --show-rc --umask nnnn /pfad/reponame::name neuer_name

Backup löschen

Backup name löschen:

borg delete -v --show-rc --umask nnnn /pfad/reponame::name

Infos & Inhalte anzeigen

borg list /pfad/reponame
borg info /pfad/reponame::name
borg list /pfad/reponame::name

Backup mount/umount

mount

borg mount -v --show-rc [-o optionen] /pfad/reponame::name /pfad/mountpoint [--strip-components n]

Zusatzliche Mountoptionen (siehe fuse) können mit -o angegeben werden. Mit -o allow_damaged_files werden auch Dateien mit fehlenden Datensegmenten gelesen. Mit --strip-components n kann die Anzahl von n führenden Pfad-Anteilen entfernt werden.

umount

borg umount -v --show-rc /pfad/mountpoint

Backups extrahieren

Allgemein

Daten werden immer in das aktuelle Arbeitsverzeichnis extrahiert. Deshalb zuerst das Verzeichis wecheln, wenn Daten in ein anderes Verzeichnis extrahiert werden sollen.

ganzes Archiv

borg extract -v --show-rc /pfad/reponame::name

einzelne Pfade

borg extract -v --show-rc --list /pfad/reponame::name pfad/muster/angabe [--exclude 'muster' --exclude-from /pfad/musterdatei --strip-components n]

Mit --exclude/--exclude-from können einzelne Daten im zu extrahierenden Verzeichnis von der Extrahierung ausgenommen werden. Mit --strip-components n kann die Anzahl von n führenden Pfad-Anteilen entfernt werden.

Skripte

Für wöchentliche Backups wird eine externe, LUKS-verschlüsselte USB-Festplatte verwendet, die zuvor mit cryptsetup entsprechend präpariert wurde. Das borg_backup Skript prüft, ob die USB-Platte angeschaltet ist und mountet die Volumes der entschlüsselten USB-Platte mit dem usb_platte Skript. Es erstellt das Cache-Verzeichnis auf der USB-Platte und setzt die enstprechende BORG_CACHE_DIR Variable, falls nicht vorhanden, führt die Backups aus, wobei Ausnahmen, für die Muster in Dateien (--exclude-from exludedatei) definiert wurden, berücksichtigt werden und löscht anschließend die Backups, die älter als vier Wochen sind und mit dem angegebeben Präfix („we-“) beginnen. Das borg_mount Skript führt die gleichen Prüfungen aus und hängt dann das Backup ein, dessen Name aus der List bereits erstellter Backups ausgewählt wurde oder hängt ein Backup aus.

borg_backup

borg_backup
#!/bin/sh
 
usbdev="/dev/usb_name"
borgbasedir="/mnt/volume_mp"
borgrepo="$borgbasedir/borg"
borgcache="$borgbasedir/borgcache"
borgconfig="$borgbasedir/borgconfig"
borgsecurity="$borgconfig/security"
borgcmd="create -v -p --show-rc --umask 0027 -s --exclude-caches -x"
borgprune="prune -v --show-rc --umask 0027 -s --list --keep-within 4w --save-space"
 
if [ `id -u` -ne 0 ]; then
    printf "BorgBackup mit sudo ausführen.\nBorgBackup wurde abgebrochen."
    exit 1
fi
 
if [ ! -L "$usbdev" ]; then
    printf "USB-Platte anschalten + Enter drücken: " "$taste" ; read taste
    sleep 10
fi
 
if [ ! -d $borgrepo ]; then
    usb_platte m
fi
 
if [ "$(echo $BORG_BASE_DIR)" != "$borgbasedir" ] ; then
    export BORG_BASE_DIR=$borgbasedir
    printf "BORG_BASE_DIR Variable auf $BORG_BASE_DIR gesetzt.\n"
fi
 
if [ "$(echo $BORG_CACHE_DIR)" != "$borgcache" ] ; then
    export BORG_CACHE_DIR=$borgcache
    printf "BORG_CACHE_DIR Variable auf $BORG_CACHE_DIR gesetzt.\n"
fi
 
if [ ! -d $borgcache ]; then
    mkdir $borgcache && chmod 2770 $borgcache && chown -R root:sudo $borgcache
    printf "Borg Cache-Dir $borgcache wurde angelegt.\n"
fi
 
if [ "$(echo $BORG_CONFIG_DIR)" != "$borgconfig" ] ; then
    export BORG_CONFIG_DIR=$borgconfig
    printf "BORG_CONFIG_DIR Variable auf $BORG_CONFIG_DIR gesetzt.\n"
fi
 
if [ ! -d $borgconfig ]; then
    mkdir $borgconfig && chmod 2770 $borgconfig && chown -R root:sudo $borgconfig
    printf "Borg Config-Dir $borgconfig wurde angelegt.\n"
fi
 
if [ "$(echo $BORG_SECURITY_DIR)" != "$borgsecurity" ] ; then
    export BORG_SECURITY_DIR=$borgsecurity
    printf "BORG_SECURITY_DIR Variable auf $BORG_SECURITY_DIR gesetzt.\n\n"
fi
 
if [ ! -d $borgsecurity ]; then
    mkdir $borgsecurity && chmod 2770 $borgsecurity && chown -R root:sudo $borgsecurity
    printf "Borg Security-Dir $borgsecurity wurde angelegt.\n\n"
fi
 
borg $borgcmd $borgrepo::we-system-{now:%d%m} /boot /etc /usw --exclude-from $borgrepo/exclude_system.txt && \
borg $borgcmd $borgrepo::we-home-{now:%d%m} /home/name --exclude-from $borgrepo/exclude_home.txt && \
borg $borgcmd $borgrepo::we-opt-{now:%d%m} /opt --exclude-from $borgrepo/exclude_opt.txt && \
sleep 3
borg $borgprune --prefix 'we-' $borgrepo && \
sleep 3
printf "\nDas Repository enthält jetzt folgende Backups:\n"
borg list $borgrepo | sort
 
exit 0

borg_mount

borg_mount
#!/bin/sh
 
usbdev="/dev/usb_name"
borgbasedir="/mnt/volume_mp"
borgrepo="$borgbasedir/borg"
borgcache="$borgbasedir/borgcache"
borgmcmd="mount -v --show-rc -o allow_other"
borgucmd="umount -v --show-rc"
borgmp="/media/borg"
 
if [ `id -u` -ne 0 ]; then
    printf "Skript mit sudo ausführen.\nBorgBackup wurde abgebrochen."
    exit 1
fi
 
if [ ! -L "$usbdev" ]; then
    printf "USB-Platte anschalten + Enter drücken: " "$taste" ; read taste
    sleep 10
fi
 
if [ ! -d $borgrepo ]; then
    usb_platte m
fi
 
if [ "$(echo $BORG_CACHE_DIR)" != "$borgcache" ] ; then
    export BORG_CACHE_DIR=$borgcache && \
    printf "BORG_CACHE_DIR Variable auf $BORG_CACHE_DIR gesetzt.\n"
fi
 
if [ ! -d $borgcache ]; then
    mkdir $borgcache && chmod 2770 $borgcache && chown -R root:sudo $borgcache
    ptintf "Borg Cache-Dir $borgcache wurde angelegt.\n\n"
fi
 
if [ ! -d $borgmp ]; then
    mkdir $borgmp && chmod 0750 $borgmp && chown -R root:sudo $borgmp
    printf "Borg Mountpoint $borgmp wurde angelegt.\n\n"
fi
 
printf "[m]ount oder [u]mount Backup? " "$wahl" ; read wahl
 
if [ $wahl = m ]; then
    printf "\nDas Repository enthält folgende Backups:\n"
    borg list $borgrepo | sort
    printf "Welches Backup soll eingehängt werden?\nBackup-Name: " "$backup" ; read backup
    borg $borgmcmd $borgrepo::$backup $borgmp
else
    borg $borgucmd $borgmp 2>/dev/null
fi
 
exit 0

usb_platte

usb_platte
#!/bin/sh
 
if [ `id -u` -ne 0 ]; then
  echo "Skript mit sudo ausführen. Skript wird beendet."
  exit 1
fi
 
# /etc/udev/rules.d/50-persistent-usb.rules
# USB-Platte
# KERNEL=="sd?1", SUBSYSTEMS=="usb", ATTRS{serial}=="seriennummer" SYMLINK+="usb_name"
dev="/dev/usb_name"
 
if [ ! -L "$dev" ]; then
  echo "USB-Platte nicht eingeschaltet. Nach Anschalten drücke Enter: " "$taste" ; read taste
  sleep 10
fi
 
dev_uid="$(lsblk -fldn -o UUID $dev)"
dev_name="/dev/disk/by-uuid/$dev_uid"
keyfile="/pfad/lukskeyfile_usb_name"
mappername=name_crypt
devmap="/dev/mapper/$mappername"
 
device=$(udevadm info --query=path --name=$dev_name --attribute-walk | \
    egrep "looking at parent device" | head -1 | \
    sed -e "s/.*looking at parent device '\(\/devices\/.*\)\/.*\/host.*/\1/g")
 
dev_bus_id=$(echo $device | cut -d / -f 6)
vfs="ext4"
lvmntoption="rw,nosuid,nodev,noexec,noauto,user,nofail,x-systemd.device-timeout=1,noatime,nodiratime,commit=120,data=ordered"
 
case "$1" in
  m)
    cryptsetup --key-file $keyfile luksOpen UUID=$dev_uid $mappername && \
    sleep 3
    mount -t $vfs -o $lvmntoption /dev/mapper/volume-name /mnt/volume_mp
    sleep 2
    if [ -f "/sys$device/power/autosuspend_delay_ms" ]; then
      echo '300000' > "/sys$device/power/autosuspend_delay_ms"
    fi
    if [ -f /sys$device/power/control ]; then
      echo 'auto' > "/sys$device/power/control"
    fi
    echo "USB-Platte entschlüsselt und gemountet."
    exit 0
    ;;
  u)
    if [ -L "$devmap" ]; then
      umount /mnt/volume_mp
      vgchange -a n volumegroupname >/dev/null && \
      cryptsetup luksClose $mappername && \
      echo "USB-Platte kann abgeschaltet werden."
    elif [ -L "$dev_name" ]; then
      sdparm --command=sync "$dev_name" >/dev/null && \
      sleep 2
      udisksctl power-off --block-device "$dev_name" && \
      echo "USB-Platte kann abgeschaltet werden."
    else
      echo "USB-Platte ist abgeschaltet."
    fi
    exit 0
    ;;
  *)
    echo "Keine gültige Auswahl getroffen."
    echo "Das Skript wird beendet."
    exit 1
    ;;
esac
 
exit 0

Verweise auf aktuelle Seite