Skip to content
Latchkey
Documentation menu

What is on the runner image

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

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#

CategoryPreinstalled
Node.js20 (default), 22, 24, with npm and yarn; nvm available
Python3.10 through 3.14, plus pipx and PyPy
Go1.22 through 1.25
Java (Temurin)8, 11, 17, 21, 25, with Maven, Gradle, and Ant
Other languagesRust (stable + rustfmt + clippy), .NET 8/9/10, Ruby (+ fastlane), PHP 8.3 (+ Composer, Xdebug), Haskell, Swift, Kotlin, Julia, PowerShell
ContainersDocker CE with BuildKit, docker buildx, docker compose; Buildah, Podman, Skopeo
BrowsersChrome, Firefox, Edge with matching drivers; Selenium; Android SDK/NDK
DatabasesPostgreSQL 16, MySQL 8.0 (services disabled at boot; start them in your job)
Package managersHomebrew, conda, vcpkg, plus the language-native ones
CLI standardsAWS 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 DockerDocker runs on the host itself: no docker-in-docker workarounds, and BuildKit is on by default.
Multi-arch buildsQEMU/binfmt is preconfigured, so docker buildx --platform linux/amd64,linux/arm64 works out of the box.
GitHub-parity toolcacheactions/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:

Start the service before the steps that use it:

.github/workflows/ci.yml
steps:
  - uses: actions/checkout@v4
  - name: Start PostgreSQL
    run: sudo systemctl start postgresql
  - run: npm test

The same pattern for MySQL 8.0:

.github/workflows/ci.yml
steps:
  - uses: actions/checkout@v4
  - name: Start MySQL
    run: sudo systemctl start mysql
  - run: npm test

Chrome, Firefox, and Edge are preinstalled with matching driver versions, and Selenium is available, so most browser test suites run with no install step at all. For mobile work, the Android SDK and NDK are on the image too.

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.