|
|
@@ -0,0 +1,194 @@
|
|
|
+# Backup-Konfiguration
|
|
|
+
|
|
|
+Backups werden in `config.php` konfiguriert. Ohne Remote-Konfiguration funktionieren sie sofort: Ein Admin kann unter **Einstellungen** lokale ZIP-Backups erstellen.
|
|
|
+
|
|
|
+## Inhalt des Backups
|
|
|
+
|
|
|
+Das Backup-ZIP enthält nur Betriebsdaten:
|
|
|
+
|
|
|
+- `data/*.json`
|
|
|
+- `data/uploads/**`
|
|
|
+
|
|
|
+Nicht enthalten sind App-Dateien, `config.php`, bestehende Backups, Updater-Arbeitsdateien, Logs, Rate-Limit-Daten und temporäre Dateien.
|
|
|
+
|
|
|
+Lokale Backup-ZIPs liegen in `data/backups/`. Mit der Standard-`.htaccess` ist dieses Verzeichnis nicht öffentlich lesbar.
|
|
|
+
|
|
|
+## Lokale Grundkonfiguration
|
|
|
+
|
|
|
+Diese Defaults sind bereits in `includes/backup.php` hinterlegt. Wenn eine Installation explizite Werte benötigt, werden sie in `config.php` gesetzt:
|
|
|
+
|
|
|
+```php
|
|
|
+define('BACKUP_DIR', DATA_DIR . 'backups/');
|
|
|
+define('BACKUP_LOCAL_RETENTION', 4);
|
|
|
+define('BACKUP_AUTO_INTERVAL_SECONDS', 604800);
|
|
|
+define('BACKUP_REMOTE_TARGETS', []);
|
|
|
+```
|
|
|
+
|
|
|
+`BACKUP_LOCAL_RETENTION` legt fest, wie viele lokale ZIP-Dateien behalten werden. Ältere Backups werden nach einem erfolgreichen neuen Backup gelöscht.
|
|
|
+
|
|
|
+`BACKUP_AUTO_INTERVAL_SECONDS` steuert automatische Backups durch Admin-Aktivität. Der Standard ist wöchentlich (`604800`). Mit `0` werden automatische Backups deaktiviert.
|
|
|
+
|
|
|
+Es gibt keinen Cron-Endpunkt. Automatische Backups laufen nur, wenn ein Admin die Einstellungsseite öffnet und das Intervall abgelaufen ist.
|
|
|
+
|
|
|
+## Bedienung im Admin
|
|
|
+
|
|
|
+Pfad: **Admin > Einstellungen > Backups**.
|
|
|
+
|
|
|
+- **Backup erstellen** erstellt sofort ein manuelles Backup.
|
|
|
+- **Letzte Backups** zeigt lokale Backups mit Erstellzeit, Auslöser, Größe, Dateianzahl, Remote-Status und Download-Aktion.
|
|
|
+- Fehlgeschlagene Remote-Uploads machen das lokale Backup nicht ungültig. Der Fehler wird in den Backup-Metadaten gespeichert.
|
|
|
+
|
|
|
+## S3-Ziel
|
|
|
+
|
|
|
+S3-Uploads nutzen eingebaute PHP-HTTPS-Streams und AWS Signature V4. Es ist keine Bibliothek erforderlich.
|
|
|
+
|
|
|
+```php
|
|
|
+define('BACKUP_REMOTE_TARGETS', [
|
|
|
+ [
|
|
|
+ 'name' => 'S3 Backup',
|
|
|
+ 'type' => 's3',
|
|
|
+ 'bucket' => 'example-bucket',
|
|
|
+ 'region' => 'eu-central-1',
|
|
|
+ 'prefix' => 'psa-orderform',
|
|
|
+ 'access_key' => 'AKIA...',
|
|
|
+ 'secret_key' => '...',
|
|
|
+ ],
|
|
|
+]);
|
|
|
+```
|
|
|
+
|
|
|
+Für S3-kompatiblen Speicher kann `endpoint` ergänzt werden:
|
|
|
+
|
|
|
+```php
|
|
|
+'endpoint' => 'https://s3.example.org',
|
|
|
+```
|
|
|
+
|
|
|
+Der Objektpfad besteht aus `prefix` plus generiertem ZIP-Dateinamen.
|
|
|
+
|
|
|
+## SFTP-Ziel
|
|
|
+
|
|
|
+SFTP benötigt die optionale PHP-SSH2-Erweiterung. Wenn die Erweiterung fehlt, funktionieren lokale Backups weiterhin; der SFTP-Upload wird als nicht verfügbar beziehungsweise fehlgeschlagen gemeldet.
|
|
|
+
|
|
|
+Passwort-Anmeldung:
|
|
|
+
|
|
|
+```php
|
|
|
+define('BACKUP_REMOTE_TARGETS', [
|
|
|
+ [
|
|
|
+ 'name' => 'SFTP Backup',
|
|
|
+ 'type' => 'sftp',
|
|
|
+ 'host' => 'backup.example.org',
|
|
|
+ 'port' => 22,
|
|
|
+ 'username' => 'backup-user',
|
|
|
+ 'password' => '...',
|
|
|
+ 'path' => '/backups/psa-orderform',
|
|
|
+ ],
|
|
|
+]);
|
|
|
+```
|
|
|
+
|
|
|
+Key-Anmeldung:
|
|
|
+
|
|
|
+```php
|
|
|
+define('BACKUP_REMOTE_TARGETS', [
|
|
|
+ [
|
|
|
+ 'name' => 'SFTP Backup',
|
|
|
+ 'type' => 'sftp',
|
|
|
+ 'host' => 'backup.example.org',
|
|
|
+ 'port' => 22,
|
|
|
+ 'username' => 'backup-user',
|
|
|
+ 'public_key' => __DIR__ . '/keys/backup.pub',
|
|
|
+ 'private_key' => __DIR__ . '/keys/backup',
|
|
|
+ 'password' => '',
|
|
|
+ 'path' => '/backups/psa-orderform',
|
|
|
+ ],
|
|
|
+]);
|
|
|
+```
|
|
|
+
|
|
|
+Das Remote-Verzeichnis muss bereits existieren und für den konfigurierten Benutzer beschreibbar sein.
|
|
|
+
|
|
|
+## Custom-Uploader
|
|
|
+
|
|
|
+Ein Custom-Uploader ist ein PHP-Callback, der in `config.php` konfiguriert wird.
|
|
|
+
|
|
|
+```php
|
|
|
+define('BACKUP_REMOTE_TARGETS', [
|
|
|
+ [
|
|
|
+ 'name' => 'Custom Backup',
|
|
|
+ 'type' => 'custom',
|
|
|
+ 'file' => __DIR__ . '/custom-backup-uploader.php',
|
|
|
+ 'callback' => 'uploadPsaOrderformBackup',
|
|
|
+ ],
|
|
|
+]);
|
|
|
+```
|
|
|
+
|
|
|
+Beispiel-Callback:
|
|
|
+
|
|
|
+```php
|
|
|
+<?php
|
|
|
+
|
|
|
+function uploadPsaOrderformBackup(string $archivePath, array $metadata, array $target)
|
|
|
+{
|
|
|
+ $targetDir = __DIR__ . '/external-backups';
|
|
|
+ if (!is_dir($targetDir) && !mkdir($targetDir, 02775, true) && !is_dir($targetDir)) {
|
|
|
+ return [
|
|
|
+ 'success' => false,
|
|
|
+ 'error' => 'Target directory cannot be created.',
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ $remotePath = $targetDir . '/' . basename($archivePath);
|
|
|
+ if (!copy($archivePath, $remotePath)) {
|
|
|
+ return [
|
|
|
+ 'success' => false,
|
|
|
+ 'error' => 'Copy failed.',
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ return [
|
|
|
+ 'remote_path' => $remotePath,
|
|
|
+ ];
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+Der Callback erhält:
|
|
|
+
|
|
|
+- `$archivePath`: absoluter Pfad zur lokalen ZIP-Datei.
|
|
|
+- `$metadata`: Dateiname, Erstellzeitpunkt, Auslöser und Prüfsumme.
|
|
|
+- `$target`: das konfigurierte Ziel-Array.
|
|
|
+
|
|
|
+Für Erfolg kann `true` oder ein Array zurückgegeben werden. Für Fehler kann eine Exception geworfen werden. Ein Array mit `'success' => false` wird als fehlgeschlagener Remote-Upload protokolliert.
|
|
|
+
|
|
|
+## Mehrere Remote-Ziele
|
|
|
+
|
|
|
+Remote-Ziele können kombiniert werden:
|
|
|
+
|
|
|
+```php
|
|
|
+define('BACKUP_REMOTE_TARGETS', [
|
|
|
+ [
|
|
|
+ 'name' => 'Primary S3',
|
|
|
+ 'type' => 's3',
|
|
|
+ 'bucket' => 'example-bucket',
|
|
|
+ 'region' => 'eu-central-1',
|
|
|
+ 'prefix' => 'psa-orderform',
|
|
|
+ 'access_key' => 'AKIA...',
|
|
|
+ 'secret_key' => '...',
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ 'name' => 'Secondary SFTP',
|
|
|
+ 'type' => 'sftp',
|
|
|
+ 'host' => 'backup.example.org',
|
|
|
+ 'port' => 22,
|
|
|
+ 'username' => 'backup-user',
|
|
|
+ 'password' => '...',
|
|
|
+ 'path' => '/backups/psa-orderform',
|
|
|
+ ],
|
|
|
+]);
|
|
|
+```
|
|
|
+
|
|
|
+Jedes Ziel wird unabhängig versucht.
|
|
|
+
|
|
|
+## Betriebshinweise
|
|
|
+
|
|
|
+- Remote-Zugangsdaten gehören in `config.php`, nicht in `data/settings.json`.
|
|
|
+- `data/` muss für PHP beschreibbar sein.
|
|
|
+- Auf Apache-Hosting muss `.htaccess` aktiv bleiben, damit `data/backups/` nicht direkt erreichbar ist.
|
|
|
+- Remote-Ziele sollten nach Konfigurationsänderungen mit einem manuellen Backup getestet werden.
|
|
|
+- Lokale Backups sollten nur über den authentifizierten Adminbereich heruntergeladen werden.
|