SSD Nodes Learn Hosting plans →
Mwongozo Matt ConnorNa Matt Connor · Imeboreshwa 2026-08-07

Jinsi ya kuweka GitHub Actions runner kwenye VPS

Jifunze kusajili self-hosted runner kwenye Ubuntu 24.04 kwa kutumia systemd. Mwongozo huu unaelezea hatua za usalama, uthibitishaji wa checksum, na hatari ya fork pull request.

Verified Every command ran end-to-end on a fresh Ubuntu 24.04 server, July 30, 2026.

Kazi ya self-hosted GitHub Actions runner

Self-hosted GitHub Actions runner ni programu unayoiweka kwenye VPS yako mwenyewe inayoomba kazi kutoka GitHub na kuziendesha kwenye maunzi yako. Unaisajili kwenye repository moja, unaifunga kama huduma ya systemd, na inajianzisha yenyewe baada ya kila reboot. GitHub hupanga kazi, na seva yako hufanya kazi hiyo.

CI (continuous integration) kwenye mashine unayomiliki ina faida kwa sababu mbili. Dakika za ujenzi (build minutes) hazipimwi tena, na kazi inaweza kufikia vitu ambavyo mashine yako pekee inavyo, kama cache ya ujenzi au mtandao wa ndani (private network). Bei yake ni usalama. Runner huendesha chochote kinachoandikwa kwenye faili ya workflow, kwa kutumia mtumiaji uliyempa ruhusa, hivyo faili ya workflow ni utekelezaji wa msimbo wa mbali (remote code execution) kwa usanifu wake. Kwenye repository ya faragha (private repository) hili ni sawa, kwa sababu watu unaowaamini pekee ndio wanaoweza kuongeza workflow. Kwenye repository ya umma (public repository), hili ni hatari halisi, na sehemu inayohusu fork pull requests inaelezea utaratibu huu.

Kila kitu hapa chini ni kwa ajili ya Ubuntu 24.04 na toleo la runner 2.336.0, ambalo ndilo toleo la sasa kufikia Julai 2026.

Unachohitaji kabla ya kuanza

Anza na VPS yenye akaunti ya kawaida ya admin na sudo, hali unayofikia katika dakika kumi za kwanza kwenye VPS mpya. Huhitaji kufungua port yoyote ya kuingia (inbound). Runner hufungua muunganisho wa kutoka (outbound) wa HTTPS (hypertext transfer protocol secure) kuelekea GitHub na kuudumisha ukiwa wazi wakati ikisubiri kazi, kwa hivyo GitHub haiunganishi kamwe na seva yako. Firewall yako inaweza kubaki imefungwa kwa ulimwengu na kazi bado zitafika.

Pia unahitaji haki za admin kwenye repository, kwa sababu token ya usajili huonyeshwa kwenye mipangilio ya repository.

Unda mtumiaji maalum kwa ajili ya runner

Usiwahi kuendesha runner kama root au kama mtumiaji wako wa admin. Kila kazi hurithi haki za mtumiaji wa runner, kwa hivyo workflow inayotumia sudo hufanikiwa ikiwa mtumiaji wa runner anaweza kutumia sudo. Unda mtumiaji mmoja asiye na upendeleo ambaye hamiliki chochote isipokuwa saraka yake ya nyumbani (home directory). Akaunti za watumiaji zenye upendeleo mdogo kwenye VPS inaelezea muundo wa jumla. Hapa kuna muundo maalum.

sudo useradd -m -s /bin/bash gharunner
sudo passwd -l gharunner
sudo chmod 750 /home/gharunner
sudo install -d -m 700 -o gharunner -g gharunner /home/gharunner/actions-runner

passwd -l hufunga nenosiri, ili hakuna mtu anayeweza kuingia kama gharunner kwa kutumia nenosiri. Mode 700 kwenye saraka ya runner ni muhimu kwa sababu runner huhifadhi vitambulisho vyake hapo katika mfumo wa maandishi wazi (cleartext), na checkout inaweza kuwa na source ya siri.

