Просмотр исходного кода

now working again since some initramfs hooks were deprecated + better uefi & non-AENS system handling + general changes to reflect my current setup

Noah Vogt 4 часов назад
Родитель
Сommit
d5b0085d19
3 измененных файлов с 288 добавлено и 157 удалено
  1. 106 21
      arch.sh
  2. 47 26
      chroot.sh
  3. 135 110
      norisa.sh

+ 106 - 21
arch.sh

@@ -5,9 +5,17 @@
 # do this if you exactly understand EVERY SINGLE
 # LINE of this bash script. You'll thank me later.
 
-pacman -Sy --noconfirm dialog || { printf "Error at script start:\n\nAre you sure you're running this as the root user?\n\t(Tip: run 'whoami' to check)\n\nAre you sure you have an internet connection?\n\t(Tip: run 'ip a' to check)\n"; exit; }
-
-dialog --defaultno --title "WARNING!" --yesno "Do only run this script if you're a big brain who doesn't mind deleting one or more (this depends on your level of stupidity in the following steps) of his /dev/sd[x] drives. \n\nThis script is only really for me so I can save some of my precious time.\n\nNoah"  15 60 || { clear; exit; }
+pacman -Sy --noconfirm dialog || {
+    printf "Error at script start:\n\nAre you sure you're running this as the root user?\n\t(Tip: run 'whoami' to check)\n\nAre you sure you have an internet connection?\n\t(Tip: run 'ip a' to check)\n"
+    exit
+}
+
+# Hardware AES Detection
+if grep -q "\baes\b" /proc/cpuinfo; then
+    AES_NI="yes"
+else
+    AES_NI="no"
+fi
 
 dialog --no-cancel --inputbox "Enter the hostname." 10 60 2>comp
 
@@ -17,7 +25,7 @@ read -rp "Press any key to continue"
 
 dialog --no-cancel --inputbox "Enter the drive you want do install Arch on." 10 60 2>drive
 
-dialog --defaultno --title "Time Zone select" --yesno "Do you want use the default time zone(Europe/Zurich)?.\n\nPress no for select your own time zone"  10 60 && echo "Europe/Zurich" > tz.tmp || tzselect > tz.tmp
+dialog --defaultno --title "Time Zone select" --yesno "Do you want use the default time zone(Europe/Zurich)?.\n\nPress no for select your own time zone" 10 60 && echo "Europe/Zurich" >tz.tmp || tzselect >tz.tmp
 
 dialog --no-cancel --inputbox "Enter swapsize in gb (only type in numbers)." 10 60 2>swapsize
 
@@ -28,20 +36,21 @@ PVALUE=$(echo "${DRIVE}" | grep "^nvme" | sed 's/.*[0-9]/p/')
 
 timedatectl set-ntp true
 
+# Dynamic Partitioning
 if [ "$EFI" = "yes" ]; then
-    UEFI_LETTER="1"
-    ROOT_LETTER="3"
-    cat <<EOF | fdisk -W always /dev/"${DRIVE}"
+    if [ "$AES_NI" = "yes" ]; then
+        UEFI_LETTER="1"
+        SWAP_LETTER="2"
+        ROOT_LETTER="3"
+        cat <<EOF | fdisk -W always /dev/"${DRIVE}"
 g
 n
-p
 
 
 +1024M
 t
 1
 n
-p
 
 
 +${SIZE}G
@@ -54,11 +63,64 @@ n
 
 w
 EOF
-mkfs.vfat -F32 /dev/"${DRIVE}${PVALUE}${UEFI_LETTER}"
+    else
+        UEFI_LETTER="1"
+        SWAP_LETTER="2"
+        BOOT_LETTER="3"
+        ROOT_LETTER="4"
+        cat <<EOF | fdisk -W always /dev/"${DRIVE}"
+g
+n
+
 
++1024M
+t
+1
+n
+
+
++${SIZE}G
+t
+2
+19
+n
+
+
++1024M
+n
+
+
+
+w
+EOF
+    fi
 else
