Раннери GitHub-hosted — нормальний дефолт. Вони перестають бути потрібні в момент, коли збірці потрібне те, чого в них немає: ваш приватний реєстр пакетів, конкретна версія тулчейну, яку набридло перевстановлювати щопрогону, база у вашій мережі або просто більше контролю над машиною. Ось тоді self-hosted раннер на VPS виправдовує себе.
Цей гайд піднімає його як слід: встановлений, зареєстрований, живий під systemd і — та частина, у якій помиляються, — безпечний. Почнемо з останнього, бо саме це кусається.
Єдине правило безпеки
Воркфлоу GitHub Actions виконує довільний код — усе, що у файлі воркфлоу, і все, що цей код тягне. На вашому репо це ваш код, і все нормально. На публічному репо pull request від чужинця може виконати його код на вашому раннері. Це не баг; так влаштований CI. Документація GitHub прямо каже: не використовуйте self-hosted раннери з публічними репозиторіями.
Тож правило просте і без винятків: self-hosted раннери — для приватних репо. Якщо репозиторій публічний, використовуйте GitHub-hosted раннери і не думайте. Усе нижче припускає приватний репозиторій.
Що раннеру потрібно від машини
Залежить від збірки, і рахувати треба під свою, а не за цифрою зі сторінки:
- Типова задача «зібрати і протестувати» — 2 ядра і 4-8 ГБ комфортні. Small ($8, 4 vCPU / 4 ГБ) або Medium ($12, 6 vCPU / 6 ГБ) покривають більшість.
- Важкі збірки — велика нативна компіляція, збірка великих Docker-образів, ненажерливі тест-сьюти — просять більше запасу. Подивіться один реальний прогін (
htopпід час збірки) і рахуйте за тим, що реально бачите, а не за надією.
Диск теж важить: кеші збірки, шари Docker і склоновані репо накопичуються. Тримайте на оці й чистіть.
1. Підготувати машину
Створіть не-root користувача для раннера — інсталятор GitHub усе одно відмовиться працювати під root, і це правильно:
sudo adduser --disabled-password --gecos "" runner
sudo usermod -aG sudo runner # лише якщо збіркам реально потрібен sudo
Поставте те, що потрібно збіркам — тулчейн мови, Docker, інструменти збірки. Наприклад, якщо задачі збирають контейнери:
sudo apt update && sudo apt install -y docker.io
sudo usermod -aG docker runner
2. Завантажити й зареєструвати раннер
У вашому репо (чи організації) на GitHub зайдіть у Settings → Actions → Runners → New self-hosted runner. GitHub видасть точні команди завантаження і токен реєстрації (він короткоживучий — беріть свіжий). Під користувачем runner:
sudo -iu runner
mkdir actions-runner && cd actions-runner
# використайте точний URL, який GitHub показав під вашу ОС/архітектуру:
curl -o actions-runner-linux-x64.tar.gz -L "URL_ВІД_GITHUB"
tar xzf actions-runner-linux-x64.tar.gz
./config.sh --url https://github.com/ВАША_ORG/ВАШ_REPO --token ВАШ_ТОКЕН
config.sh спитає імʼя раннера, мітки і робочу папку — для старту дефолти підійдуть. Мітки — те, як воркфлоу націлюється на цей раннер (runs-on: self-hosted).
3. Запустити як сервіс systemd
Раннер іде з помічником, що ставить сервіс systemd за вас — використайте його, щоб раннер переживав перезавантаження і рестартував при падінні. Усе під встановленням користувача runner, але команди сервісу вимагають root:
sudo ./svc.sh install runner
sudo ./svc.sh start
sudo ./svc.sh status
Це реєструє actions.runner.* як unit systemd, що працює від користувача runner, зі стартом при завантаженні. Логи йдуть у journald:
sudo journalctl -u 'actions.runner.*' -f
Назад на сторінці Runners у GitHub ваш раннер тепер показує Idle — зелена крапка. Націльте на нього воркфлоу:
jobs:
build:
runs-on: self-hosted
steps:
- uses: actions/checkout@v4
- run: make test
Пушіть — і задача виконається на вашій машині.
4. Тримати в чистоті
Self-hosted раннер перевикористовує свою файлову систему між задачами — це виграш у швидкості (теплі кеші) і граблі (залишковий стан). Дві звички тримають його здоровим:
- Регулярно чистіть. Особливо Docker —
docker system pruneза кроном, інакше диск тихо забивається мертвими шарами. - Не зберігайте секрети на машині. Використовуйте secrets GitHub Actions, що інжектяться щопрогону, а не файли в домашній папці раннера. Якщо раннер скомпрометують, усе на диску піде разом із ним.
Якщо потрібне по-справжньому чисте оточення на кожну задачу — запускайте кожну всередині кроку-контейнера: раннер лишається, а сміття задачі — ні.
Коли self-host, чесно
Self-host, коли потрібен свій тулчейн вшитим, доступ до приватних ресурсів мережі або контроль над машиною. Лишайтеся на GitHub-hosted раннерах, коли чисте одноразове оточення і їхні хвилини вас влаштовують — це справді простіше, а простота чогось варта. І ніколи, на публічному репо, не робіть self-host. Це не питання вподобань.
Якщо потрібен раннер під приватний репо: оберіть тариф — Small ($8) для легших збірок, Medium ($12), коли важчають, — оплатіть у USDC або USDT (без KYC, без документів), і root буде приблизно за 60 секунд. Далі йдіть за цією сторінкою — і за пару хвилин раннер почне підхоплювати задачі.