#!/usr/bin/bash # vim:ft=sh:fdm=marker:fmr={,} # archlabs installer library script file # this file is not meant to be run directly # sourcing this file in a non bash shell is not advised # shellcheck disable=2153 readonly RUN="/run/archiso/bootmnt/arch/boot" readonly VM="$(dmesg | grep -i "hypervisor")" install() { # NOTE: function calls prefixed with 'oneshot' will only ever be run once # this allows running install() multiple times without redoing things clear tput cnorm # unpack the file system oneshot install_base # generate /etc/fstab and touch it up if we used a swapfile printf "\n\n" genfstab -U $MNT > $MNT/etc/fstab 2>$ERR echeck "genfstab -U $MNT > $MNT/etc/fstab" [[ -f $MNT/swapfile ]] && sed -i "s~${MNT}~~" $MNT/etc/fstab # update the mirrorlist.. MUST be done before updating or it may be slow oneshot mirrorlist_sort # MUST be before bootloader and running mkinitcpio oneshot package_operations # mkinitcpio and bootloader install should only be done after installing the packages # and updating the mirrorlist, otherwise the chosen kernel may not be fully set up run_mkinitcpio install_bootloader # hwclock setup, falls back to setting --directisa if the default fails chrun "hwclock --systohc --utc" || chrun "hwclock --systohc --utc --directisa" # create the user oneshot create_user # set up user login.. MUST be done after package operation and user creation oneshot login_manager # drop off the user at the config editing menu edit_configs } install_base() { # compressed image? if [[ -e /run/archiso/sfs/airootfs/etc/skel ]]; then printf "\n\nUnpacking base system --- Total: ~ 2.6G\n\n" rsync -ah --info=progress2 /run/archiso/sfs/airootfs/ $MNT/ else # update the mirrorlist.. MUST be done before pacstrapping or it may be slow oneshot mirrorlist_sort printf "\nPacstrapping the base system.\n\n" local vmpkgs if [[ $VM && $KERNEL == 'linux-lts' ]]; then vmpkgs="virtualbox-guest-utils virtualbox-guest-dkms linux-lts-headers" elif [[ $VM && $KERNEL == 'linux' ]]; then vmpkgs="virtualbox-guest-utils virtualbox-guest-modules-arch" fi local packages packages="$(grep -hv '^#' /usr/share/archlabs/installer/packages.txt)" pacstrap $MNT base $KERNEL $UCODE $packages $vmpkgs fi # remove archiso init files and clean up install files rm -rf $MNT/etc/mkinitcpio-archiso.conf find $MNT/usr/lib/initcpio -name 'archiso*' -type f -exec rm '{}' \; # journal sed -i 's/volatile/auto/g' $MNT/etc/systemd/journald.conf # allow members of group 'wheel' to execute sudo commands sed -i "s/# %wheel ALL=(ALL) ALL/%wheel ALL=(ALL) ALL/g" $MNT/etc/sudoers if [[ $VM ]]; then # in a VM remove xorg configs, these cause issues rm -rf $MNT/etc/X11/xorg.conf.d elif [[ $(lspci | grep ' VGA ' | grep 'Intel') != "" ]]; then # xorg config for intel, this should never happen in a VM cat > $MNT/etc/X11/xorg.conf.d/20-intel.conf < manufacturer-ucode.img [[ $UCODE ]] && cp -f $RUN/${UCODE/-/_}.img $MNT/boot/${UCODE}.img fi # copy network settings if [[ -e /etc/NetworkManager/system-connections ]]; then cp -rf /etc/NetworkManager/system-connections $MNT/etc/NetworkManager/ fi cp -f /etc/resolv.conf $MNT/etc/ # set the locale printf "\n\n" cat > $MNT/etc/locale.conf << EOF LANG=$LOCALE EOF cat > $MNT/etc/default/locale << EOF LANG=$LOCALE EOF sed -i "s/#en_US.UTF-8/en_US.UTF-8/g; s/#${LOCALE}/${LOCALE}/g" $MNT/etc/locale.gen chrun "locale-gen" 2>/dev/null # set the timezone chrun "ln -sf /usr/share/zoneinfo/$ZONE/$SUBZONE /etc/localtime" 2>/dev/null if [[ $BROADCOM_WL == true ]]; then echo 'blacklist bcma' >> $MNT/etc/modprobe.d/blacklist.conf rm -f $MNT/etc/modprobe/ fi # set the keymaps cat > $MNT/etc/X11/xorg.conf.d/00-keyboard.conf < $MNT/etc/default/keyboard < $MNT/etc/vconsole.conf < $MNT/etc/hostname << EOF $HOSTNAME EOF cat > $MNT/etc/hosts << EOF 127.0.0.1 localhost 127.0.1.1 $HOSTNAME ::1 localhost ip6-localhost ip6-loopback ff02::1 ip6-allnodes ff02::2 ip6-allrouters EOF } create_user() { # set root password and shell if needed chrun "chpasswd <<< 'root:$ROOT_PASS'" if [[ $MYSHELL != *zsh ]]; then chrun "usermod -s $MYSHELL root" cp -f $MNT/etc/skel/.mkshrc /root/.mkshrc fi local groups='audio,autologin,floppy,log,network,rfkill,scanner,storage,optical,power,wheel' # setup the autologin group chrun "groupadd -r autologin" # Create the user, set password, and make sure the ownership of ~/ is correct chrun "useradd -m -u 1000 -g users -G $groups -s $MYSHELL $NEWUSER" 2>$ERR chrun "chpasswd <<< '$NEWUSER:$USER_PASS'" chrun "chown -Rf $NEWUSER:users /home/$NEWUSER" # for neovim set up ~/.config/nvim if [[ $PACKAGES =~ neovim ]]; then mkdir -p $MNT/home/$NEWUSER/.config/nvim cp -f $MNT/home/$NEWUSER/.vimrc $MNT/home/$NEWUSER/.config/nvim/init.vim cp -rf $MNT/home/$NEWUSER/.vim/colors $MNT/home/$NEWUSER/.config/nvim/colors fi [[ $INSTALL_WMS =~ dwm ]] && suckless_install return 0 } setup_xinit() { if [[ -e $MNT/home/$NEWUSER/.xinitrc ]]; then sed -i "s/openbox-session/${LOGIN_WM}/g" $MNT/home/$NEWUSER/.xinitrc else printf "%s\n" "exec $LOGIN_WM" > $MNT/home/$NEWUSER/.xinitrc fi # automatic startx for login shells local loginrc case $MYSHELL in "/bin/bash") loginrc=".bash_profile" rm -rf $MNT/home/$NEWUSER/.{z,mksh}* ;; "/usr/bin/mksh") loginrc=".profile" rm -rf $MNT/home/$NEWUSER/.{z,bash}* cat >> $MNT/home/$NEWUSER/.mkshrc << EOF # colors in less (manpager) export LESS_TERMCAP_mb=$'\e[01;31m' export LESS_TERMCAP_md=$'\e[01;31m' export LESS_TERMCAP_me=$'\e[0m' export LESS_TERMCAP_se=$'\e[0m' export LESS_TERMCAP_so=$'\e[01;44;33m' export LESS_TERMCAP_ue=$'\e[0m' export LESS_TERMCAP_us=$'\e[01;32m' export EDITOR=vim export MANWIDTH=100 # source shell configs for f in "\$HOME/.mksh/"*?.sh; do . "\$f" done al-info EOF ;; *) loginrc=".zprofile" rm -rf $MNT/home/$NEWUSER/.{bash,mksh}* esac # add the shell login file to the edit list after install EDIT_FILES[11]+=" /home/$NEWUSER/$loginrc" if [[ $AUTOLOGIN == true ]]; then sed -i "s/root/${NEWUSER}/g" $SERVICE/autologin.conf cat > $MNT/home/$NEWUSER/$loginrc << EOF # ~/$loginrc # sourced by $(basename $MYSHELL) when used as a login shell # automatically run startx when logging in on tty1 if [ -z "\$DISPLAY" ] && [ \$XDG_VTNR -eq 1 ]; then exec startx -- vt1 >/dev/null 2>&1 fi EOF else rm -rf $SERVICE rm -rf $MNT/home/$NEWUSER/.{profile,zprofile,bash_profile} fi } setup_lightdm() { rm -rf $SERVICE rm -rf $MNT/home/$NEWUSER/.{xinitrc,profile,zprofile,bash_profile} chrun 'systemctl set-default graphical.target && systemctl enable lightdm.service' cat > $MNT/etc/lightdm/lightdm-gtk-greeter.conf << EOF # LightDM GTK+ Configuration [greeter] active-monitor=0 default-user-image=/usr/share/icons/ArchLabs-Dark/64x64/places/distributor-logo-archlabs.png background=/usr/share/backgrounds/archlabs/archlabs.jpg theme-name=Adwaita-dark icon-theme-name=Adwaita font-name=DejaVu Sans Mono 11 position=30%,end 50%,end EOF } login_manager() { declare -g SERVICE="$MNT/etc/systemd/system/getty@tty1.service.d" # remove welcome message sed -i '/printf/d' $MNT/root/.zshrc if [[ $LOGIN_TYPE == 'lightdm' ]]; then setup_lightdm else setup_xinit fi } run_mkinitcpio() { local add="" # setup a keyfile for LUKS.. Only when choosing grub and system is UEFI [[ $LUKS && ! $LVM && $SYS == 'UEFI' && $BOOTLDR == 'grub' ]] && luks_keyfile # new hooks needed in /etc/mkinitcpio.conf if we used LUKS and/or LVM [[ $LVM ]] && add="lvm2" [[ $LUKS ]] && add="encrypt$([[ $add ]] && printf " %s" "$add")" sed -i "s/block filesystems/block ${add} filesystems ${MKINIT_HOOKS}/g" $MNT/etc/mkinitcpio.conf chrun "mkinitcpio -p $KERNEL" 2>$ERR echeck "mkinitcpio -p $KERNEL" } mirrorlist_sort() { printf "\n%s\n\n" "Sorting the mirrorlist" if hash reflector >/dev/null 2>&1; then $MIRROR_CMD --save $MNT/etc/pacman.d/mirrorlist --verbose || reflector --score 100 -l 50 -f 10 --sort rate --verbose --save $MNT/etc/pacman.d/mirrorlist else { eval $MIRROR_CMD || curl -s 'https://www.archlinux.org/mirrorlist/all/'; } | sed -e 's/^#Server/Server/' -e '/^#/d' | rankmirrors -n 10 - > $MNT/etc/pacman.d/mirrorlist fi } package_operations() { local inpkg="$PACKAGES" # add the packages chosen during setup local rmpkg="archlabs-installer" # always remove the installer if [[ $KERNEL == 'linux-lts' ]]; then rmpkg+=" linux" inpkg+=" linux-lts" fi # if the system is a VM then install the needed packages if [[ $VM ]]; then inpkg+=" virtualbox-guest-utils" if [[ $KERNEL == 'linux-lts' ]]; then inpkg+=" virtualbox-guest-dkms linux-lts-headers" else inpkg+=" virtualbox-guest-modules-arch" fi fi # for only gnome or cinnamon we don't need the xfce provided stuff [[ $INSTALL_WMS =~ (gnome|cinnamon) ]] && rmpkg+=" $(pacman -Qssq 'xfce4*' 2>/dev/null)" # when not using grub bootloader remove it's package and configurations if [[ $BOOTLDR != 'grub' ]]; then rmpkg+=" grub" rm -f $MNT/etc/default/grub find $MNT/boot/ -name 'grub*' -exec rm -rf '{}' \; >/dev/null 2>&1 fi # do the same when not using syslinux as the bootloader if [[ $BOOTLDR != 'syslinux' ]]; then find $MNT/boot/ -name 'syslinux*' -exec rm -rf '{}' \; >/dev/null 2>&1 fi chrun "pacman -Syyu --noconfirm" chrun "pacman -S iputils --noconfirm" 2>/dev/null chrun "pacman -S base-devel git --needed --noconfirm" 2>/dev/null chrun "pacman -S $inpkg --needed --noconfirm" chrun "pacman -Rs $rmpkg --noconfirm" return 0 } suckless_install() { # install and setup dwm printf "\n%s\n\n" "Installing and setting up dwm." mkdir -pv $MNT/home/$NEWUSER/suckless for i in dwm dmenu st; do p="/home/$NEWUSER/suckless/$i" chrun "git clone https://bitbucket.org/natemaia/$i $p" e=$? if (( e == 0 )); then chrun "cd $p; rm -f config.h; make clean install; make clean" else printf "\n\nFailed to clone dwm repo\n\n" fi done if [[ -d /home/$NEWUSER/suckless/dwm ]]; then printf "\n\n%s" "To configure dwm edit /home/$NEWUSER/suckless/dwm/config.h" printf "\n%s\n\n" "You can then recompile it with 'sudo make clean install'" fi sleep 2 }