07 — Hetzner + DNS/Cloudflare Audit

Scope: Hetzner-Hosting (heute: av-tools Project mit 1 Server), Hetzner-Object-Storage-Vorbereitung (noch nichts angelegt), DNS/Cloudflare-Surface fuer agenticventures.de und marvinkuehlmann.com. NDA-Relevanz markiert (Becker-NDA 10y).

Quelle: mcp__hetzner__* Tools (Servers, Firewalls, Volumes, SSH-Keys) live abgefragt 2026-05-15, plus passive DNS-Lookups (dig). Kein aktives Port-Probing.

Ampel-Uebersicht

CheckAmpelKurz-Befund
1. Hetzner Servers (Exposure, Backup)gelbPublic-IP exposed (by design), Backup NULL, kein Cloud-DDoS-Schutz dokumentiert
2. Firewalls (Regeln, Coverage)gelbSSH von 0.0.0.0/0 offen (key-only, aber kein Geofence/Tailscale), nur 1 Firewall an 1 Server
3. SSH-Keysgruen1 Key, ed25519, klar zugeordnet, Labels sauber
4. Volumesgruen0 dangling, 0 angelegt (LUKS-Frage NA bis erstes Volume)
5. Hetzner Object Storagegruen-infoDoku-Mode, noch nichts angelegt — Gating + Werte-Double-Check sauber gespect
6. Cloudflare Tunnels / TLS-Mode / Zero-Trustrot-blindAPI nicht zugaenglich, mehrere kritische Settings unverifiziert
7. DNS (DNSSEC, CAA)rotDNSSEC DEAKTIVIERT auf beiden Domains, keine CAA-Records
8. NDA-Compliance / Subdomain-LeakgruenKein Kunden-Name in oeffentlich resolvebaren Records (Becker-NDA OK)

1. Hetzner Servers

Bestand (Live-MCP-Read 2026-05-15):

ServerIDTypLocationIPv4IPv6BackupCreated
av-tools-stirling-01131113789cx23nbg1-dc346.225.16.2312a01:4f8:1c18:5e7f::/64null (deaktiviert)2026-05-15

Findings:

  • F-07-01 (gelb): backup_window: null — Hetzner-Snapshot-Backup nicht aktiviert. Bei cx23 kostet das 20 % Aufschlag (~1 €/Monat) und gibt 7 Slot-Snapshots automatisch. Begruendung warum gelb statt rot: Stirling-PDF hat keine Nutzdaten die nicht reproduzierbar sind — Bootstrap-Skripte liegen lokal/im Vault, Stack ist Compose + Docker-Volumes mit ephemeren Files. Aber: Compose-File + /opt/stirling/{data,config} sind heute NICHT im Vault gespiegelt → Reset = Userlist + interner Login + custom-files futsch. Empfehlung: Backup an, oder mindestens nightly tar | rclone von /opt/stirling/{data,config,custom-files,extra-configs} in einen Hetzner-Bucket (sobald av-tools-bucket existiert).
  • F-07-02 (gruen): rescue_enabled: false, protection.delete: false, protection.rebuild: false — alles erwartbar. Aber: protection.delete=true fuer alle Prod-Server (auch av-tools) waere ein billiger Anti-Fat-Finger-Schutz. Empfehlung: setzen, sobald Server-Inventar > 1.
  • F-07-03 (info): Server hat reverse-DNS auf static.231.16.225.46.clients.your-server.de. (Hetzner-Default). Kein Reverse-DNS-Leak zu agenticventures.de, was OK ist — Verbindung Server ↔ Marken-Domain ist nur via Cloudflare-Tunnel-CNAME einseitig sichtbar.
  • F-07-04 (gelb): Outgoing-Traffic 7,86 MB seit Server-Start (heute), Ingoing 1,13 GB — Verhaeltnis plausibel fuer reines Tunnel-Setup. Aber: kein Egress-Monitoring/Cap dokumentiert, kein Alarm bei „Server schreit auf einmal ins Internet” (Indikator fuer Crypto-Mining-Compromise). Empfehlung: Better-Stack-Heartbeat oder Hetzner-internes Traffic-Alert konfigurieren bevor Server-Inventar waechst.

2. Firewalls

Bestand:

