Dev Tools 1 service 2 GiB RAM 1 GB disk

GitHub Actions Runner

A self-hosted GitHub Actions runner - your workflows on flat-price compute, zero per-minute billing.

One-click deploy, from $13/mo on a Miget plan.

GitHub Actions minutes are the quiet line item that grows with every push: $0.006/minute for Linux 2-core past the included quota, more for bigger machines. A self-hosted runner removes the meter - and gets you exactly the CPU, RAM, and caching behavior you choose.

This template uses the de-facto env-driven runner image with PAT-based auto-registration: set a token and a repo (or org), deploy, and the runner appears in Settings > Actions. Registration state persists across redeploys; EPHEMERAL mode plus replicas gives clean-slate scale-out.

The honest constraint, documented rather than discovered: run: steps and JS/composite actions work fully; container: jobs and Docker container actions need a daemon a PaaS does not expose - image builds go through kaniko or buildah instead.

#what you get

  • PAT-based auto-registration: deploy and it appears in GitHub
  • Repo or org scope; custom labels for runs-on targeting
  • Ephemeral mode + replicas for clean parallel runners
  • Registration survives redeploys (state volume)
  • No per-minute billing - the plan is the whole CI bill
  • kaniko/buildah path documented for image builds

#topology

ServiceRolePublic
runnerActions runner, outbound long-poll to GitHubno - no ingress needed

#miget sizing

// this stack needs

2 GiB RAM · 1 GB disk · 1 service

Size to your builds, not the runner (it idles under 100 MB). 2 GiB suits typical Node/Python/Go builds; compile-heavy jobs want the next plan up.

Hobby - recommended fit

$13/mo

1 vCPU · 2 GiB · 50 GiB disk

Headroom for your own apps: 2 GiB at $19/mo

Professional - production

$22/mo

1 vCPU · 2 GiB · 10 GiB disk

Dedicated resources, production SLOs - plan details

One Miget plan is a fixed pool of compute - the whole stack (managed databases included) deploys inside it, and anything left over runs your other apps. No per-service or per-seat math.

#vs. the managed service

What the hosted equivalents charge, against the flat Miget plan this stack fits on. Prices as of June 2026, sources linked.

ServicePlanMonthlyWhat you get
GitHub Actions Runner on Miget 2 GiB plan$13this whole stack, flat - no usage meters, and room left for your own apps
GitHub Actionshosted runnersusage-based$0.006/min Linux 2-core past included minutes (2,000-3,000/mo on Free/Team) - 30k monthly minutes ≈ $165 overage

Self-hosted runners are free on GitHub’s side; the announced per-minute fee for them was retracted in December 2025.

#vs. other PaaS

Estimated monthly cost of running this exact stack (2 GiB RAM, 1 GB disk, 1 container) elsewhere, from published June 2026 rates.

PlatformEst. monthlyNotes
Miget $13 flat compose stacks first-class: one deploy, dedicated vCPU, managed Postgres/Valkey, volumes and TLS all included in the plan
Heroku ~$100 no volumes; nothing between 1 GB ($50) and 2.5 GB ($250) dynos - 2 GB containers cost far more than shown
DO App Platform ~$29 no persistent volumes - stateful containers need managed DBs/Spaces (base $5 Spaces included here)
Render ~$25 per-service instances (0.5 GB $7, 2 GB $25) - every container is its own paid service
Railway ~$20 usage-based ($10/GB RAM-mo); vCPU billed separately at $20/vCPU-mo on top
Fly.io ~$12 cheapest sticker price - but burstable shared CPUs (1/16 core; dedicated vCPUs cost ~2-3×), no compose deploys (one app per container, manual wiring), managed DBs billed extra

Estimates assume RAM fully allocated at published on-demand rates - and sticker price isn't the whole comparison: the cheaper rows buy burstable shared CPUs, per-service wiring instead of a compose deploy, and managed databases billed separately. Heroku and DO App Platform have no persistent volumes at all - stateful stacks like this one need workarounds there.

#deploy it

On Miget

  1. Create a Compose Stack in app.miget.com pointing at the templates repository
  2. Set the stack path to github-runner
  3. Set the required variables:
    • ACCESS_TOKEN, PAT (repo scope for repo runners, admin:org for org runners)
    • REPO_URL or ORG_NAME, where the runner registers (with RUNNER_SCOPE)
  4. Deploy. Miget layers compose.miget.yaml (RAM, privacy, volumes, managed services) automatically

Locally first?

Every template is portable, vanilla Docker Compose - the Miget overrides are ignored locally:

git clone https://github.com/deployable-sh/stacks
cd miget-compose-templates/github-runner
docker compose up -d

Same files, same behavior. The template README covers connection strings and scaling notes.

#faq

How much does this save vs hosted runners?

GitHub includes 2,000-3,000 minutes/month on Free/Team plans, then bills $0.006/min for Linux 2-core. A team burning 30,000 monthly minutes pays ~$165 in overage; this runner is $13/month flat at any volume - and you can give it more cores than the hosted 2-core default for the same price.

What workflows will NOT work on it?

Anything needing the Docker daemon: container: jobs, services: blocks (Postgres-in-CI style), and Docker container actions. The fixes are standard: native services (your project already runs real databases), kaniko/buildah for image builds, and JS-based actions which all work.

How do I run more jobs in parallel?

Set EPHEMERAL=true and raise replicas - each replica registers itself, takes one job, deregisters, repeats. Clean state per job, parallelism equal to replica count, all inside the same flat plan.

Is a PAT in env safe?

The token only mints runner registration tokens and lives server-side in your stack env. Use a fine-grained PAT scoped to the one repo/org, and rotate it like any credential. GitHub’s JIT-config flow exists for stricter setups; this template favors the simple, durable registration.

Ship GitHub Actions Runner today

One compose stack, 2 GiB of RAM, from $13/month flat, and it runs on your laptop with the same files.