-    ROOT_LETTER="2"
-    cat <<EOF | fdisk -W always /dev/"${DRIVE}"
+    if [ "$AES_NI" = "yes" ]; then
+        SWAP_LETTER="1"
+        ROOT_LETTER="2"
+        cat <<EOF | fdisk -W always /dev/"${DRIVE}"
+o
+n
+p
+
+
++${SIZE}G
+t
+82
+n
+p
+
+
+
+a
+2
+w
+EOF
+    else
+        SWAP_LETTER="1"
+        BOOT_LETTER="2"
+        ROOT_LETTER="3"
+        cat <<EOF | fdisk -W always /dev/"${DRIVE}"
 o
 n
 p
@@ -71,18 +133,28 @@ n
 p
 
 
++1024M
+n
+p
+
+
 
 a
 2
 w
 EOF
+    fi
 fi
 
 partprobe
 
+# Dynamic LUKS Formatting
 while true; do
-    cryptsetup luksFormat --type luks1 /dev/"${DRIVE}${PVALUE}${ROOT_LETTER}" &&
-        break
+    if [ "$AES_NI" = "yes" ]; then
+        cryptsetup luksFormat --type luks2 /dev/"${DRIVE}${PVALUE}${ROOT_LETTER}" && break
+    else
+        cryptsetup luksFormat --type luks2 --cipher xchacha12,aes-adiantum-plain64 --hash sha256 /dev/"${DRIVE}${PVALUE}${ROOT_LETTER}" && break
+    fi
 done
 
 while true; do
@@ -92,17 +164,30 @@ done
 yes | mkfs.ext4 /dev/mapper/cryptroot
 mount /dev/mapper/cryptroot /mnt
 
-pacman -Sy --noconfirm archlinux-keyring
+# Mount Unencrypted Boot (if Adiantum)
+if [ "$AES_NI" = "no" ]; then
+    yes | mkfs.ext4 /dev/"${DRIVE}${PVALUE}${BOOT_LETTER}"
+    mkdir -p /mnt/boot
+    mount /dev/"${DRIVE}${PVALUE}${BOOT_LETTER}" /mnt/boot
+fi
+
+# Mount EFI
+if [ "$EFI" = "yes" ]; then
+    mkfs.vfat -F32 /dev/"${DRIVE}${PVALUE}${UEFI_LETTER}"
+    mkdir -p /mnt/boot/efi
+    mount /dev/"${DRIVE}${PVALUE}${UEFI_LETTER}" /mnt/boot/efi
+fi
 
+pacman -Sy --noconfirm archlinux-keyring
 pacstrap /mnt base linux linux-firmware cryptsetup
 
-genfstab -U /mnt >> /mnt/etc/fstab
-cat tz.tmp > /mnt/tzfinal.tmp
+genfstab -U /mnt >>/mnt/etc/fstab
+
+# Pass variables to chroot
+cat tz.tmp >/mnt/tzfinal.tmp
+echo "$AES_NI" >/mnt/aes.tmp
 rm tz.tmp
 mv drive /mnt
 mv comp /mnt/etc/hostname
-curl -LO noahvogt.com/chroot.sh --output-dir /mnt && arch-chroot /mnt bash chroot.sh && rm /mnt/chroot.sh
 
-curl -LO noahvogt.com/norisa.sh --output-dir /mnt && dialog --defaultno --title "NoRiSA" --yesno "Launch NoRiSA install script?"  6 30 && arch-chroot /mnt bash norisa.sh && rm /mnt/norisa.sh
-dialog --defaultno --title "Final Qs" --yesno "Return to chroot environment?"  6 30 && arch-chroot /mnt
-clear
+curl -LO https://noahvogt.com/chroot.sh --output-dir /mnt && arch-chroot /mnt bash chroot.sh && rm /mnt/chroot.sh

+ 47 - 26
chroot.sh

@@ -5,17 +5,19 @@ while true; do
 done
 
 TZuser=$(cat tzfinal.tmp)
+AES_NI=$(cat aes.tmp)
 DRIVE=$(cat drive)
 PVALUE=$(echo "${DRIVE}" | grep "^nvme" | sed 's/.*[0-9]/p/')
 
