Restic Backup
Backup-Infrastruktur mit Restic und SaltStack aufbauen
Restic ist ein einfaches aber sehr mächtiges Backup-Programm. Gepaart mit Salt können Sie Backups vollautomatisch durchführen und über den Salt-Master zentral steuern. Ein einfacher SSH-Server dient als zentraler Speicher für die Backups.
Backup-Server vorbereiten
Restic kann auf einer Vielzahl von Zielen die Backups ablegen. SFTP bzw. SSH gehört dazu, was mit jedem Linux-System einfach zu realisieren ist.
Grundsätzlich kann jeder Benutzer-Account verwendet werden, ein eigener Benutzer restic
ist empfohlen, um das System „ordentlich“ zu halten. Restic authentifiziert sich ausschließlich per SSH-Key. Legen Sie einen neuen Benutzer an und generieren Sie SSH Schlüssel.
mkdir /srv/salt/restic
cd /srv/salt/restic
ssh-keygen -N "" -t ed25519 -C "restic@salt-master.local" -f ./id_ed25519
Backup-Software ausrollen
#
# Create a restic user
#
restic-group:
group.present:
- name: restic
restic:
user.present:
- fullname: Restic Backup
- shell: /bin/bash
- home: /var/lib/restic
- createhome: true
- system: true
- groups:
- restic
- require:
- group: restic-group
bzip2:
pkg.installed: []
#
# Download restic from github (the debian packages are quite outdated)
#
{% set version = '0.16.2' %}
download-restic:
file.managed:
- name: /var/tmp/restic_{{ version }}_linux_amd64.bz2
- source: https://github.com/restic/restic/releases/download/v{{ version }}/restic_{{ version }}_linux_amd64.bz2
- user: restic
- group: restic
- mode: 0755
- require:
- bzip2
#
# Install restic by unpacking the compressed binary
#
install-restic:
cmd.run:
- name: |
set -e
which bunzip2
bunzip2 -k /var/tmp/restic_{{ version }}_linux_amd64.bz2 -c > restic
chmod 0700 restic
./restic version
rm -f /var/tmp/restic_{{ version }}_linux_amd64.bz2
- cwd: /var/lib/restic
- runas: restic
- unless:
- /var/lib/restic/restic version|grep -q {{ version }}
- require:
- file: download-restic
- pkg: bzip2
/var/lib/restic/restic:
file.managed:
- mode: 0700
- user: restic
- require:
- install-restic
/var/lib/restic/.ssh/:
file.directory:
- user: restic
- group: restic
- mode: 0700
😯 Probleme:
Wenn Sie Downloads aus dem Internet ungeprüft in Ihr System übernehmen, kann Schadcode ins System gelangen.
Der State
download-restic
speichert dauerhaft das komprimierte Archiv oder lädt es erneut herunter, wenn es auf dem temporären Verzeichnis gelöscht wurde.
🧩 Aufgaben: Optimieren Sie den State. Nutzen Sie eine der folgenden Optionen:
Erweitern Sie den State mit einer Prüfsummen-Prüfung. Der Download darf nur dann verwendet werden, wenn die Prüfsumme stimmt. Suchen Sie dazu in der Dokumentation nach dem Stichwort
source_hash
.Fügen Sie eine unless Bedingung ein, damit der Download nicht mehr ausgeführt wird, sobald
restic
erfolgreich installiert wurde.Laden Sie das komprimierte Archiv zuerst auf den Salt-Master herunter, entpacken Sie es und verteilen Sie es von dort.
Backup-Server ausrollen
Restic kann die Sicherungskopien auf einer Vielzahl von Fileservern abspeichern. In einem Intranet ist der in SSH integrierte SFTP-Server die einfachste Lösung. Das bedeutet, Sie benötigen keine spezielle Server-Software. Der Server muss lediglich den passenden SSH-Private-Key nutzen, der zum Public-Key der Clients passt.
include:
- .base
openssh-server:
pkg.installed: []
sshd:
service.running:
- enable: true
authorized_keys:
file.managed:
- name: /var/lib/restic/.ssh/authorized_keys
- source: salt://restic/id_ed25519.pub
- user: restic
- group: restic
- mode: 0600
Backup-Clients ausrollen
include:
- .base
#
# Set package names and dependencies according to the disctribution
#
{% set restic_deps = salt['grains.filter_by']({
'Debian': {'libcap':'libcap2-bin','cron':'cron','crond':'cron'},
'RedHat': {'libcap':'libcap','cron':'cronie','crond':'crond'},
'Suse': {'libcap':'libcap-progs','cron':'cron','crond':'cron'},
}) %}
#
# Deploy the private key need for the backup transfer over SFTP
#
priv-key:
file.managed:
- name: /var/lib/restic/.ssh/id_ed25519
- source: salt://restic/id_ed25519
- user: restic
- group: restic
- mode: 0600
# Install the setcap utility
libcap2-bin:
pkg.installed:
- name: {{ restic_deps.libcap }}
# Allow restic do read alls files without root-rights
set-cap:
cmd.run:
- name: /usr/sbin/setcap cap_dac_read_search=+ep /var/lib/restic/restic
- unless: /usr/sbin/getcap /var/lib/restic/restic|grep -q cap_dac_read_search+ep
- require:
- pkg: libcap2-bin
#
# Create a SSH Client config
#
ssh-client-conf:
file.managed:
- name: /var/lib/restic/.ssh/config
- contents: |
HashKnownHosts no
Host restic-server
StrictHostKeyChecking No
Hostname {{ pillar['restic_server'] }}
User restic
Port 22
#
# Create a password used for the backup encryption
#
password-create:
cmd.run:
- name: openssl rand -hex 20 > .restic-password && chmod 0600 .restic-password
- cwd: /var/lib/restic
- runas: restic
- creates:
- /var/lib/restic/.restic-password
#
# Backup the genrated password to the salt master
# to restore if the machine gets completely lost
#
password-backup:
module.run:
- name: cp.push
- path: /var/lib/restic/.restic-password
#
# Initialize the remote repository where the backups will be stored
#
repo-init:
cmd.run:
- name: ./restic -p .restic-password -r sftp:restic-server:./{{ grains['id'] }} init
- runas: restic
- cwd: /var/lib/restic
- unless: ./restic -p .restic-password -r sftp:restic-server:./{{ grains['id'] }} stats
- require:
- cmd: password-create
- module: password-backup
#
# Optionally store the password on the backup server
# for direct access to unencrypted backups
#
sftp-backup-to-restic-server:
cmd.run:
- name: |
sftp restic-server <<EOF
cd {{ grains['id'] }}
pwd
PUT .restic-password
ls -a
EOF
- runas: restic
- cwd: /var/lib/restic
- require:
- cmd: repo-init
/var/lib/restic/data:
file.directory:
- user: restic
- group: restic
- mode: 0700
#
# Create a script that will execute the backup
#
/var/lib/restic/run.sh:
file.managed:
- user: restic
- group: restic
- mode: 0700
- contents: |
#!/bin/bash
set -e
cd /var/lib/restic
# Do the backup
./restic -p .restic-password -r sftp:restic-server:./{{ grains['id'] }} backup --files-from ./files_to_backup
# Remove old backups
./restic -p .restic-password -r sftp:restic-server:./{{ grains['id'] }} forget --keep-last 7 --prune
#
# Create the list of files or folders to backup
#
/var/lib/restic/files_to_backup:
file.managed:
- user: restic
- groupd: restic
- mode: 0600
- contents: |
/root
/etc
/var/lib/restic/data
#
# Create the cronjob
#
install-cron:
pkg.installed:
- name: {{ restic_deps.cron }}
run-cron:
service.running:
- name: {{ restic_deps.crond }}
- enable: true
restic-cron:
cron.present:
- name: |
/var/lib/restic/run.sh > /var/lib/restic/last.log 2>&1
- user: restic
- minute: '*/5'
- identifier: RESTIC
- require:
- file: /var/lib/restic/files_to_backup
- file: /var/lib/restic/run.sh
- pkg: install-cron
😯 Probleme:
Die Liste der Ordner, welche gesichert werden, ist „hart kodiert“. Was machen Sie, wenn Systeme unterschiedliche Ordner sichern sollen?
🧩 Aufgabe:
Speichern Sie die Backup-Ordner in einem Pillar und erweitern Sie den State, sodass
/var/lib/restic/files_to_backup
aus einem Pillar gelesen wird.
Backups prüfen
Prüfen Sie, wann das letzte Backup erstellt wurde, z. B. mit einem State:
restic-report:
cmd.run:
- name: |
./restic -p .restic-password -r sftp:restic-server:./{{grains.id}} snapshots
- cwd: /var/lib/restic
- runas: restic
Zurücksichern
Oder prüfen Sie die Backups direkt auf dem Backup-Server, indem Sie die verschlüsselte Backupdatei auf dem Backup-Server mounten.
# Change to the restic user account
root@server:~# su - restic
# Create a folder to mount a backup
restic@server:~$ mkdir -p mnt/<MINION_ID>
# Mount a backup
restic@server:~$ ./restic -r <MINION_ID> mount mnt/<MINION_ID>/ -p <MINION_ID>/.restic-password
Das zum Mounten benötigte Password entnehmen Sie der Datei /var/cache/salt/master/minions/<CLIENT>/files/var/lib/restic/.restic-password
auf dem Salt-Master.
Weitere Information zum Zurücksichern in der 📖 Restic Dokumentation.
😯 Problem:
Falls Sie das Backup nicht mounten können, ist das fuse
Paket nicht installiert. Erweitern Sie den restic.server
State und installieren Sie darüber das benötigte Paket.
Backups überwachen
Optional können Sie mit dem kostenlosen Dienst Betteruptime.com ein Monitoring der Backups einrichten.
#
# Create a monitoring at betteruptime.com
#
{% set token='xxx' %}
register-monitoring:
cmd.run:
- runas: restic
- cwd: /var/lib/restic
- name: |
curl -sf --request POST \
-o monitoring-conf.json \
--url https://betteruptime.com/api/v2/heartbeats \
--header 'Authorization: Bearer {{ token }}' \
--header 'Content-Type: application/json' \
--data '{
"name": "{{ grains['id'] }} Restic Backup",
"period": 86400,
"grace": 3600
}'
- creates: /var/lib/restic/monitoring-conf.json
Mit diesem State wird ein Monitoring Item auf dem Dashboard von Betteruptime registriert. Dieses Item erwartet alle 24 Stunden eine positive Rückmeldung, andernfalls wird ein Alarm ausgelöst. Erweitern Sie das Skript, welches das Backup durchführt, mit folgender Zeile:
curl -fs $(jq -r .data.attributes.url < monitoring-conf.json)
Last updated