Files
app-backup/README.md

9.3 KiB
Raw Blame History

app-backup (Rocky Linux 10) Split-Backups für WordPress, Nextcloud, Gitea + DBs (OneDrive/rclone)

Dieses Repo enthält ein Backup- und Restore-Setup für typische Self-Hosted-Apps auf Rocky Linux 10:

  • WordPress (Webroot)
  • Nextcloud (Code + Data getrennt; Data liegt bei uns unter .../nextcloud/data)
  • Gitea (native Installation via systemd + MariaDB)
  • MariaDB-Dumps (WordPress DB, Nextcloud DB, Gitea DB)
  • Upload nach OneDrive per rclone

Neu in dieser Version: kein riesiges “Alles-in-eins”-Archiv mehr, sondern sauber getrennte Archives pro Komponente. Das macht Uploads stabiler (große Dateien), Restore selektiver und Fehler leichter eingrenzbar.


Ziele / Designentscheidungen

1) Split statt „dickes Archiv“

Es werden pro Lauf mehrere Archive erzeugt (zstd oder gzip):

  • ..._meta.tar.zst Meta (Timestamp, Hostname, Größeninfos)
  • ..._db.tar.zst DB Dumps (SQL Dateien)
  • ..._wordpress.tar.zst WordPress Webdaten (ohne Nextcloud-Unterordner)
  • ..._nextcloud.tar.zst Nextcloud Code/Web (mit Exclude data/)
  • ..._nextcloud-data.tar.zst Nextcloud Data separat
  • ..._gitea.tar.zst Gitea Data (APP_DATA_PATH)
  • ..._gitea-etc.tar.zst /etc/gitea (Gitea config)

Vorteile:

  • Upload stabiler bei 1218 GB (nicht 1 Monolith)
  • Restore selektiv (z.B. nur DB, nur Nextcloud-data, …)
  • Fehlerbehebung leichter (ein Archiv kaputt → nicht alles kaputt)

2) Nextcloud data unterhalb von NC_DIR

Bei uns liegt Nextcloud so:

  • NC_DIR=/var/www/html/nextcloud (Code)
  • NC_DATA_DIR=/var/www/html/nextcloud/data (Data)

Damit Data nicht doppelt gesichert wird:

  • Beim Backup von NC_DIR wird data/ explizit ausgeschlossen (rsync --exclude data/).
  • Danach wird NC_DATA_DIR als eigenes Paket gesichert.

3) WordPress liegt im Webroot /var/www/html und Nextcloud als Unterordner

Bei uns liegt:

  • WordPress im WP_DIR=/var/www/html
  • Nextcloud in /var/www/html/nextcloud

Damit Nextcloud nicht im WP-Archiv landet:

  • WP-Backup schließt nextcloud/ automatisch aus, wenn NC_DIR genau WP_DIR/nextcloud ist.

4) rclone / OneDrive robust für große Dateien

Upload wird robust gemacht mit:

  • Chunking: --onedrive-chunk-size 64M
  • Timeouts: --timeout 1h, --contimeout 30s
  • konservativ: --transfers 2, --checkers 4
  • mehr Retries: --retries 10, --low-level-retries 40

Außerdem: Remote-Namen sind case-sensitive!
Remote ist bei uns z.B. OneDrive: (nicht onedrive:).


📦 Dateien & Pfade

Skripte

  • app-backup.sh → Backup erstellen, Archive erzeugen, optional Upload.
  • app-restore.sh → Restore aus lokalem Ordner oder OneDrive-Run-Folder.
  • app-backup.conf → Konfiguration (Pfad/Services/DB/Credentials).

Zielpfade (Standard)

  • Workdir: /var/backups/app-backup
  • Archive: /var/backups/app-backup/archives
  • Logs: /var/log/app-backup

OneDrive Ziel (Beispiel)

Upload in:

OneDrive:Sicherung/JRITServerBackups/<hostname>/appbackup_<timestamp>/

