#!/usr/bin/env bash # For audible sudo prompts: unset sudoFlags if [[ -x /etc/audibleprompt.sh ]]; then export SUDO_ASKPASS=/etc/audibleprompt.sh export sudoFlags=("-A") fi # shellcheck disable=SC2329 cleanup() { popd &> /dev/null || true if ! [[ -x /opt/configure-stormux/configure-stormux.sh ]]; then echo "Initial setup is not complete." echo "To continue setup, please run:" echo "sudo configure-stormux" fi } trap cleanup EXIT if [[ -x /opt/configure-stormux/configure-stormux.sh ]]; then pushd /opt/configure-stormux || exit 1 ./configure-stormux.sh exit 0 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 mapfile -t regions < <(timedatectl --no-pager list-timezones | cut -d '/' -f1 | sort -u) # Use the same text twice here and just hide the tag field. # shellcheck disable=SC2046 region=$(dialog --backtitle "Please select your Region" \ --no-tags \ --menu "Use up and down arrows or page-up and page-down to navigate the list, and press 'Enter' to make your selection." 0 0 0 \ $(for i in "${regions[@]}" ; do echo "$i";echo "$i";done) --stdout) mapfile -t cities < <(timedatectl --no-pager list-timezones | grep "$region" | cut -d '/' -f2 | sort -u) # Use the same text twice here and just hide the tag field. # shellcheck disable=SC2046 city=$(dialog --backtitle "Please select a city near you" \ --no-tags \ --menu "Use up and down arrow or page-up and page-down to navigate the list." 0 0 10 \ $(for i in "${cities[@]}" ; do echo "$i";echo "$i";done) --stdout) # Set the timezone if [[ -f /etc/localtime ]]; then rm /etc/localtime fi ln -sf /usr/share/zoneinfo/"${region}"/"${city}" /etc/localtime timedatectl set-ntp true } # Offer to switch fenrir layout. 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%.*} 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 diskDevice="${BASH_REMATCH[1]}" else # Handle sda2, sdb3 style # shellcheck disable=SC2001 diskDevice="$(echo "$diskSource" | sed 's/[0-9]*$//')" fi 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 _ 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 fi # Check for internet connectivity if ping -qc1 -W 1 stormux.org &> /dev/null; then echo "Updating the clock to prevent certificate errors..." # Get current date and time date_time=$(curl -s http://worldtimeapi.org/api/ip | grep -oP '(?<="datetime":")[^"]*') echo "Current date and time: $date_time" # set date and time date -s "$date_time" echo "If your Pi does not have a CMOS battery and is powered off regularly, it may take a while for the time to be set correctly after boot." echo "Stormux provides a service to sync the time after internet connection is established." 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 --quiet enable time_sync_at_boot.service else echo "Time sync at boot skipped." echo "If you change your mind later, simply type:" echo "sudo systemctl enable time_sync_at_boot.service" fi set_timezone else echo "Please connect to the internet and run ${0##*/} again." exit 1 fi echo "Installing configure-stormux..." git -C /opt clone -q https://git.stormux.org/storm/configure-stormux || exit 1 echo echo "Initial setup is complete." echo echo "The default passwords are stormux for the stormux user" echo "and root for the root user. It is highly recommended to change them." echo "To change the password for stormux, run:" echo "passwd" echo "To change the password for root, run:" echo "sudo passwd" echo echo "For more configuration options, run configure-stormux," 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