FirewallIDRulesAttached To
av-tools-stirling10976973SSH/22 + ICMP (beide from 0.0.0.0/0, ::/0)av-tools-stirling-01

Findings:

  • F-07-05 (gelb): SSH von Welt offen (0.0.0.0/0 + ::/0). Begruendung in av-tools: „key-only auth, kein password”. Stimmt — SSH key-only + fail2ban + unattended-upgrades sind in Bootstrap dokumentiert. Trotzdem ist die Surface unnoetig gross. Empfehlung Stufe 1 (5 min): SSH-Rule auf eigene aktuelle IP einschraenken (hcloud firewall add-rule ... --source-ips $(curl -s ifconfig.me)/32), zweite Rule fuer Hetzner-Recovery oder Tailscale-Adressraum, statt /0. Empfehlung Stufe 2 (richtiger Weg): Tailscale auf den Server, SSH-Rule entfernen, SSH nur ueber Tailscale-IP. Default fuer alle zukuenftigen Industriekunden-Server.
  • F-07-06 (gelb): Kein expliziter Deny-All-Egress — Hetzner-Firewall ist „default deny inbound, default allow outbound”. Bei einem PDF-Tool nicht kritisch, aber bei Industriekunden-Stack (PII-Daten, LLM-Calls) sollte Egress auf Allowlist (Mistral-API, S3-Endpoint, Cloudflare-Edge, Apt-Mirror) — sonst koennen Compromise-Payloads frei nach C2 telefonieren. Pattern fuer Hetzner-MVP-Industriekunde dokumentieren in _index.
  • F-07-07 (gruen): Firewall ist tatsaechlich attached (applied_to.[0].server.id == 131113789). Kein „Firewall existiert, aber wirkt auf nichts”-Antipattern.
  • F-07-08 (gruen): Labels sauber (owner=marvin, purpose=av-tools, service=stirling-pdf) — Inventar-Disziplin gemaess naming-konvention eingehalten.

3. SSH-Keys

Bestand:

NameIDTypeFingerprintOwner
marvin-av-tools112321437ed25519ab:95:0c:fc:09:40:df:57:d5:3f:da:39:30:c6:f6:0bmarvin (label)

Findings:

  • F-07-09 (gruen): Nur 1 Key, ed25519 (modern), klar gelabeled. Comment marvin@av-tools-stirling — purpose-bound (separat von ggf. anderem Personal-Key), gut.
  • F-07-10 (info): Lokaler Pfad laut Doku ~/.ssh/hetzner_av_tools. Ich kann den lokalen Pfad/Permissions hier nicht pruefen (kein Filesystem-Lookup im Scope). Empfehlung Marvin: ls -la ~/.ssh/hetzner_av_tools* → muss 600 private, 644 public sein, beide owned by user. Plus: in 1Password als Backup hinterlegt? Wenn nein → tun, sonst Hetzner-Console-Reset noetig wenn lokaler Mac stirbt.
  • F-07-11 (info): Rotation-Plan: Doku in api-token-konvention beschreibt API-Token-Rotation alle 6 Monate, aber NICHT SSH-Key-Rotation. Bei „Mitarbeiter raus oder Mac kompromittiert” muss klar sein: neuen Key in Hetzner zufuegen, alten loeschen, ~/.ssh/authorized_keys auf Server kontrolliert ersetzen. Empfehlung: 1 Satz in av-tools.md Runbook ergaenzen.

4. Volumes

  • F-07-12 (gruen): 0 Volumes — keine dangling, kein Cost-Drift. Sobald erstes Volume angelegt wird (Industriekunde, Postgres-Data): Encryption-Frage stellt sich. Hetzner Cloud Volumes sind im Klartext (kein at-rest-Encryption ab Werk im Free-Tier). Standard: LUKS auf dem Server mit Key via systemd-creds oder Mistral-KMS-Aequivalent. In cloud-volume-block-storage heute NICHT dokumentiert — Action: Volume-Encryption-Pattern (LUKS-Setup) als „Pflicht-Schritt vor erstem Industriekunden-Volume” ergaenzen.

5. Hetzner Object Storage

Status: noch kein Bucket angelegt — Doku in storage beschreibt geplanten Aufbau (<kunde>-data, <kunde>-audit, <kunde>-test-objectlock).

