GitHub Actions is genuinely good until you hit the usage limits. Then it gets expensive, fast. At roughly $0.008 per minute for hosted runners, a few busy repositories can generate surprise bills that have no business appearing in a solo developer's inbox.
The obvious fix — self-hosted runners on your own infrastructure — is technically free, but the setup process is tedious, error-prone, and different enough across operating systems that most people do it once, get it mostly working, and quietly dread ever having to do it again.
I built this tool because I was that person. Multiple repositories, repeated limit hits, and a manual runner setup process I'd already done enough times to know I never wanted to do it again. So I automated the whole thing and packaged it into a single shell-based installer.
What the Tool Actually Does
The installer handles the full lifecycle of getting a self-hosted runner operational. It detects your environment, installs any missing dependencies automatically, registers the runner with GitHub using a scoped token, and configures it as a system service. The goal is to make the ongoing operational burden close to zero.
Workflow migration is also included — an interactive selection interface lets you pick which workflows currently targeting GitHub-hosted runners should be updated to point at your self-hosted setup. Timestamped backups are created before any file is touched. That last part matters. Automated tooling that modifies your workflow files without a safety net is the kind of thing that creates 2 am incidents.
Cross-Platform Without the Usual Compromises
Supporting Linux, macOS, and Docker from a single shell codebase means handling a lot of variation quietly. Linux distributions don't all look the same — package managers differ, service management differs, path conventions differ. macOS has its own quirks. Docker needs a different approach entirely since systemd isn't running inside a container.
The installer detects the environment at runtime and adapts accordingly:
- Automatic Linux distro detection with per-distro package manager support
- macOS Homebrew auto-install when not present
- Docker-aware configuration that bypasses systemd correctly
- Systemd service templates for multi-runner deployments on a single host
The user doesn't need to know which path they're on — the script figures it out.
Token Encryption and Secrets Handling
Runner registration requires a GitHub token, and storing that token insecurely on disk is the kind of shortcut that feels fine until it isn't. The tool encrypts stored tokens using AES-256-CBC, with a XOR-based fallback for environments where OpenSSL isn't available.
The fallback approach is worth being honest about: XOR encryption is not AES-256. It's a meaningful step up from plaintext, and it keeps the tool functional in constrained environments, but it's documented clearly rather than quietly presented as equivalent. That kind of transparency is part of what makes infrastructure tooling trustworthy.
Health Monitoring and Self-Recovery
A runner that silently fails and stops processing jobs is worse than a runner that was never set up, because at least the latter fails loudly. The health check system monitors the runner process status on a schedule and restarts failed processes automatically.
It logs what happened, when, and why — so if something keeps failing, there's an audit trail to work from rather than a mystery.
For teams running multiple isolated runners on a single host, the systemd service templates handle fair resource allocation across instances. Each runner gets its own service unit, which means individual failures don't cascade and you can manage them independently.
Code Quality in Shell Scripting (Yes, Really)
Shell scripting has a reputation for being the place where code quality goes to die. This codebase takes that seriously:
- ShellCheck linting is integrated into CI validation
- shfmt formatting enforcement across the codebase
- Automated token management tests
- Comprehensive error handling with informative failure messages
None of this is glamorous, but shell scripts that haven't been linted are the kind of thing that works perfectly on one machine and fails silently on another — and that's exactly the failure mode this tool exists to prevent.
The Practical Outcome
The tool reduces the initial runner setup from a multi-hour, documentation-heavy process to a process that completes in minutes. Ongoing maintenance is handled automatically. For solo developers or small teams running several active repositories, the cost difference between GitHub-hosted and self-hosted runners is meaningful — and the previous barrier to self-hosting was mostly the operational friction, not the infrastructure cost itself.
This is the kind of infrastructure work that isn't exciting to describe but is genuinely useful to have. It solves a real problem, takes security and reliability concerns seriously, and runs reliably across the environments where it needs to.
If you're working on CI/CD automation, developer tooling, or cross-platform infrastructure and want someone who thinks carefully about the operational layer — not just the happy path — I'd be happy to talk through what that might look like.
