larpaso-website/DEPLOYMENT_ADMIN.md
Pascal Scholz ab7d506eea Fix B2 in deploy guide: generate admin credentials via Docker, not host npm
The deploy host only has Docker installed, not Node/npm directly, so the
original `npm install` / `node hash-password.js` steps failed with
"command not found". Both the bcrypt hash and session secret are now
generated with a throwaway `node:22-alpine` container instead.
2026-09-21 21:46:54 +02:00

7.9 KiB
Raw Blame History

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: fester Benutzername + Passwort (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

ssh deploy@<server>
cd ~/sites/larpaso-website
git pull

B2. Login-Zugangsdaten erzeugen

Der Server selbst braucht dafür kein Node/npm installiert zu haben – das läuft in einem kurzlebigen Docker-Container (Node steckt nur in den Containern, nicht auf dem Host):

docker run --rm -e PW='dein-neues-passwort' node:22-alpine sh -c \
  "npm install --no-save bcryptjs >/dev/null 2>&1 && \
   node -e \"console.log(require('bcryptjs').hashSync(process.env.PW, 12))\""

Gibt einen bcrypt-Hash aus (beginnt mit $2a$ oder $2b$) – merken/kopieren. Zufälliges Session-Secret erzeugen:

docker run --rm node:22-alpine node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

Auch kopieren. (Beide Befehle laden einmalig das node:22-alpine-Image, das ohnehin für den Website-Build gebraucht wird – geht beim zweiten Mal deutlich schneller.)

B3. ~/stack/admin.env anlegen (NICHT ins Git-Repo!)

cat > ~/stack/admin.env <<'EOF'
NODE_ENV=production
ADMIN_USERNAME=pascal
ADMIN_PASSWORD_HASH=<bcrypt-Hash aus B2 hier einfügen>
SESSION_SECRET=<Hex-String aus B2 hier einfügen>
EOF
chmod 600 ~/stack/admin.env

B4. Dienste in ~/stack/docker-compose.yml ergänzen

nano ~/stack/docker-compose.yml

Beim bestehenden website-Dienst ein volumes: ergänzen:

  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:

  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):

volumes:
  site-dist:
  admin-content:
  admin-uploads:

B5. Caddy-Block ergänzen

nano ~/stack/caddy/Caddyfile

Hinzufügen:

admin.larpaso.de {
    reverse_proxy admin:4321
}

B6. 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 B7 läuft (sonst bekommt Caddy kein Zertifikat).

B7. Bauen & starten

cd ~/stack
docker compose build website admin
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

B8. Prüfen

  1. https://admin.larpaso.de/admin/login öffnen, mit den Zugangsdaten aus B2/B3 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:

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

  • Nur ein Login (kein Mehrbenutzer-System, keine Passwort-Reset-Funktion in der Oberfläche – neues Passwort = neuer Hash in admin.env + 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.