
Configurare una pipeline CI/CD self-hosted non deve necessariamente passare per GitHub Actions o per un servizio cloud a pagamento.
Woodpecker CI è un motore di continuous integration open source, leggero e pensato per chi vuole mantenere il pieno controllo dei propri workflow di build e test direttamente sul proprio server, senza vincolarsi a un provider esterno.
In questa guida vedremo come installare e configurare Woodpecker CI da zero su una macchina con Ubuntu 26.04 LTS (“Resolute Raccoon”), usando Docker Compose per orchestrare server e agent.
Affiancheremo a Woodpecker un’istanza locale di Gitea, così da ottenere un ambiente di test completamente self-hosted, senza dover dipendere da GitHub o da altri forge esterni.
Passo dopo passo partiremo dall’installazione di Docker Engine, passeremo per la creazione dell’applicazione OAuth che permette a Woodpecker di autenticarsi su Gitea, fino ad arrivare alla prima pipeline di test eseguita con successo.
Lungo il percorso affronteremo anche alcuni degli inciampi più comuni in un setup di questo tipo permessi errati sui volumi Docker, file YAML danneggiati da un editor poco accorto, Client ID OAuth non corrispondenti perché conoscerli in anticipo fa risparmiare parecchio tempo di debug.
PREREQUISITI
- Serve un server (fisico, VPS o VM) con Ubuntu 26.04 LTS, accesso sudo.
- Un nome di dominio puntato al server è raccomandato per usare HTTPS, ma non obbligatorio per una prova locale.
AGGIORNAMENTO DEL SISTEMA E INSTALLAZIONE DI DOCKER
Il pacchetto docker-compose-plugin non si trova nei repository standard di Ubuntu insieme a docker.io: arriva solo dal repository ufficiale di Docker, che va aggiunto a parte. Installare quindi Docker Engine direttamente da lì (è anche il metodo raccomandato da Docker stesso, più aggiornato del docker.io di Ubuntu):
|
0 |
sudo apt update && sudo apt upgrade -y
|
# Prerequisiti
|
0 |
sudo apt install -y ca-certificates curl gnupg
|
# Chiave GPG del repository Docker
|
0
1
2
|
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
|
# Aggiungi il repository Docker (usa in automatico il codename della tua Ubuntu)
|
0
1
2
3
|
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
|
0
1
|
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
|
0
1
2
|
sudo systemctl enable --now docker
sudo usermod -aG docker $USER
newgrp docker
|
Verificare con i seguenti comandi:
|
0
1
|
docker --version
docker compose version
|
GENERAZIONE DEL SECRET CONDIVISO TRA SERVER E AGENT WOODPECKER
Eseguire il comando:
|
0 |
openssl rand -hex 32
|
Annotarsi il Secret:
607582cba2b3d4e2a89da7ad8b806e117f1a12fbe44f676ffe2c32372aed21c
Copiare il valore: lo utilizzeremo per WOODPECKER_AGENT_SECRET
CREAZIONE DELLA STRUTTURA DEL PROGETTO E IL FILE DOCKER COMPOSE
Creare la struttura del progetto e il file docker-compose con i comandi:
|
0
1
|
sudo mkdir -p /opt/woodpecker/gitea-data /opt/woodpecker/data
cd /opt/woodpecker
|
Creare il file docker-compose.yml con il comando:
|
0
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
42
43
44
45
46
47
48
49
50
51
52
|
sudo tee docker-compose.yml > /dev/null << 'EOF'
services:
gitea:
image: gitea/gitea:latest
container_name: gitea
restart: unless-stopped
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__server__ROOT_URL=http://SERVER_IP:3000/
- GITEA__server__HTTP_PORT=3000
- GITEA__webhook__ALLOWED_HOST_LIST=*
volumes:
- ./gitea-data:/data
ports:
- "3000:3000"
- "2222:22"
woodpecker-server:
image: woodpeckerci/woodpecker-server:v3
container_name: woodpecker-server
restart: unless-stopped
depends_on:
- gitea
ports:
- "8000:8000"
- "9000:9000"
volumes:
- ./data:/var/lib/woodpecker/
environment:
- WOODPECKER_HOST=http://SERVER_IP:8000
- WOODPECKER_AGENT_SECRET=IL_SECRET_GENERATO
- WOODPECKER_GITEA=true
- WOODPECKER_GITEA_URL=http://SERVER_IP:3000
- WOODPECKER_GITEA_CLIENT=DA_COMPILARE
- WOODPECKER_GITEA_SECRET=DA_COMPILARE
- WOODPECKER_ADMIN=DA_COMPILARE
woodpecker-agent:
image: woodpeckerci/woodpecker-agent:v3
container_name: woodpecker-agent
command: agent
restart: unless-stopped
depends_on:
- woodpecker-server
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- WOODPECKER_SERVER=woodpecker-server:9000
- WOODPECKER_AGENT_SECRET=IL_SECRET_GENERATO
- WOODPECKER_MAX_WORKFLOWS=2
- WOODPECKER_BACKEND=docker
EOF
|
Salvare e chiudere il filem di configurazione
ATTENZIONE: sostituire SERVER_IP e IL_SECRET_GENERATO con i tuoi valori; i campi WOODPECKER_GITEA_CLIENT/SECRET e WOODPECKER_ADMIN li completeremo dopo aver creato l’app OAuth in Gitea
AVVIO DI GITEA E CREAZIONE DELL’UTENTE AMMINISTRATORE
Per ora avviare solo Gitea con il comando:
|
0 |
sudo docker compose up -d gitea
|
Dovremmo visualizzare un putput simile al seguente:
|
0
1
2
3
|
[+] up 9/9
✔ Image gitea/gitea:latest Pulled 4.5s
✔ Network woodpecker_default Created 0.0s
✔ Container gitea Started
|
Aprire il browser su http://SERVER_IP:3000 comparirà la procedura guidata di installazione.
Lasciare tutti i valori predefiniti (usare SQLite, va benissimo per un uso locale/di test)
Nella sezione Impostazioni account amministratore creare il tuo utente admin (username, email, password).
Quindi cliccare Installare Gitea
Se è andato tutto a buon fine dovremmo visualizzare la Dashboard di Gitea
CREAZIONE DELL’APPLICAZIONE OAUTH IN GITEA PER WOODPECKER
Creare l’applicazione OAuth in Gitea per Woodpecker
Da amministratore andaree su http://SERVER_IP:3000/admin/settings/applications (oppure Impostazioni utente → Applicazioni se preferisci un’app a livello utente) e crea una nuova applicazione OAuth2:
Inserire le seguenti informazioni:
Nome applicazione: Woodpecker CI
Redirect URL: http://SERVER_IP:8000/authorize
Cliccare Crea Applicazione
Copiare le seguenti info:
Client ID: 3cf08282-49ff-46d4-9707-7bf6174ed82d
Client Secret: gto_66j26rf2li7vzqlkwdykedqpbt73ggnhpru4bz7rwjwebvisuyaa
Salva e copia il Client ID e il Client Secret mostrati (ATTENZIONE: il secret viene mostrato una sola volta).
Completa le tre variabili lasciate in sospeso nel file docker-compose.yml con sed:
|
0
1
2
3
|
cd /opt/woodpecker
sed -i 's/WOODPECKER_GITEA_CLIENT=DA_COMPILARE/WOODPECKER_GITEA_CLIENT=il-client-id-copiato/' docker-compose.yml
sed -i 's/WOODPECKER_GITEA_SECRET=DA_COMPILARE/WOODPECKER_GITEA_SECRET=il-client-secret-copiato/' docker-compose.yml
sed -i 's/WOODPECKER_ADMIN=DA_COMPILARE/WOODPECKER_ADMIN=il-tuo-username-gitea/' docker-compose.yml
|
Sostituire il-client-id-copiato, il-client-secret-copiato e il-tuo-username-gitea con i valori reali prima di eseguire i comandi.
AVVIO DI WOODPECKER (SERVER + AGENT)
Avviare Woodpecker con i seguenti comandi:
Posizionarsi nella cartella woodpcker con il comando:
|
0 |
cd /opt/woodpecker
|
Avviare Docker con il comando:
|
0 |
sudo docker compose up -d
|
Dovremmo visualizzare un output simile al seguente:
|
0
1
2
3
4
5
|
[+] up 13/14
✔ Image woodpeckerci/woodpecker-agent:v3 Pulled 3.6s
✔ Image woodpeckerci/woodpecker-server:v3 Pulled 4.0s
✔ Container gitea Started 1.0s
✔ Container woodpecker-server Started 0.4s
✔ Container woodpecker-agent Started
|
Fare la verifica con il comando:
|
0 |
sudo docker compose ps
|
Verificare i Log con il comando:
|
0 |
sudo docker compose logs -f woodpecker-server
|
ATTENZIONE: premere Ctrl+C per uscire dai log senza fermare i container.
PRIMO ACCESSO A WOODPECKER
Aprire da un qualsiasi browser il link http://SERVER_IP:8000
Cliccare Login e autorizzare l’accesso tramite il tuo account Gitea. Essendo l’utente indicato in WOODPECKER_ADMIN, sarai automaticamente amministratore di Woodpecker.
Se non dovesse mostrare la pagina di Login eseguire i comandi elencati di seguito:
|
0
1
2
3
4
5
6
7
8
|
cd /opt/woodpecker
sudo docker compose down
# assegna la cartella dati all'utente 1000 usato dal processo woodpecker-server nel container
sudo chown -R 1000:1000 /opt/woodpecker/data
sudo docker compose up -d
sudo docker compose logs -f woodpecker-server
|
Cliccare su Accedi a Woodpecker
Cliccare Autorizza Applicazione
Se è andato tutto a buon fine dovremmo visualizzare la Dashboard di Woodpecker come mostrato nell’ìimmagine sovrastante
CREAZIONE DI UN REPOSITORY DI TEST E COLLEGAMENTO ALLA PIPELINE
In Gitea (http://SERVER_IP:3000) creare un nuovo repository (es. test-ci) quindi clonarlo e aggiungere un file .woodpecker.yml.
Da browser: andare su http://192.168.80.34:3000 quindi fare login come admin cliccare sul + in alto a destra → Nuovo repository.
Nome: test-ci.
Spuntare Inizializza repository (così non è vuoto) e cliccare Crea Repository
Se è tutto OK dovremmo vedere una schermata come quella sovrastante
A questo punto da terminale eseguire i comandi elencati di seguito:
|
0 |
git clone http://192.168.80.34:3000/admin/test-ci.git
|
Dovremmo visualizzare il seguente output:
|
0
1
2
3
4
|
Cloning into 'test-ci'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
Receiving objects: 100% (3/3), done.
|
Quindi eseguire il comando:
|
0 |
cd test-ci
|
Creare il file YML con il comando:
|
0
1
2
3
4
5
6
|
cat > .woodpecker.yml << 'EOF'
steps:
- name: hello
image: alpine
commands:
- echo "Ciao da Woodpecker!"
EOF
|
Quindi eseguire i comandi:
|
0
1
2
3
4
|
git add .woodpecker.yml
git commit -m "Aggiunge pipeline di test"
git push
|
Collegarsi alla Dashboard di Woodpecker (http://SERVER_IP:8000)
Dalla dashboard di Woodpecker attivare il repository dalla lista cliccando su Aggiungi Repository
Cliccare Abilita
Cliccare Esegui Pipeline
COMANDI UTILI PER LA MANUTENZIONE
Di seguito una lista dei comandi utili per la manutenzione di Woodpecker
|
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
cd /opt/woodpecker
# Aggiornare tutte le immagini
sudo docker compose pull
sudo docker compose up -d
# Log dei singoli servizi
sudo docker compose logs -f gitea
sudo docker compose logs -f woodpecker-agent
# Fermare tutto
sudo docker compose down
|
PRO E CONTRO DI WOODPECKER CI
Prima di lanciarsi nell’installazione vale la pena capire dove Woodpecker CI si posiziona rispetto alle alternative più note come Jenkins, GitHub Actions o GitLab CI.
PRO
- Completamente self-hosted e open source (licenza AGPL v3): tutti i dati e le pipeline restano sulla propria infrastruttura, senza vendor lock-in e senza costi per utente o per minuto di build.
- Architettura leggera e container-first: ogni step è semplicemente “un’immagine Docker + un comando”, il che lo rende facile da capire, da eseguire anche su hardware modesto e da far girare in container/Kubernetes con buon isolamento.
- Supporto nativo a più forge: Gitea, Forgejo, GitHub, GitLab e Bitbucket, con integrazione OAuth2 e registrazione automatica dei webhook (come visto nella nostra configurazione con Gitea).
- Funzionalità pratiche integrate: pipeline multiple nella cartella .woodpecker/, cron job nativi senza bisogno di trigger esterni, supporto ad architetture ARM.
- Sviluppo attivo: nato come fork di Drone dopo il passaggio di quest’ultimo a una licenza BSL, riceve release e correzioni più frequenti rispetto al progetto originale.
- Sintassi delle pipeline quasi identica a Drone, il che rende la migrazione da Drone particolarmente semplice.
CONTRO
- Ecosistema di plugin più piccolo rispetto a GitHub Actions o GitLab CI: non esiste un marketplace ricco di integrazioni pronte all’uso, quindi spesso serve costruirsi il proprio step Docker.
- Nessuna offerta gestita (SaaS): a differenza di GitHub Actions o GitLab CI, non c’è un servizio cloud “pronto all’uso” — tutta la gestione operativa (aggiornamenti, backup, sicurezza) resta a carico di chi lo installa, come stiamo facendo in questa guida.
- Supporto solo community-driven: nessuna azienda dietro con SLA garantiti, a differenza per esempio di Drone (partnership con Harness). Documentazione e canali di supporto (Matrix, GitHub Issues) sono più piccoli rispetto a quelli di progetti più maturi.
- Gestione dei secret piuttosto basilare: manca il rotation automatico o l’integrazione nativa con strumenti come HashiCorp Vault, e i controlli di accesso sono granulari solo a livello di repository.
- Progetto relativamente giovane: essendo un fork di Drone, ha una storia più breve e una community più piccola rispetto a Jenkins o alle piattaforme CI dei grandi provider.
Per un uso personale, un piccolo team o un homelab proprio il caso della nostra installazione locale con Gitea questi limiti pesano poco a fronte dei vantaggi in termini di semplicità, controllo e costi.
Diventano invece un fattore da valutare con più attenzione in contesti enterprise con requisiti stringenti di compliance, supporto SLA o gestione avanzata dei segreti.

0 commenti