# What is on the runner image

> The preinstalled toolchain on every Latchkey runner: languages, Docker, browsers, databases, package managers, and the GitHub-compatible toolcache.

Source: https://latchkey.dev/documentation/runner-image-software

## Summary

- Ubuntu 24.04 with Node, Python, Go, Java, Rust, .NET, and more preinstalled, plus a GitHub-parity toolcache.
- Native Docker with BuildKit, buildx, and compose; QEMU multi-arch builds work out of the box.
- PostgreSQL 16 and MySQL 8.0 are installed with services off at boot; anything missing installs in your job steps.

Every runner boots from a maintained Ubuntu 24.04 LTS (x86_64) image with a toolchain designed to match or exceed GitHub-hosted runners, so most workflows run unchanged.

## The toolchain

| Category | Preinstalled |
| --- | --- |
| Node.js | 20 (default), 22, 24, with npm and yarn; nvm available |
| Python | 3.10 through 3.13 (3.14 included when available), plus pipx and PyPy |
| Go | 1.22 through 1.25 |
| Java (Temurin) | 8, 11, 17 (default JAVA_HOME), 21, and 25 when available, with Maven, Gradle, and Ant |
| Other languages | Rust (stable + rustfmt + clippy), .NET 8/9/10, Ruby (+ fastlane), PHP 8.3 (+ Composer, Xdebug), Haskell, Swift, Kotlin, Julia, PowerShell |
| Containers | Docker CE with BuildKit, `docker buildx`, `docker compose`; Buildah, Podman, Skopeo |
| Browsers | Chrome, Firefox, Edge with matching drivers; Selenium; Android SDK/NDK |
| Databases | PostgreSQL 16, MySQL 8.0 (services disabled at boot; start them in your job) |
| Package managers | Homebrew, conda, vcpkg, plus the language-native ones |
| CLI standards | AWS CLI v2, jq, git, build essentials |

## Matching GitHub-hosted behavior

The most useful property of the image is what you do not have to change. Keep your `actions/setup-node`, `actions/setup-python`, and similar steps exactly as they are: they resolve from the GitHub-parity toolcache at `/opt/hostedtoolcache` instantly instead of downloading, so the same workflow file stays correct on both runner types while you migrate.

Version pinning advice is the same as anywhere else: let the setup actions state the version rather than leaning on image defaults. Node 20 is the default with 22 and 24 also installed, but a `setup-node` step with an explicit `node-version` makes the workflow say what it means, and keeps it stable as the maintained image evolves.

## Three things worth knowing

- **Native Docker** Docker runs on the host itself: no docker-in-docker workarounds, and BuildKit is on by default.
- **Multi-arch builds** QEMU/binfmt is preconfigured, so `docker buildx --platform linux/amd64,linux/arm64` works out of the box.
- **GitHub-parity toolcache** `actions/setup-node`, `setup-python`, and friends resolve from `/opt/hostedtoolcache` instantly, without downloading.

## Databases and browsers

PostgreSQL 16 and MySQL 8.0 are preinstalled with their services **disabled at boot**, so they stay out of the way until a job asks for them. Starting the one you need is a one-line step, and it is standard Ubuntu service management rather than anything Latchkey-specific:

Starting services inside the job also keeps the dependency explicit: anyone reading the workflow file can see that the suite needs a database, which is worth having when a workflow moves between runner types.

> **Need something exotic?**
> Anything missing can be installed in your job steps as usual (sudo apt-get works). Self-healing can also install allowlisted system packages automatically when a step fails on a missing tool.

### What is preinstalled on a Latchkey runner?

Ubuntu 24.04 with Node, Python, Go, Java, Rust, .NET and more, plus a toolcache built for parity with GitHub-hosted runners. Docker is native, with BuildKit, buildx and compose, and QEMU multi-arch builds work without setup.

### Are databases available on the runner?

PostgreSQL 16 and MySQL 8.0 are installed with their services off at boot, so they cost nothing until you start them. Start the service in a step when a job needs it rather than running a service container.

### What if a tool my build needs is missing?

Install it in your job steps exactly as you would on a GitHub-hosted runner; the image is a starting point, not a constraint. If the same install runs on every build, that is the signal to move it into a custom runner image instead.

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
