Initial build setup for x86_64 Stormux.

This commit is contained in:
Storm Dragon
2025-11-19 03:26:25 -05:00
parent fffe426d29
commit 3c5490ea24
91 changed files with 2266 additions and 0 deletions

View File

@@ -0,0 +1,141 @@
#!/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
trap cleanup EXIT
cleanup() {
popd &> /dev/null
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
}
if [[ -x /opt/configure-stormux/configure-stormux.sh ]]; then
pushd /opt/configure-stormux
./configure-stormux.sh
exit 0
fi
# Volume calibration is now handled in stormux_first_boot.sh
export DIALOGOPTS='--insecure --no-lines --visit-items'
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.
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.
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.
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
sed -i 's/=desktop/=laptop/' /etc/fenrirscreenreader/settings/settings.conf
clear
systemctl restart fenrirscreenreader.service
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
# 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
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"
fi
fi
if ! ping -c1 stormux.org &> /dev/null ; then
echo "No internet connection detected. Press enter to open NetworkManager."
read -r continue
echo "setting set focus#highlight=True" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
nmtui-connect
echo "setting set focus#highlight=False" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.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 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."
exit 0

View File

@@ -0,0 +1,21 @@
#!/usr/bin/env bash
# Initialize pipewire audio by attempting to play sound until it succeeds
# This ensures pipewire is fully ready before fenrir starts
maxAttempts=30
attempt=0
while [[ $attempt -lt $maxAttempts ]]; do
# Try to play a silent sound using sox
if play -qnV0 synth .1 whi norm -100 2>/dev/null; then
# Success! Pipewire is working
exit 0
fi
# Wait a moment before trying again
sleep 1
((attempt++))
done
# Even if we failed, exit successfully so we don't block boot
exit 0

View File

@@ -0,0 +1,24 @@
#!/usr/bin/env bash
# Configure audio for Stormux live environment
# Ensures pipewire is running and audio is properly configured
# Start pipewire for the stormux user if not already running
if id stormux &>/dev/null; then
# Enable linger for stormux user
loginctl enable-linger stormux 2>/dev/null || true
# Start pipewire user services
stormux_uid="$(id -u stormux)"
sudo -u stormux XDG_RUNTIME_DIR="/run/user/${stormux_uid}" systemctl --user enable --now pipewire.service pipewire-pulse.service wireplumber.service 2>/dev/null || true
# Wait for pipewire to initialize
sleep 2
fi
# Unmute and set reasonable volumes
amixer -q set Master 70% unmute 2>/dev/null || true
amixer -q set PCM 70% unmute 2>/dev/null || true
amixer -q set Speaker 70% unmute 2>/dev/null || true
amixer -q set Headphone 70% unmute 2>/dev/null || true
exit 0

View File

@@ -0,0 +1,22 @@
#!/usr/bin/env bash
# Setup Pipewire for the live environment
# This ensures pipewire is running before Fenrir starts
# Note: Do not use set -e - we want this to succeed even if commands fail
# Enable user linger for the stormux user (allows user services to run without login)
if [ -d /var/lib/systemd/linger ]; then
touch /var/lib/systemd/linger/stormux
fi
# Start pipewire for the stormux user
if id stormux &>/dev/null; then
# Use machinectl to start user services in the user's session
machinectl shell stormux@ /usr/bin/systemctl --user enable pipewire.service pipewire-pulse.service wireplumber.service 2>/dev/null || true
machinectl shell stormux@ /usr/bin/systemctl --user start pipewire.service pipewire-pulse.service wireplumber.service 2>/dev/null || true
fi
# Wait a moment for pipewire to initialize
sleep 2
exit 0

View File

@@ -0,0 +1,73 @@
#!/usr/bin/env bash
#
# Customize the airootfs after package installation
# This script runs in the chroot environment after packages are installed
set -e -u
# Copy custom skel files, overwriting package defaults
if [ -d /etc/skel.custom ]; then
echo "Installing custom skel files..."
cp -f /etc/skel.custom/.* /etc/skel/ 2>/dev/null || true
rm -rf /etc/skel.custom
fi
# Set the distribution name
echo 'Stormux \r (\l)' > /etc/issue
echo >> /etc/issue
# Create realtime group if it doesn't exist
if ! getent group realtime > /dev/null 2>&1; then
echo "Creating realtime group..."
groupadd -r realtime
fi
# Create stormux user with groups matching Pi build
echo "Creating stormux user..."
useradd -m -g users -G wheel,realtime,audio,video,network,brlapi -s /bin/bash stormux
# Set passwords
echo -e "root\nroot" | passwd "root"
echo -e "stormux\nstormux" | passwd "stormux"
# Configure git for stormux user
sudo -iu stormux bash -c 'git config --global init.defaultBranch master'
# Create user directories
sudo -iu stormux xdg-user-dirs-update
# Enable linger so that sound will start at login
mkdir -p /var/lib/systemd/linger
touch /var/lib/systemd/linger/stormux
# Enable pipewire globally
# Pipewire configuration for fenrir is pre-installed in airootfs
systemctl --global enable pipewire.service pipewire-pulse.service
# Configure sudo for wheel group
echo '%wheel ALL=(ALL) ALL' > /etc/sudoers.d/wheel
# Set hostname
echo stormux > /etc/hostname
# Disable systemd-networkd in favor of NetworkManager
systemctl disable systemd-networkd.service systemd-networkd.socket 2>/dev/null || true
# Enable services
services=(
brltty.path
fenrirscreenreader.service
NetworkManager.service
stormux-audio-setup.service
)
for service in "${services[@]}"; do
echo "Enabling $service..."
if systemctl enable "$service"; then
echo " $service: OK"
else
echo " $service: FAILED"
fi
done
echo "Airootfs customization complete"

