This is an old revision of the document!
Restic Backup im Netzwerk
Übersicht über alle Backups: http://resticinfo.local
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.
Service-Unitfile anlegen
sudo systemctl edit –force –full restic.service
# from https://fedoramagazine.org/automate-backups-with-restic-and-systemd/ [Unit] Description=Restic backup service [Service] Type=oneshot ExecStart=/usr/bin/restic backup --host $HOST --verbose --one-file-system --tag systemd.timer $BACKUP_EXCLUDES $BACKUP_PATHS EnvironmentFile=/root/restic-backup.conf [Install] WantedBy=multi-user.target WantedBy=network-online.target
EnvironmentFile anlegen
HOME=/root HOST=denkbrett RESTIC_REPOSITORY=rest:https://<abc>:<def>@restic.<meine.domain> 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 - Als Dienst einrichten mit
systemctl enable restic-backup.service - Dienst prüfen mit
systemctl status restic-backup.service
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:
- /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) >> $LOG if [ -e "$LOCKFILE" ]; then echo Check if the lock file is from today >> $LOG if [ "$(date +%Y-%m-%d)" != "$(cat $LOCKFILE)" ]; then echo Lock file is from a previous day, remove it >> $LOG rm "$LOCKFILE" else echo Lock file is from today, exit >> $LOG exit 0 fi fi echo Run restic backup >> $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>>$LOG if [[$? -eq 0]]; then echo "Backup successful">>$LOG else rm $LOCKFILE fi
Das Resume-Script:
- /usr/lib/systemd/system-sleep/run_restic_backup_once_a_day
#!/bin/sh set -e # logger -p local0.notice -s "Running $0 with event $1" RESTIC_START_SCRIPT=/etc/network/if-up.d/run_restic_backup_once_a_day.sh case "$1" in post) logger -p local0.notice -s $0 event $1 submitting restic to at-daemon echo $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
Restic Backups von Windows-Clients
Ü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)
- /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
- /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
- /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.
- docker-compose.yml
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
Tricks / Links
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/$HOST/ | \
grep -v total | \
perl -pe 's!.*\s(\d+-\d+-\d+)\s(.*?)\.(\d+)$!restic backup --host $ENV{HOST} --tag historisch --tag $1 --tag $2 /backupdisk/$ENV{HOST}/$2.$3!'
Externe Server
Backup-Server induziertes backup mit
Example command on the server:
ssh -R 127.0.0.1:20022:<backup server IP>:22 <client IP> "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.hermes.markus-spring.info`)"
- "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.hermes.markus-spring.info" 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="$(ldd /bin/$binaryname | egrep -o '/lib.*\.[0-9]')"
# Looping through the dependency list
for i in $list; do cp -v --parents "$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
Links
- https://braincoke.fr/blog/2020/06/your-own-backup-monitoring-system/ (healthcheck, gotify, apprise)
- https://biqubic.com/network-trigger (um Restic auf einem Windows-Rechner zu starten)