feat(privat/CV): sync to latest upstream (cv-upstream/main, 30f9608b)
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
# 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)
|
||||
Reference in New Issue
Block a user