Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung Backup & Datensicherung 05.11.2026 · 9 min Lesezeit

Notfallprobe: VPS ins Heimnetz sichern und Dienste wiederherstellen

Teil 19 der Reihe Server im Netz: Der VPS sichert mit restic über einen frp-Tunnel in einen append-only rest-server im Heimnetz. Dann werden Webstack und Forgejo gelöscht und zurückgeholt, mit gemessener Zeit bis zur ersten Antwort und einer Falle aus dem echten Betrieb.

Geprüft am 05.11.2026 · für restic 0.18.1, rest-server 0.14.0, frp 0.72.0

Mit KI erstellt – redaktionelle Prüfung ausstehend

WerbelinksMit * 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

Symbolbild: Server mit leuchtendem Kabel zu einem kleinen Speicher, Titel Die Probe für den Ernstfall

Ein Backup ist erst etwas wert, wenn die Wiederherstellung einmal geklappt hat. Diese Anleitung sichert den VPS der Reihe mit restic in das eigene Heimnetz, ohne dort einen Port zu öffnen, und spielt danach den Ernstfall durch: Der Webserver mit allen Zertifikaten wird gelöscht, dann die Daten von Forgejo samt Datenbank. Beide Male läuft die Stoppuhr, bis der Dienst wieder antwortet. Dabei zeigte sich eine Falle, die ein Testlauf auf einem leeren System kaum gefunden hätte.

Dies ist Teil 19 der Reihe „Server im Netz“. Als Beispiel dient ein netcup-VPS mit Ubuntu 24.04 und Docker, auf dem die Dienste der Reihe im Host-Netz laufen. Teil 16 hat die umgekehrte Richtung gebaut: dort sichert das HomeLab auf den VPS.

Voraussetzungen

  • Ein VPS mit Docker und frps aus Teil 8, dort mit proxyBindAddr = "127.0.0.1" und allowPorts = [ { single = 2222 } ].
  • Ein Rechner mit Docker im Heimnetz, der dauerhaft läuft, zum Beispiel ein NAS oder ein kleiner Server.
  • Der Token von frps als Datei frp-token auf dem Rechner im Heimnetz.
  • Grundwissen zu Docker Compose, siehe Docker Compose unter Linux.

Schritt 1: Das Ziel im Heimnetz

Im Heimnetz laufen zwei Container: der rest-server von restic als Speicher und frpc, der eine ausgehende Verbindung zum VPS aufbaut. Von außen ist im Heimnetz nichts erreichbar. Der rest-server läuft mit --append-only: Neue Daten darf der VPS schreiben, löschen darf er nichts. Wer den VPS übernimmt, kann also die Sicherungen nicht vernichten.

# compose.yaml im Heimnetz
services:
  rest-server:
    image: restic/rest-server:0.14.0
    restart: unless-stopped
    environment:
      OPTIONS: "--append-only --private-repos"
    volumes:
      - ./daten:/data
  frpc:
    image: fatedier/frpc:v0.72.0
    restart: unless-stopped
    command: ["-c", "/etc/frp/frpc.toml"]
    volumes:
      - ./frpc.toml:/etc/frp/frpc.toml:ro
      - ./frp-token:/etc/frp/frp-token:ro
    depends_on: [rest-server]
# frpc.toml
serverAddr = "sedv-lab.de"
serverPort = 7000
loginFailExit = false
auth.method = "token"
auth.tokenSource.type = "file"
auth.tokenSource.file.path = "/etc/frp/frp-token"

[[proxies]]
name = "heim-backup"
type = "tcp"
localIP = "rest-server"
localPort = 8000
remotePort = 2222

Den Zugang legen Sie mit einem zufälligen Passwort für den Benutzer vps an. Wegen --private-repos darf dieser Benutzer nur in das Repository /vps/ schreiben.

umask 077; openssl rand -hex 16 > vps-pw
mkdir -p daten
docker run --rm --entrypoint htpasswd httpd:2.4-alpine -B -C 10 -nb vps "$(cat vps-pw)" > daten/.htpasswd
docker compose up -d

