Commit Graph

12 Commits

Author SHA1 Message Date
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
faece5870d Deploy-Fix: nginx routet /w (Wallet) zum Backend + nginx-Recreate bei Rollout
- nginx.prod.conf: /w (Wallet-Landing, .pkpass, Google-Redirect, Logo) fehlte in
  der Backend-Location-Regex → Wallet-Routen landeten in der SPA (index.html).
- update.sh: nginx.prod.conf ist ein Single-File-Bind-Mount (am Inode gepinnt);
  git reset ersetzt die Datei → nginx-Container force-recreaten, damit die
  aktuelle Config greift (statt nur reload).

Live-Nodes bereits nachgezogen; Apple-Wallet-Pass funktioniert über Caddy.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 09:17:30 +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
03355f89f3 Deploy-Fix: composer install + privates NIC im cloud-init
Zwei Bugs, die den ersten Live-Deploy lahmlegten:
1. composer install fehlte → vendor/ (gitignored, /app gemountet) fehlte →
   Symfony bootete nicht (autoload_runtime.php missing), Migrationen/Seed
   fielen durch. Jetzt: composer install --no-dev im php-Container nach up.
2. Hetzner-Privatnetz-NIC kam auf einem Node nicht hoch → DB unerreichbar
   (/health degraded). Jetzt: privates Interface defensiv per DHCP hochziehen
   und auf 10.x-IP warten, bevor migriert wird.

Manuell auf den Live-Nodes bereits nachgezogen; dieser Fix macht Re-Deploys
reproduzierbar.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 18:43:45 +02:00
eaa5c506de Deploy: Servertyp cx22 → cx23 (cx22 von Hetzner abgekündigt)
cx22 existiert nicht mehr; aktueller Intel-Nachfolger ist cx23 (2 vCPU/4GB),
in nbg1 verfügbar. Defaults in variables.tf + Beispiel angepasst.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 15:19:42 +02:00
4d0146d6c2 Deploy: Auto-DNS über offizielle Hetzner Cloud DNS API (ein Token)
Hetzner hat DNS in die Cloud-API integriert → der hcloud-Provider (>=1.64) bringt
hcloud_zone/hcloud_zone_rrset mit. germanbrew/hetznerdns (separate API + eigener
Token) entfernt. dns.tf legt mit manage_dns=true Apex (@) + Wildcard (*) als
A-Records auf die caddy_ip; Zone wird per Name nachgeschlagen. Plan verifiziert
(12 to add). Kein separater DNS-Token mehr nötig.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 15:03:17 +02:00
70e979eae7 Deploy: cloud-init seedet die DB (app:seed) nach den Migrationen
Bisher liefen nur Migrationen → keine Daten, kein Admin-Login. app:seed ist
idempotent (überspringt, wenn admin@vcard4reseller.de existiert), läuft nur auf
app-1 (RUN_MIGRATIONS). Damit ist der dokumentierte Login admin/admin direkt nutzbar.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 14:26:00 +02:00
a3bdb3f81b Deploy: Auto-DNS optional/deaktiviert (manage_dns=false unblockt apply)
Der germanbrew/hetznerdns-Provider ruft schon beim Init die API auf und scheitert
am leeren Token, selbst ohne DNS-Ressourcen. Da DNS standardmäßig manuell gesetzt
wird (manage_dns=false), Provider entfernt + dns.tf → dns.tf.disabled (Code bleibt
für späteres Aktivieren erhalten). Lock-File auf hcloud-only reduziert.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 14:24:42 +02:00
b316d0baf8 Docs: Wallet-Setup-Anleitung (Apple & Google) per OpenSSL
Schritt-für-Schritt zum Erzeugen der Zugangsdaten (Pass Type ID + Cert/Key/WWDR
als PEM via CSR; Google Issuer + Service-Account + Freigabe) und Eintragen der
Env-Variablen. Verlinkt aus deploy/README.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 22:33:22 +02:00
3dfb0b2831 Wallet: QR auf Profilseite → Apple/Google Wallet-Pass
- WalletService (dependency-frei): Google signierter RS256-„Save"-JWT-Link;
  Apple .pkpass (pass.json + GD-Icons + manifest + PKCS#7 via openssl + zip).
  Konfigurationsgesteuert (env), ohne Zugangsdaten deaktiviert.
- WalletController: /w/{code} Landing (Geräteerkennung + Buttons),
  /w/{code}/qr.png, /apple.pkpass, /google (302). Adressierung via shortCode.
- Öffentliche Profilseite: QR-Bereich „Zur Wallet hinzufügen" (nur wenn
  Provider konfiguriert + shortCode vorhanden).
- .env Wallet-Block (leer=aus), KONZEPT §12 + deploy/README dokumentiert.

Verifiziert: not-configured → ausgeblendet/404; mit Test-Zertifikaten valides
signiertes .pkpass + Google-Save-JWT. Produktiv: echte Apple-/Google-Creds nötig.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 22:28:14 +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