Files

4.3 KiB

Deployment-Plan — andreknie.de

Ablauf für den Produktiv-Gang. Voraussetzung: Die funktionalen Lücken und die 🔴-Punkte aus SICHERHEITS-AUDIT.md sind geschlossen.

Architektur im Überblick

Internet ──HTTPS──> Caddy (Reverse Proxy, Auto-TLS)
                      │
                      ├── /api/*  ──> Express-Backend (Docker, Port 3003)
                      │                 └── server/data/*.json (Volume)
                      │
                      └── /*      ──> statische SPA-Dateien (/opt/andreknie/site)
  • Frontend: statisches Build-Artefakt (dist/), von Caddy direkt ausgeliefert.
  • Backend: Express-Container, nur für Formulare (Kontakt, Vortrag, Newsletter, Resource).
  • Datenhaltung: JSON-Dateien im gemounteten Volume server/data/.

Voraussetzungen (vor dem ersten Deploy)

Funktionale Lücken geschlossen

  • Confirmation-Landingpages im SPA (siehe Erläuterung unten) + Routen /bestaetigung/...
  • Backend leitet Bestätigungs-Klick auf eine SPA-Seite weiter (statt rohem JSON)
  • Security-🔴: Rate-Limiting, Honeypot, resource_id-Validierung

Infrastruktur

  • Server (VM/VPS) mit Docker + Docker Compose
  • Caddy installiert (oder als Container)
  • DNS: A/AAAA-Record andreknie.de (+ www) zeigt auf die Server-IP
  • Ports 80 + 443 offen (für Let's Encrypt / TLS)
  • SMTP-Zugangsdaten vorhanden (Versand-Postfach bei d-hive)

Schritt-für-Schritt

1. Secrets konfigurieren

.env auf dem Server anlegen (nicht im Repo!):

PORT=3003
NODE_ENV=production
BASE_URL=https://andreknie.de
SMTP_HOST=<host>
SMTP_PORT=587
SMTP_USER=<user>
SMTP_PASS=<pass>
STAKEHOLDER_EMAIL=kontakt@d-hive.de

2. Frontend bauen

Lokal oder im CI:

npm ci
npm run build

Ergebnis: dist/. Inhalt nach /opt/andreknie/site/ auf den Server kopieren (rsync/scp).

3. Backend starten

Auf dem Server im Projektverzeichnis:

docker compose up -d --build
  • Container lauscht auf localhost:3003.
  • Volume ./server/data persistiert Tokens/Subscriber/Leads über Neustarts.

4. Caddy aktivieren

Caddyfile deployen, dann caddy reload (bzw. Container neu starten). Caddy holt automatisch das TLS-Zertifikat.

5. Smoke-Tests (Produktion)

  • https://andreknie.de lädt, alle Seiten navigierbar
  • GET https://andreknie.de/api/health{ status: "ok" }
  • Kontaktformular absenden → Bestätigungsmail kommt an
  • Bestätigungslink klicken → Landingpage „bestätigt", Weiterleitung an Stakeholder kommt an
  • Newsletter-Doppel-Opt-In komplett durchspielen
  • Rate-Limit greift (mehrfaches Absenden → 429)
  • Security-Header prüfen (z.B. securityheaders.com)

Wichtige Erläuterung: die „funktionalen Lücken"

Zwei zusammenhängende Punkte, die vor dem Deploy zu klären sind:

A) Confirmation-Landingpages. Aktuell zeigt die Bestätigungsmail auf den Backend-Endpunkt direkt: https://andreknie.de/api/contact/confirm/<token>. Klickt der Nutzer, antwortet Express mit rohem JSON ({ ok: true, ... }) — keine gestaltete Seite. Für eine saubere UX braucht es:

  1. Eine SPA-Seite (z.B. /bestaetigung) mit Erfolg-/Abgelaufen-Zustand.
  2. Entweder der Backend-Endpunkt antwortet mit einem Redirect (302) auf diese SPA-Seite, oder die Mail verlinkt direkt die SPA-Seite, die dann per fetch den Token beim Backend bestätigt.

B) ContentFilter / Pagination / SEOHead. Geplante, aber noch nicht gebaute Komponenten:

  • ContentFilter — Tag-Filter für lange Listen (Kniepunkt, Posts).
  • Pagination — Blättern bei >10 Einträgen.
  • SEOHead — pro Seite eigene <title>/Meta-Tags (wichtig fürs Teilen auf LinkedIn).

Diese sind kein harter Go-Live-Blocker, verbessern aber Auffindbarkeit und Bedienbarkeit deutlich. Empfehlung: SEOHead vor Go-Live (wegen Social-Sharing), Filter/Pagination danach.


Rollback

  • Frontend: vorheriges dist/ zurückkopieren (alte Builds versioniert aufbewahren).
  • Backend: docker compose down + vorheriges Image-Tag starten.
  • Daten: server/data/ regelmäßig sichern (Cron + Backup off-site).

Wartung

  • Backup-Cron für server/data/
  • Log-Rotation für Container-Logs
  • npm audit + Dependency-Updates im Quartalsrhythmus
  • Zertifikats-Erneuerung: automatisch durch Caddy (kein manueller Eingriff)