Verifizieren: docker compose logs frpc meldet start proxy success, der rest-server meldet Append only mode enabled und Private repositories enabled.

Schritt 2: Den Tunnel vom VPS aus prüfen

Auf dem VPS lauscht frps jetzt auf 127.0.0.1:2222, von außen ist der Port nicht erreichbar. Legen Sie das Passwort aus Schritt 1 auf dem VPS als /root/sin/teil19/heim-http-pw ab, mit Rechten 600.

curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:2222/vps/config
curl -s -o /dev/null -w '%{http_code}\n' -u vps:"$(cat /root/sin/teil19/heim-http-pw)" http://127.0.0.1:2222/vps/config

Verifizieren: Ohne Anmeldung kommt 401, mit Anmeldung 404, weil es noch kein Repository gibt.

Schritt 3: restic auf dem VPS

restic läuft als Container, ein kleines Skript setzt Ziel, Passwort und die Ordner, die gesichert werden. Gesichert werden die Ordner aller Dienste und die beiden Volumes von Caddy mit den Zertifikaten.

#!/bin/sh
# /root/sin/teil19/restic.sh: restic ins Heimnetz, Ziel ist der frp-Tunnel auf 127.0.0.1:2222
exec docker run --rm --network host \
  -e RESTIC_REPOSITORY="rest:http://vps:$(cat /root/sin/teil19/heim-http-pw)@127.0.0.1:2222/vps/" \
  -e RESTIC_PASSWORD_FILE=/pw -v /root/sin/teil19/restic-pw:/pw:ro \
  -v /root/sin:/quelle/sin:ro \
  -v /var/lib/docker/volumes/web_caddy_data/_data:/quelle/caddy_data:ro \
  -v /var/lib/docker/volumes/web_caddy_config/_data:/quelle/caddy_config:ro \
  -v /root/sin/teil19/restore:/restore \
  -v /root/sin/teil19/cache:/root/.cache/restic \
  -h sedv-vps restic/restic:0.18.1 "$@"
cd /root/sin/teil19
umask 077; openssl rand -hex 24 > restic-pw
chmod 700 restic.sh; mkdir -p restore
./restic.sh init
./restic.sh backup /quelle --exclude /quelle/sin/teil16/data --exclude /quelle/sin/teil19

Die erste Sicherung las 1354 Dateien mit 59,5 MiB und war nach gut 3 Sekunden fertig. Im Heimnetz kamen 20,8 MiB an, restic komprimiert und entfernt doppelte Blöcke. Den Ordner mit dem eigenen Repository aus Teil 16 haben wir ausgenommen, er ist selbst schon eine Sicherung.

Verifizieren: ./restic.sh snapshots listet den neuen Snapshot mit Host sedv-vps.

Schritt 4: Append-only beweisen

Ein Angreifer mit Root auf dem VPS hat Passwort und Zugang. Er versucht als Erstes, die Sicherungen zu löschen:

./restic.sh forget latest
Remove(<snapshot/e1e47af536>) failed: unexpected HTTP response (403): 403 Forbidden
unable to remove snapshot/e1e47af5363c1d444f7cc6f21eea152010d77899d9f7dc4c26f64a803f16d870 from the repository
Grafik: Sicherung vom VPS über den frp-Tunnel in den rest-server im Heimnetz
Grafik Ablauf VPS, Tunnel, Heimnetz

Verifizieren: ./restic.sh snapshots zeigt den Snapshot weiterhin. Alte Snapshots räumen Sie im Heimnetz auf, mit einem Zugang ohne append-only, so wie in Teil 16 auf dem VPS. Nehmen Sie dafür forget --keep-within: Ein Angreifer könnte vom VPS aus viele leere Snapshots mit frischem Zeitstempel anlegen, und Regeln wie --keep-last würden dann die echten Snapshots wegräumen. Löschen kann er nichts, die Platte im Heimnetz füllen aber schon, behalten Sie den Platz im Blick.

