Zum Inhalt springen

Eigener Server und Sicherheit

Runner und selbst hosten

Installier setup-runner auf deinem eigenen Docker-Host, verbinde ihn mit einem Workspace und halte ihn abgesichert und aktuell.

Auf dieser Seite
  1. Was du brauchst
  2. Heimserver mit einem Code verbinden
  3. Runner installieren und registrieren
  4. 1. Runner im Dashboard anlegen
  5. 2. Binärdatei auf den Host bringen
  6. 3. Starten
  7. 4. Nach einem Neustart weiterlaufen lassen
  8. So verbindet er sich
  9. Flags
  10. Registry-Mirror
  11. Subnetz-Pool
  12. Den Host absichern
  13. Aktualisieren
  14. Runner entfernen
  15. Fehlersuche

Ein Runner ist der Rechner, auf dem deine Apps laufen. Setup entscheidet, was laufen soll; der Runner lädt die Images, startet die Container und behält sie im Blick. Solange du keinen eigenen Rechner verbindest, laufen Apps in der Setup Cloud, einem gemeinsamen Runner, den Setup betreibt.

Dein eigener Runner kann ein NAS, ein Heimserver oder ein VPS sein. Darauf läuft nur ein Programm, setup-runner. Es spricht mit Docker auf diesem Rechner und baut die Verbindung zu Setup selbst auf. Du öffnest keine Ports, und deine Apps samt Daten bleiben auf deiner Hardware.

Was du brauchst

  • Einen Linux-Rechner mit Docker Engine 25 oder neuer, dem Compose-v2-Plugin und BuildKit (docker buildx).
  • Ausgehendes HTTPS von diesem Rechner zu deinem Setup-Server.
  • Die Admin-Rolle im Workspace. Nur Admins können Runner hinzufügen oder ändern.
  • Empfohlen: gVisor für stärkere Isolation, siehe Den Host absichern.

Heimserver mit einem Code verbinden

Verbinde nur ein Gerät, das Tag und Nacht läuft. Apps darauf gibt es nur, solange es läuft: Ein Teamkalender auf einem NAS, das nachts schläft, ist bis zum Morgen für alle weg. Für Apps, die andere nutzen, ist ein Server in deinem eigenen Cloud Konto meist der bessere Ort.

  1. Öffne Runner und wähl Heimserver verbinden. Setup zeigt einen Kopplungscode wie KX7P-4MQ2, die Setup Adresse und einen QR Code. Der Code gilt einmal, 15 Minuten lang.
  2. Installiere auf dem Heimserver die App Setup Runner und gib in ihren Einstellungen die Setup Adresse und den Kopplungscode ein. Es gibt Pakete für Unraid, TrueNAS, CasaOS, Umbrel, Runtipi, den Synology Container Manager, eine einfache Docker Compose Datei und ein Skript für den ersten Start eines Raspberry Pi.
  3. Der Runner tauscht den Code gegen ein eigenes Token, legt es in seinem Datenordner ab und verbindet sich. Der Dialog zeigt Verbunden mit dem Namen des Geräts. Gib ihm einen Namen und sag Setup, ob es Tag und Nacht läuft; Setup nutzt die Antwort, wenn es vorschlägt, wo eine App laufen soll.

Ohne Kommandozeile passiert alles im Installationsformular des Stores. Mit einer Shell geht dasselbe mit setup-runner pair <code> --server <adresse> und danach setup-runner run.

Was die App darf: Sie steuert Docker auf diesem Gerät über den Docker Socket, und das ist dasselbe wie volle Kontrolle über das Gerät. Sie startet deine Apps als eigene Container neben sich, gibt ihre Ports aus einem Bereich frei, den du wählst (standardmäßig 20000 bis 20999), und hält für Setup keine Ports offen, weil sie nur nach außen verbindet.

Zum Entfernen löschst du in Setup zuerst die Apps darauf und dann den Runner, deinstallierst danach die App im Store und löschst ihren Datenordner.

Die Pakete sind noch in keinem Store und das Image ist nicht veröffentlicht. Heute funktioniert das also mit einem Runner Image, das du selbst baust (make image in apps/runner).