-echo KEYMAP=de_CH-latin1 > /etc/vconsole.conf
+# TODO: Add Selection TUI
+echo KEYMAP=de_CH-latin1 >/etc/vconsole.conf
 
 ln -sf /usr/share/zoneinfo/"$TZuser" /etc/localtime
-
 hwclock --systohc
 
-echo "LANG=en_GB.UTF-8" >> /etc/locale.conf
-echo "en_GB.UTF-8 UTF-8" >> /etc/locale.gen
+# TODO: Add Selection TUI
+echo "LANG=en_GB.UTF-8" >>/etc/locale.conf
+echo "en_GB.UTF-8 UTF-8" >>/etc/locale.gen
 locale-gen
 
 pacman --noconfirm --needed -S networkmanager
@@ -24,36 +26,54 @@ systemctl enable NetworkManager
 ls /sys/firmware/efi/efivars && EFI=yes
 
 if [ "$EFI" = "yes" ]; then
-    UEFI_LETTER="1"
-    SWAP_LETTER="2"
-    ROOT_LETTER="3"
+    if [ "$AES_NI" = "yes" ]; then
+        SWAP_LETTER="2"
+        ROOT_LETTER="3"
+    else
+        SWAP_LETTER="2"
+        ROOT_LETTER="4"
+    fi
 else
-    SWAP_LETTER="1"
-    ROOT_LETTER="2"
+    if [ "$AES_NI" = "yes" ]; then
+        SWAP_LETTER="1"
+        ROOT_LETTER="2"
+    else
+        SWAP_LETTER="1"
+        ROOT_LETTER="3"
+    fi
 fi
 
+LUKS_UUID=$(blkid -s UUID -o value /dev/"${DRIVE}${PVALUE}${ROOT_LETTER}")
+pacman --noconfirm --needed -S grub
 
-dd bs=512 count=4 if=/dev/urandom of=/crypto_keyfile.bin
-while true; do
-    cryptsetup luksAddKey /dev/"${DRIVE}${PVALUE}${ROOT_LETTER}" /crypto_keyfile.bin &&
-        break
-done
-chmod 000 /crypto_keyfile.bin
-
-sed -i 's/FILES=()/FILES=(\/crypto_keyfile.bin)/' /etc/mkinitcpio.conf
-sed -i 's/block filesystems/block encrypt filesystems/' /etc/mkinitcpio.conf
-mkinitcpio -P
+if [ "$AES_NI" = "yes" ]; then
+    # AES Fully-Encrypted Root Setup (Includes Keyfile logic)
+    dd bs=512 count=4 if=/dev/urandom of=/crypto_keyfile.bin
+    while true; do
+        cryptsetup luksAddKey /dev/"${DRIVE}${PVALUE}${ROOT_LETTER}" /crypto_keyfile.bin && break
+    done
+    chmod 000 /crypto_keyfile.bin
+
+    sed -i 's|^FILES=.*|FILES=(/crypto_keyfile.bin)|' /etc/mkinitcpio.conf
+    sed -i 's|^HOOKS=.*|HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole block sd-encrypt filesystems fsck)|' /etc/mkinitcpio.conf
+    mkinitcpio -P
+
+    sed -i "s|^GRUB_CMDLINE_LINUX=.*|GRUB_CMDLINE_LINUX=\"rd.luks.name=${LUKS_UUID}=cryptroot rd.luks.key=${LUKS_UUID}=/crypto_keyfile.bin\"|" /etc/default/grub
+    sed -i 's/#GRUB_ENABLE_CRYPTODISK/GRUB_ENABLE_CRYPTODISK/' /etc/default/grub
+    SWAP_CIPHER="aes-cbc-essiv:sha256"
+else
+    # Adiantum Unencrypted Boot Setup (NO Keyfile logic to prevent plaintext key leak)
+    sed -i 's|^HOOKS=.*|HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole block sd-encrypt filesystems fsck)|' /etc/mkinitcpio.conf
+    mkinitcpio -P
 
