#!/usr/bin/env bash set -Eeuo pipefail state=/var/lib/makepad-provision seed=/run/makepad-seed mkdir -p "$state" "$seed" exec > >(tee -a /var/log/makepad-provision.log) 2>&1 trap 'rc=$?; printf "FAILED at line %s (exit %s); see /var/log/makepad-provision.log\n" "$LINENO" "$rc" > "$state/status"; exit "$rc"' ERR test ! -f "$state/complete" || exit 0 stage() { printf '%s\n' "$*" | tee "$state/status"; } stage 'Preparing persistent root filesystem' if ! mountpoint -q "$seed"; then device=/dev/disk/by-label/CIDATA test -e "$device" || device=/dev/disk/by-label/cidata mount -o ro "$device" "$seed" fi btrfs filesystem resize max / test "$(df --output=avail -B1 / | tail -1)" -gt 25000000000 stage 'Verifying USB payload checksums' (cd "$seed" && sha256sum --quiet -c sha256sums) if test ! -f "$state/mirror-extracted"; then stage 'Unpacking the offline Arch package mirror' mkdir -p /var/cache/makepad-mirror cat "$seed"/mirror-*.tar | tar --no-same-owner -xf - -C /var/cache/makepad-mirror touch "$state/mirror-extracted" fi stage 'Initializing package signing keys' pacman-key --init pacman-key --populate archlinux stage 'Installing signed Arch packages from the USB cache' # A temporary config leaves the normal pacman mirror configuration intact. cat > /run/makepad-pacman.conf <<'EOF' [options] Architecture = x86_64 SigLevel = Required DatabaseOptional LocalFileSigLevel = Required ParallelDownloads = 8 CacheDir = /var/cache/pacman/pkg CacheDir = /var/cache/makepad-mirror/core/os/x86_64 CacheDir = /var/cache/makepad-mirror/extra/os/x86_64 [core] Server = file:///var/cache/makepad-mirror/core/os/x86_64 [extra] Server = file:///var/cache/makepad-mirror/extra/os/x86_64 EOF mapfile -t packages < "$seed/requested-packages.txt" # Match the JACK provider used when resolving the offline package cache. # Also handles seeds assembled before this provider was an explicit target. if [[ " ${packages[*]} " != *" pipewire-jack "* ]]; then packages+=(pipewire-jack) fi pacman --config /run/makepad-pacman.conf -U --needed --noconfirm /var/cache/makepad-mirror/core/os/x86_64/archlinux-keyring-*.pkg.tar.zst # Full upgrade against one consistent repository snapshot; never a partial -Sy. # Adopt only the Ethernet firmware copied by firstboot before pacman was ready. pacman --config /run/makepad-pacman.conf -Syu --needed --noconfirm --overwrite 'usr/lib/firmware/rtl_nic/*' "${packages[@]}" stage 'Configuring graphics, CUDA, sound, and boot' usermod -aG wheel,audio,video,input,render,storage,uucp,games arch visudo -cf /etc/sudoers.d/10-arch cat > /etc/modprobe.d/makepad-nvidia.conf <<'EOF' options nvidia_drm modeset=1 fbdev=1 EOF cat > /etc/modprobe.d/makepad-no-nouveau.conf <<'EOF' blacklist nouveau options nouveau modeset=0 EOF mkdir -p /etc/mkinitcpio.conf.d cat > /etc/mkinitcpio.conf.d/makepad.conf <<'EOF' MODULES+=(nvidia nvidia_modeset nvidia_uvm nvidia_drm r8169 xhci_pci usbhid) HOOKS=(base systemd microcode modconf kms keyboard sd-vconsole block filesystems fsck) EOF cat > /etc/profile.d/makepad-cuda.sh <<'EOF' export CUDA_HOME=/opt/cuda export CUDA_PATH=/opt/cuda # Builds link CUDA only from a root named here (never a scanned system install). export MAKEPAD_CUDA_ROOT=/opt/cuda export NVCC_CCBIN=/usr/bin/g++-15 export CUDAHOSTCXX=/usr/bin/g++-15 case :$PATH: in *:/opt/cuda/bin:*) ;; *) export PATH=/opt/cuda/bin:$PATH ;; esac EOF # PAM also supplies these to non-login SSH commands used by build automation. cat >> /etc/environment <<'EOF' CUDA_HOME=/opt/cuda CUDA_PATH=/opt/cuda MAKEPAD_CUDA_ROOT=/opt/cuda NVCC_CCBIN=/usr/bin/g++-15 CUDAHOSTCXX=/usr/bin/g++-15 EOF printf '/opt/cuda/lib64\n/opt/cuda/targets/x86_64-linux/lib\n' > /etc/ld.so.conf.d/makepad-cuda.conf ldconfig sed -i '/^GRUB_CMDLINE_LINUX_DEFAULT=/c\GRUB_CMDLINE_LINUX_DEFAULT="rootflags=compress=zstd:1 nvidia_drm.modeset=1 nvidia_drm.fbdev=1 console=tty1 loglevel=3 module_blacklist=bluetooth,btusb"' /etc/default/grub sed -i '/^GRUB_TERMINAL=/c\GRUB_TERMINAL="console"' /etc/default/grub sed -i '/^GRUB_TIMEOUT=/c\GRUB_TIMEOUT=0' /etc/default/grub if grep -q '^GRUB_TIMEOUT_STYLE=' /etc/default/grub; then sed -i '/^GRUB_TIMEOUT_STYLE=/c\GRUB_TIMEOUT_STYLE=hidden' /etc/default/grub else printf 'GRUB_TIMEOUT_STYLE=hidden\n' >> /etc/default/grub fi mkinitcpio -P grub-mkconfig -o /boot/grub/grub.cfg systemctl set-default multi-user.target systemctl enable sshd systemd-resolved systemd-timesyncd systemctl mask systemd-networkd-wait-online.service systemd-time-wait-sync.service pacman-init.service bluetooth.service wpa_supplicant.service systemctl --global enable pipewire.socket pipewire-pulse.socket wireplumber.service loginctl enable-linger arch systemctl enable --now makepad-mount-win.service systemctl unmask iwd.service systemctl enable --now iwd.service networkctl reload stage 'Installing pinned Fanatec driver source and DKMS module' fanatec_version=0.0.dd78ef477c0d fanatec_source=/usr/src/hid-fanatec-$fanatec_version mkdir -p "$fanatec_source" tar -xzf "$seed/fanatec.tgz" --strip-components=1 -C "$fanatec_source" find "$fanatec_source" -type f \( -name dkms.conf -o -name '*.c' \) -exec sed -i "s/#VERSION#/$fanatec_version/g" {} + install -m 0644 "$fanatec_source/fanatec.rules" /etc/udev/rules.d/99-fanatec.rules if ! dkms status -m hid-fanatec -v "$fanatec_version" | grep -q .; then dkms add -m hid-fanatec -v "$fanatec_version" fi fanatec_ok=yes for directory in /usr/lib/modules/*; do test -d "$directory/build" || continue kernel=${directory##*/} if ! dkms install -m hid-fanatec -v "$fanatec_version" -k "$kernel"; then fanatec_ok=no fi done printf '%s\n' "$fanatec_ok" > "$state/fanatec-built" install -o root -g root -m 0755 "$seed/gbelt-bind.sh" /usr/local/sbin/makepad-gbelt-bind install -o root -g root -m 0644 "$seed/70-makepad-game-hardware.rules" /etc/udev/rules.d/70-makepad-game-hardware.rules udevadm control --reload-rules stage 'Unpacking the Makepad source snapshot and Cargo cache' mkdir -p /home/arch/makepad /home/arch/.cargo if test ! -f "$state/source-installed"; then tar -xzf "$seed/makepad-source.tgz" -C /home/arch/makepad tar -xf "$seed/cargo-cache.tar" -C /home/arch/.cargo touch "$state/source-installed" fi stage 'Installing the offline Linux CEF distribution' cef_root=/home/arch/makepad/local/cef-prebuilt cef_directory=$(cat "$seed/cef-directory.txt") [[ "$cef_directory" = cef_binary_*_linux64 && "$cef_directory" != */* ]] mkdir -p "$cef_root" if test ! -f "$state/cef-installed"; then tar --no-same-owner -xjf "$seed/cef-linux.bz2" -C "$cef_root" test -f "$cef_root/$cef_directory/Release/libcef.so" ln -sfn "$cef_directory" "$cef_root/current-linux64" touch "$state/cef-installed" fi chown -R arch:arch /home/arch/makepad /home/arch/.cargo install -o arch -g arch -m 0644 "$seed/source-revision.txt" /home/arch/makepad/SOURCE-REVISION.txt runuser -u arch -- git -C /home/arch/makepad init runuser -u arch -- git -C /home/arch/makepad lfs install --local stage 'Installing the direct Vulkan WM launcher' install -d /etc/makepad install -m 0755 "$seed/wm-session.sh" /usr/local/bin/makepad-wm-session install -m 0644 "$seed/wm.env" /etc/makepad/wm.env install -m 0644 "$seed/makepad-wm.service" /etc/systemd/system/makepad-wm.service install -m 0755 "$seed/aihub-session.sh" /usr/local/bin/makepad-aihub-session install -m 0644 "$seed/aihub.env" /etc/makepad/aihub.env install -m 0644 "$seed/makepad-aihub.service" /etc/systemd/system/makepad-aihub.service systemctl daemon-reload systemctl enable makepad-wm.service makepad-aihub.service stage 'Recording installed tool versions' source /etc/profile.d/makepad-cuda.sh { rustc --version cargo --version nvcc --version pacman -Q linux nvidia-open nvidia-utils cuda cudnn lspci -nnk lsusb dkms status } > "$state/installed.txt" 2>&1 if test -f "$seed/clone.json"; then stage 'Installing the verified release WM and AI Hub from the working clone' install -d -o arch -g arch /home/arch/makepad/target/release install -o arch -g arch -m 0755 "$seed/wm" /home/arch/makepad/target/release/wm install -o arch -g arch -m 0755 "$seed/makepad-ai-hub" /home/arch/makepad/target/release/makepad-ai-hub install -o arch -g arch -m 0644 "$seed/clone.json" /home/arch/makepad/CLONE-REVISION.json else stage 'Building release WM and CUDA AI Hub offline' runuser -u arch -- env HOME=/home/arch MAKEPAD=linux_direct+vulkan CARGO_NET_OFFLINE=true MAKEPAD_CEF_OFFLINE=1 MAKEPAD_CUDA_ROOT=/opt/cuda NVCC_CCBIN=/usr/bin/g++-15 CUDAHOSTCXX=/usr/bin/g++-15 PATH="$PATH" bash -c 'cd /home/arch/makepad && cargo build --offline --release -p makepad-wm -p makepad-app-ai-hub' fi sshd -t systemctl reload sshd touch "$state/complete" touch /etc/cloud/cloud-init.disabled if test "$fanatec_ok" = yes; then stage 'Package setup complete. Reboot required for the installed kernel and NVIDIA driver.' else stage 'Package setup complete; Fanatec DKMS needs inspection. Reboot required for the installed kernel/NVIDIA driver.' fi # Keep SSH available for inspection. The operator can reboot when ready.