Community
2
HostiServer
2026-08-13 09:47

GitHub Actions self-hosted runner: instalace a první pipeline na VPS

⏱️ Doba čtení: ~12 minut | 📅 Aktualizováno: srpen 2026

GitHub Actions self-hosted runner: instalace a první pipeline na VPS

Ve druhé části jsme rozebrali, jak je self-hosted runner uspořádaný: agent si vyzvedne úlohu z fronty platformy, provede ji na vašem serveru a vrátí logy a stav. Rozebrali jsme také, proč se agenta vyplatí přesunout na vlastní hardware a jak izolovat provádění kódu. Nyní se stejná architektura promění v konkrétní příkazy: vezmeme VPS, připojíme ho k repozitáři na GitHubu a dotáhneme celý řetězec až k funkčnímu nasazení do produkce.

Tato část je od začátku do konce praktická. Nejprve stručně o tom, jak je GitHub Actions poskládán, aby dál YAML dával smysl a nekopíroval se naslepo. Pak instalace agenta, zapouzdření jako systemd služby, první workflow, práce se secrets a kompletní pipeline, která po push do main sestaví projekt a nasadí ho na server přes SSH.

1.1 Co už máme a co bude dál

Minimum, ze kterého vycházíme:

  • repozitář na GitHubu, soukromý nebo interní pro organizaci;
  • VPS s Ubuntu 22.04 nebo 24.04, přístup přes SSH, samostatný uživatel bez práv root;
  • administrátorská práva k repozitáři: bez nich není stránka pro nastavení runnerů dostupná.

Agent nepotřebuje veřejnou adresu ani otevřené vstupní porty. Sám naváže spojení s GitHubem přes port 443 a drží ho, přičemž čeká na úlohu. To je důležitá vlastnost: runner lze umístit uvnitř uzavřené sítě, kam zvenčí není přístup vůbec, a přesto bude fungovat úplně stejně.

1.2 GitHub Actions: z čeho se skládá ekosystém

GitHub Actions je automatizační systém zabudovaný v GitHubu, spuštěný v roce 2019. Konfigurace žije přímo v repozitáři, v adresáři .github/workflows/: každý YAML soubor je samostatný workflow, který GitHub automaticky rozpozná bez jakékoli registrace v rozhraní.

Druhou částí ekosystému je Marketplace hotových akcí. Akce (action) je znovupoužitelný krok zabalený jako samostatný repozitář: actions/checkout naklonuje kód, actions/setup-node nainstaluje potřebnou verzi Node.js, docker/build-push-action sestaví a publikuje image. Místo desítky řádků bash v konfiguraci se objeví jeden řádek uses.

Pohodlí má i druhou stranu mince. Každá cizí akce je cizí kód, který se provádí ve vašem prostředí a vidí vaše secrets. Na self-hosted runneru je cena chyby vyšší než na jednorázovém cloudovém stroji: tento server vám žije dál. Praktické pravidlo je přišpendlit akce na plný commit hash místo tagu, přinejmenším u všeho, co nepatří organizacím actions a github:

# místo pohyblivého tagu
- uses: some-org/some-action@v3

# přišpendleno na konkrétní commit
- uses: some-org/some-action@8f4b7e2c9a1d3f5b6c8e0a2d4f6b8c0e2a4d6f8b # v3.1.0

ℹ️ Terminologie: GitHub Actions nemá stages jako samostatnou entitu, jako je má GitLab CI. Pořadí provádění se určuje závislostmi přes klíč needs. Pokud přicházíte z GitLabu, jde o hlavní rozdíl, na který si musíte zvyknout.

2. Architektura GitHub Actions

Před instalací agenta se vyplatí rozebrat tři úrovně, ve kterých se práce popisuje. Veškerý YAML dále v článku se opírá právě o ně.

2.1 Workflow → Job → Step

Workflow je jeden YAML soubor v .github/workflows/. Odpovídá na otázku „kdy se spustit" a „co udělat". Souborů může být libovolné množství: samostatné kontroly pro pull request, samostatné noční skenování závislostí, samostatný release podle tagu.

