Restic Backup im Netzwerk

Restic Server auf hermes

Backup der Server hermes, florapower, netcup

hermes macht Pull-Backups von sich selbst und den Servern florapower und netcup mit hilfe des Scripts /usr/local/bin/run-restic.sh

Restic Backups von kudell und denkbrett via systemd

( von https://fedoramagazine.org/automate-backups-with-restic-and-systemd/ )

Systemd erlaubt das Starten von Services auch einmal/Tag.

Achtung: Auf Ubuntu prüfen ob restic in /usr/bin oder /usr/local/bin liegt

Service-Unitfile anlegen

sudo systemctl edit —force —full restic-backup.service

from https://fedoramagazine.org/automate-backups-with-restic-and-systemd/

[Unit] Description=Restic backup service After=network-online.target Wants=network-online.service StartLimitIntervalSec=6000 StartLimitBurst=30

[Service] Type=oneshot ExecStart=/usr/bin/restic backup —host BACKUP_EXCLUDES $BACKUP_PATHS EnvironmentFile=/root/restic-backup.conf Restart=on-failure RestartSec=60

[Install] WantedBy=default.target

EnvironmentFile anlegen

HOME=/root HOST=denkbrett RESTIC_REPOSITORY=rest:https://:@restic. RESTIC_PASSWORD_FILE=/root/resticpw BACKUP_PATHS="/root /etc /home/springm /root /usr/local /var/spool/cron/crontabs" BACKUP_EXCLUDES="--exclude-file /root/restic-exclude.txt --exclude-if-present .exclude_from_backup" #### Service starten/stoppen/enablen/prüfen - Änderungen mitteilen mit *systemctl daemon-reload* - Starten mit *systemctl start restic-backup.service* (führt Backup durch) - Als Dienst einrichten mit *systemctl enable restic-backup.service* - Dienst prüfen mit *systemctl status restic-backup.service*

Timer anlegen

sudo systemctl edit —force —full restic-backup.timer [Unit] Description=Backup with restic daily

[Timer] OnCalendar=daily OnActiveSec=30 Persistent=true

[Install] WantedBy=timers.target

  • Enablen mit systemctl enable —now restic-backup.timer
  • Status prüfen mit systemctl status restic-backup.timer
Restic Backups von kudell und denkbrett - DEPRECATED -

Das Backup sollte im Prinzip täglich von hermes getriggert als Pull-Backup laufen, allerdings sind diese Rechner nicht immer zur festgesetzten Backup-Zeit eingeschaltet. Die Alternative ist ein Push-Backup, das vom Client getriggert entweder nach dem Booten oder nach dem Aufwachen aus dem Suspend/Hibernate stattfindet.

Achtung: Das Paket at muss installiert sein, überprüfen als root am einfachsten mit atq

Das Network-Connect-Script: <file bash /etc/network/if-up.d/run_restic_backup_once_a_day.sh> #!/bin/bash LOCKFILE=/var/lib/restic/run_restic_once_a_day.lock LOG=/tmp/run_restic_backup_once_a_day.log echo "">>LOG && echo (date) >> LOCKFILE” ]; then echo Check if the lock file is from today >> (date +%Y-%m-%d)” != “LOCKFILE)” ]; then echo Lock file is from a previous day, remove it >> LOCKFILE” else echo Lock file is from today, exit >> LOG logger -p local0.notice -s “Running restic backup” /usr/bin/date +%Y-%m-%d > LOCKFILE && /usr/bin/touch LOCKFILE # create lockfile immediately sleep 30 HOME=/root RESTIC_REPOSITORY=rest:https://test:test@restic.hermes.markus-spring.info /usr/bin/restic -v —password-file /root/resticpw —host denkbrett —exclude-caches —exclude-file=/root/restic-exclude.txt backup /etc /home/springm /root /usr/local /var/spool/cron/crontabs 2>>? -eq 0](LOG else rm $LOCKFILE fi

Das Resume-Script: <file bash /usr/lib/systemd/system-sleep/run_restic_backup_once_a_day> #!/bin/sh set -e

logger -p local0.notice -s “Running 1”

RESTIC_START_SCRIPT=/etc/network/if-up.d/run_restic_backup_once_a_day.sh case “0 event RESTIC_START_SCRIPT | at now esac Achtung: lt https:*man.archlinux.org/man/systemd-sleep.8 : *Note that scripts or binaries dropped in /usr/lib/systemd/system-sleep/ are intended for local use only and should be considered hacks. If applications want to react to system suspend/hibernation and resume, they should rather use the Inhibitor interface[1]//

Ubuntu braucht einen Service

sudo systemctl edit —force —full restic_run_when_network_up.service [Unit] Description=Run restic backup after network available Wants=network-online.target After=network-online.target

[Service] Type=simple User=root #ExecStart=/etc/network/if-up.d/run_restic_backup_once_a_day.sh ExecStart=/usr/local/bin/run_restic_backup_once_a_day.sh

[Install] WantedBy=multi-user.target sudo systemctl enable restic_run_when_network_up.service

sudo systemctl start restic_run_when_network_up.service

from: https://askubuntu.com/questions/41400/how-do-i-make-the-script-to-run-automatically-when-tun0-interface-up-down-events

Restic Backups von Windows-Clients

siehe Restic Backup von Windows-Rechnern

Übersicht über die Backups

Erzeugen der /var/lib/restic/snapshots.json

Ein inotify-Eintrag auf das snapshots-Verzeichnis im Restic-Repository triggert das Schreiben einer JSON-Zustandsdatei mit dem Befehl

restic snapshots -c —json > /var/lib/restic/snapshots.json

Die Automatisierung erfolgt über einen systemd-Service (vgl. https://www.putorius.net/systemd-path-units.html)

<file bash /etc/systemd/system/restic-snapshots-mon.path> [Unit] Description=“Monitor restic snapshots for changes”

[Path] PathModified=/backupdisk/restic-repo/snapshots/ Unit=restic-snapshots-mon.service

[Install] WantedBy=multi-user.target

<file bash /etc/systemd/system/restic-snapshots-mon.service> [Unit] Description=“Recreate /var/lib/restic/snapshots.json when snapshots have changed”

[Service] ExecStart=/usr/local/sbin/restic_json.sh

<file bash /usr/local/sbin/restic-json.sh> #!/bin/bash RESTIC_PASSWORD=abc RESTIC_REPOSITORY=/backupdisk/def /usr/bin/restic snapshots -c —json > /tmp/restic.json Analysieren mit systemd-analyze verify /etc/systemd/system/restic-snapshots-mon* Starten mit systemctl start restic-snapshots-mon.path Beim Systemstart hochfahren mit systemctl enable restic-snapshots-mon.path Status überprüfen mit systemctl status restic-snapshots-mon.path Log-Einträge ansehen mit journalctl -u restic-snapshots-mon.path Erzeugen der /tmp/restic.json beim booten durch einen cron-eintrag @reboot /usr/local/sbin/restic-json.sh

Flask-Service zur Visualisierung

Ein Docker-Container mit dem Programm restic2html stellt die JSON-Datei als sortierbare und entsprechend des Snapshot-Alters zeilenweise eingefärbte HTML-Tabelle dar.

services: restic2html: image: restic2html container_name: restic2html build: context: . dockerfile: Dockerfile restart: always environment: - PUID=1000 - PGID=1000 - TZ=Europe/Berlin volumes: - /tmp:/tmp ports: - 5001:5001 environment: - TZ=${TZ:-Europe/Berlin} labels: - "traefik.enable=true" # <== Enable traefik on itself to view dashboard and assign subdomain to view it - "traefik.http.services.resticinfo.loadbalancer.server.port=5001" - "traefik.http.routers.resticinfo.rule=Host(`resticinfo.local`)" networks: - proxy

networks: proxy: external: true Der Container ist nur aus dem Intranet unter https://resticinfo.local erreichbar.

Restic Forget/Prune

ist nötig, um überflüssige Backups zu löschen. restic forget —keep-daily 6 —keep-weekly 4 —keep-monthly 6 —keep-yearly 99 —keep-tag yearly Auf restic forget muss restic prune folgen, um den Löschvorgang durchzuführen

Mounten des Repository für ein Restore

restic mount /resticrestore

Kann z.b. mit —host kudell eingeschränkt werden.

Das Verzeichnis kann über nfs freigegeben werden, z.B. folgender Eintrag in /etc/exports:

/resticrestore kudell.fritz.box(ro,async,no_subtree_check,crossmnt,fsid=0)

Achtung: dieser Prozess bleibt im Terminal geöffnet. Sicherstellen dass der Mount wieder aufgehoben wird!

Importieren historischer Backups
Environment-Variablen

Zur Vereinfachung der Befehlseingabe können sowohl Repository als auch Paßwort im Environment gesetzt werden. export RESTIC_REPOSITORY=/repo/restic RESTIC_PASSWORD=hättestduwohlgerne

Tags

rsnapshot-Sicherungen können importiert werden - das dauert! - und mit dem Tag “historisch” versehen werden.

Tags können nachträglich hinzugefügt werden, wenn kein anderer restic-Vorgang läuft. restic tag —set historisch ba37903f

Der restic-Befehl “forget” kann mit —keep-tag angewiesen werden, diese historischen Snapshots nicht zu löschen. In einer Übergangszeit müssen dann monatliche, wöchentliche und tägliche Snapshots manuell gelöscht werden.

rsnapshot-Daten importieren

Das Importieren der historischen rsnapshot-Daten vorbereiten mit export HOST=hermes;
ls -lt —time-style=”+%Y-%m-%d” /backupdisk/!restic backup —host 1 —tag ENV{HOST}/3!’

Externe Server

Backup-Server induziertes backup mit Example command on the server: ssh -R 127.0.0.1:20022::22 “sudo restic -r ‘sftp:127.0.0.1:/path/to/repo’ -p .resticpw backup -x /”

For that to work you need:

a .ssh/config specifying the "Port 20022" for 127.0.0.1 on the client
proper known_hosts files
ssh pubkeys exchanged between client and server (via 127.0.0.1)

Netcup Test

Erfolgreich getestet mit RESTIC_PASSWORD=geheim restic -v -v —exclude-file=/root/restic-exclude.txt
-o sftp.command=‘ssh hermes.markus-spring.info -p 22022 -s sftp’
-r sftp:hermes.markus-spring.info:/repo/restic backup /home/springm

Aber:

  • braucht passwortlosen root-Zugang auf hermes
  • Eventuell geht ein nur-sftp-account
  • Und eine Nur-Hinzufügen-Konfiguration des Repos
Restic-RestServer unter Docker

version: ‘2’

services: restserver: image: restic/rest-server:latest container_name: restic-rest environment:

  • PUID=1000

  • PGID=1000

  • TZ=Europe/Berlin

  • “OPTIONS=—append-only” volumes:

  • /repo/restic:/data ports:

  • “127.0.0.1:8010:8000” networks:

  • proxy labels:

  • “traefik.enable=true”

  • “traefik.docker.network=proxy”

  • “traefik.http.routers.restic-rest.rule=Host(restic.meine.domain)”

  • “traefik.http.routers.restic-rest.entrypoints=https”

  • “traefik.http.routers.restic-rest.tls=true”

  • “traefik.http.routers.restic-rest.tls.certresolver=cloudflare”

  • “traefik.http.services.restic-rest.loadBalancer.server.port=8000”

    networks: proxy: external: true Benutzer anlegen docker exec -it restic-rest create_user user passwort

Test auf dem netcup-Server export RESTIC_REPOSITORY=“rest:https://user:passwort@restic.meine.domain” restic -v snapshots restic -v —exclude-file=/root/restic-exclude.txt backup /home/springm

Backup löschen schlägt fehl, weil das Restic-Repo mit —append-only eingebunden ist. restic forget d50ada2f enter password for repository: repository 01a62565 opened successfully, password is correct Remove(<snapshot/d50ada2fcd>) returned error, retrying after 552.330144ms: blob not removed, server response: 403 Forbidden (403) … unable to remove <snapshot/d50ada2fcd> from the repository [0:45] 0.00% 0 / 1 files deleted blob not removed, server response: 403 Forbidden (403)

Importieren alter Backups in chroot-Umgebung

Restic arbeitet wesentlich schneller, wenn die Pfade zwischen den Backups gleich sind.Dann werden nur Datei-Metadaten verglichen, anstatt die Datei komplett zu lesen, zu chunken und zu prüfen ob die Chunks schon existieren. Beim Importieren historischer Backups aus rsnapshots ist das aber nicht der Fall. In einer chroot-Umgebung können die historischen Backups mit bind-mounts so zur Verfügung gestellt werden, dass die Wurzelpfade immer gleich sind, d.h., daily.0-n, weekly.0-n etc werden für restic unsichtbar

Chroot-Umgebung vorbereiten

Chroot-Umgebung erstellen nach Anweisung in https://www.maketecheasier.com/use-chroot-linux/

mkdir /restic-chroot cd /restic-chroot mkdir bin cp /usr/bin/restic bin/ cp /bin/mount bin/ cp /bin/ls bin/ cp /bin/rm bin/ cp /bin/bash bin/

Skript /restic-chroot/copydependancy.sh anlegen und ausführbar machen: #!/bin/bash #Setting the chroot directory mte=“/restic-chroot”

enter your binary name

echo -e “Please enter your binary name \n” #Reading from terminal input read binaryname

Listing all the dependencies

list=“binaryname | egrep -o ‘/lib.*.[0-9]’)“

Looping through the dependency list

for i in i” ”${mte}”; done

Dynamic Libraries in die chroot-Umgebung kopieren

für jedes Binary ausser restic

./copydependancy.sh

Repo mit Bind-Mount zur Verfügung stellen

mount -o bind /restic /restic-chroot/restic

Testen RESTIC_PASSWORD=keineAhnung RESTIC_REPOSITORY=/restic/mein_repo chroot /restic-chroot /bin/restic —host kudell snapshots

TODO