# DEPLOYMENT_ADMIN.md – Login-Editor für larpaso.de Ergänzt DEPLOYMENT.md um einen eigenen, öffentlich erreichbaren, aber login-geschützten Editor unter **`https://admin.larpaso.de`**. Dort können Texte, Bilder, Links, Impressum, Datenschutz sowie Schriftarten/-größen und alle Farben der Seite geändert werden. „Speichern & veröffentlichen" baut die Seite neu und die Änderung ist sofort auf `larpaso.de` sichtbar – ohne weiteren Server-Zugriff nötig. Wie in DEPLOYMENT.md: **Teil A** ist bereits im Repo erledigt (Claude Code) und lokal getestet. **Teil B** unten führst du selbst per SSH auf dem Server aus – das ist eine vollständige Schritt-für-Schritt-Anleitung zum Copy-Pasten. Claude Code hat zu keinem Zeitpunkt Zugriff auf Benutzername/Passwort/Secrets oder den Server selbst. --- ## Was der Editor kann - **Texte**: alle Überschriften, Absätze, Listen, FAQ, Preis-Punkte, Mappe-Einträge usw. der Startseite – inklusive Impressum und Datenschutzerklärung. - **Bilder**: Logo, Mappe-Screenshots, Team-Foto, plus optional eigene Bilder anstelle der eingebauten Google-Vorschau und des PDF/Tabellen-Vergleichs. - **Links**: Menüpunkte, E-Mail-Adresse, Kontakt-Angaben. - **Design**: Schriftart für Überschriften/Fließtext (Auswahl aus gängigen Google Fonts oder Systemschrift), Schriftgrößen (7 Stufen, per Schieberegler), und *alle* Farben der Seite einzeln über Hex-Feld, RGB-Schieberegler und Transparenz-Regler. --- ## Was sich technisch ändert - Neuer Dienst `admin` (Node/Express, `admin/`) mit Login, Bearbeitungsoberfläche und einem „Veröffentlichen"-Knopf, der intern `npm run build` ausführt. - Der bestehende `website`-Dienst (nginx) serviert nicht mehr aus dem Image gebackene Dateien, sondern aus einem **gemeinsamen Volume** (`site-dist`), das der `admin`-Dienst nach jedem „Veröffentlichen" neu befüllt. Kein Neustart von `website` nötig. - Bearbeitete Inhalte (`content/site.json`, `content/theme.json`) und hochgeladene Bilder (`public/uploads/`) liegen auf eigenen Volumes, damit sie ein Image-Update überleben. - Login: ein oder mehrere feste Benutzername/Passwort-Paare (bcrypt-Hash), Session-Cookie (12h, httpOnly, Secure, SameSite=Strict), Rate-Limit (5 Fehlversuche → 15 Min. Sperre pro IP). --- ## TEIL A – im Repo (bereits erledigt) - `admin/` – Editor-Backend + -Oberfläche (Login, Formulare, Bild-Upload, Farb-/Font-/ Größen-Editor, Build-Trigger). - `content/site.json`, `content/theme.json` – alle editierbaren Inhalte bzw. Design-Werte. - `Dockerfile.admin` – Image für den `admin`-Dienst. - `Dockerfile` (angepasst) – `website` seedet ein leeres `site-dist`-Volume beim ersten Start aus dem gebackenen Build, statt Dateien fest einzubacken. - `docker-entrypoint-seed.sh`, `docker-entrypoint-admin-seed.sh` – Seed-Skripte für die Volumes. - Lokal geprüft: `npm run build` läuft fehlerfrei; Login, Rate-Limit-Sperre, Speichern (Texte, Bilder, Impressum/Datenschutz, Farben, Schriftarten, Schriftgrößen), Bild-Upload und Veröffentlichen wurden lokal gegen den Admin-Server End-to-End getestet. --- ## TEIL B – Schritt für Schritt per SSH (machst du) Alles unten in dieser Reihenfolge ausführen. Wo `<...>` steht, durch echte Werte ersetzen. ### B0. Voraussetzung: Code muss auf dem Server ankommen können Damit `git pull` in B1 etwas findet, muss dieser Stand vorher nach `git.larpaso.de/pascal/larpaso-website` gepusht sein. Frag im Chat nach, ob das schon passiert ist, falls du direkt startest. ### B1. Repo aktualisieren ```bash ssh deploy@ cd ~/sites/larpaso-website git pull ``` ### B2. Platzhalter für `~/stack/admin.env` anlegen (NICHT ins Git-Repo!) Erstmal nur eine leere Datei, damit Docker Compose in B3/B5 nicht meckert, dass sie fehlt. Die echten Werte kommen in B6 rein. ```bash touch ~/stack/admin.env chmod 600 ~/stack/admin.env ``` ### B3. Dienste in `~/stack/docker-compose.yml` ergänzen ```bash nano ~/stack/docker-compose.yml ``` Beim bestehenden `website`-Dienst ein `volumes:` ergänzen: ```yaml website: build: context: /home/deploy/sites/larpaso-website restart: unless-stopped networks: [web] volumes: - site-dist:/usr/share/nginx/html ``` Neuen `admin`-Dienst unter `services:` ergänzen: ```yaml admin: build: context: /home/deploy/sites/larpaso-website dockerfile: Dockerfile.admin restart: unless-stopped networks: [web] env_file: - /home/deploy/stack/admin.env volumes: - site-dist:/site-dist - admin-content:/app/content - admin-uploads:/app/public/uploads ``` (Kein `ports:` bei beiden Diensten – Caddy erreicht sie intern über den Container-Namen.) Im bestehenden **obersten** `volumes:`-Block der Datei ergänzen (nicht neu anlegen): ```yaml volumes: site-dist: admin-content: admin-uploads: ``` ### B4. Caddy-Block ergänzen ```bash nano ~/stack/caddy/Caddyfile ``` Hinzufügen: ```caddyfile admin.larpaso.de { reverse_proxy admin:4321 } ``` ### B5. Admin-Image bauen ```bash cd ~/stack docker compose build admin ``` Das baut das Image für den Login-Editor – inklusive eines sauberen `npm ci` für die Admin-Abhängigkeiten (bcryptjs, Express usw.), im selben zuverlässigen Schritt, der auch gleich für den Live-Betrieb verwendet wird. ### B6. Login-Zugangsdaten erzeugen Jetzt mit dem gerade gebauten Image statt einem Wegwerf-Container – robuster als ein Ad-hoc-`npm install` (das kann mit dem bekannten npm-Fehler „Tracker 'idealTree' already exists" fehlschlagen): ```bash docker compose run --rm admin node admin/hash-password.js "dein-neues-passwort" | sed 's/\$/$$/g' ``` Gibt einen bcrypt-Hash aus, bei dem jedes `$` bereits verdoppelt ist (`$$2a$$12$$...`) – **genau so, mit den doppelten `$`, in B7 einfügen.** Docker Compose interpretiert einzelne `$` in `env_file`-Werten nämlich selbst als Variablen (siehe Warnung weiter unten, falls das schiefgeht) – `$$` ist Compose' eigene Escape-Regel dafür, kein Tippfehler. Zufälliges Session-Secret erzeugen (rein hexadezimal, kein `$` enthalten, keine Verdopplung nötig): ```bash docker compose run --rm admin node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" ``` Auch kopieren. **Optional – zweiten Benutzer anlegen** (z. B. für Lara): denselben Hash-Befehl nochmal mit ihrem Passwort ausführen und den (verdoppelten) Hash ebenfalls kopieren. Ein Session-Secret reicht für alle Benutzer, das muss nicht nochmal erzeugt werden. ```bash docker compose run --rm admin node admin/hash-password.js "ihr-neues-passwort" | sed 's/\$/$$/g' ``` ### B7. `~/stack/admin.env` mit echten Werten befüllen Am einfachsten mit `nano` (kein Heredoc nötig): ```bash nano ~/stack/admin.env ``` Inhalt (Beispiel – deine Werte aus B6 einsetzen, die Hashes **mit den doppelten `$`** genau so wie von `sed` ausgegeben, nicht die ursprüngliche, unverdoppelte Variante): ``` NODE_ENV=production ADMIN_USERNAME=pascal ADMIN_PASSWORD_HASH=$$2a$$12$$dein.eigentlicher.hash.hier SESSION_SECRET=dein-hex-string-hier ``` **Nur falls du einen zweiten Benutzer angelegt hast**, zwei weitere Zeilen ergänzen (Muster lässt sich mit `_3`, `_4`, ... beliebig fortsetzen): ``` ADMIN_USERNAME_2=lara ADMIN_PASSWORD_HASH_2=$$2a$$12$$laras.hash.hier ``` Speichern: `Strg+O`, `Enter`, `Strg+X`. Danach: ```bash chmod 600 ~/stack/admin.env ``` **Kontrolle** (jeder Hash muss inklusive der verdoppelten `$` **63 Zeichen** lang sein – 60 für den eigentlichen bcrypt-Hash + 3 zusätzliche `$`): ```bash grep HASH ~/stack/admin.env | awk -F= '{print $1": "length($2)" Zeichen"}' ``` ### B8. DNS bei IONOS - Neuer A-Eintrag: Hostname `admin` → Server-IPv4 (gleiche IP wie `@`). - Kurz warten/prüfen: `nslookup admin.larpaso.de` muss die Server-IP liefern, bevor B9 läuft (sonst bekommt Caddy kein Zertifikat). ### B9. Bauen & starten ```bash cd ~/stack docker compose build website docker compose up -d website admin docker compose restart caddy docker compose logs -f caddy # auf "certificate obtained successfully" für admin.larpaso.de warten, dann Strg+C ``` (`admin` wurde schon in B5 gebaut – falls du seitdem nochmal `git pull` gemacht hast, einmal `docker compose build admin` vorweg wiederholen.) ### B10. Prüfen 1. `https://admin.larpaso.de/admin/login` öffnen, mit den Zugangsdaten aus B6/B7 anmelden. 2. Eine Kleinigkeit ändern (z. B. Telefonnummer im Abschnitt „Kontakt" oder eine Farbe im Abschnitt „Design – Farben"), **Speichern & veröffentlichen** klicken. 3. Build-Ausgabe sollte mit „Complete!" enden. 4. `https://larpaso.de` neu laden (ggf. Hard-Reload / Cache leeren) – Änderung sollte sofort da sein. Fertig. Ab jetzt kannst du alle Texte, Bilder, Links und das Design selbst über `admin.larpaso.de` pflegen, ohne mich oder SSH zu brauchen. --- ## Künftige Updates am Code (Admin-Backend selbst) Ändert sich `admin/` oder das Editor-Frontend am Code (nicht über die Editor-Oberfläche, sondern durch mich im Chat), reicht danach: ```bash cd ~/sites/larpaso-website && git pull cd ~/stack && docker compose build admin && docker compose up -d admin ``` `content/site.json`, `content/theme.json` und hochgeladene Bilder bleiben unangetastet (liegen auf eigenen Volumes, nicht im Image). ## Bekannte Grenzen - Mehrere feste Logins möglich (`ADMIN_USERNAME`/`ADMIN_PASSWORD_HASH`, `_2`, `_3`, ...), aber kein echtes Mehrbenutzer-System – alle Logins haben dieselben Rechte, es gibt keine Rollen und keine Passwort-Reset-Funktion in der Oberfläche. Neues/geändertes Passwort: `docker compose run --rm admin node admin/hash-password.js "..."` ausführen (wie B6), Hash in `admin.env` eintragen, dann `docker compose up -d admin`. - Sessions sind In-Memory: Ein Neustart des `admin`-Containers meldet alle ab. - Es gibt keine Versionshistorie der Inhalte oder des Designs – beides liegt aber auf dem Server und kann bei Bedarf manuell gesichert werden (z. B. regelmäßiges Backup der Volumes `admin-content` und `admin-uploads` einplanen, wie für die anderen Volumes auch). - Schriftarten sind auf eine kuratierte Liste gängiger Google Fonts + Systemschrift begrenzt (keine eigenen Font-Dateien hochladbar) – bei Bedarf im Chat erweiterbar.