Introduction
portainer-github-runner is a self-hosted GitHub Actions runner packaged as one Portainer stack: two services, one environment block, no build step.
When this pays off
Section titled “When this pays off”GitHub bills hosted runner minutes. Self-hosted minutes are free, so moving a job onto your own machine removes it from the bill.
The arithmetic only works for long jobs. Moving a two-minute typecheck saves nothing and costs you a machine to look after. The honest sequence is:
- Look at a run and note how long each job took.
- Move the one job that dominates.
- Leave the fast jobs on GitHub’s runners — then a push still gets its basic verdict when your own host is off.
A worked example: a repository whose push cost 60 billed minutes, 52 of them a single browser-test job. Moving that one job removed 87 % of the bill and left four jobs, eight minutes, where they were.
The risk you are accepting
Section titled “The risk you are accepting”The runner mounts the host’s Docker socket, which is root on that host. Any workflow it runs can start a privileged container and read or write anything on the machine.
That is a reasonable trade for a private repository with trusted authors, on a host that carries nothing precious. It is not a trade you should make if the repository is public or takes pull requests from forks — a stranger’s pull request would then run as root on your machine.
Security covers this properly, and it is worth reading before you deploy rather than after.
What is in the stack
Section titled “What is in the stack”| service | what it does |
|---|---|
runner | registers with GitHub and runs the jobs that ask for its label |
prune | removes images, build cache and stopped containers older than a day, hourly |
The second one is not decoration. A persistent runner accumulates one image per branch build plus every container a job forgets to tear down, and nothing on a Docker host removes them on its own.