Ship I38 in Pi images by default
Add the I38 desktop stack to the Raspberry Pi image build, including Cthulhu, XLibre, nodm, xorg-xinit, and I38 runtime Python dependencies. Generate the default stormux user's I38 configuration during image creation with the non-interactive I38 mode, configure nodm for that generated xinitrc, and set Speech Dispatcher to use RHVoice by default. Harden the Pi build for larger GUI images by raising the default image size to 8 GB, skipping mkinitcpio autodetect for the target image initramfs, and validating the root filesystem before compression. Rework first boot so volume calibration runs before Fenrir starts, temporary tty1 autologin and passwordless sudo are removed during setup, I38/nodm startup is selected explicitly, and physical versus headless X configuration is written before nodm starts. Document the Pi GUI rollout in gui.md and refresh README size and desktop references.
This commit is contained in:
+5
-5
@@ -1,6 +1,6 @@
|
||||
# Stormux Pi Image Builder
|
||||
|
||||
Stormux provides an Arch-based Raspberry Pi image that already includes Fenrir, Orca, and other screen-reader friendly defaults. This repository hosts the scripts maintained by the Stormux community (originally crafted by Storm) so anyone can rebuild the image, customize the overlay, and share accessible Pi spins.
|
||||
Stormux provides an Arch-based Raspberry Pi image that already includes Fenrir, Cthulhu, I38, and other screen-reader friendly defaults. This repository hosts the scripts maintained by the Stormux community (originally crafted by Storm) so anyone can rebuild the image, customize the overlay, and share accessible Pi spins.
|
||||
|
||||
## Purpose & Scope
|
||||
This repo captures the complete build pipeline for the Stormux Raspberry Pi images: bootstrapping Arch Linux ARM, layering the accessible defaults, installing Fenrir and helper tools, and producing a compressed ready-to-flash image. Running the script yourself lets you reproduce the same system the project ships for Raspberry Pi 4/5-class systems, tweak it, and publish new spins without reverse-engineering the original release.
|
||||
@@ -9,7 +9,7 @@ This repo captures the complete build pipeline for the Stormux Raspberry Pi imag
|
||||
- A 64-bit Arch Linux host (bare metal or VM) with at least 20 GB free disk space.
|
||||
- Root access on that host. The builder partitions loopback devices and must run as root.
|
||||
- Required packages: `arch-install-scripts`, `dosfstools`, `parted`, `qemu-user-static`, `qemu-user-static-binfmt`, plus standard developer tools that Arch already ships.
|
||||
- A Raspberry Pi 4, Raspberry Pi 400, Raspberry Pi 5, or compatible board, plus a microSD card (8 GB or larger recommended).
|
||||
- A Raspberry Pi 4, Raspberry Pi 400, Raspberry Pi 5, or compatible board, plus a microSD card (16 GB or larger recommended).
|
||||
|
||||
Install dependencies on the build host with:
|
||||
```bash
|
||||
@@ -31,13 +31,13 @@ The script is designed for an x86_64 Arch host so it can emulate ARM binaries wi
|
||||
1. Become root (`sudo -i`) so the script can create loop devices and mount them.
|
||||
2. From `/path/to/stormux`, run:
|
||||
```bash
|
||||
sudo ./pi4/build/build-stormux.sh -l en_US -s 6
|
||||
sudo ./pi4/build/build-stormux.sh -l en_US -s 8
|
||||
```
|
||||
- The builder creates an aarch64 image for Raspberry Pi 4/5-class systems.
|
||||
- `-l en_US` selects the locale (use `es_ES`, `fr_FR`, etc.).
|
||||
- `-s 6` sets the image size in gigabytes.
|
||||
- `-s 8` sets the image size in gigabytes.
|
||||
- Add `-n my-stormux.img` to override the default filename.
|
||||
3. Grab coffee. The script bootstraps Arch Linux ARM, provisions packages (Fenrir, Orca, NetworkManager, PipeWire, etc.), copies the overlay from `pi4/files/`, installs the latest `sas`, cleans up, compresses the image, and writes a SHA-1 checksum.
|
||||
3. Grab coffee. The script bootstraps Arch Linux ARM, provisions packages (Fenrir, Cthulhu, I38, XLibre, NetworkManager, PipeWire, etc.), copies the overlay from `pi4/files/`, installs the latest `sas`, cleans up, compresses the image, and writes a SHA-1 checksum.
|
||||
4. When the `build-stormux.sh` command returns, you should have an `.img.xz` file and matching `.sha1sum` in your working directory (for example `stormux-rpi4-5-aarch64-YYYY-MM-DD.img.xz`).
|
||||
|
||||
If the build is interrupted, run `sudo umount -R /mnt && sudo losetup -D` to be sure nothing is still mounted.
|
||||
|
||||
@@ -68,6 +68,14 @@ cleanup_image() {
|
||||
return "$cleanupStatus"
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2329 # validate_image_filesystems is invoked from finish_build
|
||||
validate_image_filesystems() {
|
||||
local rootPartition="${loopdev}p2"
|
||||
|
||||
echo "Checking root filesystem..."
|
||||
e2fsck -f -n "$rootPartition"
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2329 # cleanup is invoked via trap EXIT
|
||||
cleanup() {
|
||||
local status=$? # capture original exit status so failures propagate
|
||||
@@ -86,6 +94,19 @@ cleanup() {
|
||||
}
|
||||
|
||||
finish_build() {
|
||||
if [[ $mounted -eq 0 ]]; then
|
||||
if ! umount -R /mnt; then
|
||||
echo "Image build commands completed, but unmounting failed."
|
||||
exit 1
|
||||
fi
|
||||
mounted=1
|
||||
fi
|
||||
|
||||
if ! validate_image_filesystems; then
|
||||
echo "Image filesystem validation failed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
trap - EXIT
|
||||
|
||||
if ! cleanup_image; then
|
||||
@@ -148,7 +169,7 @@ declare -A command=(
|
||||
[h]="This help screen."
|
||||
[l:]="Language default is en_US."
|
||||
[n:]="Image name, default is stormux-rpi4-5-aarch64-<yyyy-mm-dd>.img"
|
||||
[s:]="image size in GB, default is 6."
|
||||
[s:]="image size in GB, default is 8."
|
||||
)
|
||||
|
||||
# Convert the keys of the associative array to a format usable by getopts
|
||||
@@ -178,7 +199,7 @@ while getopts "${args}" i ; do
|
||||
done
|
||||
|
||||
# make sure variables are set, or use defaults.
|
||||
export imageSize="${imageSize:-6G}"
|
||||
export imageSize="${imageSize:-8G}"
|
||||
imageName="${imageName:-stormux-rpi4-5-aarch64-$(date '+%Y-%m-%d').img}"
|
||||
export imageName
|
||||
export imageLanguage="${imageLanguage:-en_US.UTF-8}"
|
||||
@@ -362,6 +383,7 @@ packages=(
|
||||
gstreamer
|
||||
gst-plugins-base
|
||||
gst-plugins-good
|
||||
i38
|
||||
ii
|
||||
# Keep Pi onboard firmware plus common USB/network chipset firmware without
|
||||
# pulling in unrelated desktop/server GPU firmware.
|
||||
@@ -373,6 +395,7 @@ packages=(
|
||||
man
|
||||
man-pages
|
||||
networkmanager
|
||||
nodm-dgw
|
||||
openssh
|
||||
parted
|
||||
pipewire
|
||||
@@ -382,10 +405,13 @@ packages=(
|
||||
poppler
|
||||
python-dbus
|
||||
python-gobject
|
||||
python-msgpack
|
||||
python-pyenchant
|
||||
python-pyte
|
||||
python-pyperclip
|
||||
python-tornado
|
||||
raspberrypi-utils
|
||||
cthulhu
|
||||
socat
|
||||
realtime-privileges
|
||||
rhvoice-voice-bdl
|
||||
@@ -401,6 +427,11 @@ packages=(
|
||||
vi
|
||||
xdg-user-dirs
|
||||
xdg-utils
|
||||
xlibre-input-libinput
|
||||
xlibre-video-dummy-with-vt
|
||||
xlibre-video-fbdev
|
||||
xlibre-xserver
|
||||
xorg-xinit
|
||||
yay
|
||||
)
|
||||
|
||||
@@ -413,7 +444,7 @@ install_sas
|
||||
# See: https://archlinuxarm.org/forum/viewtopic.php?t=16672
|
||||
if [[ -f /etc/mkinitcpio.d/linux-rpi.preset ]]; then
|
||||
echo "Configuring mkinitcpio preset to skip kms hook..."
|
||||
sed -i "s/^default_options=.*/default_options=\"--skiphook kms\"/" /etc/mkinitcpio.d/linux-rpi.preset
|
||||
sed -i "s/^default_options=.*/default_options=\"-S autodetect --skiphook kms\"/" /etc/mkinitcpio.d/linux-rpi.preset
|
||||
sed -i "s/^fallback_options=.*/fallback_options=\"-S autodetect --skiphook kms\"/" /etc/mkinitcpio.d/linux-rpi.preset
|
||||
fi
|
||||
|
||||
@@ -435,8 +466,10 @@ echo 'Stormux \r (\l)' > /etc/issue
|
||||
echo >> /etc/issue
|
||||
# Create the stormux user
|
||||
useradd -m -g users -G wheel,realtime,audio,video,network,brlapi -s /bin/bash stormux
|
||||
# Grant sudo privileges to the stormux user for package installation.
|
||||
echo 'stormux ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers.d/wheel
|
||||
# Grant normal sudo privileges plus temporary first-boot passwordless sudo.
|
||||
echo '%wheel ALL=(ALL) ALL' > /etc/sudoers.d/wheel
|
||||
echo 'stormux ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/zz-stormux-first-boot
|
||||
chmod 440 /etc/sudoers.d/wheel /etc/sudoers.d/zz-stormux-first-boot
|
||||
# Set the password for the root user
|
||||
echo -e "root\nroot" | passwd "root"
|
||||
# Set the password for the stormux user
|
||||
@@ -449,13 +482,39 @@ git config --global init.defaultBranch master
|
||||
# Create desktop, downloads, music, and other directories.
|
||||
xdg-user-dirs-update
|
||||
exit
|
||||
mkdir -p /home/stormux/git
|
||||
chown stormux:users /home/stormux/git
|
||||
if ! sudo -u stormux git clone --depth 1 https://git.stormux.org/storm/I38 /home/stormux/git/I38; then
|
||||
echo "Failed to clone I38."
|
||||
exit 1
|
||||
fi
|
||||
cd /home/stormux/git/I38
|
||||
sudo -u stormux ./i38.sh -D
|
||||
cd /
|
||||
if [[ -f /etc/nodm.conf ]]; then
|
||||
sed -i \
|
||||
-e "s/{user}/stormux/g" \
|
||||
-e "s#^NODM_USER=.*#NODM_USER='stormux'#" \
|
||||
-e "s#^NODM_XSESSION=.*#NODM_XSESSION='/home/stormux/.xinitrc'#" \
|
||||
/etc/nodm.conf
|
||||
fi
|
||||
if command -v spd-conf > /dev/null 2>&1; then
|
||||
spd-conf -n -C || echo "Warning: Speech Dispatcher system configuration failed."
|
||||
fi
|
||||
if [[ -f /etc/speech-dispatcher/speechd.conf ]]; then
|
||||
if grep -qE '^[[:space:]]*#?[[:space:]]*DefaultModule[[:space:]]+' /etc/speech-dispatcher/speechd.conf; then
|
||||
sed -i -E 's/^[[:space:]]*#?[[:space:]]*DefaultModule[[:space:]]+.*/DefaultModule rhvoice/' /etc/speech-dispatcher/speechd.conf
|
||||
else
|
||||
printf '\nDefaultModule rhvoice\n' >> /etc/speech-dispatcher/speechd.conf
|
||||
fi
|
||||
fi
|
||||
# Enable linger so that hopefully sound will start at login.
|
||||
mkdir -p /var/lib/systemd/linger
|
||||
touch /var/lib/systemd/linger/stormux
|
||||
systemctl --global enable pipewire.service pipewire-pulse.service
|
||||
/usr/share/fenrirscreenreader/tools/configure_pipewire.sh
|
||||
sudo -u stormux /usr/share/fenrirscreenreader/tools/configure_pipewire.sh
|
||||
# Configure sudo for group wheel, remove nopasswd for the stormux user
|
||||
# Ensure normal sudo remains configured after first-boot cleanup removes NOPASSWD.
|
||||
echo '%wheel ALL=(ALL) ALL' > /etc/sudoers.d/wheel
|
||||
# Set the hostname
|
||||
echo stormux > /etc/hostname
|
||||
@@ -466,7 +525,6 @@ services=(
|
||||
brltty.path
|
||||
cronie.service
|
||||
fake-hwclock.service
|
||||
fenrirscreenreader.service
|
||||
log-to-ram-setup.service
|
||||
log-to-ram-sync.timer
|
||||
log-to-ram-shutdown.service
|
||||
|
||||
Reference in New Issue
Block a user