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:
@@ -28,6 +28,81 @@ fi
|
||||
# Volume calibration is now handled in stormux_first_boot.sh
|
||||
|
||||
export DIALOGOPTS='--insecure --no-lines --visit-items'
|
||||
i38StartAtBoot=0
|
||||
firstBootSudoersFile="/etc/sudoers.d/zz-stormux-first-boot"
|
||||
firstBootAutologinFile="/etc/systemd/system/getty@tty1.service.d/stormux-first-boot-autologin.conf"
|
||||
firstBootAutologinDir="${firstBootAutologinFile%/*}"
|
||||
|
||||
read_yes_no() {
|
||||
local answer
|
||||
while true; do
|
||||
echo "$1"
|
||||
echo "Press y for yes or n for no followed by enter."
|
||||
read -r answer
|
||||
answer="${answer::1}"
|
||||
case "${answer,,}" in
|
||||
y)
|
||||
return 0
|
||||
;;
|
||||
n)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
echo "Please answer y or n."
|
||||
done
|
||||
}
|
||||
|
||||
cleanup_first_boot_access() {
|
||||
rm -f "$firstBootSudoersFile" "$firstBootAutologinFile"
|
||||
rmdir --ignore-fail-on-non-empty "$firstBootAutologinDir"
|
||||
systemctl daemon-reload
|
||||
}
|
||||
|
||||
configure_physical_screen() {
|
||||
sudo "${sudoFlags[@]}" mkdir -p /etc/X11/xorg.conf.d
|
||||
sudo "${sudoFlags[@]}" tee /etc/X11/xorg.conf.d/10-screendriver.conf > /dev/null << 'EOF'
|
||||
Section "OutputClass"
|
||||
Identifier "vc4"
|
||||
MatchDriver "vc4"
|
||||
Driver "modesetting"
|
||||
Option "PrimaryGPU" "true"
|
||||
EndSection
|
||||
EOF
|
||||
}
|
||||
|
||||
configure_headless_screen() {
|
||||
sudo "${sudoFlags[@]}" mkdir -p /etc/X11/xorg.conf.d
|
||||
sudo "${sudoFlags[@]}" tee /etc/X11/xorg.conf.d/10-screendriver.conf > /dev/null << 'EOF'
|
||||
Section "Monitor"
|
||||
Identifier "dummy_monitor"
|
||||
HorizSync 28.0-80.0
|
||||
VertRefresh 48.0-75.0
|
||||
Modeline "1920x1080" 172.80 1920 2040 2248 2576 1080 1081 1084 1118
|
||||
EndSection
|
||||
|
||||
Section "Device"
|
||||
Identifier "dummy_card"
|
||||
Driver "dummy"
|
||||
VideoRam 256000
|
||||
Option "UseFBDev" "false"
|
||||
EndSection
|
||||
|
||||
Section "Screen"
|
||||
Identifier "dummy_screen"
|
||||
Device "dummy_card"
|
||||
Monitor "dummy_monitor"
|
||||
SubSection "Display"
|
||||
Depth 24
|
||||
Modes "1920x1080"
|
||||
EndSubSection
|
||||
EndSection
|
||||
|
||||
Section "ServerLayout"
|
||||
Identifier "dummy_layout"
|
||||
Screen 0 "dummy_screen"
|
||||
EndSection
|
||||
EOF
|
||||
}
|
||||
|
||||
set_timezone() {
|
||||
# Get the list of timezones
|
||||
@@ -58,26 +133,40 @@ set_timezone() {
|
||||
timedatectl set-ntp true
|
||||
}
|
||||
# Offer to switch fenrir layout.
|
||||
echo "Would you like to switch Fenrir to laptop layout?"
|
||||
echo "Press y for yes or n for no followed by enter."
|
||||
read -r continue
|
||||
continue="${continue::1}"
|
||||
if [[ "${continue,}" == "y" ]];then
|
||||
if read_yes_no "Would you like to switch Fenrir to laptop layout?"; then
|
||||
sed -i 's/=desktop/=laptop/' /etc/fenrirscreenreader/settings/settings.conf
|
||||
clear
|
||||
systemctl restart fenrirscreenreader.service
|
||||
fi
|
||||
|
||||
if command -v i3 > /dev/null 2>&1 && systemctl list-unit-files nodm.service > /dev/null 2>&1; then
|
||||
if read_yes_no "Will this Pi be connected to a physical screen?"; then
|
||||
configure_physical_screen
|
||||
else
|
||||
configure_headless_screen
|
||||
fi
|
||||
if read_yes_no "Should I38 start at boot?"; then
|
||||
sudo "${sudoFlags[@]}" systemctl --quiet enable nodm.service
|
||||
i38StartAtBoot=1
|
||||
if read_yes_no "Should Fenrir run in the console at boot?"; then
|
||||
sudo "${sudoFlags[@]}" systemctl --quiet enable fenrirscreenreader.service
|
||||
else
|
||||
sudo "${sudoFlags[@]}" systemctl --quiet disable fenrirscreenreader.service
|
||||
fi
|
||||
else
|
||||
sudo "${sudoFlags[@]}" systemctl --quiet disable nodm.service
|
||||
sudo "${sudoFlags[@]}" systemctl --quiet enable fenrirscreenreader.service
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check for possible resize
|
||||
diskSource="$(df --output='source' / | tail -1)"
|
||||
diskSize="$(df -h --output='size' / | tail -1 | tr -cd '[:digit:].')"
|
||||
diskSize=${diskSize%.*}
|
||||
if [[ $diskSize -le 7 ]]; then
|
||||
echo "$diskSource is only $diskSize gigs, which means it probably needs to be resized. Would you like to do this now?"
|
||||
echo "Press y for yes or n for no followed by enter."
|
||||
read -r continue
|
||||
continue="${continue::1}"
|
||||
if [[ "${continue,}" == "y" ]];then
|
||||
resizeThreshold=9
|
||||
if [[ $diskSize -le $resizeThreshold ]]; then
|
||||
if read_yes_no "$diskSource is only $diskSize gigs, which means it probably needs to be resized. Would you like to do this now?"; then
|
||||
resizeLog="/tmp/stormux-resize.log"
|
||||
# Extract base device name (handles mmcblk0p2, nvme0n1p2, sda2, etc.)
|
||||
if [[ "$diskSource" =~ (.*[0-9]+)p[0-9]+$ ]]; then
|
||||
# Handle mmcblk0p2, nvme0n1p2 style
|
||||
@@ -87,14 +176,19 @@ if [[ $diskSize -le 7 ]]; then
|
||||
# shellcheck disable=SC2001
|
||||
diskDevice="$(echo "$diskSource" | sed 's/[0-9]*$//')"
|
||||
fi
|
||||
echo "Yes" | sudo "${sudoFlags[@]}" parted ---pretend-input-tty "$diskDevice" resizepart 2 100%
|
||||
sudo "${sudoFlags[@]}" resize2fs -f "$diskSource"
|
||||
echo "Resizing the filesystem. This may take a few minutes."
|
||||
if { echo "Yes" | sudo "${sudoFlags[@]}" parted ---pretend-input-tty "$diskDevice" resizepart 2 100%; } > "$resizeLog" 2>&1 \
|
||||
&& { sudo "${sudoFlags[@]}" resize2fs -f "$diskSource"; } >> "$resizeLog" 2>&1; then
|
||||
echo "Resize complete."
|
||||
else
|
||||
echo "Resize failed. Details are in $resizeLog."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! ping -c1 stormux.org &> /dev/null ; then
|
||||
echo "No internet connection detected. Press enter to open NetworkManager."
|
||||
read -r continue
|
||||
read -r _
|
||||
echo "setting set focus#highlight=True" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
nmtui-connect
|
||||
echo "setting set focus#highlight=False" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
@@ -112,7 +206,7 @@ if ping -qc1 -W 1 stormux.org &> /dev/null; then
|
||||
read -rp "Would you like the time to sync as soon as the Pi connects to the internet? " answer
|
||||
answer="${answer:0:1}"
|
||||
if [[ "${answer,,}" == "y" ]]; then
|
||||
systemctl enable time_sync_at_boot.service
|
||||
systemctl --quiet enable time_sync_at_boot.service
|
||||
else
|
||||
echo "Time sync at boot skipped."
|
||||
echo "If you change your mind later, simply type:"
|
||||
@@ -141,5 +235,15 @@ echo "or you may configure your system manually."
|
||||
echo
|
||||
echo "Thank you for choosing Stormux."
|
||||
|
||||
echo
|
||||
read -rp "Press enter to continue."
|
||||
|
||||
cleanup_first_boot_access
|
||||
|
||||
if [[ $i38StartAtBoot -eq 1 ]]; then
|
||||
echo
|
||||
echo "Starting I38..."
|
||||
sudo "${sudoFlags[@]}" systemctl --quiet start nodm.service
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
Reference in New Issue
Block a user