Findings (Doku-Review):

  • F-07-13 (gruen): Object-Lock-Werte-Double-Check (2555 Tage = 7y, NICHT 25550) ist explizit in storage.md markiert — Disziplin gut.
  • F-07-14 (gruen): Public-Access-blocked + Versioning-enabled als Default in der Bucket-Anlage-Checkliste. Pattern stimmt.
  • F-07-15 (gelb): age-encrypted Backups (<kunde>-audit/llm/...jsonl.gz.age) ist im Doku-Pattern erwaehnt — aber Key-Management fuer age-Keys nicht definiert. Wo liegt der Identity-Key? 1Password? Auf dem Server? Quorum-Restore moeglich? Bei Becker-NDA-Relevanz (Audit-Log enthaelt potentiell Becker-PII) ist Verlust-des-age-Keys = unlesbare 7-Jahre-Audit-Logs = HGB-Verletzung. Action: ADR fuer age-Key-Management vor erstem Bucket-Anlegen.
  • F-07-16 (info): MFA-only Read-Key fuer audit-Bucket (<kunde>-audit-read-mfa) ist in Doku spec’d — Hetzner-S3-Credentials unterstuetzen aber keine MFA-Erzwingung auf API-Token-Ebene wie AWS-S3. Workaround: separater Hetzner-User mit MFA-required Console-Login, der die Keys generiert + verwaltet, plus orga-prozessual „Marvin tippt Key nur ein nach 1Password-MFA-Unlock”. Das ist eine schwaechere Garantie als AWS — sollte explizit in Compliance-Argumentation Richtung Industriekunden so kommuniziert sein.
  • F-07-17 (info): Cross-Region/Off-Site-Backup-Plan: rclone manuell (siehe Doku). Bei Becker (NDA-Daten 10y) sollte Off-Site-Strategie vor Go-Live stehen, nicht reaktiv. Action: rclone-Cron-Pattern + Ziel-Bucket (AWS S3 in av-production?) als ADR vor Industriekunden-Onboarding.

6. Cloudflare Tunnels / TLS / Zero Trust

Was ich pruefen konnte: Live-DNS-Resolution. Alle MCP-Subdomains (mcp-whatsapp, mcp-vf, pdf) zeigen auf Cloudflare-Anycast-IPs (172.67.220.246, 104.21.78.120) — Cloudflare-Edge ist also live davorgeschaltet.

Was ich NICHT pruefen kann ohne Cloudflare-API/MCP:

  • TLS-Mode (Full Strict vs Full vs Flexible) pro Zone
  • Always-Use-HTTPS (Redirect 80→443)
  • HSTS-Settings (max-age, includeSubdomains, preload)
  • Min-TLS-Version (sollte 1.2+, idealerweise 1.3)
  • Tunnel-Konfiguration pro Tunnel (Tunnel-IDs aus Doku: 6537ca14-... av-tools, ce6dd7c0-... mcp-vf, a3af8b46-... mcp-whatsapp)
  • Cloudflare-Access-Policies (existiert eine fuer pdf.agenticventures.de? Doku sagt: noch nicht angelegt → F-07-19)
  • WAF-Rules / Bot-Fight-Mode / Rate-Limiting pro Hostname
  • mTLS oder Service-Token zwischen Edge und Origin (Tunnel hat per-default kein mTLS Edge↔Tunnel-Cert)