Runner installieren und registrieren

1. Runner im Dashboard anlegen

Öffne Runner (/dashboard/runners oder /dashboard/<workspace>/runners für eine Organisation), wähl Runner hinzufügen, gib ihm einen Namen wie home-nas und wähl Runner erstellen. Der Dialog zeigt das Runner-Token. Es beginnt mit srt_ und erscheint nur einmal, weil Setup davon nur einen Hash speichert.

2. Binärdatei auf den Host bringen

setup-runner ist eine einzelne Go-Binärdatei ohne externe Abhängigkeiten. Bau sie aus apps/runner im Setup-Quellcode; für einen anderen Rechner setzt du GOOS und GOARCH (zum Beispiel GOOS=linux GOARCH=arm64).

Terminal
cd apps/runner
go build -o bin/setup-runner ./cmd/setup-runner
sudo install -m 0755 bin/setup-runner /usr/local/bin/setup-runner
setup-runner doctor --server https://setup.example

doctor prüft Docker, die Isolation, den freien Speicherplatz, das Datenverzeichnis, den Portbereich und ob dein Server antwortet. Beheb jede Zeile mit FAIL. Der Tab Docker im Dialog zeigt ein Image, das noch nicht veröffentlicht ist; nimm die Binärdatei.

3. Starten

Der Tab Binärdatei enthält diesen Befehl mit deiner Adresse und deinem Token:

Terminal
setup-runner run --server https://setup.example --token srt_…

Auf einem NAS oder Heimserver gibst du zusätzlich die Adresse an, unter der andere den Rechner erreichen, damit die App-Links funktionieren:

Terminal
setup-runner run --server https://setup.example --token srt_… \
  --public-host 192.168.1.20 --bind-ip 192.168.1.20

Der Dialog wechselt von „Wartet, bis sich der Runner verbindet …“ zu „home-nas ist verbunden.“ Wähl Fertig.

4. Nach einem Neustart weiterlaufen lassen

Speicher das als /etc/systemd/system/setup-runner.service, mit deiner Adresse und deinem Token, und aktivier den Dienst:

ini
[Unit]
Description=Setup runner
Requires=docker.service
After=docker.service network-online.target

[Service]
ExecStart=/usr/local/bin/setup-runner run --server https://setup.example --token srt_…
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
Terminal
sudo systemctl daemon-reload && sudo systemctl enable --now setup-runner

Der Dienst läuft als root mit dem Datenverzeichnis /var/lib/setup-runner, und andere Benutzer auf dem Rechner können das Token in der Unit-Datei lesen. Eine sicherere Variante steht unter Den Host absichern.

So verbindet er sich

Der Runner baut nur ausgehende HTTPS-Verbindungen auf und funktioniert deshalb hinter NAT und Firewalls. Er holt Jobs per Long-Polling (bis zu 30 Sekunden pro Anfrage) und schickt alle 15 Sekunden einen Heartbeat; nach 90 Sekunden ohne Kontakt zeigt das Dashboard ihn als Offline. Setup speichert vom Token nur einen SHA-256-Hash. Ein Runner übernimmt nur Apps aus seinem eigenen Workspace. Ist er gestoppt, laufen die Apps weiter, aber Setup sieht und ändert sie erst wieder, wenn er sich neu verbindet.

Flags

Jedes Flag liest auch eine Umgebungsvariable. Bei Schaltern bedeutet jeder nicht leere Wert „an“.

