Når skytjenesten sender regning: self-hosted CI på egen maskin

Skybasert CI/CD har to sider du ikke styrer selv: kvotene og prisen. Treffer bygget «rate limit exceeded» midt på natten, blir det stående. Deployen uteblir, og feilen testene skulle fanget, havner i produksjon. Samtidig betaler du per byggeminutt, også for tjenesten du ikke kunne stole på den natten.

Hvorfor self-hosted runner?

Kostnad er det enkleste argumentet. En skybasert CI-tjeneste fakturerer per byggeminutt, og for et aktivt team med mange daglige bygg løper det fort opp i titusener av kroner i året. En self-hosted runner i en LXC-container, eller på en gammel Dell med 16 GB RAM, koster ingenting i drift utover tiden det tar å sette den opp.

Det handler også om kontroll. Du velger selv hvilke versjoner av Node, Python, Docker eller Java som brukes, uten å vente på at tjenesten oppdaterer basebildet sitt. Du velger hvilke andre tjenester som kjører i samme miljø, for eksempel en lokal database for test. Og du slipper å være avhengig av en tredjeparts oppetid: selv 99,5 % betyr rundt tre og en halv time nedetid i måneden.

Hva du må tenke på

En self-hosted runner er et ansvar, ingen gratis snarvei.

  • Isoler den. En runner på samme server som produksjonen er en fare. Bruk LXC eller Docker, eller i det minste en egen bruker med begrenset tilgang.
  • Ikke kjør ukjente PR-er. En angriper kan sende inn kode som ser uskyldig ut, men som stjeler miljøvariabler eller legger inn bakdører. Sett runneren til å bare kjøre bygg fra eget repo eller godkjente bidragsytere.
  • Hold systemet oppdatert. En runner med gammel kjerne eller gammel Docker er et åpent mål. Bruk automatiske sikkerhetsoppdateringer, på Ubuntu unattended-upgrades.
  • Ikke lagre hemmeligheter lokalt. Bruk HashiCorp Vault, AWS Secrets Manager eller en kryptert fil i Git med git-crypt.

Slik kommer du i gang

  1. Velg maskin eller container. En LXC-container på en Proxmox-server du allerede har, er som regel raskest. Ellers en liten VM med 2 CPU og 4 GB RAM, eller en Raspberry Pi 4 med 8 GB for enkle bygg.
  2. Installer GitHub Actions runner etter den offisielle dokumentasjonen. Ikke kjør som root. Lag en egen bruker, for eksempel gh-runner.
  3. Kjør runneren som systemd-tjeneste. Runner-pakken har et skript for det:
    sudo ./svc.sh install gh-runner
    sudo ./svc.sh start
  4. Koble til GitHub. Gå til repoet, Settings, Actions, Runners, New self-hosted runner, og kopier kommandoen. Kjør den som gh-runner.
  5. Test med en enkel workflow. Lag en test.yml med bare ett echo "Hello"-steg, og sjekk at den kjører.
  6. Begrens hvem som får kjøre bygg. I GitHub: Settings, Actions, General, «Require approval for all outside collaborators».
  7. Sett opp logging og varsling. Følg med i journalctl -u actions.runner.* -f, eller send loggen til en intern ELK-stack. Få varsel hvis bygget feiler tre ganger på rad.

Deploy: hvordan runneren og produksjonen henger sammen

Runneren er også et naturlig sted å kjøre deploy. Etter vellykket bygg og test kjører steget deploy.sh, som kopierer bygget til produksjonsserveren over SSH med nøkler, kjører databasemigreringer, starter ny container og stopper den gamle bak en lastbalanserer.

Deploy-koden kjører på samme maskin som bygget, så miljøet er identisk. Da forsvinner «men på min maskin funket det».

Når er det ikke verdt det?

Har du ett team med én enkel app og ingen teknisk kompetanse internt, kan en god skytjeneste fortsatt være billigere i tid, selv om den er dyrere i penger.

En self-hosted runner lønner seg hvis du:

  • Kjører mange bygg om dagen, fra ti og oppover.
  • Har komplekse avhengigheter, som CUDA eller native moduler.
  • Har krav til datalokalitet, for eksempel av personvernhensyn.
  • Har en IT-avdeling som kan vedlikeholde den.

Har du prøvd skybasert CI og blitt skuffet over prisen, begrensningene eller stabiliteten? Ta kontakt, så setter vi opp en runner som passer situasjonen din.