View File

@@ -0,0 +1,4 @@
#!/usr/bin/env bash
date_time=$(curl -s http://worldtimeapi.org/api/ip | grep -oP '(?<="datetime":")[^"]*')
date -s "$date_time"

View File

@@ -0,0 +1,29 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBGhTtIcBEADTCqY/+das1n52HTTlp3Uf5+ER5r0fNA2HgJq4GzEeFBdqdgSF
y05P9B94d4JWtWvt0ckjsNfku19O9IquKiYP5x9/sYT8RGeRUrTlN9qlCrytTsdM
a8ij9esGQOXDeyRJQTs5igbFWQ26MrJpOkmO8xMXGmfD29yOppRLzVS8Jed0mokk
aEajui3QSWcefDnFMBYNaMF04iuWgVxv/7102adh3u3+V632+fQQhFtu+x92iosU
GtWlGGe3UkEhWJIb6wf/VCYIYQAjxTQBLul2WByXqwCXmobzc7DJbte3FSEPvPis
nJiUmT0fsIIC9c1UbTJt5Gqb6o/oI61tEJEeXieBViXFE7HwBI7FUxaIXoozgiYA
BxaLHQT0Qv9k1SXbBm82xNydjqFHIAolYSp5s1wRIhErlOaG9w3+Tb8zFSekPsbg
cgS/b3PpWmnigXBJQ94Ee+6KoPMVrwEKIu/IHexRUVAm+66Xs55ccgMY+MUupIjX
Bdn9jCYB8NwpC3UNWoSv2oQ7F2hVbXZYC/dx7gKmyvzfrw5MLOX7yEoSGlJJp2iK
fLLP8nw+x7LnDFEnAjPjtmeH7e+JANH1scP/7YMKDszO1THSK3hBAK1aeq0aEFs8
9AO++xZrNbCrF2MnqcGaXs/753k6kf8zyrW6t7A1opxjPHIz3WrQ8SbXXwARAQAB
tExTdG9ybXV4IChGb3Igc2lnbmluZyBzdG9ybXV4IHJlcG9zaXRvcnkgcGFja2Fn
ZXMpIDxzdG9ybV9kcmFnb25Ac3Rvcm11eC5vcmc+iQJOBBMBCgA4FiEEUq2kkADx
/wRW+K7vtM3hzVbvjoIFAmhTtIcCGwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AA
CgkQtM3hzVbvjoLiLQ/9HJzlwr2JNGdR/LaM1Y6VuhASGDZsUsi5XLJ7qKUKN/eA
kq0LMO7TzHO++otsEolodMr8fTkthQTPqSnbLZsW9Y3wK9U2vajryblRSEBaY6VB
1ds0pAg5SXz7O2eI2Ne05dkYB176G72KcjrOiSanKjI9sqh6pdTHcQM3XbRxxEVn
or7fKbLs/eveFWRPW3EAwuVnWI1aw3Xw9BQ3TE1eEDPvBh2GVKZ6qskbzdwfZtUB
kxAa30M+ftlNDaV7d6mNfREefEJfZjYFrY2XiqTK3+w1Q1ZaugK0Bbd/YdAoGMdt
6gbd2h/IZtxduWW/HhvWX2wtKqn4fNxAyYcY3aWm8kuq0pXlyEZ96gZas6a2lu+f
+yLvIh3UtC1IimFMDMQnKCTbWgdhd0HMnG9ULnoOroXVGltnBQwlO0hrHSVD+qmy
NVPUxkzS3ZhqSmoW2G8hSvXpMjt/w5fhC0FJhFb/uM/7LqJWSl5aAkUHupN3t/nG
9o7chBQzzXwbpiS6DQuIt6ouyPpwNjeELFPNBjZDf0auVWj6ZZ5+B/bmyHXQ4wFS
bYKZdO9VeXhBxRUMfGpIKvIw/Lnc+1Toan1RTWoUoRH+HuK2D/LAuvsam36gtLrQ
XV3//7Mh4oQ0Zg4REG3SEfG9i3rav8wMtRmaJaSbwmMVpC6mT/uiEzCSgQhO/0c=
=HIM9
-----END PGP PUBLIC KEY BLOCK-----