Findings (was sicher gesagt werden kann):

  • F-07-18 (rot-blind): Verifikations-Luecke. Action fuer Marvin: in Cloudflare Dashboard pro Zone (agenticventures.de + marvinkuehlmann.com) folgende Settings screenshotten + in intern/capabilities/hetzner/cloudflare.md (neu, gibt es noch nicht) festhalten: SSL/TLS-Mode, Edge-Cert-Status, HSTS, Min-TLS-Version, Always-Use-HTTPS, Auto-HTTPS-Rewrites, Opportunistic-Encryption. Mindest-Soll: Full Strict + HSTS 1y + includeSubdomains + Min-TLS 1.2.
  • F-07-19 (gelb, dokumentiert): pdf.agenticventures.de hat laut av-tools.md noch keine Access-Application angelegt — einzige Auth ist Stirling-interne Loginschicht mit Default-User admin/stirling-pdf. Wenn der Default-User nicht beim ersten Login geaendert wurde, ist Stirling effektiv offen sobald jemand die URL kennt. Action sofort: Cloudflare-Access-App anlegen mit Email-OTP-Allowlist, dann erst Default-Pwd-Reset im Stirling-Container verifizieren. Sequence wichtig — sonst Window wo Pwd-Wechsel-Flow ohne Access-Layer haengt.
  • F-07-20 (info): mcp-vf + mcp-whatsapp laufen ueber AWS-Fargate-Tunnel-Sidecar (laut /Users/marvinkuehlmann/source/agentic-ventures/intern/capabilities/mcps/_index.md), nicht Hetzner — sind also nur DNS-seitig im Scope dieses Audit-Teils, Compute-Audit gehoert in AWS-Teil.
  • F-07-21 (gelb): Tunnel-Token-Rotation-Plan fehlt. av-tools.md beschreibt wie rotiert wird (install-tunnel.sh <new-token>), aber kein Trigger / Interval / Owner. Empfehlung: gleicher 6-Monats-Rhythmus wie API-Tokens, plus sofort bei Compromise-Signal.

7. DNS — DNSSEC + CAA

Lookups (passive, dig 2026-05-15):

DomainNSDNSKEYDSCAA
agenticventures.delynn.ns.cloudflare.com, selah.ns.cloudflare.comleerleerleer
marvinkuehlmann.com*.awsdns-* (Route 53)leerleerleer

Findings:

  • F-07-22 (rot): DNSSEC ist auf beiden Domains nicht aktiv. Kein DNSKEY-Record, kein DS-Record bei der Registry. Konsequenz: Spoofing-Angriffe gegen mcp-*.agenticventures.de (z.B. cache-poisoning gegen Kunden-Resolver) nicht erkennbar. Bei Industriekunden-Sales-Story „DSGVO-streng, EU-only, Becker-grade” ist fehlendes DNSSEC eine Compliance-Inkonsistenz — Sales-Material verspricht „voller Edge-Schutz”, DNS-Layer ist aber nackt. Action:
    • agenticventures.de (Cloudflare-Authority): Cloudflare Dashboard → DNS → Settings → DNSSEC → Enable. Plus: DS-Record bei Strato (Registrar) einreichen. ~5 min Aufwand, kostenlos.
    • marvinkuehlmann.com (Route 53): Route 53 Hosted Zone → Sign Zone, KSK in KMS erzeugen lassen, DS bei Registrar einreichen.
  • F-07-23 (rot): CAA-Records fehlen auf beiden Domains. Heisst: jede CA der Welt darf ein Zertifikat fuer *.agenticventures.de ausstellen. Mit Cloudflare-Edge laeuft TLS-Termination zwar bei CF (Let’s Encrypt / Google Trust Services / Cloudflare-Cert), aber ohne CAA kann ein boeswilliger Akteur via Domain-Hijack oder DNS-Hijack ein eigenes Cert anfordern. Action: CAA-Records setzen die nur die Cloudflare-CAs erlauben:
    agenticventures.de.   CAA 0 issue "letsencrypt.org"
    agenticventures.de.   CAA 0 issue "pki.goog"
    agenticventures.de.   CAA 0 issuewild "letsencrypt.org"
    agenticventures.de.   CAA 0 iodef "mailto:hello@marvinkuehlmann.com"
    
    Analog fuer marvinkuehlmann.com (ggf. mit Amazon-Trust-Services wenn AWS-ACM Certs irgendwo gezogen werden). ~10 min Aufwand, kostenlos. Vor Anlage Cloudflare-Doku checken welche CAs CF aktuell nutzt — andernfalls reisst man sich die eigene Cert-Renewal-Pipeline auf.
  • F-07-24 (info): agenticventures.de (Cloudflare-NS) und marvinkuehlmann.com (Route-53-NS) — zwei verschiedene Authority-Provider. OK, dokumentiert in firma/web-properties.md. Risiko-Aspekt: Lock-In-Diversifizierung gut, aber „wo liegt was DNS-technisch” muss klar bleiben — siehe Action F-07-22 (zwei separate DNSSEC-Aktivierungen).

