I runner ospitati da GitHub sono un buon default. Smetti di averne bisogno nel momento in cui una build vuole qualcosa che non hanno — il tuo registry di pacchetti privato, una versione specifica di una toolchain che sei stanco di reinstallare a ogni run, un database sulla tua rete, o semplicemente più controllo sulla macchina. È allora che un runner self-hosted su un VPS si guadagna il posto.
Questa guida ne fa girare uno per bene: installato, registrato, vivo sotto systemd, e — la parte che la gente sbaglia — sicuro. Iniziamo da quest'ultima, perché è la parte che morde.
L'unica regola di sicurezza
Un workflow GitHub Actions esegue codice arbitrario — qualsiasi cosa sia nel file di workflow, e qualsiasi cosa quel codice tiri dentro. Sul tuo repo è il tuo codice, e va bene. Su un repo pubblico, una pull request da uno sconosciuto può eseguire il suo codice sul tuo runner. Non è un bug; è come funziona la CI. La documentazione di GitHub dice chiaramente: non usare runner self-hosted con repository pubblici.
Quindi la regola è semplice e non negoziabile: i runner self-hosted sono per repo privati. Se il tuo repo è pubblico, usa runner ospitati da GitHub e vai avanti. Tutto ciò che segue presume un repo privato.
Cosa serve al runner dalla macchina
Dipende dalla build, e dovresti dimensionare sulla tua invece che su un numero preso da una pagina:
- Un tipico job compila-e-testa — 2 core e 4-8 GB sono comodi. Small ($8, 4 vCPU / 4 GB) o Medium ($12, 6 vCPU / 6 GB) coprono la maggior parte di questi.
- Build più pesanti — grandi compilazioni native, build di grandi immagini Docker, suite di test affamate di memoria — vogliono più margine. Guarda un run reale (
htopmentre compila) e dimensiona su ciò che vedi davvero, non sulla speranza.
Anche il disco conta: cache di build, layer Docker e repo clonati si accumulano. Tienilo d'occhio e fai pruning.
1. Prepara la macchina
Crea un utente non-root per il runner — l'installer di GitHub si rifiuta comunque di girare come root, e lo vuoi così:
sudo adduser --disabled-password --gecos "" runner
sudo usermod -aG sudo runner # solo se le tue build hanno davvero bisogno di sudo
Installa qualsiasi cosa le tue build necessitino — una toolchain di linguaggio, Docker, build tools. Per esempio, se i tuoi job costruiscono container:
sudo apt update && sudo apt install -y docker.io
sudo usermod -aG docker runner
2. Scarica e registra il runner
Nel tuo repo (o org) su GitHub, vai su Settings → Actions → Runners → New self-hosted runner. GitHub ti dà i comandi esatti di download e un token di registrazione (è a breve durata — prendilo fresco). Come utente runner:
sudo -iu runner
mkdir actions-runner && cd actions-runner
# usa l'URL esatto che GitHub ti mostra per il tuo OS/arch:
curl -o actions-runner-linux-x64.tar.gz -L "URL_FROM_GITHUB"
tar xzf actions-runner-linux-x64.tar.gz
./config.sh --url https://github.com/YOUR_ORG/YOUR_REPO --token YOUR_TOKEN
config.sh chiede un nome del runner, delle label e una cartella di lavoro — i default vanno bene per iniziare. Le label sono il modo in cui il tuo workflow punta a questo runner (runs-on: self-hosted).
3. Fallo girare come servizio systemd
Il runner viene con un helper che installa un servizio systemd per te — usalo, così il runner sopravvive ai riavvii e si riavvia in caso di fallimento. Sempre dall'installazione dell'utente runner, ma i comandi del servizio richiedono root:
sudo ./svc.sh install runner
sudo ./svc.sh start
sudo ./svc.sh status
Questo registra actions.runner.* come unit systemd che gira come utente runner, avviandosi al boot. I log vanno a journald:
sudo journalctl -u 'actions.runner.*' -f
Tornando alla pagina Runners di GitHub, il tuo runner ora mostra Idle — punto verde. Punta un workflow su di esso:
jobs:
build:
runs-on: self-hosted
steps:
- uses: actions/checkout@v4
- run: make test
Fai push, e il job gira sulla tua macchina.
4. Tienilo pulito
Un runner self-hosted riusa il suo filesystem tra i job — è il guadagno di velocità (cache calde) e la trappola (stato residuo). Due abitudini lo tengono in salute:
- Fai pruning regolarmente. Docker specialmente —
docker system prunesu un cron, o il disco si riempie silenziosamente di layer morti. - Non conservare segreti sulla macchina. Usa i secret di GitHub Actions, iniettati per-run, non file che stanno nella home del runner. Se il runner viene compromesso, tutto ciò che è su disco se ne va con esso.
Se ti serve un ambiente davvero pulito per ogni job, esegui ciascun job dentro uno step in container — il runner resta, il disordine del job no.
Quando fare self-hosting, onestamente
Fai self-hosting quando ti serve la tua toolchain integrata, accesso a risorse di rete private, o controllo sulla macchina. Resta sui runner ospitati da GitHub quando un ambiente pulito e usa-e-getta e i loro minuti ti vanno bene — è genuinamente più semplice, e più semplice vale qualcosa. E mai, su un repo pubblico, fare self-hosting. Quello non è una preferenza.
Se un runner per repo privato è ciò che ti serve: scegli un piano — Small ($8) per build più leggere, Medium ($12) quando si fanno più pesanti — paga in USDC o USDT (no KYC, niente documenti), e avrai root in circa 60 secondi. Poi scorri questa pagina e avrai un runner che prende job qualche minuto dopo.
Commenti
Ancora nessun commento. Sii il primo.