# 👑 sultan **Verteiltes Ingress-Routing mit ZeroTrust-Service-Discovery – geschrieben in Go.** Schluss mit Klick-Konfiguration im Proxy-GUI und toten Routen đŸȘŠ: Bei Sultan sagen deine Dienste selbst, wie sie erreichbar sein wollen. Ob Docker-Container mit Traefik-Labels 🐳 oder klassischer Bare-Metal-/LAMP-Server mit Drop-in-Config đŸ–„ïž – ein kleiner Agent meldet das Routing sicher an den zentralen Sultan-Server, und Traefik holt sich daraus live seine Konfiguration. Ohne Neustart, ohne Portweiterleitung. ## ✹ Was Sultan kann - đŸ·ïž **Routing am Dienst deklarieren** – native `traefik.*`-Labels in Docker oder Dateien unter `/etc/sultan.d/` - 📡 **Firewall-freundlich** – der Agent baut nur *ausgehende* Verbindungen auf; funktioniert hinter NAT, CGNAT und DS-Lite - ⚡ **Echtzeit-Updates** – Container starten oder stoppen, Traefik weiß es sofort - 🔐 **Sicher von Haus aus** – TLS mit Fingerprint-Pinning (wie bei SSH), Ed25519-SchlĂŒssel, die den Host nie verlassen - đŸ›Ąïž **MandantenfĂ€hig** – jeder Mandant darf nur seine eigenen Domains beanspruchen - 🌐 **ZeroTrust-Overlay** – optional ĂŒber ein WireGuard-Mesh (z. B. NetBird), auch fĂŒr Hosts ohne öffentliche IP - 📊 **Monitoring** – Checkmk-Integration fĂŒr Knoten- und Lizenzstatus ## 🧭 So funktioniert's ```text Internet ──▶ Traefik ──(pollt)──▶ sultan server ◀──(TLS-Stream)── sultan agent (Docker / Bare-Metal) ``` Ein einziges Binary, drei Rollen: | Befehl | Aufgabe | |-----------------|----------------------------------------------------------------| | `sultan server` | Registry, Policy-Engine und Konfigurationsquelle fĂŒr Traefik | | `sultan agent` | Beobachtet Docker bzw. `/etc/sultan.d/` und meldet an den Server | | `sultan token` | SchlĂŒssel, Einladungs-Tokens und Lizenzen verwalten | Die ausfĂŒhrliche Architektur steht in [.ai/sultan-system-architecture.md](.ai/sultan-system-architecture.md). ## 🚀 Installation > 🚧 **Hinweis:** Sultan befindet sich noch am Anfang der Entwicklung. Die folgenden Schritte zeigen, wie die Installation aussehen *wird* – Befehle und Flags können sich noch Ă€ndern. ### Voraussetzungen - Zum Bauen: Go (Version laut `go.mod`) bzw. Docker mit buildx - FĂŒr den Ingress-Knoten: Traefik v3 - FĂŒr Docker-Hosts: Zugriff auf `/var/run/docker.sock` ### 1. Quellen holen ```bash git clone ssh://git@git.everdc.eu:10022/chmln-app-dev/sultan.git cd sultan ``` ### 2. Binary bauen (amd64 + arm64) ```bash go build -o sultan . && ./sultan version # schnell, nur fĂŒr die eigene Architektur deploy/build.sh # Release-Binaries fĂŒr linux/amd64 + linux/arm64 # → dist//sultan_linux_amd64, sultan_linux_arm64, SHA256SUMS sudo install -m 0755 dist//sultan_linux_amd64 /usr/local/bin/sultan ``` Die Version kommt aus `git describe` (Tag, sonst Commit-Hash; `-dirty` bei uncommitteten Änderungen) und steht in `sultan version`. ### 3. Docker-Image bauen (ein Image fĂŒr Server *und* Agent, amd64 + arm64) ```bash docker build -t sultan:latest . # lokal, eigene Architektur docker run --rm sultan:latest sultan version ``` Das Image ist distroless (nur das statische Binary, ~17 MB) und lĂ€uft als nonroot-User `65532`. Die Rolle wĂ€hlt der Befehl: `sultan server 
` bzw. `sultan agent 
`. ### 4. Image in die Registry schieben (Zot, `zot.chmln.de`) ```bash cp deploy/.env.example deploy/.env # einmalig; gitignored – nie einchecken! $EDITOR deploy/.env # REGISTRY_PASSWORD eintragen (Pflicht) deploy/push-image.sh # → zot.chmln.de/sultan: LATEST=1 deploy/push-image.sh # zusĂ€tzlich :latest (nur fĂŒr Releases) ``` Das Skript liest `deploy/.env` (Defaults: `REGISTRY=zot.chmln.de`, `REGISTRY_USER=sultan`, `IMAGE_NAME=sultan`; ohne `REGISTRY_PASSWORD` Abbruch), meldet sich per `docker login --password-stdin` an und baut per `docker buildx` gleichzeitig fĂŒr `linux/amd64` und `linux/arm64` (Go kompiliert quer, kein QEMU nötig). Versionen mit `-dirty` werden verweigert. Weitere Stellschrauben: `PLATFORMS`, `ENV_FILE`. Danach auf den Hosts: `SULTAN_IMAGE=zot.chmln.de/sultan:` in der Compose-`.env` und `docker compose pull && docker compose up -d`. ### 5. Binaries auf den statischen Webhost legen ```bash TARGET=deploy@webdocker11:/srv/inst/htdocs deploy/publish-static.sh STABLE=1 TARGET=
 deploy/publish-static.sh # zusĂ€tzlich sultan/releases/stable setzen ``` Ablage per `rsync` unter `sultan/releases//` (Binaries + `SHA256SUMS`); Ă€ltere Versionen bleiben herunterladbar. Grundlage fĂŒr das spĂ€tere `curl 
 | bash`. ### 6. Mit Docker Compose betreiben Vorlagen: [deploy/compose/server](deploy/compose/server) (Ingress-Knoten neben Traefik) und [deploy/compose/agent](deploy/compose/agent) (Docker-Host). ```bash cp -r deploy/compose/server ~/sultan-server && cd ~/sultan-server cp .env.example .env && $EDITOR .env # SULTAN_IMAGE, SULTAN_PUBLIC_URL sudo install -d -m 0700 -o 65532 -g 65532 suldata # Datenverzeichnis fĂŒr den nonroot-User docker compose up -d docker compose exec sultan-server sultan token tenant add --id=
 --domains=
 docker compose exec sultan-server sultan token invite --tenant=
 ``` Der Agent lĂ€uft mit `network_mode: host`. Nur so meldet er die Host-IP als Backend-Adresse (statt der Container-IP) und den Hostnamen als Knoten-ID. FĂŒr den Docker-Socket braucht er `DOCKER_GID` in der `.env` (`getent group docker | cut -d: -f3`). ### Server starten (Ingress-Knoten) ```bash sultan server --public-url=https://ingress.example.com:8443 # Daten landen in ./suldata sultan server --help # alle Optionen ``` Alle Optionen gehen auch als Umgebungsvariable, z. B. `SULTAN_PUBLIC_URL=
 sultan server` (praktisch fĂŒr Docker und systemd). Der Server lauscht auf `:8443` fĂŒr Agents und auf `127.0.0.1:8080` fĂŒr Traefik (beides per `--agent-addr` / `--provider-addr` Ă€nderbar). Im Verzeichnis `./suldata` liegen Datenbank und SchlĂŒssel – bitte sichern 🔑 und nie einchecken. Traefik bindest du ĂŒber den HTTP-Provider an: ```bash --providers.http.endpoint=http://127.0.0.1:8080/v1/traefik-config --providers.http.pollInterval=3s ``` ### Agent verbinden (Backend-Host) 1. Auf dem Server einen Mandanten anlegen und eine Einladung erzeugen đŸŽŸïž ```bash sultan token tenant add --id=homelab --name="Mein Homelab" --email=ich@example.com --domains="example.com,*.example.com" sultan token invite --tenant=homelab # gibt die Einladung aus, 24 h gĂŒltig sultan token --help # alle Verwaltungsbefehle ``` 2. Auf dem Backend-Host den Agent starten: ```bash SULTAN_TOKEN= sultan agent # Adresse steckt in der Einladung (sultan server --public-url=
) sultan agent --server=https://ingress.example.com:8443 --token= # sonst Adresse angeben # danach genĂŒgt: sultan agent ``` Der Agent liest die Container mit `traefik.enable=true` aus Docker und meldet sie an den Server. Wichtig: Der Ingress erreicht nur **veröffentlichte** Ports (`ports: "8081:80"`), nicht solche, die nur auf `127.0.0.1` veröffentlicht sind. Ohne Docker: `--docker-socket=none`. Über welche Adresse der Ingress den Host erreicht, ermittelt der Agent automatisch; fĂŒr NetBird z. B. `--backend-interface=wt0`. **Ohne Docker (Bare-Metal, LAMP 
)** đŸ–„ïž beschreibst du deine Dienste in `/etc/sultan.d/*.yaml`: ```yaml services: - name: kunde-a url: http://127.0.0.1:8080 hosts: [kunde-a.de] https: true redirect_http_to_https: true redirect_www: to_non_www healthcheck: { expect_title: "KundeA - Willkommen" } # bei Ausfall: Wartungsseite statt Fehler ``` Beim ersten Verbinden merkt sich der Agent den Fingerprint des Servers – ab dann lĂ€uft alles automatisch. 🎉 ### Wartung 🔧 ```bash sultan agent maintenance on --for 2h --public-reason "Wir spielen ein Sicherheitsupdate ein." # auf dem Knoten sultan token node maintenance --id=pi --for 2h # oder auf dem Server sultan token node resume --id=pi # beenden ``` Besucher sehen wĂ€hrenddessen die Wartungsseite mit Grund und voraussichtlichem Ende – auch, wenn der Knoten gerade neu startet. ### Monitoring & Benachrichtigungen 📊 ```bash sultan server --notify-slack=https://hooks.slack.com/
 --notify-ntfy=https://ntfy.sh/mein-sultan curl -s http://127.0.0.1:8080/metrics/checkmk # Checkmk Local Checks: VertrĂ€ge, Zahlungen, Knoten ``` Sultan meldet ablaufende VertrĂ€ge, Mahnstufen, ausgefallene Knoten und Policy-VerstĂ¶ĂŸe – jedes Ereignis genau einmal. ### Hinweis- und Wartungsseiten 🚧 FĂ€llt ein Dienst aus oder lĂ€uft ein Abo ab, zeigt Sultan statt eines Fehlers eine freundliche Seite (Deutsch und Englisch). Eigene Gestaltung: ```bash sultan dump-landing # Vorlagen nach ./suldata/landing – anpassen, wirkt sofort sultan server --hoster-name="Mein Hosting" --hoster-url=https://hosting.example ``` Fertige Docker-Compose-Vorlagen fĂŒr Ingress und Backend-Host liegen unter [deploy/compose](deploy/compose).