8. NDA-Compliance / Subdomain-Leak

  • F-07-25 (gruen): Live-Subdomains die ich resolved habe: agenticventures.de, www.agenticventures.de, mcp-whatsapp.agenticventures.de, mcp-vf.agenticventures.de, pdf.agenticventures.de. Kein Kunden-Name leakt (kein becker.agenticventures.de, kein *-bss.* o.ae.). Pattern mcp-<kunde>.agenticventures.de aus web-properties ist eine Sales-Risikoquelle wenn ein Kunde tatsaechlich namentlich als Subdomain erscheint. Vor jedem neuen mcp-<kunde>.*-DNS-Eintrag pruefen: ist das ein NDA-Kunde? Wenn ja: pseudonymer Slug (z.B. mcp-c1.agenticventures.de, intern c1 = becker) — gilt insbesondere fuer Becker (NDA-Frist 10y, CLAUDE.md Regel 22).
  • F-07-26 (gruen): Hetzner-Server-Hostnames im RDNS sind Hetzner-Default (static.231.16.225.46.clients.your-server.de) — kein Selbst-Set-Hostname leakt Kunden-Daten. Bei Industriekunden-Servern dieselbe Disziplin halten: PTR-Records nur auf neutrale Slugs (av-c1-web.example o.ae.), nicht auf Kundennamen.

Top 3 — was als naechstes

  1. DNSSEC + CAA auf beiden Domains aktivieren (F-07-22 + F-07-23). Rot, ~15 min Aufwand, kostenlos, schliesst zwei harte Compliance-Luecken die bei jedem Industriekunden-Pre-Sales-Audit aufschlagen wuerden.
  2. pdf.agenticventures.de Cloudflare-Access-App live nehmen (F-07-19) — heute ist die Stirling-Instanz nur durch interne Login-Schicht mit Default-Pwd geschuetzt (laut Doku noch nicht geaendert beim ersten Login dokumentiert). Plus: SSH-Firewall-Rule von 0.0.0.0/0 auf Marvin-IP-only oder Tailscale (F-07-05). Beides am gleichen Server, eine Session.
  3. Cloudflare-Settings dokumentieren + Hetzner-Volume-Encryption-Pattern spec’en (F-07-18 + F-07-12). Ohne diese beiden Doku-Stuecke ist die Hetzner-Spur fuer den naechsten Industriekunden NICHT go-live-fertig — Cloudflare-Mode + age-Key-Management + LUKS-Pattern muessen vor erstem Project-Anlage als ADRs stehen, sonst wird das erste Setup zur Vorlage fuer kompromittierte Defaults.

Was Marvin manuell nachreichen muss (Cloudflare-API nicht im Scope)

Cloudflare-MCP/API ist heute nicht in Marvins MCP-Inventar (intern/capabilities/mcps/_index.md). Folgende Werte bitte per Browser-Screenshot aus Cloudflare Dashboard ziehen und in eine neue Datei intern/capabilities/hetzner/cloudflare.md (oder besser: intern/capabilities/cloudflare/_index.md — Cloudflare ist nicht Hetzner-spezifisch) ablegen:

  • Pro Zone (agenticventures.de, marvinkuehlmann.com):
    • SSL/TLS encryption mode (soll: Full Strict)
    • Edge-Cert: Universal SSL aktiv? Min TLS Version? TLS 1.3 enabled?
    • HSTS: max-age + includeSubdomains + preload + no-sniff
    • Always Use HTTPS: on
    • Automatic HTTPS Rewrites: on
    • DNSSEC: on/off + DS-Record bei Registrar eingereicht?
  • Pro Tunnel (av-tools, mcp-vf, mcp-whatsapp):
    • Tunnel-Status (healthy/degraded)
    • Public-Hostname-Rules (welcher Hostname → welcher Origin-Port)
    • Access-Application existiert? Mit welcher Policy (Email-OTP, IP-Allowlist, Service-Token)?
    • Session-Duration der Access-App
  • Zero Trust / Access Audit Log: pruefen ob Logs aktiviert + wohin gespeichert (SIEM-Forward?)
  • WAF: Managed-Rules-Set aktiv? Bot-Fight-Mode? Rate-Limiting-Rules pro mcp-*-Subdomain?

Sobald die Datei da ist: Folge-Audit mit Browser-MCP (Claude in Chrome) gegen Cloudflare-Dashboard moeglich.