Lots of reorganization. Added stormux package repository. Removed unneeded packages. Switched to systemd management of logging to ram. Use existing tools to resize the image to fill the device, no more growpartfs. No packages installed from AUR any more.

This commit is contained in:
Storm Dragon
2025-08-19 15:18:04 -04:00
parent f80ea1e056
commit 8a7fb83be3
8 changed files with 214 additions and 160 deletions

View File

@@ -50,9 +50,8 @@ help() {
declare -A command=( declare -A command=(
[h]="This help screen." [h]="This help screen."
[l:]="Language default is en_US." [l:]="Language default is en_US."
[n:]="Image name, default is stormux-pi<32|64>-<yyyy-mm-dd>.img" [n:]="Image name, default is stormux-pi4-aarch64-<yyyy-mm-dd>.img"
[s:]="image size in GB, default is 4." [s:]="image size in GB, default is 6."
[v:]="Version of the Raspberry Pi for which you are building. (32|64) default is 64."
) )
# Convert the keys of the associative array to a format usable by getopts # Convert the keys of the associative array to a format usable by getopts
@@ -75,14 +74,6 @@ while getopts "${args}" i ; do
exit 1 exit 1
fi fi
;; ;;
v)
if [[ "${OPTARG}" =~ ^32|64$ ]]; then
imageVersion="${OPTARG}"
else
echo "Image version must be 32 for 32 bit (armv7h), or 64 for 64 bit (aarch64 default)."
exit 1
fi
;;
*) *)
exit 1 exit 1
;; ;;
@@ -90,11 +81,8 @@ while getopts "${args}" i ; do
done done
# make sure variables are set, or use defaults. # make sure variables are set, or use defaults.
export imageVersion="${imageVersion:-64}"
export imageSize="${imageSize:-6G}" export imageSize="${imageSize:-6G}"
imageName="${imageName:-stormux-pi4-${imageVersion}-$(date '+%Y-%m-%d').img}" imageName="${imageName:-stormux-pi4-aarch64-$(date '+%Y-%m-%d').img}"
imageName="${imageName/-64-/-aarch64-}"
imageName="${imageName/-32-/-armv7h-}"
export imageName export imageName
export imageLanguage="${imageLanguage:-en_US.UTF-8}" export imageLanguage="${imageLanguage:-en_US.UTF-8}"
@@ -129,9 +117,8 @@ for i in arch-install-scripts dosfstools parted wget ; do
done done
# Url for the image to be downloaded. # Url for the aarch64 image to be downloaded.
url[32]="http://os.archlinuxarm.org/os/ArchLinuxARM-rpi-armv7-latest.tar.gz" imageUrl="http://os.archlinuxarm.org/os/ArchLinuxARM-rpi-aarch64-latest.tar.gz"
url[64]="http://os.archlinuxarm.org/os/ArchLinuxARM-rpi-aarch64-latest.tar.gz"
fallocate -l "$imageSize" "$imageName" fallocate -l "$imageSize" "$imageName"
loopdev="$(losetup --find --show "${imageName}")" loopdev="$(losetup --find --show "${imageName}")"
@@ -144,72 +131,122 @@ mount "${loopdev}p1" /mnt/boot
# Things are mounted now, so set mounted to 0 (bash true) # Things are mounted now, so set mounted to 0 (bash true)
mounted=0 mounted=0
imageFileName=$(mktemp) imageFileName=$(mktemp)
wget "${url[$imageVersion]}" -O "${imageFileName}" wget "${imageUrl}" -O "${imageFileName}"
if [[ $imageVersion -eq 32 ]]; then
# Workaround for bsdtar errors when extracting 32 bit image.
set +e
fi
bsdtar -xpf "${imageFileName}" -C /mnt bsdtar -xpf "${imageFileName}" -C /mnt
# Set -e in case it got unset for 32 bit image
set -e # Copy override files into place before chroot (except skel to avoid conflicts)
cp -rv ../files/boot/* /mnt/boot
cp -rv ../files/var/* /mnt/var
cp -rv ../files/usr/* /mnt/usr
# Copy etc files but exclude skel directory to avoid package conflicts
find ../files/etc -mindepth 1 -maxdepth 1 ! -name skel -exec cp -rv {} /mnt/etc/ \;
PS1="(Chroot) [\u@\h \W] \$" arch-chroot /mnt << EOF PS1="(Chroot) [\u@\h \W] \$" arch-chroot /mnt << EOF
echo "Chroot started." echo "Chroot started."
# set up pacman # set up pacman
pacman-key --init pacman-key --init
pacman-key --populate archlinuxarm pacman-key --populate archlinuxarm
pacman -Syy
# Change kernels for aarch64 # Add stormux repository
if [[ "$imageVersion" == "64" ]]; then echo "Downloading stormux repository key..."
pacman -R --noconfirm linux-aarch64 uboot-raspberrypi curl -s https://packages.stormux.org/stormux_repo.pub > /tmp/stormux_repo.pub
pacman -S --noconfirm linux-rpi echo "Adding key to pacman keyring..."
pacman-key --add /tmp/stormux_repo.pub
echo "Locally signing key..."
pacman-key --lsign-key 52ADA49000F1FF0456F8AEEFB4CDE1CD56EF8E82
rm /tmp/stormux_repo.pub
# Add repository before core in pacman.conf
sed -i '/^\[core\]/i[stormux]\nSigLevel = Required DatabaseOptional\nServer = https://packages.stormux.org/\$arch\n' /etc/pacman.conf
# Test mirrors and configure based on responsiveness
echo "Testing mirror responsiveness..."
mirrors=(
"mirror.archlinuxarm.org"
"fl.us.mirror.archlinuxarm.org"
"il.us.mirror.archlinuxarm.org"
"tx.us.mirror.archlinuxarm.org"
"nj.us.mirror.archlinuxarm.org"
)
working_mirrors=()
for mirror in "\${mirrors[@]}"; do
echo "Testing \$mirror..."
if curl -m 5 -f -s "http://\$mirror/aarch64/core/core.db" > /dev/null 2>&1; then
echo " \$mirror: OK"
working_mirrors+=("\$mirror")
else
echo " \$mirror: FAILED"
fi
done
# Create mirrorlist with working mirrors first, then fallback to all mirrors
> /etc/pacman.d/mirrorlist
if [[ \${#working_mirrors[@]} -gt 0 ]]; then
echo "Using \${#working_mirrors[@]} working mirrors"
for mirror in "\${working_mirrors[@]}"; do
echo "Server = http://\$mirror/\\\$arch/\\\$repo" >> /etc/pacman.d/mirrorlist
done
else
echo "No mirrors responded, using all mirrors as fallback"
for mirror in "\${mirrors[@]}"; do
echo "Server = http://\$mirror/\\\$arch/\\\$repo" >> /etc/pacman.d/mirrorlist
done
fi fi
# Install packages pacman -Syy
pacman -Su --needed --noconfirm \ # Change to the Pi kernel for aarch64
alsa-firmware \ pacman -R --noconfirm linux-aarch64 uboot-raspberrypi
alsa-utils \ pacman -S --noconfirm linux-rpi
base \
base-devel \ # Install all packages (stormux repo has priority since it's listed first)
bash-completion \ packages=(
bluez \ alsa-firmware
bluez-utils \ alsa-utils
brltty \ base
cloud-utils \ base-devel
cronie \ bash-completion
espeak-ng \ bluez
fake-hwclock \ bluez-utils
firmware-raspberrypi \ brltty
git \ cronie
go \ espeak-ng
magic-wormhole \ fake-hwclock
man \ fenrir
man-pages \ firmware-raspberrypi
networkmanager \ git
pipewire \ magic-wormhole
pipewire-alsa \ man
pipewire-jack \ man-pages
pipewire-pulse \ networkmanager
poppler \ parted
python-pyudev \ pipewire
python-daemonize \ pipewire-alsa
python-evdev \ pipewire-jack
python-dbus \ pipewire-pulse
python-pyenchant \ poppler
python-pyte \ python-dbus
socat \ python-pyenchant
raspberrypi-utils \ python-pyte
realtime-privileges \ python-setuptools-scm
rhvoice-voice-bdl \ python-pyperclip
rng-tools \ raspberrypi-utils
rsync \ socat
screen \ realtime-privileges
sox \ rhvoice-voice-bdl
w3m \ rng-tools
wget \ rsync
wireless-regdb \ screen
wireplumber \ sox
xdg-user-dirs \ w3m-git
wget
wireless-regdb
wireplumber
xdg-user-dirs
xdg-utils xdg-utils
yay
)
pacman -Su --needed --noconfirm "\${packages[@]}"
# Restart gpg agents. # Restart gpg agents.
gpgconf --kill all gpgconf --kill all
@@ -231,35 +268,14 @@ echo 'stormux ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers.d/wheel
echo -e "root\nroot" | passwd "root" echo -e "root\nroot" | passwd "root"
# Set the password for the stormux user # Set the password for the stormux user
echo -e "stormux\nstormux" | passwd "stormux" echo -e "stormux\nstormux" | passwd "stormux"
# Change to the stormux user and install some packages
# Change to the stormux user for user configuration
sudo -iu stormux sudo -iu stormux
# suppress git spam about default branch name # suppress git spam about default branch name
git config --global init.defaultBranch master git config --global init.defaultBranch master
# Create desktop, downloads, music, and other directories. # Create desktop, downloads, music, and other directories.
xdg-user-dirs-update xdg-user-dirs-update
# Build AUR packages
export aurPackages=(fenrir \
growpartfs \
log2ram \
python-pythondialog \
yay)
export PKGDEST=~/packages
for p in "\${aurPackages[@]}" ; do
git clone https://aur.archlinux.org/\${p}.git
cd ~/\${p}
if [[ "\${p}" == "python-pythondialog" ]]; then
gpg --import keys/pgp/*.asc
fi
makepkg -A
cd ~
rm -rf \${p}
done
exit exit
# Install built packages
for p in /home/stormux/packages/* ; do
pacman -U --noconfirm \${p}
done
rm -rf /home/stormux/packages/
# Enable linger so that hopefully sound will start at login. # Enable linger so that hopefully sound will start at login.
mkdir -p /var/lib/systemd/linger mkdir -p /var/lib/systemd/linger
touch /var/lib/systemd/linger/stormux touch /var/lib/systemd/linger/stormux
@@ -272,20 +288,32 @@ echo '%wheel ALL=(ALL) ALL' > /etc/sudoers.d/wheel
echo stormux > /etc/hostname echo stormux > /etc/hostname
# Configure services # Configure services
systemctl disable systemd-networkd.service systemd-networkd.socket systemctl disable systemd-networkd.service systemd-networkd.socket
systemctl enable brltty.path cronie.service fake-hwclock.service fenrirscreenreader.service log2ram.service NetworkManager.service # Enable services
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
NetworkManager.service
)
for service in "\${services[@]}"; do
echo "Enabling \$service..."
if systemctl enable "\$service"; then
echo " \$service: OK"
else
echo " \$service: FAILED"
fi
done
# Cleanup packages # Cleanup packages
pacman -Sc --noconfirm pacman -Sc --noconfirm
pacman -R --noconfirm go
# Update fstab for Raspberry Pi 4. Not needed until linux-aarch64 works.
# [[ $imageVersion -eq 4 ]] && sed -i 's/mmcblk0/mmcblk1/g' /etc/fstab
EOF EOF
# Copy override files into place. # Copy skel files to stormux user home (after user rename in chroot)
cp -rv ../files/boot/* /mnt/boot
cp -rv ../files/etc/* /mnt/etc
cp -rv ../files/var/* /mnt/var
cp -rv ../files/usr/* /mnt/usr
find ../files/etc/skel/ -mindepth 1 -exec cp -rv "{}" /mnt/home/stormux/ \; find ../files/etc/skel/ -mindepth 1 -exec cp -rv "{}" /mnt/home/stormux/ \;
# Exiting calls the cleanup function to unmount. # Exiting calls the cleanup function to unmount.

View File

@@ -4,3 +4,4 @@
# <file system> <dir> <type> <options> <dump> <pass> # <file system> <dir> <type> <options> <dump> <pass>
LABEL=STRMX_BOOT /boot vfat defaults 0 1 LABEL=STRMX_BOOT /boot vfat defaults 0 1
LABEL=STRMX_ROOT / ext4 defaults,noatime 0 1 LABEL=STRMX_ROOT / ext4 defaults,noatime 0 1
tmpfs /var/log tmpfs defaults,noatime,nosuid,nodev,noexec,mode=0755,size=128M 0 0

View File

@@ -1,37 +0,0 @@
# Configuration file for Log2Ram (https://github.com/azlux/log2ram) under MIT license.
# This configuration file is read by the log2ram service
# Size for the ram folder, it defines the size the log folder will reserve into the RAM.
# If it's not enough, log2ram will not be able to use ram. Check you /var/log size folder.
# The default is 40M and is basically enough for a lot of applications.
# You will need to increase it if you have a server and a lot of log for example.
SIZE=128M
# This variable can be set to true if you prefer "rsync" rather than "cp".
# I use the command cp -u and rsync -X, so I don't copy the all folder every time for optimization.
# You can choose which one you want. Be sure rsync is installed if you use it.
USE_RSYNC=true
# If there are some errors with available RAM space, a system mail will be send
# Change it to false and you will have only a log if there is no place on RAM anymore.
MAIL=false
# Variable for folders to put in RAM. You need to specify the real folder `/path/folder` , the `/path/hdd.folder` will be automatically created. Multiple path can be separeted by `;`. Do not add the final `/` !
# example : PATH_DISK="/var/log;/home/test/FolderInRam"
PATH_DISK="/var/log"
# **************** Zram backing conf *************************************************
# ZL2R Zram Log 2 Ram enables a zram drive when ZL2R=true ZL2R=false is mem only tmpfs
ZL2R=false
# COMP_ALG this is any compression algorithm listed in /proc/crypto
# lz4 is fastest with lightest load but deflate (zlib) and Zstandard (zstd) give far better compression ratios
# lzo is very close to lz4 and may with some binaries have better optimisation
# COMP_ALG=lz4 for speed or Zstd for compression, lzo or zlib if optimisation or availabilty is a problem
COMP_ALG=lz4
# LOG_DISK_SIZE is the uncompressed disk size. Note zram uses about 0.1% of the size of the disk when not in use
# LOG_DISK_SIZE is expected compression ratio of alg chosen multiplied by log SIZE
# lzo/lz4=2.1:1 compression ratio zlib=2.7:1 zstandard=2.9:1
# Really a guestimate of a bit bigger than compression ratio whilst minimising 0.1% mem usage of disk size
LOG_DISK_SIZE=100M

View File

@@ -0,0 +1,16 @@
[Unit]
Description=Setup RAM logging and restore logs from disk
DefaultDependencies=false
After=local-fs.target
Before=sysinit.target
RequiresMountsFor=/var
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStartPre=/bin/mkdir -p /var/log.hdd
ExecStartPre=/bin/sh -c 'if [ -d /var/log.hdd ] && [ "$(ls -A /var/log.hdd 2>/dev/null)" ]; then cp -au /var/log.hdd/* /var/log/ 2>/dev/null || true; fi'
ExecStart=/bin/true
[Install]
WantedBy=sysinit.target

View File

@@ -0,0 +1,14 @@
[Unit]
Description=Sync logs to disk before shutdown
DefaultDependencies=false
Before=shutdown.target reboot.target halt.target
Conflicts=shutdown.target reboot.target halt.target
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/bin/sh -c 'rsync -aXv --delete --exclude="*.hdd" /var/log/ /var/log.hdd/ 2>/dev/null || true'
TimeoutStopSec=30
[Install]
WantedBy=shutdown.target reboot.target halt.target

View File

@@ -0,0 +1,8 @@
[Unit]
Description=Sync logs from RAM to disk
After=local-fs.target
[Service]
Type=oneshot
ExecStartPre=/bin/mkdir -p /var/log.hdd
ExecStart=/bin/sh -c 'rsync -aXv --delete --exclude="*.hdd" /var/log/ /var/log.hdd/ 2>/dev/null || true'

View File

@@ -0,0 +1,11 @@
[Unit]
Description=Sync logs from RAM to disk every hour
Requires=log-to-ram-sync.service
[Timer]
OnBootSec=15min
OnUnitActiveSec=1h
Persistent=true
[Install]
WantedBy=timers.target

View File

@@ -24,29 +24,33 @@ if [[ -x /opt/configure-stormux/configure-stormux.sh ]]; then
exit 0 exit 0
fi fi
# make sure the system is at a decent volume # Wait for pipewire to become available and set volume
echo "Waiting for audio system to initialize..."
volume=50 volume=50
wait=0 wait=0
# Wait for pipewire to become available
while [[ $wait -lt 30 ]]; do while [[ $wait -lt 30 ]]; do
if pgrep pipewire &> /dev/null ; then if pgrep pipewire &> /dev/null ; then
wait=30 # We don't want to continue the loop echo "Audio system ready. Setting up volume..."
break
else else
sleep 1 sleep 1
continue ((wait++))
fi fi
done
# Volume calibration - this should be the first interactive part
while [[ $volume -le 130 ]]; do while [[ $volume -le 130 ]]; do
clear clear
echo "Volume calibration (current: ${volume}%)"
pactl set-sink-volume @DEFAULT_SINK@ "${volume}%" 2>/dev/null
spd-say "If this is loud enough, press enter." spd-say "If this is loud enough, press enter."
if read -t4 ; then if read -t4 ; then
echo "Volume set to ${volume}%"
break break
else else
((volume+=5)) ((volume+=5))
fi fi
pactl set-sink-volume @DEFAULT_SINK@ "${volume}%"
done
((wait++))
done done
export DIALOGOPTS='--insecure --no-lines --visit-items' export DIALOGOPTS='--insecure --no-lines --visit-items'
@@ -98,7 +102,16 @@ if [[ $diskSize -le 7 ]]; then
read -r continue read -r continue
continue="${continue::1}" continue="${continue::1}"
if [[ "${continue,}" == "y" ]];then if [[ "${continue,}" == "y" ]];then
sudo "${sudoFlags[@]}" growpartfs $diskSource # 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
sudo "${sudoFlags[@]}" parted "$diskDevice" resizepart 2 100%
sudo "${sudoFlags[@]}" resize2fs "$diskSource"
fi fi
fi fi