Produktiv- und Testtabellen per Prefix trennen
This commit is contained in:
@@ -36,6 +36,11 @@ Wichtige Punkte:
|
||||
|
||||
- `--single-transaction` sorgt für einen konsistenten Snapshot ohne
|
||||
Tabellen zu sperren (InnoDB, wie hier durchgängig verwendet).
|
||||
- Da `test_` und `prod_` in derselben physischen Datenbank liegen, enthält
|
||||
der vollständige Dump beide logisch getrennten Schemas. Beim Restore darf
|
||||
nicht nur ein einzelner Prefix zurückgespielt werden, ohne Abhängigkeiten
|
||||
und den jeweiligen Stand von `test_schema_migrations` beziehungsweise
|
||||
`prod_schema_migrations` zu prüfen.
|
||||
- Der Backup-Ordner muss **außerhalb** des über HTTP erreichbaren Webroots
|
||||
liegen, sonst wären Dumps öffentlich abrufbar.
|
||||
- Zusätzlich zu lokalen Backups auf dem Webspace mindestens eine Kopie an
|
||||
@@ -55,7 +60,9 @@ gunzip -c kaffeeliste_20260715_030000.sql.gz | mysql -h "$DB_HOST" -u "$DB_USER"
|
||||
|
||||
Danach `php scripts/migrate.php` laufen lassen, falls das Backup älter als
|
||||
die zuletzt eingespielten Migrationen ist (das Skript ist idempotent und
|
||||
wendet nur fehlende Migrationen an).
|
||||
wendet nur fehlende Migrationen im konfigurierten `DB_TABLE_PREFIX` an).
|
||||
Den Lauf daher mit der Konfiguration jeder wiederhergestellten Umgebung
|
||||
separat ausführen.
|
||||
|
||||
**Restore-Test:** Mindestens einmal pro Quartal einen echten Restore gegen
|
||||
eine separate Test-Datenbank durchführen und die App dagegen starten
|
||||
|
||||
+41
-14
@@ -9,14 +9,22 @@ Dieses Dokument beschreibt, wie die Anwendung auf den Netcup-Webspace
|
||||
|
||||
## Umgebungen
|
||||
|
||||
| Umgebung | Host | Webroot | Zweck |
|
||||
| --- | --- | --- | --- |
|
||||
| Staging | `testumgebung.kaffeeliste.de` | `/testumgebung.kaffeeliste.de/httpdocs/` | Vollständiger Durchlauf vor jedem Produktiv-Deploy |
|
||||
| Produktion | `app.kaffeeliste.de` (App) + `kaffeeliste.de` (Marketing) | noch einzurichten | Echtbetrieb |
|
||||
| Umgebung | Host | Webroot | Tabellen-Prefix | Zweck |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Staging | `testumgebung.kaffeeliste.de` | `/testumgebung.kaffeeliste.de/httpdocs/` | `test_` | Vollständiger Durchlauf vor jedem Produktiv-Deploy |
|
||||
| Produktion | `app.kaffeeliste.de` (App) + `kaffeeliste.de` (Marketing) | noch einzurichten | `prod_` | Echtbetrieb |
|
||||
|
||||
Beide Umgebungen brauchen **eigene Datenbanken** und **eigene**
|
||||
`env.local.php`. Die Staging-Umgebung läuft mit Stripe-Testkeys, die
|
||||
Produktion mit Live-Keys.
|
||||
Beide Umgebungen verwenden dieselbe physische Datenbank, aber zwingend
|
||||
unterschiedliche Tabellen-Prefixe und jeweils eine eigene `env.local.php`.
|
||||
Damit sind Daten, Migrationstabellen und Fremdschlüssel von Staging und
|
||||
Produktion logisch getrennt. Die Staging-Umgebung läuft mit Stripe-Testkeys,
|
||||
die Produktion mit Live-Keys.
|
||||
|
||||
Der Prefix schützt vor versehentlichem Zugriff der einen Umgebung auf die
|
||||
Tabellen der anderen, ersetzt aber keine getrennte Datenbank als harte
|
||||
Sicherheitsgrenze: Ein kompromittierter gemeinsamer Datenbankzugang kann
|
||||
weiterhin alle Tabellen sehen. Deshalb Zugangsdaten besonders restriktiv
|
||||
behandeln und immer die gesamte Datenbank sichern.
|
||||
|
||||
### Host-Split beachten
|
||||
|
||||
@@ -80,12 +88,13 @@ Die temporäre `phpinfo()`-Datei danach wieder löschen.
|
||||
|
||||
### 2. Datenbank anlegen
|
||||
|
||||
In Plesk eine leere MySQL-Datenbank samt eigenem Benutzer anlegen. Die
|
||||
Zugangsdaten werden gleich in `env.local.php` eingetragen.
|
||||
In Plesk eine MySQL-Datenbank samt Benutzer anlegen. Beide Umgebungen dürfen
|
||||
dieselben Zugangsdaten verwenden; die Trennung erfolgt über
|
||||
`DB_TABLE_PREFIX=test_` beziehungsweise `DB_TABLE_PREFIX=prod_`.
|
||||
|
||||
Die vorhandene Entwicklungsdatenbank **nicht** übernehmen: sie enthält
|
||||
ausschließlich Testdaten inklusive des migrierten Default-Mandanten aus
|
||||
der Legacy-App.
|
||||
Unpräfixierte vorhandene Testdaten dürfen ausschließlich mit dem dafür
|
||||
vorgesehenen Übernahmeskript nach `test_` kopiert werden. Sie dürfen niemals
|
||||
nach `prod_` übernommen werden.
|
||||
|
||||
### 3. Dateien hochladen
|
||||
|
||||
@@ -121,12 +130,16 @@ putenv('APP_TIMEZONE=Europe/Berlin');
|
||||
putenv('APP_DB_DRIVER=mysql');
|
||||
putenv('DB_HOST=localhost');
|
||||
putenv('DB_NAME=…'); putenv('DB_USER=…'); putenv('DB_PASS=…');
|
||||
putenv('DB_TABLE_PREFIX=test_');
|
||||
putenv('APP_SESSION_PATH=' . __DIR__ . '/var/sessions');
|
||||
putenv('APP_MAIL_TRANSPORT=mail');
|
||||
putenv('APP_MAIL_FROM=noreply@kaffeeliste.de');
|
||||
```
|
||||
|
||||
Stripe-, Dolibarr- und IMAP-Werte je Umgebung ergänzen (siehe unten).
|
||||
In der produktiven `env.local.php` muss stattdessen
|
||||
`DB_TABLE_PREFIX=prod_` stehen. Ein leerer Prefix ist im laufenden Betrieb
|
||||
nicht zulässig.
|
||||
|
||||
### 5. Schreibrechte für `var/`
|
||||
|
||||
@@ -139,7 +152,21 @@ den CSV-Import. Beide sind per `.htaccess` von außen gesperrt.
|
||||
|
||||
Es gibt 30 versionierte Migrationen in `database/migrations/`, angewendet
|
||||
über `scripts/migrate.php`. Das Skript ist idempotent und wendet nur
|
||||
fehlende Migrationen an.
|
||||
fehlende Migrationen an. Es arbeitet ausschließlich im Prefix aus der
|
||||
jeweiligen `env.local.php`; daher müssen Migrationen einmal in Staging und
|
||||
einmal in Produktion ausgeführt werden.
|
||||
|
||||
Für die einmalige Übernahme vorhandener, bisher unpräfixierter Testdaten:
|
||||
|
||||
```bash
|
||||
php scripts/migrate-table-prefix.php --target-prefix=test_ --replace
|
||||
```
|
||||
|
||||
Das Skript migriert zuerst das `test_`-Schema, ersetzt dessen Inhalt
|
||||
transaktional durch eine exakte Kopie der unpräfixierten Daten und vergleicht
|
||||
pro Tabelle die Zeilenzahl. Die unpräfixierten Quelltabellen bleiben als
|
||||
Rückfallmöglichkeit unverändert. Vor dem Lauf trotzdem ein vollständiges
|
||||
Datenbank-Backup erstellen.
|
||||
|
||||
Ohne SSH-Zugang läuft das über **Plesk → Geplante Aufgaben (Scheduled
|
||||
Tasks)** als einmalig ausgeführter Task vom Typ *PHP-Skript ausführen*:
|
||||
@@ -348,7 +375,7 @@ Rechten der Secret-Dateien oder einer nicht angewendeten Legal-Migration.
|
||||
ein Vorlauf mit `--dry-run` wurde kontrolliert
|
||||
- [ ] Stündlicher Task `php scripts/purge-expired-operational-data.php` ist
|
||||
eingerichtet; ein Vorlauf mit `--dry-run` wurde kontrolliert
|
||||
- [ ] Frische Produktivdatenbank ohne Testdaten
|
||||
- [ ] Frisches `prod_`-Schema ohne Testdaten; Staging verwendet ausschließlich `test_`
|
||||
|
||||
## Bewusst offen
|
||||
|
||||
|
||||
+4
-1
@@ -44,6 +44,7 @@ export DB_PORT="3306"
|
||||
export DB_NAME="example_database"
|
||||
export DB_USER="example_user"
|
||||
export DB_PASS="example_password"
|
||||
export DB_TABLE_PREFIX="test_"
|
||||
export DEV_AUTH_EMAIL="admin@test.local"
|
||||
export DEV_AUTH_NAME="Test Admin"
|
||||
# Optional: Standard ist var/sessions im Repository.
|
||||
@@ -95,7 +96,9 @@ der Port über die Ports-Ansicht weitergeleitet werden.
|
||||
Nachrichten unter `var/mail` ab. Für Produktion kann zunächst
|
||||
`APP_MAIL_TRANSPORT=mail` mit passendem `APP_BASE_URL` und Absender gesetzt
|
||||
werden; eine SMTP-/Provider-Anbindung bleibt ein späterer Betriebsausbau.
|
||||
- Die Tabellen werden über `database/migrations/` angelegt.
|
||||
- Die Tabellen werden über `database/migrations/` mit dem Prefix aus
|
||||
`DB_TABLE_PREFIX` angelegt. Lokal und auf Staging ist das `test_`, in
|
||||
Produktion ausschließlich `prod_`.
|
||||
- `database/mysql-dev-schema.sql` bleibt als historische Dev-Schema-Baseline
|
||||
erhalten; der aktive Weg ist `scripts/migrate.php`.
|
||||
- Session-Dateien liegen standardmäßig unter `var/sessions`; `var/` wird von
|
||||
|
||||
@@ -111,8 +111,8 @@ LD_LIBRARY_PATH="$PWD/.local/php/usr/lib/x86_64-linux-gnu:$PWD/.local/php/usr/li
|
||||
```
|
||||
|
||||
Die Skripte erwarten die bekannten Dev-Umgebungsvariablen `DB_HOST`, `DB_NAME`,
|
||||
`DB_USER` und `DB_PASS`. `scripts/init-mysql-dev.php` braucht zusätzlich
|
||||
`DEV_AUTH_EMAIL`.
|
||||
`DB_USER`, `DB_PASS` und `DB_TABLE_PREFIX`. `scripts/init-mysql-dev.php`
|
||||
braucht zusätzlich `DEV_AUTH_EMAIL`.
|
||||
|
||||
## Aktueller Prüfstatus
|
||||
|
||||
|
||||
Reference in New Issue
Block a user