3 # This program is free software, provided under the GNU GPL
4 # Written by Nathaniel Maia for use in Archlabs
5 # Some ideas and code reworked from other resources
6 # AIF, Cnichi, Calamares, Arch Wiki.. Credit where credit is due
10 # bulk default values {
12 : ${DIST=ArchLabs} # distro name if not set
13 MNT=/mnt # install mountpoint
14 ANS=/tmp/ans # dialog answer file
15 BOOTDIR=boot # location to mount boot partition
16 FONT=ter-i16n # font used for the linux console
17 HOOKS=shutdown # list of additional mkinitcpio HOOKS
18 SEL=0 # currently selected menu item
19 SYS=Unknown # bios type to be determined: UEFI/BIOS
20 ERR=/tmp/errlog # error log used internally
21 DBG=/tmp/debuglog # debug log when passed -d
22 RUN=/run/archiso/bootmnt/arch/boot # path for live system /boot
23 VM="$(dmesg | grep -i hypervisor)" # system running in a virtual machine
24 export DIALOGOPTS="--cr-wrap" # see `man dialog`
26 BASE_PKGS="base-devel xorg xorg-drivers sudo git gvfs gtk3 libmad libmatroska "
27 BASE_PKGS+="tumbler playerctl pulseaudio pulseaudio-alsa pavucontrol pamixer scrot "
28 BASE_PKGS+="xdg-user-dirs ffmpeg gstreamer gst-libav gst-plugins-base gst-plugins-good"
29 AL_BASE_PKGS="archlabs-skel-base archlabs-fonts archlabs-themes "
30 AL_BASE_PKGS+="archlabs-icons archlabs-wallpapers archlabs-scripts archlabs-baph"
31 WM_BASE_PKGS="arandr archlabs-networkmanager-dmenu nitrogen polkit-gnome "
32 WM_BASE_PKGS+="volumeicon xclip exo laptop-detect xdotool compton wmctrl feh "
33 WM_BASE_PKGS+="gnome-keyring dunst gsimplecal xfce4-power-manager xfce4-settings"
34 SYS_MEM="$(awk '/MemTotal/ {print int($2 / 1024) "M"}' /proc/meminfo)"
35 LOCALES="$(awk '/\.UTF-8/ {gsub(/# .*|#/, ""); if ($1) {print $1 " - "}}' /etc/locale.gen)"
36 CMAPS="$(find /usr/share/kbd/keymaps -name '*.map.gz' | awk '{gsub(/\.map\.gz|.*\//, ""); print $1 " - "}' | sort)"
37 [[ $LINES ]] || LINES=$(tput lines)
38 [[ $COLUMNS ]] || COLUMNS=$(tput cols)
42 # commands used to install each bootloader, however most get modified during runtime {
44 [refind-efi]='refind-install'
45 [grub]='grub-install --recheck --force' [syslinux]='syslinux-install_update -i -a -m'
46 [efistub]='efibootmgr -v -d /dev/sda -p 1 -c -l' [systemd-boot]='bootctl --path=/boot install'
49 # executable name for each wm/de used in ~/.xinitrc {
50 declare -A WM_SESSIONS=(
51 [dwm]='dwm' [i3-gaps]='i3' [bspwm]='bspwm' [awesome]='awesome' [plasma]='startkde' [xfce4]='startxfce4'
52 [gnome]='gnome-session' [fluxbox]='startfluxbox' [openbox]='openbox-session' [cinnamon]='cinnamon-session'
55 # packages installed for each wm/de, most are depends of the skel packages {
57 [dwm]='' [gnome]='' [cinnamon]='gnome-terminal' [plasma]='kdebase-meta'
58 [awesome]='archlabs-skel-awesome' [bspwm]='archlabs-skel-bspwm' [fluxbox]='archlabs-skel-fluxbox'
59 [i3-gaps]='archlabs-skel-i3-gaps' [openbox]='archlabs-skel-openbox' [xfce4]='archlabs-skel-xfce4 xfce4-goodies'
62 # files offered for editing after install is complete {
63 declare -A EDIT_FILES=(
64 [login]='' # login is populated once we know the username and shell
65 [fstab]='/etc/fstab' [sudoers]='/etc/sudoers' [crypttab]='/etc/crypttab' [pacman]='/etc/pacman.conf'
66 [console]='/etc/vconsole.conf' [mkinitcpio]='/etc/mkinitcpio.conf' [hostname]='/etc/hostname /etc/hosts'
67 [bootloader]="/boot/loader/entries/$DIST.conf" # ** based on bootloader
68 [locale]='/etc/locale.conf /etc/default/locale' [keyboard]='/etc/X11/xorg.conf.d/00-keyboard.conf /etc/default/keyboard'
71 # mkfs command flags for filesystem formatting {
72 declare -A FS_CMD_FLAGS=(
73 [f2fs]='' [jfs]='-q' [xfs]='-f' [ntfs]='-q' [ext2]='-q' [ext3]='-q' [ext4]='-q' [vfat]='-F32' [nilfs2]='-q' [reiserfs]='-q'
76 # mount options for each filesystem {
78 [vfat]='' [ntfs]='' [ext2]='' [ext3]='' # NA
79 [jfs]='discard errors=continue errors=panic nointegrity'
80 [reiserfs]='acl nolog notail replayonly user_xattr off'
81 [ext4]='discard dealloc nofail noacl relatime noatime nobarrier nodelalloc'
82 [xfs]='discard filestreams ikeep largeio noalign nobarrier norecovery noquota wsync'
83 [nilfs2]='discard nobarrier errors=continue errors=panic order=relaxed order=strict norecovery'
84 [f2fs]='discard fastboot flush_merge data_flush inline_xattr inline_data noinline_data inline_dentry no_heap noacl nobarrier norecovery noextent_cache disable_roll_forward disable_ext_identify'
87 # packages installed for each login option {
88 declare -A LOGIN_PKGS=(
89 [xinit]='xorg-xinit' [ly]='archlabs-ly' [gdm]='gdm' [sddm]='sddm'
90 [lightdm]='lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings accountsservice'
93 # extras installed for user selected packages {
94 # if a package requires additional packages that aren't already dependencies
95 # they can be added here eg. [package]="extra"
97 [vlc]='qt4' [mpd]='mpc' [mupdf]='mupdf-tools'
98 [rxvt-unicode]='urxvt-pearls' [zathura]='zathura-pdf-poppler' [noto-fonts]='noto-fonts-emoji' [cairo-dock]='cairo-dock-plug-ins' [qt5ct]='qt5-styleplugins'
99 [vlc]='qt5ct qt5-styleplugins' [qutebrowser]='qt5ct qt5-styleplugins' [qbittorrent]='qt5ct qt5-styleplugins' [transmission-qt]='qt5ct qt5-styleplugins'
100 [bluez]='bluez-libs bluez-utils bluez-tools bluez-plugins bluez-hid2hci' [kdenlive]='kdebase-meta dvdauthor frei0r-plugins breeze breeze-gtk qt5ct qt5-styleplugins'
103 # dialog text variables {
104 # Basics (somewhat in order)
105 _welcome="\nThis will help you get $DIST installed and setup on your system.\n\nIf you are unsure about a section the default option will be listed or\nthe first selected item will be the default.\n\n\nMenu Navigation:\n\n - Select items with the arrow keys or the option number.\n - Use [Space] to toggle check boxes and [Enter] to accept.\n - Switch between fields using [Tab] or the arrow keys.\n - Use [Page Up] and [Page Down] to jump whole pages\n - Press the highlighted key of an option to select it.\n"
106 _keymap="\nPick which keymap to use for the system from the list below\n\nThis is used once a graphical environment is running (Xorg).\n\nSystem default: us"
107 _vconsole="\nSelect the console keymap, the console is the tty shell you reach before starting a graphical environment (Xorg).\n\nIts keymap is seperate from the one used by the graphical environments, though many do use the same such as 'us' English.\n\nSystem default: us"
108 _device="\nSelect a device to use from the list below.\n\nDevices (/dev) are the available drives on the system. /sda, /sdb, /sdc ..."
109 _resize="\nSelect a new filesystem size in MB, a new partition will be created from the free space but will be left unformatted.\nThe lowest size is just enough to fit the currently in use space on the partition while the default is set to split the free space evenly.\n\nUse Tab or the arrow keys move the cursor between the buttons and the value, when the cursor is on the value, you can edit it by:\n\n - left/right cursor movement to select a digit to modify\n - +/- characters to increment/decrement the digit by one\n - 0 through 9 to set the digit to the given value\n\nSome keys are also recognized in all cursor positions:\n\n - Home/End set the value to its maximum or minimum\n - Pageup/Pagedown increment the value so that the slider moves by one column."
110 _mount="\nUse [Space] to toggle mount options from below, press [Enter] when done to confirm selection.\n\nNot selecting any and confirming will run an automatic mount."
111 _warn="\nIMPORTANT:\n\nChoose carefully when editing, formatting, and mounting partitions or your DATA MAY BE LOST.\n\nTo mount a partition without formatting it, select 'skip' when prompted to choose a filesystem during the mounting stage.\nThis can only be used for partitions that already contain a filesystem and cannot be the root (/) partition, it needs to be formatted before install.\n"
112 _part="\nFull device auto partitioning is available for beginners otherwise cfdisk is recommended.\n\n - All systems will require a root partition (8G or greater).\n - UEFI (and BIOS using LUKS without LVM) require a separate boot partition (100-512M)."
113 _uefi="\nSelect the EFI boot partition (/boot), required for UEFI boot.\n\nIt's usually the first partition on the device, 100-512M, and will be formatted as vfat/fat32 if not already."
114 _bios="\nDo you want to use a separate boot partition? (optional)\n\nIt's usually the first partition on the device, 100-512M, and will be formatted as ext3/4 if not already."
115 _biosluks="\nSelect the boot partition (/boot), required for LUKS.\n\nIt's usually the first partition on the device, 100-512M, and will be formatted as ext3/4 if not already."
116 _format="is already formatted correctly.\n\nFor a clean install, previously existing partitions should be reformatted, however this removes ALL data (bootloaders) on the partition so choose carefully.\n\nDo you want to reformat the partition?\n"
117 _swapsize="\nEnter the size of the swapfile in megabytes (M) or gigabytes (G).\n\neg. 100M will create a 100 megabyte swapfile, while 10G will create a 10 gigabyte swapfile.\n\nFor ease of use and as an example it is filled in to match the size of your system memory (RAM).\n\nMust be greater than 1, contain only whole numbers, and end with either M or G."
118 _expart="\nYou can now choose any additional partitions you want mounted, you'll be asked for a mountpoint after.\n\nSelect 'done' to finish the mounting step and begin unpacking the base system in the background."
119 _exmnt="\nWhere do you want the partition mounted?\n\nEnsure the name begins with a slash (/).\nExamples include: /usr, /home, /var, etc."
120 _user="\nEnter a name and password for the new user account.\n\nThe name must not use capital letters, contain any periods (.), end with a hyphen (-), or include any colons (:)\n\nNOTE: Use [Up], [Down], or [Tab] to switch between fields, and [Enter] to accept."
121 _hostname="\nEnter a hostname for the new system.\n\nA hostname is used to identify systems on the network.\n\nIt's restricted to alphanumeric characters (a-z, A-Z, 0-9).\nIt can contain hyphens (-) BUT NOT at the beggining or end."
122 _locale="\nLocale determines the system language and currency formats.\n\nThe format for locale names is languagecode_COUNTRYCODE\n\neg. en_US is: english United States\n en_GB is: english Great Britain"
123 _timez="\nThe time zone is used to set the system clock.\n\nSelect your country or continent from the list below"
124 _timesubz="\nSelect the nearest city to you or one with the same time zone.\n\nTIP: Pressing the first letter of the city name repeatedly will navigate between entries beggining with that letter."
125 _sessions="\nUse [Space] to toggle available sessions, use [Enter] to accept the selection and continue.\n\nA basic package set will be installed for compatibility and functionality."
126 _login="\nSelect which of your session choices to use for the initial login.\n\nYou can be change this later by editing your ~/.xinitrc"
127 _autologin="\nDo you want autologin enabled for USER?\n\nIf so the following two files will be created (disable autologin by removing them):\n\n - /home/USER/RC (run startx when logging in on tty1)\n - /etc/systemd/system/getty@tty1.service.d/autologin.conf (login USER without password)\n"
128 _packages="\nUse [Space] to move a package into the selected area and press [Enter] to accept the selection.\n\nPackages may be installed by your DE/WM (if any), or for the packages you select."
129 _edit="\nBefore exiting you can select configuration files to review/change.\n\nIf you need to make other changes with the drives still mounted, use Ctrl-z to pause the installer, when finished type 'fg' and [Enter] to resume the installer, if you want to avoid the automatic reboot using Ctrl-c will cleanly exit."
132 _luksnew="Basic LUKS Encryption"
133 _luksadv="Advanced LUKS Encryption"
134 _luksopen="Open Existing LUKS Partition"
135 _luksmenu="\nA seperate boot partition without encryption or logical volume management (LVM) is required (except BIOS systems using grub).\n\nBasic uses the default encryption settings, and is recommended for beginners. Advanced allows cypher and key size parameters to be entered manually."
136 _luksomenu="\nEnter a name and password for the encrypted device.\n\nIt is not necessary to prefix the name with /dev/mapper/,an example has been provided."
137 _lukskey="Once the specified flags have been amended, they will automatically be used with the 'cryptsetup -q luksFormat /dev/...' command.\n\nNOTE: Do not specify any additional flags such as -v (--verbose) or -y (--verify-passphrase)."
140 _lvmmenu="\nLogical volume management (LVM) allows 'virtual' hard drives (volume groups) and partitions (logical volumes) to be created from existing device partitions.\n\nA volume group must be created first, then one or more logical volumes within it.\n\nLVM can also be used with an encrypted partition to create multiple logical volumes (e.g. root and home) within it."
141 _lvmnew="Create Volume Group and Volume(s)"
142 _lvmdel="Delete an Existing Volume Group"
143 _lvmdelall="Delete ALL Volume Group(s) and Volume(s)"
144 _lvmvgname="\nEnter a name for the volume group (VG) being created from the partition(s) selected."
145 _lvmlvname="\nEnter a name for the logical volume (LV) being created.\n\nThis is similar to setting a label for a partition."
146 _lvmlvsize="\nEnter what size you want the logical volume (LV) to be in megabytes (M) or gigabytes (G).\n\neg. 100M will create a 100 megabyte volume, 10G will create a 10 gigabyte volume."
147 _lvmdelask="\nConfirm deletion of volume group(s) and logical volume(s).\n\nDeleting a volume group, will delete all logical volumes within it.\n"
150 _errexpart="\nCannot mount partition due to a problem with the mountpoint.\n\nEnsure it begins with a slash (/) followed by atleast one character.\n"
151 _errpart="\nYou need create the partiton(s) first.\n\n\nBIOS systems require at least one partition (ROOT).\n\nUEFI systems require at least two (ROOT and EFI).\n"
152 _lukserr="\nA minimum of two partitions are required for encryption:\n\n 1. root (/) - standard or LVM.\n 2. boot (/boot) - standard (unless using LVM on BIOS systems).\n"
153 _lvmerr="\nThere are no viable partitions available to use for LVM, a minimum of one is required.\n\nIf LVM is already in use, deactivating it will allow the partition(s) to be used again.\n"
154 _lvmerrvgname="\nInvalid name entered.\n\nThe volume group name may be alpha-numeric, but may not contain spaces, start with a '/', or already be in use.\n"
155 _lvmerlvname="\nInvalid name entered.\n\nThe logical volume (LV) name may be alpha-numeric, but may not contain spaces or be preceded with a '/'\n"
156 _lvmerrlvsize="\nInvalid value Entered.\n\nMust be a numeric value with 'M' (megabytes) or 'G' (gigabytes) at the end.\n\neg. 400M, 10G, 250G, etc...\n\nThe value may also not be equal to or greater than the remaining size of the volume group.\n"
160 ###############################################################################
162 # main is the entry point which calls functions including outside of its block
163 # once those functions finished they always are returned here with the
164 # exception of install_main(), it exits upon completion
168 (( SEL < 12 )) && (( SEL++ ))
170 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Prepare " --default-item $SEL --cancel-label 'Exit' --menu "$_prep" 0 0 0 \
171 1 "Device tree (optional)" \
172 2 "Partitioning (optional)" \
173 3 "LUKS setup (optional)" \
174 4 "LVM setup (optional)" \
175 5 "Mount partitions" \
176 6 "System bootloader" \
177 7 "User and password" \
178 8 "System configuration" \
179 9 "Select WM/DE (optional)" \
180 10 "Select Packages (optional)" \
181 11 "View configuration (optional)" \
182 12 "Start the installation" 2>"$ANS"
185 [[ -z $WARN && $SEL =~ (2|5) ]] && { msg "Data Warning" "$_warn"; WARN=true; }
188 2) part_menu || (( SEL-- )) ;;
189 3) luks_menu || (( SEL-- )) ;;
190 4) lvm_menu || (( SEL-- )) ;;
191 5) mount_menu || (( SEL-- )) ;;
192 6) prechecks 0 && { select_boot || (( SEL-- )); } ;;
193 7) prechecks 1 && { select_mkuser || (( SEL-- )); } ;;
194 8) prechecks 2 && { select_config || (( SEL-- )); } ;;
195 9) prechecks 3 && { select_sessions || (( SEL-- )); } ;;
196 10) prechecks 3 && { select_packages || (( SEL-- )); } ;;
197 11) prechecks 3 && select_show ;;
198 12) prechecks 3 && install_main ;;
199 *) yesno "Exit" "\nUnmount partitions (if any) and exit the installer?\n" && die 0
205 if [[ $SYS == 'BIOS' ]]; then
206 dlg BOOTLDR menu "BIOS Bootloader" "\nSelect which bootloader to use." \
207 "grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
208 "syslinux" "A collection of boot loaders for booting drives, CDs, or over the network" || return 1
210 dlg BOOTLDR menu "UEFI Bootloader" "\nSelect which bootloader to use." \
211 "systemd-boot" "A simple UEFI boot manager which executes configured EFI images" \
212 "grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
213 "refind-efi" "A UEFI boot manager that aims to be platform neutral and simplify multi-boot" \
214 "efistub" "Boot the kernel image directly (no chainloading support)" \
215 "syslinux" "A collection of boot loaders for booting drives, CDs, or over the network (no chainloading support)" || return 1
222 local pkgs="${USER_PKGS// / } ${PACKAGES// / }"
223 [[ $BOOT_PART ]] && local mnt="/$BOOTDIR"
224 [[ $INSTALL_WMS == *dwm* ]] && pkgs="dwm st dmenu $pkgs"
225 pkgs="${pkgs// / }" pkgs="${pkgs# }"
226 msg "Show Configuration" "
227 ---------- PARTITION CONFIGURATION ------------
229 Root: ${ROOT_PART:-none}
230 Boot: ${BOOT_PART:-${BOOT_DEV:-none}}
232 Swap: ${SWAP_PART:-none}
233 Size: ${SWAP_SIZE:-none}
234 Extra: ${EXMNTS:-${EXMNT:-none}}
235 Hooks: ${HOOKS:-none}
241 ------------ SYSTEM CONFIGURATION -------------
243 Locale: ${MYLOCALE:-none}
244 Keymap: ${KEYMAP:-none}
245 Hostname: ${MYHOST:-none}
246 Timezone: ${ZONE:-none}/${SUBZ:-none}
249 ------------ USER CONFIGURATION ---------------
251 Username: ${NEWUSER:-none}
252 Login Shell: ${MYSHELL:-none}
253 Login Session: ${LOGIN_WM:-none}
254 Autologin: ${AUTOLOGIN:-none}
255 Login Type: ${LOGIN_TYPE:-none}
258 ----------- PACKAGE CONFIGURATION -------------
260 Kernel: ${KERNEL:-none}
261 Bootloader: ${BOOTLDR:-none}
262 Packages: ${pkgs:-none}
268 [[ $INSTALL_WMS ]] || return 0
270 AUTOLOGIN='' # no autologin unless using xinit
272 dlg LOGIN_TYPE menu "Login Management" "\nSelect what kind of login management to use." \
273 "xinit" "Console login without a display manager" \
274 "ly" "TUI display manager with a ncurses-like interface" \
275 "lightdm" "Lightweight display manager with a gtk greeter" \
276 "gdm" "Gnome display manager" \
277 "sddm" "Simple desktop display manager" || return 1
280 ly) EDIT_FILES[login]="/etc/ly/config.ini" ;;
281 gdm|sddm) EDIT_FILES[login]="" ;;
282 lightdm) EDIT_FILES[login]="/etc/lightdm/lightdm.conf /etc/lightdm/lightdm-gtk-greeter.conf" ;;
283 xinit) EDIT_FILES[login]="/home/$NEWUSER/.xinitrc /home/$NEWUSER/.xprofile"
284 if (( $(wc -w <<< "$INSTALL_WMS") > 1 )); then
285 dlg LOGIN_WM menu "Login Management" "$_login" $LOGIN_CHOICES || return 1
286 LOGIN_WM="${WM_SESSIONS[$LOGIN_WM]}"
288 [[ -z $LOGIN_WM ]] && LOGIN_WM="${WM_SESSIONS[${INSTALL_WMS%% *}]}"
289 yesno "Autologin" "$(sed "s|USER|$NEWUSER|g; s|RC|$LOGINRC|g" <<< "$_autologin")" && AUTOLOGIN=true || AUTOLOGIN=''
299 until [[ $CONFIG_DONE ]]; do
301 0) dlg MYSHELL menu "Shell" "\nChoose which shell to use." \
302 zsh 'A very advanced and programmable command interpreter (shell) for UNIX' \
303 bash 'The GNU Bourne Again shell, standard in many GNU/Linux distributions' \
304 mksh 'The MirBSD Korn Shell - an enhanced version of the public domain ksh' || return 1
306 1) dlg MYHOST input "Hostname" "$_hostname" "${DIST,,}" limit || { i=0; continue; } ;;
307 2) dlg MYLOCALE menu "Locale" "$_locale" $LOCALES || { i=1; continue; } ;;
309 until [[ $ZONE && $SUBZ ]]; do
310 dlg ZONE menu "Timezone" "$_timez" America - Australia - Asia - Atlantic - Africa - Europe - Indian - Pacific - Arctic - Antarctica - || break
311 dlg SUBZ menu "Timezone" "$_timesubz" $(awk '/'"$ZONE"'\// {gsub(/'"$ZONE"'\//, ""); print $3 " - "}' /usr/share/zoneinfo/zone.tab | sort) || continue
313 [[ $ZONE && $SUBZ ]] || { i=2; continue; } ;;
314 4) dlg KERNEL menu "Kernel" "\nChoose which kernel to use." \
315 linux 'Vanilla linux kernel and modules, with a few patches applied' \
316 linux-lts 'Long-term support (LTS) linux kernel and modules' \
317 linux-zen 'A effort of kernel hackers to provide the best kernel for everyday systems' \
318 linux-hardened 'A security-focused linux kernel with hardening patches to mitigate exploits' || { i=3; continue; }
322 (( i++ )) # progress through to the next choice
325 case $MYSHELL in bash) LOGINRC='.bash_profile' ;; zsh) LOGINRC='.zprofile' ;; mksh) LOGINRC='.profile' ;; esac
333 local v='' u='' p='' p2='' rp='' rp2=''
335 until [[ $NEWUSER ]]; do
338 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " User " --mixedform "$_user" 0 0 0 \
339 "Username:" 1 1 "$u" 1 11 "$COLUMNS" 0 0 \
340 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
341 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 \
342 "--- Root password, if left empty the user password will be used ---" 6 1 '' 6 68 "$COLUMNS" 0 2 \
343 "Password:" 8 1 '' 8 11 "$COLUMNS" 0 1 \
344 "Password2:" 9 1 '' 9 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
346 while read -r line; do
347 case $i in 0) u="$line" ;; 1) p="$line" ;; 2) p2="$line" ;; 4) rp="$line" ;; 5) rp2="$line" ;; esac
351 # root passwords empty, so use the user passwords
352 [[ -z $rp && -z $rp2 ]] && { rp="$p"; rp2="$p2"; }
354 # make sure a username was entered and that the passwords match
355 if [[ ${#u} -eq 0 || $u =~ \ |\' || $u =~ [^a-z0-9] ]]; then
356 msg "Invalid Username" "\nIncorrect user name.\n\nPlease try again.\n"; u=''
357 elif [[ -z $p ]]; then
358 msg "Empty Password" "\nThe user password cannot be left empty.\n\nPlease try again.\n"
359 elif [[ "$p" != "$p2" ]]; then
360 msg "Password Mismatch" "\nThe user passwords do not match.\n\nPlease try again.\n"
361 elif [[ "$rp" != "$rp2" ]]; then
362 msg "Password Mismatch" "\nThe root passwords do not match.\n\nPlease try again.\n"
374 dlg KEYMAP menu "Keyboard Layout" "$_keymap" \
375 us English cm English gb English au English gh English \
376 za English ng English ca French 'cd' French gn French \
377 tg French fr French de German at German ch German \
378 es Spanish latam Spanish br Portuguese pt Portuguese ma Arabic \
379 sy Arabic ara Arabic ua Ukrainian cz Czech ru Russian \
380 sk Slovak nl Dutch it Italian hu Hungarian cn Chinese \
381 tw Taiwanese vn Vietnamese kr Korean jp Japanese th Thai \
382 la Lao pl Polish se Swedish is Icelandic 'fi' Finnish \
383 dk Danish be Belgian in Indian al Albanian am Armenian \
384 bd Bangla ba Bosnian 'bg' Bulgarian dz Berber mm Burmese \
385 hr Croatian gr Greek il Hebrew ir Persian iq Iraqi \
386 af Afghani fo Faroese ge Georgian ee Estonian kg Kyrgyz \
387 kz Kazakh lt Lithuanian mt Maltese mn Mongolian ro Romanian \
388 no Norwegian rs Serbian si Slovenian tj Tajik lk Sinhala \
389 tr Turkish uz Uzbek ie Irish pk Urdu 'mv' Dhivehi \
390 np Nepali et Amharic sn Wolof ml Bambara tz Swahili \
391 ke Swahili bw Tswana ph Filipino my Malay tm Turkmen \
392 id Indonesian bt Dzongkha lv Latvian md Moldavian mao Maori \
393 by Belarusian az Azerbaijani mk Macedonian kh Khmer epo Esperanto \
394 me Montenegrin || return 1
396 if [[ $CMAPS == *"$KEYMAP"* ]]; then
399 dlg CMAP menu "Console Keymap" "$_vconsole" $CMAPS || return 1
402 if [[ $DISPLAY && $TERM != 'linux' ]]; then
403 setxkbmap "$KEYMAP" >/dev/null 2>&1
405 loadkeys "$CMAP" >/dev/null 2>&1
414 dlg INSTALL_WMS check "Sessions" "$_sessions\n" \
415 openbox "A lightweight, powerful, and highly configurable stacking wm" "$(ofn openbox "${INSTALL_WMS[*]}")" \
416 i3-gaps "A fork of i3wm with more features including gaps" "$(ofn i3-gaps "${INSTALL_WMS[*]}")" \
417 dwm "A dynamic WM for X that manages windows in tiled, floating, or monocle layouts" "$(ofn dwm "${INSTALL_WMS[*]}")" \
418 bspwm "A tiling wm that represents windows as the leaves of a binary tree" "$(ofn bspwm "${INSTALL_WMS[*]}")" \
419 xfce4 "A lightweight and modular desktop environment based on gtk+2/3" "$(ofn xfce4 "${INSTALL_WMS[*]}")" \
420 awesome "A customized Awesome WM session created by @elanapan" "$(ofn awesome "${INSTALL_WMS[*]}")" \
421 fluxbox "A lightweight and highly-configurable window manager" "$(ofn fluxbox "${INSTALL_WMS[*]}")" \
422 plasma "A kde software project currently comprising a full desktop environment" "$(ofn plasma "${INSTALL_WMS[*]}")" \
423 gnome "A desktop environment that aims to be simple and easy to use" "$(ofn gnome "${INSTALL_WMS[*]}")" \
424 cinnamon "A desktop environment combining traditional desktop with modern effects" "$(ofn cinnamon "${INSTALL_WMS[*]}")"
426 [[ $INSTALL_WMS ]] || return 0
428 WM_PKGS="${INSTALL_WMS/dwm/}" # remove dwm from package list
429 WM_PKGS="${WM_PKGS// / }" # remove double spaces
430 WM_PKGS="${WM_PKGS# }" # remove leading space
432 # add archlabs base when choosing any session
433 [[ $WM_PKGS ]] && WM_PKGS+=" $AL_BASE_PKGS"
435 for i in $INSTALL_WMS; do
436 LOGIN_CHOICES+="$i - "
437 [[ ${WM_EXT[$i]} && $WM_PKGS != *"${WM_EXT[$i]}"* ]] && WM_PKGS+=" ${WM_EXT[$i]}"
440 select_login || return 1
442 while IFS=' ' read -r pkg; do
443 [[ $PACKAGES != *"$pkg"* ]] && PACKAGES+=" $pkg"
451 dlg USER_PKGS check " Packages " "$_packages" \
452 abiword "A Fully-featured word processor" "$(ofn abiword "${USER_PKGS[*]}")" \
453 alacritty "A cross-platform, GPU-accelerated terminal emulator" "$(ofn alacritty "${USER_PKGS[*]}")" \
454 atom "An open-source text editor developed by GitHub" "$(ofn atom "${USER_PKGS[*]}")" \
455 audacious "A free and advanced audio player based on GTK+" "$(ofn audacious "${USER_PKGS[*]}")" \
456 audacity "A program that lets you manipulate digital audio waveforms" "$(ofn audacity "${USER_PKGS[*]}")" \
457 blueman "GUI bluetooth device manager" "$(ofn blueman "${USER_PKGS[*]}")" \
458 bluez "Simple CLI based bluetooth support" "$(ofn bluez "${USER_PKGS[*]}")" \
459 cairo-dock "Light eye-candy fully themable animated dock" "$(ofn cairo-dock "${USER_PKGS[*]}")" \
460 calligra "A set of applications for productivity" "$(ofn calligra "${USER_PKGS[*]}")" \
461 chromium "An open-source web browser based on the Blink rendering engine" "$(ofn chromium "${USER_PKGS[*]}")" \
462 clementine "A modern music player and library organizer" "$(ofn clementine "${USER_PKGS[*]}")" \
463 cmus "A small, fast and powerful console music player" "$(ofn cmus "${USER_PKGS[*]}")" \
464 deadbeef "A GTK+ audio player for GNU/Linux" "$(ofn deadbeef "${USER_PKGS[*]}")" \
465 deluge "A BitTorrent client written in python" "$(ofn deluge "${USER_PKGS[*]}")" \
466 emacs "An extensible, customizable, self-documenting real-time display editor" "$(ofn emacs "${USER_PKGS[*]}")" \
467 epiphany "A GNOME web browser based on the WebKit rendering engine" "$(ofn epiphany "${USER_PKGS[*]}")" \
468 evince "A document viewer" "$(ofn evince "${USER_PKGS[*]}")" \
469 evolution "Manage your email, contacts and schedule" "$(ofn evolution "${USER_PKGS[*]}")" \
470 file-roller "Create and modify archives" "$(ofn file-roller "${USER_PKGS[*]}")" \
471 firefox "A popular open-source web browser from Mozilla" "$(ofn firefox "${USER_PKGS[*]}")" \
472 gcolor2 "A simple GTK+2 color selector" "$(ofn gcolor2 "${USER_PKGS[*]}")" \
473 geany "A fast and lightweight IDE" "$(ofn geany "${USER_PKGS[*]}")" \
474 geary "A lightweight email client for the GNOME desktop" "$(ofn geary "${USER_PKGS[*]}")" \
475 gimp "GNU Image Manipulation Program" "$(ofn gimp "${USER_PKGS[*]}")" \
476 gnome-calculator "GNOME Scientific calculator" "$(ofn gnome-calculator "${USER_PKGS[*]}")" \
477 gnome-disk-utility "Disk Management Utility" "$(ofn gnome-disk-utility "${USER_PKGS[*]}")" \
478 gnome-system-monitor "View current processes and monitor system state" "$(ofn gnome-system-monitor "${USER_PKGS[*]}")" \
479 gparted "A GUI frontend for creating and manipulating partition tables" "$(ofn gparted "${USER_PKGS[*]}")" \
480 gpick "Advanced color picker using GTK+ toolkit" "$(ofn gpick "${USER_PKGS[*]}")" \
481 gpicview "Lightweight image viewer" "$(ofn gpicview "${USER_PKGS[*]}")" \
482 guvcview "Capture video from camera devices" "$(ofn guvcview "${USER_PKGS[*]}")" \
483 hexchat "A popular and easy to use graphical IRC client" "$(ofn hexchat "${USER_PKGS[*]}")" \
484 inkscape "Professional vector graphics editor" "$(ofn inkscape "${USER_PKGS[*]}")" \
485 irssi "Modular text mode IRC client" "$(ofn irssi "${USER_PKGS[*]}")" \
486 kdenlive "A popular non-linear video editor for Linux" "$(ofn kdenlive "${USER_PKGS[*]}")" \
487 krita "Edit and paint images" "$(ofn krita "${USER_PKGS[*]}")" \
488 libreoffice-fresh "Full featured office suite" "$(ofn libreoffice-fresh "${USER_PKGS[*]}")" \
489 lollypop "A new music playing application" "$(ofn lollypop "${USER_PKGS[*]}")" \
490 mousepad "A simple text editor" "$(ofn mousepad "${USER_PKGS[*]}")" \
491 mpd "A flexible, powerful, server-side application for playing music" "$(ofn mpd "${USER_PKGS[*]}")" \
492 mpv "A media player based on mplayer" "$(ofn mpv "${USER_PKGS[*]}")" \
493 mupdf "Lightweight PDF and XPS viewer" "$(ofn mupdf "${USER_PKGS[*]}")" \
494 mutt "Small but very powerful text-based mail client" "$(ofn mutt "${USER_PKGS[*]}")" \
495 nautilus "The default file manager for Gnome" "$(ofn nautilus "${USER_PKGS[*]}")" \
496 ncmpcpp "A mpd client and almost exact clone of ncmpc with some new features" "$(ofn ncmpcpp "${USER_PKGS[*]}")" \
497 neovim "A fork of Vim aiming to improve user experience, plugins, and GUIs." "$(ofn neovim "${USER_PKGS[*]}")" \
498 noto-fonts "Google Noto fonts" "$(ofn noto-fonts "${USER_PKGS[*]}")" \
499 noto-fonts-cjk "Google Noto CJK fonts (Chinese, Japanese, Korean)" "$(ofn noto-fonts-cjk "${USER_PKGS[*]}")" \
500 obs-studio "Free opensource streaming/recording software" "$(ofn obs-studio "${USER_PKGS[*]}")" \
501 openshot "An open-source, non-linear video editor for Linux" "$(ofn openshot "${USER_PKGS[*]}")" \
502 opera "A Fast and secure, free of charge web browser from Opera Software" "$(ofn opera "${USER_PKGS[*]}")" \
503 pcmanfm "A fast and lightweight file manager based in Lxde" "$(ofn pcmanfm "${USER_PKGS[*]}")" \
504 pidgin "Multi-protocol instant messaging client" "$(ofn pidgin "${USER_PKGS[*]}")" \
505 plank "An elegant, simple, and clean dock" "$(ofn plank "${USER_PKGS[*]}")" \
506 qbittorrent "An advanced BitTorrent client" "$(ofn qbittorrent "${USER_PKGS[*]}")" \
507 qpdfview "A tabbed PDF viewer" "$(ofn qpdfview "${USER_PKGS[*]}")" \
508 qt5ct "GUI for managing Qt based application themes, icons, and fonts" "$(ofn qt5ct "${USER_PKGS[*]}")" \
509 qutebrowser "A keyboard-focused vim-like web browser based on Python and PyQt5" "$(ofn qutebrowser "${USER_PKGS[*]}")" \
510 rhythmbox "A Music playback and management application" "$(ofn rhythmbox "${USER_PKGS[*]}")" \
511 rxvt-unicode "A unicode enabled rxvt-clone terminal emulator" "$(ofn rxvt-unicode "${USER_PKGS[*]}")" \
512 sakura "A terminal emulator based on GTK and VTE" "$(ofn sakura "${USER_PKGS[*]}")" \
513 simple-scan "Simple scanning utility" "$(ofn simple-scan "${USER_PKGS[*]}")" \
514 simplescreenrecorder "A feature-rich screen recorder" "$(ofn simplescreenrecorder "${USER_PKGS[*]}")" \
515 steam "A popular game distribution platform by Valve" "$(ofn steam "${USER_PKGS[*]}")" \
516 surf "A simple web browser based on WebKit2/GTK+" "$(ofn surf "${USER_PKGS[*]}")" \
517 terminator "Terminal emulator that supports tabs and grids" "$(ofn terminator "${USER_PKGS[*]}")" \
518 termite "A minimal VTE-based terminal emulator" "$(ofn termite "${USER_PKGS[*]}")" \
519 thunar "A modern file manager for the Xfce Desktop Environment" "$(ofn thunar "${USER_PKGS[*]}")" \
520 thunderbird "Standalone mail and news reader from mozilla" "$(ofn thunderbird "${USER_PKGS[*]}")" \
521 tilda "A GTK based drop down terminal for Linux and Unix" "$(ofn tilda "${USER_PKGS[*]}")" \
522 tilix "A tiling terminal emulator for Linux using GTK+ 3" "$(ofn tilix "${USER_PKGS[*]}")" \
523 transmission-cli "Free BitTorrent client CLI" "$(ofn transmission-cli "${USER_PKGS[*]}")" \
524 transmission-gtk "GTK+ Front end for transmission" "$(ofn transmission-gtk "${USER_PKGS[*]}")" \
525 transmission-qt "Qt Front end for transmission" "$(ofn transmission-qt "${USER_PKGS[*]}")" \
526 ttf-anonymous-pro "A family fixed-width fonts designed with code in mind" "$(ofn ttf-anonymous-pro "${USER_PKGS[*]}")" \
527 ttf-fira-code "Monospaced font with programming ligatures" "$(ofn ttf-fira-code "${USER_PKGS[*]}")" \
528 ttf-font-awesome "Iconic font designed for Bootstrap" "$(ofn ttf-font-awesome "${USER_PKGS[*]}")" \
529 ttf-hack "A hand groomed typeface based on Bitstream Vera Mono" "$(ofn ttf-hack "${USER_PKGS[*]}")" \
530 vlc "A free and open source cross-platform multimedia player" "$(ofn vlc "${USER_PKGS[*]}")" \
531 weechat "Fast, light and extensible IRC client" "$(ofn weechat "${USER_PKGS[*]}")" \
532 xapps "Common library for X-Apps project" "$(ofn xapps "${USER_PKGS[*]}")" \
533 xarchiver "A GTK+ frontend to various command line archivers" "$(ofn xarchiver "${USER_PKGS[*]}")" \
534 xed "A small and lightweight text editor. X-Apps Project." "$(ofn xed "${USER_PKGS[*]}")" \
535 xfce4-terminal "A terminal emulator based in the Xfce Desktop Environment" "$(ofn xfce4-terminal "${USER_PKGS[*]}")" \
536 xreader "Document viewer for files like PDF and Postscript. X-Apps Project." "$(ofn xed "${USER_PKGS[*]}")" \
537 xterm "The standard terminal emulator for the X window system" "$(ofn xterm "${USER_PKGS[*]}")" \
538 zathura "Minimalistic document viewer" "$(ofn zathura "${USER_PKGS[*]}")"
540 if [[ $USER_PKGS ]]; then # add any needed PKG_EXT to the list
541 for i in $USER_PKGS; do
542 [[ ${PKG_EXT[$i]} && $USER_PKGS != *"${PKG_EXT[$i]}"* ]] && USER_PKGS+=" ${PKG_EXT[$i]}"
549 ###############################################################################
551 # non-essential partitioning helpers called by the user when using the optional
552 # partition menu and selecting a device to edit
556 no_bg_install || return 0
557 local device choice devhash
558 devhash="$(lsblk -f | base64)"
560 part_device || return 1
565 dlg choice menu "Edit Partitions" "$_part" \
566 "auto" "Whole device automatic partitioning" \
567 "shrink" "Shrink an existing ext2/3/4 or ntfs partition to make room for a new partition" \
568 "cfdisk" "Curses based variant of fdisk" \
569 "parted" "GNU partition editor" \
570 "fdisk" "Dialog-driven creation and manipulation of partitions" \
571 "done" "Return to the main menu"
573 if [[ -z $choice || $choice == 'done' ]]; then
575 elif [[ $choice == 'shrink' ]]; then
576 part_shrink "$device"
577 elif [[ $choice == 'auto' ]]; then
578 local root_size txt table boot_fs
579 root_size=$(lsblk -lno SIZE "$device" | awk 'NR == 1 {
582 print ($1 * 1000 - 512) / 1000 "G"
588 txt="\nWARNING:\n\nALL data on $device will be destroyed and the following partitions will be created\n\n- "
589 if [[ $SYS == 'BIOS' ]]; then
590 table="msdos" boot_fs="ext4"
591 txt+="An $boot_fs boot partition with the boot flag enabled (512M)\n- "
593 table="gpt" boot_fs="fat32"
594 txt+="A $boot_fs efi boot partition (512M)\n- "
596 txt+="An ext4 partition using all remaining space ($root_size)\n\nDo you want to continue?\n"
597 yesno "Auto Partition" "$txt" && part_auto "$device" "$table" "$boot_fs" "$root_size"
603 if [[ $devhash != "$(lsblk -f | base64)" ]]; then
604 msg "Probing Partitions" "\nInforming kernel of partition changes using partprobe\n" 0
605 partprobe >/dev/null 2>&1
606 [[ $choice == 'auto' ]] && return
614 if [[ $IGNORE_DEV ]]; then
615 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk "!/$IGNORE_DEV/"' && /disk|part|lvm|crypt|NAME/')"
617 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk '/disk|part|lvm|crypt|NAME/')"
619 msg "Device Tree" "\n\n$txt\n\n"
624 local device="$1" table="$2" boot_fs="$3" size="$4" dev_info=""
625 dev_info="$(parted -s "$device" print)"
627 msg "Auto Partition" "\nRemoving partitions on $device and setting table to $table\n" 1
630 while read -r PART; do
631 parted -s "$device" rm "$PART" >/dev/null 2>&1
632 done <<< "$(awk '/^ [1-9][0-9]?/ {print $1}' <<< "$dev_info" | sort -r)"
634 [[ $(awk '/Table:/ {print $3}' <<< "$dev_info") != "$table" ]] && parted -s "$device" mklabel "$table" >/dev/null 2>&1
636 msg "Auto Partition" "\nCreating a 512M $boot_fs boot partition.\n" 1
637 if [[ $SYS == "BIOS" ]]; then
638 parted -s "$device" mkpart primary "$boot_fs" 1MiB 513MiB >/dev/null 2>&1
640 parted -s "$device" mkpart ESP "$boot_fs" 1MiB 513MiB >/dev/null 2>&1
645 AUTO_BOOT_PART=$(lsblk -lno NAME,TYPE "$device" | awk 'NR==2 {print "/dev/" $1}')
647 if [[ $SYS == "BIOS" ]]; then
648 mkfs.ext4 -q "$AUTO_BOOT_PART" >/dev/null 2>&1
650 mkfs.vfat -F32 "$AUTO_BOOT_PART" >/dev/null 2>&1
653 msg "Auto Partition" "\nCreating a $size ext4 root partition.\n" 0
654 parted -s "$device" mkpart primary ext4 513MiB 100% >/dev/null 2>&1
656 AUTO_ROOT_PART="$(lsblk -lno NAME,TYPE "$device" | awk 'NR==3 {print "/dev/" $1}')"
657 mkfs.ext4 -q "$AUTO_ROOT_PART" >/dev/null 2>&1
659 msg "Auto Partition" "\nProcess complete.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$device")\n"
666 local device="$1" fs=""
668 part_find "${device##*/}[^ ]" || return 1
669 (( COUNT == 1 )) && part="$(awk '{print $1}' <<< "${PARTS[@]}" )"
671 if (( COUNT == 1 )) || dlg part menu "Resize" "\nWhich partition on $device do you want to resize?" $PARTS; then
672 fs=$(lsblk -lno FSTYPE "$part")
675 msg "Resize" "\nGathering device size info.\n" 0
677 end=$(parted -s "$device" unit KiB print | awk '/^\s*'"$num"'/ {print $3}') # part size in KiB
678 devsize=$(parted -s "$device" unit KiB print | awk '/Disk '"${device//\//\\/}"':/ {print $3}') # whole device size in KiB
679 mount "$part" $MNT >/dev/null 2>&1; sleep 0.5
680 min=$(df --output=used --block-size=MiB "$part" | awk 'NR == 2 {print int($1) + 256}')
681 max=$(df --output=avail --block-size=MiB "$part" | awk 'NR == 2 {print int($1)}')
684 if dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Resize: $part " --rangebox "$_resize" 17 "$COLUMNS" "$min" "$max" $((max / 2)) 2>$ANS; then
686 size=$((size * 1024))
693 if ntfsresize -fc "$part"; then
694 ntfsresize -ff --size $(( (size * 1024) / 1000 ))k "$part" 2>$ERR # k=10^3 bytes
695 errshow "ntfsresize -f -s $(( (size * 1024) / 1000 ))k $part" || return 1
697 msg "Resize" "\nThe ntfs partition $part cannot be resized because it is scheduled for a consistency check.\n\nTo do a consistency check in windows open command prompt as admin and run:\n\n\tchkdsk /f /r /x\n"
702 e2fsck -f "$part"; sleep 0.5
703 resize2fs -f "$part" ${size}K 2>$ERR # K=2^10 bytes
704 errshow "resize2fs -f $part ${size}K" || return 1
708 parted "$device" resizepart "$num" ${size}KiB || return 1
711 if [[ $devsize == "$end" ]]; then
712 parted -s "$device" mkpart primary ext4 ${size}KiB 100% 2>$ERR
713 errshow "parted -s $device mkpart primary ext4 ${size}KiB 100%" || return 1
715 parted -s "$device" mkpart primary ext4 ${size}KiB ${end}KiB 2>$ERR
716 errshow "parted -s $device mkpart primary ext4 ${size}KiB ${end}KiB" || return 1
718 msg "Resize Complete" "\n$part has been successfully resized to $((size / 1024))M.\n" 1
720 "") msg "No Filesystem" "\nFor unformatted partitions, cfdisk can be used in the partition menu.\n" ;;
721 *) msg "Invalid Filesystem: $fs" "\nResizing only supports ext and ntfs.\n" ;;
726 ###############################################################################
727 # partition management functions
728 # these are helpers for use by other functions to do essential setup/teardown
732 local regexp="$1" err=''
734 # string of partitions as /TYPE/PART SIZE
735 if [[ $IGNORE_DEV ]]; then
736 PARTS="$(lsblk -lno TYPE,NAME,SIZE |
737 awk "/$regexp/"' && !'"/$IGNORE_DEV/"' {
738 sub(/^part/, "/dev/")
739 sub(/^lvm|^crypt/, "/dev/mapper/")
743 PARTS="$(lsblk -lno TYPE,NAME,SIZE |
745 sub(/^part/, "/dev/")
746 sub(/^lvm|^crypt/, "/dev/mapper/")
751 # number of partitions total
753 while read -r line; do
757 # ensure we have enough partitions for the system and action type
759 'part|lvm|crypt') [[ $COUNT -lt 1 || ($SYS == 'UEFI' && $COUNT -lt 2) ]] && err="$_errpart" ;;
760 'part|crypt') (( COUNT < 1 )) && err="$_lvmerr" ;;
761 'part|lvm') (( COUNT < 2 )) && err="$_lukserr" ;;
764 # if there aren't enough partitions show the relevant error message
765 [[ $err ]] && { msg "Not Enough Partitions" "$err" 2; return 1; }
772 if [[ $1 == "$MNT/swapfile" && $SWAP_SIZE ]]; then
773 fallocate -l $SWAP_SIZE "$1" 2>$ERR
774 errshow "fallocate -l $SWAP_SIZE $1"
775 chmod 600 "$1" 2>$ERR
776 errshow "chmod 600 $1"
778 mkswap "$1" >/dev/null 2>$ERR
780 swapon "$1" >/dev/null 2>$ERR
787 local part="$1" mountp="${MNT}$2" fs=""
788 fs="$(lsblk -lno FSTYPE "$part")"
791 if [[ $fs && ${FS_OPTS[$fs]} && $part != "$BOOT_PART" && $part != "$AUTO_ROOT_PART" ]] && select_mntopts "$fs"; then
792 mount -o "$MNT_OPTS" "$part" "$mountp" >/dev/null 2>&1
794 mount "$part" "$mountp" >/dev/null 2>&1
797 part_mountconf "$part" "$mountp" || return 1
805 local part="$1" fs="$2" delay="$3"
807 msg "Format" "\nFormatting $part as $fs\n" 0
808 mkfs.$fs ${FS_CMD_FLAGS[$fs]} "$part" >/dev/null 2>$ERR
809 errshow "mkfs.$fs ${FS_CMD_FLAGS[$fs]} "$part"" || return 1
816 if [[ $DEV_COUNT -eq 1 && $SYS_DEVS ]]; then
817 DEVICE="$(awk '{print $1}' <<< "$SYS_DEVS")"
818 elif (( DEV_COUNT > 1 )); then
820 dlg DEVICE menu "Boot Device" "\nSelect the device to use for bootloader install." $SYS_DEVS
822 dlg DEVICE menu "Select Device" "$_device" $SYS_DEVS
824 [[ $DEVICE ]] || return 1
825 elif [[ $DEV_COUNT -lt 1 && ! $1 ]]; then
826 msg "Device Error" "\nNo available devices.\n\nExiting..\n" 2
830 [[ $1 ]] && BOOT_DEV="$DEVICE"
837 BOOT_DEV="${BOOT_PART%[1-9]}"
838 BOOT_PART_NUM="${BOOT_PART: -1}"
839 [[ $BOOT_PART = /dev/nvme* ]] && BOOT_DEV="${BOOT_PART%p[1-9]}"
840 if [[ $SYS == 'UEFI' ]]; then
841 parted -s $BOOT_DEV set $BOOT_PART_NUM esp on >/dev/null 2>&1
843 parted -s $BOOT_DEV set $BOOT_PART_NUM boot on >/dev/null 2>&1
850 local part="$1" devs=""
851 devs="$(lsblk -lno NAME,FSTYPE,TYPE)"
853 # Identify if $part is LUKS+LVM, LVM+LUKS, LVM alone, or LUKS alone
854 if lsblk -lno TYPE "$part" | grep -q 'crypt'; then
856 LUKS_NAME="${part#/dev/mapper/}"
857 for dev in $(awk '/lvm/ && /crypto_LUKS/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
858 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
859 LUKS_DEV="$LUKS_DEV cryptdevice=$dev:$LUKS_NAME"
864 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
865 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
866 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
867 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
871 elif lsblk -lno TYPE "$part" | grep -q 'lvm'; then
873 VNAME="${part#/dev/mapper/}"
874 for dev in $(awk '/crypt/ && /lvm2_member/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
875 if lsblk -lno NAME "$dev" | grep -q "$VNAME"; then
876 LUKS_NAME="${dev/\/dev\/mapper\//}"
880 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
881 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
882 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
883 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
894 if (( COUNT > 0 )); then
895 PARTS="$(sed "/${pt//\//\\/}/d" <<< "$PARTS")"
903 if grep -qw "$1" /proc/mounts; then
904 msg "Mount Success" "\nPartition $1 mounted at $2\n" 1
908 msg "Mount Fail" "\nPartition $1 failed to mount at $2\n" 2
913 ###############################################################################
915 # mount_menu is the entry point which calls all other functions
916 # once finished it returns to the main menu: main()
920 msg "Info" "\nGathering device info.\n" 0
921 no_bg_install || return 0
924 part_find 'part|lvm|crypt' || { SEL=2; return 1; }
926 [[ $LUKS && $LUKS_PART ]] && part_countdec $LUKS_PART
927 [[ $LVM && $LVM_PARTS ]] && part_countdec $LVM_PARTS
929 select_root_partition || return 1
931 if [[ $SYS == 'UEFI' ]]; then
932 select_efi_partition || { BOOT_PART=''; return 1; }
933 elif (( COUNT > 0 )); then
934 select_boot_partition || { BOOT_PART=''; return 1; }
937 if [[ $BOOT_PART ]]; then
938 part_mount "$BOOT_PART" "/$BOOTDIR" && SEP_BOOT=true || return 1
942 select_swap || return 1
943 select_extra_partitions || return 1
951 dlg SWAP_PART menu "Swap Setup" "\nSelect whether to use a swapfile, swap partition, or none." \
952 "none" "Don't allocate any swap space" \
953 "swapfile" "Allocate $SYS_MEM at /swapfile" \
956 if [[ -z $SWAP_PART || $SWAP_PART == "none" ]]; then
959 elif [[ $SWAP_PART == "swapfile" ]]; then
961 until [[ ${SWAP_SIZE:0:1} =~ [1-9] && ${SWAP_SIZE: -1} =~ (M|G) ]]; do
962 (( i > 0 )) && msg "Swap Size Error" "\nSwap size must be 1(M|G) or greater, and can only contain whole numbers\n\nSize entered: $SWAP_SIZE\n" 2
963 dlg SWAP_SIZE input "Swap Setup" "$_swapsize" "$SYS_MEM" || { SWAP_PART=''; SWAP_SIZE=''; return 1; }
966 part_swap "$MNT/$SWAP_PART"
967 SWAP_PART="/$SWAP_PART"
968 elif [[ $PARTS == *"$SWAP_PART"* ]]; then
970 part_countdec $SWAP_PART
971 SWAP_SIZE="$(lsblk -lno SIZE $SWAP_PART)"
981 local fs="$1" opts=''
982 local title="${fs^} Mount Options"
984 for i in ${FS_OPTS[$fs]}; do
988 until [[ $MNT_OPTS ]]; do
989 dlg MNT_OPTS check "$title" "$_mount" $opts
990 [[ $MNT_OPTS ]] || return 1
991 MNT_OPTS="${MNT_OPTS// /,}"
992 yesno "$title" "\nConfirm the following options: $MNT_OPTS\n" || MNT_OPTS=''
1001 until [[ $EXMNT ]]; do
1002 dlg EXMNT input "Extra Mount $part" "$_exmnt" "/" || return 1
1003 if [[ ${EXMNT:0:1} != "/" || ${#EXMNT} -le 1 || $EXMNT =~ \ |\' || $EXMNTS == *"$EXMNT"* ]]; then
1004 msg "Mountpoint Error" "$_errexpart"
1013 local part="$1" fs='' cur=''
1014 local txt="\nSelect which filesystem to use for: $part\n\nDefault: ext4"
1015 cur="$(lsblk -lno FSTYPE "$part" 2>/dev/null)"
1017 # bail early if the partition was created in part_auto()
1018 [[ $cur && $part == "$AUTO_ROOT_PART" ]] && return 0
1021 if [[ $cur && $FORMATTED == *"$part"* ]]; then
1022 dlg fs menu "Filesystem" "$txt\nCurrent: $cur" skip - ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1024 dlg fs menu "Filesystem" "$txt" ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1026 [[ $fs == 'skip' ]] && return 0
1027 yesno "Filesystem" "\nFormat $part as $fs?\n" || fs=''
1029 part_format "$part" "$fs"
1032 select_efi_partition()
1034 if [[ $AUTO_BOOT_PART ]]; then
1035 msg "EFI Boot Partition" "\nUsing partition created during automatic format.\n" 2
1036 BOOT_PART="$AUTO_BOOT_PART"
1037 return 0 # were done here
1039 local pts size dev isize bsize ptcount=0
1041 # walk partition list and skip ones that are too small/big for boot
1042 while read -r dev size; do
1043 size_t="${size: -1:1}" # size type eg. K, M, G, T
1044 isize=${size:0:-1} # remove trailing size type character
1045 isize=${isize%.*} # remove any decimal (round down)
1046 [[ $size_t =~ [KT] || ($size_t == 'G' && $isize -gt 2) || ($size_t == 'M' && $isize -lt 100) ]] || { pts+="$dev $size "; (( ptcount++ )); }
1049 if (( ptcount == 1 )); then
1050 msg "EFI Boot Partition" "\nOnly one partition available that meets size requirements.\n" 1
1051 BOOT_PART="$(awk 'NF > 0 {print $1}' <<< "$pts")"
1053 dlg BOOT_PART menu "EFI Partition" "$_uefi" $pts
1057 if [[ -z $BOOT_PART ]]; then
1059 elif grep -q 'fat' <<< "$(fsck -N "$BOOT_PART")"; then
1060 local txt="\nIMPORTANT:\n\nThe EFI partition $BOOT_PART $_format"
1061 if yesno "Format EFI Partition" "$txt" "Format $BOOT_PART" "Skip Formatting" 1; then
1062 part_format "$BOOT_PART" "vfat" 2
1065 part_format "$BOOT_PART" "vfat" 2
1071 select_boot_partition()
1073 if [[ $AUTO_BOOT_PART && ! $LVM ]]; then
1074 msg "Boot Partition" "\nUsing partition created during automatic format.\n" 2
1075 BOOT_PART="$AUTO_BOOT_PART"
1076 return 0 # were done here
1078 local pts size dev isize bsize ptcount=0
1080 # walk partition list and skip ones that are too small/big for boot
1081 while read -r dev size; do
1082 size_t="${size: -1:1}" # size type eg. K, M, G, T
1083 isize=${size:0:-1} # remove trailing size type character
1084 isize=${isize%.*} # remove any decimal (round down)
1085 [[ $size_t =~ [KT] || ($size_t == 'G' && $isize -gt 2) || ($size_t == 'M' && $isize -lt 100) ]] || { pts+="$dev $size "; (( ptcount++ )); }
1088 if [[ $LUKS && ! $LVM ]]; then
1089 dlg BOOT_PART menu "Boot Partition" "$_biosluks" $pts
1090 [[ $BOOT_PART ]] || return 1
1092 dlg BOOT_PART menu "Boot Partition" "$_bios" "skip" "don't use a separate boot" $pts
1093 [[ -z $BOOT_PART || $BOOT_PART == "skip" ]] && { BOOT_PART=''; return 0; }
1097 if grep -q 'ext[34]' <<< "$(fsck -N "$BOOT_PART")"; then
1098 local txt="\nIMPORTANT:\n\nThe boot partition $BOOT_PART $_format"
1099 if yesno "Format Boot Partition" "$txt" "Format $BOOT_PART" "Skip Formatting" 1; then
1100 part_format "$BOOT_PART" "ext4" 2
1103 part_format "$BOOT_PART" "ext4" 2
1108 select_root_partition()
1110 if [[ $AUTO_ROOT_PART && -z $LVM && -z $LUKS ]]; then
1111 ROOT_PART="$AUTO_ROOT_PART"
1112 msg "Root Partition (/)" "\nUsing partition created during automatic format.\n" 2
1113 part_mount "$ROOT_PART" || { ROOT_PART=''; return 1; }
1114 return 0 # we're done here
1116 local pts size dev isize bsize ptcount=0
1118 # walk partition list and skip ones that are too small for / (root)
1119 while read -r dev size; do
1120 size_t="${size: -1:1}" # size type eg. K, M, G, T
1121 isize=${size:0:-1} # remove trailing size type character
1122 isize=${isize%.*} # remove any decimal (round down)
1123 [[ $size_t =~ [MK] || ($size_t == 'G' && $isize -lt 4) ]] || { pts+="$dev $size "; (( ptcount++ )); }
1126 if (( ptcount == 1 )); then # only one available device
1127 msg "Root Partition (/)" "\nOnly one partition available that meets size requirements.\n" 2
1128 ROOT_PART="$(awk 'NF > 0 {print $1}' <<< "$pts")"
1130 dlg ROOT_PART menu "Mount Root" "\nSelect the root (/) partition, this is where $DIST will be installed.\n\nDevices smaller than 8G will not be shown here." $pts
1134 if [[ -z $ROOT_PART ]] || ! select_filesystem "$ROOT_PART" || ! part_mount "$ROOT_PART"; then
1142 select_extra_partitions()
1146 # walk partition list and skip ones that are too small to be usable
1147 while read -r dev size; do
1148 [[ ${size: -1:1} =~ [KM] ]] && part_countdec "$dev"
1151 while (( COUNT > 0 )); do
1153 dlg part menu 'Mount Extra' "$_expart" 'done' 'finish mounting step' $PARTS || break
1154 if [[ $part == 'done' ]]; then
1156 elif select_filesystem "$part" && select_mountpoint && part_mount "$part" "$EXMNT"; then
1157 EXMNTS+="$part: $EXMNT "
1158 [[ $EXMNT == '/usr' && $HOOKS != *usr* ]] && HOOKS="usr $HOOKS"
1166 ###############################################################################
1168 # main is the entry point which calls all other install functions, once
1169 # complete it shows a dialog to edit files on the new system before reboot
1174 genfstab -U $MNT >$MNT/etc/fstab 2>$ERR
1175 errshow 1 "genfstab -U $MNT >$MNT/etc/fstab"
1176 [[ -f $MNT/swapfile ]] && sed -i "s~${MNT}~~" $MNT/etc/fstab
1180 chrun "hwclock --systohc --utc" || chrun "hwclock --systohc --utc --directisa"
1183 chrun "chown -Rf $NEWUSER:users /home/$NEWUSER"
1186 dlg choice menu "Finalization" "$_edit" \
1187 finished "exit the installer and reboot" \
1188 keyboard "${EDIT_FILES[keyboard]}" \
1189 console "${EDIT_FILES[console]}" \
1190 locale "${EDIT_FILES[locale]}" \
1191 hostname "${EDIT_FILES[hostname]}" \
1192 sudoers "${EDIT_FILES[sudoers]}" \
1193 mkinitcpio "${EDIT_FILES[mkinitcpio]}" \
1194 fstab "${EDIT_FILES[fstab]}" \
1195 crypttab "${EDIT_FILES[crypttab]}" \
1196 bootloader "${EDIT_FILES[bootloader]}" \
1197 pacman "${EDIT_FILES[pacman]}" \
1198 login "${EDIT_FILES[login]}"
1200 if [[ -z $choice || $choice == 'finished' ]]; then
1201 [[ $DEBUG == true && -r $DBG ]] && $EDITOR $DBG
1205 for f in ${EDIT_FILES[$choice]}; do
1206 [[ -e ${MNT}$f ]] && exists+=" ${MNT}$f"
1208 if [[ $exists ]]; then
1211 msg "File Missing" "\nThe file(s) selected do not exist:\n\n${EDIT_FILES[$choice]}\n"
1221 while kill -0 $BG_PID 2>/dev/null; do
1222 clear; printf "\nA background install process is still running...\n"; sleep 1
1227 rm -rf $MNT/etc/mkinitcpio-archiso.conf
1228 find $MNT/usr/lib/initcpio -name 'archiso*' -type f -delete
1229 sed -i 's/#\(Storage=\)volatile/\1auto/' $MNT/etc/systemd/journald.conf
1230 find $MNT/boot -name '*-ucode.img' -delete
1232 [[ $DIST != "ArchLabs" ]] || sed -i "s/ArchLabs/$DIST/g" $MNT/etc/{lsb-release,os-release}
1235 find $MNT/etc/X11/xorg.conf.d/ -name '*.conf' -delete
1236 elif lspci | grep ' VGA ' | grep -q 'Intel'; then
1237 echo "Creating Intel VGA Tear Free config /etc/X11/xorg.conf.d/20-intel.conf"
1238 cat > $MNT/etc/X11/xorg.conf.d/20-intel.conf <<- EOF
1240 Identifier "Intel Graphics"
1242 Option "TearFree" "true"
1247 [[ -e /run/archiso/sfs/airootfs && $KERNEL == 'linux' ]] && cp -vf $RUN/x86_64/vmlinuz $MNT/boot/vmlinuz-linux
1248 [[ -d /etc/netctl ]] && cp -rfv /etc/netctl $MNT/etc/
1249 [[ -f /etc/resolv.conf ]] && cp -fv /etc/resolv.conf $MNT/etc/
1250 [[ -e /etc/NetworkManager/system-connections ]] && cp -rvf /etc/NetworkManager/system-connections $MNT/etc/NetworkManager/
1252 echo "LANG=$MYLOCALE" > $MNT/etc/locale.conf
1253 cp -fv $MNT/etc/locale.conf $MNT/etc/default/locale
1254 sed -i "s/#en_US.UTF-8/en_US.UTF-8/g; s/#${MYLOCALE}/${MYLOCALE}/g" $MNT/etc/locale.gen
1256 chrun "ln -svf /usr/share/zoneinfo/$ZONE/$SUBZ /etc/localtime"
1258 cat > $MNT/etc/X11/xorg.conf.d/00-keyboard.conf <<- EOF
1259 # Use localectl(1) to instruct systemd-localed to update it.
1260 Section "InputClass"
1261 Identifier "system-keyboard"
1262 MatchIsKeyboard "on"
1263 Option "XkbLayout" "$KEYMAP"
1267 cat > $MNT/etc/default/keyboard <<- EOF
1268 # KEYBOARD CONFIGURATION FILE
1269 # Consult the keyboard(5) manual page.
1276 printf "KEYMAP=%s\nFONT=%s\n" "$CMAP" "$FONT" > $MNT/etc/vconsole.conf
1277 echo "$MYHOST" > $MNT/etc/hostname
1278 cat > $MNT/etc/hosts <<- EOF
1281 ::1 localhost ip6-localhost ip6-loopback
1282 ff02::1 ip6-allnodes
1283 ff02::2 ip6-allrouters
1289 echo "Installing $BOOTLDR"
1291 if [[ $ROOT_PART == /dev/mapper* ]]; then
1292 ROOT_PART_ID="$ROOT_PART"
1294 local uuid_type="UUID"
1295 [[ $BOOTLDR =~ (systemd-boot|refind-efi|efistub) ]] && uuid_type="PARTUUID"
1296 ROOT_PART_ID="$uuid_type=$(blkid -s $uuid_type -o value $ROOT_PART)"
1299 if [[ $SYS == 'UEFI' ]]; then
1300 # remove our old install and generic BOOT/ dir
1301 find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname "$DIST" -type d -delete
1302 find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname 'BOOT' -type d -delete
1306 chrun "${BCMDS[$BOOTLDR]}" 2>$ERR
1307 errshow 1 "${BCMDS[$BOOTLDR]}"
1309 if [[ -d $MNT/hostrun ]]; then
1310 # cleanup the bind mounts we made earlier for the grub-probe module
1311 umount_dir $MNT/hostrun/{udev,lvm}
1312 rm -rf $MNT/hostrun >/dev/null 2>&1
1315 if [[ $SYS == 'UEFI' ]]; then
1316 # some UEFI firmware requires a generic esp/BOOT/BOOTX64.EFI
1317 mkdir -pv $MNT/$BOOTDIR/EFI/BOOT
1319 grub) cp -fv $MNT/$BOOTDIR/EFI/$DIST/grubx64.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI ;;
1320 syslinux) cp -rf "$MNT/$BOOTDIR/EFI/syslinux/"* $MNT/$BOOTDIR/EFI/BOOT/ && cp -f $MNT/$BOOTDIR/EFI/syslinux/syslinux.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI ;;
1321 refind-efi) sed -i '/#extra_kernel_version_strings/ c extra_kernel_version_strings linux-hardened,linux-zen,linux-lts,linux' $MNT/$BOOTDIR/EFI/refind/refind.conf
1322 cp -fv $MNT/$BOOTDIR/EFI/refind/refind_x64.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI ;;
1331 rm -f $MNT/root/.zshrc # remove welcome message from root zshrc
1333 chrun "chpasswd <<< 'root:$ROOT_PASS'" 2>$ERR
1334 errshow 1 "set root password"
1335 if [[ $MYSHELL != 'zsh' ]]; then # root uses zsh by default
1336 chrun "usermod -s /bin/$MYSHELL root" 2>$ERR
1337 errshow 1 "usermod -s /bin/$MYSHELL root"
1338 # copy the default mkshrc to /root if it was selected
1339 [[ $MYSHELL == 'mksh' ]] && cp -fv $MNT/etc/skel/.mkshrc $MNT/root/.mkshrc
1342 echo "Creating new user $NEWUSER and setting password"
1343 local groups='audio,floppy,log,network,rfkill,scanner,storage,optical,power,wheel'
1345 chrun "useradd -m -u 1000 -g users -G $groups -s /bin/$MYSHELL $NEWUSER" 2>$ERR
1346 errshow 1 "useradd -m -u 1000 -g users -G $groups -s /bin/$MYSHELL $NEWUSER"
1347 chrun "chpasswd <<< '$NEWUSER:$USER_PASS'" 2>$ERR
1348 errshow 1 "set $NEWUSER password"
1350 if [[ $INSTALL_WMS == *dwm* ]];then
1351 mkdir -pv "$MNT/home/$NEWUSER/suckless"
1352 for i in dwm dmenu st; do
1353 if chrun "git clone https://git.suckless.org/$i /home/$NEWUSER/suckless/$i"; then
1354 chrun "cd /home/$NEWUSER/suckless/$i; make prefix=/usr install; make clean"
1356 printf "failed to clone %s repo\n" "$i"
1361 [[ $WM_PKGS == *xfce* ]] && echo 'volumeicon &' >> $MNT/home/$NEWUSER/.xprofile
1363 # remove some commands from ~/.xprofile when using KDE or Gnome as the login session
1364 if [[ $LOGIN_WM =~ (startkde|gnome-session) || ($LOGIN_TYPE =~ (lightdm|ly) && $WM_PKGS =~ (plasma|gnome)) ]]; then
1365 sed -i '/super/d' $MNT/home/$NEWUSER/.xprofile $MNT/root/.xprofile
1366 sed -i '/nitrogen/d' $MNT/home/$NEWUSER/.xprofile $MNT/root/.xprofile
1367 sed -i '/compton/d' $MNT/home/$NEWUSER/.xprofile $MNT/root/.xprofile
1370 # create user home directories (Music, Documents, Downloads, etc..)
1371 chrun 'xdg-user-dirs-update'
1378 local serv="$MNT/etc/systemd/system/getty@tty1.service.d"
1379 echo "Setting up $LOGIN_TYPE"
1381 ly|sddm|gdm|lightdm)
1382 rm -rf "$serv" "$MNT/home/$NEWUSER/.xinitrc"
1383 chrun "systemctl enable $LOGIN_TYPE.service" 2>$ERR
1384 errshow 1 "systemctl enable $LOGIN_TYPE.service"
1385 if [[ $LOGIN_TYPE == 'lightdm' ]]; then
1386 cat > $MNT/etc/lightdm/lightdm-gtk-greeter.conf <<- EOF
1388 default-user-image=/usr/share/icons/ArchLabs-Dark/64x64/places/distributor-logo-archlabs.png
1389 background=/usr/share/backgrounds/archlabs/archlabs.jpg
1390 theme-name=Adwaita-dark
1391 icon-theme-name=Adwaita
1392 font-name=DejaVu Sans Mono 11
1393 position=30%,end 50%,end
1398 if [[ $INSTALL_WMS ]]; then
1399 sed -i "/exec/ c exec ${LOGIN_WM}" "$MNT/home/$NEWUSER/.xinitrc"
1400 elif [[ -e $MNT/home/$NEWUSER/.xinitrc ]]; then
1401 sed -i '/exec/d' "$MNT/home/$NEWUSER/.xinitrc"
1404 if [[ $AUTOLOGIN ]]; then
1405 sed -i "s/root/${NEWUSER}/g" $serv/autologin.conf
1406 cat > "$MNT/home/$NEWUSER/$LOGINRC" <<- EOF
1407 # automatically run startx when logging in on tty1
1408 [ -z \$DISPLAY ] && [ \$XDG_VTNR -eq 1 ] && exec startx
1419 local rmpkg="archlabs-installer "
1420 local inpkg="$BASE_PKGS ${LOGIN_PKGS[$LOGIN_TYPE]} $PACKAGES $USER_PKGS "
1422 case $MYSHELL in zsh) inpkg+="zsh-completions " ;; mksh) inpkg+="mksh " rmpkg+="zsh " ;; bash) inpkg+="bash-completion " rmpkg+="zsh " ;; esac
1424 # using a different kernel, remove the stock one
1425 [[ $KERNEL != 'linux' ]] && inpkg+="$KERNEL " rmpkg+="linux "
1427 # don't install extras on dwm only installs
1428 if [[ $INSTALL_WMS != 'dwm' ]]; then
1429 # gnome, plasma, and cinnamon have their own superkey bind and ksuperkey conflicts
1430 [[ $INSTALL_WMS =~ ^(plasma|gnome|cinnamon)$ ]] || inpkg+="archlabs-ksuperkey "
1431 # window manager only packages
1432 [[ $INSTALL_WMS =~ (openbox|bspwm|i3-gaps|fluxbox) ]] && inpkg+="$WM_BASE_PKGS "
1434 inpkg+="arandr nitrogen polkit-gnome xclip xdotool compton gnome-keyring dunst feh "
1437 # update first to avoid issues
1438 chrun "pacman -Syyu --noconfirm"
1440 # remove the packages we don't want on the installed system
1441 [[ $rmpkg ]] && chrun "pacman -Rnsc $rmpkg --noconfirm"
1443 # reinstalling iputils fixes the network issue for non-root users
1444 chrun "pacman -S iputils $UCODE --noconfirm"
1446 # install the packages chosen throughout the install
1447 chrun "pacman -S $inpkg --needed --noconfirm" 2>$ERR
1448 errshow 1 "pacman -S $inpkg --needed --noconfirm"
1450 # bootloader packages
1451 if [[ $BOOTLDR == 'grub' ]]; then
1452 [[ $SYS == 'UEFI' ]] && local efib="efibootmgr"
1453 chrun "pacman -S os-prober grub $efib --needed --noconfirm" 2>$ERR
1454 errshow 1 "pacman -S os-prober grub $efib --needed --noconfirm"
1455 elif [[ $BOOTLDR == 'refind-efi' ]]; then
1456 chrun "pacman -S refind-efi efibootmgr --needed --noconfirm" 2>$ERR
1457 errshow 1 "pacman -S refind-efi efibootmgr --needed --noconfirm"
1458 elif [[ $SYS == 'UEFI' ]]; then
1459 chrun "pacman -S efibootmgr --needed --noconfirm" 2>$ERR
1460 errshow 1 "pacman -S efibootmgr --needed --noconfirm"
1463 # allow members of the wheel group to run commands as root
1464 sed -i "s/# %wheel ALL=(ALL) ALL/%wheel ALL=(ALL) ALL/g" $MNT/etc/sudoers
1469 install_mkinitcpio()
1472 [[ $LUKS ]] && add="encrypt"
1473 [[ $LVM ]] && { [[ $add ]] && add+=" lvm2" || add+="lvm2"; }
1474 sed -i "s/block filesystems/block ${add} filesystems ${HOOKS}/g" $MNT/etc/mkinitcpio.conf
1475 chrun "mkinitcpio -p $KERNEL" 2>$ERR
1476 errshow 1 "mkinitcpio -p $KERNEL"
1479 install_mirrorlist()
1481 if hash reflector >/dev/null 2>&1; then
1482 reflector --verbose --score 80 -l 40 -f 5 --sort rate --save "$1"
1483 elif hash rankmirrors >/dev/null 2>&1; then
1484 echo "Sorting mirrorlist"
1485 local key="access_key=5f29642060ab983b31fdf4c2935d8c56"
1486 ip_add="$(curl -fsSL "http://api.ipstack.com/check&?$key&fields=ip" | python -c "import sys, json; print(json.load(sys.stdin)['ip'])")"
1487 country="$(curl -fsSL "http://api.ipstack.com/$ip_add?$key&fields=country_code" | python -c "import sys, json; print(json.load(sys.stdin)['country_code'])")"
1488 if [[ "$country" ]]; then
1489 if [[ $country =~ (CA|US) ]]; then
1490 # use both CA and US mirrors for CA or US countries
1491 mirror="https://www.archlinux.org/mirrorlist/?country=US&country=CA&use_mirror_status=on"
1492 elif [[ $country =~ (AU|NZ) ]]; then
1493 # use both AU and NZ mirrors for AU or NZ countries
1494 mirror="https://www.archlinux.org/mirrorlist/?country=AU&country=NZ&use_mirror_status=on"
1496 mirror="https://www.archlinux.org/mirrorlist/?country=${country}&use_mirror_status=on"
1498 else # no country code so just grab all mirrors, will be a very slow sort but we don't have other options
1499 mirror="https://www.archlinux.org/mirrorlist/?country=all&use_mirror_status=on"
1501 curl -fsSL "$mirror" | sed -e 's/^#Server/Server/' -e '/^#/d' | rankmirrors -n 6 - >"$1"
1507 install_background()
1509 ( rsync -a /run/archiso/sfs/airootfs/ $MNT/ && install_mirrorlist "$MNT/etc/pacman.d/mirrorlist" >/dev/null 2>&1 ) &
1511 trap "kill $BG_PID 2>/dev/null" EXIT
1514 ###############################################################################
1516 # prerun_* set up the configs needed before actually running the commands
1517 # setup_* are run after selecting a bootloader and build the command used later
1518 # they can also be used for further user input as these run before control is taken away
1522 EDIT_FILES[bootloader]="/etc/default/grub"
1524 if [[ $SYS == 'BIOS' ]]; then
1525 [[ $BOOT_DEV ]] || { part_device 1 || return 1; }
1526 BCMDS[grub]="grub-install --recheck --force --target=i386-pc $BOOT_DEV"
1528 BCMDS[grub]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1529 grub-install --recheck --force --target=x86_64-efi --efi-directory=/$BOOTDIR --bootloader-id=$DIST"
1530 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1533 BCMDS[grub]="mkdir -p /run/udev /run/lvm &&
1534 mount --bind /hostrun/udev /run/udev &&
1535 mount --bind /hostrun/lvm /run/lvm &&
1537 grub-mkconfig -o /boot/grub/grub.cfg &&
1538 sleep 1 && umount /run/udev /run/lvm"
1545 sed -i "s/GRUB_DISTRIBUTOR=.*/GRUB_DISTRIBUTOR=\"${DIST}\"/g; s/GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT=\"\"/g" $MNT/etc/default/grub
1547 if [[ $LUKS_DEV ]]; then
1548 sed -i "s~#GRUB_ENABLE_CRYPTODISK~GRUB_ENABLE_CRYPTODISK~g; s~GRUB_CMDLINE_LINUX=.*~GRUB_CMDLINE_LINUX=\"${LUKS_DEV}\"~g" $MNT/etc/default/grub 2>$ERR
1549 errshow 1 "sed -i 's~#GRUB_ENABLE_CRYPTODISK~GRUB_ENABLE_CRYPTODISK~g; s~GRUB_CMDLINE_LINUX=.*~GRUB_CMDLINE_LINUX=\"${LUKS_DEV}\"~g' $MNT/etc/default/grub"
1552 if [[ $SYS == 'BIOS' && $LVM && -z $SEP_BOOT ]]; then
1553 sed -i "s/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g" $MNT/etc/default/grub 2>$ERR
1554 errshow 1 "sed -i 's/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g' $MNT/etc/default/grub"
1557 # setup for os-prober module
1558 mkdir -p /run/{lvm,udev} $MNT/hostrun/{lvm,udev}
1559 mount --bind /run/lvm $MNT/hostrun/lvm
1560 mount --bind /run/udev $MNT/hostrun/udev
1567 EDIT_FILES[bootloader]=""
1572 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1573 efibootmgr -v -d $BOOT_DEV -p $BOOT_PART_NUM -c -L '${DIST} Linux' -l /vmlinuz-${KERNEL} \
1574 -u 'root=$ROOT_PART_ID rw $([[ $UCODE ]] && printf 'initrd=\%s.img ' "$UCODE")initrd=\initramfs-${KERNEL}.img'"
1579 if [[ $SYS == 'BIOS' ]]; then
1580 EDIT_FILES[bootloader]="/boot/syslinux/syslinux.cfg"
1582 EDIT_FILES[bootloader]="/boot/EFI/syslinux/syslinux.cfg"
1583 BCMDS[syslinux]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1584 efibootmgr -v -c -d $BOOT_DEV -p $BOOT_PART_NUM -l /EFI/syslinux/syslinux.efi -L $DIST"
1590 local c="$MNT/boot/syslinux" s="/usr/lib/syslinux/bios" d=".."
1591 [[ $SYS == 'UEFI' ]] && { c="$MNT/boot/EFI/syslinux"; s="/usr/lib/syslinux/efi64"; d=''; }
1594 cp -rfv "$s/"* "$c/"
1595 cat > "$c/syslinux.cfg" <<- EOF
1598 MENU TITLE $DIST Boot Menu
1603 MENU LABEL $DIST Linux
1604 LINUX $d/vmlinuz-$KERNEL
1605 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1606 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL.img
1608 LABEL ${DIST}fallback
1609 MENU LABEL $DIST Linux Fallback
1610 LINUX $d/vmlinuz-$KERNEL
1611 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1612 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL-fallback.img
1619 EDIT_FILES[bootloader]="/boot/refind_linux.conf"
1620 BCMDS[refind-efi]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1; refind-install"
1625 cat > $MNT/boot/refind_linux.conf <<- EOF
1626 "$DIST Linux" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] &&
1627 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1628 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL.img"
1629 "$DIST Linux Fallback" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] &&
1630 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1631 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL-fallback.img"
1633 mkdir -p $MNT/etc/pacman.d/hooks
1634 cat > $MNT/etc/pacman.d/hooks/refind.hook <<- EOF
1641 Description = Updating rEFInd on ESP
1642 When = PostTransaction
1643 Exec = /usr/bin/refind-install
1647 setup_systemd-boot()
1649 EDIT_FILES[bootloader]="/boot/loader/entries/$DIST.conf"
1650 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1; bootctl --path=/boot install"
1653 prerun_systemd-boot()
1655 mkdir -p $MNT/boot/loader/entries
1656 cat > $MNT/boot/loader/loader.conf <<- EOF
1661 cat > $MNT/boot/loader/entries/$DIST.conf <<- EOF
1663 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1664 initrd /initramfs-$KERNEL.img
1665 options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1667 cat > $MNT/boot/loader/entries/$DIST-fallback.conf <<- EOF
1668 title $DIST Linux Fallback
1669 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1670 initrd /initramfs-$KERNEL-fallback.img
1671 options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1673 mkdir -p $MNT/etc/pacman.d/hooks
1674 cat > $MNT/etc/pacman.d/hooks/systemd-boot.hook <<- EOF
1681 Description = Updating systemd-boot
1682 When = PostTransaction
1683 Exec = /usr/bin/bootctl update
1685 systemd-machine-id-setup --root="$MNT"
1689 ###############################################################################
1694 msg "Info" "\nGathering device info.\n" 0
1695 no_bg_install || return 1
1699 dlg choice menu "Logical Volume Management" "$_lvmmenu" \
1700 "$_lvmnew" "vgcreate -f, lvcreate -L -n" \
1701 "$_lvmdel" "vgremove -f" \
1702 "$_lvmdelall" "lvrmeove, vgremove, pvremove -f" \
1703 "Back" "Return to the main menu"
1705 "$_lvmnew") lvm_create && break ;;
1706 "$_lvmdel") lvm_delgroup && yesno "$_lvmdel" "$_lvmdelask" && vgremove -f "$DEL_VG" >/dev/null 2>&1 ;;
1707 "$_lvmdelall") lvm_del_all ;;
1718 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
1719 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
1720 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
1722 if [[ $VGROUP && $v && $pv ]]; then
1723 msg "LVM Setup" "\nActivating existing logical volume management.\n" 0
1724 modprobe dm-mod >/dev/null 2>$ERR
1725 errshow 'modprobe dm-mod'
1726 vgscan >/dev/null 2>&1
1727 vgchange -ay >/dev/null 2>&1
1733 VGROUP='' LVM_PARTS='' VGROUP_MB=0
1735 lvm_mkgroup || return 1
1736 local txt="\nThe last (or only) logical volume will automatically use all remaining space in the volume group."
1737 dlg VOL_COUNT menu "$_lvmnew" "\nSelect the number of logical volumes (LVs) to create in: $VGROUP\n$txt" 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -
1738 [[ $VOL_COUNT ]] || return 1
1739 lvm_extra_lvs || return 1
1740 lvm_volume_name "$_lvmlvname\nNOTE: This LV will use up all remaining space in the volume group (${VGROUP_MB}MB)" || return 1
1741 msg "$_lvmnew (LV:$VOL_COUNT)" "\nCreating volume $VNAME from remaining space in $VGROUP\n" 0
1742 lvcreate -l +100%FREE "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
1743 errshow "lvcreate -l +100%FREE $VGROUP -n $VNAME" || return 1
1744 LVM='logical volume'; sleep 0.5
1745 txt="\nDone, volume: $VGROUP-$VNAME (${VOLUME_SIZE:-${VGROUP_MB}MB}) has been created.\n"
1746 msg "$_lvmnew (LV:$VOL_COUNT)" "$txt\n$(lsblk -o NAME,MODEL,TYPE,FSTYPE,SIZE $LVM_PARTS)\n"
1752 local txt="${VGROUP}: ${SIZE}$SIZE_UNIT (${VGROUP_MB}MB remaining).$_lvmlvsize"
1756 dlg VOLUME_SIZE input "$_lvmnew (LV:$VOL_COUNT)" "$txt" ''
1757 if [[ -z $VOLUME_SIZE ]]; then
1759 break # allow bailing with escape or an empty choice
1760 elif (( ${VOLUME_SIZE:0:1} == 0 )); then
1761 ERR_SIZE=1 # size values can't begin with '0'
1763 # walk the string and make sure all but the last char are digits
1764 local lv=$((${#VOLUME_SIZE} - 1))
1765 for (( i=0; i<lv; i++ )); do
1766 [[ ${VOLUME_SIZE:$i:1} =~ [0-9] ]] || { ERR_SIZE=1; break; }
1768 if (( ERR_SIZE != 1 )); then
1769 case ${VOLUME_SIZE:$lv:1} in
1770 [mMgG]) local s=${VOLUME_SIZE:0:$lv} m=$((s * 1000))
1771 case ${VOLUME_SIZE:$lv:1} in
1772 [Gg]) (( m >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - m)) ;;
1773 [Mm]) (( ${VOLUME_SIZE:0:$lv} >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - s)) ;;
1780 if (( ERR_SIZE )); then
1781 msg "Invalid Logical Volume Size" "$_lvmerrlvsize"
1794 until [[ $named ]]; do
1795 lvm_partitions || return 1
1796 lvm_group_name || return 1
1797 yesno "$_lvmnew" "\nCreate volume group: $VGROUP\n\nusing these partition(s): $LVM_PARTS\n" && named=true
1800 msg "$_lvmnew" "\nCreating volume group: $VGROUP\n" 0
1801 vgcreate -f "$VGROUP" $LVM_PARTS >/dev/null 2>$ERR
1802 errshow "vgcreate -f $VGROUP $LVM_PARTS" || return 1
1804 SIZE=$(vgdisplay "$VGROUP" | awk '/VG Size/ { gsub(/[^0-9.]/, ""); print int($0) }')
1805 SIZE_UNIT="$(vgdisplay "$VGROUP" | awk '/VG Size/ { print substr($NF, 0, 1) }')"
1807 if [[ $SIZE_UNIT == 'G' ]]; then
1808 VGROUP_MB=$((SIZE * 1000))
1813 msg "$_lvmnew" "\nVolume group $VGROUP (${SIZE}$SIZE_UNIT) successfully created\n"
1819 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
1820 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
1821 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
1823 if [[ $VGROUP || $v || $pv ]]; then
1824 if yesno "$_lvmdelall" "$_lvmdelask"; then
1825 for i in $v; do lvremove -f "/dev/mapper/$i" >/dev/null 2>&1; done
1826 for i in $VGROUP; do vgremove -f "$i" >/dev/null 2>&1; done
1827 for i in $pv; do pvremove -f "$i" >/dev/null 2>&1; done
1831 msg "Delete LVM" "\nNo LVMs to remove...\n" 2
1841 for i in $(lvs --noheadings | awk '{print $2}' | uniq); do
1842 VOL_GROUP_LIST+="$i $(vgdisplay "$i" | awk '/VG Size/ {print $3$4}') "
1845 [[ $VOL_GROUP_LIST ]] || { msg "No Groups" "\nNo volume groups found."; return 1; }
1847 dlg DEL_VG menu "Logical Volume Management" "\nSelect volume group to delete.\n\nAll logical volumes within will also be deleted." $VOL_GROUP_LIST
1853 while (( VOL_COUNT > 1 )); do
1854 lvm_volume_name "$_lvmlvname" && lvm_lv_size || return 1
1855 msg "$_lvmnew (LV:$VOL_COUNT)" "\nCreating a $VOLUME_SIZE volume $VNAME in $VGROUP\n" 0
1856 lvcreate -L "$VOLUME_SIZE" "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
1857 errshow "lvcreate -L $VOLUME_SIZE $VGROUP -n $VNAME" || return 1
1858 msg "$_lvmnew (LV:$VOL_COUNT)" "\nDone, logical volume (LV) $VNAME ($VOLUME_SIZE) has been created.\n"
1866 part_find 'part|crypt' || return 1
1867 PARTS="$(awk 'NF > 0 {print $0 " off"}' <<< "$PARTS")"
1868 dlg LVM_PARTS check "$_lvmnew" "\nSelect the partition(s) to use for the physical volume (PV)." $PARTS
1875 until [[ $VGROUP ]]; do
1876 dlg VGROUP input "$_lvmnew" "$_lvmvgname" "lvgroup"
1877 if [[ -z $VGROUP ]]; then
1879 elif [[ ${VGROUP:0:1} == "/" || $VGROUP =~ \ |\' ]] || vgdisplay | grep -q "$VGROUP"; then
1880 msg "LVM Name Error" "$_lvmerrvgname"
1890 local txt="$1" default="mainvolume"
1891 (( VOL_COUNT > 1 )) && default="extvolume$VOL_COUNT"
1892 until [[ $VNAME ]]; do
1893 dlg VNAME input "$_lvmnew (LV:$VOL_COUNT)" "\n$txt" "$default"
1894 if [[ -z $VNAME ]]; then
1896 elif [[ ${VNAME:0:1} == "/" || $VNAME =~ \ |\' ]] || lsblk | grep -q "$VNAME"; then
1897 msg "LVM Name Error" "$_lvmerlvname"
1904 ###############################################################################
1910 no_bg_install || return 1
1911 dlg choice menu "LUKS Encryption" "$_luksmenu" \
1912 "$_luksnew" "cryptsetup -q luksFormat" \
1913 "$_luksopen" "cryptsetup open --type luks" \
1914 "$_luksadv" "cryptsetup -q -s -c luksFormat" \
1915 "Back" "Return to the main menu"
1918 "$_luksnew") luks_basic || return 1 ;;
1919 "$_luksopen") luks_open || return 1 ;;
1920 "$_luksadv") luks_advanced || return 1 ;;
1928 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
1930 part_find 'part|crypt|lvm' || return 1
1932 if (( COUNT == 1 )); then
1933 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
1935 dlg LUKS_PART menu "$_luksopen" "\nSelect which partition to open." $PARTS
1938 [[ $LUKS_PART ]] || return 1
1940 luks_pass "$_luksopen" || return 1
1941 msg "$_luksopen" "\nOpening encrypted partition: $LUKS_NAME\n\nUsing device/volume: $LUKS_PART\n" 0
1942 cryptsetup open --type luks "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
1943 errshow "cryptsetup open --type luks $LUKS_PART $LUKS_NAME" || return 1
1944 LUKS='encrypted'; luks_show
1951 local t="$1" n='' p='' p2=''
1953 until [[ $LUKS_PASS ]]; do
1956 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " $t " --mixedform "$_luksomenu" 0 0 0 \
1957 "Name:" 1 1 "${LUKS_NAME:-cryptroot}" 1 7 "$COLUMNS" 0 0 \
1958 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
1959 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
1961 while read -r line; do
1970 if [[ -z $n ]]; then
1971 msg "Name Empty" "\nEncrypted device name cannot be empty.\n\nPlease try again.\n" 2
1972 elif [[ -z $p || "$p" != "$p2" ]]; then
1974 msg "Password Mismatch" "\nThe passwords entered do not match.\n\nPlease try again.\n" 2
1976 LUKS_NAME="$n" LUKS_PASS="$p"
1986 msg "$_luksnew" "\nEncrypted partition ready for mounting.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$LUKS_PART")\n\n"
1991 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
1993 part_find 'part|lvm' || return 1
1995 if [[ $AUTO_ROOT_PART ]]; then
1996 LUKS_PART="$AUTO_ROOT_PART"
1997 elif (( COUNT == 1 )); then
1998 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2000 dlg LUKS_PART menu "$_luksnew" "\nSelect the partition you want to encrypt." $PARTS
2003 [[ $LUKS_PART ]] || return 1
2004 luks_pass "$_luksnew"
2009 luks_setup || return 1
2010 msg "$_luksnew" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2011 cryptsetup -q luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2012 errshow "cryptsetup -q luksFormat $LUKS_PART" || return 1
2013 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2014 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2015 LUKS='encrypted'; luks_show
2023 dlg cipher input "LUKS Encryption" "$_lukskey" "-s 512 -c aes-xts-plain64"
2024 [[ $cipher ]] || return 1
2025 msg "$_luksadv" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2026 cryptsetup -q $cipher luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2027 errshow "cryptsetup -q $cipher luksFormat $LUKS_PART" || return 1
2028 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2029 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2036 ###############################################################################
2038 # some help avoid repetition and improve usability of some commands
2039 # others are initial setup functions used before reaching the main loop
2043 [[ "$2" == *"$1"* ]] && printf "on" || printf "off"
2048 # cleanup and exit the installer cleanly with exit code $1
2049 local e="$1" # when e is 127 unmount /run/archiso/bootmnt and reboot
2053 if [[ -d $MNT ]]; then
2055 if (( e == 127 )); then
2056 umount_dir /run/archiso/bootmnt && sleep 0.5 && reboot -f
2064 local var="$1" # assign output from dialog to var
2065 local dlg_t="$2" # dialog type (menu, check, input)
2066 local title="$3" # dialog title
2067 local body="$4" # dialog message
2068 local n=0 # number of items to display for menu and check dialogs
2070 shift 4 # shift off args assigned above
2072 # adjust n when passed a large list
2073 local l=$((LINES - 20))
2074 (( ($# / 2) > l )) && n=$l
2078 menu) dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --menu "$body" 0 0 $n "$@" 2>"$ANS" || return 1 ;;
2079 check) dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --checklist "$body" 0 0 $n "$@" 2>"$ANS" || return 1 ;;
2082 local def="$1" # assign default value for input
2084 if [[ $1 == 'limit' ]]; then
2085 dialog --backtitle "$DIST Installer - $SYS - v$VER" --max-input 63 --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2087 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2091 # if answer file isn't empty read from it into $var
2092 [[ -s "$ANS" ]] && printf -v "$var" "%s" "$(< "$ANS")"
2097 # displays a message dialog
2098 # when more than 2 args the message will disappear after sleep time ($3)
2104 dialog --backtitle "$DIST Installer - $SYS - v$VER" --sleep "$1" --title " $title " --infobox "$body\n" 0 0
2106 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --msgbox "$body\n" 0 0
2114 if ! select_keymap; then
2117 elif ! net_connect; then
2118 msg "Not Connected" "\nRunning live requires an active internet connection.\n\nExiting..\n" 2
2122 pacman -Syyu --noconfirm || die 1
2123 pacman -S $AL_BASE_PKGS $WM_BASE_PKGS xorg-xinit xorg-server --needed --noconfirm || die 1
2127 pacman -S git --needed --noconfirm || die 1
2128 mkdir -pv /root/suckless
2129 for i in dwm dmenu st; do
2130 git clone https://git.suckless.org/$i /root/suckless/$i && cd /root/suckless/$i && make PREFIX=/usr install
2133 i3-gaps|oepnbox|fluxbox|bspwm|xfce4|gnome|plasma|cinnamon|awesome)
2134 pacman -S "$ses" ${WM_EXT[$ses]} xterm --needed --noconfirm || die 1
2136 *) echo "error: invalid session for -l, --live, see -h, --help"; die 1 ;;
2139 pacman -Scc --noconfirm
2140 rm -rf "/var/cache/pacman/pkg/"*
2141 cp -rfT /etc/skel /root || die 1
2142 sed -i "/exec/ c exec ${WM_SESSIONS[$ses]}" /root/.xinitrc
2143 printf "\n%s has been set as the login session in /root/.xinitrc, to start the session simply run\n\n\tstartx\n\n" "${WM_SESSIONS[$ses]}"
2151 usage: $1 [-hdl] [session]
2154 -h, --help print this message and exit
2155 -l, --live install and setup a live session
2156 -d, --debug enable debugging and log output to $DBG
2159 i3-gaps - A fork of i3wm with more features including gaps
2160 openbox - A lightweight, powerful, and highly configurable stacking wm
2161 dwm - A dynamic WM for X that manages windows in tiled, floating, or monocle layouts
2162 awesome - A customized Awesome WM session created by @elanapan
2163 bspwm - A tiling wm that represents windows as the leaves of a binary tree
2164 fluxbox - A lightweight and highly-configurable window manager
2165 gnome - A desktop environment that aims to be simple and easy to use
2166 cinnamon - A desktop environment combining traditional desktop with modern effects
2167 plasma - A kde software project currently comprising a full desktop environment
2168 xfce4 - A lightweight and modular desktop environment based on gtk+2/3
2176 local title="$1" body="$2" yes='Yes' no='No'
2177 (( $# >= 3 )) && yes="$3"
2178 (( $# >= 4 )) && no="$4"
2180 if (( $# == 5 )); then
2181 dialog --backtitle "$DIST Installer - $SYS - v$VER" --defaultno --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2183 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2189 arch-chroot "$MNT" bash -c "$1"
2194 export PS4='| ${BASH_SOURCE} LINE:${LINENO} FUNC:${FUNCNAME[0]:+ ${FUNCNAME[0]}()} |> '
2204 "\e]P0191919" # #191919
2205 "\e]P1D15355" # #D15355
2206 "\e]P2609960" # #609960
2207 "\e]P3FFCC66" # #FFCC66
2208 "\e]P4255A9B" # #255A9B
2209 "\e]P5AF86C8" # #AF86C8
2210 "\e]P62EC8D3" # #2EC8D3
2211 "\e]P7949494" # #949494
2212 "\e]P8191919" # #191919
2213 "\e]P9D15355" # #D15355
2214 "\e]PA609960" # #609960
2215 "\e]PBFF9157" # #FF9157
2216 "\e]PC4E88CF" # #4E88CF
2217 "\e]PDAF86C8" # #AF86C8
2218 "\e]PE2ec8d3" # #2ec8d3
2219 "\e]PFE1E1E1" # #E1E1E1
2222 [[ $TERM == 'linux' ]] && printf "%b" "${colors[@]}" && clear
2227 [ $? -eq 0 ] && return 0
2229 local fatal=0 err=""
2230 err="$(sed 's/[^[:print:]]//g; s/\[[0-9\;:]*\?m//g; s/==> //g; s/] ERROR:/]\nERROR:/g' "$ERR")"
2231 [[ -z $err ]] && err="no error message was found"
2233 (( $1 == 1 )) && { fatal=1; shift; }
2235 local txt="\nCommand: $1\n\n\n\nError: $err\n\n"
2237 if (( fatal )); then
2238 msg "Install Error" "${txt}Errors at this stage are fatal, the install cannot continue.\n"
2239 [[ -r $DBG && $TERM == 'linux' ]] && less "$DBG"
2243 msg "Install Error" "${txt}Errors at this stage are non-fatal and may be fixed or ignored depending on the error.\n"
2251 if (( $1 >= 0 )) && ! grep -qw "$MNT" /proc/mounts; then
2252 msg "Not Mounted" "\nPartition(s) must be mounted first.\n" 2
2254 elif [[ $1 -ge 1 && -z $BOOTLDR ]]; then
2255 msg "No Bootloader" "\nBootloader must be selected first.\n" 2
2257 elif [[ $1 -ge 2 && (-z $NEWUSER || -z $USER_PASS) ]]; then
2258 msg "No User" "\nA user must be created first.\n" 2
2260 elif [[ $1 -ge 3 && -z $CONFIG_DONE ]]; then
2261 msg "Not Configured" "\nSystem configuration must be done first.\n" 2
2264 (( i )) # return code
2269 mount | grep -q 'swap' && swapoff -a
2271 if [[ -d $dir ]] && mount | grep -q "on $dir "; then
2272 if ! umount "$dir" 2>/dev/null; then
2274 umount -f "$dir" 2>/dev/null || umount -l "$dir"
2282 msg "Network Connect" "\nVerifying network connection\n" 0
2283 curl -sIN --connect-timeout 5 'https://www.archlinux.org/' | sed '1q' | grep -q '200'
2288 if chk_connect; then
2290 elif hash nmtui >/dev/null 2>&1; then
2292 if [[ $TERM == 'linux' ]]; then
2293 printf "%b" "\e]P1191919" "\e]P4191919"
2295 printf "%b" "\e]P1D15355" "\e]P4255a9b"
2300 elif hash wifi-menu >dev/null 2>&1; then
2310 [[ $BG_PID ]] || return 0
2311 msg "Install Running" "\nA background install process is currently running.\n" 2
2317 IGNORE_DEV="$(lsblk -lno NAME,MOUNTPOINT | awk '/\/run\/archiso\/bootmnt/ {sub(/[1-9]/, ""); print $1}')"
2319 if [[ $IGNORE_DEV ]]; then
2320 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ && !'"/$IGNORE_DEV/"' {print "/dev/" $1 " " $2}')"
2322 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ {print "/dev/" $1 " " $2}')"
2325 if [[ -z $SYS_DEVS ]]; then
2326 msg "Device Error" "\nNo available devices...\n\nExiting..\n" 2
2331 while read -r line; do
2333 done <<< "$SYS_DEVS"
2340 # amd-ucode is not needed it's provided by linux-firmware
2341 # elif grep -q 'AuthenticAMD' /proc/cpuinfo; then
2343 elif grep -q 'GenuineIntel' /proc/cpuinfo; then
2347 modprobe -q efivarfs >/dev/null 2>&1
2349 _prep="\nOnce a step is finished a step you will be returned here, if the step was successful the cursor will be advanced to the next step.\nIf a step is unsuccessful the cursor will be placed on the step required to advance (when possible).\n\nTo begin the install you should have:\n\n - A root (/) partition mounted."
2350 if [[ -d /sys/firmware/efi/efivars ]]; then
2352 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars
2353 _prep+="\n - An EFI boot partition mounted."
2357 _prep+="\n\nOnce finished mounting, a portion of the install can be done in the background while you continue configuring the system:\n"
2358 _prep+="\n - Choose the system bootloader.\n - Create a user and password."
2359 _prep+="\n - Basic system configuration, kernel, shell, login, packages, etc..\n\nOnce you're happy with the choices and the required steps are complete, the main install can be started."
2362 ###############################################################################
2365 # enable some nicer colours in the linux console
2368 if (( UID != 0 )); then
2369 msg "Not Root" "\nThis installer must be run as root or using sudo.\n\nExiting..\n" 2
2371 elif ! grep -qwm 1 'lm' /proc/cpuinfo; then
2372 msg "Not x86_64 Architecture" "\nThis installer only supports x86_64 architectures.\n\nExiting..\n" 2
2375 case "$1" in -d|--debug) debug ;; -h|--help) usage "$0" ;; -l|--live) shift; live "$@" ;; esac
2378 # trap ^C to perform cleanup
2379 trap 'printf "\n^C\n" && die 1' INT
2384 msg "Welcome to the $DIST Installer" "$_welcome"
2386 if ! select_keymap; then
2388 elif ! net_connect; then
2389 msg "Not Connected" "\nThis installer requires an active internet connection.\n\nExiting..\n" 2
2398 # vim:fdm=marker:fmr={,}