Job je úloha uvnitř workflow. Každá úloha dostane vlastní runner a vlastní čisté prostředí. Úlohy se ve výchozím stavu provádějí paralelně, pořadí se určuje přes needs. Důležitý důsledek: dvě úlohy nevidí navzájem své soubory, výměna probíhá přes artefakty.

Step je samostatný krok uvnitř úlohy. Kroky se provádějí postupně v jednom prostředí, takže soubory se mezi nimi předávají běžným způsobem. Krok existuje ve dvou typech: run pro shellové příkazy a uses pro hotovou akci.

workflow (soubor ci.yml)
├── job: build → runner č. 1, vlastní prostředí
│ ├── step: checkout
│ ├── step: npm ci
│ └── step: npm run build
└── job: deploy → runner č. 2, čisté prostředí
needs: build
├── step: download-artifact
└── step: ssh deploy

2.2 Triggery: kdy se workflow spustí

Triggery se popisují v sekci on. Čtyři hlavní:

  • push do určité větve nebo podle tagu. Základní trigger pro CI i pro release.
  • pull_request. Kontroluje výsledek sloučení ještě předtím, než k němu skutečně dojde. Právě na tento trigger se věší blokování sloučení, dokud kontroly neprojdou.
  • schedule. Spuštění podle rozvrhu v cron syntaxi, v časovém pásmu UTC. Vhodné pro noční běhy a denní skenování závislostí.
  • workflow_dispatch. Spuštění tlačítkem v rozhraní nebo voláním přes API, s volitelnými parametry. Je to ten samý ruční krok, který odlišuje Continuous Delivery od Continuous Deployment.
on:
push:
branches: [main]
paths-ignore:
- '**.md'
- 'docs/**'
pull_request:
branches: [main]
schedule:
- cron: '0 3 * * *' # denně v 03:00 UTC
workflow_dispatch:
inputs:
environment:
description: 'Kam nasadit'
type: choice
options: [staging, production]
default: staging

K rozvrhu existuje nuance, která ušetří hodiny pátrání: schedule funguje jen pro workflow ve výchozí větvi a spuštění se může opozdit o pár minut nebo posunout kvůli špičkovému zatížení. Pro přesný čas je potřeba externí plánovač, který přes API dere za workflow_dispatch.

2.3 GitHub-hosted a self-hosted runner: rozdíl v praxi

GitHub-hosted runner je virtuální stroj, který GitHub vytvoří pro každou úlohu a po ní zničí. Self-hosted runner je váš vlastní server s nainstalovaným agentem, který žije trvale. Rozdíl jde daleko za hranici toho, kdo platí za hardware.

Parametr GitHub-hosted Self-hosted
Životnost prostředí Čistý VM pro každou úlohu Trvalé, stav se hromadí
Zdroje Fixní podle tarifu Vaše, klidně GPU a stovky GB RAM
Platba Za minuty sestavení Za server, minuty se nepočítají
Předinstalovaný software Velký image s jazyky a utilitami Jen to, co jste nainstalovali sami
Přístup do uzavřené sítě Není Je, runner stojí uvnitř
Fronta ve špičce Možná Vlastní fronta, předvídatelný čas
Administrace Žádná Aktualizace, disk, izolace, monitoring

Srovnání GitHub-hosted a self-hosted runneru: dočasné čisté prostředí versus trvalý server pod vaší vlastní kontrolou

Řádek o trvalém prostředí je zároveň hlavní výhodou i hlavní pastí. Výhoda je v rychlosti: mezi sestaveními zůstává cache balíčků, vrstvy Dockeru, naklonovaný repozitář, takže druhé sestavení bývá často dvakrát rychlejší než první. Past je v tom, že zůstává i všechno ostatní: globálně nainstalované balíčky, dočasné soubory, zapomenuté proměnné prostředí, soukromý klíč, který předchozí úloha zapsala do domovského adresáře a zapomněla uklidit.

