Compare commits
2 Commits
d623f39c54
...
a9057b25dd
| Author | SHA1 | Date | |
|---|---|---|---|
| a9057b25dd | |||
| 769d06e04e |
314
DEPLOY_TESTUMGEBUNG_ANLEITUNG.md
Normal file
314
DEPLOY_TESTUMGEBUNG_ANLEITUNG.md
Normal file
@@ -0,0 +1,314 @@
|
||||
# Anleitung: Testumgebung testmodul.qrmaster.net aufsetzen
|
||||
|
||||
Diese Anleitung richtet auf dem Produktionsserver eine **zweite, getrennte Instanz** von
|
||||
QR Master ein, erreichbar unter `testmodul.qrmaster.net`. Sie läuft auf dem Branch `test`
|
||||
mit einer eigenen, leeren Datenbank.
|
||||
|
||||
Die laufende Produktion wird dabei **nicht angefasst**. Alle Schritte hier legen neue
|
||||
Container, ein neues Volume und ein neues Verzeichnis an.
|
||||
|
||||
## Kurzfassung zum Abhaken
|
||||
|
||||
Wer die Begründungen nicht braucht, arbeitet diese Liste ab. Die ausführlichen Abschnitte
|
||||
darunter erklären jeden Schritt und was schiefgehen kann.
|
||||
|
||||
- [ ] **1.** Repo klonen, Branch `test`, **eigenes Verzeichnis** neben der Produktion
|
||||
- [ ] **2.** `.env.test` von Timo dort ablegen und die vier Kernwerte prüfen
|
||||
- [ ] **3.** Stack bauen und starten (`-p qrmaster-test`)
|
||||
- [ ] **4.** Schema aus Prod dumpen und einspielen - **kein** `prisma migrate`
|
||||
- [ ] **5.** Testaccount per SQL anlegen (Registrierungsformular funktioniert nicht)
|
||||
- [ ] **6.** Caddy-Block ergänzen und neu laden
|
||||
- [ ] **7.** Abnahme: DB-Trennung, keine Migrationen, robots.txt, Browser-Test
|
||||
|
||||
### Alle Befehle am Stück
|
||||
|
||||
```bash
|
||||
# 1 - Checkout (NICHT im Produktionsverzeichnis)
|
||||
git clone -b test https://git.bizmatch.net/tknuth/QR-master.git qrmaster-test
|
||||
cd qrmaster-test
|
||||
git branch --show-current # muss "test" zeigen
|
||||
|
||||
# 2 - .env.test hier ablegen, dann pruefen
|
||||
grep -E "NEXT_PUBLIC_WWW_URL|NEXT_PUBLIC_APP_URL|AUTH_COOKIE_NAME|POSTGRES_DB" .env.test
|
||||
# Erwartet: beide URLs auf testmodul, AUTH_COOKIE_NAME=userId_test,
|
||||
# POSTGRES_DB=qrmaster_test. Steht dort app./www. -> STOPP, siehe Schritt 2.
|
||||
|
||||
# 3 - Stack starten
|
||||
docker compose -p qrmaster-test --env-file .env.test \
|
||||
-f docker-compose.yml -f docker-compose.test.yml up -d --build
|
||||
docker ps --filter "name=qrmaster-test" --format "table {{.Names}}\t{{.Status}}"
|
||||
|
||||
# 4 - Schema (nur Struktur, keine Kundendaten)
|
||||
docker exec qrmaster-db pg_dump -U postgres --schema-only qrmaster > schema.sql
|
||||
docker exec -i qrmaster-test-db psql -U postgres -d qrmaster_test < schema.sql
|
||||
docker exec qrmaster-test-db psql -U postgres -d qrmaster_test -c "\dt" | head -20
|
||||
|
||||
# 5 - Testaccount: erst Hash erzeugen, dann in den INSERT einsetzen
|
||||
docker exec qrmaster-test-web node -e "console.log(require('bcryptjs').hashSync('DEIN_TESTPASSWORT',12))"
|
||||
docker exec -i qrmaster-test-db psql -U postgres -d qrmaster_test -c "INSERT INTO \"User\" (id,email,name,password,\"emailVerified\",\"updatedAt\") VALUES ('testuser1','test@qrmaster.net','Test','HIER_DER_HASH',now(),now());"
|
||||
|
||||
# 6 - Caddy: Block ergaenzen (siehe Schritt 6), dann
|
||||
caddy reload --config /etc/caddy/Caddyfile
|
||||
|
||||
# 7 - Abnahme
|
||||
docker exec qrmaster-test-db psql -U postgres -d qrmaster_test -c 'SELECT count(*) FROM "User";'
|
||||
docker exec qrmaster-db psql -U postgres -d qrmaster -c 'SELECT count(*) FROM "User";'
|
||||
docker logs qrmaster-test-web 2>&1 | head -20
|
||||
curl -s https://testmodul.qrmaster.net/robots.txt
|
||||
```
|
||||
|
||||
Die beiden `count(*)` müssen sich unterscheiden, in den Logs darf kein "Applying Prisma
|
||||
migrations" stehen, und `robots.txt` muss `Disallow: /` liefern.
|
||||
|
||||
## Voraussetzungen
|
||||
|
||||
- SSH-Zugang zum Server, auf dem QR Master läuft
|
||||
- Docker und Docker Compose (mindestens v2.24 - wird für `!override` und `!reset` gebraucht;
|
||||
prüfen mit `docker compose version`)
|
||||
- Schreibrechte auf die Caddy-Konfiguration
|
||||
- Die Datei **`.env.test`** - die kommt von Timo und ist nicht im Repository, weil sie
|
||||
Passwörter enthält
|
||||
- Der DNS-Eintrag `testmodul.qrmaster.net` existiert bereits (CNAME)
|
||||
|
||||
## Was NICHT angefasst wird
|
||||
|
||||
- Das bestehende Produktionsverzeichnis: dort **nicht** den Branch wechseln. Ein späterer
|
||||
Prod-Rebuild würde sonst Testcode bauen.
|
||||
- Die Produktions-`.env`
|
||||
- Die bestehenden Caddy-Blöcke für `www.qrmaster.net`, `app.qrmaster.net` und `qrmaster.net`
|
||||
- Die Produktionsdatenbank. Der einzige Zugriff darauf ist ein `pg_dump --schema-only`,
|
||||
das ausschließlich liest.
|
||||
|
||||
---
|
||||
|
||||
## 1. Zweites Checkout anlegen
|
||||
|
||||
**Nicht** im Produktionsverzeichnis arbeiten. Ein eigenes Verzeichnis daneben, z.B. im
|
||||
selben übergeordneten Ordner:
|
||||
|
||||
```bash
|
||||
git clone -b test https://git.bizmatch.net/tknuth/QR-master.git qrmaster-test
|
||||
```
|
||||
|
||||
Danach in dieses Verzeichnis wechseln. **Alle weiteren Befehle laufen von dort**, sofern
|
||||
nicht anders angegeben.
|
||||
|
||||
```bash
|
||||
cd qrmaster-test
|
||||
```
|
||||
|
||||
Prüfen, dass der richtige Branch ausgecheckt ist - es muss `test` erscheinen:
|
||||
|
||||
```bash
|
||||
git branch --show-current
|
||||
```
|
||||
|
||||
## 2. `.env.test` ablegen
|
||||
|
||||
Die von Timo erhaltene Datei als `.env.test` in dieses Verzeichnis legen (also
|
||||
`qrmaster-test/.env.test`).
|
||||
|
||||
Kurz gegenprüfen, dass die vier wichtigsten Werte stimmen:
|
||||
|
||||
```bash
|
||||
grep -E "NEXT_PUBLIC_WWW_URL|NEXT_PUBLIC_APP_URL|AUTH_COOKIE_NAME|POSTGRES_DB" .env.test
|
||||
```
|
||||
|
||||
Erwartet:
|
||||
|
||||
```
|
||||
NEXT_PUBLIC_WWW_URL=https://testmodul.qrmaster.net
|
||||
NEXT_PUBLIC_APP_URL=https://testmodul.qrmaster.net
|
||||
AUTH_COOKIE_NAME=userId_test
|
||||
POSTGRES_DB=qrmaster_test
|
||||
```
|
||||
|
||||
Steht bei einer der URLs `app.qrmaster.net` oder `www.qrmaster.net`, **nicht starten** -
|
||||
dann würden Klicks in der Testumgebung in die Produktion umleiten.
|
||||
|
||||
## 3. Stack bauen und starten
|
||||
|
||||
```bash
|
||||
docker compose -p qrmaster-test --env-file .env.test -f docker-compose.yml -f docker-compose.test.yml up -d --build
|
||||
```
|
||||
|
||||
Der erste Build dauert einige Minuten. Der Projektname `-p qrmaster-test` ist wichtig: er
|
||||
sorgt dafür, dass eigene Container und ein eigenes Volume entstehen und nichts aus der
|
||||
Produktion überschrieben wird.
|
||||
|
||||
Läuft alles, sollten drei neue Container existieren:
|
||||
|
||||
```bash
|
||||
docker ps --filter "name=qrmaster-test" --format "table {{.Names}}\t{{.Status}}"
|
||||
```
|
||||
|
||||
Erwartet: `qrmaster-test-db`, `qrmaster-test-redis`, `qrmaster-test-web`.
|
||||
|
||||
Die Anwendung kann zu diesem Zeitpunkt noch nichts anzeigen - die Datenbank ist leer. Das
|
||||
ist normal und wird im nächsten Schritt behoben.
|
||||
|
||||
## 4. Datenbankschema einspielen
|
||||
|
||||
Die Testdatenbank bekommt **nur die Struktur** aus der Produktion, keine Daten. Es werden
|
||||
also keine Kundendaten kopiert.
|
||||
|
||||
Struktur aus der Produktionsdatenbank exportieren (reiner Lesezugriff):
|
||||
|
||||
```bash
|
||||
docker exec qrmaster-db pg_dump -U postgres --schema-only qrmaster > schema.sql
|
||||
```
|
||||
|
||||
In die Testdatenbank einspielen:
|
||||
|
||||
```bash
|
||||
docker exec -i qrmaster-test-db psql -U postgres -d qrmaster_test < schema.sql
|
||||
```
|
||||
|
||||
> **Wichtig:** Nicht `prisma migrate` verwenden. Die Migrationsdateien im Repository sind
|
||||
> seit April 2026 nicht mehr gepflegt - alle Schemaänderungen seitdem wurden per SQL
|
||||
> gemacht. Ein `migrate deploy` würde ein veraltetes Schema erzeugen, mit dem die
|
||||
> Anwendung nicht läuft. Der Container startet deshalb bewusst ohne Migrationsschritt.
|
||||
|
||||
Prüfen, dass Tabellen angekommen sind:
|
||||
|
||||
```bash
|
||||
docker exec qrmaster-test-db psql -U postgres -d qrmaster_test -c "\dt" | head -20
|
||||
```
|
||||
|
||||
## 5. Testaccount anlegen
|
||||
|
||||
Die Registrierung über das Formular funktioniert hier **nicht**: die Testumgebung
|
||||
verschickt bewusst keine E-Mails, und ohne Bestätigungsmail wird der Account vom System
|
||||
wieder gelöscht. Der Account wird deshalb direkt in der Datenbank angelegt.
|
||||
|
||||
Zuerst einen Passwort-Hash erzeugen (`DEIN_TESTPASSWORT` durch ein selbst gewähltes
|
||||
Passwort ersetzen):
|
||||
|
||||
```bash
|
||||
docker exec qrmaster-test-web node -e "console.log(require('bcryptjs').hashSync('DEIN_TESTPASSWORT',12))"
|
||||
```
|
||||
|
||||
Die Ausgabe ist eine Zeichenkette, die mit `$2a$12$` oder `$2b$12$` beginnt. Diese im
|
||||
folgenden Befehl anstelle von `HIER_DER_HASH` einsetzen:
|
||||
|
||||
```bash
|
||||
docker exec -i qrmaster-test-db psql -U postgres -d qrmaster_test -c "INSERT INTO \"User\" (id,email,name,password,\"emailVerified\",\"updatedAt\") VALUES ('testuser1','test@qrmaster.net','Test','HIER_DER_HASH',now(),now());"
|
||||
```
|
||||
|
||||
Anmeldung erfolgt danach ganz normal über `/login` mit `test@qrmaster.net` und dem
|
||||
gewählten Passwort.
|
||||
|
||||
## 6. Caddy konfigurieren
|
||||
|
||||
Einen neuen Block in die Caddy-Konfiguration aufnehmen (Pfad ggf. anpassen). Die
|
||||
bestehenden Blöcke bleiben unverändert:
|
||||
|
||||
```caddyfile
|
||||
testmodul.qrmaster.net {
|
||||
reverse_proxy qrmaster-test-web:3000
|
||||
}
|
||||
```
|
||||
|
||||
Konfiguration neu laden:
|
||||
|
||||
```bash
|
||||
caddy reload --config /etc/caddy/Caddyfile
|
||||
```
|
||||
|
||||
Caddy holt das TLS-Zertifikat automatisch. Das kann eine Minute dauern.
|
||||
|
||||
## 7. Abnahme
|
||||
|
||||
**a) Datenbanken sind getrennt.** Die beiden Zahlen müssen sich unterscheiden - die
|
||||
Testdatenbank enthält nur den eben angelegten Account:
|
||||
|
||||
```bash
|
||||
docker exec qrmaster-test-db psql -U postgres -d qrmaster_test -c 'SELECT count(*) FROM "User";'
|
||||
```
|
||||
|
||||
```bash
|
||||
docker exec qrmaster-db psql -U postgres -d qrmaster -c 'SELECT count(*) FROM "User";'
|
||||
```
|
||||
|
||||
**b) Keine Migrationen gelaufen.** In der Ausgabe darf **nicht** "Applying Prisma
|
||||
migrations" stehen:
|
||||
|
||||
```bash
|
||||
docker logs qrmaster-test-web 2>&1 | head -20
|
||||
```
|
||||
|
||||
**c) Suchmaschinen ausgesperrt.** Muss `Disallow: /` liefern:
|
||||
|
||||
```bash
|
||||
curl -s https://testmodul.qrmaster.net/robots.txt
|
||||
```
|
||||
|
||||
**d) Im Browser:**
|
||||
|
||||
- `https://testmodul.qrmaster.net` lädt mit gültigem Zertifikat
|
||||
- Anmeldung mit dem Testaccount funktioniert
|
||||
- `https://testmodul.qrmaster.net/dashboard` **bleibt auf testmodul** und springt nicht auf
|
||||
`app.qrmaster.net`. Passiert das doch, sind die URLs in der `.env.test` falsch.
|
||||
- In den Entwicklertools unter Application → Cookies liegen zwei getrennte Cookies:
|
||||
`userId` mit Domain `.qrmaster.net` (Produktion) und `userId_test` mit Domain
|
||||
`testmodul.qrmaster.net`
|
||||
- Die Produktion ist weiterhin erreichbar und man ist dort weiterhin angemeldet
|
||||
|
||||
---
|
||||
|
||||
## Laufender Betrieb
|
||||
|
||||
Neuen Stand deployen, nachdem auf dem Branch `test` etwas gepusht wurde - aus dem
|
||||
Verzeichnis `qrmaster-test`:
|
||||
|
||||
```bash
|
||||
git pull
|
||||
```
|
||||
|
||||
```bash
|
||||
docker compose -p qrmaster-test --env-file .env.test -f docker-compose.yml -f docker-compose.test.yml up -d --build
|
||||
```
|
||||
|
||||
Ein Rebuild ist **immer** nötig, ein bloßer Neustart genügt nicht: die Host-URLs und der
|
||||
Cookie-Name werden beim Bauen fest in die Anwendung kompiliert.
|
||||
|
||||
Schemaänderungen werden weiterhin **von Hand per SQL** ausgeführt - erst auf Test, nach
|
||||
erfolgreicher Prüfung dasselbe Statement auf Produktion. Es gibt keinen automatischen Weg
|
||||
dazwischen.
|
||||
|
||||
## Testumgebung stoppen oder entfernen
|
||||
|
||||
Stoppen, Daten bleiben erhalten:
|
||||
|
||||
```bash
|
||||
docker compose -p qrmaster-test --env-file .env.test -f docker-compose.yml -f docker-compose.test.yml down
|
||||
```
|
||||
|
||||
Vollständig entfernen inklusive Testdatenbank - der Projektname `-p qrmaster-test` sorgt
|
||||
dafür, dass ausschließlich die Test-Volumes gelöscht werden:
|
||||
|
||||
```bash
|
||||
docker compose -p qrmaster-test --env-file .env.test -f docker-compose.yml -f docker-compose.test.yml down -v
|
||||
```
|
||||
|
||||
## Wenn etwas nicht funktioniert
|
||||
|
||||
| Symptom | Ursache |
|
||||
|---|---|
|
||||
| Build bricht ab mit `set AUTH_COOKIE_NAME in .env.test` | `.env.test` fehlt oder liegt im falschen Verzeichnis |
|
||||
| `qrmaster-test-db` bleibt `unhealthy`, `web` startet nicht | In der `.env.test` steht nicht `POSTGRES_DB=qrmaster_test` |
|
||||
| Caddy liefert 502 | Containername im Caddy-Block stimmt nicht, oder der Container läuft nicht - mit `docker ps` prüfen |
|
||||
| Anwendung meldet `column ... does not exist` | Schema-Import aus Schritt 4 war unvollständig - erneut einspielen |
|
||||
| `/dashboard` springt auf `app.qrmaster.net` | Die URLs in der `.env.test` zeigen nicht auf testmodul. Korrigieren und **neu bauen**, nicht nur neu starten. |
|
||||
| Anmeldung wirkt zufällig abgelaufen | `AUTH_COOKIE_NAME` ist nicht gesetzt oder steht auf `userId` - dann kollidiert es mit dem Produktions-Cookie |
|
||||
| Registrierung über das Formular schlägt fehl | Erwartet - die Testumgebung verschickt keine E-Mails. Account per SQL anlegen, Schritt 5. |
|
||||
|
||||
## Bekannte Einschränkungen der Testumgebung
|
||||
|
||||
Bewusst deaktiviert, weil die Umgebung nach außen nichts auslösen soll:
|
||||
|
||||
- **Kein E-Mail-Versand** - Registrierung, Passwort-Reset und Benachrichtigungen funktionieren nicht
|
||||
- **Kein Google-Login** - Zugangsdaten sind nicht hinterlegt
|
||||
- **Keine Datei-Uploads** - der Objektspeicher (R2) ist nicht konfiguriert
|
||||
- **Kein Stripe** - Checkout und Abo-Verwaltung funktionieren nicht, solange keine Testschlüssel eingetragen sind
|
||||
- **Keine Analytics** - damit die Produktionszahlen nicht verfälscht werden
|
||||
Reference in New Issue
Block a user