🔧 Installation / Setup

1) Skripte installieren

Beispiel:

sudo install -d /etc/app-backup /usr/local/sbin
sudo install -m 0755 app-backup.sh  /usr/local/sbin/app-backup.sh
sudo install -m 0755 app-restore.sh /usr/local/sbin/app-restore.sh
sudo install -m 0640 app-backup.conf /etc/app-backup/app-backup.conf

2) DB Credential Files anlegen

Für WordPress / Nextcloud / Gitea je eine .cnf.

Beispiele:

  • /etc/app-backup/db-wordpress.cnf
  • /etc/app-backup/db-nextcloud.cnf
  • /etc/app-backup/db-gitea.cnf

Inhalt:

[client]
user=backup
password=DEIN_PASSWORT
host=localhost

Rechte:

sudo chown root:root /etc/app-backup/db-*.cnf
sudo chmod 600 /etc/app-backup/db-*.cnf

3) MariaDB Backup-User (Minimal-Rechte)

Pro DB (z.B. gitea):

CREATE USER 'backup'@'localhost' IDENTIFIED BY 'DEIN_PASSWORT';
GRANT SELECT, SHOW VIEW, TRIGGER, EVENT, LOCK TABLES ON gitea.* TO 'backup'@'localhost';
FLUSH PRIVILEGES;

Optional: denselben User für wordpress/nextcloud verwenden, dann jeweils GRANT ... ON wordpress.* etc.

4) rclone Remote prüfen (Case-Sensitive!)

Auf dem Server (als derselbe User, der später rclone nutzt typischerweise root oder johannes):

rclone listremotes
rclone lsf "OneDrive:" --max-depth 1
rclone lsf "OneDrive:Sicherung" --max-depth 1

⚠️ Wichtig: Wenn das Backup als root läuft, muss root auch Zugriff auf die rclone config haben. Typisch sind zwei Wege:

Option A root nutzt eigene rclone config

  • sudo rclone config als root durchführen und Remote anlegen.

Option B root nutzt Config von johannes

  • im Script/Service RCLONE_CONFIG=/home/johannes/.config/rclone/rclone.conf setzen
  • oder in systemd Unit Environment=RCLONE_CONFIG=...

⚙️ Konfiguration: app-backup.conf (wichtige Stellen)

OneDrive Remote Base

RCLONE_REMOTE_BASE="OneDrive:Sicherung/JRITServerBackups/$(hostname -s)"

Das Skript legt pro Run einen Unterordner an:

remote_run="${RCLONE_REMOTE_BASE}/appbackup_<timestamp>"

WordPress / Nextcloud Layout (wichtig!)

WP_DIR="/var/www/html"
NC_DIR="/var/www/html/nextcloud"
NC_DATA_DIR="/var/www/html/nextcloud/data"

Damit wird:

  • WordPress = alles in /var/www/html ohne nextcloud/
  • Nextcloud Code = /var/www/html/nextcloud ohne data/
  • Nextcloud Data = /var/www/html/nextcloud/data separat

Gitea (native + MariaDB)

Aus deinem systemd/app.ini:

  • WorkingDirectory=/var/lib/gitea
  • APP_DATA_PATH=/var/lib/gitea/data
  • config: /etc/gitea/app.ini

Daher:

ENABLE_GITEA="true"
GITEA_SERVICE_NAME="gitea"
ENABLE_GITEA_SERVICE_STOP="true"

GITEA_DATA_DIR="/var/lib/gitea/data"
GITEA_ETC_DIR="/etc/gitea"

GITEA_DB_NAME="gitea"
GITEA_DB_CNF="/etc/app-backup/db-gitea.cnf"

▶️ Backup ausführen

sudo /usr/local/sbin/app-backup.sh

