Restore: Paperless-ngx
Backup- und Restore-Pfad für die Paperless-ngx-Instanz auf paperless.mrrm.de (Host prod-alt).
Backup-Setup
- Repo:
sftp:qnap-backup:/share/Backup - Server/restic-repo(geteiltes restic-Repo, alle Hosts; Snapshots per--host-Tag separiert) - Wrapper:
/usr/local/bin/resticq(setztsftp.commandfür die QNAP, die kein registriertes SFTP-Subsystem hat) - Timer:
restic-backup.timer(täglich 03:30) - Pre-Hook:
/etc/restic-backup/pre.d/10-paperless-export.shruftdocument_exporterim Containerpaperless-paperless-webserver-1auf und schreibt den portablen Export nach/usr/src/paperless/export(gemountet als Docker-Volumepaperless_paperless-export) - Gesichertes Volume:
/var/lib/docker/volumes/paperless_paperless-export/_data(Teil vonnas_backup_dirsininventory/host_vars/prod-alt/main.yml)
Der Export enthält manifest.json (Django-Fixtures aller Documents inkl. MD5-Checksummen), metadata.json, sowie die Verzeichnisse originals/, archive/, thumbnails/.
Restore-Test (Hash-Verify)
Verifiziert das Backup ohne den Live-Stack zu berühren. Läuft auf dev-neu gegen den prod-alt-Snapshot.
# 1. Neuesten prod-alt-Snapshot mit Paperless-Export finden
. /etc/restic.env
SNAP=$(resticq snapshots \
--host prod-alt \
--path /var/lib/docker/volumes/paperless_paperless-export/_data \
--json | jq -r '.[-1].id')
# 2. Restore in Temp-Dir
TARGET=/tmp/restore-test-paperless-$(date +%Y%m%d-%H%M%S)
resticq restore "$SNAP" \
--target "$TARGET" \
--include /var/lib/docker/volumes/paperless_paperless-export/_data
EXPORT="$TARGET/var/lib/docker/volumes/paperless_paperless-export/_data"
# 3. Hash-Verify: alle MD5s aus manifest.json gegen die restored Files matchen
python3 - "$EXPORT" <<'PY'
import json, hashlib, os, sys
root = sys.argv[1]
m = json.load(open(os.path.join(root, "manifest.json")))
docs = [x["fields"] for x in m if x.get("model") == "documents.document"]
expected_orig = {d["checksum"] for d in docs if d.get("checksum")}
expected_arch = {d["archive_checksum"] for d in docs if d.get("archive_checksum")}
def md5(p):
h = hashlib.md5()
with open(p, "rb") as f:
for c in iter(lambda: f.read(65536), b""): h.update(c)
return h.hexdigest()
def check(subdir, expected):
d = os.path.join(root, subdir)
if not os.path.isdir(d): return (0, 0, len(expected))
files = [os.path.join(d, f) for f in os.listdir(d)]
found = {md5(p) for p in files}
return (len(files), len(expected & found), len(expected - found))
o = check("originals", expected_orig)
a = check("archive", expected_arch)
print(f"docs={len(docs)}")
print(f"originals: files={o[0]} matched={o[1]} missing={o[2]}")
print(f"archive: files={a[0]} matched={a[1]} missing={a[2]}")
print("OVERALL:", "PASS" if (o[2]==0 and a[2]==0) else "FAIL")
PY
# 4. Cleanup
rm -rf "$TARGET"
Letzter erfolgreicher Restore-Test
| Datum | Snapshot | Docs | Originals matched | Archive matched | Ergebnis |
|---|---|---|---|---|---|
| 2026-05-17 | 0f73d181 (2026-05-17 02:38 prod-alt) |
1 | 1/1 | 1/1 | PASS |
Echter Restore in Produktion
Wenn der prod-alt-Paperless-Stack verloren geht:
-
Stack stoppen (falls noch läuft):
cd /opt/server-stack/hosts/prod-alt/paperless && docker compose down -
Neusten Export aus dem Backup restoren:
. /etc/restic.env SNAP=$(resticq snapshots --host prod-alt \ --path /var/lib/docker/volumes/paperless_paperless-export/_data \ --json | jq -r '.[-1].id') resticq restore "$SNAP" \ --target /tmp/paperless-restore \ --include /var/lib/docker/volumes/paperless_paperless-export/_data -
Stack neu starten (legt leere Volumes an):
docker compose up -d -
Restored Export ins Volume kopieren:
docker cp /tmp/paperless-restore/var/lib/docker/volumes/paperless_paperless-export/_data/. \ paperless-paperless-webserver-1:/usr/src/paperless/export/ -
document_importer im Container ausführen:
docker exec paperless-paperless-webserver-1 document_importer \ --no-progress-bar /usr/src/paperless/exportdocument_importerlegt alle Dokumente, Tags, Korrespondenten, User und Permissions neu an. -
Verifikation: Web-UI auf
https://paperless.mrrm.deöffnen, Document-Count abgleichen.
Referenzen
- Issue: #288 (Backup-Strategie + Restore-Test)
- Code:
roles/nas-backup/imserver-stack-Repo - Paperless-Doku: Document exporter / importer