A pool of self-hosted GitHub Actions runners, each backed by a Dedalus Machine. The first job warmsDocumentation Index
Fetch the complete documentation index at: https://docs.dedaluslabs.ai/llms.txt
Use this file to discover all available pages before exploring further.
~/.cargo, ~/.rustup, ~/.npm, ~/.cache/sccache. Every job after that wakes the same machine and reuses everything. You pay only for the seconds a runner is actually running a job.
1. Provision a runner pool
Run this once per runner you want in the pool. Each machine registers itself as an Actions runner on first boot.2. Wake on workflow_job webhook, sleep when idle
GitHub fires aworkflow_job webhook with action queued when a job is dispatched. Wake the matching machine; let auto-sleep handle the rest.
gh-runner.service is on by default; once the VM wakes, systemd starts the runner process and it polls the GitHub queue. After the job finishes the runner goes idle. Five minutes later the platform auto-sleeps the VM (idle_sleep_after_seconds, default 300s).
Why this beats GitHub-hosted runners
- Hot toolchain caches.
~/.cargo(3 GB of crates),~/.rustup,~/.cache/sccache,~/.npm,node_modulesfor monorepo workspaces — all stay on disk between jobs. GitHub-hosted runners cold-pull every job. A Rust job that takes 12 minutes cold takes 90 seconds warm. - Pay only for awake-seconds. A pool of 10 runners that handle a 4-hour-per-day workload pays for ~40 vCPU-hours, not 240.
- 4 vCPU / 8 GiB / 40 GiB out of the box; provision bigger if you need it. Standard GitHub runners cap at 2 vCPU / 7 GiB.
- Real Linux, your kernel — install kernel modules, run Docker-in-VM with full nesting, run privileged containers, whatever your build needs.
Notes
- Pre-warming. If you want zero cold-start on the first job of the day, run a dummy
wakeon cron a few minutes before peak. (See Cron on a Sleeping VM.) - Pool size. Provision N machines; a queued job wakes the first idle one. Concurrency above N queues — your webhook handler should fall back to creating a new machine if the pool is saturated.
- Caches survive sleep and wake. They don’t survive
delete. If you provision a new machine you lose its cache; budget for that on first build. - Auto-sleep timing. Default 300s of idle is fine for back-to-back PRs. Push it higher (
idle_sleep_after_seconds: 1800) for spiky CI patterns.