⚠️ Veřejné repozitáře: GitHub přímo nedoporučuje připojovat self-hosted runner k veřejnému repozitáři. Kdokoli může otevřít pull request a spolu s ním navrhnout změny ve workflow nebo v kódu, který tento workflow provádí. Na jednorázovém cloudovém stroji to skončí spolu s úlohou. Na vašem serveru získá cizí kód přístup ke všemu, co na něm leží, i k síti, ve které stojí. Pro open source zůstaňte u GitHub-hosted runnerů.

3. Instalace self-hosted runneru na VPS

Dál následuje postup, po kterém se agent objeví v seznamu runnerů se stavem Idle a přežije restart serveru.

3.1 Registrace na GitHubu a získání tokenu

Runner se připojuje na jedné ze tří úrovní:

  • Repozitář. Settings → Actions → Runners → New self-hosted runner. Nejjednodušší varianta pro prvního agenta.
  • Organizace. Stejná cesta v nastavení organizace. Jeden agent obsluhuje více repozitářů, přístup se odděluje skupinami runnerů.
  • Enterprise. Úroveň pro velké instalace, stejná logika.

Stránka rovnou zobrazí hotové příkazy pro zvolený OS a architekturu, s aktuální verzí agenta a kontrolním součtem. Kopírujte je odtamtud: verze se pravidelně aktualizuje a příkazy z cizího článku rychle zastarají.

⚠️ Registrační token žije zhruba hodinu. Pokud mezi zkopírováním a spuštěním config.sh uplyne víc času, konfigurace spadne s chybou autorizace. Řešení je jednoduché: obnovit stránku a vzít nový token. Tento token je potřeba jen pro připojení agenta, pro běžný provoz se nepoužívá.

3.2 Stažení a spuštění agenta

Všechny příkazy se provádějí pod běžným uživatelem, ne pod root. Agent se odmítne nakonfigurovat pod root, a to je správné chování: úlohy se provádějí s právy toho uživatele, pod kterým agent běží.

# samostatný systémový uživatel pro runner
sudo adduser --disabled-password --gecos "" runner
sudo usermod -aG docker runner # jen pokud sestavení používají Docker
sudo su - runner

mkdir -p ~/actions-runner && cd ~/actions-runner

# verzi a odkaz vezmeme ze stránky New self-hosted runner
RUNNER_VERSION=2.3xx.x
curl -o actions-runner.tar.gz -L \
https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz

# kontrola kontrolního součtu s tím, který ukázal GitHub
echo "<hash ze stránky> actions-runner.tar.gz" | shasum -a 256 -c

tar xzf ./actions-runner.tar.gz

Rozbalený adresář obsahuje config.sh pro připojení, run.sh pro spuštění, svc.sh pro zapouzdření jako služby a skript bin/installdependencies.sh, který doručí systémové knihovny potřebné pro .NET prostředí agenta. Poslední se spouští jednou a vyžaduje sudo.

sudo ./bin/installdependencies.sh

./config.sh \
--url https://github.com/OWNER/REPO \
--token <token ze stránky> \
--name vps-build-01 \
--labels self-hosted,linux,x64,build \
--work _work \
--unattended \
--replace

Co znamenají přepínače:

  • --name je jméno v seznamu runnerů. Dělejte ho smysluplné: až budete mít pět agentů, vps-build-01 se čte lépe než ubuntu-server.
  • --labels jsou štítky, podle kterých workflow vybírá agenta. Ke třem standardním (self-hosted, OS, architektura) přidávejte vlastní: build, deploy, gpu.
  • --unattended odstraní interaktivní dotazy, což je potřeba pro automatizaci přes Ansible nebo cloud-init.
  • --replace přepíše agenta se stejným jménem, pokud je už zaregistrovaný.

Spojení lze ověřit hned, na popředí:

./run.sh

# √ Connected to GitHub
# Listening for Jobs

V tuto chvíli se agent objeví v seznamu se stavem Idle. Zastavíme ho přes Ctrl+C a přejdeme ke službě.

3.3 Runner jako systemd služba

Spuštění přes run.sh žije přesně do zavření session. Pro trvalý provoz se agent zapouzdří jako služba a skript pro to už leží v adresáři:

sudo ./svc.sh install runner
sudo ./svc.sh start
sudo ./svc.sh status

