TL;DR
Automatisches Backup-System für Paperless-NGX mit täglichen Backups, wöchentlicher Rotation und optionalem Offsite-Transfer. Alles läuft via Cron-Job und einem simplen Bash-Script.
Warum überhaupt Backups?
Paperless-NGX ist großartig – alle Dokumente digitalisiert, durchsuchbar und ordentlich organisiert. Aber was passiert, wenn die Festplatte den Geist aufgibt, ein Update schiefgeht oder man sich aus Versehen die Datenbank zerschießt? Genau: Game Over.
Deshalb habe ich mir ein Backup-Konzept gebaut, das automatisch läuft und mich nachts ruhig schlafen lässt.
Das Konzept
Die Anforderungen
- Automatisch: Kein manuelles Eingreifen nötig
- Vollständig: Datenbank, Medien und Konfiguration
- Versioniert: Mehrere Backup-Generationen
- Offsite-fähig: Optional auf externen Speicher (NAS, Cloud, etc.)
- Ressourcenschonend: Läuft nachts, wenn eh nichts los ist
Die Backup-Strategie
Ich setze auf ein 3-2-1-Prinzip (oder zumindest so nah wie möglich dran):
- 3 Kopien der Daten (Produktiv + 2 Backups)
- 2 verschiedene Medien (lokale Festplatte + NAS/Cloud)
- 1 Offsite-Kopie (außerhalb des Servers)
Backup-Rotation
- Täglich: Die letzten 7 Tage
- Wöchentlich: Die letzten 4 Wochen
- Optional: Monatliche Backups für längere Aufbewahrung
Das Backup-Script
Das Script macht folgendes:
- Stoppt Paperless-Container (optional, für konsistente Backups)
- Exportiert die PostgreSQL-Datenbank
- Packt alles zusammen: DB-Dump, Media-Files, Config
- Erstellt ein komprimiertes Archiv mit Timestamp
- Startet Paperless wieder
- Löscht alte Backups nach Rotation-Schema
- Optional: Sync zu externem Speicher
#!/bin/bash
###############################################################################
# Paperless-NGX Backup Script
# Erstellt vollständige Backups inkl. Datenbank, Medien und Konfiguration
###############################################################################
# Konfiguration
PAPERLESS_DIR="/opt/paperless-ngx"
BACKUP_DIR="/mnt/backups/paperless"
COMPOSE_FILE="$PAPERLESS_DIR/docker-compose.yml"
RETENTION_DAYS=7
RETENTION_WEEKS=4
# Optional: Offsite Backup (NAS, rsync, rclone, etc.)
OFFSITE_ENABLED=false
OFFSITE_DEST="/mnt/nas/backups/paperless"
# Timestamp für Backup
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
BACKUP_NAME="paperless_backup_$TIMESTAMP"
TEMP_DIR="/tmp/$BACKUP_NAME"
# Logging
LOG_FILE="$BACKUP_DIR/backup.log"
log() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# Backup-Verzeichnis erstellen
mkdir -p "$BACKUP_DIR"
mkdir -p "$TEMP_DIR"
log "=== Paperless-NGX Backup gestartet ==="
# 1. Container stoppen (optional - für konsistente Backups)
log "Stoppe Paperless-Container..."
cd "$PAPERLESS_DIR" || exit 1
docker compose -f "$COMPOSE_FILE" stop webserver
# 2. Datenbank exportieren
log "Exportiere PostgreSQL-Datenbank..."
docker compose -f "$COMPOSE_FILE" exec -T db pg_dump -U paperless paperless > "$TEMP_DIR/database.sql"
if [ $? -eq 0 ]; then
log "Datenbank-Export erfolgreich"
else
log "FEHLER: Datenbank-Export fehlgeschlagen!"
docker compose -f "$COMPOSE_FILE" start webserver
exit 1
fi
# 3. Media-Files kopieren
log "Kopiere Media-Files..."
cp -r "$PAPERLESS_DIR/media" "$TEMP_DIR/"
cp -r "$PAPERLESS_DIR/data" "$TEMP_DIR/"
# 4. Konfiguration sichern
log "Sichere Konfiguration..."
cp "$PAPERLESS_DIR/docker-compose.yml" "$TEMP_DIR/"
cp "$PAPERLESS_DIR/.env" "$TEMP_DIR/" 2>/dev/null || log "Keine .env Datei gefunden"
# 5. Container wieder starten
log "Starte Paperless-Container..."
docker compose -f "$COMPOSE_FILE" start webserver
# 6. Backup komprimieren
log "Komprimiere Backup..."
cd /tmp || exit 1
tar -czf "$BACKUP_DIR/$BACKUP_NAME.tar.gz" "$BACKUP_NAME"
if [ $? -eq 0 ]; then
log "Backup erfolgreich erstellt: $BACKUP_NAME.tar.gz"
BACKUP_SIZE=$(du -h "$BACKUP_DIR/$BACKUP_NAME.tar.gz" | cut -f1)
log "Backup-Größe: $BACKUP_SIZE"
else
log "FEHLER: Backup-Komprimierung fehlgeschlagen!"
exit 1
fi
# Temp-Verzeichnis aufräumen
rm -rf "$TEMP_DIR"
# 7. Alte Backups löschen (Rotation)
log "Lösche alte Backups..."
# Täglich: Behalte letzte 7 Tage
find "$BACKUP_DIR" -name "paperless_backup_*.tar.gz" -type f -mtime +$RETENTION_DAYS -delete
# Optional: Wöchentliche Backups behalten
# Hier könnte man zusätzliche Logik einbauen für wöchentliche/monatliche Backups
log "Alte Backups bereinigt"
# 8. Optional: Offsite-Backup
if [ "$OFFSITE_ENABLED" = true ]; then
log "Starte Offsite-Backup..."
mkdir -p "$OFFSITE_DEST"
# Beispiel mit rsync (anpassen je nach Setup)
rsync -avz --delete "$BACKUP_DIR/" "$OFFSITE_DEST/"
# Alternativ mit rclone (z.B. für Cloud-Storage):
# rclone sync "$BACKUP_DIR" "remote:paperless-backups"
if [ $? -eq 0 ]; then
log "Offsite-Backup erfolgreich"
else
log "WARNUNG: Offsite-Backup fehlgeschlagen!"
fi
fi
# Backup-Statistik
BACKUP_COUNT=$(ls -1 "$BACKUP_DIR"/paperless_backup_*.tar.gz 2>/dev/null | wc -l)
log "Anzahl vorhandener Backups: $BACKUP_COUNT"
log "=== Backup abgeschlossen ==="
# Optional: Benachrichtigung senden (z.B. via ntfy, gotify, email, etc.)
# curl -d "Paperless Backup erfolgreich: $BACKUP_SIZE" ntfy.sh/mein-paperless-backup
Code-Sprache: PHP (php)
Der Cron-Job
Um das Backup automatisch laufen zu lassen, richte ich einen Cron-Job ein:
# Crontab bearbeiten
sudo crontab -e
Code-Sprache: PHP (php)
Eintrag für tägliches Backup um 3 Uhr nachts:
# Paperless-NGX Backup - täglich um 3:00 Uhr
0 3 * * * /opt/paperless-ngx/scripts/backup.sh >> /mnt/backups/paperless/backup.log 2>&1
Code-Sprache: PHP (php)
Alternative Cron-Schedules
# Alle 6 Stunden
0 */6 * * * /opt/paperless-ngx/scripts/backup.sh
# Jeden Sonntag um 2 Uhr (wöchentlich)
0 2 * * 0 /opt/paperless-ngx/scripts/backup.sh
# Werktags um 1 Uhr nachts
0 1 * * 1-5 /opt/paperless-ngx/scripts/backup.sh
Code-Sprache: PHP (php)
Installation & Setup
1. Script vorbereiten
# Verzeichnis für Scripts erstellen
sudo mkdir -p /opt/paperless-ngx/scripts
# Script erstellen
sudo nano /opt/paperless-ngx/scripts/backup.sh
# Script ausfü
Code-Sprache: PHP (php)

Schreibe einen Kommentar