Erwartetes Verhalten:

  1. Lock /run/app-backup.lock verhindert Parallelruns
  2. optional stoppt es Gitea kurz (konsistenter Snapshot)
  3. Dumps: wordpress / nextcloud / gitea
  4. rsync in staging
  5. mehrere .tar.zst werden erzeugt
  6. Upload pro Datei nach OneDrive (falls ENABLE_UPLOAD=true)
  7. Remote retention (best effort)
  8. lokale Retention löscht alte Archive

♻️ Restore ausführen

Restore von OneDrive (Run-Ordnername angeben)

Du brauchst den Ordnernamen, z.B.: appbackup_2026-02-11_02-31-28

Dann:

sudo /usr/local/sbin/app-restore.sh --remote-run appbackup_2026-02-11_02-31-28

Restore aus lokalem Ordner

Wenn du die Archive lokal hast:

sudo /usr/local/sbin/app-restore.sh --local-run /var/backups/app-backup/archives/<run-folder>

Dry-Run

sudo /usr/local/sbin/app-restore.sh --remote-run appbackup_... --dry-run

Nur Files / nur DB

sudo /usr/local/sbin/app-restore.sh --remote-run appbackup_... --no-db
sudo /usr/local/sbin/app-restore.sh --remote-run appbackup_... --no-files

🧠 Restore-Details (was passiert danach?)

Nextcloud

  • Maintenance Mode wird optional aktiviert (konfigurierbar)
  • Restore kopiert Code und Data getrennt zurück
  • Danach:
    • occ maintenance:repair
    • optional occ files:scan --all (deaktiviert per default; kann lange dauern)

Gitea

  • Service wird optional gestoppt
  • Data wird nach GITEA_DATA_DIR zurück synchronisiert
  • /etc/gitea wird wiederhergestellt
  • DB Dump wird importiert
  • Service wird wieder gestartet

🧯 Troubleshooting

1) rclone Remote not reachable / “didn't find section in config file”

Typischer Fehler:

  • Remote heißt OneDrive: aber Config nutzt onedrive:case-sensitive.
  • Backup läuft als root, aber rclone config ist nur bei johannes.

Prüfen:

sudo rclone listremotes
sudo -u johannes rclone listremotes

Fix:

  • Entweder rclone remote auch für root konfigurieren,
  • oder RCLONE_CONFIG auf johannes Config zeigen lassen.

2) Nextcloud Data doppelt oder fehlt

Stellen prüfen:

  • NC_DIR korrekt?
  • NC_DATA_DIR korrekt?
  • Das Skript excludet data/ bei Nextcloud Code. Data wird separat gesichert.

3) Große Uploads brechen ab

Setze z.B.:

  • RCLONE_TRANSFERS=1
  • RCLONE_CHECKERS=2
  • RCLONE_ONEDRIVE_CHUNK_SIZE=32M
  • optional RCLONE_BWLIMIT="20M"

4) Restore soll “hart” spiegeln

Standard ist vorsichtig (kein delete). Wenn du wirklich Ziel-Verzeichnisse exakt spiegeln willst:

RESTORE_STRICT_DELETE="true"

⚠️ Achtung: Das kann Dateien löschen, die nicht im Backup sind.


🗓️ Optional: systemd Service + Timer (Beispiel)

Nur als Beispiel wenn ihr mögt, legen wir das als Files ins Repo.

/etc/systemd/system/app-backup.service

[Unit]
Description=app-backup
After=network.target mariadb.service
Wants=mariadb.service

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/app-backup.sh

/etc/systemd/system/app-backup.timer

[Unit]
Description=Run app-backup daily

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target

Aktivieren:

sudo systemctl daemon-reload
sudo systemctl enable --now app-backup.timer

Empfehlung: Restore-Test

Backups sind erst dann gut, wenn Restore getestet ist:

  • Test-VM / Test-Host
  • DB importieren
  • Archive entpacken / rsync zurückspielen
  • Nextcloud startet, Login klappt, Files sichtbar
  • WordPress Frontend/Backend ok
  • Gitea WebUI ok, Repos vorhanden