The runbook explained every step but had no way to just work through it. Adds a checklist and all commands in one block up front, with the prose below as the reference for what a step does and how it fails. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
12 KiB
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.testvon 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
# 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
!overrideund!resetgebraucht; prüfen mitdocker 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.netexistiert 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.netundqrmaster.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:
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.
cd qrmaster-test
Prüfen, dass der richtige Branch ausgecheckt ist - es muss test erscheinen:
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:
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
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:
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):
docker exec qrmaster-db pg_dump -U postgres --schema-only qrmaster > schema.sql
In die Testdatenbank einspielen:
docker exec -i qrmaster-test-db psql -U postgres -d qrmaster_test < schema.sql
Wichtig: Nicht
prisma migrateverwenden. Die Migrationsdateien im Repository sind seit April 2026 nicht mehr gepflegt - alle Schemaänderungen seitdem wurden per SQL gemacht. Einmigrate deploywü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:
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):
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:
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:
testmodul.qrmaster.net {
reverse_proxy qrmaster-test-web:3000
}
Konfiguration neu laden:
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:
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";'
b) Keine Migrationen gelaufen. In der Ausgabe darf nicht "Applying Prisma migrations" stehen:
docker logs qrmaster-test-web 2>&1 | head -20
c) Suchmaschinen ausgesperrt. Muss Disallow: / liefern:
curl -s https://testmodul.qrmaster.net/robots.txt
d) Im Browser:
https://testmodul.qrmaster.netlädt mit gültigem Zertifikat- Anmeldung mit dem Testaccount funktioniert
https://testmodul.qrmaster.net/dashboardbleibt auf testmodul und springt nicht aufapp.qrmaster.net. Passiert das doch, sind die URLs in der.env.testfalsch.- In den Entwicklertools unter Application → Cookies liegen zwei getrennte Cookies:
userIdmit Domain.qrmaster.net(Produktion) unduserId_testmit Domaintestmodul.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:
git pull
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:
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:
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