Runner yang dihosting GitHub memang nyaman tetapi memiliki keterbatasan yang penting pada skala: 6-10 GB RAM, tidak ada cache alat persisten, runner konkuren terbatas pada paket gratis, dan IP runner publik yang ditolak oleh beberapa layanan internal. Di Commsult Indonesia, saya menyiapkan self-hosted runner di DigitalOcean Droplet terutama karena dua alasan: untuk mengakses resource GCP privat kami tanpa mengeksposnya ke IP runner publik GitHub, dan untuk meng-cache layer Docker dan paket npm antar build, memotong waktu build dari 8 menit menjadi kurang dari 3 menit. Panduan ini mencakup setup lengkap dengan praktik keamanan yang tidak memotong sudut.
Runner yang dihosting GitHub adalah default yang tepat untuk sebagian besar proyek — tidak ada pemeliharaan, diperbarui secara otomatis, dan tersedia dalam berbagai ukuran dan sistem operasi. Self-hosted runner menambah nilai ketika: CI/CD Anda membutuhkan akses ke resource di dalam jaringan privat (VPC, layanan on-premises); Anda membutuhkan cache persisten yang bertahan antar run (cache layer Docker, cache npm); Anda membutuhkan hardware khusus (GPU untuk pelatihan ML, NVMe untuk pengujian I/O-intensif); atau Anda mencapai batas konkurensi GitHub pada paket gratis atau Team. Paket gratis GitHub membatasi Anda pada 20 job konkuren; self-hosted runner tidak memiliki batas konkurensi selain hardware Anda.
Self-hosted runner mengeksekusi kode sembarang dari repositori Anda — termasuk kode dari pull request jika Anda mengaktifkannya. Dokumentasi GitHub sendiri merekomendasikan untuk tidak pernah menggunakan self-hosted runner untuk repositori publik, karena PR berbahaya dapat menjalankan kode di infrastruktur Anda. Untuk repositori privat, risikonya berkurang tetapi tidak hilang — akun developer yang dikompromikan dapat mendorong kode workflow berbahaya. Kontrol keamanan terpenting: jalankan runner dalam ephemeral mode (setiap job mendapatkan lingkungan segar yang terisolasi); jangan pernah memberikan runner akses ke secrets di luar apa yang dibutuhkan job tertentu; gunakan runner group untuk membatasi repositori mana yang dapat menggunakan runner mana.
Mulai Maret 2026, GitHub merekomendasikan menjalankan self-hosted runner dalam ephemeral mode: flag --ephemeral berarti runner memproses satu job lalu membatalkan registrasinya sendiri. Runner manager (Actions Runner Controller untuk Kubernetes, atau restart layanan systemd sederhana untuk VPS) menyediakan runner segar untuk job berikutnya. Ini mencegah state dari satu job memengaruhi job lain — tidak ada variabel lingkungan yang tersisa, tidak ada file sisa, tidak ada secrets yang dibagikan antar run. Pada DigitalOcean Droplet, implementasikan ephemeral runner dengan layanan systemd yang me-restart runner setelah setiap job selesai menggunakan flag --once --ephemeral.
Dari pengalaman saya: tempatkan self-hosted runner Anda di region yang sama dengan resource GCP utama Anda. Runner kami ada di DigitalOcean Singapura, dan mereka menarik image Docker dari Artifact Registry kami di asia-southeast1 (Singapura). Transfer intra-datacenter (dalam Singapura) cepat dan gratis di DigitalOcean, dan jaringan internal GCP cepat untuk traffic GCP-ke-GCP. Lokalitas cache ini saja mengurangi waktu pull image Docker kami dari 45 detik menjadi 8 detik per build — pengurangan waktu build keseluruhan 35%.
Menyiapkan self-hosted runner memerlukan: membuat token registrasi runner di GitHub (Settings → Actions → Runners → New self-hosted runner), mengunduh dan mengonfigurasi runner agent, dan menyiapkan runner sebagai layanan systemd. Runner berkomunikasi dengan GitHub melalui HTTPS (port 443 hanya keluar) — tidak perlu membuka port masuk di firewall Anda. Token registrasi runner berumur pendek (1 jam) — hasilkan segera sebelum menjalankan skrip konfigurasi. Simpan file .credentials runner dengan aman dan jangan pernah meng-commit-nya ke version control.
# Install and configure self-hosted runner (Ubuntu)
# 1. Download the runner agent
mkdir actions-runner && cd actions-runner
curl -o actions-runner-linux-x64-2.321.0.tar.gz -L https://github.com/actions/runner/releases/download/v2.321.0/actions-runner-linux-x64-2.321.0.tar.gz
tar xzf ./actions-runner-linux-x64-2.321.0.tar.gz
# 2. Configure (use token from GitHub Settings > Actions > Runners)
./config.sh --url https://github.com/myorg/myrepo --token RUNNER_TOKEN --labels "self-hosted,linux,x64,gcp-sg" --ephemeral
# 3. Install as systemd service (auto-restart after each ephemeral job)
sudo ./svc.sh install
sudo ./svc.sh start
# Workflow targeting self-hosted runner
# .github/workflows/deploy.yml
# jobs:
# deploy:
# runs-on: [self-hosted, gcp-sg]
# steps:
# - uses: google-github-actions/auth@v2
# with:
# workload_identity_provider: 'projects/123/locations/global/workloadIdentityPools/...'
# service_account: 'deploy-sa@my-project.iam.gserviceaccount.com'Self-hosted runner dapat memiliki label khusus yang digunakan workflow untuk menarget jenis runner tertentu. Runner dengan label [self-hosted, linux, x64, gcp-sg] dapat ditarget dengan runs-on: [self-hosted, gcp-sg] dalam YAML workflow Anda. Gunakan label untuk membedakan runner berdasarkan kemampuan (gpu, high-memory, gcp-access) dan berdasarkan lingkungan (staging-runner, prod-runner). Hanya job deployment produksi yang harus berjalan di runner dengan akses kredensial produksi. Job development dan test dapat berjalan di runner dengan akses read-only. Routing berbasis label ini adalah cara Anda mengimplementasikan isolasi lingkungan tanpa memelihara armada runner terpisah untuk setiap workflow.
┌──────────────────────────────────────────────────────┐
│ Self-Hosted Runner Security Model │
├──────────────────────────────────────────────────────┤
│ │
│ GitHub Actions Queue │
│ ↓ (HTTPS outbound only, no inbound ports) │
│ Runner Agent (ephemeral mode) │
│ ↓ Authenticates via OIDC token │
│ GCP Workload Identity Federation │
│ ↓ Short-lived token (1 hour TTL) │
│ GCP Resources (Artifact Registry, Cloud Run, etc.) │
│ │
│ Key: No static service account keys on runner │
│ Key: Each job = fresh isolated environment │
└──────────────────────────────────────────────────────┘Ketika saya pertama kali menyiapkan self-hosted runner kami, saya mengonfigurasi kunci akun layanan GCP sebagai variabel lingkungan dalam file layanan systemd runner. Ini berarti setiap job di runner itu memiliki akses GCP penuh, terlepas dari apa yang sebenarnya dibutuhkan job tersebut. Ketika job pemindaian dependensi berjalan dan menarik dependensi dari sumber yang dikompromikan, kode yang dikompromikan tersebut secara teoritis memiliki akses ke akun layanan GCP kami. Pendekatan yang benar: gunakan token OIDC GitHub untuk mengautentikasi ke GCP secara dinamis, per workflow. Runner itu sendiri tidak memiliki kredensial persisten — setiap workflow mengautentikasi dengan token berumur pendek yang dicakupkan ke kebutuhan spesifik workflow tersebut. GitHub Actions OIDC + GCP Workload Identity Federation menghilangkan kebutuhan kunci akun layanan statis pada runner.
Untuk tim dengan lebih dari 3-4 self-hosted runner atau beban CI/CD yang sangat bervariasi, Actions Runner Controller (ARC) adalah solusi autoscaling berbasis Kubernetes yang direkomendasikan GitHub. ARC memantau antrian GitHub Actions dan menskalakan pod runner naik dan turun berdasarkan jumlah job yang menunggu. Runner adalah pod Kubernetes yang bersifat sementara — dibuat untuk satu job dan dihancurkan setelahnya. ARC berintegrasi dengan GKE, EKS, dan AKS. Overhead Kubernetes dibenarkan ketika Anda perlu menskalakan dari 2 ke 20 runner secara dinamis — penskalaan VPS manual akan memerlukan provisioning dan konfigurasi setiap runner secara individual.
Keunggulan performa utama self-hosted runner dibandingkan runner yang dihosting GitHub adalah persistent caching. Cache layer Docker: konfigurasikan daemon Docker runner Anda untuk menggunakan direktori cache lokal. Build berikutnya yang menggunakan base layer yang sama melewati pull sepenuhnya. Cache npm/yarn: cache action berfungsi pada self-hosted runner dengan meng-cache ke direktori lokal daripada layanan cache GitHub. Untuk proyek Next.js dengan 500MB node_modules, meng-cache langkah instalasi dependensi menghemat 90-120 detik per build. Python venv, modul Go, repositori lokal Maven — semuanya mendapat manfaat dari strategi persistent cache yang sama.
Untuk proyek kecil dengan 5-20 CI run per hari, runner yang dihosting GitHub lebih sederhana dan biayanya dapat diabaikan. Self-hosted runner mulai masuk akal sekitar 50-100 build harian di mana penghematan waktu build dan efisiensi cache bertambah, atau ketika Anda memiliki persyaratan akses jaringan tertentu. Di Commsult Indonesia, self-hosted runner kami (DigitalOcean Droplet $12/bulan dengan 2 vCPU dan 4GB RAM) menjalankan 40-60 CI job per hari dan telah terbayar dalam penghematan waktu dalam bulan pertama. Cadence pembaruan runner (GitHub kini memberlakukan versi runner minimum) memerlukan perhatian — saya menjalankan cron job mingguan untuk memeriksa versi runner dan memperbarui jika diperlukan.
Sumber & Bacaan Lanjutan