Files
app-backup/README.md

341 lines
9.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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:
```bash
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:
```ini
[client]
user=backup
password=DEIN_PASSWORT
host=localhost
```
Rechte:
```bash
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):
```sql
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):
```bash
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
```bash
RCLONE_REMOTE_BASE="OneDrive:Sicherung/JRITServerBackups/$(hostname -s)"
```
Das Skript legt pro Run einen Unterordner an:
```bash
remote_run="${RCLONE_REMOTE_BASE}/appbackup_<timestamp>"
```
### WordPress / Nextcloud Layout (wichtig!)
```bash
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:
```bash
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
```bash
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:
```bash
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:
```bash
sudo /usr/local/sbin/app-restore.sh --local-run /var/backups/app-backup/archives/<run-folder>
```
### Dry-Run
```bash
sudo /usr/local/sbin/app-restore.sh --remote-run appbackup_... --dry-run
```
### Nur Files / nur DB
```bash
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:
```bash
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:
```bash
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`
```ini
[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`
```ini
[Unit]
Description=Run app-backup daily
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
```
Aktivieren:
```bash
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