Skript vytvoří unit s názvem typu actions.runner.OWNER-REPO.vps-build-01.service a zapne automatické spouštění. Dál se s ním pracuje běžnými prostředky systemd:

systemctl status 'actions.runner.*'
journalctl -u 'actions.runner.*' -f
sudo ./svc.sh stop
sudo ./svc.sh uninstall

Podrobné logy provádění úloh leží samostatně, v adresáři _diag uvnitř složky agenta. Vyplatí se tam nahlédnout, když úloha spadne bez srozumitelné zprávy v rozhraní GitHubu.

Dvě nastavení, která je lepší udělat hned:

  • Rotace pracovního adresáře. Adresář _work roste bez konce: každý repozitář, každý artefakt, každá cache. Jednou týdně ho čistěte podle rozvrhu nebo sledujte volné místo, protože docházející disk vypadá jako chaotické pády sestavení.
  • Automatické aktualizace. Agent se aktualizuje sám, jakmile GitHub vydá novou verzi. Pokud aktualizace mají probíhat jen ve vašem servisním okně, přidejte při konfiguraci --disableupdate a aktualizujte ručně. Počítejte s tím, že zastaralý agent časem přestane přijímat úlohy.

4. První workflow

Agent je připojený, teď mu dáme práci.

4.1 Struktura YAML souboru

Soubor se ukládá do .github/workflows/ci.yml a má tři povinné části: name pro zobrazení v rozhraní, on pro triggery, jobs pro samotnou práci.

name: CI

on:
push:
branches: [main]
pull_request:

jobs:
test:
runs-on: [self-hosted, linux, x64]
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm test

GitHub soubor automaticky rozpozná po push. Nikde ho není třeba registrovat a syntaktické chyby jsou vidět na záložce Actions hned po commitu.

4.2 runs-on: jak úloha najde vašeho agenta

runs-on je filtr podle štítků. Úloha půjde na agenta, který má všechny vyjmenované štítky:

# kterýkoli váš agent
runs-on: self-hosted

# jen linux x64 mezi vašimi
runs-on: [self-hosted, linux, x64]

# jen agent se štítkem gpu
runs-on: [self-hosted, linux, gpu]

# cloudový agent GitHubu
runs-on: ubuntu-latest

Pokud agent s potřebnou sadou štítků neexistuje nebo je offline, úloha nespadne, ale zařadí se do fronty a čeká. Ve výchozím stavu tam visí několik hodin, pak se zruší timeoutem. Toto je typická příčina situace „pipeline se spustil a nic se neděje": nekontrolujte logy, ale shodu štítků a stav agenta.

Štítky se vyplatí kombinovat se skupinami runnerů na úrovni organizace: skupina určuje, které repozitáře vůbec smí posílat úlohy na tohoto agenta, a štítky pak rozdělují úlohy v rámci povoleného.

4.3 Praktický příklad: checkout, závislosti, testy

Kompletní konfigurace s komentáři ke každému bloku:

name: CI

on:
push:
branches: [main]
pull_request:

# nové spuštění pro stejnou větev zruší předchozí
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

jobs:
test:
runs-on: [self-hosted, linux, x64]
timeout-minutes: 20
steps:
- name: Získat kód
uses: actions/checkout@v4

- name: Nastavit Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- name: Nainstalovat závislosti
run: npm ci

- name: Linter
run: npm run lint

- name: Testy
run: npm test -- --ci

- name: Uložit report
if: always()
uses: actions/upload-artifact@v4
with:
name: test-report
path: reports/
retention-days: 7

Tři detaily, které jsou na self-hosted runneru důležitější než na cloudovém:

  • timeout-minutes. Bez něj zaseklá úloha zabírá agenta na šest hodin a všechna další sestavení stojí ve frontě. Na vlastním agentovi to blokuje celý tým, protože náhradní stroj není.
  • concurrency. Ruší předchozí spuštění stejné větve. Když je agent jeden, odstraní to zbytečné běhy pro commity, které jsou už překryté novějšími.
  • if: always(). Krok se provede i po pádu předchozích. Pro uložení reportů je to nutné, protože zajímavý je právě report o neúspěšném běhu.

