10 KiB
Sultan für Hoster: Kunden-Onboarding (pro / enterprise)
Für Hoster, die Sultan als bezahlten Dienst anbieten: Du betreibst Ingress (Traefik + sultan server), der Kunde betreibt seine Backends mit sultan agent. Grundinstallation: siehe community.md. Wartung: siehe wartung.md.
Stand: Der kommerzielle Teil (Lizenzen, Mahnwesen, Vertragsende) ist durch Tests abgedeckt, im echten Betrieb aber noch nicht erprobt. Bekannte Lücken stehen am Ende.
Wer hat was?
| Hoster | Kunde | |
|---|---|---|
| Läuft dort | Traefik, sultan server |
Docker-Host(s) mit sultan agent |
| Geheimnisse | suldata/ des Servers: TLS-Schlüssel, Master-Key (signiert Lizenzen, Leases, Befehle) |
node.key je Host; verlässt den Host nie, auch du siehst ihn nicht |
| Entscheidet | welche Domains, wie viele Routen, bis wann | welche Dienste wie geroutet werden (Labels) |
| Sieht | alle Routen, Knoten, Verstöße, Fristen | nur sein eigenes Agent-Log |
Der Kunde kann nur Domains aus seinem Mandanten beanspruchen und nur bis max_routes. Alles andere verwirft der Server mit Eintrag im Audit-Log. Kunden sehen sich gegenseitig nicht. Gleichnamige Router verschiedener Kunden kollidieren nicht, weil jeder Router in Traefik als <mandant>__<knoten>__<router> erscheint.
1. Vor dem Onboarding klären
Aus dem Vertrag gehen diese Werte in den Mandanten:
| Wert | Flag | Hinweise |
|---|---|---|
| Kennung | --id |
a–z 0–9 - _, dauerhaft (erscheint in Routernamen, Logs, Monitoring). Z. B. Kundennummer. |
| Name, Kontakt | --name, --email |
für dich (Listen, Benachrichtigungen) |
| Domains | --domains |
kunde.de = genau diese; *.kunde.de = alle Subdomains, ohne kunde.de selbst → meist beides eintragen. Wildcard auf TLD (*.de) ist verboten. Umlaut-Domains als Punycode (xn--…). |
| Paket | --tier pro oder enterprise |
Beide verhalten sich technisch derzeit gleich (Mahnwesen, Vertragsende). Der Unterschied ist vertraglich. community = kein Mahnwesen, läuft nicht ab. |
| Routen | --max-routes |
Anzahl Router (jeder traefik.http.routers.<name> zählt, auch Redirect-Router). -1 = unbegrenzt. Überzählige werden alphabetisch verworfen. |
| Vertragsende | --valid-until JJJJ-MM-TT |
Default: heute + 1 Jahr. Danach sehen Besucher die Landingpage „Hosting abgelaufen“. |
| Zusatzfunktionen | --features |
custom_middleware, websockets, tcp_stream. Ohne custom_middleware sind nur Standard-Middlewares erlaubt (Redirects, Pfad-Umschreibung, Header, Kompression). BasicAuth, Rate-Limit, IP-Allowlist usw. brauchen das Feature, sonst wird der Router mit Verstoß abgelehnt. chain und errors sind nie erlaubt. |
Achtung: Vertragsende, Domains und Paket lassen sich bisher nicht nachträglich ändern (tenant update fehlt, siehe Lücken). Deshalb --valid-until und --domains beim Anlegen sorgfältig setzen.
2. Netzwerk mit dem Kunden klären
Das ist der häufigste Grund für ein holpriges Onboarding. Zwei Wege müssen frei sein:
- Agent → Server: ausgehend TCP 8443 vom Kunden-Host zu deiner
--public-url. Meist ohnehin offen. - Traefik → Kunden-Backend: dein Ingress verbindet sich per HTTP auf den veröffentlichten Port des Containers. Dafür gibt es drei Möglichkeiten:
| Situation beim Kunden | Lösung |
|---|---|
| öffentliche IP / eigenes Rechenzentrum | Kunde gibt die Ports nur für deine Ingress-IP(s) frei |
| hinter NAT/CGNAT/DS-Lite | VPN/Overlay (z. B. NetBird): Agent mit SULTAN_BACKEND_INTERFACE=wt0; eventuell Einladung mit --server-url https://<netbird-ip>:8443 |
| gleiches LAN wie der Ingress | nichts zu tun |
Vorgaben für den Kunden:
- Ports veröffentlichen (
"9080:80"), nicht nur127.0.0.1:9080:80. - Der Agent meldet als Backend die Adresse, über die er deinen Server erreicht. Das kann eine IPv6-Adresse sein. Dann muss dein Ingress IPv6 können, sonst setzt der Kunde
SULTAN_BACKEND_HOST. - Knoten-ID: Default ist der Hostname. Gleichnamige Hosts beim selben Kunden (z. B.
web01) brauchenSULTAN_NODE_ID.
3. Mandant anlegen und einladen
cd /docker/sultan-server
docker compose exec sultan-server sultan token tenant add \
--id k10042 --name "Novesia Bonn" --email it@novesia-bonn.de \
--domains "novesia-bonn.de,www.novesia-bonn.de" \
--tier pro --max-routes 10 --valid-until 2027-10-31
docker compose exec sultan-server sultan token invite --tenant k10042 --ttl 7d
Die Einladung (sltn_enroll_…):
- Ein Knoten pro Einladung. Drei Hosts = drei Einladungen.
- Bis zur Benutzung geheim: Wer sie hat, kann einen Knoten für diesen Kunden anmelden. Danach ist sie wertlos. Übergabe über einen sicheren Kanal (Kundenportal, verschlüsselte Mail, Passwortmanager), nicht ins Ticket kopieren.
- Gespeichert wird nur ein Hash; du kannst sie später also nicht noch einmal anzeigen. Verloren oder abgelaufen → einfach neu erzeugen. Aufräumen:
sultan token purge. - Sie enthält Server-Adresse und Zertifikats-Fingerprint. Der Kunde braucht nichts weiter, kein CA-Zertifikat, keine IP-Liste. Mit einer gefälschten Adresse landet der Agent nie bei einem fremden Server (Pinning).
4. Was du dem Kunden schickst
Ein Paket aus:
- Einladung (sicherer Kanal) und Gültigkeit.
- Compose-Vorlage deploy/compose/agent + Image
zot.chmln.de/sultan:<version>. - Die Labels, passend zu deinen Traefik-Namen (Entrypoint, Certresolver):
labels: - "traefik.enable=true" - "traefik.http.routers.shop.rule=Host(`www.novesia-bonn.de`) || Host(`novesia-bonn.de`)" - "traefik.http.routers.shop.entrypoints=websecure" - "traefik.http.routers.shop.tls.certresolver=le" - "traefik.http.services.shop.loadbalancer.server.port=80" - DNS-Vorgabe: Domains per CNAME auf deinen Ingress (z. B.
web11.r25dc.de). Erst dann klappt Let's Encrypt. - Freigabe aus Abschnitt 2 (Ports nur für deine Ingress-IP).
- Die Wartungsregeln aus wartung.md, vor allem:
stopstattdownundsultan agent maintenance on.
5. Abnahme
docker compose exec sultan-server sultan token node list --tenant k10042 # online, Lease bis …
curl -s 'http://127.0.0.1:8080/v1/traefik-config?format=yaml' | grep k10042 # Router + Backend-URL
curl -sI http://<backend-ip>:<port> # vom Ingress: Backend erreichbar?
curl -sI https://www.novesia-bonn.de # Zertifikat + Seite
docker compose logs sultan-server | grep -i verstoß # abgelehnte Domains/Routen?
Fehlt eine Route, steht der Grund im Server-Log („Policy-Verstoß“: fremde Domain, HostRegexp, Routenlimit, verbotene Middleware) oder im Agent-Log des Kunden („Container nicht übernommen“: Port nicht veröffentlicht).
6. Laufender Betrieb
Zahlung und Mahnwesen
Sultan kennt keine Rechnungen, nur das Fälligkeitsdatum einer offenen Zahlung. Das trägst du (oder später dein Rechnungssystem) ein:
docker compose exec sultan-server sultan token tenant payment --id k10042 --overdue-since 2026-11-01
docker compose exec sultan-server sultan token tenant payment --id k10042 --paid
Daraus ergibt sich automatisch:
| Tage überfällig | Stufe | Besucher sehen |
|---|---|---|
| < 8 | – | normale Seite |
| ab 8 | watermark | Hinweisseite, nach 5 s weiter zur Seite (dann 60 min Ruhe) |
| ab 25 | firemark | wie oben, 10 s |
| ab 32 | paywall | Seite offline, Hinweisseite mit deinem Angebot (--hoster-name, --hoster-url) |
Mit --paid ist sofort (nächster Refresh, ≤ 1 min) alles normal. Bei Stufe 1 und 2 meldet Checkmk bzw. Slack/ntfy.
Sofort sperren, z. B. bei Zahlungsausfall oder Missbrauch:
sultan token tenant set-status --id k10042 --status suspended_payment # Paywall-Seite
sultan token tenant set-status --id k10042 --status quarantined # Routen weg, Agent-Anfragen abgelehnt
sultan token tenant set-status --id k10042 --status active # zurück
Vertragsende
- Checkmk (
/metrics/checkmk): WARN 30, CRIT 14 Tage vorvalid_until. Benachrichtigungen gehen einmal pro Frist raus. - Ab
valid_untilwird der Mandantexpired, Besucher sehen „Hosting abgelaufen“ (402). Die Leases enden spätestens zum Vertragsende. - Verlängern: siehe Lücken.
Monitoring
curl -s http://127.0.0.1:8080/metrics/checkmk # als Checkmk-Local-Check einbinden
Liefert pro kommerziellem Mandanten Vertragsfrist und Mahnstufe, pro Knoten online/offline/Wartung und Lease, dazu Policy-Verstöße der letzten 24 h. Zusätzlich Push per SULTAN_NOTIFY_SLACK / SULTAN_NOTIFY_NTFY: Knoten > 15 min offline, wieder online, Fristen, Mahnstufen. Policy-Verstöße erscheinen nur im Server-Log und als Zähler in Checkmk.
Sicherheit
- Verdacht auf kompromittierten Kunden-Host:
sultan token node drain --id …(Routen sofort weg), danachnode deleteund neue Einladung für einen sauberen Host. - Schlüssel des Knotens tauschen, ohne Neuanmeldung:
sultan token node command --id … --cmd rotate_key. - Dein
suldata/(Master-Key!) regelmäßig verschlüsselt sichern. Wer den Master-Key hat, kann Lizenzen und Befehle für alle Kunden ausstellen.
Kunde kündigt
sultan token node drain --id <knoten> # Routen sofort weg (für jeden Knoten)
sultan token tenant delete --id k10042 # löscht Mandant, Knoten und offene Einladungen
Bekannte Lücken (Stand heute)
| Lücke | Folge | Notlösung |
|---|---|---|
tenant update fehlt |
Vertragsende, Domains, Paket, Routenlimit nicht änderbar | Keine saubere: tenant delete + neu anlegen löscht auch die Knoten (neue Einladungen nötig). Erste Priorität für den kommerziellen Betrieb. |
| pro = enterprise | kein technischer Unterschied | vertraglich regeln |
| Keine Admin-API | Zahlungsstatus nur per CLI | Skript über docker compose exec |
| Kommerzieller Betrieb nicht im Feld getestet | – | mit einem Testmandanten und kurzen Fristen (--valid-until in wenigen Tagen, payment --overdue-since in der Vergangenheit) durchspielen |
public_reason einsprachig |
Wartungstext für de und en gleich | – |