Denis Pynkin
July 17, 2026
Reading time:
Valve uses an adapted version of the Arch Linux distribution in its products. At Collabora we have been working with Valve on Holo Core, a pure aarch64 port of Arch Linux to be used as the basis for the OS running on the Steam Frame, which uses an aarch64 CPU. Since Arch Linux does not officially support the aarch64 architecture, we have needed to work on the tooling and CI infrastructure to make this possible.
In this first step toward opening up the work on the aarch64 port, we are publishing prepared binaries, their sources, and the development containers we've built from them, allowing anyone to begin to explore the port and experiment with Arch Linux on aarch64:
registry.gitlab.steamos.cloud/holo/holo-core-aarch64-preview/base-develThese published artifacts correspond to a subset of packages from a snapshot of the Arch Linux “state” repository with commit 97c0a0b47d15 with any modifications needed to build for the aarch64 architecture.
At this stage, we have not rebuilt the entire world (all the packages available in the Arch Linux repositories). Our initial goal is to provide the set of packages required for development and image creation for the Steam Frame. Even when limiting ourselves to this subset of Arch Linux packages, including these packages along with their runtime and build dependencies still results in several thousand packages.
The idea behind this port is much more complex than simply recompiling and installing selected packages for the aarch64 architecture. We are trying to solve two main problems:
It is more or less known how to create a port: initial cross-compilation, bootstrap preparation, package rebuilds, and so on. However, it becomes much less obvious when you want the entire process to be reproducible from scratch in CI.
We also have to calculate the correct build order for the dependency tree. Here we encounter the first caveat: we cannot rely entirely on the state Git repository, which tracks the history of the Arch Linux package repositories. In many cases, batches of packages are pushed into the repository in an order that is not suitable for rebuilding, meaning that we have to correct the ordering ourselves to construct a valid build sequence.
Another major challenge comes from the nature of Arch Linux's rolling-release model. While we are preparing the initial port, the packages and their dependency chains keep moving forward, often several steps ahead of the state we had been working on. During the development process, we have already stepped forward to newer snapshots a few times; however, we cannot simply skip intermediate versions because of package interdependencies. Intermediate package versions are often required to build later versions, which in turn are needed for other packages' versions. For example, if you need to rebuild rust 1.91, you must first have 1.90 available, which itself requires 1.89, and so on, all the way back to the version used during bootstrapping. The CI tooling that we have been creating must take this into account.
A similar issue arises with SONAME transitions, especially for libraries that are part of the build infrastructure itself, such as icu or gpgme, both of which are required by pacman. In this instance, the package manager used to perform the build depends on the old library version, while the package manager being produced by the build must depend on the new one; thus, both must be available when the build is performed.
Time is the biggest enemy when trying to replay a historical build sequence. If you try to catch up with Arch Linux by rebuilding packages from months or years ago, you will inevitably discover that the upstream landscape has changed. Sources may have moved, projects may have migrated to different hosting services, checksums of Git sources may change because short commit hashes that were used when the package was created have since been expanded to a longer form, and countless other issues can arise.
You may also face infrastructure problems that did not exist when those package versions were originally released. Nowadays, many upstream services actively defend themselves against aggressive bots and AI crawlers by limiting download rates, restricting connections, or temporarily blocking clients. This can be painful for CI pipelines that rely on downloading sources directly from upstream.
That's not even mentioning packages that are simply not compatible with the aarch64 architecture and require additional patches to build and run correctly. And of course, there are always corner cases and human mistakes to deal with when maintaining your own Arch Linux port. This is far from a complete list of challenges involved in porting a rolling-release distribution, but hopefully provides an idea of the scope of the task.
In order to replay the Arch Linux build history, we had to develop a complex set of tooling to deal with the issues above. Working on the tooling was entirely iterative, bouncing back and forth between bootstraps, build trees and deadlock resolutions, and fixing the tooling to be able to solve those issues and progress past them.
The package tree we've released is not just a one-off tarball drop; this is not the end point. This snapshot serves as a proof of concept demonstrating that the tooling and CI infrastructure can produce a fully functional package tree, and one which can support a product launch.
The tooling can calculate the complete build tree, resolve the full dependency chain, and then "replay" Arch Linux package builds from an initial bootstrap up to a specific snapshot of the state Git repository, including all necessary intermediate rebuilds. The GitLab-based CI is able to build all these packages in a repeatable manner. The tooling is not yet ready to be published; however, our team is working on it.
Whilst the infrastructure developed to this point is capable of building from first principles up until a point-in-time snapshot, the next step is to build this into a system which can track Arch Linux as it is developed. This work will serve as the basis of a continuously-operating CI system capable of shadowing Arch Linux itself. We will work with the upstream Arch Linux project to help Arch with their efforts to port the distribution to aarch64 architecture and work towards automated repeatable builds.<?p>
Even in its preview state, the port is mature enough for experimentation with Arch Linux on aarch64.
If you already have an aarch64 host, you do not need virtualization support or any special setup. However, if you don't have this, you may want to run an aarch64 container on an x86_64 host. To do this, some additional configuration is required. While the instructions were tested on a recent Arch Linux host, they should be suitable for most Linux distributions.
Skip this section if you are able to run the build container on an aarch64 host.
To run an aarch64 container on a host with a different architecture, you need the QEMU user-space emulator and a proper binfmt configuration. Every binary executed inside the container will be started through this mechanism.
Make sure the required QEMU packages are installed:
sudo pacman -S --noconfirm qemu-user-static qemu-user-static-binfmt
In Arch Linux, the default binfmt configuration in /usr/lib/binfmt.d/qemu-aarch64-static.conf uses the :FP flags (see binfmt-misc from kernel docs), preventing execution of sudo and other SUID binaries through qemu-aarch64-static:
$ sudo true sudo: effective uid is not 0, is /usr/bin/sudo on a file system with the 'nosuid' option set or an NFS file system without root privileges?
This prevents makepkg from installing build dependencies automatically, so you may want to enable sudo support inside the container.
Be aware that the following configuration enables execution of SUID-enabled aarch64 binaries globally on your host.
1. Copy the configuration:
sudo cp /usr/lib/binfmt.d/qemu-aarch64-static.conf /etc/binfmt.d/qemu-aarch64-static.conf
2. Add the C (credentials) flag:
sudo sed -i -e "s/:FP$/:FCP/" /etc/binfmt.d/qemu-aarch64-static.conf
3. Re-register the configuration:
sudo systemctl restart systemd-binfmt.service
The base-devel container image is available at:
registry.gitlab.steamos.cloud/holo/holo-core-aarch64-preview/base-devel
This image can be used with Docker or Podman. In this example we will use distrobox to simplify the setup.
1. Install distrobox:
sudo pacman -S --noconfirm distrobox
2. Since Distrobox uses user-ID mapping for rootless containers, verify that correct UID/GID mappings exist:
$ grep "$USER" /etc/subuid /etc/subgid $ sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER
3. Create the container:
distrobox create \ --platform linux/arm64 \ --image registry.gitlab.steamos.cloud/holo/holo-core-aarch64-preview/base-devel:latest \ --name builder
After downloading the image, you can enter the aarch64 container and verify that it works correctly:
$ distrobox enter builder Starting container... [ OK ] Installing basic packages... [ OK ] Setting up devpts mounts... [ OK ] Setting up read-only mounts... [ OK ] Setting up read-write mounts... [ OK ] Setting up host's sockets integration... [ OK ] Integrating host's themes, icons, fonts... [ OK ] Setting up distrobox profile... [ OK ] Setting up sudo... [ OK ] Setting up user's group list... [ OK ] Setting up existing user - shell... [ OK ] Setting up existing user - groups... [ OK ] Ensuring user's access... [ OK ] Container Setup Complete! [user@builder ~]$ file /bin/bash /bin/bash: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=6b5cf11c690122687bb20c169b56aadf44a9aeb6, for GNU/Linux 4.4.0, stripped [user@builder ~]$ cat /etc/os-release NAME="Holo core Aarch64 port (preview)" PRETTY_NAME="Holo core Aarch64 port (preview)" ID=holo-core ID_LIKE=arch VARIANT_ID=aarch64-preview ANSI_COLOR="1;35" HOME_URL="https://gitlab.steamos.cloud/holo/holo-core-aarch64-preview" LOGO=holo VERSION_ID=mash-20251118.1 BUILD_ID=240949 [user@builder ~]$ sudo pacman -Syu :: Synchronizing package databases... core is up to date extra is up to date :: Starting full system upgrade... there is nothing to do [user@builder ~]$ exit logout $
The build container is now ready for testing package builds using the packages published in the preview repository.
Clone the repository and build any available package:
$ git clone https://gitlab.steamos.cloud/holo/holo-core-aarch64-preview $ cd holo-core-aarch64-preview/core-aarch64/c/coreutils/9.9-1 $ distrobox enter builder -- gpg --import keys/pgp/*.asc $ distrobox enter builder -- makepkg --cleanbuild --noconfirm --syncdeps
The build process may take a while. Remember that on an x86_64 host every `aarch64` binary is executed through emulation.
Once the build finishes, you will obtain a package for the aarch64 architecture.
We are continuing to work on the tooling, with the primary aim to be able to efficiently keep the aarch64 port up-to-date with the package revisions that are being used to develop future versions of the amd64/x86_64 flavor of SteamOS. We are proud of what we have achieved so far and hope to provide access to the tooling in the near future. We have aspirations to open this up far more and work on a common approach with those interested in bringing both CI infrastructure and a aarch64 port to the upstream Arch Linux distribution, providing some benefit back to the community which provides the foundations on which SteamOS is built!
17/07/2026
The Holo Core aarch64 preview provides early binaries, sources, and containers for an Arch Linux-based aarch64 port, backed by tooling and…
16/07/2026
Weston 16 expands HDR and color management support, improves Perfetto debugging and DRM backend performance, and adds new protocol and renderer…
13/07/2026
Next week we'll be in Santa Fe, Argentina, for DebConf 2026! Catch our 2 talks covering the latest Apertis developments and toolkits in…