@@ -20,16 +20,30 @@ milliseconds and is thrown away after the run.
2020## Tiers
2121
2222Different workloads need different images. Each tier is a separate golden rootfs
23- selected by the runner labels a workflow requests.
23+ selected by the runner label a workflow requests (` runs-on: <tier> ` ). In the
24+ scale-set model GitHub routes a job to the scale set whose name matches that
25+ label, so each tier runs as its own firerunner instance/scale set.
2426
2527| Tier | vCPU / RAM (suggested) | Contents | Use for |
2628| ------------------------- | ---------------------- | ---------------------------------------------------- | ----------------------------------------------------------- |
27- | ` firerunner-4c8g ` | 4 / 8 GiB | actions/runner, git, Node LTS + pnpm, build-essential | typical JS/TS builds, tests, lint |
29+ | ` firerunner-4c8g ` | 4 / 8 GiB | actions/runner, git, curl, jq, build-essential base | generic jobs; toolchains fetched by ` setup-* ` per workflow |
30+ | ` firerunner-node ` | 2 / 4 GiB | everything above ** + Node.js LTS + npm** (baked) | JS/TS builds where ` setup-node ` should hit a local toolchain |
2831| ` firerunner-8c16g-docker ` | 8 / 16 GiB | everything above ** + Docker Engine (dind-capable)** | jobs using ` container: ` , service containers, ` docker build ` |
2932
30- The Docker tier exists because some pipelines rely on ` docker build ` , job
31- ` container: ` and service containers, which need a real Docker daemon inside the
32- guest.
33+ The base tier deliberately ships no language toolchain — a workflow's ` setup-go `
34+ / ` setup-node ` fetches one per run. Baking a toolchain (the ` firerunner-node `
35+ tier) removes that download, mirroring GitHub's hosted ** tool cache**
36+ (` /opt/hostedtoolcache ` ). The Docker tier exists because some pipelines rely on
37+ ` docker build ` , job ` container: ` and service containers, which need a real
38+ Docker daemon inside the guest.
39+
40+ ### Running several tiers on one host
41+
42+ Each tier is a distinct scale set, so a host running more than one firerunner
43+ instance must give each its own network identity or their nftables tables and
44+ guest subnets collide. Set, per extra instance: ` FR_NAME ` (the tier label),
45+ ` FR_GOLDEN ` (its rootfs), and non-overlapping ` FR_TAP_PREFIX ` , ` FR_NET_BASE `
46+ (second IP octet, e.g. 17), ` FR_NFT_TABLE ` and ` FR_WORKDIR ` .
3347
3448## What the boot service does (MMDS → JIT)
3549
@@ -58,13 +72,19 @@ sudo ./build-rootfs.sh \
5872 --tier firerunner-4c8g \
5973 --runner-version 2.320.0 \
6074 --out /var/lib/firerunner/golden-4c8g.ext4
75+
76+ # Node tier (bakes Node.js LTS); --node-version overrides the default:
77+ sudo ./build-rootfs.sh \
78+ --tier firerunner-node \
79+ --node-version 22.11.0 \
80+ --out /var/lib/firerunner/golden-node.ext4
6181```
6282
6383` build-rootfs.sh ` creates/formats the ext4 image, debootstraps a minimal Debian
6484base (systemd + git/curl/iproute2), installs ` actions/runner ` and runs its
6585` installdependencies.sh ` , drops in the boot service + a static resolv.conf,
66- enables the service, and (for the docker tier) installs Docker. The result is an
67- immutable file firerunner reflink-clones per job. Requires ` debootstrap ` ,
86+ enables the service, and (per tier) installs Docker or bakes Node.js. The result
87+ is an immutable file firerunner reflink-clones per job. Requires ` debootstrap ` ,
6888` mkfs.ext4 ` , ` curl ` and ` tar ` on the host.
6989
7090## Rebuild policy
0 commit comments