Woodpecker CI mit Docker installieren: Schlanke CI/CD-Engine für Gitea und Forgejo
Woodpecker CI ist ein ressourcenschonender CI/CD-Fork von Drone, der nativ mit Gitea und Forgejo zusammenarbeitet. Jeder Pipeline-Schritt läuft in einem eigenen Docker-Container – Server und Agent zusammen unter 50 MB RAM. Diese Anleitung zeigt den kompletten Aufbau per Docker Compose.

Wer bereits Gitea oder Forgejo selbst hostet, steht früher oder später vor der Frage: Wie automatisiere ich Tests, Builds und Deployments, ohne eine schwergewichtige CI/CD-Plattform à la Jenkins aufsetzen zu müssen? Woodpecker CI ist die Antwort für alle, die schlanke, transparente und Docker-native Pipelines suchen. Als Community-Fork von Drone CI läuft Woodpecker mit zwei winzigen Containern (Server + Agent), verbraucht zusammen unter 50 MB RAM im Leerlauf und ist in rund 25 Minuten einsatzbereit – auch auf einem kleinen VPS oder einem ARM-Board. Jeder Pipeline-Schritt wird in einem eigenen, isolierten Docker-Container ausgeführt; kein gemeinsamer Zustand, kein verstecktes Side-Effect. Diese Anleitung richtet sich an Linux-Admins und ambitionierte Selfhoster, die Gitea oder Forgejo bereits betreiben und eine saubere, wartungsarme CI/CD-Lösung ohne Kubernetes-Overhead benötigen.
Voraussetzungen
- Docker Engine >= 20.10 und Docker Compose Plugin v2 (
docker compose) auf einem Linux-Host (Ubuntu/Debian empfohlen). Falls noch nicht installiert: Docker und Docker Compose auf Linux installieren. - Laufende Gitea- oder Forgejo-Instanz mit Admin-Zugang zum Erstellen einer OAuth-App. Für den Gitea-Einstieg: Gitea mit Docker: eigener Git-Server als GitHub-Alternative.
- Öffentlich erreichbare Domain oder URL für den Woodpecker-Server – für Webhooks von Gitea/Forgejo zwingend erforderlich. Ohne erreichbare URL empfangen deine Repos keine Push-Events.
- Mindestens 512 MB RAM frei (Empfehlung: 1 GB), 1 vCPU, ca. 1 GB Speicherplatz. Läuft auch auf ARM64 (Raspberry Pi, Apple Silicon).
- openssl zum Generieren des Agent-Secrets (auf jedem modernen Linux vorinstalliert).
- Für Produktion: ein Reverse Proxy mit TLS. Eine schnelle Option ist Caddy als Reverse Proxy mit automatischem HTTPS.
Schritt 1: Projektordner und Secret anlegen
Lege zunächst ein dediziertes Verzeichnis für den Woodpecker-Stack an und generiere das Agent-Secret. Dieses Secret authentifiziert den Agent gegenüber dem Server – beide müssen exakt denselben Wert tragen.
mkdir -p /opt/woodpecker
cd /opt/woodpecker
openssl rand -hex 32Den ausgegebenen Hex-String (64 Zeichen) kopierst du gleich in die .env-Datei. Behandle ihn wie ein Passwort: nicht in ein öffentliches Repository einchecken, nicht per Chat verschicken. Bei einem Leak musst du ihn auf Server und Agent gleichzeitig rotieren.
Verifizieren: Das Verzeichnis /opt/woodpecker existiert (ls -la /opt/woodpecker) und openssl hat einen 64-stelligen Hex-String ausgegeben. Falls openssl fehlt: apt install openssl -y.
Schritt 2: OAuth-App in Gitea oder Forgejo erstellen
Woodpecker benötigt eine OAuth2-App in deiner Forge, um Benutzer anzumelden und Repository-Webhooks einzurichten. Der Ablauf ist in Gitea und Forgejo identisch.
- Melde dich als Admin in Gitea/Forgejo an und öffne: Benutzer-Einstellungen → Anwendungen → OAuth2-Anwendungen verwalten → Neue OAuth2-Anwendung erstellen.
- Vergib einen Namen (z. B.
Woodpecker CI). - Setze die Redirect/Callback-URI exakt auf:
https://ci.example.com/authorize– ersetzeci.example.comdurch deine tatsächliche Woodpecker-Domain. Groß-/Kleinschreibung und das abschließende Slash sind relevant; jede Abweichung führt zu einem 400 Bad Request – redirect_uri does not match-Fehler. - Bestätige und notiere Client-ID und Client-Secret – das Secret wird nur einmal angezeigt.
Verifizieren: In Gitea/Forgejo unter „OAuth2-Anwendungen" erscheint der neue Eintrag mit der korrekten Redirect-URI. Client-ID und Client-Secret sind notiert.
Schritt 3: .env-Datei anlegen
Alle variablen und geheimen Werte wandern in eine .env-Datei im Projektordner. Docker Compose liest diese Datei automatisch ein. Lege sie unter /opt/woodpecker/.env an:
# Pflicht-Konfiguration
WOODPECKER_HOST=https://ci.example.com
WOODPECKER_AGENT_SECRET=<dein-64-stelliger-hex-string>
WOODPECKER_ADMIN=meinusername
# Initiale Einrichtung: Registrierung offen lassen, danach auf false setzen
WOODPECKER_OPEN=true
# Gitea-Forge (fuer Forgejo: WOODPECKER_FORGEJO=true + WOODPECKER_FORGEJO_* Variablen)
WOODPECKER_GITEA=true
WOODPECKER_GITEA_URL=https://gitea.example.com
WOODPECKER_GITEA_CLIENT=<oauth-client-id-aus-gitea>
WOODPECKER_GITEA_SECRET=<oauth-client-secret-aus-gitea>
# Agent-Konfiguration
WOODPECKER_MAX_WORKFLOWS=2
# Optional
WOODPECKER_LOG_LEVEL=infoWichtige Hinweise zur .env-Datei:
WOODPECKER_HOSTmuss das Schema (https://) enthalten und darf keinen abschließenden Schrägstrich haben.- Für Forgejo ersetzt du den Gitea-Block durch:
WOODPECKER_FORGEJO=true,WOODPECKER_FORGEJO_URL,WOODPECKER_FORGEJO_CLIENTundWOODPECKER_FORGEJO_SECRET. In Woodpecker v3 gibt es einen dedizierten Forgejo-Driver – ältere Anleitungen, die Forgejo mitWOODPECKER_GITEA=truekonfigurieren, sind veraltet. - Setze
WOODPECKER_OPEN=false, sobald der erste Admin-Account angelegt ist. - Berechtigungen einschränken:
chmod 600 /opt/woodpecker/.env.
Verifizieren: cat /opt/woodpecker/.env zeigt alle gesetzten Werte; keine Zeile enthält noch einen Platzhalter wie <...>. stat /opt/woodpecker/.env zeigt Berechtigungen 600.
Schritt 4: compose.yaml erstellen
Lege die Compose-Datei unter /opt/woodpecker/compose.yaml an. Der Agent startet erst, wenn der Server-Healthcheck erfolgreich ist (condition: service_healthy). Der gRPC-Port 9000 wird nicht in ports: gemappt – er ist nur innerhalb des internen Docker-Netzwerks erreichbar.
services:
woodpecker-server:
image: woodpeckerci/woodpecker-server:v3
container_name: woodpecker-server
restart: unless-stopped
ports:
- "8000:8000"
volumes:
- woodpecker-server-data:/var/lib/woodpecker/
networks:
- woodpecker
environment:
- WOODPECKER_OPEN=${WOODPECKER_OPEN:-false}
- WOODPECKER_ADMIN=${WOODPECKER_ADMIN}
- WOODPECKER_HOST=${WOODPECKER_HOST}
- WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET}
- WOODPECKER_GITEA=${WOODPECKER_GITEA:-true}
- WOODPECKER_GITEA_URL=${WOODPECKER_GITEA_URL}
- WOODPECKER_GITEA_CLIENT=${WOODPECKER_GITEA_CLIENT}
- WOODPECKER_GITEA_SECRET=${WOODPECKER_GITEA_SECRET}
- WOODPECKER_LOG_LEVEL=${WOODPECKER_LOG_LEVEL:-info}
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:8000/healthz"]
interval: 30s
timeout: 10s
retries: 5
start_period: 30s
woodpecker-agent:
image: woodpeckerci/woodpecker-agent:v3
container_name: woodpecker-agent
restart: unless-stopped
command: agent
depends_on:
woodpecker-server:
condition: service_healthy
volumes:
- woodpecker-agent-config:/etc/woodpecker
- /var/run/docker.sock:/var/run/docker.sock
networks:
- woodpecker
environment:
- WOODPECKER_SERVER=woodpecker-server:9000
- WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET}
- WOODPECKER_MAX_WORKFLOWS=${WOODPECKER_MAX_WORKFLOWS:-2}
- WOODPECKER_LOG_LEVEL=${WOODPECKER_LOG_LEVEL:-info}
volumes:
woodpecker-server-data:
woodpecker-agent-config:
networks:
woodpecker:Eckdaten auf einen Blick
| Parameter | Wert | Hinweis |
|---|---|---|
| Image Server | woodpeckerci/woodpecker-server:v3 | Aktuell v3.15.0 (Mai 2026); :latest ist deprecated |
| Image Agent | woodpeckerci/woodpecker-agent:v3 | Multi-Arch: amd64 + arm64 |
| Port Web-UI | 8000 | HTTP; für Produktion Reverse Proxy vorschalten |
| Port gRPC | 9000 | Nur intern im Docker-Netz – niemals nach außen öffnen |
| Volume Server | woodpecker-server-data | Enthält SQLite-DB woodpecker.sqlite |
| Volume Agent | /var/run/docker.sock | Pflicht für Docker-Backend |
| RAM (Idle) | < 50 MB | Server + Agent zusammen |
| Datenbank | SQLite (Standard) | PostgreSQL/MySQL optional |
Verifizieren: Schnellprüfung mit: docker compose -f /opt/woodpecker/compose.yaml config – das Kommando gibt die aufgelöste Compose-Konfiguration aus, ohne etwas zu starten. Fehlende Variablen werden hier sofort sichtbar.
Schritt 5: Stack starten
Wechsle in den Projektordner und starte den Stack:
cd /opt/woodpecker
docker compose up -dDocker zieht zunächst beide Images (beim ersten Start je nach Verbindung 30–90 Sekunden). Der Agent wartet automatisch, bis der Server-Healthcheck erfolgreich ist.
Verifizieren:
docker compose psErwartete Ausgabe (nach ca. 60 Sekunden):
NAME IMAGE STATUS
woodpecker-server woodpeckerci/woodpecker-server:v3 Up (healthy)
woodpecker-agent woodpeckerci/woodpecker-agent:v3 UpZeigt der Server Up (starting) oder Up (unhealthy), warte weitere 30 Sekunden und prüfe die Logs:
docker compose logs woodpecker-server --tail=50Anschließend den Health-Endpunkt direkt testen:
curl -s http://localhost:8000/healthzErwartete Antwort: OK oder ein JSON-Body mit "status":"ok". Ein HTTP-200 bestätigt, dass der Server läuft.
Schritt 6: Reverse Proxy und HTTPS einrichten (Produktion)
Für den Produktivbetrieb muss Port 8000 hinter einem Reverse Proxy mit TLS liegen, da Gitea/Forgejo die Webhooks an WOODPECKER_HOST sendet – und dieser Wert mit https:// beginnen sollte. Eine ausführliche Anleitung für Caddy (mit automatischem Let's-Encrypt-Zertifikat) findest du unter Caddy als Reverse Proxy einrichten. Minimale Caddy-Konfiguration für Woodpecker:
ci.example.com {
reverse_proxy localhost:8000
}Nach dem Aktivieren des Reverse Proxys muss WOODPECKER_HOST in der .env exakt der HTTPS-Domain entsprechen. Danach den Stack neu starten:
cd /opt/woodpecker
docker compose up -d --force-recreateVerifizieren:
curl -I https://ci.example.com/healthzErwartetes Ergebnis: HTTP/2 200 (oder HTTP/1.1 200) ohne Zertifikatsfehler. Im Browser sollte https://ci.example.com das Woodpecker-Login laden.
Schritt 7: Erste Anmeldung und Admin-Einrichtung
Öffne https://ci.example.com im Browser. Du wirst zu Gitea/Forgejo weitergeleitet und nach dem Autorisieren der OAuth-App zurückgeleitet. Der erste angemeldete Benutzer, dessen Username in WOODPECKER_ADMIN eingetragen ist, erhält automatisch Admin-Rechte.
- Melde dich über den OAuth-Flow an.
- Navigiere zu Admin → Agents – dort sollte der Agent mit Status connected erscheinen.
- Unter Repositories kannst du ein vorhandenes Gitea-Repository aktivieren. Woodpecker legt automatisch einen Webhook im Repo an.
- Setze nach dem ersten Login
WOODPECKER_OPEN=falsein der.envund starte den Server neu:docker compose up -d woodpecker-server. Damit verhinderst du, dass sich unbekannte Benutzer selbst registrieren können.
Verifizieren: In der Admin-Oberfläche unter https://ci.example.com/admin/agents ist mindestens ein Agent mit Status connected gelistet. Die Logs zeigen keine authentication failed-Meldungen:
docker compose logs woodpecker-agent --tail=20Erwarteter Logeintrag: connecting to server gefolgt von successfully connected.
Schritt 8: Erste Pipeline anlegen
Pipelines werden als .woodpecker.yaml (oder .woodpecker.yml) im Root des Repositories definiert. Hier ein minimales Beispiel, das zeigt, wie jeder Schritt in einem eigenen Container läuft:
when:
- event: push
steps:
- name: test
image: alpine
commands:
- echo "Build laeuft in eigenem Container"
- uname -a
- name: lint
image: node:20-alpine
commands:
- npm ci
- npm run lintCommitte und pushe diese Datei in ein in Woodpecker aktiviertes Repository. Der Push-Event löst über den Gitea/Forgejo-Webhook sofort eine Pipeline aus.
Verifizieren: In der Woodpecker-Web-UI unter Pipelines erscheint ein neuer Build-Eintrag. Klicke ihn an – jeder Step zeigt seine Container-Logs in Echtzeit. Alternativ per CLI:
docker compose logs woodpecker-agent --tail=30 --followBeim Ausführen einer Pipeline siehst du Logzeilen wie starting step test, pulling image alpine und step test done.
Schritt 9: Updates und Backup
Woodpecker erscheint etwa alle 4–6 Wochen mit neuen Releases, inkl. Security-Patches. Das Update-Verfahren ist schlank:
cd /opt/woodpecker
docker compose pull
docker compose up -dBei Major-Version-Wechseln (z. B. v2 → v3) immer zuerst die Migrations-Dokumentation lesen – dort werden Breaking Changes und notwendige Datenbankmigrationen dokumentiert.
Für das Backup reicht es, das Docker-Volume woodpecker-server-data zu sichern. Es enthält die SQLite-Datei woodpecker.sqlite mit allen Repositories, Pipelines, Secrets und Benutzerkonten. Einfaches Backup:
docker compose stop woodpecker-server
tar -czf /backup/woodpecker-$(date +%F).tar.gz \
$(docker volume inspect woodpecker_woodpecker-server-data \
--format '{{.Mountpoint}}')
docker compose start woodpecker-serverEine ausführliche Backup-Strategie für Docker-Volumes beschreibt 3-2-1-Backup-Strategie umsetzen.
Verifizieren:
docker compose psNach dem Update zeigt docker inspect woodpecker-server | grep Image den neuen Image-Digest. Alle vorherigen Pipelines und Repository-Einstellungen sind unverändert erhalten.
Troubleshooting / Typische Fehler
- Agent erscheint nicht in der Admin-UI / „authentication failed" in den Logs: Server und Agent verwenden unterschiedliche
WOODPECKER_AGENT_SECRET-Werte. Ursache ist meist ein Tippfehler in der.envoder zwei verschiedene.env-Dateien. Prüfen:docker compose logs woodpecker-agent | grep -i auth. Fix: Wert in der.envvereinheitlichen, Stack neu starten. - „400 Bad Request – redirect_uri does not match" beim Login: Die in Gitea/Forgejo eingetragene OAuth-Callback-URL stimmt nicht exakt mit
https://<WOODPECKER_HOST>/authorizeüberein. Häufige Ursachen:httpstatthttps, fehlender Pfad/authorize, abschließender Schrägstrich. In Gitea/Forgejo die OAuth-App bearbeiten und URL korrigieren. - Webhooks werden nicht ausgelöst (Gitea/Forgejo und Woodpecker auf demselben Host): Fehler in Gitea-Logs:
dial: connection refused. Fix: Beide Services in dasselbe Docker-Netzwerk bringen. In Gitea/Forgejoapp.iniunter[webhook]den WertALLOWED_HOST_LIST=external,loopbacksetzen und Gitea/Forgejo neu starten. - „permission denied while trying to connect to the Docker daemon socket": Der Agent-Container darf nicht auf
/var/run/docker.sockzugreifen. Fix: Sicherstellen, dass der Socket korrekt in dercompose.yamlgemountet ist und der Docker-Daemon auf dem Host läuft. Bei Berechtigungsproblemen:ls -la /var/run/docker.sock– der Socket muss der Gruppedockergehören. - Server bleibt dauerhaft „unhealthy": Häufig falsch gesetzte Umgebungsvariablen (z. B.
WOODPECKER_GITEA_URLnicht erreichbar vom Container aus) oder Port 8000 bereits belegt. Prüfen:docker compose logs woodpecker-server --tail=100undss -tlnp | grep 8000. - Datenbank geht bei jedem Neustart verloren: Das Volume
woodpecker-server-dataist nicht persistent definiert oder wurde mitdocker compose down -vgelöscht. Niemals-vbeim Stoppen verwenden, wenn die Daten erhalten bleiben sollen. - Unerwartetes Major-Version-Upgrade nach
docker compose pull: Das:latest-Tag ist in Woodpecker offiziell deprecated und kann einen Sprung von v2 auf v3 auslösen, der Breaking Changes enthält. Immer explizite Tags wiev3oderv3.15verwenden – so wie in der obigencompose.yamlangegeben.
Häufige Fragen
Brauche ich zwingend Gitea oder Forgejo?
Nein. Woodpecker unterstützt auch GitHub, GitLab, Bitbucket und weitere Forges über ein Plugin-System. Es ist jedoch speziell für Gitea und Forgejo optimiert und wird in diesen Setups am häufigsten eingesetzt. Die Konfiguration für andere Forges folgt demselben Prinzip mit entsprechend anderen Umgebungsvariablen.
Kann ich mehrere Agents betreiben?
Ja. Du kannst beliebig viele Agents mit demselben Server verbinden – sie müssen lediglich das identische WOODPECKER_AGENT_SECRET verwenden und den Server über WOODPECKER_SERVER=woodpecker-server:9000 (oder die öffentliche IP/Domain mit Port 9000, wenn der Agent auf einem anderen Host läuft) erreichen. Damit lassen sich horizontale Build-Kapazitäten aufbauen, ohne den Server anzufassen.
Wo wird die Pipeline-Konfiguration abgelegt?
Im Repository-Root als .woodpecker.yaml (oder .woodpecker.yml). Alternativ kannst du mehrere Dateien im Verzeichnis .woodpecker/ ablegen – Woodpecker führt alle darin enthaltenen YAML-Dateien aus. Die Datei wird vom Agent beim Start einer Pipeline direkt aus dem Repository geklont; es gibt keine zentrale Pipeline-Konfiguration im Server.
Läuft Woodpecker auf einem Raspberry Pi oder Apple Silicon?
Ja. Beide Images (woodpeckerci/woodpecker-server und woodpeckerci/woodpecker-agent) sind Multi-Arch-Images und unterstützen linux/amd64 sowie linux/arm64. Docker zieht automatisch die passende Architektur. Woodpecker wird sogar offiziell auf dem Raspberry Pi getestet.
Wie führe ich das Update auf eine neue Minor-Version durch?
Mit dem Tag v3 bekommst du automatisch das neueste v3.x.x-Release beim nächsten docker compose pull. Willst du präziser pinnen, nutze v3.15 (minor-stable) oder v3.15.0 (exakter Commit). Bei Minor-Updates reicht docker compose pull && docker compose up -d. Bei einem Major-Update (v2 → v3) unbedingt vorher die Migrationsdokumentation lesen.
Kann ich den Docker-Socket vermeiden?
Für das Standard-Docker-Backend ist /var/run/docker.sock erforderlich. Alternativ gibt es ein Kubernetes-Backend (für K8s-Cluster) und ein lokales Backend. Wer den Socket-Zugriff einschränken möchte, sollte sich die offizielle Dokumentation zu alternativen Backends ansehen. Allgemeine Härtungsmaßnahmen für Docker-Compose-Stacks beschreibt Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only.
Fazit
Woodpecker CI ist eine der schlanksten CI/CD-Lösungen, die du selbst hosten kannst. Zwei kleine Container, eine SQLite-Datenbank, eine .env-Datei – und du hast eine vollwertige Pipeline-Engine, die auf jedem VPS ab 512 MB RAM läuft. Der Docker-native Ansatz (jeder Step = eigener Container) sorgt für saubere Isolation ohne magische Build-Environments. Besonders für Teams, die bereits Gitea oder Forgejo betreiben, ist Woodpecker der logische nächste Schritt: OAuth-Integration, automatische Webhooks und eine übersichtliche Web-UI sind in unter 30 Minuten einsatzbereit. Wer mehr Buildkapazität benötigt, hängt einfach weitere Agents an – ohne Änderung am Server. Das macht Woodpecker zu einem ernsthaften, wartungsarmen CI/CD-Companion für KMU-Setups und Homelab-Infrastrukturen.
Weiterführende Anleitungen und Quellen
- Gitea mit Docker: eigener Git-Server als GitHub-Alternative
- Caddy als Reverse Proxy einrichten: Anfänger-Anleitung mit automatischem HTTPS
- Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only für den Produktivbetrieb
- 3-2-1-Backup-Strategie umsetzen: Anleitung mit Restic, USB-Disk und S3-Cloud
- Docker und Docker Compose auf Linux installieren (Ubuntu/Debian): die Self-Hosting-Grundlage
Offizielle Quellen: Woodpecker CI – Docker Compose Installation (offizielle Doku, v3/next) · Woodpecker CI – Releases auf GitHub · Forgejo-Forge-Integration (offizielle Doku)