Updates und Notizen:
- 2025-01-09: Mit Forgejo Runner
v6
ist dieses Setup nicht mehr gültig, die benötigten Updates habe ich hier besprochen.
Ich nutze Forgejo als lokale Alternative für Github, um verschiedene Code-Repositories zu hosten. Bisher hatte ich zusätzlich Drone für CI/CD Tasks im Einsatz, aber mit Drone war ich eigentlich nie ganz glücklich. Trotzdem war es gefühlt das geringste Übel, und ich hatte keine Motivation, etwas zu verändert.
Vor einiger Zeit hat Gitea eine eigene CI/CD Alternative mit dem Namen Gitea Runners vogestellt. Diese sind auch für Forgejo verfügbar, und jetzt habe ich den Wechsel endlich gewagt.
Mein primäres Setup
Ich wollte mein Setup so klar wie möglich haben: Das System sollte möglichst wenig Veränderungen haben. Sprich: Ich habe einen Debian Host mit Docker installiert, und darauf läuft der Runner. Mehr sollte nicht passieren.
Viele Guides verfolgen dann den “Docker in Docker” Ansatz, um die Tasks auszuführen. Nachdem mein Forgejo Runner die einzige Applikation auf dieser Maschine ist, war mir das zu viel - der Runner dürfte ruhig direkt den Docker Host nutzen, auf dem er läuft. Mir ist bewusst dass das in bestimmten Szenarien ein Security-Problem sein kann, aber ich sehe es so: Mein Git Server läuft in meinem Homelab und ist im Wesentlichen unerreichbar von außen (abgesehen von einer kleinen Anzahl an Personen die einen VPN Zugang haben). Das gleiche gilt für den Forgejo Runner Server. Damit betrachte ich das Sicherheitsrisiko eines potentiellen Ausbruchs zumindest aktuell als gering genug, um diese weitere Virtualisierungsschicht nicht zu haben.
Die Infrastruktur ist also simpel: Installiere einen Debian Server, installiere Docker darauf. Alles andere läuft in Docker.
Setup vom Runner
Nach ein bisschen Ausprobieren habe ich das folgende docker-compose.yaml
File.
Update: Bitte beachte, dass ich das für die aktuelleren Versionen verändert habe, siehe hier.
services:
forgejo-runner:
image: code.forgejo.org/forgejo/runner:3.5.1
container_name: runner
environment:
DOCKER_HOST: unix:///var/run/docker.sock
user: 0:0
volumes:
- ./data:/data
restart: unless-stopped
command: forgejo-runner -c /data/config.yml daemon
Wo ich von der offiziellen Dokumentation abweiche:
- Ich habe keinen Docker-in-Docker.
- Der Runner läuft als User
root
(user: 0:0
). Das ist benötigt, um den äußerendocker.sock
zu nutzen. - Offensichtlich muss der äußere
docker.sock
in den Container gemapped werden. DieDOCKER_HOST
Variable ist auch entsprechend gesetzt. - Das ausgeführte Kommando ist angepasst: In der Dokumentation wird ein
sleep 5
benötigt, um den Docker in Docker Container zu starten; das benötige ich hier nicht und habe es daher entfernt.
Konfiguration
- Zuerst erzeugen wir das Verzeichnis:
mkdir ~/data
- Als nächstes soll Forgejo seine default Konfiguration erzeugen. Das geht mit dem folgenden Befehl:
Beachte die Anführungszeichen - diese sind mit Bedacht gesetzt. Der Container kennt die ausführbare Dateidocker compose run --rm forgejo-runner 'forgejo-runner' 'generate-config' > data/config.yaml
forgejo-runner
, und mit dieser Setzung von Anführungszeichen wird der Subkommandogenerate-config
von dieser ausführbaren Datei ausgeführt. Wenn wir die Anführungszeichen so nicht setzen, sucht Docker im Container nach der Executable'forgejo-runner generate-config'
, und das würde offensichtlich scheitern.
Dieser Befehl erzeugt die Default Konfiguration. Der Teil> data/config.yaml
wird wieder am Host-System ausgeführt, und die Konfiguration wird dadurch nach~/data/config.yaml
geschrieben. - Als nächstes passen wir die Konfiguration an. Ich habe die folgenden Änderungen durchgeführt:
- Ich habe mit dem
fetch_interval
undreport_interval
ein bisschen herumgespielt. Das ist aber nicht wirklich nötig und war eher meinem Interesse geschuldet. - Ich habe die folgenden Labels definiert:
ubuntu-22.04:docker://node:20-bullseye
. Das wird also guter Ansatz in der Dokumentation definiert.debian-12:docker://registry.hub.docker.com/library/debian:12
. Das ist nur ein Test von mir. Beachte dass damit keine vordefinierten Actions ausgeführt werden könne!
- Beachte: Für neuere Versionen vom Forgejo Runner sind ein paar Updates nötig, die ich hier beschrieben habe.
- Ich habe mit dem
Diese Labels sind ziemlich wichtig, weil sie definieren welche Jobs man auf dem System ausführen kann. Welche Lables gut sind und wie ich sie nutze werde ich wohl in Zukunft noch beschreiben.
Beachte dass diese Labels auch nicht zwangsläufig statisch sind. Sie können angepasst werden und sind dann per Neustart des Runners auch nutzbar.
Den Runner registrieren
Das war überraschend einfach.
- Geh zu deiner Forgejo Instanz (ich nutze
forgejo.tech-tales.blog
als Beispiel) und logge dich ein.- Gehe zu Settings - Actions - Runners. Dort gibt es einen “Create new runner” Knopf, durch den du ein Registrierungs-Token erhältst. Kopiere das, das benötigen wir gleich wieder.
- Zurück zum Forgejo Runner Server. Hier führst du den folgenden Befehl aus:
docker compose run --rm -it forgejo-runner 'forgejo-runner' 'register'
- Du wirst zuerst nach der Domain gefragt (also
https://forgejo.tech-tales.blog
), dann nach dem Token (das haben wir gerade kopiert), und dann nach einem Namen für den Runner (ich habeforgejo-docker-runner-0
gewählt, hier aber gerne kreativ sein). Alles eingeben, und wir sind fertig!
- Du wirst zuerst nach der Domain gefragt (also
- Zurück auf der Command Line wurde eine neue Datei erzeugt:
~/data/.runner
. Darin steht die relevante Information für den Runner, um sich zur Forgejo Instanz zu verbinden. Beachte dass sich das Token vom Registrierungstoken unterscheidet!
Fertig - Starte den Runner!
Wir sind fertig! Führe docker compose up -d
aus, und checke mit docker compose logs -f
die Logs. Wenn alles gut gelaufen ist, solltest du drei Zeilen sehen die dir sagen dass der Runner erfolgreich läuft.
Gehe jetzt wieder zurück zu Forgejo. In Settings - Actions - Runners siehst du den Runner jetzt, und der Status sollte Idle
sein.
Ab sofort kannst du Workflows in deinen Repos nutzen. Beachte dass du in den Einstellungen eines Repos unter “Repository units - Overview” die Actions erst aktivieren musst. In einem Workflow musst du dann runs-on: ubuntu-22.04
nutzen.