image:Pick the smallest, fastest image that has the packages you need. This page is a quick selector.
alpine/edge unless you have a specific reason otherwise. Boot is fast (~5 seconds), apk install is fast, packages are recent. Most projects work on Alpine.
alpine/latest is also fine if you want the latest stable rather than edge (rolling).
debian/stable or ubuntu/lts..deb → debian/stable; building a .rpm → fedora/latest; AUR things → archlinux.*.srht.bigb.es and similar)Upstream builds.sr.ht.org ships a large pre-built image catalog. A self-hosted instance ships only:
/var/lib/images/<distro>/<version>/ installed by the builds.sr.ht-images Alpine package. These describe how to build a qcow2 but are not themselves bootable.genimg. Each recipe must be run once (and re-run when you want a fresh base) to produce /var/lib/images/<distro>/<version>/<arch>/root.img.qcow2.Submitting image: <distro>/<version> against a self-hosted instance fails with "no such image" until the qcow2 has been built. Before recommending an image for someone's self-hosted instance, check whether they've built it. The skill's surrounding phoebe-lab/srht repo exposes just list-built-images for this.
Self-hosted instances also commonly ship a subset of the upstream catalog. The builds.sr.ht-images apk package (the source of recipes) does not include 9front or gentoo; instances that want those have to add them manually. Don't assume an image exists on a self-hosted instance just because it works on builds.sr.ht.org.
alpine/*)apk. Install: apk add <pkg> (the manifest's packages: does this).coreutils if a script uses --features not in BusyBox.alpine/edge — rolling, daily refresh.alpine/latest = alpine/3.23 (current stable).alpine/old = alpine/3.22, alpine/older = alpine/3.21, alpine/oldest = alpine/3.20.alpine/edge boots in ~5 seconds. Tiny image.python3 requires py3-pip separately. Go is go. Node is nodejs + npm. Rust is rust + cargo.repo-url key-url key-name in repositories:.archlinux)pacman. Rolling release.yay or paru via packages, then build.debian/<codename>)apt. Older but stable packages.apt-get install needs -y to skip prompts; the manifest's packages: handles this.build-essential.python3 + python3-pip. Node is nodejs + npm (modern Debian).debian/stable = debian/trixie (Debian 13).debian/oldstable = debian/bookworm (Debian 12).debian/testing = debian/forky.debian/unstable = debian/sid.debian/stable / debian/testing and the codenames are valid; pick whichever you'd rather not have to update in two years.amd64, not x86_64.ubuntu/<codename>)apt for packages.ubuntu/lts = ubuntu/resolute (26.04 LTS).ubuntu/oldlts = ubuntu/noble (24.04 LTS).focal (20.04 LTS), jammy (22.04 LTS), oracular (24.10), plucky (25.04), questing (25.10).amd64, not x86_64. Slower boot than Alpine. Larger image.fedora/<version>)dnf. Recent packages.fedora/latest = fedora/43.fedora/rawhide = fedora/44 (pre-release).fedora/42.repositories: invocation differs between Fedora 41+ (dnf config-manager addrepo) and Fedora 40- (dnf config-manager --add-repo); the worker handles it but the .repo file format varies.rockylinux/<version>)dnf. RHEL-compatible (replaces CentOS for RHEL-clone testing).rockylinux/8, rockylinux/9.freebsd/<version>)pkg. BSD make and BSD coreutils.freebsd/latest = freebsd/15.x.freebsd/current = freebsd/16.0-CURRENT (pre-release).freebsd/14.x (14.4-RELEASE).amd64, not x86_64. Custom package repositories are not supported — only the standard pkg repos work.openbsd/<version>)pkg_add. Base system gets syspatch for binary patches.openbsd/latest = openbsd/7.8, openbsd/old = openbsd/7.7.netbsd/<version>)pkgin.netbsd/latest = netbsd/10.x (10.0). Also: netbsd/9.x (9.3).nixos/<channel>)NIX_CONFIG: "experimental-features = nix-command flakes" in environment: to opt in.packages: uses nix-env -iA, so you need a selection path: nixos.hello, not bare hello.nixos/unstable, nixos/latest = nixos/25.05, also nixos/24.11.repositories: (channel-name: channel-url) run nix-channel --add + --update for you. The pre-installed root channel is nixos, pointing at the image's release (or nixos-unstable for nixos/unstable).nix build .#mypackage is the whole task.guix)The upstream sr.ht-docs compatibility matrix (2026) lists these distros for builds.sr.ht:
Alpine, Arch, Debian, Fedora, FreeBSD, Guix, NetBSD, NixOS, OpenBSD, Rocky Linux, Ubuntu.
It does not list Gentoo or 9front. The builds.sr.ht repo's images/ directory contains recipes for the distros above plus qemu and a control script — no gentoo/ or 9front/ directories. Submitting image: gentoo or image: 9front will fail on every standard sr.ht instance (upstream included) with "no such image" until an operator adds and builds those recipes by hand. Do not generate manifests targeting them by default.
Default is x86_64. Other architectures are available on a subset of images:
aarch64 — available on alpine/*, recent debian/*, recent freebsd/*, archlinux (varies).riscv64 — alpine/edge typically.armv7, ppc64le) — case-by-case, check the compatibility page.To use:
image: alpine/edge
arch: aarch64
Not every image+arch combination exists. If submission fails with "no such image", the combination isn't supported.
On the worker, qcow2 disks live at /var/lib/images/<distro>/<version>/<arch>/root.img.qcow2. The /var/lib/images/control script reads arch: from the job, checks that path, and:
/dev/kvm exists → KVM acceleration (~native speed).Recipes (<distro>/<version>/functions) gate which archs they support. Most upstream recipes default to x86_64 and explicitly reject other arches — e.g. Alpine's functions has default_arch=x86_64 and a hard error otherwise. So "this distro supports aarch64" depends on the recipe, not just the worker's QEMU binaries.
For self-hosted instances: adding a new arch means (a) installing qemu-system-<arch> in the worker, (b) patching each recipe's functions to drop the arch guard and fetch arch-specific bootstrap, and (c) rebuilding the qcow2 under the new arch directory. Performance on a mismatched host (e.g. aarch64 on x86_64 hardware) makes this mostly useful for "does it compile?" CI, not real workloads.
For real cross-arch CI, the right pattern is a separate worker on native hardware — builds.sr.ht is multi-worker and the scheduler routes jobs by the arch: field to the worker that has a matching built image.
| Image | Boot speed | Image size | Package recency | Best for |
|---|---|---|---|---|
alpine/edge |
★★★★★ | Tiny | Recent | Default |
archlinux |
★★★★ | Medium | Bleeding-edge | Rolling deps, AUR |
debian/stable |
★★★ | Medium | Stable, older | Debian packaging, glibc |
ubuntu/lts |
★★ | Larger | Stable | Canonical workflows |
fedora/latest |
★★★ | Medium | Recent | RPM packaging |
freebsd/latest |
★★ | Medium | Recent | BSD testing |
nixos/unstable |
★★ | Larger | Rolling | Reproducible builds |
Before committing a manifest, verify the package name in the target image's repos:
Package names vary: ninja (Alpine, Arch, Fedora) vs ninja-build (Debian, Ubuntu). When in doubt, look it up — the failure mode of guessing is a wasted CI run, but the lookup takes 5 seconds.