Deploy Self-Hosted GitHub Actions Runners on Vectorlay
Tired of waiting in GitHub's runner queue? Want GPU access in your CI/CD pipeline? This guide shows you how to run self-hosted GitHub Actions runners on Vectorlay with automatic failover and scaling.
Why Self-Hosted Runners?
GitHub's hosted runners are convenient, but they come with limitations:
- Queue times: Popular repos can wait minutes for a runner
- Resource limits: 2 vCPUs, 7GB RAM on free tier
- No GPUs: Can't run ML training or inference in CI
- Minutes caps: Free tier limits, expensive overages
- No customization: Can't pre-install your toolchain
Self-hosted runners on Vectorlay solve all of these. You get dedicated resources, instant job pickup, GPU access, and Vectorlay's automatic failover if a node goes offline.
Prerequisites
What You'll Need
- •A Vectorlay account (we handle the infrastructure)
- •A GitHub Classic PAT (Personal Access Token)
- • For single repo:
reposcope - • For org-wide:
admin:org+reposcopes
- • For single repo:
Important: Fine-grained PATs don't work for organization runners. You must use a Classic PAT. Go to GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic) → Generate new token.
Step 1: Create the Cluster
We'll use the popular myoung34/github-runner Docker image, which handles runner registration, deregistration, and auto-updates.
Option A: Single Repository Runner
For runners that only serve one repository:
Option B: Organization-Wide Runner
For runners that can serve any repository in your organization:
Pro tip: Don't set RUNNER_NAME. The image auto-generates unique names for each replica, which is required when running multiple instances.
Step 2: Deploy and Verify
Click Deploy and wait for your cluster to reach the "Running" state. This typically takes 1-2 minutes as the runner image is pulled and containers start.
Once running, verify your runners are registered:
- Go to your repository (or organization) on GitHub
- Navigate to Settings → Actions → Runners
- You should see your runners listed as "Idle"
Step 3: Use the Runners in Your Workflows
Update your workflow files to use runs-on: self-hosted:
# .github/workflows/build.yml
name: Build and Test
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: self-hosted
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build
run: npm run buildUsing Labels for GPU Runners
If you have GPU nodes and want to route ML jobs specifically to them, add labels:
jobs:
train-model:
runs-on: [self-hosted, gpu]
steps:
- uses: actions/checkout@v4
- name: Train model
run: python train.py --epochs 100How It Works
- Outbound connection: Runners connect outbound to GitHub over HTTPS. No public IP or inbound ports needed.
- Auto-registration: On container start, the runner registers itself with GitHub using your PAT.
- Job pickup: Runners long-poll GitHub for jobs. When a workflow triggers, an idle runner picks it up instantly.
- Clean environment: Each job runs in a fresh environment. The container persists but the workspace is cleaned.
- Graceful shutdown: On container stop, the runner deregisters from GitHub automatically.
Scaling and Failover
Each replica is an independent runner. With 4 replicas, you can run 4 jobs in parallel.
Scaling Up
Need more parallelism? Just increase the replica count in your cluster settings. New runners spin up and register within seconds.
Automatic Failover
If a Vectorlay node goes offline:
- Vectorlay detects the failure via heartbeat
- The runner on that node becomes unresponsive to GitHub
- GitHub marks the runner as offline after 30 seconds
- Vectorlay schedules a replacement replica on a healthy node
- New runner registers and becomes available
Any in-progress job on the failed node will be marked as failed by GitHub and can be re-run. Queued jobs will be picked up by remaining healthy runners.
Advanced Configuration
Runner Groups (Enterprise)
If you're on GitHub Enterprise, you can assign runners to groups:
Ephemeral Runners
For maximum isolation, use ephemeral mode. The runner handles one job then exits (Vectorlay will automatically restart it):
Docker-in-Docker
Need to build Docker images in your CI? The runner image supports Docker-in-Docker. Make sure to use a Vectorlay node with Docker installed and add:
Troubleshooting
Runner not appearing in GitHub
- Check the container logs in Vectorlay dashboard for registration errors
- Verify your PAT has the correct scopes
- For org runners, confirm you used a Classic PAT (not fine-grained)
- Check that
REPO_URLorORG_NAMEis correct
Jobs stuck in "Queued"
- Verify at least one runner shows "Idle" in GitHub Settings
- Check that your workflow's
runs-onlabels match the runner's labels - For org runners, ensure the repository has access to the runner group
"PAT does not have admin:org scope"
- You're trying to register an org-wide runner
- Regenerate your PAT with
admin:orgscope - Or switch to
REPO_URLfor a single-repo runner
Cost Comparison
Running 4 concurrent runners on Vectorlay vs GitHub's hosted runners:
| Provider | Specs | Monthly Cost |
|---|---|---|
| GitHub Free | 2 vCPU, 7GB RAM | 2,000 mins then $0.008/min |
| GitHub Team | 2 vCPU, 7GB RAM | 3,000 mins then $0.008/min |
| Larger Runners | 8 vCPU, 32GB RAM | $0.032/min (~$46/1000 mins) |
| Vectorlay | 8+ vCPU, 32GB+ RAM, GPU optional | ~$0.20-0.40/hr per runner |
If you run 10,000+ minutes of CI per month, self-hosted runners on Vectorlay can save 50-70% compared to GitHub's hosted runners—with better specs and GPU access.
Wrapping Up
Self-hosted GitHub Actions runners on Vectorlay give you the best of both worlds: the convenience of GitHub Actions with the power and control of your own infrastructure.
- No more queue wait times
- Run GPU workloads in CI
- Automatic failover and scaling
- Predictable costs
Ready to speed up your CI/CD?
Deploy self-hosted runners in minutes. Get $10 in free credits.
Get Started→