Commit Graph

5 Commits

Author SHA1 Message Date
8daef8e98f White-Label Phase 5: DNS-Automatik für Firmen-Subdomains
- DnsProvisioner (dependency-frei, cURL) legt pro Reseller *.<slug>.<portal>
  A-Record via Hetzner-Cloud-DNS-API an (deckt firma.reseller.portal ab,
  was der globale *.<portal>-Eintrag nicht kann)
- ResellerDnsListener (Doctrine postPersist/preRemove), fail-soft,
  überspringt Plattform-Reseller
- Env HCLOUD_DNS_TOKEN/HCLOUD_DNS_ZONE_NAME (leer = aus); Terraform reicht
  Cloud-Token + Zone an die App-Nodes durch (nur bei manage_dns)
- Ziel-IP = APP_EDGE_IP oder DNS-Auflösung der Portal-Domain

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 18:14:41 +02:00
cc33040b4b Deploy: HTTP/3 (QUIC) in Caddy deaktiviert
Manche Security-Suites (AVG Webschutz) zerlegen QUIC → ERR_QUIC_PROTOCOL_ERROR
bei betroffenen Kunden. Caddy global auf `servers { protocols h1 h2 }` (nur
HTTP/1.1 + HTTP/2 über TCP), kein alt-svc h3 mehr. Caddy-Server bekommt
ignore_changes=[user_data] (Caddyfile-Änderung per reload, kein Recreate).
Live-Caddy bereits nachgezogen (Caddyfile in-place + caddy reload).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 10:00:18 +02:00
c49ff37746 Deploy: Terraform-Code-Rollout auf App-Nodes (ohne Recreate)
terraform_data.app_deploy führt per remote-exec auf jedem App-Node ein Update
aus (git reset auf origin + deploy/update.sh: SPA bauen, composer, migrate(app-1),
cache:clear), getriggert über var.deploy_version (z. B. Git-SHA). Server werden
NICHT ersetzt: hcloud_server.app ignoriert user_data-Änderungen (cloud-init nur
Erstboot). Gemeinsames deploy/update.sh (cloud-init ruft es ebenfalls auf).
Fix: ${PRIV:-} in der .tftpl als $${PRIV:-} escaped (templatefile-Kollision).

Workflow: tofu apply -var deploy_version=$(git rev-parse --short HEAD)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 19:47:59 +02:00
79e996ab03 Deployment: Caddy-Edge (TLS + On-Demand für Custom-Domains) + Hetzner DNS
- Caddy ersetzt den Hetzner-LB: terminiert TLS (Portal-Domain automatisch) und
  load-balanced per reverse_proxy über die App-Nodes. Für Custom-Domains (§11)
  On-Demand-TLS, autorisiert über GET /internal/tls-allowed.
- TlsCheckController + DomainRepository::findVerifiedByHostname: erlaubt Zertifikate
  nur für Portal-Domain oder verifizierte Domains (Schutz vor Cert-Flooding).
- Terraform: hcloud_load_balancer entfernt, Caddy-Server + Firewall (80/443) +
  cloud-init-caddy (Caddyfile templated mit Upstreams/Domain/ACME).
- Optional Hetzner DNS via API (manage_dns): A-Record Portal + Wildcard → Caddy.
- nginx.prod: /internal zu Symfony geroutet; APP_PORTAL_DOMAIN-Env.

Validiert: Caddyfile (caddy validate), Terraform (validate), /internal/tls-allowed (200/403/400).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 22:13:29 +02:00
c3e05257cb Deployment: Hetzner Cloud via Terraform (Multi-Node, skalierbar)
Infrastruktur als Code für den Skalierungs-Test auf Hetzner:
- deploy/terraform: privates Netz, Firewalls, 2 App-Nodes, DB-Node, Load
  Balancer (Health-Check /health); cloud-init bootet Docker + Stack je Node
- deploy/compose/docker-compose.prod.yml + nginx.prod.conf: App-Node-Stack
  (PHP-FPM + Nginx) routet /api,/p,/t,/css,/health → Symfony, Rest → Vue-SPA
- App-Anpassungen: HealthController (/health für LB), brand.css nach /css
  verschoben (kein Pfad-Clash mit SPA-Assets im Prod-Routing)
- deploy/README.md: Anleitung inkl. JWT-Key-Verteilung & Cross-Node-Test
- reference.php (auto-generiert) aus Versionierung entfernt

Terraform validiert (terraform validate), Prod-Compose-Syntax geprüft.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 21:20:58 +02:00