Kagua sifa zote mbili kabla ya kuendelea:

sudo passwd -S gharunner
sudo -l -U gharunner

passwd -S huchapisha mstari unaoanza na gharunner L, ambapo L inamaanisha nenosiri limefungwa. sudo -l -U gharunner inapaswa kujibu na is not allowed to run sudo. Ikiwa inachapisha orodha ya amri zinazoruhusiwa badala yake, akaunti hiyo iko kwenye kundi la sudo na kutengwa (isolation) uliyojenga hivi punde kumepotea.

Pakua runner na uhakiki tarball

Fanya kazi kama mtumiaji runner kuanzia hapa.

sudo -iu gharunner
cd ~/actions-runner
RUNNER_VERSION=2.336.0
curl -fL -o actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz \
  "https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz"

Tekeleza uname -m kwanza ikiwa huna uhakika na usanifu (architecture) wa mfumo wako. x86_64 hutumia faili la linux-x64 hapo juu. aarch64 hutumia actions-runner-linux-arm64-${RUNNER_VERSION}.tar.gz.

Sasa hakiki ulichopakua. SHA256 (secure hash algorithm, 256 bit) hapa chini ni kwa ajili ya tarball ya 2.336.0 x64. GitHub huchapisha thamani ya toleo la sasa kwenye ukurasa wa releases na kwenye skrini ya New self-hosted runner. Thamani hii hubadilika kila toleo jipya, kwa hivyo nakili kutoka hapo unapoweka toleo tofauti.

echo "04cf0be1aff4c3ec3554466c39124ca250e3effd8873bb7e8d68535aa9505d5d  actions-runner-linux-x64-2.336.0.tar.gz" | sha256sum -c

Upakuaji uliofanikiwa huchapisha mstari mmoja:

actions-runner-linux-x64-2.336.0.tar.gz: OK

Faili lililoharibika au kubadilishwa huchapisha hitilafu na onyo:

actions-runner-linux-x64-2.336.0.tar.gz: FAILED
sha256sum: WARNING: 1 computed checksum did NOT match

Usiruke hatua hii ya uhakiki na kumwacha tar atafute tatizo hilo baadaye. Kumbukumbu (archive) iliyoandikwa nusu hushindwa na gzip: stdin: unexpected end of file na tar: Unexpected EOF in archive, ambayo hukuambia kuwa faili limeharibika lakini haikwambii kama limekatwa katikati au limebadilishwa.

tar xzf ./actions-runner-linux-x64-2.336.0.tar.gz
ls

Yaliyomo kwenye tarball na yale yasiyokuwemo

Baada ya kutoa faili, saraka hiyo ina config.sh, run.sh, env.sh, safe_sleep.sh, bin/ na externals/. bin/ ina binaries za runner na bin/installdependencies.sh. externals/ ina Node runtime iliyounganishwa ambayo hatua za JavaScript hutekelezwa juu yake.

Hakuna svc.sh bado. Nyaraka za GitHub zinaielezea kama hati "inayoundwa baada ya kuongeza runner kwa mafanikio", kwa sababu imeandikwa kutoka kwenye kiolezo chenye jina la hazina yako na jina la runner yakiwa yameingizwa kwenye jina la huduma. Kwa hivyo sudo ./svc.sh install kabla ya ./config.sh inashindwa na kutoa sudo: ./svc.sh: command not found. Sajili kwanza, kisha usakinishe huduma.

Sakinisha vitegemezi vya runner

Runner ni programu ya .NET, kwa hivyo inahitaji maktaba kadhaa zilizoshirikiwa. Ondoka kwenye shell ya mtumiaji wa runner na uzisakinishe kwa kutumia sudo, kwa sababu hati hiyo huandika kwenye hifadhidata ya vifurushi vya mfumo.

exit
cd /home/gharunner/actions-runner
sudo ./bin/installdependencies.sh

