# 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