Az otthoni NAS-on futó Nextcloud kényelmes és rugalmas megoldás, de nem szabad megfeledkezni a rendszeres, offsite backupról. Egy lemezhiba, ransomware vagy véletlen törlés bármikor megtörténhet.
Nextcloud (Docker)
↓
MariaDB dump + Nextcloud data mappa
↓
restic (titkosított, deduplikált backup)
↓
SFTP
↓
Hetzner Storage Box
Az esetemben konkrétan ezek:
/srv/docker/nextcloud/conf
/srv/docker/nextcloud/db
/mnt/data/nextcloud
+ MariaDB dump
A mentés eszköze: restic
A Storage Box-hoz a hozzáférés SSH kulccsal történik, nem jelszóval.
Az ~/.ssh/config példa:
Host hetzner-box
HostName <host>.your-storagebox.de
User <username>
Port 23
IdentityFile ~/.ssh/hetzner_storage
A backup script esetemben a nextcloud-backup.sh fájl.
Többek közt feltételezi, hogy a MariaDB container environment változói (MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE) be vannak állítva:
#!/bin/bash
set -Eeuo pipefail
#####################################
# CONFIG
#####################################
ADMIN_EMAIL="user@email.tld"
HOSTNAME="$(hostname)"
APP_CONTAINER="nextcloud-compose"
DB_CONTAINER="nextcloud-compose-db"
COMPOSE_DIR="/srv/docker/nextcloud"
DATA_DIR="/mnt/data/nextcloud"
DB_DUMP="/root/nextcloud-db.sql"
LOCKFILE="/var/run/nextcloud-backup.lock"
LOGFILE="/var/log/nextcloud-backup.log"
export RESTIC_REPOSITORY="sftp:hetzner-box:/home/backup"
export RESTIC_PASSWORD_FILE="/root/.restic-pass"
#####################################
# FUNCTIONS
#####################################
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOGFILE"
}
cleanup() {
log "Disabling maintenance mode..."
docker exec -u www-data "$APP_CONTAINER" php occ maintenance:mode --off || true
rm -f "$LOCKFILE"
}
error_handler() {
log "ERROR occurred. Cleaning up..."
exit 1
}
trap cleanup EXIT
trap error_handler ERR
#####################################
# LOCK PROTECTION
#####################################
if [ -f "$LOCKFILE" ]; then
log "Backup already running. Exiting."
exit 1
fi
touch "$LOCKFILE"
log "===== BACKUP STARTED ====="
#####################################
# ENABLE MAINTENANCE MODE
#####################################
log "Enabling maintenance mode..."
docker exec -u www-data "$APP_CONTAINER" php occ maintenance:mode --on
#####################################
# DATABASE DUMP (container env-ből)
#####################################
log "Creating MariaDB dump..."
docker exec "$DB_CONTAINER" sh -c \
'mariadb-dump -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DATABASE"' \
> "$DB_DUMP"
#####################################
# RESTIC BACKUP
#####################################
log "Running restic backup..."
restic backup \
"$DATA_DIR" \
"$COMPOSE_DIR/conf" \
"$COMPOSE_DIR/db" \
"$DB_DUMP" \
--verbose >> "$LOGFILE" 2>&1
#####################################
# RETENTION POLICY
#####################################
log "Applying retention policy..."
restic forget --prune \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 6 >> "$LOGFILE" 2>&1
log "Backup completed successfully."
touch /var/run/nextcloud-backup.success
# --- Weekly status email (Sunday = 7) ---
DAY_OF_WEEK=$(date +%u)
if [ "$DAY_OF_WEEK" -eq 7 ]; then
STATS=$(restic stats latest --mode raw-data)
SNAPSHOT_COUNT=$(restic snapshots | grep ID | wc -l)
SUBJECT="Weekly Nextcloud Backup Status on $HOSTNAME"
BODY="Weekly backup report
Hostname: $HOSTNAME
Date: $(date)
Snapshots stored: $SNAPSHOT_COUNT
Latest snapshot stats:
$STATS
"
{
echo "Subject: $SUBJECT"
echo "From: $ADMIN_EMAIL"
echo
echo "$BODY"
} | msmtp "$ADMIN_EMAIL"
log "Weekly status email sent."
fi
exit 0
Napi futás 03:00-kor cronból:
0 3 * * * /srv/docker/nextcloud/nextcloud-backup.sh
A backup script siker esetén létrehozza a /var/run/nextcloud-backup.success fájlt. Ezt ellenőrzi egy watchdog. Abban az esetben ha ez a nextcloud-backup.success fájl nincs, vagy túl régi - nem volt sikeres backup, a beállított msmtp címre riasztó emailt küld. Ezen kívül küld egy heti státusz email-t.
A watchdog esetemben a nextcloud-backup-watchdog.sh így néz ki:
#!/bin/bash
ADMIN_EMAIL="user@email.tld"
HOSTNAME="$(hostname)"
SUCCESS_FILE="/var/run/nextcloud-backup.success"
if [ ! -f "$SUCCESS_FILE" ]; then
exit 0
fi
LAST_RUN=$(stat -c %Y "$SUCCESS_FILE")
NOW=$(date +%s)
DIFF=$((NOW - LAST_RUN))
# 24 óra = 86400 másodperc
if [ "$DIFF" -gt 86400 ]; then
SUBJECT="Nextcloud Backup NOT running on $HOSTNAME"
BODY="No successful backup log update in the last 24 hours.
Last log modification:
$(date -d @$LAST_RUN)
Please check the system."
{
echo "Subject: $SUBJECT"
echo "From: $ADMIN_EMAIL"
echo
echo "$BODY"
} | msmtp "$ADMIN_EMAIL"
fi
Óránkénti futtatás cronból:
0 * * * * /srv/docker/nextcloud/nextcloud-backup-watchdog.sh
A watchdog script óránként fut le cronból, és minden egész órakor ellenőrzi, hogy az elmúlt 24 órában volt-e sikeres backup.
A mentés addig nem backup, amíg nincs restore tesztelve.
restic restore latest --target /tmp/restore-test
Eredményként hibamentes visszaállítást kell kapnunk a /tmp/restore-test mappába.