Kwenye Ubuntu 24.04, hatua hiyo huvuta libkrb5-3, zlib1g, liblttng-ust1t64, libssl3t64 na libicu74. Hati hiyo hujaribu majina kadhaa ya matoleo kwa kila maktaba na kuhifadhi lile ambalo toleo lako la mfumo linatoa, ndiyo maana hati hiyo hiyo hufanya kazi kwenye Ubuntu ya zamani na kwenye Debian.

Ruka hatua hii na ./config.sh itasimama kabla ya kufanya chochote:

Dependencies is missing for Dotnet Core 6.0
Execute sudo ./bin/installdependencies.sh to install any missing Dotnet Core 6.0 dependencies.

Kukosekana kwa libicu hutoa ushauri uleule chini ya mstari wa kwanza tofauti, Libicu's dependencies is missing for Dotnet Core 6.0. Yote mawili yanatoka mahali pamoja: config.sh huendesha ldd dhidi ya maktaba zilizounganishwa kabla ya kuanza, kwa hivyo kiungo kisichotatuliwa husimamisha hati badala ya kusababisha ajali ya kutatanisha baadaye.

Jisajili kama runner kwenye hazina yako

Pata token kutoka kwenye hazina. Fungua Settings, kisha Actions, kisha Runners, kisha New self-hosted runner. Ukurasa huo unaonyesha token ya usajili inayoanza na A. Token hiyo huisha muda wake saa moja baada ya kutengenezwa, kwa hivyo itengeneze ukiwa tayari kuibandika.

Jisajili kama mtumiaji wa runner. config.sh hukataa kufanya kazi chini ya sudo.

sudo -iu gharunner
cd ~/actions-runner
./config.sh --url https://github.com/YOUR-USER/YOUR-REPO \
  --token PASTE_REGISTRATION_TOKEN_HERE \
  --name vps-runner-1 \
  --labels vps \
  --work _work \
  --unattended \
  --replace

Kazi za flag hizo. --name ndilo jina ambalo runner atatumia kwenye hazina, kwa hivyo chagua jina ambalo utalikumbuka hata baada ya miezi sita. --labels huongeza lebo zako mwenyewe; runner tayari anazo self-hosted, Linux na X64 bila kuombwa. --work hupa jina saraka ambapo checkouts huwekwa, ndani ya saraka ya runner. --unattended hujibu maombi ya maingiliano kwa kutumia chaguo-msingi, jambo ambalo ni muhimu wakati amri hiyo inapoendeshwa ndani ya script. --replace huchukua nafasi ya usajili uliopo wenye jina lilelile badala ya kufeli, jambo ambalo ni muhimu unapojenga upya seva.

Uendeshaji uliofanikiwa huishia na mistari hii:

√ Runner successfully added
√ Runner connection is good
√ Settings Saved.

Usajili sasa unapatikana ndani ya saraka ya runner kama .runner, .credentials na .credentials_rsaparams. Faili mbili za mwisho humtambulisha runner huyu kwa GitHub, kwa hivyo yeyote anayeweza kuzisoma anaweza kujifanya kuwa yeye. Hiyo ndiyo sababu saraka hiyo ina mode 700 na mtumiaji hana sudo.

Sakinisha runner kama huduma ya systemd

./run.sh katika terminal inafaa kwa jaribio moja, lakini inakufa pale unapofunga session yako ya SSH. Sakinisha huduma hii ili runner ianze kuwaka wakati wa boot. systemd services and timers on a VPS inaelezea faili za unit zenyewe. Hapa svc.sh inakuandikia moja.

exit
cd /home/gharunner/actions-runner
sudo ./svc.sh install gharunner
sudo ./svc.sh start
sudo ./svc.sh status

svc.sh inahitaji root kwa sababu inaandika unit ndani ya /etc/systemd/system na kuiwezesha. Hoja inayofuata install ni mtumiaji ambaye huduma hiyo itatumia kufanya kazi. Pitisha gharunner kwa uwazi. Bila hoja yoyote, script inarudi kwenye $SUDO_USER, ambayo ni akaunti yako ya admin, na kisha kila kazi itafanyika kama mtumiaji anayeweza kutumia sudo.

