Backrest mit Docker Compose: restic-Backups per Weboberfläche planen und wiederherstellen
Backrest legt Weboberfläche und Scheduler über restic. Die Anleitung zeigt compose.yaml, Login, lokales Repository, Backup-Plan mit Aufbewahrung, Prüfungen und Restore mit Prüfsummenvergleich, getestet mit Version 1.14.1.
Werbung Mit * markierte Links sind Werbelinks: Bei einem Kauf erhalten wir eine Provision, der Preis bleibt gleich. Als Amazon-Partner verdiene ich an qualifizierten Verkäufen. Mehr dazu

restic erstellt verschlüsselte, deduplizierte Backups, scheitert im Alltag aber an unüberwachten Cronjobs und einem Restore, den nur eine Person beherrscht. Backrest legt Weboberfläche und Scheduler über restic, plant Backups, Prune und Check, zeigt jede Operation mit Status und stellt einzelne Dateien per Klick wieder her.
Alle Befehle und Fehlermeldungen beziehen sich auf Backrest 1.14.1. Die Kommandozeilen-Variante steht in der Anleitung zu restic mit Cron.
Was Backrest ist und wo die Grenzen liegen
Backrest ist ein Go-Dienst (GPL-3.0), der die restic-Kommandozeile aufruft und Ergebnisse in einer SQLite-Historie speichert. Aktuell: v1.14.1.
Was Backrest leistet:
- restic-Repositories lokal oder auf S3, B2, SFTP, Azure, GCS, rclone
- Backup-Pläne mit Pfaden, Ausschlüssen, Zeitplan (Cron oder Intervall) und Aufbewahrung
- Geplantes
pruneundcheckje Repository - Snapshot-Browser und Restore einzelner Dateien oder Verzeichnisse
- Hooks und Benachrichtigungen (Gotify, Healthchecks, Slack, Discord, Telegram, Webhook)
- JSON-API für Skripte
Grenzen: Backrest sichert Dateien, keine konsistenten Datenbankzustände (Dump per Hook). Ein lokales Repository schützt nicht vor Hardwareverlust oder Ransomware, eine Kopie außer Haus gehört dazu (Anleitung Immutable Backups nach 3-2-1-1-0 mit restic). Repository-Passwörter stehen im Klartext in der config.json.
Voraussetzungen und Ressourcen
Der Container belegt im Leerlauf 7 MiB RAM, das Image 315 MB. Bei Backups steigt der Bedarf, bei Millionen Dateien auf mehrere hundert MB.
- Linux-Host mit Docker Engine und Compose-Plugin. Wie Sie beides auf Debian oder Ubuntu installieren, zeigt die Anleitung Docker und Docker Compose auf Linux installieren (Ubuntu/Debian).
- Lesezugriff auf die zu sichernden Verzeichnisse
- Repository-Ziel: Platte, NAS, S3-kompatibler Speicher oder SFTP
- Passwortmanager für das Repository-Passwort, ohne es ist kein Restore möglich
Unterstützte Plattformen und Image-Tags
Das GHCR-Image gibt es für amd64, arm64, arm/v6, arm/v7 und 386 (dazu native Builds). Die Tags tragen das v des Release-Namens.
| Tag | In der Registry | Hinweis |
|---|---|---|
v1.14.1 | vorhanden | Standard-Image mit rclone |
v1.14.1-alpine | vorhanden | Alpine-Variante |
v1.14.1-scratch | vorhanden | ohne Shell, keine Shell-Hooks |
latest | vorhanden | wandert mit, besser pinnen |
1.14.1 | nicht vorhanden | ohne v schlägt der Pull fehl |
Beim Start meldet Backrest 1.14.1 das mitgelieferte /bin/restic 0.19.1 (dazu rclone v1.74.4). Fehlt ein passendes restic, lädt es eine signaturgeprüfte Version von GitHub.
Schritt 1: Vollständige compose.yaml und .env
Basis ist das README-Beispiel mit Port nur an 127.0.0.1, schreibgeschützten Quelldaten, Healthcheck, fester Version statt :latest und ohne die veraltete Zeile version:. Die .env enthält nur Pfade und Zeitzone. Wie Healthchecks in Compose funktionieren, zeigt die Anleitung Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only.
services:
backrest:
image: ghcr.io/garethgeorge/backrest:v1.14.1
container_name: backrest
hostname: backrest
volumes:
- ./backrest/data:/data
- ./backrest/config:/config
- ./backrest/cache:/cache
- ./backrest/tmp:/tmp
- ./backrest/rclone:/root/.config/rclone
- ${BACKUP_SOURCE}:/userdata:ro
- ${REPO_PATH}:/repos
- ./restore:/restore
environment:
- BACKREST_DATA=/data
- BACKREST_CONFIG=/config/config.json
- XDG_CACHE_HOME=/cache
- TMPDIR=/tmp
- TZ=${TZ}
ports:
- "127.0.0.1:${BACKREST_HOST_PORT}:9898"
healthcheck:
test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://127.0.0.1:9898/"]
interval: 30s
timeout: 5s
retries: 3
start_period: 20s
restart: unless-stopped
# .env für Backrest
TZ=Europe/Berlin
BACKREST_HOST_PORT=9898
BACKUP_SOURCE=/srv/daten
REPO_PATH=/mnt/backup/restic
| Pfad oder Variable | Zweck |
|---|---|
/data (BACKREST_DATA) | Operationshistorie oplog.sqlite, jwt-secret, Logs |
/config/config.json (BACKREST_CONFIG) | Konfiguration: Repos, Passwörter, Pläne, Benutzer |
/cache (XDG_CACHE_HOME) | restic-Cache, beim Backup verzichtbar |
/userdata | Quelldaten (schreibgeschützt) |
/repos | Lokale restic-Repositories |
/restore | Beschreibbares Restore-Ziel |
TZ | Zeitzone für Cron mit lokaler Uhr |
/restore ist nötig, weil ein Restore nach /userdata (schreibgeschützt) fehlschlägt.
docker compose config -q im Projektordner gibt nichts aus. Die Pfade aus BACKUP_SOURCE und REPO_PATH existieren auf dem Host.
Schritt 2: Installation und Start
# Verzeichnis anlegen, compose.yaml und .env ablegen
mkdir -p /opt/backrest && cd /opt/backrest
# Image laden und Container starten
docker compose up -d
# Startmeldungen prüfen
docker compose logs --no-log-prefix | head -20
Startmeldungen:
Setting docker defaults for env variables:
- BACKREST_PORT="0.0.0.0:9898"
INFO backrest starting {"version": "1.14.1", "commit": "875c9cb5..."}
INFO restic binary "/bin/restic" in $PATH matches required version 0.19.1, it will be used for backrest commands
INFO generating new auth secret
INFO starting web server {"addr": "0.0.0.0:9898"}
Das Log enthält backrest starting mit der Version 1.14.1 und starting web server.
Schritt 3: Funktionsprüfung und Healthcheck
# Status inklusive Healthcheck
docker compose ps
# Weboberfläche antwortet mit HTTP 200
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:9898/
Nach rund 30 Sekunden zeigt docker compose ps (healthy), die Startseite liefert 200. wget und curl sind im Image, in der scratch-Variante nicht.
docker compose ps zeigt (healthy), curl liefert 200.
Schritt 4: Erstkonfiguration, Login und Instanz-ID
Rufen Sie http://127.0.0.1:9898 auf (entfernt per ssh -L 9898:127.0.0.1:9898 server). Backrest fragt nach Instanz-ID, Benutzername und Passwort. Die Instanz-ID steht als created-by:<ID> an jedem Snapshot und ist später nicht änderbar, nehmen Sie den Hostnamen.
Bis zur Ersteinrichtung ist die API offen (GetConfig ohne Anmeldung: HTTP 200, "auth":{"disabled":true}). Richten Sie den Login sofort ein.
Per API (Automatisierung): HashPassword erwartet ein JSON-Objekt mit Feld value, ein nackter String wird mit unmarshal into *types.StringValue: proto: syntax error abgelehnt.
# bcrypt-Hash für das Admin-Passwort erzeugen lassen
curl -s -X POST http://127.0.0.1:9898/v1.Authentication/HashPassword \
-H 'Content-Type: application/json' -d '{"value":"IHR_ADMIN_PASSWORT"}'
Tragen Sie den Wert als passwordBcrypt eines Benutzers in die per GetConfig gelesene Konfiguration ein und schreiben Sie sie mit SetConfig zurück. Danach: ohne oder mit falschem Passwort 401, mit Basic Auth 200.
Ein Aufruf ohne Anmeldung wird abgelehnt:
curl -s -o /dev/null -w '%{http_code}\n' -X POST http://127.0.0.1:9898/v1.Backrest/GetConfig \
-H 'Content-Type: application/json' -d '{}'
# Erwartete Ausgabe: 401Schritt 5: Repository anlegen
Unter Add Repo vergeben Sie Namen, URI und Repository-Passwort, lokal etwa /repos/server01. Entfernt: s3:bucket/prefix, b2:bucket, sftp:user@host:/pfad, rclone:remote:pfad, Zugangsdaten als Umgebungsvariablen am Repo (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY).
Wartung im selben Dialog:
- Prune monatlich, Cron
0 3 1 * *, Uhr „Last Run Time“, Schwelle 10 Prozent - Check monatlich, Cron
0 4 1 * *, Uhr „Last Run Time“, 5 Prozent der Datenpakete lesen
„Last Run Time“ empfiehlt die Doku für seltene Operationen, damit ein verpasster Termin nicht bis zum nächsten Monat entfällt.
Das Repo erscheint in der Seitenleiste, im lokalen Pfad REPO_PATH liegen die restic-Dateien config, data, index, keys und snapshots.
Schritt 6: Backup-Plan mit Zeitplan und Aufbewahrung
Unter Add Plan verbinden Sie Quellpfade mit einem Repository. Planname und Repo sind später nicht änderbar (Empfehlung: [speicher]-[inhalt]). Beispielplan:
| Einstellung | Wert |
|---|---|
| Pfade | /userdata |
| Ausschlüsse | *.tmp |
| Zeitplan | Cron 30 1 * * *, Uhr lokal (täglich 01:30 Uhr) |
| Aufbewahrung | 7 tägliche, 4 wöchentliche, 6 monatliche, immer die letzten 3 |
Das Log zeigt die Aufgaben, auch nach einem Container-Neustart:
INFO scheduled task {"task": "backup for plan \"testdaten\"", "runAt": "2026-09-28T01:30:00+02:00"}
INFO scheduled task {"task": "prune repo \"lokal\"", "runAt": "2026-10-01T03:00:00+02:00"}
INFO scheduled task {"task": "check for repo \"lokal\"", "runAt": "2026-10-01T04:00:00+02:00"}
Backrest lehnt unmögliche Cron-Ausdrücke ab (0 0 30 2 *), klassisches Cron führt sie still nie aus.
Den ersten Lauf starten Sie mit Backup Now oder per API (blockiert bis zum Ende, geeignet für Hooks):
# Plan "testdaten" sofort ausführen
curl -X POST http://127.0.0.1:9898/v1.Backrest/Backup \
-H 'Content-Type: application/json' -u admin:IHR_ADMIN_PASSWORT \
--data '{"value": "testdaten"}'
Ein Backup von vier Dateien (600 KB) dauert 4,7 Sekunden, danach laufen forget und Indizierung automatisch.
Im Log steht für den Plan ein scheduled task mit dem nächsten Termin, die Operation „Backup“ zeigt in der Oberfläche den Status erfolgreich.
Schritt 7: Backups prüfen
- Operationshistorie: Status je Operation in der Oberfläche, per API
GetOperations(STATUS_SUCCESS,STATUS_ERROR). - Repository-Check: auch manuell startbar, meldet
STATUS_SUCCESSmit Statistik. - Gegenprobe mit restic: Das Repository ist ein normales restic-Repository, der Zugriff geht auch ohne Backrest.
# Snapshots mit restic direkt im Container auflisten
docker compose exec -e RESTIC_PASSWORD='IHR_REPO_PASSWORT' backrest \
restic -r /repos/server01 snapshots
Für Benachrichtigungen: Hook mit CONDITION_ANY_ERROR an Gotify oder Healthchecks-Ping bei CONDITION_SNAPSHOT_SUCCESS.
restic snapshots listet denselben Snapshot wie die Oberfläche, der manuelle Check endet mit Erfolg.
Schritt 8: Dateien wiederherstellen
Eine gelöschte Datei holen Sie so zurück: Snapshot öffnen, im Snapshot Browser Restore to path wählen und Ziel angeben. Ohne Ziel schreibt Backrest in ein Downloads-Verzeichnis, nutzen Sie in Docker einen gemounteten Pfad wie /restore/….
# Prüfsumme der Originaldatei vor dem Löschen
bbbf5751f586881a00d71e4662c98918cee2d2ac8cb1fe778cc2ff950228e14f source/rechnung.txt
# Prüfsumme nach Restore über Backrest
bbbf5751f586881a00d71e4662c98918cee2d2ac8cb1fe778cc2ff950228e14f /restore/r1/rechnung.txt
Auch ein vollständiger Restore und restic restore latest --include liefern identische Prüfsummen. Der Container läuft als root, wiederhergestellte Dateien gehören zunächst root.
# Wiederherstellung an Ort und Stelle zurückkopieren, Rechte anpassen
sudo cp -a /opt/backrest/restore/r1/rechnung.txt /srv/daten/
sudo chown benutzer:gruppe /srv/daten/rechnung.txt
sha256sum liefert für Original und wiederhergestellte Datei denselben Wert.
Schritt 9: Persistente Daten, Rechte und Sicherung von Backrest selbst
Alle Dateien unter ./backrest gehören root, die config.json ist für den Host-Benutzer nicht lesbar (Klartext-Passwörter). Lesen Sie sie mit docker compose exec backrest cat /config/config.json. Bei jeder Änderung entsteht config.json.bak.<Zeitstempel>.
Die Backups liegen im restic-Repository. Sichern Sie zusätzlich config und data:
# Anhalten (konsistente SQLite-Dateien)
docker compose stop
sudo tar czf backrest-config-$(date +%F).tgz -C /opt/backrest/backrest config data
docker compose start
Nach Löschen und Zurückspielen startet die Instanz mit Login und sichtbaren Snapshots. Verschlüsseln Sie das Archiv (Klartext-Passwörter) und notieren Sie das Repository-Passwort separat.
tar tzf backrest-config-*.tgz listet config/config.json und data/oplog.sqlite.
Schritt 10: Netzwerkfreigabe, Reverse Proxy und TLS
Backrest spricht nur HTTP, davor gehört ein Reverse Proxy mit TLS (Caddy-Anleitung: Caddy als Reverse Proxy mit automatischem HTTPS). Mit Caddy im selben Compose-Netz (Weiterleitung auf backrest:9898) genügt:
backup.example.de {
reverse_proxy backrest:9898
}
curl -I https://backup.example.de antwortet über TLS, ss -tlnp | grep 9898 zeigt nur 127.0.0.1:9898.
Schritt 11: Updates und Rollback-Grenzen
# Vorher Konfiguration sichern (siehe oben), dann Tag in compose.yaml anheben
docker compose pull
docker compose up -d
# Version im Log prüfen
docker compose logs --no-log-prefix | grep 'backrest starting'
Beim ersten Start migriert Backrest die Historie (zum Beispiel Schema 0 auf 6, mit Kopie oplog.sqlite-<Datum>-s06m06.backup), ein Rollback ist danach nicht garantiert. Halten Sie das Archiv von config und data bereit und lesen Sie vor größeren Sprüngen die Release-Notes (restic-Repository-Format).
Die Logzeile backrest starting nennt die neue Version, docker compose ps zeigt (healthy).
Typische Fehler mit Diagnose und Lösung
Diese Meldungen stammen wörtlich aus Backrest 1.14.1:
Fatal: wrong password or no key found(restic Exit-Code 12)Falsches Repository-Passwort. Passwort im Repo korrigieren, dann Index Snapshots.
failed to init repo ... config file already existsPfad enthält schon ein Repository. Vorhandenes Repository einbinden statt neu anlegen.
auto_initialize set with guid but guid implies that repo is already initializedautoInitializefür bereits initialisiertes Repo. Option weglassen.invalid cron "0 0 30 2 *": next scheduled time is invalidCron-Ausdruck, der nie zutrifft. Ausdruck korrigieren (crontab.guru).
restore failed output processing: cannot create target director...Restore-Ziel in schreibgeschütztem Mount. Beschreibbares Ziel wie
/restore/…verwenden.FATAL error loading config {"error": "... auth: auth enabled but no users"}, Container im Neustart-LoopNur
usersaus derconfig.jsongelöscht. Siehe folgender Absatz.
Der letzte Fall betrifft das vergessene Admin-Passwort. Die Doku empfiehlt, "users" aus der config.json zu entfernen, in 1.14.1 bricht das mit auth enabled but no users ab. Erst das Entfernen des Blocks "auth" lässt die Instanz starten, die API ist dann offen und gibt Repository-Passwörter aus. Nur bei localhost-Bindung ausführen, sofort neues Passwort vergeben.
Diagnose: docker compose logs backrest, je Operation View Logs. Mit restic erstellte Snapshots erscheinen nach Index Snapshots.
Saubere Deinstallation
Achtung, Datenverlust: Die Befehle löschen Konfiguration, Historie und mit dem Repository-Verzeichnis alle Backups unwiderruflich. Prüfen Sie vorher, ob eine andere Kopie existiert.
# Container und Netz entfernen
cd /opt/backrest
docker compose down -v --remove-orphans
# Konfiguration, Historie, Cache löschen
sudo rm -rf /opt/backrest/backrest /opt/backrest/restore
# Nur wenn die Backups weg sollen: Repository löschen
# sudo rm -rf /mnt/backup/restic
# Image gezielt entfernen
docker rmi ghcr.io/garethgeorge/backrest:v1.14.1
Entfernen Sie das Image namentlich, nicht per docker image prune.
Häufige Fragen
Ist Backrest vor der Ersteinrichtung geschützt?
Nein. Bis zur Ersteinrichtung ist die API ohne Anmeldung erreichbar (GetConfig liefert HTTP 200). Binden Sie den Port nur an 127.0.0.1 und richten Sie den Login sofort ein.
Kommen Sie auch ohne Backrest an die Backups?
Ja. Das Repository ist ein normales restic-Repository, der Zugriff geht auch direkt mit restic. Ohne das Repository-Passwort ist allerdings kein Restore möglich, bewahren Sie es separat im Passwortmanager auf.
Sichert Backrest Datenbanken konsistent?
Nein. Backrest sichert Dateien, keine konsistenten Datenbankzustände. Erzeugen Sie vorher einen Dump per Hook.
Was tun bei vergessenem Admin-Passwort?
Das Entfernen von "users" aus der config.json bricht in 1.14.1 mit auth enabled but no users ab. Erst das Entfernen des Blocks "auth" lässt die Instanz starten, die API ist dann offen und gibt Repository-Passwörter aus. Das nur bei localhost-Bindung ausführen und sofort ein neues Passwort vergeben.
Fazit
Backrest legt Zeitplan, Operationshistorie und Restore per Klick über restic, damit Backups nicht an unüberwachten Cronjobs hängen. Binden Sie den Port an 127.0.0.1, richten Sie den Login sofort ein und planen Sie Prune und Check je Repository. Sichern Sie zusätzlich config und data von Backrest, notieren Sie das Repository-Passwort separat und halten Sie eine Kopie außer Haus bereit.
Weiterführende Anleitungen und Quellen
- restic-Backups unter Linux und Windows mit Cron automatisieren
- Immutable Backups gegen Ransomware nach 3-2-1-1-0 mit restic
- Caddy als Reverse Proxy mit automatischem HTTPS