-pacman --noconfirm --needed -S grub
-sed -i "s/GRUB_CMDLINE_LINUX=\"\"/GRUB_CMDLINE_LINUX=\"cryptdevice=\/dev\/${DRIVE}${PVALUE}${ROOT_LETTER}:cryptroot\"/" /etc/default/grub
-sed -i 's/#GRUB_ENABLE_CRYPTODISK/GRUB_ENABLE_CRYPTODISK/' /etc/default/grub
+    sed -i "s|^GRUB_CMDLINE_LINUX=.*|GRUB_CMDLINE_LINUX=\"rd.luks.name=${LUKS_UUID}=cryptroot\"|" /etc/default/grub
+    SWAP_CIPHER="xchacha12,aes-adiantum-plain64"
+fi
 
-echo "swap /dev/${DRIVE}${PVALUE}${SWAP_LETTER} /dev/urandom swap,cipher=aes-cbc-essiv:sha256,size=256" >> /etc/crypttab
+echo "swap /dev/${DRIVE}${PVALUE}${SWAP_LETTER} /dev/urandom swap,cipher=${SWAP_CIPHER},size=256" >>/etc/crypttab
 
 if [ "$EFI" = "yes" ]; then
     pacman --noconfirm --needed -S efibootmgr
-    mkdir /boot/efi
-    mount /dev/"${DRIVE}${PVALUE}${UEFI_LETTER}" /boot/efi
     grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=grub /dev/"${DRIVE}" --recheck
 else
     grub-install --target=i386-pc /dev/"${DRIVE}" --recheck
@@ -61,4 +81,5 @@ fi
 
 grub-mkconfig -o /boot/grub/grub.cfg
 
-rm drive tzfinal.tmp
+# Cleanup
+rm drive tzfinal.tmp aes.tmp

+ 135 - 110
norisa.sh

@@ -1,8 +1,17 @@
 #!/bin/bash
 