Unit hiyo hupewa jina kulingana na repository na runner, kwa muundo wa actions.runner.YOUR-USER-YOUR-REPO.vps-runner-1.service. Huna haja ya kuandika jina hilo:

systemctl list-units 'actions.runner.*'
sudo journalctl -u 'actions.runner.*' -n 20 --no-pager

Runner iliyo katika hali nzuri hutoa log ya √ Connected to GitHub na kisha mstari unaoishia na Listening for Jobs, na ukurasa wa Runners wa repository hiyo huionyesha kama Idle. Runner inayoonekana kama Offline aidha haifanyi kazi au haiwezi kufikia GitHub kupitia port 443.

Tuma kazi kwa runner

runs-on huchagua runner kwa kutumia lebo. Omba self-hosted pamoja na lebo yako mwenyewe, ili kazi isitue kwenye runner ambayo hukuikusudia.

name: build
on:
  push:
    branches: [main]
jobs:
  build:
    runs-on: [self-hosted, linux, vps]
    steps:
      - uses: actions/checkout@v5
      - run: uname -a

Ikiwa kazi inasubiri kwenye Waiting for a runner to pick up this job, lebo hazilingani. Kila lebo iliyo kwenye runs-on lazima iwepo kwenye runner, kwa hivyo neno moja la ziada litaacha kazi ikiwa kwenye foleni bila kutoa kosa lolote. Linganisha orodha hiyo na lebo zinazoonyeshwa kando ya runner katika mipangilio ya repository.

Kwa nini self-hosted runners na public repositories haviendani

Hii ndiyo sehemu ambayo watu huiruka. Mwongozo wa GitHub uko wazi: self-hosted runners "karibu kamwe hazipaswi kutumiwa kwa public repositories", na "hazina uhakika wa kuendeshwa kwenye ephemeral clean virtual machines, na zinaweza kuathiriwa (compromised) kwa kudumu na code isiyoaminika iliyo kwenye workflow".

Utaratibu huu ni rahisi. Pull request kutoka kwenye fork huleta nakala yake ya faili ya workflow. Ikiwa public repository yako inaendesha workflow za pull request kwenye runner yako, basi yeyote anayeweza kufanya fork ya repository hiyo anaweza kupendekeza workflow inayoendesha amri zake kwenye VPS yako. Hawahitaji access ya kuandika (write access), kwa sababu kitu wanachopendekeza ndicho kinachoendesha.

Mipangilio ya idhini (approval settings) hupunguza hatari hii bila kuiondoa. Sera ya kawaida ya public repository humtaka maintainer kuidhinisha workflow ya fork ya mchangiaji wa mara ya kwanza. Baada ya kumuidhinisha mtu huyo mara moja, pull request zake za baadaye huendeshwa bila ombi jipya. Kwa hivyo, kizuizi hapa ni binadamu kusoma diff, kila wakati, na payload iliyofichwa ndani ya script ya build ni rahisi kuikosa.

Fork pull request haipokei siri (secrets) zako, na GITHUB_TOKEN yake ni ya kusoma tu (read only). Hilo hupunguza uharibifu ndani ya GitHub. Halisaidii chochote kwa seva yako. Mshambuliaji ana shell kama gharunner, kwa hivyo anaweza kusoma kila faili ambayo mtumiaji huyo anaweza kuisoma, kufikia chochote ambacho VPS inaweza kukifikia kwenye mtandao wake wa ndani, na kuacha kitu nyuma kwenye ~/.bashrc au systemd unit ya mtumiaji inayoendeshwa wakati wa job inayofuata.

Kujisajili na --ephemeral hufanya runner ikubali job moja kisha ijiondoe kwenye usajili, kwa hivyo job moja haiwezi kusoma workspace ya job inayofuata. Hii husaidia tu ikiwa kitu fulani kitajenga upya mashine au container kwa kila job, kwa sababu backdoor iliyoandikwa kwenye home directory ya mtumiaji wa runner huendelea kuwepo hata baada ya usajili mpya.

