A purpose-built Arch Linux ARM image that boots straight into drDRO — full-screen, silent, touch-ready, no desktop. One image covers the Pi 3 / 4 / 5 family. This page explains how it works, how to configure and maintain it, and how to build your own.
Rather than install Raspberry Pi OS and hand-configure Python, Kivy, touch, autostart and the serial link, the appliance image ships all of it pre-baked. Power on and you're in the DRO.
kmsdrm) — full-screen, no display server.For end use, there's nothing to assemble — download the release image, flash it, and boot:
Grab the latest image and write it to an SD card — the full walkthrough (Raspberry Pi Imager or dd, checksum, tested Pi models) is on the Get Started page.
Connect the drDRO board to the Pi's RS-485/UART and attach the touchscreen.
Power on — silent splash, then the app. The root FS grows to the card on the first boot.
The rest of this page is for people who want to configure, maintain, customise or rebuild the image. If you only want a working DRO, Get Started is all you need.
The image is assembled by a single build.sh that runs on a native aarch64 host
(the GitHub ARM64 runner — no qemu):
Downloads and unpacks the Arch Linux ARM rpi-aarch64 tarball.
In a native chroot, replaces ALARM's mainline kernel + U-Boot with linux-rpi — so it direct-boots kernel8.img, our cmdline.txt is authoritative, and the firmware auto-selects the per-board dtb.
pacman -S the packages the Kivy wheel needs: SDL2, mesa (VC4/V3D GL), mtdev (touch), Python, git, NetworkManager, audio, fonts (see packages.txt).
pyenv builds CPython 3.13 and pip installs the app into a venv at /opt/drdro/app/.venv — native aarch64 wheels, so the venv lives inside the image and first boot is offline-clean.
Drops in the launcher, drdro.service and the helper services, and writes config.txt/cmdline.txt.
Builds a 2-partition image (FAT boot + ext4 root) with mke2fs -d + mtools — no loop mounts.
Boot is silent (Plymouth drDRO splash → app). drdro-growfs.service grows the root
partition on first boot; drdro-vt-watch.service hands the screen between the app and the
maintenance consoles.
default / default — in wheel, passwordless sudo.ssh default@<ip>.root/root and alarm/alarm also exist.These are intentionally permissive for setup — change the password (and consider disabling SSH) on a shared network.
The app takes a couple of seconds to release the screen on a VT switch (SDL teardown).
Where things live: the app is at /opt/drdro/app (a git checkout + its .venv), runs as root via drdro.service, and logs to /var/log/drdro/. The image stamps its version at /etc/drdro-release.
| What | Where / how |
|---|---|
| Serial port to the board | App config.ini → serial_port = /dev/serial0 (the Pi's GPIO UART; set by the build). |
| Wi-Fi | From the app's Network screen (NetworkManager / nmcli), or nmcli over SSH. |
| Display | Targets a 1024×600 USB touch panel; mtdev auto-detects the touch controller — no Kivy config needed. |
| Boot / kernel options | boot/config.txt and boot/cmdline.txt (linux-rpi stock + drDRO settings appended). |
| Pi 5 USB power | Ships usb_max_current_enable so a USB touch panel doesn't trip the 600 mA cap. |
| Storage | Root auto-grows on first boot (drdro-growfs.service); no manual resize. |
Building the image requires a native aarch64 host with root (a Raspberry Pi, an aarch64 VM/cloud instance, or the ARM64 CI runner) — there's no qemu emulation step.
git clone https://github.com/bartei/drdro-arch.git
cd drdro-arch
sudo ./build.sh
# -> out/drdro-arch-rpi-aarch64.img
| Variable | Default | Meaning |
|---|---|---|
APP_REF | latest | App version to bake in — newest release tag, or a tag/branch/rev. |
ENABLE_PLYMOUTH | 1 | Silent boot + drDRO splash; 0 = verbose boot. |
BOOT_MB | 128 | Size of the FAT boot partition. |
DRDRO_VERSION | dev | Version stamp (CI passes the real release version). |
WORK / OUT | ./work / ./out | Scratch and output directories. |
gh workflow run build-arch -R bartei/drdro-arch # or push to main
gh run download <run-id> -R bartei/drdro-arch -n drdro-arch-rpi-aarch64
sudo dd if=drdro-arch-rpi-aarch64.img of=/dev/sdX bs=4M conv=fsync status=progress
packages.txt — the pacman runtime package list.overlay/ — files copied onto the rootfs: the launcher & drdro.service, growfs / VT-watch / log-tty3 services, the 99-com.rules udev rule (creates /dev/serial0), Wi-Fi modprobe / powersave tweaks.boot/config.txt, boot/cmdline.txt — firmware & kernel settings.plymouth/theme/ — the boot splash.Rolling release, by design. Each build pulls current Arch packages plus the latest app release (APP_REF=latest), so builds aren't reproducible commit-to-commit — CI is run on demand and images are tested before release. Pin APP_REF to a tag for a repeatable build.
Same tooling as the rest of the project (python-semantic-release, conventional commits): a push to
dev cuts a vX.Y.Z-beta.N prerelease; a push to main cuts a stable
release. Each release publishes a compressed image and checksum:
zstd -d drdro-arch-vX.Y.Z-rpi-aarch64.img.zst
sha256sum -c SHA256SUMS
sudo dd if=drdro-arch-vX.Y.Z-rpi-aarch64.img of=/dev/sdX bs=4M conv=fsync status=progress
The image stamps its own version — cat /etc/drdro-release on a running board.