ℹ️ K setup-node a podobným akcím: na self-hosted runneru si cachují nainstalované verze v adresáři agenta, takže první spuštění je delší a další už téměř okamžité. Alternativou je nainstalovat potřebné verze do systému předem, ale pak se aktualizace verze přestane rovnat změně jednoho řádku v konfiguraci a vrátí se k ruční práci na serveru.

5. Secrets a proměnné

Pipeline téměř vždy potřebuje něco, co nelze uložit do repozitáře: SSH klíče, tokeny registru image, hesla do databáze. GitHub má pro to samostatné úložiště.

5.1 Kde se secrets ukládají

Cesta v rozhraní: Settings → Secrets and variables → Actions. Jsou tam dvě záložky. V Secrets leží hodnoty, které se v logách maskují a po uložení se zpětně nedají přečíst. Ve Variables leží běžná nastavení bez maskování: název větve, adresa staging serveru, verze image.

Secrets existují na třech úrovních:

Úroveň Kdo vidí Kdy zvolit
Repository Všechny workflow tohoto repozitáře Hodnota potřebná jen tomuto projektu
Organization Vybrané repozitáře organizace Sdílený token registru, klíč monitoringu
Environment Jen úlohy s odpovídajícím environment Produkční přístupy, které je třeba oddělit od zbytku

Maskování funguje na úrovni textu: pokud se hodnota secretu objeví ve výstupu, GitHub ji nahradí hvězdičkami. Ochrana není absolutní. Secret rozebraný na části, zakódovaný do base64 nebo vypsaný po znacích je v logách vidět celý. Kromě maskování proto platí běžné pravidlo minimálních práv: klíč, který umí jen nahrát soubory do adresáře a restartovat jednu službu, se nestane katastrofou ani po úniku.

5.2 Environment secrets pro staging a production

Environments (Settings → Environments) je nejužitečnější mechanismus v této kapitole. Dělá dvě věci najednou: drží vlastní sadu secrets a ukládá pravidla úlohám, které se na něj odkazují.

  • Required reviewers. Úloha se zastaví a čeká na potvrzení od konkrétní osoby. Je to ruční tlačítko Continuous Delivery, ale se jménem odpovědného v logách.
  • Deployment branches. Omezení, ze kterých větví lze nasazovat. Nastavte main pro production a náhodný deploy z experimentální větve se stane nemožným.
  • Wait timer. Pauza před provedením, během které lze deploy zrušit.
jobs:
deploy-staging:
runs-on: [self-hosted, linux, deploy]
environment: staging
steps:
- run: ./scripts/deploy.sh
env:
HOST: ${{ secrets.DEPLOY_HOST }} # hodnota z prostředí staging

deploy-production:
needs: deploy-staging
runs-on: [self-hosted, linux, deploy]
environment: production # čeká na potvrzení revizora
steps:
- run: ./scripts/deploy.sh
env:
HOST: ${{ secrets.DEPLOY_HOST }} # stejný název, jiná hodnota

Stejný název secretu ve dvou prostředích není náhoda, ale pohodlí: workflow zůstává jeden a rozdíl mezi prostředími drží GitHub.

5.3 Použití secrets ve workflow

Přístup probíhá přes kontext secrets:

steps:
- name: Správně: přes env
env:
API_TOKEN: ${{ secrets.API_TOKEN }}
run: ./scripts/publish.sh

- name: Nebezpečně: hodnota se dostane do příkazové řádky
run: ./scripts/publish.sh --token ${{ secrets.API_TOKEN }}

Rozdíl mezi dvěma kroky není kosmetický. Ve druhém případě se hodnota dosadí do řetězce příkazu ještě před spuštěním shellu, takže je vidět v ps na serveru a dostane se do historie shellu. Přes env se předává jako proměnná prostředí procesu, a to je znatelně užší plocha.

⚠️ Pull requesty z forků: pro takové běhy nejsou secrets ve výchozím stavu dostupné, a to je ochrana proti zjevnému útoku. Trigger pull_request_target tuto ochranu odstraní, protože provádí workflow v kontextu základní větve včetně secrets. Používejte ho jen s kódem základní větve a nikdy v něm nedělejte checkout kódu z forku.

