21 KiB
Gast-Zugang: Read-only Showcase für Freunde/Bekannte und Bewerbungsgespräche — Rebuild-Runbook
Cross-cutting, kein eigener Host: nutzt CT101 (NAS), CT104 (Monitoring) und VPS (Caddy). Die Sicherheitsdiskussion, die zu diesem Design geführt hat: siehe ENTSCHEIDUNGEN.md, Abschnitt „Warum der Gast-Zugang eine eigene, komplett neue Oberfläche bekam".
Prinzip
Zwei komplett read-only Showcase-Konten (gast-freunde, gast-bewerbung), standardmäßig deaktiviert, manuell vor einem Termin aktiviert (plus optionales Ablaufzeit-Sicherheitsnetz). Kein Terminal, kein Schreibzugriff, keine Sicht auf interne Login-/Zugriffs-Daten. Bewusst kein Zugriff auf den bestehenden Management-Desktop (CT102) — der hat ein Terminal und sitzt im flachen LAN, für Gäste zu riskant.
Drei Bausteine:
- Grafana-Gast-Dashboard (CT104) — kuratierte Kopie ohne Login-Daten, plus fail2ban-Statistik als Sicherheits-Showcase
- Zweite Filebrowser-Instanz (CT101) — eigener Port/eigene DB, read-only, zeigt nur
/srv/gast-demo(= die genericierten Portfolio-Runbooks) - Uptime-Kuma-Status-Page (CT104) — öffentliche Ampel-Ansicht ohne technische Details
Alle drei über neue öffentliche Caddy-Vhosts auf dem VPS erreichbar (gleiches Muster wie guac.<DOMAIN>).
1. Grafana: Ordner-getrenntes Gast-Dashboard
Grafanas eingebaute Rolle „Viewer" reicht nicht als Isolation — ein Viewer sieht standardmäßig alle Dashboards der Org. Für echte Trennung: zwei Ordner mit gebrochener Berechtigungs-Vererbung.
# Dashboards in getrennte Unterordner der Provisionierung legen
mkdir -p /opt/monitoring/grafana-provisioning/dashboards/intern /opt/monitoring/grafana-provisioning/dashboards/gast
mv .../dashboards/homelab.json .../dashboards/intern/
mv .../dashboards/homelab-gast.json .../dashboards/gast/
provider.yaml mit zwei Providern (je eigenem folder: und path:), danach docker compose restart grafana (reine Datei-Provisionierung reicht sonst nicht für neue Ordner-Zuordnung).
Anschließend Ordner-Berechtigungen umbauen (klassische Permissions-API, nicht die neue /api/access-control/...-RBAC-API — letztere zeigt zwar den Ist-Zustand an, ist aber für Änderungen umständlicher):
# Intern: Viewer-Rolle komplett entfernen -> kein Viewer-Konto sieht das je automatisch
curl -u admin:$PW -X POST http://localhost:3000/api/folders/$INTERN_UID/permissions \
-d '{"items":[{"role":"Editor","permission":2}]}'
# Gast: Viewer-Rolle raus, stattdessen nur die zwei konkreten User explizit erlauben
curl -u admin:$PW -X POST http://localhost:3000/api/folders/$GAST_UID/permissions \
-d '{"items":[{"role":"Editor","permission":2},{"userId":2,"permission":1},{"userId":3,"permission":1}]}'
Nutzer anlegen (Rolle Viewer ist bei Admin-erstellten Usern bereits Default):
curl -u admin:$PW -X POST http://localhost:3000/api/admin/users \
-d '{"name":"Gast Freunde","login":"gast-freunde","password":"...","OrgId":1}'
⚠️ NICHT TUN: sich auf isDefault/Standard-Ordner-Vererbung verlassen und nur ein Dashboard ohne Ordner-Trennung anlegen — ein Viewer-Account sieht dann trotzdem alle anderen Dashboards der Instanz mit (bestätigt: curl -u gast-freunde ... /api/dashboards/uid/homelab-overview gab vor der Ordner-Trennung 200 zurück, keine echte Isolation).
Deaktivieren/Aktivieren eines Users:
curl -u admin:$PW -X POST http://localhost:3000/api/admin/users/$ID/enable # bzw. /disable
Echte Hostnamen aus den Legenden entfernt (2026-07-20, Nutzerwunsch)
Die Ressourcen-Panels (CPU/RAM/Disk je LXC) wurden zunächst 1:1 aus dem internen Dashboard übernommen — die Grafana-Legende zeigt dabei den host-Tag aus InfluxDB, also die echten Container-Hostnamen (adguard, nas, browser, vaultwarden, monitoring) bzw. den PVE-Hostnamen (<PVE_HOSTNAME>). Auf Nutzerwunsch durch Rollen-Bezeichnungen statt Servernamen ersetzt — man soll erkennen können, was läuft (DNS-Blocking, NAS, Passwort-Manager, …), ohne die echten internen Namen zu erfahren. Umsetzung per Flux map(), das den host-Wert vor dem finalen keep() umschreibt:
|> map(fn: (r) => ({ r with host:
if r.host == "adguard" then "DNS / Ad-Blocking"
else if r.host == "nas" then "NAS / Dateiablage"
else if r.host == "browser" then "Remote-Desktop"
else if r.host == "vaultwarden" then "Passwort-Manager"
else if r.host == "monitoring" then "Monitoring-Stack"
else r.host }))
|> keep(columns: ["_time", "host", "_value"])
Der PVE-Host selbst hat nur eine Zeile (kein Tag-Vergleich nötig): map(fn: (r) => ({ r with host: "Hauptserver" })). Zusätzlich Panel-Titel generisiert, die Hardware-Marken/Dataset-Namen im Klartext hatten: „Esprimo (PVE-Host)" → „Hauptserver", „Intenso NVMe" → „NVMe-Speicher", „nas/freigabe"/"nas/backups" → „Dateiablage"/"Backup-Speicher", „VPS" → „VPN-Gateway". Das interne Dashboard (Intern-Ordner) bleibt bewusst unverändert mit den echten Namen — nur die Gast-Kopie wurde angepasst. Per Live-Query gegen InfluxDB verifiziert: alle fünf LXC-Rollen + Hauptserver lösen korrekt auf, keine rohen Hostnamen mehr in den Ergebnissen.
⚠️ NICHT TUN: Rollen-Namen so generisch wählen, dass der Showcase-Zweck verloren geht (z.B. "System A"/"System B"). Ziel war ausdrücklich, dass ein Betrachter weiterhin erkennt, welche Art Dienst läuft — nur der konkrete interne Name/Hostname soll verborgen bleiben.
2. Zweite Filebrowser-Instanz auf CT101
Eigener Systemd-Unit, eigene DB, eigener Port, eigener dedizierter Linux-User (kein Zugriff auf sonstige Homelab-Pfade — Defense in Depth für den einzigen wirklich öffentlich erreichbaren Datei-Endpunkt):
useradd --system --no-create-home --shell /usr/sbin/nologin gastdemo
mkdir -p /srv/gast-demo /var/lib/filebrowser-gast
chown -R gastdemo:gastdemo /srv/gast-demo /var/lib/filebrowser-gast
# Inhalt: die genericierten Portfolio-Runbooks (siehe Abschnitt 4)
runuser -u gastdemo -- filebrowser config init -d /var/lib/filebrowser-gast/filebrowser.db --root /srv/gast-demo
runuser -u gastdemo -- filebrowser users add gast-freunde '...' -d /var/lib/filebrowser-gast/filebrowser.db \
--perm.admin=false --perm.execute=false --perm.create=false --perm.rename=false \
--perm.modify=false --perm.delete=false --perm.share=false --perm.download=true --scope /
Systemd-Unit bindet nur an die Tailscale-IP (<TS_IP_NAS>:8081), nicht ans LAN — der einzige Zugriffsweg ist über den VPS-Caddy-Vhost + Tailscale, LAN-Nutzer erreichen die Instanz gar nicht:
[Service]
User=gastdemo
Group=gastdemo
ExecStart=/usr/local/bin/filebrowser -d /var/lib/filebrowser-gast/filebrowser.db -a <TS_IP_NAS> -p 8081
Restart=on-failure
⚠️ NICHT TUN: --perm.execute vergessen. Der users add-Default für Execute ist true (Command-Runner-Feature) — beim ersten Anlegen übersehen, per users update ... --perm.execute=false nachgezogen. Immer nach dem Anlegen mit filebrowser users ls -d ... verifizieren, dass wirklich nur Download=true gesetzt ist.
⚠️ NICHT TUN: die bestehende NAS-Freigabe read-only exponieren wollen. Ein Berechtigungs-Bug in der Konfiguration würde dann echte Daten zeigen. Stattdessen komplett eigenes Verzeichnis + eigene Instanz, die von Anfang an nichts anderes kennt.
Bekannte Einschränkung: Filebrowser hat in dieser Version kein Feld/Flag zum Deaktivieren einzelner Nutzer (anders als Grafana). Der „Aus"-Zustand wird deshalb über den ganzen Systemd-Service abgebildet (systemctl stop filebrowser-gast) — das deaktiviert zwangsläufig beide Gast-Logins gleichzeitig auf dieser Ebene. Da beide Konten ohnehin unabhängige Passwörter mit identischen Rechten haben, ist das funktional unkritisch, aber beachten: „nur freunde aktiv lassen" gilt nur für Grafana, nicht für die Dateifreigabe.
3. Caddy-Vhosts (VPS)
Gleiches Muster wie guac.<DOMAIN>, /etc/caddy/Caddyfile:
grafana-gast.<DOMAIN> {
reverse_proxy <TS_IP_MONITORING>:3000
}
dateien-gast.<DOMAIN> {
reverse_proxy <TS_IP_NAS>:8081
}
status-gast.<DOMAIN> {
reverse_proxy <TS_IP_MONITORING>:3001
}
caddy validate --config /etc/caddy/Caddyfile vor systemctl reload caddy. TLS-Zertifikate zieht Caddy automatisch, sobald die DNS-A-Records existieren (siehe Abschnitt 6).
4. Portfolio-Runbooks (Inhalt von /srv/gast-demo)
Genericierte Kopien aller rebuild/*.md in ../rebuild-portfolio/ — echte LAN-/Tailscale-IPs, Domain, Tailnet-Name, MAC-Adresse, Benutzername ersetzt durch Platzhalter (<LAN_SUBNET>, <DOMAIN>, <TAILNET>, <PC1_MAC_ADDRESS>, <PVE_HOSTNAME>, <PRIMARY_USER>, …). Erklärung der Platzhalter in ../rebuild-portfolio/VARIABLEN.md. Debugging-Geschichten/„NICHT TUN"-Blöcke bleiben bewusst unverändert drin — nach der Anonymisierung nicht mehr auf die echte Instanz rückführbar, und genau das zeigt in einem Bewerbungsgespräch, dass reale Probleme selbst gefunden und gelöst wurden.
sed -i -e 's/192\.168\.178\.10\b/<LAN_IP_PVE>/g' ... *.md # vollständige sed-Kette: siehe Session-Log
Nach jeder Änderung an den echten rebuild/*.md-Dateien: Portfolio-Kopie manuell nachziehen (kein automatischer Sync) und erneut gegen die bekannten echten Werte grep-verifizieren.
5. Uptime Kuma: Gast-Monitore + Status-Page
Kein REST-API für Monitor-/Status-Page-Verwaltung — Python-Bibliothek uptime-kuma-api (Socket.IO-Client) nötig:
from uptime_kuma_api import UptimeKumaApi, MonitorType
api = UptimeKumaApi('http://<TS_IP_MONITORING>:3001')
api.login('admin', PASSWORD)
api.add_monitor(type=MonitorType.HTTP, name='Grafana (Gast)', url='https://grafana-gast.<DOMAIN>',
interval=60, retryInterval=60, maxretries=2, notificationIDList=[])
api.add_status_page('gast', 'Homelab Showcase')
api.save_status_page(slug='gast', title='Homelab Showcase', published=True, showPoweredBy=False,
publicGroupList=[{'name': 'Showcase', 'weight': 1,
'monitorList': [{'id': 12}, {'id': 13}, {'id': 14}]}])
⚠️ NICHT TUN: den drei Gast-Monitoren die ntfy-Notification zuweisen (weder explizit noch über isDefault). Die Konten werden absichtlich manuell rauf-/runtergefahren — mit Notification würde jedes Deaktivieren einen „Down"-Alarm auslösen. notificationIDList=[] beim Anlegen explizit setzen.
Zweite Gruppe: echte Infrastruktur-Telemetrie hinter Rollen-Namen (2026-07-20)
Die Status-Page wirkte mit nur drei Kacheln leer. Statt reiner Ampeln (Up/Down) zeigt eine zweite Gruppe „Infrastruktur" jetzt echte Ping-Telemetrie (Antwortzeit-Verlauf, Uptime-%) für die Kern-Systeme — mit denselben generischen Rollen-Namen wie im Gast-Grafana-Dashboard (siehe Abschnitt 1), damit beide Oberflächen konsistent wirken:
specs = [
('Hauptserver', '<LAN_IP_PVE>'), ('DNS / Ad-Blocking', '<LAN_IP_ADGUARD>'),
('NAS / Dateiablage', '<LAN_IP_NAS>'), ('Remote-Desktop', '<LAN_IP_DESKTOP>'),
('Passwort-Manager', '<LAN_IP_VAULTWARDEN>'), ('Monitoring-Stack', '<LAN_IP_MONITORING>'),
('VPN-Gateway', '<TS_IP_VPS>'),
]
for name, ip in specs:
api.add_monitor(type=MonitorType.PING, name=name, hostname=ip,
interval=60, retryInterval=60, maxretries=2, notificationIDList=[])
Uptime Kuma zeigt auf der Status-Page nur den konfigurierten Namen + Antwortzeit-Graph, nicht die Ziel-IP — die echten LAN-IPs sind also nur intern für den Check relevant, nie öffentlich sichtbar. Zweite Gruppe per publicGroupList mit eigenem weight ergänzt (bestehende „Showcase"-Gruppe bleibt unverändert stehen, Gruppen werden per Name identifiziert und beim Speichern komplett ersetzt — beide Gruppen müssen bei jedem save_status_page-Aufruf mit angegeben werden, sonst verschwindet die andere).
Verifiziert über die öffentliche URL (curl https://status-gast.<DOMAIN>/api/status-page/heartbeat/gast): alle sieben neuen Monitore liefern echte Ping-Antwortzeiten (0,05–25 ms je nach Ziel), Gruppennamen und Monitor-Namen kommen unverändert als reine Rollen-Bezeichnungen an — keine IP/Hostname in der API-Antwort sichtbar.
Uptime-Kuma-Admin-Passwort verloren gegangen: Die ursprünglichen Zugangsdaten wurden nur im Chat einer früheren Session ausgegeben und nirgends dauerhaft abgelegt (Konvention: Passwörter gehören in Vaultwarden, das ist hier nicht passiert). Reset direkt in der SQLite-DB des laufenden Containers (Uptime Kuma bringt node+bcryptjs+sqlite3 im Image mit):
HASH=$(docker exec uptime-kuma node -e "const bcrypt=require('bcryptjs'); console.log(bcrypt.hashSync(process.argv[1], 10));" "$NEWPW")
docker exec uptime-kuma sqlite3 /app/data/kuma.db "UPDATE user SET password = '$HASH' WHERE id = 1;"
Funktioniert bei laufendem Container (SQLite/WAL erlaubt den kurzen Fremdzugriff für ein einzelnes UPDATE). Lehre: Admin-Zugangsdaten für alle Dienste dieser Session tatsächlich in Vaultwarden ablegen, nicht nur im Chat stehen lassen.
6. DNS (manueller Schritt, keine API verfügbar)
Drei A-Records im STRATO-Panel für <DOMAIN>, alle auf die VPS-IP (gleiche IP wie der bestehende guac-Eintrag):
grafana-gast→ VPS-IPdateien-gast→ VPS-IPstatus-gast→ VPS-IP
⚠️ NICHT TUN: Caddy neu laden/starten, bevor alle A-Records korrekt gesetzt sind, und dann erwarten, dass es sich von selbst korrigiert. Certmagic (Caddys ACME-Bibliothek) merkt sich fehlgeschlagene Versuche pro Hostname und schaltet nach mehreren Fehlschlägen zur Schonung des Let's-Encrypt-Produktiv-Rate-Limits automatisch auf die Staging-CA um (liefert kein von Browsern akzeptiertes Zertifikat) plus einen Backoff von bis zu 20 Minuten zwischen Versuchen. Gleiches Muster wie beim ursprünglichen guac-Setup. Fix: erst alle DNS-Einträge verifizieren (dig @1.1.1.1 <name>.<DOMAIN> A, gegen mehrere öffentliche Resolver prüfen, eigener AdGuard-Resolver cached u.U. noch den alten Stand), danach systemctl restart caddy (nicht nur reload — ein Neustart setzt den internen Fehlversuch-/Backoff-Zustand zurück, ein reines reload nicht zuverlässig). Direkt danach in journalctl -u caddy auf "certificate obtained successfully" mit ca":"https://acme-v02.api.letsencrypt.org/directory" (nicht -staging-) prüfen.
Stolperstein bei diesem Durchlauf: ein Subdomain-Eintrag im STRATO-Panel landete zunächst auf 217.160.0.161 (STRATOs eigenem Parking-/Webhosting-Server) statt der eingetragenen Ziel-IP — vermutlich ein falsch vorausgewählter Eintragstyp im Formular (z.B. "STRATO-Webhosting" statt "eigene IP-Adresse"). Per dig direkt gegen die autoritativen STRATO-Nameserver (docks14.rzone.de/shades02.rzone.de) und mehrere öffentliche Resolver (1.1.1.1/8.8.8.8/9.9.9.9) geprüft, um Panel-Fehler von reiner Propagationsverzögerung zu unterscheiden — eine SOA-Antwort statt einer A-Antwort bedeutet "Eintrag existiert nicht", nicht "noch nicht propagiert". Ein Tippfehler in der Subdomain selbst (datein-gast statt dateien-gast) trat ebenfalls auf — beim Anlegen den tatsächlich in Caddy konfigurierten Namen exakt gegenprüfen.
7. Login-Tracking (Gast-Nutzung sichtbar machen)
Anders als bei Guacamole/Vaultwarden/PVE-Web/SSH ist bei den Gast-Oberflächen die Logausbeute schlechter:
- Grafana: loggt bei Formular-Login (
/login, POST) weder bei Erfolg noch bei Fehlschlag den Benutzernamen. Ein Fehlschlag erzeugtlevel=info msg="Failed to authenticate request" client=auth.client.form+ eine „Request Completed"-Zeile mitpath=/login status=401— aber ohne Username, könnte auch ein vertippter Admin-Login sein. Ein Erfolg erzeugt gar keine Log-Zeile beim Login selbst; einzig nachfolgende authentifizierte Requests tragenuname=gast-freunde/uname=gast-bewerbungals Tag.track-grafana-gast.sh(Cron alle 5 Min. auf CT104) zählt deshalb Fehlschläge generisch und deutet „Aktivität" über das Vorkommen dieseruname=-Tags. - Filebrowser: loggt nur Fehlschläge, mit IP (
/api/login: 403 <ip> <err>), keine Erfolge — gleiche Einschränkung wie beim bereits dokumentierten AdGuard-Gap.track-filebrowser-gast.sh(Cron alle 5 Min. auf CT101, no-op wenn der Service gerade gestoppt ist) trackt entsprechend nurfail.
Beide schreiben ins bestehende logins-Measurement (service=grafana-gast/service=filebrowser-gast), gleiches Muster wie die übrigen Tracker.
ntfy-Push (2026-07-20 ergänzt): track-grafana-gast.sh pusht bei >3 Fehlversuchen (hohe Priorität) und bei jeder erkannten Aktivität (uname=-Tag, Standard-Priorität — das deckt "erfolgreicher Login" für Grafana ab, da ein echtes Login-Event selbst nicht separat loggbar ist). track-filebrowser-gast.sh pusht nur bei >3 Fehlversuchen — ein Push bei erfolgreichem Filebrowser-Login ist technisch nicht möglich: kein Verbose-/Debug-Log-Flag vorhanden (filebrowser -h zeigt nur -l/--log für das Ausgabeziel, keine Log-Level-Option), das Tool loggt nachweislich nur Fehlschläge — exakt dieselbe Einschränkung wie bei AdGuard.
8. Aktivieren/Deaktivieren + Ablaufzeit-Sicherheitsnetz
Zwei Skripte auf dem PVE-Host (steuern CT104 + CT101 gemeinsam über pct exec):
gast-aktivieren.sh freunde|bewerbung [stunden]
gast-deaktivieren.sh freunde|bewerbung|alle
gast-aktivieren.sh aktiviert den Grafana-User, startet filebrowser-gast.service, und plant bei Angabe von [stunden] per at einen einmaligen Folgejob (gast-deaktivieren.sh <wer>) — reines Sicherheitsnetz für den Fall, dass das manuelle Abschalten vergessen wird, kein Ersatz dafür. gast-deaktivieren.sh stoppt filebrowser-gast.service nur dann mit, wenn danach kein Gast-Grafana-Konto mehr aktiv ist (sonst würde das Deaktivieren von freunde auch bewerbungs Dateizugriff kappen, obwohl der ggf. noch laufen soll).
apt-get install -y at && systemctl enable --now atd
⚠️ NICHT TUN: at-Pakete für die Auto-Deaktivierung annehmen, ohne atd separat zu aktivieren — auf frisch installiertem Debian läuft der Dienst nach apt-get install at nicht automatisch.
Automatisches Passwort-Cycling
Weder Grafana OSS noch Filebrowser kennen ein "Passwort muss nach Login neu gesetzt werden"-Flag — als praktisches Äquivalent erzeugt gast-aktivieren.sh bei jeder Aktivierung ein frisches Zufallspasswort (12 Zeichen, nur Buchstaben/Ziffern ohne verwechselbare Zeichen wie 0/O/1/l/I — bewusst niedrige Komplexität, da es dem Gast mündlich/per Kurznachricht mitgeteilt werden soll) und setzt es für beide Dienste gleich, damit sich der Gast nur ein Passwort merken muss:
NEWPASS=$(tr -dc 'ABCDEFGHJKMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789' < /dev/urandom | head -c 12 || true)
curl -u admin:$GF_PASS -X PUT http://localhost:3000/api/admin/users/$ID/password -d "{\"password\":\"$NEWPASS\"}"
filebrowser users update gast-freunde -d /var/lib/filebrowser-gast/filebrowser.db -p "$NEWPASS"
Altes Passwort wird dadurch automatisch ungültig — keine manuelle Rotation nötig, das alte Passwort muss auch nirgends aufgehoben werden.
⚠️ NICHT TUN: tr ... | head -c N unter set -o pipefail verwenden, ohne den SIGPIPE-Fall abzufangen. head beendet die Pipe, sobald genug Bytes gelesen sind — tr bekommt dadurch SIGPIPE (Exit 141), was mit pipefail das ganze Skript abbricht. Fix: ... | head -c N || true.
⚠️ NICHT TUN: das Filebrowser-Passwort per CLI setzen, während filebrowser-gast.service bereits läuft. Filebrowsers bbolt-Datenbank erlaubt nur einen Prozess gleichzeitig — CLI und laufender Dienst kollidieren mit Error: timeout. Reihenfolge im Skript: Service stoppen → Passwort per CLI setzen → Service starten.
Verifiziert: gast-aktivieren.sh freunde → Grafana-Login + Filebrowser-Login funktionieren; gast-deaktivieren.sh freunde → beides sofort wieder zu; at-Job mit 1 Minute Vorlauf → gast-deaktivieren.sh feuert zuverlässig automatisch. Nach dem DNS-/Zertifikats-Fix zusätzlich vollständig über die echten öffentlichen URLs (nicht nur intern/Tailnet) durchgetestet: Login bei aktiviertem Konto funktioniert über https://grafana-gast.<DOMAIN> und https://dateien-gast.<DOMAIN>, zeigt nachweislich nur das Gast-Dashboard, Status-Page lädt; nach Deaktivierung liefern beide öffentlichen URLs wieder 401/502. Passwort-Rotation getestet: nach zweiter Aktivierung meldet das alte Passwort 401, nur das neu ausgegebene funktioniert — für beide Konten (freunde/bewerbung) einzeln bestätigt.
ntfy-Push bei Aktivieren/Deaktivieren (2026-07-20)
Beide Skripte schließen jetzt mit einem curl an http://localhost:8090/homelab-alerts (via pct exec 104, da ntfy auf CT104 läuft) ab — Standard-Priorität, kein Alarm-Ton, reine Statusmeldung ("Gast-Zugang 'freunde' wurde soeben aktiviert (Auto-Deaktivierung in 3h)." bzw. "... deaktiviert."). Über curl "http://localhost:8090/homelab-alerts/json?poll=1&since=2m" gegen echte Zustellung verifiziert (nicht nur, dass der curl-Aufruf ohne Fehler durchläuft).