Kanuni zinazofuata ni fupi. Tumia self-hosted runners kwa private repositories. Ikiwa lazima uunganishe moja na public repository, usiendeshe fork pull requests juu yake, usiweke kitu kingine chochote kwenye seva hiyo, na ichukulie mashine hiyo kama kitu kinachoweza kutupwa (disposable).

Kazi za Docker, na kundi ambalo ni root halisi

Kazi za container, service containers, na hatua yoyote ya workflow inayotumia docker build inahitaji Docker daemon kwenye host ya runner. Sakinisha Docker kwa njia ya kawaida, ambayo Docker na Docker Compose kwenye VPS inaelezea, kisha ongeza mtumiaji wa runner kwenye kundi la docker.

Elewa athari kabla ya kufanya hivyo. Uanachama wa kundi la docker ni sawa na kuwa root, kwa sababu container inaweza kufanya bind mount ya / na kuendesha kama root ndani yake. Kwa hivyo, workflow inayoweza kuwasiliana na Docker socket inaweza kusoma na kuandika kila faili kwenye VPS, ikiwemo /etc/shadow. Kwenye repository ya faragha yenye wachangiaji wanaoaminika, hii inaweza kuwa gharama inayokubalika. Mahali pengine popote, hii huondoa maana ya kutumia mtumiaji asiye na upendeleo (unprivileged user). Rootless Docker huweka ujenzi wa container ndani ya haki za mtumiaji wa runner mwenyewe, kwa gharama ya storage driver ya polepole na kutokuwa na uwezo wa kutumia privileged containers.

Masasisho, na kuondoa runner kwa usafi

Runner inayojiendesha yenyewe (self-hosted runner) hujisasisha yenyewe kwa chaguo-msingi. Inapogundua toleo jipya, inajichukulia faili zake na kuanzisha upya huduma, kwa hivyo kwa kawaida huhitaji kufanya lolote. ./config.sh --disableupdate huzima sasisho la kiotomatiki unapohitaji toleo lisilobadilika. Baada ya hapo, kusasisha ni jukumu lako: nyaraka za GitHub zinasema wazi kuwa runner iliyosanidiwa kwa --disableupdate lazima isasishwe kwa mkono.

Sasisho la mwongozo hudumisha usajili, kwa sababu .runner na .credentials havimo kwenye tarball. Simamisha huduma, pakua na uhakiki checksum ya tarball mpya kama gharunner, itoe kwenye saraka ileile kwa tar xzf, kisha anzisha huduma tena:

cd /home/gharunner/actions-runner
sudo ./svc.sh stop
sudo ./svc.sh start

Ili kuondoa runner, ondoa huduma kwanza, kisha uifute usajili. Token ya kuondoa inapatikana kutoka kwenye ukurasa uleule wa Runners, chini ya kitufe cha Remove cha runner husika.

cd /home/gharunner/actions-runner
sudo ./svc.sh stop
sudo ./svc.sh uninstall
sudo -iu gharunner
cd ~/actions-runner
./config.sh remove --token PASTE_REMOVAL_TOKEN_HERE

Kufuta saraka bila kufuta usajili kutaiacha runner ikiwa imeorodheshwa kama Offline kwenye hazina, kwa sababu GitHub hujua kuwa imeondoka pale tu runner inapotoa taarifa au msimamizi anapofuta ingizo hilo kwa mkono.

Njia za kushindwa, pamoja na ujumbe utakaouona

Must not run with sudo. config.sh huchapisha ujumbe huu na kusimama inapoendeshwa kama root. Ukaguzi huu ni wa makusudi, kwa sababu faili zinazomilikiwa na root ndani ya _work huharibu kila kazi inayofuata inayoendeshwa kama mtumiaji wa huduma (service user). Endesha ./config.sh kama gharunner. Variable ya RUNNER_ALLOW_RUNASROOT hupuuza ukaguzi huu, na kuitumia kutasogeza tu tatizo mbele.

sudo: ./svc.sh: command not found. Upo kwenye saraka sahihi. svc.sh haipo bado, kwa sababu config.sh haijakamilisha usajili. Sajili runner, kisha sakinisha huduma.