6. Praktický příklad: deploy na server přes SSH

Dáme to všechno dohromady. Cíl: po push do main se projekt sestaví na runneru, artefakt odjede na produkční server, služba se restartuje.

6.1 Klíč pro deploy

Klíč se generuje samostatný, jen pro tuto úlohu, a nikdy se nepřekrývá s osobním klíčem inženýra:

ssh-keygen -t ed25519 -C "github-actions-deploy" -f ./gh_deploy -N ""

Na produkčním serveru vytvoříme uživatele bez práv root a přidáme mu veřejnou část s omezeními:

# na produkčním serveru
sudo adduser --disabled-password --gecos "" deploy
sudo install -o deploy -g deploy -m 700 -d /home/deploy/.ssh

# /home/deploy/.ssh/authorized_keys
from="203.0.113.10",no-agent-forwarding,no-port-forwarding,no-X11-forwarding,no-pty ssh-ed25519 AAAA... github-actions-deploy

Parametr from naváže klíč na adresu vašeho runneru: i s ukradeným soukromým klíčem se z jiného stroje přihlásit nepodaří. Práva na restart služby se udělují cíleně, přes sudoers, a ne plošným přístupem k sudo:

# /etc/sudoers.d/deploy
deploy ALL=(root) NOPASSWD: /bin/systemctl restart app.service

6.2 Secrets v repozitáři

Přidáme tři hodnoty do prostředí production:

  • SSH_PRIVATE_KEY je celý obsah souboru gh_deploy, včetně řádků BEGIN a END a koncového odřádkování.
  • SSH_KNOWN_HOSTS je výstup ssh-keyscan -H your-server.example.com.
  • DEPLOY_HOST je adresa serveru.

Druhý bod se často vynechává a nahrazuje se StrictHostKeyChecking=no. Takhle to dělat nevyplatí: tato volba vypíná kontrolu, která chrání před podvržením serveru, a její přítomnost v konfiguraci znamená, že deploy pojede kamkoli, kde odpoví přes SSH.

6.3 Kompletní workflow

name: Build and deploy

on:
push:
branches: [main]

concurrency:
group: deploy-production
cancel-in-progress: false

jobs:
build:
runs-on: [self-hosted, linux, x64, build]
timeout-minutes: 20
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- run: npm ci
- run: npm run lint
- run: npm test -- --ci
- run: npm run build

- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
retention-days: 7

deploy:
needs: build
runs-on: [self-hosted, linux, deploy]
environment: production
timeout-minutes: 10
steps:
- uses: actions/download-artifact@v4
with:
name: dist
path: dist/

- name: Připravit SSH
run: |
install -m 700 -d ~/.ssh
install -m 600 /dev/null ~/.ssh/deploy_key
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/deploy_key
echo "${{ secrets.SSH_KNOWN_HOSTS }}" > ~/.ssh/known_hosts

- name: Nahrát soubory
run: |
rsync -az --delete \
-e "ssh -i ~/.ssh/deploy_key" \
dist/ deploy@${{ secrets.DEPLOY_HOST }}:/var/www/app/

- name: Restartovat službu
run: |
ssh -i ~/.ssh/deploy_key deploy@${{ secrets.DEPLOY_HOST }} \
"sudo systemctl restart app.service"

