#!/usr/bin/env bash # # Copyright 2024, Stormux, # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License as published by the Free # Software Foundation; either version 3, or (at your option) any later # version. # # This software is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; see the file COPYING. If not, write to the Free # Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # # keep track of mounted status for exit function mounted=1 # Dialog accessibility export DIALOGOPTS='--no-lines --visit-items' set -e # Don't want to destroy stuff if this goes majorly wrong. trap cleanup EXIT # make sure the script cleans up after itself before closing. cleanup() { if [[ $mounted -eq 0 ]]; then umount -R /mnt || echo "Warning: Failed to unmount /mnt" fi exit 0 } help() { echo -e "Usage:\n" echo "With no arguments, build with default parameters." for i in "${!command[@]}" ; do echo "-${i/:/ }: ${command[${i}]}" done | sort exit 0 } inputbox() { local boxType if [[ "$*" =~ password ]]; then boxType="--insecure --passwordbox" else boxType="--inputbox" fi dialog --title "Stormux X86_64 Installer" \ --backtitle "Enter text and press enter. Press escape to cancel." \ ${boxType} "$*" -1 -1 } menulist() { # Args: Instructions, Tag, description. # returns: selected tag local instructions="${1}" shift dialog --title "Stormux X86_64 Installer" \ --backtitle "Use the up and down arrow keys to find the option you want, then press enter to select it." \ --clear \ --cancel-label "Exit" \ --ok-label "Continue" \ --no-tags \ --menu "${instructions}" 0 0 0 "$@" --stdout local code=$? [[ $code -eq 1 ]] && exit 0 } msgbox() { dialog --backtitle "Stormux X86_64 Installer" \ --ok-label "Continue" \ --msgbox "$*" -1 -1 local code=$? [[ $code -eq 1 ]] && exit 0 } yesno() { # Returns: 0 yes, or 1 no # Args: Question to user. dialog --clear --title "Stormux X86_64 Installer" \ --backtitle "Press 'Enter' for \"yes\" or 'Escape' for \"no\"." --yesno "$*" -1 -1 --stdout return $? } # Array of command line arguments declare -A command=( [h]="This help screen." ) # Convert the keys of the associative array to a format usable by getopts args="${!command[*]}" args="${args//[[:space:]]/}" while getopts "${args}" i ; do case "$i" in h) help ;; *) exit 1 ;; esac done # make sure variables are set, or use defaults. # Make sure this script is ran as root. if [ "$(whoami)" != "root" ] ; then echo "Error: This script must be run as root." exit 1 fi answer="$(yesno "Have you created your own disk layout and mounted it at /mnt?")" if [[ $answer -eq 1 ]]; then msgbox "Stormux can format a drive for you. Keep in mind that all data on the selected drive will be lost, including any other operating system that may be installed. To cancel, press control+c." mapfile -t driveList < <(lsblk -l -d -o 'PATH,SiZE' | tail -n +2 | tr -s '[:space:]' | tr '[:space:]' $'\n') drive=$(menulist "Select a drive for the installation." "${driveList[@]}" --stdout) # Check if the system is using UEFI if [ -d /sys/firmware/efi ]; then echo "UEFI detected. Setting up GPT partition table." parted -s "$drive" mklabel gpt parted -s "$drive" mkpart primary fat32 1MiB 512MiB parted -s "$drive" set 1 esp on parted -s "$drive" mkpart primary ext4 512MiB 100% mkfs.fat -F32 "${drive}1" mkfs.ext4 "${drive}2" mount "${drive}2" /mnt mkdir -p /mnt/boot mount "${drive}1" /mnt/boot else echo "BIOS detected. Setting up MBR partition table." parted -s "$drive" mklabel msdos parted -s "$drive" mkpart primary ext4 1MiB 100MiB parted -s "$drive" set 1 boot on mkfs.ext4 "${drive}1" mount "${drive}1" /mnt mounted=0 fi fi language=$(menulist "Select the System Language" \ "en_US.UTF-8" "English United States" \ "en_GB.UTF-8" "English Great Britain" \ "en_GB.UTF-8" "English Great Britain" \ "cs_CZ.UTF-8" "Czech Republic" \ ) kernel=$(menulist "Select a kernel" \ "Linux" "The latest kernel." \ "linux-lts" "The long term support kernel" \ "linux-zen" "Optimized for desktops" \ ) userName="$(inputbox "Enter the user name for your new system. User names can contain letters (both upper and lowercase), numbers, and underscores (_).")" password1="" password2=" " while [[ "${password1}" != "${password2}" ]]; do password1="$(inputbox "Enter a password for $userName.")" password2="$(inputbox "Enter the password for $userName again.")" if [[ "${password1}" != "${password2}" ]]; then msgbox "Passwords do not match." fi done hostname=$(inputbox "Enter the hostname of your computer, for example, stormux-desktop.") # Install packages pacstrap /mnt \ alsa-firmware \ alsa-utils \ base \ base-devel \ bash-completion \ bluez \ bluez-utils \ brltty \ cronie \ efibootmgr-ng \ espeak-ng \ git \ go \ grub \ ${kernel} \ ${kernel}-headers \ magic-wormhole \ man \ man-pages \ networkmanager \ pipewire \ pipewire-alsa \ pipewire-jack \ pipewire-pulse \ poppler \ python-pyudev \ python-daemonize \ python-evdev \ python-dbus \ python-pyte \ realtime-privileges \ rhvoice-voice-bdl \ rsync \ screen \ sox \ w3m \ wget \ wireless-regdb \ wireplumber \ xdg-user-dirs \ xdg-utils # Chroot into the image arch-chroot /mnt << EOF # set the language sed -i "s/#$language/$language/" /etc/locale.gen echo "LANG=$language" > /etc/locale.conf locale-gen # Set the distribution name. echo 'Stormux \r (\l)' > /etc/issue echo >> /etc/issue # Create the user useradd -m -g users -G wheel,realtime,audio,video,network,brlapi -s /bin/bash $userName # Grant sudo privileges to the stormux user for package installation. echo "${userName} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/wheel # Set the password for the root user echo -e "root\nroot" | passwd "root" # Set the password for the user echo -e "${password1}\n${password1}" | passwd "${userName}" # Change to the user and install some packages sudo -iu ${userName} # Create desktop, downloads, music, and other directories. xdg-user-dirs-update # Build AUR packages git clone https://aur.archlinux.org/yay cd ~/yay makepkg -cris --noconfirm cd ~ rm -rf yay/ yay -S --noconfirm fenrir-git exit # 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 user echo '%wheel ALL=(ALL) ALL' > /etc/sudoers.d/wheel # Set the hostname echo $hostname > /etc/hostname # Configure services systemctl disable systemd-networkd.service systemd-networkd.socket systemctl enable brltty.path cronie.service fenrirscreenreader.service NetworkManager.service # Cleanup packages pacman -Sc --noconfirm pacman -R --noconfirm go # Install grub grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB grub-mkconfig -o /boot/grub/grub.cfg EOF # Exiting calls the cleanup function to unmount. exit 0