diff --git a/README.md b/README.md index d7b16ce..bb28a95 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,9 @@ ausblenden. ## Inhalt -- [Schnellstart](#schnellstart) +- [Schritt für Schritt zum laufenden Stack](#schritt-für-schritt-zum-laufenden-stack) +- [Hinter einem Reverse Proxy (Nginx Proxy Manager)](#hinter-einem-reverse-proxy-nginx-proxy-manager) +- [Wenn etwas nicht läuft](#wenn-etwas-nicht-läuft) - [Aktualisieren](#aktualisieren) - [Konfiguration](#konfiguration) - [Bedienung](#bedienung) @@ -22,28 +24,225 @@ ausblenden. --- -## Schnellstart +## Schritt für Schritt zum laufenden Stack -Voraussetzung: Docker mit Docker Compose. +Vom leeren Server bis zum ersten QR-Code. Alle Befehle laufen auf dem +Rechner, auf dem die Anwendung später läuft. + +### Schritt 1 — Voraussetzungen prüfen + +Gebraucht werden Docker mit Compose v2 und Git: + +```bash +docker compose version # erwartet: Docker Compose version v2.x oder höher +git --version +``` + +Kommt `docker: command not found`, fehlt Docker — die +[offizielle Anleitung](https://docs.docker.com/engine/install/) installiert +Engine und Compose in einem Rutsch. + +### Schritt 2 — Projekt holen + +```bash +git clone https://git.wilde-server.de/florian.wilde/qrcode-generator.git +cd qrcode-generator +``` + +### Schritt 3 — Konfiguration anlegen + +```bash +cp .env.example .env +nano .env +``` + +Zwei Werte **musst** du anfassen: + +| Wert | Was eintragen | +| --- | --- | +| `POSTGRES_PASSWORD` | Ein eigenes Passwort. Es steht nur in dieser Datei und wird nirgends sonst gebraucht. | +| `DATABASE_URL` | Dasselbe Passwort noch einmal — es steckt mitten im Verbindungsstring. | + +Und einen solltest du bewusst setzen: + +| Wert | Was eintragen | +| --- | --- | +| `BASE_URL` | Die Adresse, unter der die Anwendung **von außen** erreichbar ist. | + +Beispiel für ein eigenes Passwort `MeinGeheimes123`: + +```bash +POSTGRES_PASSWORD=MeinGeheimes123 +DATABASE_URL=postgresql://qrcode:MeinGeheimes123@db:5432/qrcode?schema=public +BASE_URL=http://192.168.1.50:3000 +``` + +> **Warum `BASE_URL` so wichtig ist:** Ein dynamischer QR-Code enthält nicht +> das eigentliche Ziel, sondern die Kurz-URL `{BASE_URL}/r/{slug}`. Steht dort +> `localhost`, funktioniert der Code **nur auf dem Server selbst** — ein Handy +> läuft ins Leere. Trage deshalb die LAN-Adresse des Servers oder die +> öffentliche Domain ein. Bereits gedruckte Codes lassen sich später nicht +> mehr umbiegen, also am besten vor dem ersten produktiven Code festlegen. + +Der Hostname `db` im `DATABASE_URL` bleibt unverändert — das ist der +Servicename aus der `docker-compose.yml`, nicht dein Server. + +### Schritt 4 — Starten ```bash -cp .env.example .env # anschließend POSTGRES_PASSWORD und BASE_URL anpassen docker compose up -d --build ``` -Danach ist die Anwendung unter erreichbar. Die -Datenbankmigrationen laufen beim Start des App-Containers automatisch — es -sind keine weiteren Schritte nötig. +Der erste Durchlauf baut das Image und dauert je nach Maschine **5 bis 15 +Minuten**. Spätere Starts brauchen nur wenige Sekunden. -Nützliche Befehle: +### Schritt 5 — Prüfen, ob alles läuft ```bash -docker compose logs -f app # Protokoll der Anwendung -docker compose ps # Status beider Container -docker compose down # Stack stoppen (Daten bleiben erhalten) -docker compose down -v # Stack stoppen und Datenbank löschen +docker compose ps ``` +Erwartet werden zwei Container, `db` mit dem Zusatz `(healthy)`: + +``` +NAME SERVICE STATUS +qrcode-generator-app-1 app Up 30 seconds +qrcode-generator-db-1 db Up 45 seconds (healthy) +``` + +Und im Protokoll: + +```bash +docker compose logs app +``` + +``` +→ Datenbankmigrationen werden angewendet … +All migrations have been successfully applied. +→ Anwendung wird gestartet … +▲ Next.js 16.3.0 +✓ Ready +``` + +Die Datenbank richtet sich beim ersten Start selbst ein — es gibt keinen +Extraschritt dafür. + +### Schritt 6 — Aufrufen + +Im Browser die Adresse öffnen, die du als `BASE_URL` eingetragen hast, zum +Beispiel . Es erscheint „Was möchtest du +erstellen?“ mit den Typ-Kacheln. + +### Schritt 7 — Ersten Code erstellen + +1. Kachel **Website** anklicken. +2. Adresse eingeben, etwa `https://example.com` — die Vorschau erscheint + sofort. +3. **PNG** oder **SVG** herunterladen. Fertig. + +Für einen Code, dessen Ziel du später ändern kannst: + +1. Unter „Art des Codes“ auf **Dynamisch** wechseln. +2. Optional einen Namen vergeben, damit du ihn wiederfindest. +3. **Dynamischen Code speichern** — erst dabei entsteht die Kurz-URL, deshalb + ist der Download bis dahin gesperrt. +4. Danach herunterladen. Unter **Meine Codes** lässt sich das Ziel jederzeit + ändern, ohne den gedruckten Code anzufassen. + +### Schritt 8 — Aufräumen, was du nicht brauchst + +Unter **Verwaltung → QR-Typen** kannst du einzelne Typen ausblenden — etwa +die sechs, die noch nicht umgesetzt sind, damit sie gar nicht erst +auftauchen. + +### Die wichtigsten Befehle im Betrieb + +```bash +docker compose logs -f app # Protokoll mitlesen (Abbruch mit Strg+C) +docker compose ps # Status beider Container +docker compose restart app # Anwendung neu starten +docker compose down # Stack stoppen — die Daten bleiben erhalten +docker compose up -d # wieder starten +docker compose down -v # Stack stoppen UND die Datenbank löschen +``` + +--- + +## Hinter einem Reverse Proxy (Nginx Proxy Manager) + +Soll die Anwendung unter einer eigenen Domain mit HTTPS laufen, übernimmt der +Proxy die Zertifikate; die Anwendung selbst bleibt unverändert. + +**1. Port nur lokal veröffentlichen.** Wenn Proxy und Anwendung auf demselben +Rechner laufen, muss Port 3000 nicht nach außen offen sein. In der `.env`: + +```bash +APP_PORT=3000 +BASE_URL=https://qr.deine-domain.de +``` + +**2. Im Nginx Proxy Manager** einen *Proxy Host* anlegen: + +| Feld | Wert | +| --- | --- | +| Domain Names | `qr.deine-domain.de` | +| Scheme | `http` | +| Forward Hostname / IP | IP des Docker-Hosts, z. B. `192.168.1.50` | +| Forward Port | `3000` | +| Websockets Support | an | +| Block Common Exploits | an | +| SSL | Zertifikat anfordern, *Force SSL* aktivieren | + +Läuft der Proxy als Container im selben Docker-Netz wie dieser Stack, kann +statt der IP auch der Servicename `app` mit Port `3000` stehen — dann muss +das Port-Mapping gar nicht nach außen offen sein. + +**3. `BASE_URL` auf die öffentliche Adresse setzen** — mit `https://` und ohne +Port. Danach: + +```bash +docker compose up -d +``` + +> `BASE_URL` muss zur Adresse passen, unter der Besucher die Anwendung +> aufrufen. Steht dort weiterhin `http://192.168.1.50:3000`, zeigen neue +> dynamische Codes ins interne Netz statt auf die Domain. + +Mehrere Domains gleichzeitig unterstützt diese Version noch nicht — das kommt +in Phase B (siehe [Ausblick](#ausblick-version-2)). Zurzeit gilt genau eine +`BASE_URL`. + +--- + +## Wenn etwas nicht läuft + +**`POSTGRES_PASSWORD fehlt — bitte .env aus .env.example anlegen`** +Die `.env` fehlt oder ist leer. Schritt 3 nachholen. + +**`ports are not available: ... bind: address already in use`** +Port 3000 ist belegt. Entweder den anderen Dienst beenden oder in der `.env` +einen anderen Port setzen, z. B. `APP_PORT=3100`, dann `docker compose up -d`. + +**Der Container `db` bleibt `unhealthy` oder startet immer neu** +Meist ein Datenverzeichnis aus einer älteren PostgreSQL-Version. Protokoll +ansehen mit `docker compose logs db`. Wenn dort von einem inkompatiblen +Datenlayout die Rede ist und du die Daten nicht brauchst: +`docker compose down -v` — Achtung, das löscht die Datenbank. + +**Der QR-Code führt auf dem Handy ins Leere** +`BASE_URL` zeigt auf `localhost`. Auf die LAN-Adresse oder Domain ändern, +`docker compose up -d`, und die betroffenen dynamischen Codes neu +herunterladen. Statische Codes sind davon nicht betroffen. + +**Die Anwendung antwortet nicht, `docker compose ps` zeigt sie aber als `Up`** +`docker compose logs app` ansehen. Kommt dort ein Datenbankfehler, stimmt +meist das Passwort in `DATABASE_URL` nicht mit `POSTGRES_PASSWORD` überein — +beide Werte müssen identisch sein. + +**Nach einem Update fehlt etwas oder die Seite ist leer** +`docker compose up -d --build` erzwingt einen Neubau. Hilft das nicht: +`docker compose down && docker compose up -d --build`. + --- ## Aktualisieren