pkg für traefik ist drin

This commit is contained in:
br committed 2026-10-02 22:42:56 +02:00
1 parent ca6cdcca63
commit bed742c3d0
7 files changed
+44 -15

No files matched your search

+2 -2
View File
@@ -787,7 +787,7 @@ services:
| 2026-10-02 | **Leases und Befehle umgesetzt:** Lease mit eigenem Signaturpräfix; ungeplant getrennter Knoten zeigt die Wartungsseite bis Lease-Ende; Befehle über eine DB-Warteschlange (CLI ist eigener Prozess); alle Server-Events signiert; `rotate_key` mit Besitznachweis und abbruchsicherer Wiederaufnahme. | Kein 404 bei kurzen Ausfällen; keine Fernsteuerung ohne Server-Signatur; Schlüsselwechsel ohne Aussperren. |
| 2026-10-02 | **Schritt 3 umgesetzt:** Checkmk-Ausgabe als reine Funktion (`pkg/checkmk`); Job bei jedem Refresh (Ablauf, Benachrichtigung, Aufräumen); Benachrichtigungen Slack-kompatibel + ntfy mit Wiederholung bis zur erfolgreichen Zustellung; Community läuft nicht über `valid_until` ab. | Testbar, ohne zusätzlichen Prozess; keine verlorenen Alarme. |
| 2026-10-02 | **Mehrere Server-Adressen:** `--public-url` mehrfach; die Einladung trägt nur die erste; die Liste kommt per signiertem `config`-Befehl bei jedem Verbinden; der Agent weicht der Reihe nach aus und merkt sich die funktionierende Adresse. | Kurze Einladung; Ausfall einer Adresse (DNS, Weiterleitung) ohne Eingriff überbrückt. |
| 2026-10-02 | **Build & Auslieferung:** ein distroless-Image (nonroot) für Server und Agent, Multi-Arch amd64+arm64 per buildx mit Go-Cross-Compile (kein QEMU); Registry ist die Container-Registry von Gitea (`git.everdc.eu/chmln-app-dev/sultan`), ein Vanity-Name (`pods.chmln.de/<image>`) entsteht später per Traefik-Proxy mit `replacePathRegex` auf eine feste Gitea-Organisation (kein Redirect: Docker verwirft den `Authorization`-Header bei Host-Wechsel). Binaries + `SHA256SUMS` statisch unter `sultan/releases/<version>/`, `releases/stable` als Zeiger. Agent-Container mit `network_mode: host`. Vorerst manuell über `deploy/*.sh`, später Gitea Actions bei Tags. | Kein Go-Stack beim Nutzer; ein Image für alle Architekturen; Agent meldet sonst die Container-IP als Backend; Registry ohne zusätzlichen Dienst. |
| 2026-10-02 | **Build & Auslieferung:** ein distroless-Image (nonroot) für Server und Agent, Multi-Arch amd64+arm64 per buildx mit Go-Cross-Compile (kein QEMU); Registry: eigener **Zot**-Server `pod.chmln.de`, Image `pod.chmln.de/sultan` (ohne Owner-Ebene, daher kein Rewrite-Proxy nötig); Zugangsdaten für den Push nur in `deploy/.env` (gitignored), ohne Passwort bricht `push-image.sh` ab. (Ursprünglich geplant: Gitea-Registry hinter Rewrite-Proxy – verworfen.) Binaries + `SHA256SUMS` statisch unter `sultan/releases/<version>/`, `releases/stable` als Zeiger. Agent-Container mit `network_mode: host`. Vorerst manuell über `deploy/*.sh`, später Gitea Actions bei Tags. | Kein Go-Stack beim Nutzer; ein Image für alle Architekturen; Agent meldet sonst die Container-IP als Backend; eigene Registry mit kurzen Image-Namen ohne Proxy-Tricks. |
| 2026-10-02 | **Kleinere Punkte:** Rate-Limit `/enroll` 10/min/IP vor der Signaturprüfung (`-1` = aus); `SULTAN_<FLAG>` für alle Flags, Flags gewinnen; „wieder online“ nur nach Offline-Alarm; Checkmk-Zeiten in Server-Zeitzone. Ein Agent, dessen Enrollment mit 429 scheitert, beendet sich; der Neustart erfolgt über systemd bzw. Docker `restart`. | Schutz vor Durchprobieren; Container-/systemd-freundliche Konfiguration; vollständige Alarmkette. |
| geplant | Geordneter Zertifikatswechsel; optionale Root-CA. (Signierte Server-Events: umgesetzt.) | Zweite Sicherheitsschicht neben dem TLS-Pin; Betrieb ohne Aussperren. |
@@ -865,7 +865,7 @@ services:
**Schritt 5 – Betrieb und Installationsskript** (teilweise umgesetzt: `Dockerfile`, `deploy/build.sh`, `deploy/push-image.sh`, `deploy/publish-static.sh`, `deploy/compose/`)
* Strukturiertes Logging (`log/slog`, umgesetzt), Graceful Shutdown (umgesetzt), Versionsinfo
* ✅ Dockerfile (statisch, distroless, Multi-Arch), Build-/Deploy-Skripte, Compose-Vorlagen
* offen: systemd-Unit, `install.sh`, Signatur von `SHA256SUMS` (Ed25519, Schlüssel nur im Runner), Gitea Actions (Tests bei Push, Release bei Tag `v*`), Image-Digest in der veröffentlichten Compose-Vorlage, Vanity-Proxy `pods.chmln.de`, optional Spiegel auf ghcr.io
* offen: systemd-Unit, `install.sh`, Signatur von `SHA256SUMS` (Ed25519, Schlüssel nur im Runner), Gitea Actions (Tests bei Push, Release bei Tag `v*`), Image-Digest in der veröffentlichten Compose-Vorlage, optional Spiegel auf ghcr.io
* Installationsskript für `curl | sh`: Herkunft mit öffentlichem Zertifikat und/oder Prüfsumme bzw. Signatur. Die eigentliche Vertrauensfrage ist das Skript, nicht der Token.
**Weitere offene Bausteine (ohne feste Reihenfolge):**
+1 -1
View File
@@ -34,7 +34,7 @@ Go-Modul `sultan` (Go 1.26). `main.go` ist nur eine Hülle um `pkg/cli`; umgeset
**Mehrere Adressen (Schritt 4):** `Config.PublicURLs` (gemerkt als `settings.public_urls`, `server.LoadPublicURLs`), Versand per `config`-Befehl in `nodeOnline`; Agent: `Identity.ServerURLs`, `serverCandidates`/`nextServerURL` (Wechsel in `OnError` des Stream-Clients), `a.serverURL` nur über `currentServerURL()` lesen.
- [deploy/](deploy) – Auslieferung: `Dockerfile` im Root (distroless, nonroot 65532, Multi-Arch, kein `ENTRYPOINT`, `WORKDIR /`), `build.sh` (Binaries amd64/arm64 + `SHA256SUMS` nach `dist/<version>/`), `push-image.sh` (buildx → Gitea-Registry `git.everdc.eu/chmln-app-dev/sultan`), `publish-static.sh` (rsync nach `sultan/releases/<version>/`), `compose/{server,agent}` (Agent mit `network_mode: host`). Version überall aus `git describe`; `-dirty` wird nicht veröffentlicht. `.dockerignore` hält `suldata/`, `.ai/`, `CLAUDE.md` aus dem Build-Kontext.
- [deploy/](deploy) – Auslieferung: `Dockerfile` im Root (distroless, nonroot 65532, Multi-Arch, kein `ENTRYPOINT`, `WORKDIR /`), `build.sh` (Binaries amd64/arm64 + `SHA256SUMS` nach `dist/<version>/`), `push-image.sh` (liest `deploy/.env` mit `REGISTRY`/`REGISTRY_USER`/`REGISTRY_PASSWORD`, Vorlage `deploy/.env.example`; buildx → Zot-Registry `pod.chmln.de/sultan`; ohne Passwort Exit 1), `publish-static.sh` (rsync nach `sultan/releases/<version>/`), `compose/{server,agent}` (Agent mit `network_mode: host`). Version überall aus `git describe`; `-dirty` wird nicht veröffentlicht. `.dockerignore` hält `suldata/`, `.ai/`, `CLAUDE.md` aus dem Build-Kontext.
**CLI-Umgebung:** `pkg/cli/env.go` – `annotateEnv`/`applyEnv` machen jedes Flag als `SULTAN_<FLAG>` setzbar (nach `fs.Parse`, nur für nicht gesetzte Flags; Listen-Flags `stringList` kommagetrennt). Neue Flags bekommen das automatisch. Rate-Limit: `pkg/server/ratelimit.go` (`EnrollLimit`, `-1` = aus).
+7 -4
View File
@@ -67,15 +67,18 @@ 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 Gitea-Registry schieben
### 4. Image in die Registry schieben (Zot, `pod.chmln.de`)
```bash
docker login git.everdc.eu # einmalig: Gitea-User + Token mit Scope write:package
deploy/push-image.sh # → git.everdc.eu/chmln-app-dev/sultan:<version>
cp deploy/.env.example deploy/.env # einmalig; gitignored – nie einchecken!
$EDITOR deploy/.env # REGISTRY_PASSWORD eintragen (Pflicht)
deploy/push-image.sh # → pod.chmln.de/sultan:<version>
LATEST=1 deploy/push-image.sh # zusätzlich :latest (nur für Releases)
```
Baut per `docker buildx` gleichzeitig für `linux/amd64` und `linux/arm64` (Go kompiliert quer, kein QEMU nötig) und verweigert Versionen mit `-dirty`. Anpassbar über `REGISTRY`, `OWNER`, `PLATFORMS`.
Das Skript liest `deploy/.env` (Defaults: `REGISTRY=pod.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=pod.chmln.de/sultan:<version>` in der Compose-`.env` und `docker compose pull && docker compose up -d`.
### 5. Binaries auf den statischen Webhost legen
+10
View File
@@ -0,0 +1,10 @@
# Zugangsdaten für deploy/push-image.sh – als deploy/.env kopieren (gitignored, nie einchecken!)
# Container-Registry (Zot)
REGISTRY=pod.chmln.de
REGISTRY_USER=sultan
# Pflicht – ohne Passwort bricht push-image.sh ab
REGISTRY_PASSWORD=
# Image-Name in der Registry → ${REGISTRY}/${IMAGE_NAME}:<version>
IMAGE_NAME=sultan
+1 -1
View File
@@ -1,6 +1,6 @@
# Image: lokal gebaut (docker build -t sultan:latest .) oder aus der Registry
SULTAN_IMAGE=sultan:latest
# SULTAN_IMAGE=git.everdc.eu/chmln-app-dev/sultan:v0.1.0
# SULTAN_IMAGE=pod.chmln.de/sultan:v0.1.0
# Einladung vom Server: docker compose exec sultan-server sultan token invite --tenant=…
SULTAN_TOKEN=
+1 -1
View File
@@ -1,6 +1,6 @@
# Image: lokal gebaut (docker build -t sultan:latest .) oder aus der Registry
SULTAN_IMAGE=sultan:latest
# SULTAN_IMAGE=git.everdc.eu/chmln-app-dev/sultan:v0.1.0
# SULTAN_IMAGE=pod.chmln.de/sultan:v0.1.0
# Adresse, unter der Agents den Server erreichen – steckt danach in jeder Einladung
SULTAN_PUBLIC_URL=https://webproxy11.example.de:8443
+22 -6
View File
@@ -1,21 +1,35 @@
#!/usr/bin/env bash
# Baut das Multi-Arch-Image (amd64 + arm64) und schiebt es in die
# Container-Registry von Gitea.
# Container-Registry (Zot).
#
# docker login git.everdc.eu # einmalig, Gitea-User + Token mit write:package
# cp deploy/.env.example deploy/.env && $EDITOR deploy/.env # einmalig: REGISTRY_PASSWORD
# deploy/push-image.sh # Tag aus `git describe`
# LATEST=1 deploy/push-image.sh # zusätzlich :latest setzen (nur für Releases)
#
# Ergebnis: ${REGISTRY}/${OWNER}/sultan:<version> (und ggf. :latest)
# Ergebnis: ${REGISTRY}/${IMAGE_NAME}:<version> (und ggf. :latest)
set -euo pipefail
cd "$(dirname "$0")/.."
REGISTRY="${REGISTRY:-git.everdc.eu}"
OWNER="${OWNER:-chmln-app-dev}"
IMAGE="${REGISTRY}/${OWNER}/sultan"
ENV_FILE="${ENV_FILE:-deploy/.env}"
if [ -f "$ENV_FILE" ]; then
set -a
# shellcheck disable=SC1090
. "$ENV_FILE"
set +a
fi
REGISTRY="${REGISTRY:-pod.chmln.de}"
REGISTRY_USER="${REGISTRY_USER:-sultan}"
IMAGE_NAME="${IMAGE_NAME:-sultan}"
IMAGE="${REGISTRY}/${IMAGE_NAME}"
VERSION="${VERSION:-$(git describe --tags --always --dirty)}"
PLATFORMS="${PLATFORMS:-linux/amd64,linux/arm64}"
if [ -z "${REGISTRY_PASSWORD:-}" ]; then
echo "REGISTRY_PASSWORD fehlt – in ${ENV_FILE} setzen (Vorlage: deploy/.env.example)." >&2
exit 1
fi
case "$VERSION" in
*-dirty)
echo "Arbeitsverzeichnis hat uncommittete Änderungen (${VERSION}) – erst committen." >&2
@@ -23,6 +37,8 @@ case "$VERSION" in
;;
esac
printf '%s' "$REGISTRY_PASSWORD" | docker login "$REGISTRY" -u "$REGISTRY_USER" --password-stdin
tags=(-t "${IMAGE}:${VERSION}")
if [ "${LATEST:-0}" = 1 ]; then
tags+=(-t "${IMAGE}:latest")