-# install git, vim, opendoas and (base-devel minus sudo)
-echo -e "\e[0;30;34mInstalling some packages ...\e[0m"
-pacman -Sy --noconfirm --needed git vim opendoas autoconf automake binutils bison fakeroot file findutils flex gawk gcc gettext grep groff gzip libtool m4 make pacman patch pkgconf sed texinfo which libxft || { echo -e "\e[0;30;101m Error at script start:\n\nAre you sure you're running this as the root user?\n\t(Tip: run 'whoami' to check)\n\nAre you sure you have an internet connection?\n\t(Tip: run 'ip a' to check)\n\e[0m"; exit 1; }
+# ASSUMED STATE OF TARGET SYSTEM:
+# - internet access
+# - root user login
+# - ~30 GB of free disk space
+# working 1.) base 2.) linux packages
+
+# Install opendoas and (base-devel, devtools minus sudo), libxft
+echo -e "\e[0;30;34mInstalling some initial packages ...\e[0m"
+pacman -Sy --noconfirm --needed archlinux-keyring opendoas autoconf automake binutils bison debugedit fakeroot file findutils flex gawk gcc gettext grep groff gzip libtool m4 make pacman patch pkgconf sed texinfo which libxft breezy coreutils curl diffutils expac git glow gum jq mercurial openssh parallel reuse rsync subversion util-linux || {
+    echo -e "\e[0;30;101m Error at script start:\n\nAre you sure you're running this as the root user?\n\t(Tip: run 'whoami' to check)\n\nAre you sure you have an internet connection?\n\t(Tip: run 'ip a' to check)\n\e[0m"
+    exit 1
+}
 
 pacman_error_exit() {
     echo -e "\e[0;30;101m Error: Pacman command was not successfull. Exiting ...\e[0m"
@@ -28,7 +37,7 @@ cd_error_exit() {
 setup_temporary_doas() {
     echo -e "\e[0;30;34mSetting up temporary doas config ...\e[0m"
     printf "permit nopass :wheel
-permit nopass root as $username\n" > /etc/doas.conf
+permit nopass root as $username\n" >/etc/doas.conf
     chown -c root:root /etc/doas.conf
     chmod -c 0400 /etc/doas.conf
 }
@@ -38,7 +47,7 @@ setup_final_doas() {
     printf "permit persist :wheel
 permit nopass $username as root cmd mount
 permit nopass $username as root cmd umount
-permit nopass root as $username\n" > /etc/doas.conf
+permit nopass root as $username\n" >/etc/doas.conf
     chown -c root:root /etc/doas.conf
     chmod -c 0400 /etc/doas.conf
 }
@@ -56,146 +65,162 @@ choose_user() {
     echo -e "\e[0;30;46m Available users: \e[0m"
     ls /home
     while true; do
-    echo -e "\e[0;30;42m Enter in your chosen user \e[0m"
-    read -rp " >>> " username
+        echo -e "\e[0;30;42m Enter in your chosen user \e[0m"
+        read -rp " >>> " username
         ls /home/ | grep -q "^$username$" && break
     done
 }
 
-# give info if /home is not empty
-if [ "$(ls -A /home)" ]; then
-    echo -e "\e[0;30;46m /home/ not empty, human users already available \e[0m"
-fi
+add_user_to_groups() {
+    if ! groups "$username" | grep "input" | grep -q "video"; then
+        echo -e "\e[0;30;34mAdding $username to video and input groups ... \e[0m"
+        usermod -aG video "$username"
+        usermod -aG input "$username"
+    fi
+}
 
-while true; do
-    echo -e "\e[0;30;42m Do you want to create a new user? [y/n] \e[0m"
-    read -rp " >>> " want_new_user
-    if echo "$want_new_user" | grep -q "y\|Y"; then
-        create_new_user; break
-    elif echo "$want_new_user" | grep -q "n\|N"; then
-        choose_user; break
+ensure_history_file_exists() {
+    if ! [ -f /home/"$username"/.cache/zsh/history ]; then
+        echo -e "\e[0;30;34mEnsuring initial zsh history file exists ...\e[0m"
+        mkdir -vp /home/"$username"/.cache/zsh
+        touch /home/"$username"/.cache/zsh/history
     fi
-done
+}
+
+change_login_shell_to_zsh() {
+    if ! grep "^$username.*::/home/$username" /etc/passwd | sed 's/^.*://' |
+        grep -q "^$(which zsh)$"; then
+        echo -e "\e[0;30;34mSetting default shell to $(which zsh)...\e[0m"
+        chsh -s "$(which zsh)" "$username" || exit 1
+    fi
+}
+
+make_user_owner_of_HOME_and_mnt_dirs() {
+    echo -e "\e[0;30;34mChanging ownership of /home/$username + /mnt ...\e[0m"
+    chown -R "$username":users /home/"$username"/
+    chown -R "$username":users /mnt/
+}
+
+# Check if /home is not empty
+if [ -d /home ]; then
+    mapfile -t home_users < <(ls -A /home)
+    user_count=${#home_users[@]}
+else
+    user_count=0
+fi
+
+if [ "$user_count" -eq 1 ]; then
+    username="${home_users[0]}"
+    echo -e "\e[0;30;46m A single user was found: $username \e[0m"
+elif [ "$user_count" -gt 1 ]; then
+    echo -e "\e[0;30;46m /home/ not empty, $user_count users already available \e[0m"
+    while true; do
+        echo -e "\e[0;30;42m Do you want to create another user? [y/n] \e[0m"
+        read -rp " >>> " want_new_user
+
+        if [[ "$want_new_user" =~ ^[yY]$ ]]; then
+            create_new_user
+            break
+        elif [[ "$want_new_user" =~ ^[nN]$ ]]; then
+            choose_user
+            break
+        fi
+    done
+else
+    want_new_user=y
+    create_new_user
+fi
 
-# create ~/ directories
+# Create ~/ Directories
 echo -e "\e[0;30;34mCreating ~/ directories ...\e[0m"
 mkdir -vp /home/"$username"/dox /home/"$username"/pix /home/"$username"/dl
 mkdir -vp /home/"$username"/vids /home/"$username"/mus
 mkdir -vp /home/"$username"/.local/bin /home/"$username"/.config
 mkdir -vp /home/"$username"/.local/share /home/"$username"/.local/src
 
-echo -e "\e[0;30;34mChanging ownership of /home/$username ...\e[0m"
-chown -R "$username":users /home/"$username"/* /home/"$username"/.*
+if [[ "$want_new_user" =~ ^[yY]$ ]]; then
+    echo -e "\e[0;30;34mChanging ownership of /home/$username ...\e[0m"
+    chown -R "$username":users /home/"$username"/* /home/"$username"/.*
+fi
 
 setup_temporary_doas
 
+add_user_to_groups
+
+# add xdg-repo
+# if ! grep -q "^\s*\[xdg-repo\]\s*$" /etc/pacman.conf; then
+#     echo -e "\e[0;30;34mAdding Noah's xdg-repo ...\e[0m"
+#     pacman-key --recv-keys 7FA7BB604F2A4346 --keyserver keyserver.ubuntu.com
+#     pacman-key --lsign-key 7FA7BB604F2A4346
+#     echo "[xdg-repo]
+# Server = https://git.noahvogt.com/noah/\$repo/raw/master/\$arch" >> /etc/pacman.conf
+# fi
+
+# Add chaotic-aur
+if ! grep -q "^\s*\[chaotic-aur\]\s*$" /etc/pacman.conf; then
+    echo -e "\e[0;30;34mAdding the chaotic aur repo ...\e[0m"
+    pacman-key --recv-key 3056513887B78AEB --keyserver keyserver.ubuntu.com
+    pacman-key --lsign-key 3056513887B78AEB
+    pacman -U --noconfirm 'https://cdn-mirror.chaotic.cx/chaotic-aur/chaotic-keyring.pkg.tar.zst'
+    pacman -U --noconfirm 'https://cdn-mirror.chaotic.cx/chaotic-aur/chaotic-mirrorlist.pkg.tar.zst'
+    echo "[chaotic-aur]
+Include = /etc/pacman.d/chaotic-mirrorlist" >>/etc/pacman.conf
+fi
+
+# Sync all Package db's
+pacman -Syyy
 
-# install aur helper (paru)
+# Install AUR Helper (paru as paru-bin is out-of-date)
 if ! pacman -Q | grep -q paru; then
     echo -e "\e[0;30;34mInstalling AUR helper (paru) ...\e[0m"
-    cd_into /home/"$username"/.local/src
-    pacman -S --noconfirm --needed asp bat devtools || pacman_error_exit
-    curl -sO https://aur.archlinux.org/cgit/aur.git/snapshot/paru-bin.tar.gz &&
-    tar xvf paru-bin.tar.gz
-    cd_into /home/"$username" && chown -R "$username":wheel /home/"$username"/.local/src/ && cd_into .local/src
-    cd_into paru-bin
-    doas -u "$username" makepkg --noconfirm -si || pacman_error_exit
-    rm /home/"$username"/.local/src/paru-bin.tar.gz
+    pacman -S --noconfirm paru
 fi
 
-# fetch dotfiles repo + apply dotfiles
+# Symlink sudo to doas for Compatibility with paru and hardcoded PKGBUILDs
+echo -e "\e[0;30;34mSymlinking sudo to doas ...\e[0m"
+if [ ! -f /usr/bin/sudo ]; then
+    ln -s /usr/bin/doas /usr/bin/sudo
+fi
+
+# Fetch + Apply Dotfiles
 if [ ! -d /home/"$username"/.local/src/dotfiles ]; then
     echo -e "\e[0;30;34mFetching dotfiles ...\e[0m"
     cd_into /home/"$username"/.local/src
-    git clone https://github.com/noahvogt/dotfiles.git
+    while true; do
+        git clone https://git.noahvogt.com/noah/dotfiles.git && break
+    done
 fi
-c
-d_into /home/"$username"/.local/src/dotfiles
+cd_into /home/"$username"/.local/src/dotfiles
 echo -e "\e[0;30;34mApplying dotfiles ...\e[0m"
 doas -u "$username" /home/"$username"/.local/src/dotfiles/apply-dotfiles
 
-# download packages from the official repos
+# Download Packages from the Official Repos
+# TODO: add element-desktop back
 echo -e "\e[0;30;34mInstalling packages from official repos ...\e[0m"
-pacman -S --noconfirm --needed xorg-server xorg-xinit xorg-xwininfo xorg-xprop xorg-xbacklight xorg-xdpyinfo xorg-xsetroot xbindkeys xf86-video-vesa xf86-video-fbdev libxinerama geogebra shellcheck neovim ranger xournalpp ffmpeg obs-studio sxiv arandr man-db brightnessctl unzip python mupdf-gl mediainfo highlight pulseaudio-alsa pulsemixer pamixer ttf-linux-libertine calcurse xclip noto-fonts-emoji imagemagick gimp xorg-setxkbmap wavemon texlive-most dash neofetch htop wireless_tools alsa-utils acpi zip libreoffice nm-connection-editor dunst libnotify dosfstools tlp mpv xorg-xinput cpupower zsh zsh-syntax-highlighting newsboat nomacs pcmanfm openbsd-netcat powertop mupdf-tools nomacs stow zsh-autosuggestions xf86-video-amdgpu xf86-video-intel xf86-video-nouveau npm fzf unclutter tlp ccls mpd mpc ncmpcpp pavucontrol strawberry smartmontools firefox python-pynvim python-pylint element-desktop tesseract-data-deu tesseract-data-eng keepassxc ueberzug img2pdf dust ctags python-wand python-termcolor python-black jdk-openjdk ripgrep || pacman_error_exit
+pacman -S --noconfirm --needed xorg-server xf86-video-vesa xf86-video-fbdev shellcheck neovim ranger xournalpp ffmpeg obs-studio sxiv arandr man-db brightnessctl unzip python mupdf-gl mediainfo highlight pulseaudio-alsa pulsemixer pamixer ttf-linux-libertine calcurse xclip noto-fonts-emoji imagemagick gimp xorg-setxkbmap wavemon texlive dash unifetch htop wireless_tools alsa-utils acpi zip libreoffice nm-connection-editor dunst libnotify dosfstools mpv xorg-xinput cpupower zsh zsh-syntax-highlighting newsboat nomacs pcmanfm openbsd-netcat powertop mupdf-tools nomacs stow zsh-autosuggestions xf86-video-amdgpu xf86-video-intel xf86-video-nouveau npm fzf unclutter ccls mpd mpc ncmpcpp pavucontrol strawberry smartmontools firefox python-pynvim python-pylint tesseract-data-deu tesseract-data-eng keepassxc ueberzug img2pdf dust ctags python-wand python-termcolor python-black jdk-openjdk ripgrep lf ungoogled-chromium-bin ttf-jetbrains-mono-nerd foliate coreutils curl fish foot fuzzel gjs gnome-bluetooth-3.0 gnome-control-center gnome-keyring gobject-introspection grim gtk3 gtk-layer-shell libdbusmenu-gtk3 meson nlohmann-json plasma-browser-integration playerctl polkit-gnome python-pywal sassc slurp swayidle typescript xorg-xrandr webp-pixbuf-loader wireplumber yad ydotool gojq hyprland python-poetry python-build python-pillow ttf-material-symbols-variable-git ttf-space-mono-nerd wlogout kitty shfmt ruff luarocks rust-analyzer hyprland-guiutils waybar socat hyprlock brave-bin clang swaync bat wl-clipboard syncthing python-debug ghostty awww kitty tokei gemini-cli hypridle tlp || pacman_error_exit
 
-# install aur packages
+# Install AUR Packages
 echo -e "\e[0;30;34mInstalling packages from AUR ...\e[0m"
-doas -u "$username" paru -S --noconfirm --needed betterlockscreen simple-mtpfs redshift dashbinsh devour vim-plug lf-bin picom-jonaburg-fix doasedit openssh-dotconfig wget-xdg networkmanager-openvpn-xdg abook-configdir ungoogled-chromium-xdg-bin nerd-fonts-jetbrains-mono-160 electron-xdg-bin yarn-xdg-bin chromium-extension-clearurls chromium-extension-copy-url-on-hover-bin chromium-extension-decentraleyes chromium-extension-history-disabler-bin chromium-extension-https-everywhere chromium-extension-keepassxc-browser-bin chromium-extension-return-youtube-dislike chromium-extension-rggl-bin chromium-extension-ublock-origin-bin || pacman_error_exit
-
-suckless_build() {
-    if [ ! -d /home/"$username"/.local/src/"$1" ]; then
-        echo -e "\e[0;30;34mFetching "$1" ...\e[0m"
-        cd_into /home/"$username"/.local/src
-        git clone https://github.com/noahvogt/"$1".git
-    fi
-
-    cd_into /home/"$username"/.local/src/"$1"
-
-    if ! command -v "$1" > /dev/null; then
-        echo -e "\e[0;30;34mCompiling "$1" ...\e[0m"
-        make install || compile_error_exit
-    fi
-}
-
-dwm_build() {
-    if [ ! -d /home/"$username"/.local/src/"$1" ]; then
-        echo -e "\e[0;30;34mFetching "$1" ...\e[0m"
-        cd_into /home/"$username"/.local/src
-        git clone https://github.com/noahvogt/"$1".git --depth 1
-    fi
-
-    mv /home/"$username"/.local/src/"$1" /home/"$username"/.config
-    cd_into /home/"$username"/.config/"$1"
+doas -u "$username" paru -S --noconfirm --needed simple-mtpfs redshift dashbinsh cspell-lsp doasedit nodejs-cspell nvim-lazy google-java-format lexend-fonts-git || pacman_error_exit
 
-    if ! command -v "$1" > /dev/null; then
-        echo -e "\e[0;30;34mCompiling "$1" ...\e[0m"
-        make install || compile_error_exit
-    fi
-}
-
-suckless_build st
-suckless_build dwmblocks
-suckless_build dmenu
-
-# set global zshenv
+# Set Global zshenv
 echo -e "\e[0;30;34mSetting global zshenv ...\e[0m"
 mkdir -vp /etc/zsh
-echo "export ZDOTDIR=\$HOME/.config/zsh" > /etc/zsh/zshenv
-
-# make initial history file
-echo -e "\e[0;30;34mSetting initial zsh history file ...\e[0m"
-mkdir -vp /home/"$username"/.cache/zsh
-[ -f /home/"$username"/.cache/zsh/history ] ||
-    touch /home/"$username"/.cache/zsh/history
-
-# make user to owner of ~/ and /mnt/
-echo -e "\e[0;30;34mChanging ownership of /home/$username + /mnt ...\e[0m"
-chown -R "$username":users /home/"$username"/
-chown -R "$username":users /mnt/
-
-# change shell to zsh
-echo -e "\e[0;30;34mSetting default shell to $(which zsh)...\e[0m"
-if ! grep "^$username.*::/home/$username" /etc/passwd | sed 's/^.*://' | \
-    grep -q "^$(which zsh)$"; then
-    while true; do
-        doas -u "$username" chsh -s "$(which zsh)" && break
-    done
-fi
+echo "export ZDOTDIR=\$HOME/.config/zsh" >/etc/zsh/zshenv
+
+ensure_history_file_exists
+
+make_user_owner_of_HOME_and_mnt_dirs
 
-# enable tap to click
-echo -e "\e[0;30;34mEnabling tap to click ...\e[0m"
-[ ! -f /etc/X11/xorg.conf.d/40-libinput.conf ] && printf 'Section "InputClass"
-    Identifier "libinput touchpad catchall"
-    MatchIsTouchpad "on"
-    MatchDevicePath "/dev/input/event*"
-    Driver "libinput"
-    # Enable left mouse button by tapping
-    Option "Tapping" "on"
-EndSection' > /etc/X11/xorg.conf.d/40-libinput.conf
+change_login_shell_to_zsh
 
 setup_final_doas
 
-# cleanup
-echo -e "\e[0;30;34mCleaning up ...\e[0m"
-ls -A /home/"$username" | grep -q "\.bash" && rm /home/"$username"/.bash*
-ls -A /home/"$username" | grep -q "\.less" && rm /home/"$username"/.less*
+# ~/ Cleanup
+echo -e "\e[0;30;34mCleaning up \$HOME ...\e[0m"
+for f in /home/"$username"/.bash*; do
+    [ -f "$f" ] && rm "$f"
+done
+for f in /home/"$username"/.less*; do
+    [ -f "$f" ] && rm "$f"
+done