Http response code: NotFound from 'POST https://api.github.com/actions/runner-registration'. Token hii si token halali ya usajili. Aidha muda wake umeisha, kwa kuwa hudumu kwa saa moja, au personal access token iliwekwa badala ya token ya usajili kutoka ukurasa wa Runners. Tengeneza token mpya na uiweke tena.

Dependencies is missing for Dotnet Core 6.0. Endesha sudo ./bin/installdependencies.sh kutoka kwenye saraka ya runner kama root, kisha sajili tena.

Runner iko Offline baada ya reboot. Endesha systemctl is-enabled 'actions.runner.*'. Ikiwa hakuna kinachoonekana, ./svc.sh install haikuwahi kuendeshwa, kwa hivyo runner iliwepo tu ndani ya terminal session yako. Ikiwa unit imewezeshwa na runner bado iko Offline, soma journalctl -u 'actions.runner.*' na uangalie mawasiliano ya HTTPS ya kutoka nje (outbound).

Diski kujaa. Checkouts, build caches na Docker images hujilimbikiza chini ya _work na kwenye home directory ya mtumiaji wa runner, na hakuna kinachozifuta kwa ajili yako. Fuatilia du -sh /home/gharunner/actions-runner/_work na uweke utaratibu wa kusafisha (scheduled clean-up) kabla diski haijajiamulia yenyewe.

FAQ

Kwa nini sudo ./svc.sh install inasema command not found?

Kwa sababu svc.sh haipo kwenye tarball ya runner. Inatengenezwa ndani ya saraka ya runner wakati ./config.sh inapomaliza kujiandikisha, ikitumia jina la repository yako na jina la runner ili kuunda jina la huduma. Endesha ./config.sh kama mtumiaji wa runner kwanza. Baada ya hapo, sudo ./svc.sh install gharunner itapata script hiyo na kuandika unit inayoitwa actions.runner.OWNER-REPO.RUNNER-NAME.service ndani ya /etc/systemd/system.

Je, nahitaji kufungua port ya firewall kwa ajili ya self-hosted runner?

Hapana. Runner hufungua muunganisho wa HTTPS wa kutoka nje (outbound) kuelekea GitHub na kuushikilia ukiwa wazi wakati inasubiri kazi, kwa hivyo GitHub haianzishi muunganisho kuelekea VPS yako. Ruhusu trafiki ya kutoka nje kwenye port 443 na uache sheria zako za kuingia ndani (inbound) zikiwa zimefungwa. Ikiwa runner inaonyesha Offline wakati huduma yake inaendelea, angalia uchujaji wa trafiki ya kutoka nje na DNS badala ya sheria za kuingia ndani.

Je, ninaweza kutumia self-hosted runner kwenye repository ya umma?

Unaweza, lakini GitHub inashauri kutofanya hivyo. Pull request kutoka kwa fork hubeba faili lake la workflow, kwa hivyo mtu yeyote anayeweza kufanya fork ya repository yako anaweza kupendekeza amri zinazoendeshwa kwenye mashine yako. Kidokezo cha idhini kinashughulikia tu mara ya kwanza ya mchangiaji. Ikiwa utaunganisha runner kwenye repository ya umma, zima workflow za pull request za fork kwenye runner hiyo, usiweke kitu kingine chochote kwenye seva hiyo, na ujenge upya mashine hiyo mara kwa mara kulingana na ratiba.

Kwa nini usajili unashindwa na Http response code: NotFound?

Wito wa usajili hujibu NotFound wakati kitambulisho (credential) si sahihi, si tu wakati URL si sahihi, jambo ambalo hufanya ujumbe huo kupotosha. Tokeni za usajili huisha muda wake saa moja baada ya kuonyeshwa, na personal access token haikubaliki kwa wito huu. Fungua Settings, Actions, Runners, New self-hosted runner tena, nakili tokeni mpya, na uthibitishe kuwa thamani ya --url inaelekeza kwenye repository ambapo una haki za admin.

#github-actions#ci#self-hosted#runner#ubuntu-24-04