FlagVariableStandardWirkung
--serverSETUP_SERVERPflichtDeine Setup-Adresse
--tokenSETUP_RUNNER_TOKENPflichtDas Runner-Token
--public-hostSETUP_PUBLIC_HOSTlocalhostHost oder IP in App-Links
--bind-ipSETUP_BIND_IPalle InterfacesHost-IP, auf der App-Ports lauschen
--port-rangeSETUP_PORT_RANGE20000-20999Host-Ports für Apps
--max-jobsSETUP_MAX_JOBS2Parallele Jobs, 1 bis 64
--data-dirSETUP_DATA_DIR/var/lib/setup-runner als root unter Linux, sonst ~/.local/state/setup-runnerStatus, Compose-Dateien, Sicherungen
--docker-contextDOCKER_CONTEXTaktueller KontextWelcher Docker-Host genutzt wird
--runtimeSETUP_RUNTIMEautoWählt gVisor, dann Kata, dann runc; runc schaltet das ab
--allow-published-portsSETUP_ALLOW_PUBLISHED_PORTSausErlaubt Rezepten, rohe TCP- oder UDP-Ports zu veröffentlichen
--registry-mirrorSETUP_REGISTRY_MIRRORkeinerDocker-Hub-Mirror, siehe unten
--subnet-poolSETUP_SUBNET_POOLkeinerIPv4-Bereich für App-Netze, siehe unten
--no-log-shippingSETUP_NO_LOG_SHIPPINGausKeine App-Logs an Setup schicken

--tofu-image, --ingress-image, --helper-image und --go-builder-image ersetzen die fest gepinnten Hilfs-Images für Hosts mit eigener Registry. setup-runner run -h listet alle Flags.

Registry-Mirror

Docker Hub begrenzt anonyme Downloads pro IP-Adresse, und ein Heimnetz hinter einer einzigen öffentlichen Adresse stößt schnell an diese Grenze.

Terminal
setup-runner run --server https://setup.example --token srt_… \
  --registry-mirror mirror.gcr.io

mirror.gcr.io ist Googles öffentlicher Docker-Hub-Cache; jeder Pull-Through-Mirror funktioniert (host[:port][/path]). Der Runner holt Docker-Hub-Images zuerst vom Mirror und taggt sie unter ihrem ursprünglichen Namen, die Rezepte bleiben also unverändert. Klappt das nicht, lädt er direkt von Docker Hub. Andere Registries und per Digest gepinnte Images nutzt er immer direkt. Basis-Images in den FROM-Zeilen von Builds kommen weiterhin von Docker Hub, weil BuildKit sie selbst holt; dafür trägst du registry-mirrors in daemon.json ein.

Subnetz-Pool

Jede App nutzt bis zu vier Docker-Netze. Ein Docker-Daemon mit Standardeinstellungen vergibt etwa 30 davon, und ein Host mit weiteren Compose-Projekten kann sie aufbrauchen: „all predefined address pools have been fully subnetted“.

Terminal
setup-runner run --server https://setup.example --token srt_… \
  --subnet-pool 10.213.0.0/16

Der Runner gibt dann jedem App-Netz ein eigenes /27 aus diesem Bereich (ein /16 reicht für 2.048), überspringt Blöcke, die sich mit bestehenden Netzen überschneiden, und gibt sie wieder frei, wenn die App entfernt wird. Jobs für externe Dienste nutzen denselben Pool. Er muss IPv4 und /27 oder größer sein. Wähl einen Bereich, den dein LAN und VPN nicht nutzen.

Den Host absichern

Jeden Container und jedes App-Netz sichert der Runner ohne Konfiguration ab; was er durchsetzt, steht im Sicherheitsmodell. Die folgenden Schritte gehen weiter. Sie sind optional, und der Runner wendet keinen davon an. Teste sie vorher: Firewall-Regeln können andere Container abschneiden.

gVisor installieren. Unter runc teilen sich Container den Kernel des Hosts. gVisor gibt ihnen einen eigenen Kernel im User-Space, und der Runner nutzt ihn automatisch. Unter Debian oder Ubuntu:

Terminal
curl -fsSL https://gvisor.dev/archive.key | sudo gpg --dearmor -o /usr/share/keyrings/gvisor-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/gvisor-archive-keyring.gpg] https://storage.googleapis.com/gvisor/releases release main" \
  | sudo tee /etc/apt/sources.list.d/gvisor.list
sudo apt-get update && sudo apt-get install -y runsc
sudo runsc install
sudo systemctl restart docker

Images, die stark auf io_uring oder Direct I/O setzen, verhalten sich darunter manchmal anders; --runtime runc nimmt einen Runner aus.

Builds aus deinem LAN fernhalten. Build-Schritte (RUN) nutzen Dockers Standard-Bridge und erreichen so auch dein Netz. Diese Regeln verwerfen neue Verbindungen von docker0 in private Bereiche und lassen die App-Netze in Ruhe:

