← back to posts
homelab github

Notes on running a self-hosted GitHub Actions runner

Self-hosted runners are one of those things that sound like pure upside until you’re three hours into debugging why a workflow that passes on GitHub-hosted runners silently fails on your own box.

The economics are real though. If you’re running anything that hits the free tier limits, or if you need access to resources on your private network, a self-hosted runner pays for itself fast. Mine runs on the same Proxmox box as everything else, allocated 2 cores and 4 GB, and it handles CI for about six personal repos without breaking a sweat.

The ACL rule

The thing that took the evening was a firewall rule on my ER605 that was blocking outbound connections on port 443 from the runner’s VLAN to api.github.com. The runner registered fine, picked up jobs fine, and then stalled silently at the step that tried to download action artifacts.

bash
# What the runner logs said:
##[error]The request was canceled due to the configured HttpClient.Timeout

# What was actually happening:
# VLAN20 -> WAN:443 -> DENY (missing outbound rule)

The lesson: always check firewall rules before assuming the runner itself is broken. The runner’s error messages are not specific about network failures.

What I’d change

The registration token flow is annoying to automate. GitHub’s API gives you a one-time token that expires after an hour, which means you can’t just bake it into a Terraform resource and call it done. I ended up writing a small script that fetches a fresh token at provision time via Ansible, which works, but it’s a seam I’d rather not have.

← previous
Using a Python script as an external data source for Terraform
next →
Why I moved my homelab off Docker Compose and into Terraform