diff --git a/CHANGELOG.md b/CHANGELOG.md index c7fb632..020046f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,23 @@ Vor `npm version` wandert der Abschnitt „Unveröffentlicht" unter eine neue ## [Unveröffentlicht] +## [1.1.1] – 2026-10-08 + +### Hinzugefügt + +- **Betrieb hinter einem vorhandenen Reverse Proxy** wie dem Nginx Proxy + Manager: Die Adresse, auf der Docker Port 3000 veröffentlicht, ist über + `LERNBAR_ADRESSE` in `.env` einstellbar (Vorgabe weiterhin `127.0.0.1`) +- `scripts/betrieb/lernbar-portsperre.sh` mit systemd-Dienst – öffnet Port 3000 + nur für den Reverse Proxy. Docker-Ports laufen an ufw vorbei, die Regel steht + deshalb in der Kette `DOCKER-USER` +- Abschnitt 6b in `docs/BETRIEB-PROXMOX.md` mit den Einstellungen für den + Proxy-Host + +### Geändert + +- Die Betriebsanleitung nennt für Docker Compose „2.x oder neuer" + ## [1.1.0] – 2026-10-05 Module lassen sich abschalten. diff --git a/README.md b/README.md index cc9759f..97bc049 100644 --- a/README.md +++ b/README.md @@ -245,6 +245,7 @@ Protokollzeilen. | Name | Vorgabe im Container | Bedeutung | |---|---|---| +| `LERNBAR_ADRESSE` | `127.0.0.1` | Adresse, auf der Docker Port 3000 veröffentlicht – in `.env` neben `docker-compose.yml`, wenn der Reverse Proxy auf einem anderen Rechner läuft ([Betrieb, 6b](docs/BETRIEB-PROXMOX.md#6b-hinter-einem-vorhandenen-nginx-proxy-manager)) | | `PORT` | `3000` | Lauschport | | `TZ` | `Europe/Berlin` | Zeitzone | | `LERNBAR_DATEN` | `/daten` | Wurzel für Datenbank und Anhänge | diff --git a/docker-compose.yml b/docker-compose.yml index 0614587..f4985c3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,8 +15,12 @@ services: # Hinter einem Proxy, der TLS beendet, bleibt das hier http. NODE_ENV: production ports: - # Nur auf der Schleife lauschen – nach außen geht der Reverse Proxy. - - "127.0.0.1:3000:3000" + # Vorgabe: nur auf der Schleife lauschen, der Reverse Proxy läuft auf + # derselben Maschine. Steht der Proxy woanders (etwa ein Nginx Proxy + # Manager), in .env die Adresse der VM eintragen: + # LERNBAR_ADRESSE=10.10.13.200 + # Docker-Ports laufen an ufw vorbei – siehe docs/BETRIEB-PROXMOX.md. + - "${LERNBAR_ADRESSE:-127.0.0.1}:3000:3000" volumes: - lernbar-daten:/daten healthcheck: diff --git a/docs/BETRIEB-PROXMOX.md b/docs/BETRIEB-PROXMOX.md index 1db1d55..af261b7 100644 --- a/docs/BETRIEB-PROXMOX.md +++ b/docs/BETRIEB-PROXMOX.md @@ -2,7 +2,8 @@ Diese Anleitung führt von einer leeren Proxmox-Umgebung zur laufenden Lern-Bar im Betriebsnetz: eine virtuelle Maschine mit Debian, darin Docker mit der Lern-Bar und Caddy -als Reverse Proxy mit HTTPS. Rechne mit etwa zwei Stunden. +als Reverse Proxy mit HTTPS – oder, wenn es schon einen Reverse Proxy wie den Nginx Proxy +Manager gibt, dieser (Abschnitt 6b). Rechne mit etwa zwei Stunden. > **HTTPS ist Pflicht, nicht Kür.** Die Lern-Bar setzt das Anmeldecookie im Betrieb mit dem > Merkmal `Secure`. Über `http://` nimmt der Browser es nicht an – die Anmeldung scheitert @@ -17,7 +18,7 @@ als Reverse Proxy mit HTTPS. Rechne mit etwa zwei Stunden. 3. [Grundeinrichtung](#3-grundeinrichtung) 4. [Docker installieren](#4-docker-installieren) 5. [Die Lern-Bar holen und starten](#5-die-lern-bar-holen-und-starten) -6. [HTTPS mit Caddy](#6-https-mit-caddy) +6. [HTTPS mit Caddy](#6-https-mit-caddy) – oder [6b. hinter einem vorhandenen Nginx Proxy Manager](#6b-hinter-einem-vorhandenen-nginx-proxy-manager) 7. [Das erste Konto](#7-das-erste-konto) 8. [Sicherung](#8-sicherung) 9. [Aktualisieren](#9-aktualisieren) @@ -97,7 +98,7 @@ sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin d sudo usermod -aG docker "$USER" ``` -Prüfen: `docker compose version` zeigt eine Fassung 2.x. +Prüfen: `docker compose version` zeigt eine Fassung 2.x oder neuer. ## 5. Die Lern-Bar holen und starten @@ -184,6 +185,52 @@ sudo systemctl reload caddy > Browser ein Zertifikat, dem das Gerät vertraut. Mit Variante B heißt das: Wurzelzertifikat > auch auf den Diensthandys installieren. +## 6b. Hinter einem vorhandenen Nginx Proxy Manager + +Gibt es im Betrieb schon einen Reverse Proxy, der Zertifikate verwaltet – etwa den +Nginx Proxy Manager –, entfällt Caddy auf der VM. Die Lern-Bar muss dann auf der +Adresse der VM lauschen statt nur auf `127.0.0.1`, damit der Proxy sie erreicht. + +**1. Lauschadresse einstellen.** In `/opt/lernbar/.env` (die Datei steht in der +`.gitignore`, `update.sh` lässt sie in Ruhe): + +```bash +echo "LERNBAR_ADRESSE=10.10.13.200" > /opt/lernbar/.env # Adresse der VM +cd /opt/lernbar && docker compose up -d +``` + +**2. Port 3000 nur für den Proxy öffnen.** Ports, die Docker veröffentlicht, +laufen an ufw vorbei – ohne diesen Schritt wäre die Lern-Bar für das ganze Netz +unverschlüsselt erreichbar. Die Regel kommt deshalb in Dockers eigene Kette +`DOCKER-USER`: + +```bash +sudo install -m 755 /opt/lernbar/scripts/betrieb/lernbar-portsperre.sh /usr/local/sbin/lernbar-portsperre +sudo install -m 644 /opt/lernbar/scripts/betrieb/lernbar-portsperre.service /etc/systemd/system/ +sudo sed -i 's/10.10.13.5//' /etc/systemd/system/lernbar-portsperre.service +sudo systemctl daemon-reload +sudo systemctl enable --now lernbar-portsperre +sudo iptables -S DOCKER-USER # muss die DROP-Regel mit „! -s " zeigen +``` + +Prüfen: Vom NPM aus antwortet `curl http://10.10.13.200:3000/api/gesundheit`, +von jedem anderen Rechner läuft derselbe Aufruf ins Leere. + +**3. Proxy-Host im Nginx Proxy Manager anlegen:** + +| Reiter | Einstellung | +|---|---| +| Details | Domain `lernbar.`, Scheme `http`, Forward Hostname `10.10.13.200`, Port `3000`, „Block Common Exploits" an | +| SSL | Zertifikat wählen oder anfordern, „Force SSL" und „HTTP/2 Support" an | +| Advanced | `client_max_body_size 30m;` – sonst scheitern Fotos als Anhang | + +Der NPM gibt den Host-Namen der Anfrage unverändert weiter. Das ist wichtig: Next.js +prüft bei jedem Formular, ob Herkunft und Host zusammenpassen, und lehnt das +Absenden sonst ab. + +Danach weiter mit Abschnitt 7. Abschnitt 6 (Caddy) entfällt, ebenso die Freigabe +von Port 80 und 443 in ufw auf der VM. + ## 7. Das erste Konto ```bash diff --git a/scripts/betrieb/lernbar-portsperre.service b/scripts/betrieb/lernbar-portsperre.service new file mode 100644 index 0000000..a0e8a82 --- /dev/null +++ b/scripts/betrieb/lernbar-portsperre.service @@ -0,0 +1,16 @@ +# Öffnet Port 3000 der Lern-Bar nur für den Reverse Proxy. +# Installation siehe docs/BETRIEB-PROXMOX.md, Abschnitt 6b. +# Die Adresse des Proxys in der Zeile ExecStart anpassen. + +[Unit] +Description=Lern-Bar: Port 3000 nur für den Reverse Proxy +After=docker.service +Requires=docker.service + +[Service] +Type=oneshot +ExecStart=/usr/local/sbin/lernbar-portsperre 10.10.13.5 +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/scripts/betrieb/lernbar-portsperre.sh b/scripts/betrieb/lernbar-portsperre.sh new file mode 100755 index 0000000..4aa9ea3 --- /dev/null +++ b/scripts/betrieb/lernbar-portsperre.sh @@ -0,0 +1,10 @@ +#!/bin/sh +# Port 3000 der Lern-Bar nur für den Reverse Proxy öffnen. +# Docker-Ports laufen an ufw vorbei, deshalb die Kette DOCKER-USER, die Docker +# selbst vor seinen eigenen Regeln auswertet und nie überschreibt. +set -eu +PROXY="${1:?Aufruf: lernbar-portsperre }" +REGEL="-p tcp -m conntrack --ctorigdstport 3000 --ctdir ORIGINAL ! -s $PROXY -j DROP" +iptables -N DOCKER-USER 2>/dev/null || true +# shellcheck disable=SC2086 +iptables -C DOCKER-USER $REGEL 2>/dev/null || iptables -I DOCKER-USER $REGEL