What is Blacksmith CI, and how do its runners work?
What is Blacksmith CI: it is a managed replacement for GitHub-hosted Actions runners, running on bare metal in four of its own regions, which you adopt by installing a GitHub App and changing one runs-on label. Your workflow files, actions, secrets and matrix stay exactly as they are, and what changes is the machine underneath, the cache it talks to, and the per-minute rate.

Blacksmith does not replace GitHub Actions. It replaces the computer GitHub Actions runs on, which is a much smaller change than the category name suggests and is why adoption is measured in minutes rather than sprints.
This page is an explainer, not a pitch. Everything in it was read from blacksmith.sh and docs.blacksmith.sh on 20 September 2026, and where Blacksmith does not publish something, it says so. If you want the head-to-head comparisons instead, Blacksmith against GitHub-hosted runners and Blacksmith against Depot carry the full tables.
How it works: an app, a label, and someone else's hardware
Adoption is two steps. You install the Blacksmith GitHub App on the repositories that will use it, and you change runs-on from a GitHub label to a Blacksmith one. Nothing else in the workflow moves: uses: steps, marketplace actions, secrets, environments, matrix strategy and artifacts all behave as before, because the runner is still the standard GitHub Actions runner agent, just on a different machine.
The GitHub App is not only authentication, and this is the part worth understanding before you roll out. Per the runner docs, Blacksmith watches and provisions capacity for the repositories where the app is installed. A repository that uses blacksmith-* labels without the app installed can end up adopting runners provisioned for a different repository, which under-provisions everybody. If jobs queue in an organization that has "no concurrency limits", the missing app install is the first thing to check.
Jobs run in one of four Blacksmith regions: Ashburn, Phoenix, Amsterdam and Frankfurt. Nested virtualization is supported on x64 Linux, which is what KVM-dependent jobs and Android emulators need, and is not supported on ARM Linux.
jobs:
build:
- runs-on: ubuntu-latest
+ runs-on: blacksmith-4vcpu-ubuntu-2404
steps:
- uses: actions/checkout@v7
- run: npm ci && npm run buildThe runner sizes, and what the label encodes
The label carries the size, the OS and the architecture: blacksmith-{n}vcpu-{os}-{version}, with -arm appended for ARM Linux. Every tier below is published in the instance-types documentation, read 20 September 2026.
| Label | vCPU | RAM | Storage |
|---|---|---|---|
blacksmith-2vcpu-ubuntu-2404 | 2 | 8 GB | 80 GB |
blacksmith-4vcpu-ubuntu-2404 | 4 | 16 GB | 80 GB |
blacksmith-8vcpu-ubuntu-2404 | 8 | 32 GB | 160 GB |
blacksmith-16vcpu-ubuntu-2404 | 16 | 64 GB | 750 GB |
blacksmith-32vcpu-ubuntu-2404 | 32 | 128 GB | 1.5 TB |
blacksmith-2vcpu-ubuntu-2404-arm | 2 | 6 GB | 75 GB |
blacksmith-32vcpu-ubuntu-2404-arm | 32 | 96 GB | 1.5 TB |
blacksmith-2vcpu-windows-2025 (public beta) | 2 | 7 GB | 130 GB |
blacksmith-6vcpu-macos-latest | 6 | 24 GB | 150 GB |
blacksmith-12vcpu-macos-latest | 12 | 48 GB | 250 GB |
Two things stand out against GitHub-hosted. The smallest Blacksmith Linux runner has the same 8 GB of RAM as a standard private-repo GitHub runner but 80 GB of disk against 14 GB, which quietly removes a whole class of disk-full failures without any change to your workflow. And ARM tiers carry less memory than their x64 equivalents at the same core count, 6 GB against 8 GB at 2 vCPU, so an ARM migration is not a like-for-like move if your jobs are memory-bound.
Ubuntu 22.04 is published at the same sizes as 24.04. macOS runs on Apple silicon M4 with images from macOS 15 through a macOS 27 public beta, and Windows Server 2025 is itself still labeled public beta.
Caching: two mechanisms, and they are not the same
The first mechanism needs no workflow change at all. Blacksmith intercepts the official and popular third-party cache actions and points them at its own colocated cache in the same datacentre as the runners, and its docs put downloads at roughly 4x GitHub's backend. The free allowance is 25 GB per repository per week against GitHub's 10 GB per repository, which matters more than it sounds: a bigger window means fewer forced evictions inside a week.
Two documented exceptions are worth knowing before you count on it. Rust's sccache and the cache option in docker/build-push-action still redirect to GitHub's backend, so those paths keep GitHub's storage rules rather than the 25 GB allowance.
The second mechanism is sticky disks, which are ext4 volumes mounted into the runner by useblacksmith/stickydisk@v1 and persisted across jobs by a key you choose. The docs allow up to 5 per job, report about 3 seconds to access data that takes around 1m6s as a 6 GB GitHub Actions Cache artifact, and evict a disk after 7 days without a job mounting it. Storage is billed at $0.50 per GB per month. Inside a container job they need privileged mode, specific environment variables and sudo in the image, which is the usual reason a sticky disk works on the host and fails in a container.
- uses: useblacksmith/stickydisk@v1
with:
key: ${{ github.repository }}-npm-cache
path: ~/.npmDocker builds
Docker acceleration is its own pair of actions, useblacksmith/setup-docker-builder@v2 and useblacksmith/build-push-action@v2, and the layer cache they maintain lives on a sticky disk. Blacksmith reports customers seeing 2x to 40x improvements in build time, which is a range wide enough to tell you that the answer depends entirely on your Dockerfile.
The v2 builder changed the contract, and it is the one thing to check before you copy an older snippet. Its README, read 2026-09-20, lists cache-key as a required input naming the sticky disk the layers land on, where v1 had no such input at all. Builds that pass the same key share cached layers, so the key belongs to the build target rather than to the repository, and two images sharing one key will evict each other.
The garbage collection rule is the practical one to remember: layers that have not been used for 8 days are cleaned up while actively used layers are kept regardless of total cache size, and the sticky disk underneath still evicts after 7 days of inactivity. A pipeline that runs weekly sits right on that boundary and will keep going cold.
- uses: useblacksmith/setup-docker-builder@v2
with:
cache-key: my-repo/backend-image # required on v2, one key per build target
- uses: useblacksmith/build-push-action@v2
with:
push: true
tags: user/backend:latestThe limits its own documentation records
- No concurrency limits on simultaneous jobs or vCPUs, per the runner docs. Capacity is nonetheless provisioned per repository with the GitHub App installed, so queuing without a stated limit is usually a missing install.
- Docker Linux containers are not supported on Windows runners because of nested virtualization constraints. Windows containers matching Windows Server 2025 work through process isolation.
- Nested virtualization is x64 Linux only, so KVM-dependent jobs and emulator-based tests will not work on ARM.
- Sticky disks: 5 per job, evicted after 7 days idle, and container jobs need privileged mode plus specific environment variables and
sudo. - Billing granularity is not published. Neither the pricing page nor the docs read on 20 September 2026 says whether a partial minute is rounded, which matters if your matrices are wide and your jobs are short.
What it costs, in one paragraph
Ubuntu x64 is $0.004 a minute at 2 vCPU and doubles with each size step, Ubuntu ARM is $0.0025, Windows x64 is $0.008 and macOS M4 is $0.08. Every runner card carries 3,000 free minutes a month. Docker layer caching and sticky disk storage are add-ons at $0.50 per GB per month, and a static IP is $100 per IP per month. The full rate card, the free-minute rules and the arithmetic against GitHub-hosted are on Blacksmith pricing explained.
What Blacksmith does not do
Blacksmith optimises how fast a job runs and what it costs. It does not do anything about why a job failed. A registry timeout, a browser binary that did not install, a kernel out-of-memory kill: on Blacksmith those fail the job, bill the minutes, and wait for a person to press re-run, which bills again. Nothing in its documentation claims otherwise, and that is the correct scope for a compute vendor.
That gap is the reason Latchkey exists, and the honest framing is that these are different products rather than better and worse ones. Blacksmith sells arm64, Windows and macOS runners at published rates and 3,000 free minutes a month, none of which Latchkey offers; Latchkey sells Linux x64 at $0.0025 a minute with transient failures diagnosed and retried inside the run. If your problem is that builds are slow, Blacksmith is a better fit than a self-healing runner. If your problem is that builds are red for reasons that have nothing to do with your code, faster hardware will not touch it.
Key takeaways
- A GitHub App install plus a
runs-onchange; workflows, actions and secrets are untouched. - Linux x64 from 2 to 32 vCPU with 4 GB of RAM per core and 80 GB of disk at the smallest size; ARM carries 3 GB per core.
actions/cacheis transparently redirected to a colocated cache with 25 GB free per repo per week, withsccacheanddocker/build-push-actiondocumented exceptions.- Sticky disks persist state across jobs, 5 per job, evicted after 7 days idle, billed at $0.50/GB/month.
- Its runner docs state no concurrency limits at all on jobs or vCPUs. Billing granularity is not published, and failed jobs are not handled automatically.
Frequently asked questions
What is Blacksmith CI and how do their runners work?
runs-on to a blacksmith-* label, and your existing workflow runs unchanged on Blacksmith's bare-metal hardware in one of four regions. It is compute only: the orchestration, the actions and the logs are still GitHub Actions.What are the Blacksmith runner sizes?
Why is my Blacksmith job queuing if there are no concurrency limits?
blacksmith-* labels is the documented fix.