- name: Ověřit, že služba naběhla
run: |
for i in $(seq 1 10); do
code=$(curl -s -o /dev/null -w "%{http_code}" https://app.example.com/health || true)
[ "$code" = "200" ] && exit 0
sleep 3
done
echo "Služba po deployi neodpovídá"
exit 1

- name: Uklidit klíč
if: always()
run: rm -f ~/.ssh/deploy_key

Schéma deploy přes SSH: runner sestaví projekt, zkopíruje soubory na produkční server a restartuje službu

Poslední krok s if: always() není formalita, ale přímý důsledek trvalého prostředí. Na cloudovém runneru stroj zmizí spolu s klíčem. Váš agent žije dál a soukromý klíč zapomenutý v domovském adresáři zůstane dostupný jakékoli další úloze, včetně té, která přijde z jiné větve.

Krok s kontrolou zdraví promění deploy na akci s ověřeným výsledkem. Bez něj workflow zezelená hned po restartu služby, i kdyby aplikace okamžitě spadla do crash-loopu, a o havárii se dozvíte od zákazníků.

ℹ️ Kdy SSH vůbec není potřeba: pokud runner stojí na stejném serveru jako aplikace, deploy se zredukuje na lokální kopírování souborů. Pokušení je pochopitelné, ale sestavení je zátěž na CPU, disk a paměť a bude konkurovat produkci v nejhorší možný moment. Funkční kompromis je samostatný stroj pro runner a privátní síť mezi ním a produkcí: sestavení je izolované a provoz deploye se nedostane do veřejného internetu.

7. Závěr

Self-hosted runner pro GitHub Actions se nainstaluje pár příkazy a hlavní práce začíná až po nich. Co si z této části odnést:

  • Agent nepotřebuje otevřené porty. Sám jde na GitHub přes port 443, takže klidně žije v uzavřené síti hned vedle produkce.
  • Štítky jsou směrovací mechanismus. runs-on hledá agenta se všemi vyjmenovanými štítky a úloha visící ve frontě téměř vždy znamená neshodu právě tady.
  • Trvalé prostředí zrychluje i hromadí. Cache mezi sestaveními je výhra, zapomenuté soubory a klíče jsou riziko. Úklid po sobě se stává součástí workflow.
  • Environments jsou důležitější než jednotlivé secrets. Environment s revizory a omezením větví dává jak oddělení přístupů, tak ruční krok před produkcí.
  • Deploy končí kontrolou. Zelený pipeline bez health-checku znamená jen to, že se provedly příkazy, ne že aplikace funguje.

Minimální funkční sada vypadá takto: samostatný uživatel pro agenta, systemd služba, štítky podle typu úloh, timeout-minutes v každé úloze, secrets v prostředí production a úklid klíčů v kroku s if: always().

Co bude dál v sérii

Ve čtvrté části uděláme totéž pro GitLab CI: nainstalujeme GitLab Runner na VPS, rozebereme executory (shell, docker, docker+machine) a projdeme cestu od prvního .gitlab-ci.yml až po deploy do produkce. Srovnání s GitHub Actions bude průběžné, protože architektonická rozhodnutí se tam liší výrazněji než syntaxe.

📚 Navigace v sérii:
Čtete část 3 ze 6 „GitHub Actions self-hosted runner: instalace a první pipeline na VPS".
Předchozí: ← Část 2. Self-hosted CI/CD: koncept, architektura a runnery
Další: Část 4. GitLab CI self-hosted runner: instalace a první pipeline na VPS →

🚀 VPS a dedikované servery pro vaše GitHub Actions runnery

Runner naráží na CPU během sestavení, na disk během instalace závislostí a na síť během deploye. Hostiserver pro to dává předvídatelné zdroje a síť, ze které lze bezpečně dosáhnout na produkci.

🖥️ Dedikované servery

  • Od $90/měsíc, plná kontrola nad hardwarem pro náročná a paralelní sestavení
  • NVMe úložiště: rychlá cache npm, Maven a Docker vrstev mezi běhy
  • Bez limitu minut sestavení: platíte za server, ne za čas pipeline
  • Privátní síť mezi runnerem a produkčními servery
  • Podpora 24/7: inženýři pomohou s nastavením agenta a deploye

💻 Cloud (VPS) hosting

  • Od $19.95/měsíc, KVM izolace, vyhrazené vCPU a RAM
  • Ideální pro prvního runnera: rozjet, připojit k repozitáři, vyzkoušet na reálném projektu
  • Snadné škálování: samostatný VPS pro build a samostatný pro deploy, s různými štítky

💬 Nejste si jistí, kterou variantu potřebujete?
💬 Napište nám a se vším pomůžeme!

Časté dotazy

Lze umístit runner na stejný server, kde běží produkce?

Technicky ano a pro malý projekt to funguje. Problém je v konkurenci o zdroje: sestavení sežere CPU a paměť přesně ve chvíli, kdy se nasazuje release, tedy v momentě největší zátěže aplikace. Druhý problém jsou práva: agent stojící vedle produkce obvykle dostane přístup k souborům aplikace a k restartu služeb, a spolu s ním tento přístup dostane jakýkoli kód, který se v pipeline provede. Kompromis je samostatný levný VPS pro runner a privátní síť do produkce.

Kolik zdrojů VPS potřebuje jeden runner?

Samotný agent spotřebuje v klidu zhruba 150-250 MB RAM, zbytek závisí na sestaveních. Pro typický webový projekt na Node.js nebo Pythonu stačí 2 vCPU a 4 GB RAM, pro sestavení s Dockerem je lepší 4 vCPU a 8 GB. Disk je důležitější, než se zdá: 40 GB je minimum, protože _work, cache balíčků a Docker vrstvy rostou rychle. Jeden agent provádí jednu úlohu najednou, takže pro paralelní sestavení buď přidáte další agenty, nebo vezmete výkonnější server.

Runner ukazuje stav Offline, přestože služba běží. Co zkontrolovat?

Nejprve logy: journalctl -u 'actions.runner.*' -n 100 a adresář _diag ve složce agenta. Nejčastější příčiny jsou blokování odchozích spojení na port 443 na github.com ze strany firewallu nebo firemní proxy, zastaralá verze agenta, kterou GitHub už nepřijímá, a docházející místo na disku. Samostatný případ je smazaný runner na straně GitHubu: agent dál běží, ale jeho token už není platný a pomůže jen opětovná konfigurace s novým tokenem.

Je bezpečné zapnout self-hosted runner ve veřejném repozitáři?

Ne, a GitHub na to přímo upozorňuje. Kdokoli může otevřít pull request a jeho kód se provede na vašem serveru. Prostředí je přitom trvalé, takže důsledky po dokončení úlohy nezmizí: zapomenutý proces, změněný systémový balíček, přečtené soubory z pracovního adresáře. Pro veřejné projekty berte GitHub-hosted runnery. Pokud tam vlastního agenta opravdu potřebujete, zůstává varianta s ephemeral agenty v jednorázových kontejnerech a povinným potvrzením spuštění pro externí přispěvatele.

Jak spustit více runnerů na jednom serveru?

Každý agent žije ve vlastním adresáři s vlastní konfigurací. Vytvoříte ~/actions-runner-1, ~/actions-runner-2, v každém spustíte config.sh s unikátním --name, pak svc.sh install. Vyjdou z toho dvě nezávislé systemd služby a dvě paralelní úlohy. Rozumná hranice je počet jader dělený dvěma: agenti soupeří o CPU a disk, a čtyři souběžná sestavení na dvoujádrovém VPS budou pomalejší než dvě po sobě.

Je potřeba actions/cache, když je prostředí stejně trvalé?

Většinou ne. Na trvalém agentovi zůstávají node_modules, adresář ~/.m2 nebo ~/.cache/pip mezi běhy, takže actions/cache přidává zbytečný cyklus nahrání a stažení přes síť GitHubu. Výjimkou je více agentů: sdílená cache pak vyrovná čas sestavení bez ohledu na to, kterému agentovi úloha připadla. Pro ephemeral agenty je cache povinná, protože prostředí je pokaždé nové.

Co dělat, když na runneru chybí potřebná verze jazyka nebo utility?

Dvě cesty. První jsou akce typu setup-node, setup-python, setup-java: samy stáhnou potřebnou verzi a cachují ji na agentovi, přičemž verze zůstává popsaná v repozitáři. Druhá je provádět kroky v kontejneru přes klíč container na úrovni úlohy, a pak je prostředí plně popsané image. Ruční instalace balíčků na serveru funguje také, ale vrací stejný problém, kterým jsme sérii začínali: prostředí zná jen ten, kdo ho nastavil.

Contents

Sdílejte tento článek

MANAGED VPS STARTING AT

$19 95 / mo

NEW INTEL XEON BASED SERVERS

$80 / mo

CDN STARTING AT

$0 / mo

 

Tento web používá cookies. Používáním tohoto webu souhlasíte s politikou ochrany osobních údajů.