I have published JIT Runner Kit v0.1.0, an MIT-licensed toolkit for ephemeral GitHub Actions runners.
The goal is simple: keep expensive build, test, and deploy work off GitHub-hosted runners without paying for an idle self-hosted server. A short GitHub-hosted control job creates a fresh Hetzner VM with a unique just-in-time label. One trusted workload job runs there; an always() cleanup job then removes the runner record, VM, Primary IPv4, firewall, and temporary SSH key. An independent TTL sweep is the backstop.
The repository also retains an external polling-controller mode for teams that need zero GitHub-hosted control minutes. No Mac or permanent controller VPS is required for the recommended Actions-driven mode.
What has been validated on a real Hetzner CX33 pilot:
- successful provisioning, registration, workload execution, deregistration, and full cleanup;
- cleanup after successful, failed, and cancelled workloads;
- Docker/Compose, GitHub CLI, ShellCheck, PHP CLI, Python 3, and native build tooling on Ubuntu 24.04;
- custom package and Bash/Zsh/Fish guidance;
- immutable action pinning and an unprivileged runner user without
sudo.
The project is still pre-1.0. It is intended for trusted repositories and controlled pilots. Public fork PRs should use a separate, secret-free execution path; a workflow job fully controls its runner VM. Parallelism is isolated: use one VM per job, with a small global cap, rather than multiple concurrent jobs sharing one machine.
The next controller design is provider-agnostic. The first serverless adapter is planned for Cloudflare Workers with a GitHub App, Queues, Durable Objects, and Cron; Hetzner remains the first compute adapter. The core lifecycle, lease state machine, idempotency, retry policy, concurrency limits, and cleanup contracts will not depend on either provider.
I would especially value feedback on:
- Which provider driver should come next?
- Which serverless controller adapter should follow Cloudflare?
- Which observability signals are essential before calling this production-ready?
- What image customization should be declarative rather than handled by cloud-init or a prebuilt snapshot?