Terminal
sudo iptables -I DOCKER-USER -i docker0 -m conntrack --ctstate ESTABLISHED,RELATED -j RETURN
for net in 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 100.64.0.0/10 169.254.0.0/16; do
  sudo iptables -A DOCKER-USER -i docker0 -d "$net" -j DROP
done

Weniger nach außen zeigen. Binde die Ports mit --bind-ip an die LAN-Adresse, schütz den Portbereich mit einer Firewall und lass --allow-published-ports aus, solange keine App rohe Ports braucht.

Dem Runner einen eigenen Benutzer geben. Zugriff auf Docker ist so gut wie root. Nimm einen eigenen Benutzer in der Gruppe docker, auf einem Rechner oder einer VM, die sonst nichts tut. Das Datenverzeichnis enthält Compose-Dateien mit aufgelösten Secrets und die Sicherungen; leg es auf eine verschlüsselte Platte. Verschieb das Token nach /etc/setup-runner.env, lesbar nur für root:

SETUP_SERVER=https://setup.example
SETUP_RUNNER_TOKEN=srt_…
ini
[Unit]
Description=Setup runner
After=docker.service
Requires=docker.service

[Service]
User=setup-runner
EnvironmentFile=/etc/setup-runner.env
ExecStart=/usr/local/bin/setup-runner run --data-dir /var/lib/setup-runner
Restart=on-failure
RestartPreventExitStatus=3

[Install]
WantedBy=multi-user.target

Der Benutzer setup-runner muss Eigentümer von /var/lib/setup-runner sein. Exit-Status 3 heißt, dass Setup das Token abgelehnt hat; ein Neustart bringt dann nichts.

Aktualisieren

Der Runner aktualisiert sich nicht selbst. Bau die neue Binärdatei und tausch sie aus:

Terminal
sudo systemctl stop setup-runner
sudo install -m 0755 bin/setup-runner /usr/local/bin/setup-runner
sudo systemctl start setup-runner
setup-runner version

Beim Stoppen nimmt der Runner keine neuen Jobs an und gibt laufenden bis zu fünf Minuten. systemd wartet standardmäßig nur 90 Sekunden; erhöh TimeoutStopSec, wenn lange Jobs fertig werden sollen.

Token erneuern am Runner erzeugt ein neues Token, das alte funktioniert sofort nicht mehr. Trag das neue in die Unit oder die Umgebungsdatei ein und starte den Dienst neu.

Runner entfernen

  1. Entferne zuerst seine Apps im Dashboard, damit Setup ihre Container, Volumes und externen Ressourcen löscht.
  2. Wähl Löschen und dann Runner löschen. Laufen noch Apps darauf, deaktiviert Setup den Runner nur und behält ihre Einträge. In beiden Fällen funktioniert das Token nicht mehr.
  3. Stopp den Dienst. ls listet Apps, die noch im Datenverzeichnis stehen; destroy entfernt alles, was das Label eines Slugs trägt.
Terminal
sudo systemctl disable --now setup-runner
sudo setup-runner ls
sudo setup-runner destroy <slug>

Jobs für externe Dienste hinterlassen das Volume setup-tofu-plugin-cache und das Netz setup-provision-egress. Lösch das Datenverzeichnis zuletzt; darin liegen die Sicherungen.

Fehlersuche

  • Verbindet sich nie. Führ setup-runner doctor --server https://setup.example aus und lies journalctl -u setup-runner.
  • Beendet sich mit Status 3. Das Token wurde erneuert, oder der Runner wurde gelöscht oder deaktiviert. Nimm ein neues Token.
  • „cannot reach the Docker daemon“. Docker läuft nicht, der Benutzer ist nicht in der Gruppe docker, oder --docker-context stimmt nicht.
  • App-Links zeigen auf localhost. Setz --public-host.
  • „all predefined address pools have been fully subnetted“. Nimm --subnet-pool.
  • Pulls laufen ins Rate-Limit von Docker Hub. Nimm --registry-mirror.
  • Der Runner zeigt „Gehärtete Container“. Er hat weder gVisor noch Kata gefunden. Installier gVisor.