CI / CD on Pi
Eine CI / CD Pipeline in die 4 GB RAM des Raspberry Pi 4 quetschen? Hier ist mein Erfahrungsbericht.
Ausgangspunkt
Mein Raspberry Pi 4 lag zuletzt nur noch herum, da ich neue Projekte stets auf dem wesentlich leistungsstärkeren Proxmox Server aufgesetzt habe. Das aber muss ja nicht sein, denn auch ein bisschen Rechenkraft kann nützlich sein.
Ich programmiere viele meiner Apps für den Heimgebrauch selbst. Das tue ich auch im Zeitalter des Vibe-Codings immer noch gerne - wobei die AI mithelfen darf. Dabei verstreuen sich die Projekte, vom Code bis zum Endprodukt, auf viele verschiedene Systeme und Dienste. Der Code liegt beispielsweise auf dem Laptop, landet bei GitHub und GitHub Action schiebt es zu Docker, von wo der Deployment Server (zum Beispiel Proxmox) das Image zieht.
Diese Kette würde ich gerne lokal verfügbar machen. CI / CD für den Hausgebrauch. Also habe ich mir den Rasby geschnappt und einfach mal angefangen. Ich bin selbst gespannt, wo das hinführt.
So sieht das Vorhaben aus:
- Raspberry Pi OS Lite auf dem Raspberry Pi 4
- VS Code Server per Direktinstallation
- Docker nebst Docker Compose
- Arcane für Docker (Ich bin ein GUI Guy)
- Forgejo als Projektverwaltung
- Forgejo-Runner für die Actions (um die Projekte zu bauen und zu deployen)
Es gibt viel zu tun, also tippen wir los.
Raspberry Pi vorbereiten
Ich habe mit dem Raspberry Pi Imager Raspberry Pi OS Lite auf eine SD-Karte geschrieben. Das kommt ohne Weboberfläche daher, da ich diese für mein Vorhaben nicht brauche. Ich verbinde mich ausschließlich per SSH - der Pi läuft also headless.
Ich werde nicht zu sehr ins Detail gehen, da der Artikel schon recht lang wird. Wer versucht ist, das hier nachzustellen, wird also viel offizielle Dokumentation lesen müssen. Für den Raspberry findet sich diese zum Beispiel unter diesem Link.
Nachdem ich mich per SSH verbunden habe, wird das System aktualisiert:
1
sudo apt update & upgrade -y
Danach kann ich damit beginnen, die einzelnen Komponenten zu installieren.
VS Code Server
Als Erstes installiere ich den VS Code Server. Damit kann ich VS Code geräteunabhängig im Browser nutzen. Es läuft ja alles auf dem Pi. Die Installation ist sehr einfach.
Von coder.com die lokale Installation ausführen:
1
curl -fsSL https://code-server.dev/install.sh | sh
Dann den Services aktivieren:
1
systemctl enable --now code-server@$USER
Nun muss noch die Config bearbeitet werden, sonst kann ich den Server von außen nicht erreichen:
1
nano /home/pi-user/.config/code-server/config.yaml`
Diese bekommt folgende Einträge:
1
2
3
bind-addr: 0.0.0.0:8080
auth: none
cert: false
Es ist kein Zertifikat aktiv und es kann von überall aus zugegriffen werden. Das ist potenziell sehr unsicher. Daher nur für den Heimgebrauch so machen!
Durch die geänderte bind-addr können auch externe Clients auf den VS Code Server zugreifen.
Der VS Code Server ist unter der IP des Pi (pun intended) erreichbar (Screenshot: Markus Daams / 2026)
Docker
Jetzt kommt Docker an die Reihe, denn den Rest will ich in Containern laufen lassen. Das dient vor allem der Übersichtlichkeit. Für die Installation habe ich mich nach der Anleitung unter diesem Link gerichtet:
- Docker auf dem Raspberry Pi installieren: https://raspberry.tips/raspberrypi-tutorials/docker-raspberry-pi-installieren.
Neben Docker habe ich auch Docker Compose mit installiert, denn damit mache ich ab sofort weiter.
Arcane
Um die Images und Container zu verwalten und um die Systemauslastung zu überwachen, installiere ich Arcane. In meinem Artikel Breaking Changes habe ich ja bereits erwähnt, dass Portainer die Community Edition einstampfen wird und nur noch eine ältere Version anbieten möchte. Ich teste daher aktuell Alternativen, wobei es mir Arcane angetan hat.
Für meine Container erstelle ich als Erstes einen neuen Ordner:
1
mkdir -p /opt/containers
Das schafft Ordnung. Da ich Arcane installieren will, lege ich den entsprechenden Ordner auch direkt an:
1
2
mkdir -p /opt/containers/arcane
cd /opt/containers/arcane
Anschließend erstelle ich das Compose-Datei mit:
1
nano compose.yaml
Bei dem Inhalt halte ich mich einfach an die offizielle Anleitung. Ich ändere aber die APP_URL auf die IP meines Raspberrys ab. Außerdem wird noch ein ENCRYPTION_KEY benötigt. Den lasse ich mir im Terminal per openssl rand -hex 32 erstellen und kopiere diesen in die Zwischenablage.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
services:
arcane:
image: ghcr.io/getarcaneapp/manager:latest
container_name: arcane
ports:
- '3552:3552'
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- arcane-data:/app/data
environment:
- APP_URL=http://192.168.178.40:3552
- PUID=1000
- PGID=1000
- ENCRYPTION_KEY=xxxxxxxxxxxxxxxxxx
cgroup: host
restart: unless-stopped
volumes:
arcane-data:
Zuletzt starte ich Arcane mittels:
1
docker compose up -d
Danach kann ich es unter http://192.168.178.40:3552 erreichen und mich anmelden. Für die erste Anmeldung werden die Default-Daten verwendet:
Benutzername: arcane
Passwort: arcane-admin
Das Passwort muss nun geändert werden, danach kann es in Arcane aber losgehen.
Die Weboberfläche von Arcane. Ich verwalte hiermit nun mein Docker-Gelöt (Screenshot: Markus Daams / 2026)
Forgejo
In meinem Artikel GitHub Alternativen hatte ich das Projekt Forgejo schon einmal vorgestellt. Es handelt sich um einen Fork von Gitea. Kurz erklärt: Es handelt sich um ein GitHub für den Hausgebrauch. Es ist open source und frei zugänglich. Wer Git liebt oder es nutzen muss und nicht liebt, wird sich über Forgejo freuen. Hiermit lassen sich Code-Projekte verwalten, nebst Ticketverwaltung, Projektdokumentation und vielem mehr. Vor allem ist es sehr ressourcenschonend. Ich kann natürlich auch nur auf Git setzen, der Raspberry würde sich freuen. Aber ein bisschen Komfort erlaube ich mir.
Für Forgejo spricht auch, dass es Runner gibt, die ich mit den Actions nutzen kann. Den brauche ich für meinen CI / CD Workflow. Aber erst einmal installiere ich Forgejo.
1
2
mkdir -p /opt/containers/forgejo
cd /opt/containers/forgejo
Anschließend erstelle ich das Compose-Datei für Forgejo:
1
nano compose.yaml
Den Inhalt entnehme ich meiner alten Installation und hoffe, dass das noch funktioniert.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
services:
server:
image: codeberg.org/forgejo/forgejo:16
container_name: forgejo
environment:
- USER_UID=1000
- USER_GID=1000
- FORGEJO__database__DB_TYPE=postgres
- FORGEJO__database__HOST=db:5432
- FORGEJO__database__NAME=forgejo
- FORGEJO__database__USER=forgejo
- FORGEJO__database__PASSWD=<DBPASSWORD>
restart: always
networks:
- forgejo
volumes:
- ./forgejo:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "222:22"
depends_on:
- db
db:
image: postgres:14
restart: always
environment:
- POSTGRES_USER=forgejo
- POSTGRES_PASSWORD=<DBPASSWORD>
- POSTGRES_DB=forgejo
networks:
- forgejo
volumes:
- ./postgres:/var/lib/postgresql/data
networks:
forgejo:
external: false
Danach starte ich Forgejo mittels:
1
docker compse up -d
Hau ab mit GitHub. Forgejo ist schick und schnell (Screenshot: Markus Daams / 2026)
Und es klappt. Unter http://192.168.178.40:3000 erreiche ich Forgejo, überprüfe die Daten und starte es. Die Installation von Forgejo ist inzwischen echt smooth geworden.
Forgejo Runner
In diesem Artikel hatte ich schon einmal beschrieben, wie ich mit den GitHub Actions Docker Container gebaut und in die Registry geschoben habe. Mittels der GitHub Actions kann ich eine Reihe von Aktionen ausführen, die ich nach dem git push erledigt haben will. In meinem Fall soll das in etwa so ablaufen:
- Ich pushe meinen Code via
gitin die Forgejo Instanz - Der Runner legt los und holt sich den Code
- Das Projekt wird gebaut (also zum Beispiel
npm installundnpm run build) - Das Image wird gebaut und der Container in der lokalen Docker-Umgebung bereitgestellt.
Ich brauche nur noch coden und die Actions machen mit dem Runner den Rest.
Auch für den Runner lege ich einen Ordner an:
1
2
mkdir -p /opt/containers/forgejo-runner/data
cd /opt/containers/forgejo-runner
Dann erstelle ich das Compose-Datei.
1
nano compose.yaml
Die Datei bekommt folgenden Inhalt:
1
2
3
4
5
6
7
8
9
10
11
12
13
services:
runner:
image: code.forgejo.org/forgejo/runner:13.1.0
container_name: forgejo-runner
restart: unless-stopped
user: root
command: forgejo-runner daemon --config /data/config.yaml
environment:
- DOCKER_HOST=unix:///var/run/docker.sock
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./data:/data
Ich habe den User auf root gelegt, damit der Runner selbst Zugriff auf den Docker Socket bekommt. Auch das ist potenziell sehr unsicher. Aber es ist eben auch ein Bastelprojekt.
Der Runner muss noch in Forgejo registriert werden. Damit das funktioniert, muss das Registrierungstoken in Forgejo abgerufen werden.
Rechts oben auf das Profilbild klicken -> Administration -> Actions -> Runners. Einmal auf Registrierungstoken anzeigen klicken und das Token kopieren.
Zurück im Terminal muss im Ordner /opt/containers/forgejo-runner nun dieser Befehl ausgeführt werden:
1
2
3
4
5
6
docker compose run --rm runner forgejo-runner register \
--no-interactive \
--instance http://192.168.178.40:3000/ \
--token REGISTRIERUNGS_TOKEN_HIER_REIN \
--name pi4-runner \
--labels docker:docker://node:20-bookworm
Die instance ist das zuvor installierte Forgejo. Damit wird der Runner erstellt und in Forgejo registriert.
Der Runner ist online und ich kann mit den Actions loslegen (Screenshot: Markus Daams / 2026)
Bis hierher - Fortsetzung folgt
Ich bin mit der Grundinstallation meiner geplanten CI / CD Pipeline fertig und diese sieht so aus:
- Der Raspberry Pi 4 läuft mit Raspberry Pi OS Lite (Debian Trixie)
- Als Basis dient mir der VS Code Server
- Ich habe Docker (Compose) installiert
- Per Docker Compose läuft darauf Arcane (das ist aber optional)
- Ich habe Forgejo und den Forgejo Runner installiert, um diesen in den Actions nutzen zu können
So weit läuft alles und damit soll es für diesen Artikel auch erst einmal gut sein. Als Nächstes werde ich die CI / CD Pipeline mit einem kleinen Testprojekt ausprobieren.
Bisher macht der Raspberry Pi 4 alles mit. Die RAM-Auslastung liegt mit allen 4 Containern (Arcane, Forgejo, Forgejo-DB, Forgejo-Runner) und dem VS Code Server bei ca. 30 %. Das wird sich natürlich ändern, wenn der Runner loslegt.
Wie es weitergeht, beschreibe ich in Teil 2 dieses Artikels.
