341 lines
9.3 KiB
Markdown
341 lines
9.3 KiB
Markdown
# 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 **12–18 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
|