Schritt 5: Der Notfallzettel

Ist der VPS weg, sind auch restic-pw und heim-http-pw weg. Ohne das Passwort des Repositorys sind die Daten im Heimnetz nicht lesbar. Legen Sie deshalb außerhalb des VPS ab, zum Beispiel im Passwortmanager:

  • das Passwort des Repositorys (restic-pw),
  • das Passwort des Benutzers vps und den Token von frps,
  • das Skript restic.sh und die Liste der Volumes, die es sichert.

Verifizieren: Prüfen Sie, ob Sie jeden Punkt ohne Zugriff auf den VPS finden.

Schritt 6: Probe 1, der Webstack ist weg

Caddy ist die Eingangstür aller Dienste der Reihe. Die folgenden Befehle stoppen den Stack, löscht den Ordner mit Caddyfile und Website sowie beide Volumes mit den Zertifikaten, holt alles aus dem Heimnetz zurück und misst bis zur ersten Antwort mit HTTP 200.

cd /root/sin/web && docker compose down
rm -rf /root/sin/web; docker volume rm web_caddy_data web_caddy_config
cd /root/sin/teil19; rm -rf restore/*
./restic.sh restore latest --path /quelle --target /restore --include /quelle/sin/web \
  --include /quelle/caddy_data --include /quelle/caddy_config
mkdir -p /root/sin/web && cp -a restore/quelle/sin/web/. /root/sin/web/
docker volume create web_caddy_data; docker volume create web_caddy_config
cp -a restore/quelle/caddy_data/. /var/lib/docker/volumes/web_caddy_data/_data/
cp -a restore/quelle/caddy_config/. /var/lib/docker/volumes/web_caddy_config/_data/
cd /root/sin/web && docker compose up -d

Der erste Anlauf scheiterte. Während des Restores, noch vor dem Zurückkopieren, lief der Cron-Job von GoAccess aus Teil 7 und legte /root/sin/web/log neu an. Weil der Zielordner damit schon da war, kopierte cp -a restore/quelle/sin/web /root/sin/web alles nach /root/sin/web/web, und docker compose up meldete no configuration file provided: not found. Mit mkdir -p und dem Punkt am Ende der Quelle wie oben landen die Dateien immer richtig.

Der zweite Anlauf brauchte 2,7 Sekunden vom Start des Restores bis HTTP 200. restic war nach 1,7 Sekunden fertig, der Rest war das Kopieren und der Start von Caddy. Weil die Zertifikate aus dem Volume zurückkamen, holte Caddy kein neues Zertifikat bei Let's Encrypt. Bei vielen Subdomains und mehreren Neuaufbauten am Tag wäre das sonst eine Frage der Rate-Limits.

Grafik: gemessene Zeiten der Wiederherstellung
Grafik Messwerte der Notfallprobe

Verifizieren: curl -sI https://sedv-lab.de/ antwortet mit 200, und docker logs caddy enthält keine Zeile certificate obtained.

Schritt 7: Probe 2, Forgejo mit Datenbank

Forgejo aus Teil 15 speichert in SQLite. Eine Kopie der Datenbankdatei im laufenden Betrieb kann unvollständig sein. Deshalb stoppt die Sicherung Forgejo kurz. Vorher legten wir ein Ticket mit dem Titel „Notfallprobe Marker 1638“ an.

docker stop forgejo
./restic.sh backup /quelle/sin/teil15 --tag forgejo
docker start forgejo

Vom Stopp bis Forgejo wieder antwortete, vergingen 3,9 Sekunden. Dann der Ausfall: docker compose down und rm -rf /root/sin/teil15/forgejo. Der Restore läuft wie in Schritt 6, mit --tag forgejo statt --path und dem Ordner von Forgejo als --include.

Nach 4,4 Sekunden meldete /api/healthz wieder 200. Das Ticket „Notfallprobe Marker 1638“ war da, und git ls-remote lieferte denselben Commit wie vorher. Der Runner startete schneller als Forgejo, brach einmal mit unavailable: 502 Bad Gateway ab und meldete sich nach dem automatischen Neustart mit declared successfully zurück.

Für den Alltag gilt dasselbe: Die regelmäßige Sicherung sollte Forgejo kurz stoppen oder vorher einen Dump ziehen, etwa mit forgejo dump. Das Skript rufen Sie dann per Cron oder systemd-Timer auf, wie den Sicherheitsbericht in Teil 18.

Verifizieren: docker ps zeigt forgejo und forgejo-runner mit Status Up.

Schritt 8: Alles zurück in einen leeren Ordner

Für den Fall, dass nichts mehr da ist, sicherten wir noch einmal alles und holten den ganzen Snapshot in einen leeren Ordner:

./restic.sh backup /quelle --exclude /quelle/sin/teil16/data --exclude /quelle/sin/teil19
rm -rf restore/*
./restic.sh restore latest --path /quelle --target /restore
./restic.sh check

2149 Dateien und Ordner mit 59,5 MiB waren nach 5,9 Sekunden da, restic check meldete no errors were found. Über alle Snapshots lag die Kompressionsrate bei 3,41 zu 1.

Darstellung: Löschversuch mit 403, Restore und restic check im Terminal
Darstellung: Löschversuch und Restore im Terminal

Verifizieren: du -sh /root/sin/teil19/restore zeigt die Größe, danach den Ordner wieder leeren.

Typische Fehler

  • no configuration file provided: not found nach dem Restore: Der Zielordner existierte schon, cp -a hat einen Unterordner angelegt. Prüfen Sie mit ls, kopieren Sie mit quelle/. in den Zielordner, und stoppen Sie Cron-Jobs, die in den Ordner schreiben, während der Probe.
  • unexpected HTTP response (403) bei forget oder prune: Das ist append-only und gewollt. Aufräumen im Heimnetz.
  • 401 beim Zugriff auf den Tunnel: Benutzer oder Passwort passen nicht zur .htpasswd, oder der Pfad ist nicht /vps/. Mit --private-repos muss der Pfad dem Benutzernamen entsprechen.
  • fail to invoke Declare ... 502 Bad Gateway beim Runner: Forgejo war noch nicht bereit. Die Neustart-Regel restart: unless-stopped des Containers fängt das ab, ein Healthcheck mit depends_on macht es sauber.

Häufige Fragen

Warum sichert der VPS ins Heimnetz und nicht in die Cloud?

Der VPS liegt schon in einem Rechenzentrum. Eine Kopie zu Hause liegt außerhalb des Anbieters, an einem anderen Ort und unter Ihrer Kontrolle. Mit dem Tunnel braucht der Router dafür keine Portfreigabe.

Wie schnell geht das bei mehr Daten?

Hier waren es 59,5 MiB. Beim Restore fließen die Daten vom Heimnetz zum VPS, also über den Upload Ihres Anschlusses. Der begrenzt bei großen Datenmengen die Zeit.

Reicht ein Snapshot des Anbieters nicht?

Ein Snapshot liegt beim selben Anbieter und oft im selben Konto. Ist das Konto gesperrt oder übernommen, ist er mit weg. Er ist eine gute Ergänzung für schnelle Rückwege, aber keine Kopie außer Haus.

Fazit

Mit rest-server im Heimnetz und einem frp-Tunnel bekommt der VPS ein Ziel, das er beschreiben, aber nicht löschen kann. Die Probe hat sich gelohnt: Der Restore selbst dauerte Sekunden, gescheitert wäre er an einem Cron-Job, der den Zielordner wieder anlegt. Solche Fehler findet nur, wer den Ernstfall auf dem echten System durchspielt. Ein kompletter Neuaufbau auf leerem Server folgt kurz vor Teil 20.

Weiterführende Anleitungen und Quellen

Server im Netzresticrest-serverBackupfrpNotfallplanForgejo