Einen Runner sicher einrichten
Diese Anleitung fügt einer SupaCloud-Installation einen Runner hinzu — eine separate Maschine, die Agent-Aufgaben abholt und ausführt. Der Runner verbindet sich rein ausgehend über HTTPS und arbeitet daher hinter NAT ohne eingehende Ports. Für die Konzepte (Pull-Transport, laufspezifisches Secret-Modell, die zwei Bedeutungen von „Runner-Flotte“) siehe die Erklärung Die Runner-Flotte.
1. Hub-Modus aktivieren (Server)
Abschnitt betitelt „1. Hub-Modus aktivieren (Server)“-
Setze eine Umgebungsvariable auf dem Server und starte ihn neu:
SUPACLOUD_HUB_MODE=trueDer Standard ist
false. Solange aus, läuft jede Aufgabe lokal — egal wie viele Runner registriert sind. Genau das macht es sicher, den Hub-Modus im Notfall auszuschalten, ohne etwas zu deregistrieren. -
Bestätige, dass er an ist:
Terminal window curl https://supacloud.example.com/api/runners/config \-H "Authorization: Bearer <admin-session-oder-API-token>"# → { "hub_mode_enabled": true }
2. Worker-Node registrieren (Server)
Abschnitt betitelt „2. Worker-Node registrieren (Server)“-
Registriere den Runner als System-Admin und sichere das Token:
Terminal window curl -X POST https://supacloud.example.com/api/runners \-H "Authorization: Bearer <admin-session-oder-API-token>" \-H "Content-Type: application/json" \-d '{"name": "gpu-worker-01","capabilities": { "images": ["unified"], "max_parallel": 2 }}' -
Die Antwort enthält das Klartext-Bearer-Token (
scrn_…) genau einmal — der Server speichert nur dessen SHA-256-Hash. Kopiere es jetzt; im nächsten Schritt übergibst du es dem Worker. Geht es verloren, rotiere das Token, statt neu zu registrieren.
Wasm-Connector- und Skript-Ausführung bewerben
Abschnitt betitelt „Wasm-Connector- und Skript-Ausführung bewerben“Ein Runner kann sich auch dafür entscheiden, Wasm auf seinem Node auszuführen — sowohl Marketplace-Connector-Nodes als auch freie Skripte (JS / TS / Python). Beides läuft in derselben WASI-0.2-Sandbox (pro Lauf Speicher- und Wall-Clock-Grenzen, deny-all-SSRF-geprüfter Egress) hinter der eigenen OS-Grenze des Runners. Zwei Capability-Schlüssel steuern das:
connectors: true— der Runner entscheidet sich, Connector-Node-Wasm auszuführen. Der Hub schickt einem Node ohne dieses Flag nie einen Connector-Lauf.wasm.script_languages— die Skriptsprachen, deren Interpreter das Image des Runners tatsächlich bereitgestellt hat. Der Hub schickt einen Skript-Lauf nur an einen Runner, der sowohlconnectors: trueals auch die Sprache des Skripts hier bewirbt (ein Skript führt Wasm auf dem Node aus, also muss der Node sich für die Wasm-Ausführung entschieden haben und den Interpreter besitzen).
{ "name": "wasm-worker-01", "capabilities": { "images": ["unified"], "connectors": true, "wasm": { "script_languages": ["js", "ts", "py"] } }}Liste nur Sprachen auf, deren Interpreter der Runner unter
SUPACLOUD_SCRIPT_RUNTIME_DIR tatsächlich bereitgestellt hat (reproduzierbar
gebaut durch scripts/build-script-runtimes.sh). Der Matcher ist
fail-closed: ein fehlender oder fehlerhafter wasm-Schlüssel bedeutet, dass
der Runner keine Skriptsprache bewirbt und nie ein Skript erhält — eine
bestehende Flotte bleibt also völlig unberührt, und das Hinzufügen des Schlüssels
ist ein sicheres, monotones Opt-in.
Wird ein Skript an die Flotte verteilt, schickt der Hub nur Metadaten — die Sprache plus Quelltext und Eingaben als Daten — und einen SHA-256-Integritätsanker seines eigenen Interpreters. Er schickt nie den mehrere MB großen Interpreter. Der Runner löst seinen eigenen lokalen, vertrauenswürdigen Interpreter für diese Sprache auf und prüft den SHA erneut, bevor er ausführt; eine Abweichung (Versionsdrift oder Manipulation) schlägt fail-closed fehl. Eine Anfrage, die versucht, Interpreter-Bytes einzuschmuggeln, wird als Protokollverletzung abgelehnt. Der Interpreter ist stets ein lokal vertrauenswürdiges Runner-Asset — ein per Payload mitgeschickter wird nie ausgeführt.
Das wird instanzweit über SUPACLOUD_CONNECTOR_EXECUTOR_MODE gesteuert
(in_process — der Standard — / pooled / runner_fleet); setze es auf
runner_fleet, um Connector- und Skript-Läufe an die Flotte zu verteilen.
Mit dem Standardmodus in_process laufen Skripte auf dem Hub genau wie zuvor —
für bestehende Deployments ist dies ein No-op ohne Konfiguration.
Einen Drittanbieter-Runner onboarden (Enrollment)
Abschnitt betitelt „Einen Drittanbieter-Runner onboarden (Enrollment)“Abschnitt 2 erzeugt ein langlebiges scrn_…-Bearer für einen Runner, den du
betreibst. Um einen Runner auf einem Host hochzufahren, dem du weniger vertraust —
die Maschine einer Kundin, Edge-Compute, die GPU-Box einer Partnerin — nutze
stattdessen den Enrollment-Ablauf. Du übergibst dem Betreiber ein
einmaliges, kurzlebiges Enrollment-Token; sein Runner tauscht es beim Boot
gegen ein scope-begrenztes, kurzlebiges scrnj_…-JWT ein und erneuert es
automatisch. Der Betreiber hält nie ein langlebiges Hub-Credential, und der Runner
kann ausschließlich die Workspaces bedienen, auf die du ihn scopt hast. Zum
Trust-Modell dahinter siehe Runner-Flotten-Sicherheit.
-
Enrollment-Token erzeugen (Admin). Wähle Trust-Klasse, Ausführungs-Tier, Isolation und die Workspaces, die der Runner bedienen darf:
Terminal window curl -X POST https://supacloud.example.com/api/runners/enroll \-H "Authorization: Bearer <admin-session-oder-API-token>" \-H "Content-Type: application/json" \-d '{"class": "edge","tier": "docker","isolation": "container","allowed_workspace_ids": ["<workspace-uuid>"],"allowed_labels": []}'classisttrustedoderedge;tieristwasm,dockeroderboth;isolationistcontainerodermicrovm. Die Antwort enthält das Klartext-Enrollment-Token genau einmal (der Server speichert nur dessen Hash) und eine kurze Ablaufzeit. Kopiere es jetzt und übergib es dem Betreiber über einen sicheren Kanal. -
Worker mit dem Installer onboarden (Betreiber). Der Betreiber führt den gehosteten Ein-Zeilen-Installer aus. Dieser lädt das signierte Runner-Artefakt, verifiziert Prüfsumme und Signatur, tauscht das einmalige Enrollment-Token gegen ein scope-begrenztes
scrnj_…-JWT und bootet den Runner damit — rein ausgehend, keine eingehenden Ports:Terminal window curl -fsSL https://supacloud.example.com/install-runner.sh | \SUPACLOUD_HUB_URL=https://supacloud.example.com \SUPACLOUD_RUNNER_ENROLLMENT_TOKEN=<einmal-token> \SUPACLOUD_RUNNER_NAME=customer-edge-01 \bashDer Installer (nicht das nackte Binary) führt den Eintausch durch: das eigenständige
supacloud --runner-Binary liest ausschließlichSUPACLOUD_RUNNER_TOKEN(dasscrnj_…-JWT), nie das Enrollment-Token. Zum Onboarding ohne Installer tauschst du das Token selbst — der gRPC-RPCRunnerService.ExchangeToken({enrollment_token, name}→ das JWT, ADR 0050) —, setzt dannSUPACLOUD_RUNNER_TOKEN=<das scrnj_-JWT>und startest das Binary oder Image genau wie in Abschnitt 3. -
Der Runner erneuert sein JWT automatisch. Der Eintausch verbrennt das Enrollment-Token (es lässt sich nicht erneut verwenden) und liefert ein scope-begrenztes
scrnj_…-JWT, das Trust-Klasse, Tier, Isolation und die erlaubten Workspaces trägt. Das JWT lebt höchstens eine Stunde; der Runner-Daemon holt ein frisches, bevor das alte abläuft — standardmäßig bei etwa der halben Token-TTL, abgeleitet austoken_expires_atdes Grants / dem JWT-exp—, und jede Erneuerung ruft den grant-prüfenden gRPC-RPCRunnerService.RefreshTokendes Hubs auf, sodass der Entzug eines Workspaces innerhalb einer Token-Lebensdauer wirkt. Um den Takt explizit festzulegen, setzeSUPACLOUD_RUNNER_TOKEN_REFRESH_SECSauf die Anzahl Sekunden-vor-Ablauf, bei der neu eingetauscht wird (0, der Standard, bedeutet automatisch ableiten).
3. Runner online bringen (Worker-Node)
Abschnitt betitelt „3. Runner online bringen (Worker-Node)“Der Runner ist dasselbe SupaCloud-Binary im --runner-Modus. Wähle die
Plattform, auf der du installierst. In jedem Fall ist die Konfiguration dieselbe
Menge an Umgebungsvariablen; nur der Start unterscheidet sich.
Ein-Zeilen-Installer (signiertes Binary)
Abschnitt betitelt „Ein-Zeilen-Installer (signiertes Binary)“Sobald dein Release-Kanal die signierten Binaries hostet, übernehmen die
Installer das gesamte Onboarding auf einer Worker-Node — Plattform erkennen,
das gepinnte Binary herunterladen, Prüfsumme und Signatur verifizieren, das
einmalige Enrollment-Token eintauschen, installieren und supacloud --runner
über TLS ohne eingehende Ports starten. Das einzige Secret, das du übergibst,
ist das einmalige Enrollment-Token aus dem Mint-Schritt; der Skript-Body enthält
keines.
Linux / macOS (genau die Ein-Zeilen-Anweisung, die die SupaCloud-UI dir gibt):
curl -fsSL "$SUPACLOUD_URL/install-runner.sh" \ | SUPACLOUD_ENROLLMENT_TOKEN=<einmal-token> bashWindows (PowerShell):
$env:SUPACLOUD_URL = "https://supacloud.example.com"$env:SUPACLOUD_ENROLLMENT_TOKEN = "<einmal-token>"irm "$env:SUPACLOUD_URL/install-runner.ps1" | iexNützliche Overrides (Umgebungsvariablen, beide Installer): SUPACLOUD_RUNNER_NAME
(Standard: Hostname), SUPACLOUD_RUNNER_VERSION / SUPACLOUD_DOWNLOAD_BASE (ein
bestimmtes Release oder einen Artifact-Host pinnen) und
SUPACLOUD_RUNNER_DRY_RUN=1, um den aufgelösten Download-, Verify- und
Start-Plan auszugeben, ohne das Netzwerk anzufassen.
Gemeinsame Konfiguration (alle Plattformen)
Abschnitt betitelt „Gemeinsame Konfiguration (alle Plattformen)“SUPACLOUD_HUB_URL=https://supacloud.example.comSUPACLOUD_RUNNER_TOKEN=scrn_xxxxxxxxxxxxxxxxxxxxxxxxSUPACLOUD_RUNNER_NAME=gpu-worker-01# Optionale Takt-Overrides (sinnvolle Defaults gezeigt):# SUPACLOUD_RUNNER_HEARTBEAT_SECS=30# SUPACLOUD_RUNNER_POLL_SECS=3# Docker-Netzwerk für Agent-Container (muss auf dem Worker existieren):# AGENT_NETWORK=supacloud-agentsDie Hub-URL muss https:// sein. Ein Klartext-http://-Hub wird beim Start
abgelehnt, außer du setzt explizit
SUPACLOUD_RUNNER_ALLOW_INSECURE_TRANSPORT=true — nur in einem vertrauenswürdigen
privaten Netz je akzeptabel.
Linux / macOS
Abschnitt betitelt „Linux / macOS“-
Lege die obigen Variablen in eine
.envneben das Binary (oder exportiere sie), dann:Terminal window supacloud --runner -
Oder mit dem Docker-Image (Docker-Socket einhängen, damit der Runner Agent-Container auf seinem eigenen Host starten kann):
Terminal window docker run -d --name supacloud-runner \-e SUPACLOUD_HUB_URL=https://supacloud.example.com \-e SUPACLOUD_RUNNER_TOKEN=scrn_xxxxxxxxxxxxxxxxxxxxxxxx \-e SUPACLOUD_RUNNER_NAME=gpu-worker-01 \-v /var/run/docker.sock:/var/run/docker.sock \<dein-supacloud-image> --runner
Windows
Abschnitt betitelt „Windows“-
Der Runner braucht einen Docker-Host, um Agent-Container zu starten — installiere Docker Desktop (WSL-2-Backend) auf dem Worker.
-
Setze die Variablen in PowerShell für die Sitzung und starte das Binary:
Terminal window $env:SUPACLOUD_HUB_URL = "https://supacloud.example.com"$env:SUPACLOUD_RUNNER_TOKEN = "scrn_xxxxxxxxxxxxxxxxxxxxxxxx"$env:SUPACLOUD_RUNNER_NAME = "win-worker-01".\supacloud.exe --runnerFür einen dauerhaft laufenden Worker führe denselben Befehl als Dienst aus (z. B. mit NSSM) oder nutze den Docker-Image-Befehl aus dem Linux/macOS-Tab innerhalb von WSL 2.
microVM-Ausführungs-Backend (stärkste Isolation)
Abschnitt betitelt „microVM-Ausführungs-Backend (stärkste Isolation)“Das Standard-Backend docker führt jede Aufgabe in einem Container auf dem lokalen
Docker-Host des Runners aus. Für einen nicht vertrauenswürdigen oder Edge-Runner
ist das microVM-Backend die stärkste Isolationsstufe: jede beanspruchte Aufgabe
läuft in einem eigenen kurzlebigen hardware-virtualisierten Gast (eine
Firecracker/Kata-artige microVM), sodass ein kompromittierter Agent-Prozess hinter
einer VM-Grenze eingeschlossen ist, nicht nur in einem Kernel-Namespace. Wie die
Stufen sich vergleichen, siehe Runner-Flotte Defense-in-Depth →
Isolationsstufen.
-
Baue (oder beziehe) ein Runner-Binary, das mit dem
microvm-backend-Feature kompiliert wurde. -
Stelle auf dem Worker einen microVM-Launcher bereit (z. B. einen Firecracker/Kata-Wrapper), wähle dann das Backend und richte den Runner darauf aus:
SUPACLOUD_RUNNER_EXECUTION_BACKEND=microvmSUPACLOUD_RUNNER_MICROVM_CMD=/usr/local/bin/launch-microvm -
Onboarde (oder onboarde neu) den Runner mit
isolation: microvm, damit der fail-closed Dispatch-Filter des Hubs microVM-pflichtige Aufgaben an ihn und nur an ihn routet.
Den Runner-Transport mit mTLS absichern
Abschnitt betitelt „Den Runner-Transport mit mTLS absichern“Standardmäßig vertraut der Runner dem Hub über One-Way-TLS (der Hub präsentiert ein Server-Zertifikat; der Runner verifiziert es gegen den System-Trust-Store). Um einen gegenseitigen TLS-Handshake zu verlangen — sodass der Hub auch jeden Runner per Client-Zertifikat authentifiziert, ein starker zweiter Faktor zusätzlich zum Bearer-Token — konfiguriere beide Seiten. mTLS ist optional; ist nichts davon gesetzt, ist der Transport genau wie heute.
-
Auf dem Hub (Server). TLS direkt ausliefern und Client-Zertifikate verlangen:
SUPACLOUD_TLS_CERT_PATH=/etc/supacloud/tls/hub.crtSUPACLOUD_TLS_KEY_PATH=/etc/supacloud/tls/hub.keySUPACLOUD_TLS_CLIENT_CA_PATH=/etc/supacloud/tls/runner-ca.crtSUPACLOUD_TLS_CERT_PATH+SUPACLOUD_TLS_KEY_PATHschalten TLS ein;SUPACLOUD_TLS_CLIENT_CA_PATHverlangt und verifiziert zusätzlich ein Client-Zertifikat gegen diese CA. Eine Verbindung ohne vertrauenswürdiges Client-Zertifikat wird beim Handshake abgewiesen. -
Auf jedem Runner. Eine Client-Identität präsentieren und (optional) die Hub-CA pinnen:
SUPACLOUD_RUNNER_TLS_CLIENT_CERT_PATH=/etc/supacloud/tls/runner.crtSUPACLOUD_RUNNER_TLS_CLIENT_KEY_PATH=/etc/supacloud/tls/runner.keySUPACLOUD_RUNNER_TLS_CA_PATH=/etc/supacloud/tls/hub-ca.crt # optional: Hub-CA pinnen
4. Verifizieren
Abschnitt betitelt „4. Verifizieren“-
Beim Start macht der Runner einen Heartbeat-Aufruf. Wird das Token abgelehnt, beendet er sich sofort mit klarer Fehlermeldung; ist der Hub kurz nicht erreichbar, startet er trotzdem und versucht es weiter.
-
Die Zeile des Runners wechselt beim ersten erfolgreichen Heartbeat von
pending → online. Bestätige es vom Server aus:Terminal window curl https://supacloud.example.com/api/runners \-H "Authorization: Bearer <admin-session-oder-API-token>" -
Starte eine Aufgabe, deren Image der Runner bewirbt. Bei aktivem Hub-Modus und einem passenden Online-Runner verteilt der Server sie an den Runner, und der Live-Ereignisstrom zeigt den Fortschritt genau wie bei einem lokalen Lauf.