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ßeren docker.sock zu nutzen.
  • Offensichtlich muss der äußere docker.sock in den Container gemapped werden. Die DOCKER_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:
    docker compose run --rm forgejo-runner 'forgejo-runner' 'generate-config' > data/config.yaml
    
    Beachte die Anführungszeichen - diese sind mit Bedacht gesetzt. Der Container kennt die ausführbare Datei forgejo-runner, und mit dieser Setzung von Anführungszeichen wird der Subkommando generate-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 und report_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.

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 habe forgejo-docker-runner-0 gewählt, hier aber gerne kreativ sein). Alles eingeben, und wir sind fertig!
  • 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.