Files
ssmithx be82d9dd81 Guix router testbed for Raspberry Pi 4 (MT6000 port prep)
Bootable aarch64 image pipeline: cross-build efi-raw image from rpi4.scm
(nonguix linux 6.17 + firmware subsets), inject the Pi boot chain
(start4.elf, u-boot distro boot, DTB, extlinux.conf) with
prepare-rpi-image.sh.  Includes host setup and pitfalls docs, OpenWrt
userland package drafts, and the project plans.
2026-10-12 10:55:30 -04:00

4.2 KiB

Build host setup (Debian 13 x86_64)

Everything done to turn this box into the Guix cross-build host, so it can be reproduced from a clean machine. Run as a user with passwordless sudo.

1. Guix 1.5.0 from the binary tarball

Debian has no guix package. The official binary tarball is at https://ftp.gnu.org/gnu/guix/guix-binary-1.5.0.x86_64-linux.tar.xz (sha512 check against https://ftp.gnu.org/gnu/guix/SHA512SUMS; the .sig is signed by Efraim Flashner, key 41AAE7DCCA3D8351).

curl -sL -o guix-binary.tar.xz \
  https://ftp.gnu.org/gnu/guix/guix-binary-1.5.0.x86_64-linux.tar.xz
sudo tar -C / -xJf guix-binary.tar.xz

2. Build users

sudo groupadd --system guixbuild
for i in $(seq -w 1 30); do
  sudo useradd -g guixbuild -s /usr/sbin/nologin -d /var/empty -M guixbuild$i
done
# IMPORTANT: primary-group membership is not seen by the daemon.
# Add them as explicit members or builds fail with
# "the build users group `guixbuild' has no members":
USERS=$(printf 'guixbuild%02d,' $(seq 1 30) | sed 's/,$//')
sudo groupmod -a -U "$USERS" guixbuild

3. guix-daemon systemd unit

/etc/systemd/system/guix-daemon.service:

[Unit]
Description=Build daemon for the GNU Guix distribution

[Service]
ExecStart=/gnu/store/1hjkcmzrcb0d2sf9afkmyx1pcvln97ss-profile/bin/guix-daemon \
  --build-users-group=guixbuild
Environment=TMPDIR=/var/guix-tmp
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

TMPDIR is required on this host: /tmp is a 7.8 G tmpfs and the kernel build tree needs ~15 G (see PITFALLS #4).

sudo mkdir -m 1777 /var/guix-tmp
sudo systemctl daemon-reload && sudo systemctl enable --now guix-daemon

4. CLI + PATH

mkdir -p ~/.local/bin
ln -sf /gnu/store/1hjkcmzrcb0d2sf9afkmyx1pcvln97ss-profile/bin/guix ~/.local/bin/guix
echo 'export PATH="$HOME/.local/bin:$HOME/.guix-profile/bin:$HOME/.config/guix/current/bin:$PATH"' >> ~/.bashrc

5. Authorize substitutes (critical!)

The binary tarball ships no signing keys — without these the daemon silently rebuilds the entire bootstrap toolchain from source. Check with guix weather <pkg> for "substitutes ... are unauthorized".

P=/gnu/store/1hjkcmzrcb0d2sf9afkmyx1pcvln97ss-profile/share/guix
for f in ci.guix.gnu.org.pub ci.guix.info.pub bordeaux.guix.gnu.org.pub berlin.guix.gnu.org.pub; do
  sudo ~/.local/bin/guix archive --authorize < $P/$f
done
# Nonguix server (for its packages' substitutes, x86_64 at least):
curl -sL https://substitutes.nonguix.org/signing-key.pub \
  | sudo ~/.local/bin/guix archive --authorize

6. QEMU

sudo apt-get install -y qemu-system-arm qemu-utils qemu-efi-aarch64 mtools \
                        qemu-user-static binfmt-support
sudo systemctl enable --now systemd-binfmt   # registers /usr/lib/binfmt.d/qemu-aarch64.conf

qemu-aarch64 binfmt must be active for cross builds that execute target binaries in build phases (binutils info pages, locale dirs, etc.).

7. Nonguix — pinned checkout, not a channel

guix pull is currently broken upstream (PITFALLS #1), and nonguix master requires a newer guix than 1.5.0 (it needs linux-libre-7.2; loading aborts mid-file and leaves a half-initialized module, symptom: linux: unbound variable). Use the newest commit that predates nonguix's linux-6.18:

git clone https://gitlab.com/nonguix/nonguix ~/channels/nonguix
git -C ~/channels/nonguix checkout f5338f6   # 'nongnu: firefox: Update to 147.0'

Load it via environment, not a channel:

export GUIX_PACKAGE_PATH="$HOME/guix-router/packages:$HOME/channels/nonguix"

(~/.config/guix/channels.scm with the nonguix channel + introduction is in place for when guix pull works again.)

8. Reference trees

  • ~/openwrt — shallow clone of OpenWrt master; source of truth for the OpenWrt userland package metadata (package/libs/libubox, package/system/{ubus,uci}) and the MT6000 DTS (target/linux/mediatek/dts/mt7986a-glinet-gl-mt6000.dts).

9. Verify the host

guix build hello                        # substitutes on x86_64 ✓
guix build --system=aarch64-linux bash-minimal   # substitutes on aarch64 ✓
guix weather --system=aarch64-linux coreutils    # "100.0% substitutes available"