# GerbilManager — Oeffentliche Webseite (Self-Hosted, TrueNAS) > **Zielgruppe:** Julian. > Die oeffentliche Seite (Jimdo-Ersatz) laeuft self-hosted auf der TrueNAS neben dem Manager. > Strato-Domain → DynDNS → IP → Julians nginx-Proxy → publicsite-Container (Port 8081). --- ## Architektur ``` Internet | HTTPS/HTTP v Julians nginx-Reverse-Proxy (laeuft schon auf NAS) | proxy_pass http://127.0.0.1:8081 v publicsite (nginx:alpine, Port 8081) ← liest nur: /usr/share/nginx/html/live/ | (Shared Volume, read-only) | [POST /api/publish im Manager schreibt in dasselbe Volume] v api (.NET, Port 8080 intern) → schreibt: /data/publicsite/live/ | (Shared Volume, read-write) v Manager (frontend-nginx, Port 80) ← LAN-only, NIE internet-exponiert ``` **SICHERHEIT — harte Bedingung:** - Nur `publicsite` (Port 8081) wird ins Internet weitergeleitet. - Der Manager (API + Frontend, Port 80) hat KEINE Authentifizierung → LAN-only. - Der `publicsite`-nginx proxied NICHT auf die API — er serviert nur statisches HTML. --- ## Erstinstallation ### 1. Verzeichnis anlegen ```bash mkdir -p /mnt/JailStorage/DockerVolumes/gerbilmanager/publicsite ``` Das Verzeichnis wird von der API beschrieben (laeuft als root im Container) — keine ACL-Aenderung noetig. Beim ersten `POST /api/publish` legt die API automatisch `live/` und `_staging_new/` darunter an. ### 2. .env erganzen In `deploy/truenas/.env` hinzufuegen (oder aus `.env.example` uebernehmen): ```env PUBLICSITE_PATH=/mnt/JailStorage/DockerVolumes/gerbilmanager/publicsite PUBLICSITE_PORT=8081 ``` ### 3. Compose-Stack neu starten ```bash cd /opt/gerbilmanager docker compose -f deploy/truenas/compose.yaml up -d ``` Der neue `publicsite`-Container startet und serviert Port 8081. Solange noch nicht veroeffentlicht wurde, zeigt er einen 404 (live/-Verzeichnis leer). ### 4. Julians externen nginx konfigurieren Inhalt von `deploy/truenas/vhost-snippet.conf` in den bestehenden nginx-Proxy einfuegen (als eigenen `server`-Block oder per `include`): ```bash # Auf der NAS, nginx-Konfigverzeichnis (z.B. /etc/nginx/conf.d/ oder sites-available): nano /etc/nginx/conf.d/gerbilmanager-public.conf # durch den tatsaechlichen Hostnamen ersetzen nginx -t && nginx -s reload ``` --- ## Seite veroeffentlichen (Publish-Ablauf) 1. Im Manager einloggen (http://\/) 2. Navigiere zu **Webseite** → Inhalte bearbeiten → **Veroeffentlichen** 3. Klick auf "Veroeffentlichen" loest `POST /api/publish` aus. **Was passiert intern:** ``` POST /api/publish → API baut SiteSnapshot aus DB (alle Published-Seiten) → SiteRenderer rendert Snapshot → HTML-Dateien (path → content Map) → Schreibt Dateien nach /data/publicsite/_staging_new/ → Atomic Swap: _staging_new/ → live/ (rename = ein Syscall, nie halb-geschrieben) → publicsite-nginx serviert beim naechsten Request sofort den neuen Stand → Kein Container-Restart, kein Image-Rebuild, kein CI Response: { "filesPublished": N } ``` **Endergebnis:** publicsite-nginx liest sofort den neuen Stand aus `live/`. --- ## Verifikation ```bash # publicsite-Container laeuft? docker compose -f deploy/truenas/compose.yaml ps publicsite # Seite lokal abrufbar? curl -s http://localhost:8081/ | head -5 # live/-Verzeichnis gefuellt? ls /mnt/JailStorage/DockerVolumes/gerbilmanager/publicsite/live/ # Oeffentlich erreichbar (nach DNS-Propagation)? curl -s http:/// | grep "Kleine Chaoten" ``` --- ## Sicherheitstrennung (Pflichtcheck) | Was | Port | Internet-exponiert? | |-----|------|---------------------| | Manager (api + frontend) | 80 | **NEIN** — LAN-only | | Oeffentliche Seite (publicsite) | 8081 | Ja, via Julians nginx-Proxy | | API-Doku (Scalar) | 80/scalar | **NEIN** — LAN-only | Der Manager-nginx (gerbilmanager-frontend, Port 80) und die API (Port 8080 intern) sind NICHT in `vhost-snippet.conf` eingetragen und NICHT in Julians externem Proxy konfiguriert. Sie sind ausschliesslich im Heimnetz erreichbar. --- ## Hostname noch ausstehend `` in `deploy/truenas/vhost-snippet.conf` ist ein Platzhalter. Julian nennt den Hostnamen/Subdomain → ersetzen und nginx neu laden.