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 base-devel xorg xorg-drivers sudo git gvfs gtk3 libmad libmatroska tumbler "
27 BASE_PKGS+="playerctl pulseaudio pulseaudio-alsa pavucontrol pamixer scrot xdg-user-dirs "
28 BASE_PKGS+="ffmpeg gstreamer gst-libav gst-plugins-base gst-plugins-good bash-completion "
30 AL_BASE_PKGS="archlabs-keyring archlabs-icons archlabs-fonts archlabs-themes "
31 AL_BASE_PKGS+="archlabs-baph archlabs-wallpapers archlabs-scripts archlabs-skel-base"
33 WM_BASE_PKGS="arandr nitrogen polkit-gnome network-manager-applet "
34 WM_BASE_PKGS+="volumeicon xclip exo laptop-detect xdotool compton wmctrl feh "
35 WM_BASE_PKGS+="gnome-keyring dunst gsimplecal xfce4-power-manager xfce4-settings"
37 SYS_MEM="$(awk '/MemTotal/ {print int($2 / 1024) "M"}' /proc/meminfo)"
38 LOCALES="$(awk '/\.UTF-8/ {gsub(/# .*|#/, ""); if ($1) {print $1 " - "}}' /etc/locale.gen)"
39 CMAPS="$(find /usr/share/kbd/keymaps -name '*.map.gz' | awk '{gsub(/\.map\.gz|.*\//, ""); print $1 " - "}' | sort)"
41 [[ $LINES ]] || LINES=$(tput lines)
42 [[ $COLUMNS ]] || COLUMNS=$(tput cols)
46 # commands used to install each bootloader, however most get modified during runtime {
48 [refind-efi]='refind-install'
49 [grub]='grub-install --recheck --force' [syslinux]='syslinux-install_update -i -a -m'
50 [efistub]='efibootmgr -v -d /dev/sda -p 1 -c -l' [systemd-boot]='bootctl --path=/boot install'
53 # executable name for each wm/de used in ~/.xinitrc {
54 declare -A WM_SESSIONS=(
55 [dwm]='dwm' [i3-gaps]='i3' [bspwm]='bspwm' [awesome]='awesome' [plasma]='startkde' [xfce4]='startxfce4'
56 [gnome]='gnome-session' [fluxbox]='startfluxbox' [openbox]='openbox-session' [cinnamon]='cinnamon-session'
59 # packages installed for each wm/de, most are depends of the skel packages {
61 [dwm]='' [gnome]='' [cinnamon]='gnome-terminal' [plasma]='kdebase-meta'
62 [awesome]='archlabs-skel-awesome' [bspwm]='archlabs-skel-bspwm' [fluxbox]='archlabs-skel-fluxbox'
63 [i3-gaps]='archlabs-skel-i3-gaps' [openbox]='archlabs-skel-openbox' [xfce4]='archlabs-skel-xfce4 xfce4-goodies'
66 # files offered for editing after install is complete {
67 declare -A EDIT_FILES=(
68 [login]='' # login is populated once we know the username and shell
69 [fstab]='/etc/fstab' [sudoers]='/etc/sudoers' [crypttab]='/etc/crypttab' [pacman]='/etc/pacman.conf'
70 [console]='/etc/vconsole.conf' [mkinitcpio]='/etc/mkinitcpio.conf' [hostname]='/etc/hostname /etc/hosts'
71 [bootloader]="/boot/loader/entries/$DIST.conf" # ** based on bootloader
72 [locale]='/etc/locale.conf /etc/default/locale' [keyboard]='/etc/X11/xorg.conf.d/00-keyboard.conf /etc/default/keyboard'
75 # mkfs command flags for filesystem formatting {
76 declare -A FS_CMD_FLAGS=(
77 [f2fs]='' [jfs]='-q' [xfs]='-f' [ntfs]='-q' [ext2]='-q' [ext3]='-q' [ext4]='-q' [vfat]='-F32' [nilfs2]='-q' [reiserfs]='-q'
80 # mount options for each filesystem {
82 [vfat]='' [ntfs]='' [ext2]='' [ext3]='' # NA
83 [jfs]='discard errors=continue errors=panic nointegrity'
84 [reiserfs]='acl nolog notail replayonly user_xattr off'
85 [ext4]='discard dealloc nofail noacl relatime noatime nobarrier nodelalloc'
86 [xfs]='discard filestreams ikeep largeio noalign nobarrier norecovery noquota wsync'
87 [nilfs2]='discard nobarrier errors=continue errors=panic order=relaxed order=strict norecovery'
88 [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'
91 # packages installed for each login option {
92 declare -A LOGIN_PKGS=(
93 [xinit]='xorg-xinit' [ly]='archlabs-ly' [gdm]='gdm' [sddm]='sddm'
94 [lightdm]='lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings accountsservice'
97 # extras installed for user selected packages {
98 # if a package requires additional packages that aren't already dependencies
99 # they can be added here eg. [package]="extra"
101 [vlc]='qt4' [mpd]='mpc' [mupdf]='mupdf-tools'
102 [rxvt-unicode]='urxvt-pearls' [zathura]='zathura-pdf-poppler' [noto-fonts]='noto-fonts-emoji' [cairo-dock]='cairo-dock-plug-ins' [qt5ct]='qt5-styleplugins'
103 [vlc]='qt5ct qt5-styleplugins' [qutebrowser]='qt5ct qt5-styleplugins' [qbittorrent]='qt5ct qt5-styleplugins' [transmission-qt]='qt5ct qt5-styleplugins'
104 [bluez]='bluez-libs bluez-utils bluez-tools bluez-plugins bluez-hid2hci' [kdenlive]='kdebase-meta dvdauthor frei0r-plugins breeze breeze-gtk qt5ct qt5-styleplugins'
107 # dialog text variables {
108 # Basics (somewhat in order)
109 _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"
110 _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"
111 _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"
112 _device="\nSelect a device to use from the list below.\n\nDevices (/dev) are the available drives on the system. /sda, /sdb, /sdc ..."
113 _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."
114 _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."
115 _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"
116 _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 or BIOS using LUKS without LVM require a separate boot partition (100-512M)."
117 _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."
118 _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."
119 _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."
120 _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"
121 _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."
122 _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."
123 _exmnt="\nWhere do you want the partition mounted?\n\nEnsure the name begins with a slash (/).\nExamples include: /usr, /home, /var, etc."
124 _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."
125 _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."
126 _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"
127 _timez="\nThe time zone is used to set the system clock.\n\nSelect your country or continent from the list below"
128 _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."
129 _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."
130 _login="\nSelect which of your session choices to use for the initial login.\n\nYou can be change this later by editing your ~/.xinitrc"
131 _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"
132 _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."
133 _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."
136 _luksnew="Basic LUKS Encryption"
137 _luksadv="Advanced LUKS Encryption"
138 _luksopen="Open Existing LUKS Partition"
139 _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."
140 _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."
141 _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)."
144 _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."
145 _lvmnew="Create Volume Group and Volume(s)"
146 _lvmdel="Delete an Existing Volume Group"
147 _lvmdelall="Delete ALL Volume Group(s) and Volume(s)"
148 _lvmvgname="\nEnter a name for the volume group (VG) being created from the partition(s) selected."
149 _lvmlvname="\nEnter a name for the logical volume (LV) being created.\n\nThis is similar to setting a label for a partition."
150 _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."
151 _lvmdelask="\nConfirm deletion of volume group(s) and logical volume(s).\n\nDeleting a volume group, will delete all logical volumes within it.\n"
154 _errexpart="\nCannot mount partition due to a problem with the mountpoint.\n\nEnsure it begins with a slash (/) followed by atleast one character.\n"
155 _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"
156 _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"
157 _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"
158 _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"
159 _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"
160 _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"
164 ###############################################################################
166 # main is the entry point which calls functions including outside of its block
167 # once those functions finished they always are returned here with the
168 # exception of install_main(), it exits upon completion
172 (( SEL < 12 )) && (( SEL++ ))
174 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Prepare " --default-item $SEL --cancel-label 'Exit' --menu "$_prep" 0 0 0 \
175 1 "Device tree (optional)" \
176 2 "Partitioning (optional)" \
177 3 "LUKS setup (optional)" \
178 4 "LVM setup (optional)" \
179 5 "Mount partitions" \
180 6 "System bootloader" \
181 7 "User and password" \
182 8 "System configuration" \
183 9 "Select WM/DE (optional)" \
184 10 "Select Packages (optional)" \
185 11 "View configuration (optional)" \
186 12 "Start the installation" 2>"$ANS"
189 [[ -z $WARN && $SEL =~ (2|5) ]] && { msg "Data Warning" "$_warn"; WARN=true; }
192 2) part_menu || (( SEL-- )) ;;
193 3) luks_menu || (( SEL-- )) ;;
194 4) lvm_menu || (( SEL-- )) ;;
195 5) mount_menu || (( SEL-- )) ;;
196 6) prechecks 0 && { select_boot || (( SEL-- )); } ;;
197 7) prechecks 1 && { select_mkuser || (( SEL-- )); } ;;
198 8) prechecks 2 && { select_config || (( SEL-- )); } ;;
199 9) prechecks 3 && { select_sessions || (( SEL-- )); } ;;
200 10) prechecks 3 && { select_packages || (( SEL-- )); } ;;
201 11) prechecks 3 && select_show ;;
202 12) prechecks 3 && install_main ;;
203 *) yesno "Exit" "\nUnmount partitions (if any) and exit the installer?\n" && die 0
209 if [[ $SYS == 'BIOS' ]]; then
210 dlg BOOTLDR menu "BIOS Bootloader" "\nSelect which bootloader to use." \
211 "grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
212 "syslinux" "A collection of boot loaders for booting drives, CDs, or over the network" || return 1
214 dlg BOOTLDR menu "UEFI Bootloader" "\nSelect which bootloader to use." \
215 "systemd-boot" "A simple UEFI boot manager which executes configured EFI images" \
216 "grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
217 "refind-efi" "A UEFI boot manager that aims to be platform neutral and simplify multi-boot" \
218 "efistub" "Boot the kernel image directly (no chainloading support)" \
219 "syslinux" "A collection of boot loaders for booting drives, CDs, or over the network (no chainloading support)" || return 1
226 local pkgs="${USER_PKGS// / } ${PACKAGES// / }"
227 [[ $BOOT_PART ]] && local mnt="/$BOOTDIR"
228 [[ $INSTALL_WMS == *dwm* ]] && pkgs="dwm st dmenu $pkgs"
229 pkgs="${pkgs// / }" pkgs="${pkgs# }"
230 msg "Show Configuration" "
231 ---------- PARTITION CONFIGURATION ------------
233 Root: ${ROOT_PART:-none}
234 Boot: ${BOOT_PART:-${BOOT_DEV:-none}}
236 Swap: ${SWAP_PART:-none}
237 Size: ${SWAP_SIZE:-none}
238 Extra: ${EXMNTS:-${EXMNT:-none}}
239 Hooks: ${HOOKS:-none}
245 ------------ SYSTEM CONFIGURATION -------------
247 Locale: ${MYLOCALE:-none}
248 Keymap: ${KEYMAP:-none}
249 Hostname: ${MYHOST:-none}
250 Timezone: ${ZONE:-none}/${SUBZ:-none}
253 ------------ USER CONFIGURATION ---------------
255 Username: ${NEWUSER:-none}
256 Login Shell: ${MYSHELL:-none}
257 Login Session: ${LOGIN_WM:-none}
258 Autologin: ${AUTOLOGIN:-none}
259 Login Type: ${LOGIN_TYPE:-none}
262 ----------- PACKAGE CONFIGURATION -------------
264 Kernel: ${KERNEL:-none}
265 Bootloader: ${BOOTLDR:-none}
266 Packages: ${pkgs:-none}
272 [[ $INSTALL_WMS ]] || return 0
274 AUTOLOGIN='' # no autologin unless using xinit
276 dlg LOGIN_TYPE menu "Login Management" "\nSelect what kind of login management to use." \
277 "xinit" "Console login without a display manager" \
278 "ly" "TUI display manager with a ncurses-like interface" \
279 "lightdm" "Lightweight display manager with a gtk greeter" \
280 "gdm" "Gnome display manager" \
281 "sddm" "Simple desktop display manager" || return 1
284 ly) EDIT_FILES[login]="/etc/ly/config.ini" ;;
285 gdm|sddm) EDIT_FILES[login]="" ;;
286 lightdm) EDIT_FILES[login]="/etc/lightdm/lightdm.conf /etc/lightdm/lightdm-gtk-greeter.conf" ;;
287 xinit) EDIT_FILES[login]="/home/$NEWUSER/.xinitrc /home/$NEWUSER/.xprofile"
288 if (( $(wc -w <<< "$INSTALL_WMS") > 1 )); then
289 dlg LOGIN_WM menu "Login Management" "$_login" $LOGIN_CHOICES || return 1
290 LOGIN_WM="${WM_SESSIONS[$LOGIN_WM]}"
292 [[ -z $LOGIN_WM ]] && LOGIN_WM="${WM_SESSIONS[${INSTALL_WMS%% *}]}"
293 yesno "Autologin" "$(sed "s|USER|$NEWUSER|g; s|RC|$LOGINRC|g" <<< "$_autologin")" && AUTOLOGIN=true || AUTOLOGIN=''
303 until [[ $CONFIG_DONE ]]; do
305 0) dlg MYSHELL menu "Shell" "\nChoose which shell to use." \
306 zsh 'A very advanced and programmable command interpreter (shell) for UNIX' \
307 bash 'The GNU Bourne Again shell, standard in many GNU/Linux distributions' \
308 mksh 'The MirBSD Korn Shell - an enhanced version of the public domain ksh' || return 1
310 1) dlg MYHOST input "Hostname" "$_hostname" "${DIST,,}" limit || { i=0; continue; } ;;
311 2) dlg MYLOCALE menu "Locale" "$_locale" $LOCALES || { i=1; continue; } ;;
313 until [[ $ZONE && $SUBZ ]]; do
314 dlg ZONE menu "Timezone" "$_timez" America - Australia - Asia - Atlantic - Africa - Europe - Indian - Pacific - Arctic - Antarctica - || break
315 dlg SUBZ menu "Timezone" "$_timesubz" $(awk '/'"$ZONE"'\// {gsub(/'"$ZONE"'\//, ""); print $3 " - "}' /usr/share/zoneinfo/zone.tab | sort) || continue
317 [[ $ZONE && $SUBZ ]] || { i=2; continue; } ;;
318 4) dlg KERNEL menu "Kernel" "\nChoose which kernel to use." \
319 linux 'Vanilla linux kernel and modules, with a few patches applied' \
320 linux-lts 'Long-term support (LTS) linux kernel and modules' \
321 linux-zen 'A effort of kernel hackers to provide the best kernel for everyday systems' \
322 linux-hardened 'A security-focused linux kernel with hardening patches to mitigate exploits' || { i=3; continue; }
326 (( i++ )) # progress through to the next choice
330 bash) LOGINRC='.bash_profile' ;;
331 zsh) LOGINRC='.zprofile' ;;
332 mksh) LOGINRC='.profile' ;;
343 until [[ $NEWUSER ]]; do
345 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " User " --mixedform "$_user" 0 0 0 \
346 "Username:" 1 1 "${ans[0]}" 1 11 "$COLUMNS" 0 0 \
347 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
348 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 \
349 "--- Root password, if left empty the user password will be used ---" 6 1 '' 6 68 "$COLUMNS" 0 2 \
350 "Password:" 8 1 '' 8 11 "$COLUMNS" 0 1 \
351 "Password2:" 9 1 '' 9 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
353 mapfile -t ans <"$ANS"
355 # root passwords empty, so use the user passwords
356 if [[ -z "${ans[4]}" && -z "${ans[5]}" ]]; then
361 # make sure a username was entered and that the passwords match
362 if [[ -z ${ans[0]} || ${ans[0]} =~ \ |\' || ${ans[0]} =~ [^a-z0-9] ]]; then
363 msg "Invalid Username" "\nInvalid user name.\n\nPlease try again.\n"; u=''
364 elif [[ -z "${ans[1]}" || "${ans[1]}" != "${ans[2]}" ]]; then
365 msg "Password Mismatch" "\nThe user passwords do not match.\n\nPlease try again.\n"
366 elif [[ "${ans[4]}" != "${ans[5]}" ]]; then
367 msg "Password Mismatch" "\nThe root passwords do not match.\n\nPlease try again.\n"
370 USER_PASS="${ans[1]}"
371 ROOT_PASS="${ans[4]}"
379 dlg KEYMAP menu "Keyboard Layout" "$_keymap" \
380 us English cm English gb English au English gh English \
381 za English ng English ca French 'cd' French gn French \
382 tg French fr French de German at German ch German \
383 es Spanish latam Spanish br Portuguese pt Portuguese ma Arabic \
384 sy Arabic ara Arabic ua Ukrainian cz Czech ru Russian \
385 sk Slovak nl Dutch it Italian hu Hungarian cn Chinese \
386 tw Taiwanese vn Vietnamese kr Korean jp Japanese th Thai \
387 la Lao pl Polish se Swedish is Icelandic 'fi' Finnish \
388 dk Danish be Belgian in Indian al Albanian am Armenian \
389 bd Bangla ba Bosnian 'bg' Bulgarian dz Berber mm Burmese \
390 hr Croatian gr Greek il Hebrew ir Persian iq Iraqi \
391 af Afghani fo Faroese ge Georgian ee Estonian kg Kyrgyz \
392 kz Kazakh lt Lithuanian mt Maltese mn Mongolian ro Romanian \
393 no Norwegian rs Serbian si Slovenian tj Tajik lk Sinhala \
394 tr Turkish uz Uzbek ie Irish pk Urdu 'mv' Dhivehi \
395 np Nepali et Amharic sn Wolof ml Bambara tz Swahili \
396 ke Swahili bw Tswana ph Filipino my Malay tm Turkmen \
397 id Indonesian bt Dzongkha lv Latvian md Moldavian mao Maori \
398 by Belarusian az Azerbaijani mk Macedonian kh Khmer epo Esperanto \
399 me Montenegrin || return 1
401 if [[ $CMAPS == *"$KEYMAP"* ]]; then
404 dlg CMAP menu "Console Keymap" "$_vconsole" $CMAPS || return 1
407 if [[ $TERM == 'linux' ]]; then
408 loadkeys "$CMAP" >/dev/null 2>&1
410 setxkbmap "$KEYMAP" >/dev/null 2>&1
419 dlg INSTALL_WMS check "Sessions" "$_sessions\n" \
420 openbox "A lightweight, powerful, and highly configurable stacking wm" "$(ofn openbox "${INSTALL_WMS[*]}")" \
421 i3-gaps "A fork of i3wm with more features including gaps" "$(ofn i3-gaps "${INSTALL_WMS[*]}")" \
422 dwm "A dynamic WM for X that manages windows in tiled, floating, or monocle layouts" "$(ofn dwm "${INSTALL_WMS[*]}")" \
423 bspwm "A tiling wm that represents windows as the leaves of a binary tree" "$(ofn bspwm "${INSTALL_WMS[*]}")" \
424 xfce4 "A lightweight and modular desktop environment based on gtk+2/3" "$(ofn xfce4 "${INSTALL_WMS[*]}")" \
425 awesome "A customized Awesome WM session created by @elanapan" "$(ofn awesome "${INSTALL_WMS[*]}")" \
426 fluxbox "A lightweight and highly-configurable window manager" "$(ofn fluxbox "${INSTALL_WMS[*]}")" \
427 plasma "A kde software project currently comprising a full desktop environment" "$(ofn plasma "${INSTALL_WMS[*]}")" \
428 gnome "A desktop environment that aims to be simple and easy to use" "$(ofn gnome "${INSTALL_WMS[*]}")" \
429 cinnamon "A desktop environment combining traditional desktop with modern effects" "$(ofn cinnamon "${INSTALL_WMS[*]}")"
431 [[ $INSTALL_WMS ]] || return 0
433 WM_PKGS="${INSTALL_WMS/dwm/}" # remove dwm from package list
434 WM_PKGS="${WM_PKGS// / }" # remove double spaces
435 WM_PKGS="${WM_PKGS# }" # remove leading space
437 for i in $INSTALL_WMS; do
438 LOGIN_CHOICES+="$i - "
439 [[ ${WM_EXT[$i]} && $WM_PKGS != *"${WM_EXT[$i]}"* ]] && WM_PKGS+=" ${WM_EXT[$i]}"
442 select_login || return 1
444 while IFS=' ' read -r pkg; do
445 [[ $PACKAGES != *"$pkg"* ]] && PACKAGES+=" $pkg"
453 dlg USER_PKGS check " Packages " "$_packages" \
454 abiword "A Fully-featured word processor" "$(ofn abiword "${USER_PKGS[*]}")" \
455 alacritty "A cross-platform, GPU-accelerated terminal emulator" "$(ofn alacritty "${USER_PKGS[*]}")" \
456 atom "An open-source text editor developed by GitHub" "$(ofn atom "${USER_PKGS[*]}")" \
457 audacious "A free and advanced audio player based on GTK+" "$(ofn audacious "${USER_PKGS[*]}")" \
458 audacity "A program that lets you manipulate digital audio waveforms" "$(ofn audacity "${USER_PKGS[*]}")" \
459 blueman "GUI bluetooth device manager" "$(ofn blueman "${USER_PKGS[*]}")" \
460 bluez "Simple CLI based bluetooth support" "$(ofn bluez "${USER_PKGS[*]}")" \
461 cairo-dock "Light eye-candy fully themable animated dock" "$(ofn cairo-dock "${USER_PKGS[*]}")" \
462 calligra "A set of applications for productivity" "$(ofn calligra "${USER_PKGS[*]}")" \
463 chromium "An open-source web browser based on the Blink rendering engine" "$(ofn chromium "${USER_PKGS[*]}")" \
464 clementine "A modern music player and library organizer" "$(ofn clementine "${USER_PKGS[*]}")" \
465 cmus "A small, fast and powerful console music player" "$(ofn cmus "${USER_PKGS[*]}")" \
466 deadbeef "A GTK+ audio player for GNU/Linux" "$(ofn deadbeef "${USER_PKGS[*]}")" \
467 deluge "A BitTorrent client written in python" "$(ofn deluge "${USER_PKGS[*]}")" \
468 emacs "An extensible, customizable, self-documenting real-time display editor" "$(ofn emacs "${USER_PKGS[*]}")" \
469 epiphany "A GNOME web browser based on the WebKit rendering engine" "$(ofn epiphany "${USER_PKGS[*]}")" \
470 evince "A document viewer" "$(ofn evince "${USER_PKGS[*]}")" \
471 evolution "Manage your email, contacts and schedule" "$(ofn evolution "${USER_PKGS[*]}")" \
472 file-roller "Create and modify archives" "$(ofn file-roller "${USER_PKGS[*]}")" \
473 firefox "A popular open-source web browser from Mozilla" "$(ofn firefox "${USER_PKGS[*]}")" \
474 gcolor2 "A simple GTK+2 color selector" "$(ofn gcolor2 "${USER_PKGS[*]}")" \
475 geany "A fast and lightweight IDE" "$(ofn geany "${USER_PKGS[*]}")" \
476 geary "A lightweight email client for the GNOME desktop" "$(ofn geary "${USER_PKGS[*]}")" \
477 gimp "GNU Image Manipulation Program" "$(ofn gimp "${USER_PKGS[*]}")" \
478 gnome-calculator "GNOME Scientific calculator" "$(ofn gnome-calculator "${USER_PKGS[*]}")" \
479 gnome-disk-utility "Disk Management Utility" "$(ofn gnome-disk-utility "${USER_PKGS[*]}")" \
480 gnome-system-monitor "View current processes and monitor system state" "$(ofn gnome-system-monitor "${USER_PKGS[*]}")" \
481 gparted "A GUI frontend for creating and manipulating partition tables" "$(ofn gparted "${USER_PKGS[*]}")" \
482 gpick "Advanced color picker using GTK+ toolkit" "$(ofn gpick "${USER_PKGS[*]}")" \
483 gpicview "Lightweight image viewer" "$(ofn gpicview "${USER_PKGS[*]}")" \
484 guvcview "Capture video from camera devices" "$(ofn guvcview "${USER_PKGS[*]}")" \
485 hexchat "A popular and easy to use graphical IRC client" "$(ofn hexchat "${USER_PKGS[*]}")" \
486 inkscape "Professional vector graphics editor" "$(ofn inkscape "${USER_PKGS[*]}")" \
487 irssi "Modular text mode IRC client" "$(ofn irssi "${USER_PKGS[*]}")" \
488 kdenlive "A popular non-linear video editor for Linux" "$(ofn kdenlive "${USER_PKGS[*]}")" \
489 krita "Edit and paint images" "$(ofn krita "${USER_PKGS[*]}")" \
490 libreoffice-fresh "Full featured office suite" "$(ofn libreoffice-fresh "${USER_PKGS[*]}")" \
491 lollypop "A new music playing application" "$(ofn lollypop "${USER_PKGS[*]}")" \
492 mousepad "A simple text editor" "$(ofn mousepad "${USER_PKGS[*]}")" \
493 mpd "A flexible, powerful, server-side application for playing music" "$(ofn mpd "${USER_PKGS[*]}")" \
494 mpv "A media player based on mplayer" "$(ofn mpv "${USER_PKGS[*]}")" \
495 mupdf "Lightweight PDF and XPS viewer" "$(ofn mupdf "${USER_PKGS[*]}")" \
496 mutt "Small but very powerful text-based mail client" "$(ofn mutt "${USER_PKGS[*]}")" \
497 nautilus "The default file manager for Gnome" "$(ofn nautilus "${USER_PKGS[*]}")" \
498 ncmpcpp "A mpd client and almost exact clone of ncmpc with some new features" "$(ofn ncmpcpp "${USER_PKGS[*]}")" \
499 neovim "A fork of Vim aiming to improve user experience, plugins, and GUIs." "$(ofn neovim "${USER_PKGS[*]}")" \
500 noto-fonts "Google Noto fonts" "$(ofn noto-fonts "${USER_PKGS[*]}")" \
501 noto-fonts-cjk "Google Noto CJK fonts (Chinese, Japanese, Korean)" "$(ofn noto-fonts-cjk "${USER_PKGS[*]}")" \
502 obs-studio "Free opensource streaming/recording software" "$(ofn obs-studio "${USER_PKGS[*]}")" \
503 openshot "An open-source, non-linear video editor for Linux" "$(ofn openshot "${USER_PKGS[*]}")" \
504 opera "A Fast and secure, free of charge web browser from Opera Software" "$(ofn opera "${USER_PKGS[*]}")" \
505 pcmanfm "A fast and lightweight file manager based in Lxde" "$(ofn pcmanfm "${USER_PKGS[*]}")" \
506 pidgin "Multi-protocol instant messaging client" "$(ofn pidgin "${USER_PKGS[*]}")" \
507 plank "An elegant, simple, and clean dock" "$(ofn plank "${USER_PKGS[*]}")" \
508 qbittorrent "An advanced BitTorrent client" "$(ofn qbittorrent "${USER_PKGS[*]}")" \
509 qpdfview "A tabbed PDF viewer" "$(ofn qpdfview "${USER_PKGS[*]}")" \
510 qt5ct "GUI for managing Qt based application themes, icons, and fonts" "$(ofn qt5ct "${USER_PKGS[*]}")" \
511 qutebrowser "A keyboard-focused vim-like web browser based on Python and PyQt5" "$(ofn qutebrowser "${USER_PKGS[*]}")" \
512 rhythmbox "A Music playback and management application" "$(ofn rhythmbox "${USER_PKGS[*]}")" \
513 rxvt-unicode "A unicode enabled rxvt-clone terminal emulator" "$(ofn rxvt-unicode "${USER_PKGS[*]}")" \
514 sakura "A terminal emulator based on GTK and VTE" "$(ofn sakura "${USER_PKGS[*]}")" \
515 simple-scan "Simple scanning utility" "$(ofn simple-scan "${USER_PKGS[*]}")" \
516 simplescreenrecorder "A feature-rich screen recorder" "$(ofn simplescreenrecorder "${USER_PKGS[*]}")" \
517 steam "A popular game distribution platform by Valve" "$(ofn steam "${USER_PKGS[*]}")" \
518 surf "A simple web browser based on WebKit2/GTK+" "$(ofn surf "${USER_PKGS[*]}")" \
519 terminator "Terminal emulator that supports tabs and grids" "$(ofn terminator "${USER_PKGS[*]}")" \
520 termite "A minimal VTE-based terminal emulator" "$(ofn termite "${USER_PKGS[*]}")" \
521 thunar "A modern file manager for the Xfce Desktop Environment" "$(ofn thunar "${USER_PKGS[*]}")" \
522 thunderbird "Standalone mail and news reader from mozilla" "$(ofn thunderbird "${USER_PKGS[*]}")" \
523 tilda "A GTK based drop down terminal for Linux and Unix" "$(ofn tilda "${USER_PKGS[*]}")" \
524 tilix "A tiling terminal emulator for Linux using GTK+ 3" "$(ofn tilix "${USER_PKGS[*]}")" \
525 transmission-cli "Free BitTorrent client CLI" "$(ofn transmission-cli "${USER_PKGS[*]}")" \
526 transmission-gtk "GTK+ Front end for transmission" "$(ofn transmission-gtk "${USER_PKGS[*]}")" \
527 transmission-qt "Qt Front end for transmission" "$(ofn transmission-qt "${USER_PKGS[*]}")" \
528 ttf-anonymous-pro "A family fixed-width fonts designed with code in mind" "$(ofn ttf-anonymous-pro "${USER_PKGS[*]}")" \
529 ttf-fira-code "Monospaced font with programming ligatures" "$(ofn ttf-fira-code "${USER_PKGS[*]}")" \
530 ttf-font-awesome "Iconic font designed for Bootstrap" "$(ofn ttf-font-awesome "${USER_PKGS[*]}")" \
531 ttf-hack "A hand groomed typeface based on Bitstream Vera Mono" "$(ofn ttf-hack "${USER_PKGS[*]}")" \
532 vlc "A free and open source cross-platform multimedia player" "$(ofn vlc "${USER_PKGS[*]}")" \
533 weechat "Fast, light and extensible IRC client" "$(ofn weechat "${USER_PKGS[*]}")" \
534 xapps "Common library for X-Apps project" "$(ofn xapps "${USER_PKGS[*]}")" \
535 xarchiver "A GTK+ frontend to various command line archivers" "$(ofn xarchiver "${USER_PKGS[*]}")" \
536 xed "A small and lightweight text editor. X-Apps Project." "$(ofn xed "${USER_PKGS[*]}")" \
537 xfce4-terminal "A terminal emulator based in the Xfce Desktop Environment" "$(ofn xfce4-terminal "${USER_PKGS[*]}")" \
538 xreader "Document viewer for files like PDF and Postscript. X-Apps Project." "$(ofn xed "${USER_PKGS[*]}")" \
539 xterm "The standard terminal emulator for the X window system" "$(ofn xterm "${USER_PKGS[*]}")" \
540 zathura "Minimalistic document viewer" "$(ofn zathura "${USER_PKGS[*]}")"
542 if [[ $USER_PKGS ]]; then # add any needed PKG_EXT to the list
543 for i in $USER_PKGS; do
544 [[ ${PKG_EXT[$i]} && $USER_PKGS != *"${PKG_EXT[$i]}"* ]] && USER_PKGS+=" ${PKG_EXT[$i]}"
551 ###############################################################################
553 # non-essential partitioning helpers called by the user when using the optional
554 # partition menu and selecting a device to edit
558 no_bg_install || return 0
559 local device choice devhash
560 devhash="$(lsblk -f | base64)"
562 part_device || return 1
567 dlg choice menu "Edit Partitions" "$_part\n\n$(lsblk -no NAME,MODEL,SIZE,TYPE,FSTYPE $device)" \
568 "auto" "Whole device automatic partitioning" \
569 "shrink" "Shrink an existing ext or ntfs partition" \
570 "cfdisk" "Curses based variant of fdisk" \
571 "parted" "GNU partition editor" \
572 "fdisk" "Dialog-driven creation and manipulation of partitions" \
573 "done" "Return to the main menu"
575 if [[ -z $choice || $choice == 'done' ]]; then
577 elif [[ $choice == 'shrink' ]]; then
578 part_shrink "$device"
579 elif [[ $choice == 'auto' ]]; then
580 local root_size txt table boot_fs
581 root_size=$(lsblk -lno SIZE "$device" | awk 'NR == 1 {
584 print ($1 * 1000 - 512) / 1000 "G"
590 txt="\nWARNING:\n\nALL data on $device will be destroyed and the following partitions will be created\n\n- "
591 if [[ $SYS == 'BIOS' ]]; then
592 table="msdos" boot_fs="ext4"
593 txt+="An $boot_fs boot partition with the boot flag enabled (512M)\n- "
595 table="gpt" boot_fs="fat32"
596 txt+="A $boot_fs efi boot partition (512M)\n- "
598 txt+="An ext4 partition using all remaining space ($root_size)\n\nDo you want to continue?\n"
599 yesno "Auto Partition" "$txt" && part_auto "$device" "$table" "$boot_fs" "$root_size"
605 if [[ $devhash != "$(lsblk -f | base64)" ]]; then
606 msg "Probing Partitions" "\nInforming kernel of partition changes using partprobe\n" 0
607 partprobe >/dev/null 2>&1
608 [[ $choice == 'auto' ]] && return
616 if [[ $IGNORE_DEV ]]; then
617 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk "!/$IGNORE_DEV/"' && /disk|part|lvm|crypt|NAME/')"
619 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk '/disk|part|lvm|crypt|NAME/')"
621 msg "Device Tree" "\n\n$txt\n\n"
626 local device="$1" table="$2" boot_fs="$3" size="$4" dev_info=""
627 dev_info="$(parted -s "$device" print)"
629 msg "Auto Partition" "\nRemoving partitions on $device and setting table to $table\n" 1
632 while read -r PART; do
633 parted -s "$device" rm "$PART" >/dev/null 2>&1
634 done <<< "$(awk '/^ [1-9][0-9]?/ {print $1}' <<< "$dev_info" | sort -r)"
636 [[ $(awk '/Table:/ {print $3}' <<< "$dev_info") != "$table" ]] && parted -s "$device" mklabel "$table" >/dev/null 2>&1
638 msg "Auto Partition" "\nCreating a 512M $boot_fs boot partition.\n" 1
639 if [[ $SYS == "BIOS" ]]; then
640 parted -s "$device" mkpart primary "$boot_fs" 1MiB 513MiB >/dev/null 2>&1
642 parted -s "$device" mkpart ESP "$boot_fs" 1MiB 513MiB >/dev/null 2>&1
647 AUTO_BOOT_PART=$(lsblk -lno NAME,TYPE "$device" | awk 'NR==2 {print "/dev/" $1}')
649 if [[ $SYS == "BIOS" ]]; then
650 mkfs.ext4 -q "$AUTO_BOOT_PART" >/dev/null 2>&1
652 mkfs.vfat -F32 "$AUTO_BOOT_PART" >/dev/null 2>&1
655 msg "Auto Partition" "\nCreating a $size ext4 root partition.\n" 0
656 parted -s "$device" mkpart primary ext4 513MiB 100% >/dev/null 2>&1
658 AUTO_ROOT_PART="$(lsblk -lno NAME,TYPE "$device" | awk 'NR==3 {print "/dev/" $1}')"
659 mkfs.ext4 -q "$AUTO_ROOT_PART" >/dev/null 2>&1
661 msg "Auto Partition" "\nProcess complete.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$device")\n"
668 local device="$1" fs=""
670 part_find "${device##*/}[^ ]" || return 1
671 (( COUNT == 1 )) && part="$(awk '{print $1}' <<< "${PARTS[@]}" )"
673 if (( COUNT == 1 )) || dlg part menu "Resize" "\nWhich partition on $device do you want to resize?" $PARTS; then
674 fs=$(lsblk -lno FSTYPE "$part")
677 msg "Resize" "\nGathering device size info.\n" 0
679 end=$(parted -s "$device" unit KiB print | awk '/^\s*'"$num"'/ {print $3}') # part size in KiB
680 devsize=$(parted -s "$device" unit KiB print | awk '/Disk '"${device//\//\\/}"':/ {print $3}') # whole device size in KiB
681 mount "$part" $MNT >/dev/null 2>&1; sleep 0.5
682 min=$(df --output=used --block-size=MiB "$part" | awk 'NR == 2 {print int($1) + 256}')
683 max=$(df --output=avail --block-size=MiB "$part" | awk 'NR == 2 {print int($1)}')
686 if dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Resize: $part " --rangebox "$_resize" 17 "$COLUMNS" "$min" "$max" $((max / 2)) 2>$ANS; then
688 size=$((size * 1024))
695 if ntfsresize -fc "$part"; then
696 ntfsresize -ff --size $(( (size * 1024) / 1000 ))k "$part" 2>$ERR # k=10^3 bytes
697 errshow "ntfsresize -f -s $(( (size * 1024) / 1000 ))k $part" || return 1
699 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"
704 e2fsck -f "$part"; sleep 0.5
705 resize2fs -f "$part" ${size}K 2>$ERR # K=2^10 bytes
706 errshow "resize2fs -f $part ${size}K" || return 1
710 parted "$device" resizepart "$num" ${size}KiB || return 1
713 if [[ $devsize == "$end" ]]; then
714 parted -s "$device" mkpart primary ext4 ${size}KiB 100% 2>$ERR
715 errshow "parted -s $device mkpart primary ext4 ${size}KiB 100%" || return 1
717 parted -s "$device" mkpart primary ext4 ${size}KiB ${end}KiB 2>$ERR
718 errshow "parted -s $device mkpart primary ext4 ${size}KiB ${end}KiB" || return 1
720 msg "Resize Complete" "\n$part has been successfully resized to $((size / 1024))M.\n" 1
722 "") msg "No Filesystem" "\nFor unformatted partitions, cfdisk can be used in the partition menu.\n" ;;
723 *) msg "Invalid Filesystem: $fs" "\nResizing only supports ext and ntfs.\n" ;;
728 ###############################################################################
729 # partition management functions
730 # these are helpers for use by other functions to do essential setup/teardown
734 local regexp="$1" err=''
736 # string of partitions as /TYPE/PART SIZE
737 if [[ $IGNORE_DEV ]]; then
738 PARTS="$(lsblk -lno TYPE,NAME,SIZE |
739 awk "/$regexp/"' && !'"/$IGNORE_DEV/"' {
740 sub(/^part/, "/dev/")
741 sub(/^lvm|^crypt/, "/dev/mapper/")
745 PARTS="$(lsblk -lno TYPE,NAME,SIZE |
747 sub(/^part/, "/dev/")
748 sub(/^lvm|^crypt/, "/dev/mapper/")
753 # number of partitions total
755 while read -r line; do
759 # ensure we have enough partitions for the system and action type
761 'part|lvm|crypt') [[ $COUNT -lt 1 || ($SYS == 'UEFI' && $COUNT -lt 2) ]] && err="$_errpart" ;;
762 'part|crypt') (( COUNT < 1 )) && err="$_lvmerr" ;;
763 'part|lvm') (( COUNT < 2 )) && err="$_lukserr" ;;
766 # if there aren't enough partitions show the relevant error message
767 [[ $err ]] && { msg "Not Enough Partitions" "$err" 2; return 1; }
774 if [[ $1 == "$MNT/swapfile" && $SWAP_SIZE ]]; then
775 fallocate -l $SWAP_SIZE "$1" 2>$ERR
776 errshow "fallocate -l $SWAP_SIZE $1"
777 chmod 600 "$1" 2>$ERR
778 errshow "chmod 600 $1"
780 mkswap "$1" >/dev/null 2>$ERR
782 swapon "$1" >/dev/null 2>$ERR
789 local part="$1" mountp="${MNT}$2" fs=""
790 fs="$(lsblk -lno FSTYPE "$part")"
793 if [[ $fs && ${FS_OPTS[$fs]} && $part != "$BOOT_PART" && $part != "$AUTO_ROOT_PART" ]] && select_mntopts "$fs"; then
794 mount -o "$MNT_OPTS" "$part" "$mountp" >/dev/null 2>&1
796 mount "$part" "$mountp" >/dev/null 2>&1
799 part_mountconf "$part" "$mountp" || return 1
807 local part="$1" fs="$2" delay="$3"
809 msg "Format" "\nFormatting $part as $fs\n" 0
810 mkfs.$fs ${FS_CMD_FLAGS[$fs]} "$part" >/dev/null 2>$ERR
811 errshow "mkfs.$fs ${FS_CMD_FLAGS[$fs]} "$part"" || return 1
818 if [[ $DEV_COUNT -eq 1 && $SYS_DEVS ]]; then
819 DEVICE="$(awk '{print $1}' <<< "$SYS_DEVS")"
820 elif (( DEV_COUNT > 1 )); then
822 dlg DEVICE menu "Boot Device" "\nSelect the device to use for bootloader install." $SYS_DEVS
824 dlg DEVICE menu "Select Device" "$_device" $SYS_DEVS
826 [[ $DEVICE ]] || return 1
827 elif [[ $DEV_COUNT -lt 1 && ! $1 ]]; then
828 msg "Device Error" "\nNo available devices.\n\nExiting..\n" 2
832 [[ $1 ]] && BOOT_DEV="$DEVICE"
839 BOOT_DEV="${BOOT_PART%[1-9]}"
840 BOOT_PART_NUM="${BOOT_PART: -1}"
841 [[ $BOOT_PART = /dev/nvme* ]] && BOOT_DEV="${BOOT_PART%p[1-9]}"
842 if [[ $SYS == 'UEFI' ]]; then
843 parted -s $BOOT_DEV set $BOOT_PART_NUM esp on >/dev/null 2>&1
845 parted -s $BOOT_DEV set $BOOT_PART_NUM boot on >/dev/null 2>&1
852 local part="$1" devs=""
853 devs="$(lsblk -lno NAME,FSTYPE,TYPE)"
855 # Identify if $part is LUKS+LVM, LVM+LUKS, LVM alone, or LUKS alone
856 if lsblk -lno TYPE "$part" | grep -q 'crypt'; then
858 LUKS_NAME="${part#/dev/mapper/}"
859 for dev in $(awk '/lvm/ && /crypto_LUKS/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
860 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
861 LUKS_DEV="$LUKS_DEV cryptdevice=$dev:$LUKS_NAME"
866 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
867 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
868 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
869 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
873 elif lsblk -lno TYPE "$part" | grep -q 'lvm'; then
875 VNAME="${part#/dev/mapper/}"
876 for dev in $(awk '/crypt/ && /lvm2_member/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
877 if lsblk -lno NAME "$dev" | grep -q "$VNAME"; then
878 LUKS_NAME="${dev/\/dev\/mapper\//}"
882 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
883 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
884 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
885 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
896 if (( COUNT > 0 )); then
897 PARTS="$(sed "/${pt//\//\\/}/d" <<< "$PARTS")"
905 if grep -qw "$1" /proc/mounts; then
906 msg "Mount Success" "\nPartition $1 mounted at $2\n" 1
910 msg "Mount Fail" "\nPartition $1 failed to mount at $2\n" 2
915 ###############################################################################
917 # mount_menu is the entry point which calls all other functions
918 # once finished it returns to the main menu: main()
922 msg "Info" "\nGathering device info.\n" 0
923 no_bg_install || return 0
926 part_find 'part|lvm|crypt' || { SEL=2; return 1; }
928 [[ $LUKS && $LUKS_PART ]] && part_countdec $LUKS_PART
929 [[ $LVM && $LVM_PARTS ]] && part_countdec $LVM_PARTS
931 select_root_partition || return 1
933 if [[ $SYS == 'UEFI' ]]; then
934 select_efi_partition || { BOOT_PART=''; return 1; }
935 elif (( COUNT > 0 )); then
936 select_boot_partition || { BOOT_PART=''; return 1; }
939 if [[ $BOOT_PART ]]; then
940 part_mount "$BOOT_PART" "/$BOOTDIR" && SEP_BOOT=true || return 1
944 select_swap || return 1
945 select_extra_partitions || return 1
953 dlg SWAP_PART menu "Swap Setup" "\nSelect whether to use a swapfile, swap partition, or none." \
954 "none" "Don't allocate any swap space" \
955 "swapfile" "Allocate $SYS_MEM at /swapfile" \
958 if [[ -z $SWAP_PART || $SWAP_PART == "none" ]]; then
961 elif [[ $SWAP_PART == "swapfile" ]]; then
963 until [[ ${SWAP_SIZE:0:1} =~ [1-9] && ${SWAP_SIZE: -1} =~ (M|G) ]]; do
964 (( 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
965 dlg SWAP_SIZE input "Swap Setup" "$_swapsize" "$SYS_MEM" || { SWAP_PART=''; SWAP_SIZE=''; return 1; }
968 part_swap "$MNT/$SWAP_PART"
969 SWAP_PART="/$SWAP_PART"
970 elif [[ $PARTS == *"$SWAP_PART"* ]]; then
972 part_countdec $SWAP_PART
973 SWAP_SIZE="$(lsblk -lno SIZE $SWAP_PART)"
983 local fs="$1" opts=''
984 local title="${fs^} Mount Options"
986 for i in ${FS_OPTS[$fs]}; do
990 until [[ $MNT_OPTS ]]; do
991 dlg MNT_OPTS check "$title" "$_mount" $opts
992 [[ $MNT_OPTS ]] || return 1
993 MNT_OPTS="${MNT_OPTS// /,}"
994 yesno "$title" "\nConfirm the following options: $MNT_OPTS\n" || MNT_OPTS=''
1003 until [[ $EXMNT ]]; do
1004 dlg EXMNT input "Extra Mount $part" "$_exmnt" "/" || return 1
1005 if [[ ${EXMNT:0:1} != "/" || ${#EXMNT} -le 1 || $EXMNT =~ \ |\' || $EXMNTS == *"$EXMNT"* ]]; then
1006 msg "Mountpoint Error" "$_errexpart"
1010 msg "Mount Extra" "\nMounting Finished\n\n\nNo extra partitions available to mount, returning to main menu.\n" 2
1016 local part="$1" fs='' cur=''
1017 local txt="\nSelect which filesystem to use for: $part\n\nDefault: ext4"
1018 cur="$(lsblk -lno FSTYPE "$part" 2>/dev/null)"
1020 # bail early if the partition was created in part_auto()
1021 [[ $cur && $part == "$AUTO_ROOT_PART" ]] && return 0
1024 if [[ $cur && $FORMATTED == *"$part"* ]]; then
1025 dlg fs menu "Filesystem" "$txt\nCurrent: $cur" skip - ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1027 dlg fs menu "Filesystem" "$txt" ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1029 [[ $fs == 'skip' ]] && return 0
1030 yesno "Filesystem" "\nFormat $part as $fs?\n" || fs=''
1032 part_format "$part" "$fs"
1035 select_efi_partition()
1037 if [[ -z $BOOT_PART ]]; then
1038 if [[ $AUTO_BOOT_PART ]]; then
1039 BOOT_PART="$AUTO_BOOT_PART"
1040 return 0 # were done here
1042 local pts size dev isize bsize ptcount=0
1044 # walk partition list and skip ones that are too small/big for boot
1045 while read -r dev size; do
1046 size_t="${size: -1:1}" # size type eg. K, M, G, T
1047 isize=${size:0:-1} # remove trailing size type character
1048 isize=${isize%.*} # remove any decimal (round down)
1049 [[ $size_t =~ [KT] || ($size_t == 'G' && $isize -gt 2) || ($size_t == 'M' && $isize -lt 100) ]] || { pts+="$dev $size "; (( ptcount++ )); }
1052 if (( ptcount == 1 )); then
1053 msg "EFI Boot Partition" "\nOnly one partition available that meets size requirements.\n" 1
1054 BOOT_PART="$(awk 'NF > 0 {print $1}' <<< "$pts")"
1056 dlg BOOT_PART menu "EFI Partition" "$_uefi" $pts
1061 if [[ -z $BOOT_PART ]]; then
1063 elif grep -q 'fat' <<< "$(fsck -N "$BOOT_PART")"; then
1064 local txt="\nIMPORTANT:\n\nThe EFI partition $BOOT_PART $_format"
1065 if yesno "Format EFI Partition" "$txt" "Format $BOOT_PART" "Skip Formatting" 1; then
1066 part_format "$BOOT_PART" "vfat" 2
1069 part_format "$BOOT_PART" "vfat" 2
1075 select_boot_partition()
1077 if [[ -z $BOOT_PART ]]; then
1078 if [[ $AUTO_BOOT_PART && ! $LVM ]]; then
1079 BOOT_PART="$AUTO_BOOT_PART"
1080 return 0 # were done here
1082 local pts size dev isize bsize ptcount=0
1084 # walk partition list and skip ones that are too small/big for boot
1085 while read -r dev size; do
1086 size_t="${size: -1:1}" # size type eg. K, M, G, T
1087 isize=${size:0:-1} # remove trailing size type character
1088 isize=${isize%.*} # remove any decimal (round down)
1089 [[ $size_t =~ [KT] || ($size_t == 'G' && $isize -gt 2) || ($size_t == 'M' && $isize -lt 100) ]] || { pts+="$dev $size "; (( ptcount++ )); }
1092 if [[ $LUKS && ! $LVM ]]; then
1093 dlg BOOT_PART menu "Boot Partition" "$_biosluks" $pts
1094 [[ $BOOT_PART ]] || return 1
1096 dlg BOOT_PART menu "Boot Partition" "$_bios" "skip" "don't use a separate boot" $pts
1097 [[ -z $BOOT_PART || $BOOT_PART == "skip" ]] && { BOOT_PART=''; return 0; }
1102 if grep -q 'ext[34]' <<< "$(fsck -N "$BOOT_PART")"; then
1103 local txt="\nIMPORTANT:\n\nThe boot partition $BOOT_PART $_format"
1104 if yesno "Format Boot Partition" "$txt" "Format $BOOT_PART" "Skip Formatting" 1; then
1105 part_format "$BOOT_PART" "ext4" 2
1108 part_format "$BOOT_PART" "ext4" 2
1113 select_root_partition()
1115 if [[ -z $ROOT_PART ]]; then
1116 if [[ $AUTO_ROOT_PART && -z $LVM && -z $LUKS ]]; then
1117 ROOT_PART="$AUTO_ROOT_PART"
1118 msg "Mount Menu" "\nUsing partitions created during automatic format.\n" 2
1119 part_mount "$ROOT_PART" || { ROOT_PART=''; return 1; }
1120 return 0 # we're done here
1122 local pts size dev isize bsize ptcount=0
1124 # walk partition list and skip ones that are too small for / (root)
1125 while read -r dev size; do
1126 size_t="${size: -1:1}" # size type eg. K, M, G, T
1127 isize=${size:0:-1} # remove trailing size type character
1128 isize=${isize%.*} # remove any decimal (round down)
1129 [[ $size_t =~ [MK] || ($size_t == 'G' && $isize -lt 4) ]] || { pts+="$dev $size "; (( ptcount++ )); }
1132 if (( ptcount == 1 )); then # only one available device
1133 msg "Root Partition (/)" "\nOnly one partition available that meets size requirements.\n" 2
1134 ROOT_PART="$(awk 'NF > 0 {print $1}' <<< "$pts")"
1136 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
1141 if [[ -z $ROOT_PART ]] || ! select_filesystem "$ROOT_PART" || ! part_mount "$ROOT_PART"; then
1148 select_extra_partitions()
1152 # walk partition list and skip ones that are too small to be usable
1153 while read -r dev size; do
1154 [[ ${size: -1:1} =~ [KM] ]] && part_countdec "$dev"
1157 while (( COUNT > 0 )); do
1159 dlg part menu 'Mount Extra' "$_expart" 'done' 'finish mounting step' $PARTS || break
1160 if [[ $part == 'done' ]]; then
1162 elif select_filesystem "$part" && select_mountpoint && part_mount "$part" "$EXMNT"; then
1163 EXMNTS+="$part: $EXMNT "
1164 [[ $EXMNT == '/usr' && $HOOKS != *usr* ]] && HOOKS="usr $HOOKS"
1172 ###############################################################################
1174 # main is the entry point which calls all other install functions, once
1175 # complete it shows a dialog to edit files on the new system before reboot
1180 genfstab -U $MNT >$MNT/etc/fstab 2>$ERR
1181 errshow 1 "genfstab -U $MNT >$MNT/etc/fstab"
1182 [[ -f $MNT/swapfile ]] && sed -i "s~${MNT}~~" $MNT/etc/fstab
1186 chrun "hwclock --systohc --utc" || chrun "hwclock --systohc --utc --directisa"
1189 chrun "chown -Rf $NEWUSER:users /home/$NEWUSER"
1192 dlg choice menu "Finalization" "$_edit" \
1193 finished "exit the installer and reboot" \
1194 keyboard "${EDIT_FILES[keyboard]}" \
1195 console "${EDIT_FILES[console]}" \
1196 locale "${EDIT_FILES[locale]}" \
1197 hostname "${EDIT_FILES[hostname]}" \
1198 sudoers "${EDIT_FILES[sudoers]}" \
1199 mkinitcpio "${EDIT_FILES[mkinitcpio]}" \
1200 fstab "${EDIT_FILES[fstab]}" \
1201 crypttab "${EDIT_FILES[crypttab]}" \
1202 bootloader "${EDIT_FILES[bootloader]}" \
1203 pacman "${EDIT_FILES[pacman]}" \
1204 login "${EDIT_FILES[login]}"
1206 if [[ -z $choice || $choice == 'finished' ]]; then
1207 [[ $DEBUG == true && -r $DBG ]] && ${EDITOR:-vim} $DBG
1211 for f in ${EDIT_FILES[$choice]}; do
1212 [[ -e ${MNT}$f ]] && exists+=" ${MNT}$f"
1214 if [[ $exists ]]; then
1215 ${EDITOR:-vim} -O $exists
1217 msg "File Missing" "\nThe file(s) selected do not exist:\n\n${EDIT_FILES[$choice]}\n"
1227 while kill -0 $BG_PID 2>/dev/null; do
1228 clear; printf "\nA background install process is still running...\n"; sleep 1
1233 rm -rf $MNT/etc/mkinitcpio-archiso.conf
1234 find $MNT/usr/lib/initcpio -name 'archiso*' -type f -delete
1235 sed -i 's/#\(Storage=\)volatile/\1auto/' $MNT/etc/systemd/journald.conf
1236 find $MNT/boot -name '*-ucode.img' -delete
1238 [[ $DIST != "ArchLabs" ]] || sed -i "s/ArchLabs/$DIST/g" $MNT/etc/{lsb-release,os-release}
1241 find $MNT/etc/X11/xorg.conf.d/ -name '*.conf' -delete
1242 elif lspci | grep ' VGA ' | grep -q 'Intel'; then
1243 echo "Creating Intel VGA Tear Free config /etc/X11/xorg.conf.d/20-intel.conf"
1244 cat > $MNT/etc/X11/xorg.conf.d/20-intel.conf <<- EOF
1246 Identifier "Intel Graphics"
1248 Option "TearFree" "true"
1253 [[ -e /run/archiso/sfs/airootfs ]] && cp -vf $RUN/x86_64/vmlinuz $MNT/boot/vmlinuz-linux
1254 [[ -d /etc/netctl ]] && cp -rfv /etc/netctl $MNT/etc/
1255 [[ -f /etc/resolv.conf ]] && cp -fv /etc/resolv.conf $MNT/etc/
1256 [[ -e /etc/NetworkManager/system-connections ]] && cp -rvf /etc/NetworkManager/system-connections $MNT/etc/NetworkManager/
1258 echo "LANG=$MYLOCALE" > $MNT/etc/locale.conf
1259 cp -fv $MNT/etc/locale.conf $MNT/etc/default/locale
1260 sed -i "s/#en_US.UTF-8/en_US.UTF-8/g; s/#${MYLOCALE}/${MYLOCALE}/g" $MNT/etc/locale.gen
1262 chrun "ln -svf /usr/share/zoneinfo/$ZONE/$SUBZ /etc/localtime"
1264 cat > $MNT/etc/X11/xorg.conf.d/00-keyboard.conf <<- EOF
1265 # Use localectl(1) to instruct systemd-localed to update it.
1266 Section "InputClass"
1267 Identifier "system-keyboard"
1268 MatchIsKeyboard "on"
1269 Option "XkbLayout" "$KEYMAP"
1273 cat > $MNT/etc/default/keyboard <<- EOF
1274 # KEYBOARD CONFIGURATION FILE
1275 # Consult the keyboard(5) manual page.
1282 printf "KEYMAP=%s\nFONT=%s\n" "$CMAP" "$FONT" > $MNT/etc/vconsole.conf
1283 echo "$MYHOST" > $MNT/etc/hostname
1284 cat > $MNT/etc/hosts <<- EOF
1287 ::1 localhost ip6-localhost ip6-loopback
1288 ff02::1 ip6-allnodes
1289 ff02::2 ip6-allrouters
1295 echo "Installing $BOOTLDR"
1297 if [[ $ROOT_PART == /dev/mapper* ]]; then
1298 ROOT_PART_ID="$ROOT_PART"
1300 local uuid_type="UUID"
1301 [[ $BOOTLDR =~ (systemd-boot|refind-efi|efistub) ]] && uuid_type="PARTUUID"
1302 ROOT_PART_ID="$uuid_type=$(blkid -s $uuid_type -o value $ROOT_PART)"
1305 if [[ $SYS == 'UEFI' ]]; then
1306 # remove our old install and generic BOOT/ dir
1307 find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname "$DIST" -type d -delete
1308 find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname 'BOOT' -type d -delete
1312 chrun "${BCMDS[$BOOTLDR]}" 2>$ERR
1313 errshow 1 "${BCMDS[$BOOTLDR]}"
1315 if [[ -d $MNT/hostrun ]]; then
1316 # cleanup the bind mounts we made earlier for the grub-probe module
1317 umount_dir $MNT/hostrun/{udev,lvm}
1318 rm -rf $MNT/hostrun >/dev/null 2>&1
1321 if [[ $SYS == 'UEFI' ]]; then
1322 # some UEFI firmware requires a generic esp/BOOT/BOOTX64.EFI
1323 mkdir -pv $MNT/$BOOTDIR/EFI/BOOT
1325 grub) cp -fv $MNT/$BOOTDIR/EFI/$DIST/grubx64.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI ;;
1326 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 ;;
1327 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
1328 cp -fv $MNT/$BOOTDIR/EFI/refind/refind_x64.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI ;;
1337 local groups='audio,floppy,log,network,rfkill,scanner,storage,optical,power,wheel'
1339 rm -f $MNT/root/.zshrc # remove welcome message from root zshrc
1341 chrun "chpasswd <<< 'root:$ROOT_PASS'" 2>$ERR
1342 errshow 1 "set root password"
1343 if [[ $MYSHELL != 'zsh' ]]; then # root uses zsh by default
1344 chrun "usermod -s /bin/$MYSHELL root" 2>$ERR
1345 errshow 1 "usermod -s /bin/$MYSHELL root"
1346 # copy the default mkshrc to /root if it was selected
1347 [[ $MYSHELL == 'mksh' ]] && cp -fv "$MNT/etc/skel/.mkshrc" "$MNT/root/.mkshrc"
1350 echo "Creating new user $NEWUSER and setting password"
1351 chrun "useradd -m -u 1000 -g users -G $groups -s /bin/$MYSHELL $NEWUSER" 2>$ERR
1352 errshow 1 "useradd -m -u 1000 -g users -G $groups -s /bin/$MYSHELL $NEWUSER"
1353 chrun "chpasswd <<< '$NEWUSER:$USER_PASS'" 2>$ERR
1354 errshow 1 "set $NEWUSER password"
1356 if [[ $INSTALL_WMS == *dwm* ]];then
1357 install_suckless "/home/$NEWUSER" chroot
1358 [[ $INSTALL_WMS == 'dwm' ]] && rm -rf "$MNT/home/$NEWUSER/.config/xfce4"
1361 [[ $INSTALL_WMS != *bspwm* && $INSTALL_WMS != *openbox* ]] && rm -rf "$MNT/home/$NEWUSER/.config/"{jgmenu,tint2}
1362 [[ $USER_PKGS != *geany* ]] && rm -rf "$MNT/home/$NEWUSER/.config/geany"
1363 [[ $MYSHELL != 'bash' ]] && rm -rf "$MNT/home/$NEWUSER/.bash"*
1364 [[ $MYSHELL != 'zsh' ]] && rm -rf "$MNT/home/$NEWUSER/.z"*
1366 # remove some commands from ~/.xprofile when using KDE or Gnome as the login session
1367 if [[ $LOGIN_WM =~ (startkde|gnome-session) || ($LOGIN_TYPE != 'xinit' && $WM_PKGS =~ (plasma|gnome)) ]]; then
1368 sed -i '/super/d; /nitrogen/d; /compton/d' "$MNT/home/$NEWUSER/.xprofile" "$MNT/root/.xprofile"
1369 elif [[ $LOGIN_WM == 'dwm' ]]; then # and dwm
1370 sed -i '/super/d; /compton/d' "$MNT/home/$NEWUSER/.xprofile" "$MNT/root/.xprofile"
1373 # create user home directories (Music, Documents, Downloads, etc..)
1374 chrun 'xdg-user-dirs-update'
1381 local serv="$MNT/etc/systemd/system/getty@tty1.service.d"
1382 echo "Setting up $LOGIN_TYPE"
1384 ly|sddm|gdm|lightdm)
1385 if [[ $LOGIN_WM == *dwm* ]]; then # dwm doesn't include an xsession file for display managers
1386 mkdir -p $MNT/usr/share/xsessions
1387 cat >$MNT/usr/share/xsessions/dwm.desktop <<- EOF
1391 Comment=Dynamic Window Manager
1396 rm -rf "$serv" "$MNT/home/$NEWUSER/.xinitrc"
1397 chrun "systemctl enable $LOGIN_TYPE.service" 2>$ERR
1398 errshow 1 "systemctl enable $LOGIN_TYPE.service"
1399 ${LOGIN_TYPE}_config
1402 if [[ $INSTALL_WMS ]]; then
1403 sed -i "/exec/ c exec ${LOGIN_WM}" "$MNT/home/$NEWUSER/.xinitrc"
1404 elif [[ -e $MNT/home/$NEWUSER/.xinitrc ]]; then
1405 sed -i '/exec/d' "$MNT/home/$NEWUSER/.xinitrc"
1408 if [[ $AUTOLOGIN ]]; then
1409 sed -i "s/root/${NEWUSER}/g" $serv/autologin.conf
1410 cat > "$MNT/home/$NEWUSER/$LOGINRC" <<- EOF
1411 # automatically run startx when logging in on tty1
1412 [ -z "\$DISPLAY" ] && [ \$XDG_VTNR -eq 1 ] && startx
1423 local rmpkg="archlabs-installer "
1424 local inpkg="$PACKAGES $USER_PKGS $AL_BASE_PKGS "
1426 if [[ $MYSHELL == 'zsh' ]]; then
1427 inpkg+="zsh-completions "
1432 if [[ $INSTALL_WMS == 'dwm' ]]; then # dwm only needs a very limited package set
1433 inpkg+="nitrogen polkit-gnome gnome-keyring dunst "
1435 [[ $INSTALL_WMS =~ (plasma|gnome|cinnamon) ]] || inpkg+="archlabs-ksuperkey "
1436 [[ $INSTALL_WMS =~ (openbox|bspwm|i3-gaps|fluxbox) ]] && inpkg+="$WM_BASE_PKGS "
1437 [[ $inpkg =~ (term|plasma|rxvt|tilda|tilix|sakura) || $INSTALL_WMS =~ (gnome|plasma|xfce4) ]] || inpkg+="xterm "
1440 # update and install crucial packages first to avoid issues
1441 chrun "pacman -Syyu $KERNEL $BASE_PKGS ${LOGIN_PKGS[$LOGIN_TYPE]} $MYSHELL --noconfirm --needed" 2>$ERR
1442 errshow 1 "pacman -Syyu $KERNEL $BASE_PKGS ${LOGIN_PKGS[$LOGIN_TYPE]} $MYSHELL --noconfirm --needed"
1444 # remove the packages we don't want on the installed system
1445 chrun "pacman -Rnsc $rmpkg --noconfirm"
1447 # reinstalling iputils fixes the network issue for non-root users
1448 chrun "pacman -S iputils $UCODE --noconfirm"
1450 # install the packages chosen throughout the install
1451 chrun "pacman -S $inpkg --needed --noconfirm" 2>$ERR
1452 errshow 1 "pacman -S $inpkg --needed --noconfirm"
1454 # bootloader packages
1455 if [[ $BOOTLDR == 'grub' ]]; then
1456 [[ $SYS == 'UEFI' ]] && local efib="efibootmgr"
1457 chrun "pacman -S os-prober grub $efib --needed --noconfirm" 2>$ERR
1458 errshow 1 "pacman -S os-prober grub $efib --needed --noconfirm"
1459 elif [[ $BOOTLDR == 'refind-efi' ]]; then
1460 chrun "pacman -S refind-efi efibootmgr --needed --noconfirm" 2>$ERR
1461 errshow 1 "pacman -S refind-efi efibootmgr --needed --noconfirm"
1462 elif [[ $SYS == 'UEFI' ]]; then
1463 chrun "pacman -S efibootmgr --needed --noconfirm" 2>$ERR
1464 errshow 1 "pacman -S efibootmgr --needed --noconfirm"
1467 # allow members of the wheel group to run commands as root
1468 sed -i "s/# %wheel ALL=(ALL) ALL/%wheel ALL=(ALL) ALL/g" $MNT/etc/sudoers
1473 install_mkinitcpio()
1476 [[ $LUKS ]] && add="encrypt"
1477 [[ $LVM ]] && { [[ $add ]] && add+=" lvm2" || add+="lvm2"; }
1478 sed -i "s/block filesystems/block ${add} filesystems ${HOOKS}/g" $MNT/etc/mkinitcpio.conf
1479 chrun "mkinitcpio -p $KERNEL" 2>$ERR
1480 errshow 1 "mkinitcpio -p $KERNEL"
1483 install_mirrorlist()
1485 if hash reflector >/dev/null 2>&1; then
1486 reflector --verbose --score 80 -l 40 -f 5 --sort rate --save "$1"
1487 elif hash rankmirrors >/dev/null 2>&1; then
1488 echo "Sorting mirrorlist"
1489 local key="access_key=5f29642060ab983b31fdf4c2935d8c56"
1490 ip_add="$(curl -fsSL "http://api.ipstack.com/check&?$key&fields=ip" | python -c "import sys, json; print(json.load(sys.stdin)['ip'])")"
1491 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'])")"
1492 if [[ "$country" ]]; then
1493 if [[ $country =~ (CA|US) ]]; then
1494 # use both CA and US mirrors for CA or US countries
1495 mirror="https://www.archlinux.org/mirrorlist/?country=US&country=CA&use_mirror_status=on"
1496 elif [[ $country =~ (AU|NZ) ]]; then
1497 # use both AU and NZ mirrors for AU or NZ countries
1498 mirror="https://www.archlinux.org/mirrorlist/?country=AU&country=NZ&use_mirror_status=on"
1500 mirror="https://www.archlinux.org/mirrorlist/?country=${country}&use_mirror_status=on"
1502 else # no country code so just grab all mirrors, will be a very slow sort but we don't have other options
1503 mirror="https://www.archlinux.org/mirrorlist/?country=all&use_mirror_status=on"
1505 curl -fsSL "$mirror" | sed -e 's/^#Server/Server/' -e '/^#/d' | rankmirrors -n 6 - >"$1"
1511 install_background()
1513 ( rsync -a /run/archiso/sfs/airootfs/ $MNT/ && install_mirrorlist "$MNT/etc/pacman.d/mirrorlist" >/dev/null 2>&1 ) &
1515 trap "kill $BG_PID 2>/dev/null" EXIT
1520 local dir="$1/suckless"
1523 if [[ $2 == 'chroot' ]]; then
1524 chrun "mkdir -pv '$dir'"
1525 for i in dwm dmenu st; do
1526 if chrun "git clone 'https://git.suckless.org/$i' '$dir/$i'"; then
1527 chrun "cd '$dir/$i' && make PREFIX=/usr install"
1529 printf "failed to clone %s repo\n" "$i"
1534 for i in dwm dmenu st; do
1535 if git clone "https://git.suckless.org/$i" "$dir/$i"; then
1536 cd "$dir/$i" && make PREFIX=/usr install
1538 printf "failed to clone %s repo\n" "$i"
1544 ###############################################################################
1545 # display manager config
1546 # these are called based on which DM is chosen after it is installed
1547 # additional config can be handled here, for now only lightdm has one
1551 cat > $MNT/etc/lightdm/lightdm-gtk-greeter.conf <<- EOF
1553 default-user-image=/usr/share/icons/ArchLabs-Dark/64x64/places/distributor-logo-archlabs.png
1554 background=/usr/share/backgrounds/archlabs/archlabs.jpg
1555 theme-name=Adwaita-dark
1556 icon-theme-name=Adwaita
1557 font-name=DejaVu Sans Mono 11
1558 position=30%,end 50%,end
1577 ###############################################################################
1579 # prerun_* set up the configs needed before actually running the commands
1580 # setup_* are run after selecting a bootloader and build the command used later
1581 # they can also be used for further user input as these run before control is taken away
1585 EDIT_FILES[bootloader]="/etc/default/grub"
1587 if [[ $SYS == 'BIOS' ]]; then
1588 [[ $BOOT_DEV ]] || { part_device 1 || return 1; }
1589 BCMDS[grub]="grub-install --recheck --force --target=i386-pc $BOOT_DEV"
1591 BCMDS[grub]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1592 grub-install --recheck --force --target=x86_64-efi --efi-directory=/$BOOTDIR --bootloader-id=$DIST"
1593 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1596 BCMDS[grub]="mkdir -p /run/udev /run/lvm &&
1597 mount --bind /hostrun/udev /run/udev &&
1598 mount --bind /hostrun/lvm /run/lvm &&
1600 grub-mkconfig -o /boot/grub/grub.cfg &&
1601 sleep 1 && umount /run/udev /run/lvm"
1608 sed -i "s/GRUB_DISTRIBUTOR=.*/GRUB_DISTRIBUTOR=\"${DIST}\"/g; s/GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT=\"\"/g" $MNT/etc/default/grub
1610 if [[ $LUKS_DEV ]]; then
1611 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
1612 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"
1615 if [[ $SYS == 'BIOS' && $LVM && -z $SEP_BOOT ]]; then
1616 sed -i "s/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g" $MNT/etc/default/grub 2>$ERR
1617 errshow 1 "sed -i 's/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g' $MNT/etc/default/grub"
1620 # setup for os-prober module
1621 mkdir -p /run/{lvm,udev} $MNT/hostrun/{lvm,udev}
1622 mount --bind /run/lvm $MNT/hostrun/lvm
1623 mount --bind /run/udev $MNT/hostrun/udev
1630 EDIT_FILES[bootloader]=""
1635 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1636 efibootmgr -v -d $BOOT_DEV -p $BOOT_PART_NUM -c -L '${DIST} Linux' -l /vmlinuz-${KERNEL} \
1637 -u 'root=$ROOT_PART_ID rw $([[ $UCODE ]] && printf 'initrd=\%s.img ' "$UCODE")initrd=\initramfs-${KERNEL}.img'"
1642 if [[ $SYS == 'BIOS' ]]; then
1643 EDIT_FILES[bootloader]="/boot/syslinux/syslinux.cfg"
1645 EDIT_FILES[bootloader]="/boot/EFI/syslinux/syslinux.cfg"
1646 BCMDS[syslinux]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1647 efibootmgr -v -c -d $BOOT_DEV -p $BOOT_PART_NUM -l /EFI/syslinux/syslinux.efi -L $DIST"
1653 local c="$MNT/boot/syslinux" s="/usr/lib/syslinux/bios" d=".."
1654 [[ $SYS == 'UEFI' ]] && { c="$MNT/boot/EFI/syslinux"; s="/usr/lib/syslinux/efi64"; d=''; }
1657 cp -rfv "$s/"* "$c/"
1658 cat > "$c/syslinux.cfg" <<- EOF
1661 MENU TITLE $DIST Boot Menu
1666 MENU LABEL $DIST Linux
1667 LINUX $d/vmlinuz-$KERNEL
1668 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1669 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL.img
1671 LABEL ${DIST}fallback
1672 MENU LABEL $DIST Linux Fallback
1673 LINUX $d/vmlinuz-$KERNEL
1674 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1675 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL-fallback.img
1682 EDIT_FILES[bootloader]="/boot/refind_linux.conf"
1683 BCMDS[refind-efi]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1; refind-install"
1688 cat > $MNT/boot/refind_linux.conf <<- EOF
1689 "$DIST Linux" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] &&
1690 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1691 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL.img"
1692 "$DIST Linux Fallback" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] &&
1693 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1694 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL-fallback.img"
1696 mkdir -p $MNT/etc/pacman.d/hooks
1697 cat > $MNT/etc/pacman.d/hooks/refind.hook <<- EOF
1704 Description = Updating rEFInd on ESP
1705 When = PostTransaction
1706 Exec = /usr/bin/refind-install
1710 setup_systemd-boot()
1712 EDIT_FILES[bootloader]="/boot/loader/entries/$DIST.conf"
1713 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1; bootctl --path=/boot install"
1716 prerun_systemd-boot()
1718 mkdir -p $MNT/boot/loader/entries
1719 cat > $MNT/boot/loader/loader.conf <<- EOF
1724 cat > $MNT/boot/loader/entries/$DIST.conf <<- EOF
1726 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1727 initrd /initramfs-$KERNEL.img
1728 options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1730 cat > $MNT/boot/loader/entries/$DIST-fallback.conf <<- EOF
1731 title $DIST Linux Fallback
1732 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1733 initrd /initramfs-$KERNEL-fallback.img
1734 options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1736 mkdir -p $MNT/etc/pacman.d/hooks
1737 cat > $MNT/etc/pacman.d/hooks/systemd-boot.hook <<- EOF
1744 Description = Updating systemd-boot
1745 When = PostTransaction
1746 Exec = /usr/bin/bootctl update
1748 systemd-machine-id-setup --root="$MNT"
1752 ###############################################################################
1757 msg "Info" "\nGathering device info.\n" 0
1758 no_bg_install || return 1
1762 dlg choice menu "Logical Volume Management" "$_lvmmenu" \
1763 "$_lvmnew" "vgcreate -f, lvcreate -L -n" \
1764 "$_lvmdel" "vgremove -f" \
1765 "$_lvmdelall" "lvrmeove, vgremove, pvremove -f" \
1766 "Back" "Return to the main menu"
1768 "$_lvmnew") lvm_create && break ;;
1769 "$_lvmdel") lvm_delgroup && yesno "$_lvmdel" "$_lvmdelask" && vgremove -f "$DEL_VG" >/dev/null 2>&1 ;;
1770 "$_lvmdelall") lvm_del_all ;;
1781 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
1782 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
1783 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
1785 if [[ $VGROUP && $v && $pv ]]; then
1786 msg "LVM Setup" "\nActivating existing logical volume management.\n" 0
1787 modprobe dm-mod >/dev/null 2>$ERR
1788 errshow 'modprobe dm-mod'
1789 vgscan >/dev/null 2>&1
1790 vgchange -ay >/dev/null 2>&1
1796 VGROUP='' LVM_PARTS='' VGROUP_MB=0
1798 lvm_mkgroup || return 1
1799 local txt="\nThe last (or only) logical volume will automatically use all remaining space in the volume group."
1800 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 -
1801 [[ $VOL_COUNT ]] || return 1
1802 lvm_extra_lvs || return 1
1803 lvm_volume_name "$_lvmlvname\nNOTE: This LV will use up all remaining space in the volume group (${VGROUP_MB}MB)" || return 1
1804 msg "$_lvmnew (LV:$VOL_COUNT)" "\nCreating volume $VNAME from remaining space in $VGROUP\n" 0
1805 lvcreate -l +100%FREE "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
1806 errshow "lvcreate -l +100%FREE $VGROUP -n $VNAME" || return 1
1807 LVM='logical volume'; sleep 0.5
1808 txt="\nDone, volume: $VGROUP-$VNAME (${VOLUME_SIZE:-${VGROUP_MB}MB}) has been created.\n"
1809 msg "$_lvmnew (LV:$VOL_COUNT)" "$txt\n$(lsblk -o NAME,MODEL,TYPE,FSTYPE,SIZE $LVM_PARTS)\n"
1815 local txt="${VGROUP}: ${SIZE}$SIZE_UNIT (${VGROUP_MB}MB remaining).$_lvmlvsize"
1819 dlg VOLUME_SIZE input "$_lvmnew (LV:$VOL_COUNT)" "$txt" ''
1820 if [[ -z $VOLUME_SIZE ]]; then
1822 break # allow bailing with escape or an empty choice
1823 elif (( ${VOLUME_SIZE:0:1} == 0 )); then
1824 ERR_SIZE=1 # size values can't begin with '0'
1826 # walk the string and make sure all but the last char are digits
1827 local lv=$((${#VOLUME_SIZE} - 1))
1828 for (( i=0; i<lv; i++ )); do
1829 [[ ${VOLUME_SIZE:$i:1} =~ [0-9] ]] || { ERR_SIZE=1; break; }
1831 if (( ERR_SIZE != 1 )); then
1832 case ${VOLUME_SIZE:$lv:1} in
1833 [mMgG]) local s=${VOLUME_SIZE:0:$lv} m=$((s * 1000))
1834 case ${VOLUME_SIZE:$lv:1} in
1835 [Gg]) (( m >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - m)) ;;
1836 [Mm]) (( ${VOLUME_SIZE:0:$lv} >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - s)) ;;
1843 if (( ERR_SIZE )); then
1844 msg "Invalid Logical Volume Size" "$_lvmerrlvsize"
1857 until [[ $named ]]; do
1858 lvm_partitions || return 1
1859 lvm_group_name || return 1
1860 yesno "$_lvmnew" "\nCreate volume group: $VGROUP\n\nusing these partition(s): $LVM_PARTS\n" && named=true
1863 msg "$_lvmnew" "\nCreating volume group: $VGROUP\n" 0
1864 vgcreate -f "$VGROUP" $LVM_PARTS >/dev/null 2>$ERR
1865 errshow "vgcreate -f $VGROUP $LVM_PARTS" || return 1
1867 SIZE=$(vgdisplay "$VGROUP" | awk '/VG Size/ { gsub(/[^0-9.]/, ""); print int($0) }')
1868 SIZE_UNIT="$(vgdisplay "$VGROUP" | awk '/VG Size/ { print substr($NF, 0, 1) }')"
1870 if [[ $SIZE_UNIT == 'G' ]]; then
1871 VGROUP_MB=$((SIZE * 1000))
1876 msg "$_lvmnew" "\nVolume group $VGROUP (${SIZE}$SIZE_UNIT) successfully created\n"
1882 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
1883 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
1884 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
1886 if [[ $VGROUP || $v || $pv ]]; then
1887 if yesno "$_lvmdelall" "$_lvmdelask"; then
1888 for i in $v; do lvremove -f "/dev/mapper/$i" >/dev/null 2>&1; done
1889 for i in $VGROUP; do vgremove -f "$i" >/dev/null 2>&1; done
1890 for i in $pv; do pvremove -f "$i" >/dev/null 2>&1; done
1894 msg "Delete LVM" "\nNo LVMs to remove...\n" 2
1904 for i in $(lvs --noheadings | awk '{print $2}' | uniq); do
1905 VOL_GROUP_LIST+="$i $(vgdisplay "$i" | awk '/VG Size/ {print $3$4}') "
1908 [[ $VOL_GROUP_LIST ]] || { msg "No Groups" "\nNo volume groups found."; return 1; }
1910 dlg DEL_VG menu "Logical Volume Management" "\nSelect volume group to delete.\n\nAll logical volumes within will also be deleted." $VOL_GROUP_LIST
1916 while (( VOL_COUNT > 1 )); do
1917 lvm_volume_name "$_lvmlvname" && lvm_lv_size || return 1
1918 msg "$_lvmnew (LV:$VOL_COUNT)" "\nCreating a $VOLUME_SIZE volume $VNAME in $VGROUP\n" 0
1919 lvcreate -L "$VOLUME_SIZE" "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
1920 errshow "lvcreate -L $VOLUME_SIZE $VGROUP -n $VNAME" || return 1
1921 msg "$_lvmnew (LV:$VOL_COUNT)" "\nDone, logical volume (LV) $VNAME ($VOLUME_SIZE) has been created.\n"
1929 part_find 'part|crypt' || return 1
1930 PARTS="$(awk 'NF > 0 {print $0 " off"}' <<< "$PARTS")"
1931 dlg LVM_PARTS check "$_lvmnew" "\nSelect the partition(s) to use for the physical volume (PV)." $PARTS
1938 until [[ $VGROUP ]]; do
1939 dlg VGROUP input "$_lvmnew" "$_lvmvgname" "lvgroup"
1940 if [[ -z $VGROUP ]]; then
1942 elif [[ ${VGROUP:0:1} == "/" || $VGROUP =~ \ |\' ]] || vgdisplay | grep -q "$VGROUP"; then
1943 msg "LVM Name Error" "$_lvmerrvgname"
1953 local txt="$1" default="mainvolume"
1954 (( VOL_COUNT > 1 )) && default="extvolume$VOL_COUNT"
1955 until [[ $VNAME ]]; do
1956 dlg VNAME input "$_lvmnew (LV:$VOL_COUNT)" "\n$txt" "$default"
1957 if [[ -z $VNAME ]]; then
1959 elif [[ ${VNAME:0:1} == "/" || $VNAME =~ \ |\' ]] || lsblk | grep -q "$VNAME"; then
1960 msg "LVM Name Error" "$_lvmerlvname"
1967 ###############################################################################
1973 no_bg_install || return 1
1974 dlg choice menu "LUKS Encryption" "$_luksmenu" \
1975 "$_luksnew" "cryptsetup -q luksFormat" \
1976 "$_luksopen" "cryptsetup open --type luks" \
1977 "$_luksadv" "cryptsetup -q -s -c luksFormat" \
1978 "Back" "Return to the main menu"
1981 "$_luksnew") luks_basic || return 1 ;;
1982 "$_luksopen") luks_open || return 1 ;;
1983 "$_luksadv") luks_advanced || return 1 ;;
1991 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
1993 part_find 'part|crypt|lvm' || return 1
1995 if (( COUNT == 1 )); then
1996 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
1998 dlg LUKS_PART menu "$_luksopen" "\nSelect which partition to open." $PARTS
2001 [[ $LUKS_PART ]] || return 1
2003 luks_pass "$_luksopen" || return 1
2004 msg "$_luksopen" "\nOpening encrypted partition: $LUKS_NAME\n\nUsing device/volume: $LUKS_PART\n" 0
2005 cryptsetup open --type luks "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2006 errshow "cryptsetup open --type luks $LUKS_PART $LUKS_NAME" || return 1
2007 LUKS='encrypted'; luks_show
2015 typeset -a ans=(cryptroot) # default name to start
2017 until [[ $LUKS_PASS ]]; do
2019 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " $t " --mixedform "$_luksomenu" 0 0 0 \
2020 "Name:" 1 1 "${ans[0]}" 1 7 "$COLUMNS" 0 0 \
2021 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
2022 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
2024 mapfile -t ans <"$ANS"
2026 if [[ -z "${ans[0]}" ]]; then
2027 msg "Name Empty" "\nEncrypted device name cannot be empty.\n\nPlease try again.\n" 2
2028 elif [[ -z "${ans[1]}" || "${ans[1]}" != "${ans[2]}" ]]; then
2029 LUKS_NAME="${ans[0]}"
2030 msg "Password Mismatch" "\nThe passwords entered do not match.\n\nPlease try again.\n" 2
2032 LUKS_NAME="${ans[0]}"
2033 LUKS_PASS="${ans[1]}"
2043 msg "$_luksnew" "\nEncrypted partition ready for mounting.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$LUKS_PART")\n\n"
2048 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
2050 part_find 'part|lvm' || return 1
2052 if [[ $AUTO_ROOT_PART ]]; then
2053 LUKS_PART="$AUTO_ROOT_PART"
2054 elif (( COUNT == 1 )); then
2055 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2057 dlg LUKS_PART menu "$_luksnew" "\nSelect the partition you want to encrypt." $PARTS
2060 [[ $LUKS_PART ]] || return 1
2061 luks_pass "$_luksnew"
2066 luks_setup || return 1
2067 msg "$_luksnew" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2068 cryptsetup -q luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2069 errshow "cryptsetup -q luksFormat $LUKS_PART" || return 1
2070 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2071 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2072 LUKS='encrypted'; luks_show
2080 dlg cipher input "LUKS Encryption" "$_lukskey" "-s 512 -c aes-xts-plain64"
2081 [[ $cipher ]] || return 1
2082 msg "$_luksadv" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2083 cryptsetup -q $cipher luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2084 errshow "cryptsetup -q $cipher luksFormat $LUKS_PART" || return 1
2085 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2086 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2093 ###############################################################################
2095 # some help avoid repetition and improve usability of some commands
2096 # others are initial setup functions used before reaching the main loop
2100 [[ "$2" == *"$1"* ]] && printf "on" || printf "off"
2105 # cleanup and exit the installer cleanly with exit code $1
2106 local e="$1" # when e is 127 unmount /run/archiso/bootmnt and reboot
2110 if [[ -d $MNT ]]; then
2112 if (( e == 127 )); then
2113 umount_dir /run/archiso/bootmnt && sleep 0.5 && reboot -f
2121 local var="$1" # assign output from dialog to var
2122 local dlg_t="$2" # dialog type (menu, check, input)
2123 local title="$3" # dialog title
2124 local body="$4" # dialog message
2125 local n=0 # number of items to display for menu and check dialogs
2127 shift 4 # shift off args assigned above
2129 # adjust n when passed a large list
2130 local l=$((LINES - 20))
2131 (( ($# / 2) > l )) && n=$l
2135 menu) dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --menu "$body" 0 0 $n "$@" 2>"$ANS" || return 1 ;;
2136 check) dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --checklist "$body" 0 0 $n "$@" 2>"$ANS" || return 1 ;;
2139 local def="$1" # assign default value for input
2141 if [[ $1 == 'limit' ]]; then
2142 dialog --backtitle "$DIST Installer - $SYS - v$VER" --max-input 63 --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2144 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2148 # if answer file isn't empty read from it into $var
2149 [[ -s "$ANS" ]] && printf -v "$var" "%s" "$(< "$ANS")"
2154 # displays a message dialog
2155 # when more than 2 args the message will disappear after sleep time ($3)
2161 dialog --backtitle "$DIST Installer - $SYS - v$VER" --sleep "$1" --title " $title " --infobox "$body\n" 0 0
2163 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --msgbox "$body\n" 0 0
2171 if (( $# == 0 )); then
2172 msg "No Session" "\nRunning live requires a session to use.\n\nExiting..\n" 2
2175 elif ! select_keymap; then
2178 elif ! net_connect; then
2179 msg "Not Connected" "\nRunning live requires an active internet connection.\n\nExiting..\n" 2
2183 pacman -Syyu archlinux-keyring --needed --noconfirm || die 1
2184 pacman -S $AL_BASE_PKGS xorg-xinit xorg-server --needed --noconfirm || die 1
2188 pacman -S git --needed --noconfirm || die 1
2189 install_suckless "/root" nochroot
2191 i3-gaps|oepnbox|fluxbox|bspwm|awesome)
2192 pacman -S "$ses" $WM_BASE_PKGS ${WM_EXT[$ses]} xterm --needed --noconfirm || die 1
2194 gnome|plasma|cinnamon|xfce4)
2195 pacman -S "$ses" ${WM_EXT[$ses]} xterm --needed --noconfirm || die 1
2197 *) echo "error: invalid session for -l, --live, see -h, --help"; die 1 ;;
2200 pacman -Scc --noconfirm
2201 rm -rf "/var/cache/pacman/pkg/"*
2202 cp -rfT /etc/skel /root || die 1
2203 sed -i "/exec/ c exec ${WM_SESSIONS[$ses]}" /root/.xinitrc
2204 printf "\n%s has been set as the login session in ~/.xinitrc, to start the session simply run\n\n\tstartx\n\n" "${WM_SESSIONS[$ses]}"
2212 usage: $1 [-hdl] [session]
2215 -h, --help print this message and exit
2216 -l, --live install and setup a live session
2217 -d, --debug enable xtrace and log output to $DBG
2220 i3-gaps - A fork of i3wm with more features including gaps
2221 openbox - A lightweight, powerful, and highly configurable stacking wm
2222 dwm - A dynamic WM for X that manages windows in tiled, floating, or monocle layouts
2223 awesome - A customized Awesome WM session created by @elanapan
2224 bspwm - A tiling wm that represents windows as the leaves of a binary tree
2225 fluxbox - A lightweight and highly-configurable window manager
2226 gnome - A desktop environment that aims to be simple and easy to use
2227 cinnamon - A desktop environment combining traditional desktop with modern effects
2228 plasma - A kde software project currently comprising a full desktop environment
2229 xfce4 - A lightweight and modular desktop environment based on gtk+2/3
2233 set the DIST environment variable before launching the installer eg.
2239 set the EDITOR environment variable before launching the installer eg.
2249 local title="$1" body="$2" yes='Yes' no='No'
2250 (( $# >= 3 )) && yes="$3"
2251 (( $# >= 4 )) && no="$4"
2253 if (( $# == 5 )); then
2254 dialog --backtitle "$DIST Installer - $SYS - v$VER" --defaultno --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2256 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2262 arch-chroot "$MNT" bash -c "$1"
2267 export PS4='| ${BASH_SOURCE} LINE:${LINENO} FUNC:${FUNCNAME[0]:+ ${FUNCNAME[0]}()} |> '
2277 "\e]P0191919" # #191919
2278 "\e]P1D15355" # #D15355
2279 "\e]P2609960" # #609960
2280 "\e]P3FFCC66" # #FFCC66
2281 "\e]P4255A9B" # #255A9B
2282 "\e]P5AF86C8" # #AF86C8
2283 "\e]P62EC8D3" # #2EC8D3
2284 "\e]P7949494" # #949494
2285 "\e]P8191919" # #191919
2286 "\e]P9D15355" # #D15355
2287 "\e]PA609960" # #609960
2288 "\e]PBFF9157" # #FF9157
2289 "\e]PC4E88CF" # #4E88CF
2290 "\e]PDAF86C8" # #AF86C8
2291 "\e]PE2ec8d3" # #2ec8d3
2292 "\e]PFE1E1E1" # #E1E1E1
2295 [[ $TERM == 'linux' ]] && printf "%b" "${colors[@]}" && clear
2300 [ $? -eq 0 ] && return 0
2302 local fatal=0 err=""
2303 err="$(sed 's/[^[:print:]]//g; s/\[[0-9\;:]*\?m//g; s/==> //g; s/] ERROR:/]\nERROR:/g' "$ERR")"
2304 [[ -z $err ]] && err="no error message was found"
2306 (( $1 == 1 )) && { fatal=1; shift; }
2308 local txt="\nCommand: $1\n\n\n\nError: $err\n\n"
2310 if (( fatal )); then
2311 msg "Install Error" "${txt}Errors at this stage are fatal, the install cannot continue.\n"
2312 [[ -r $DBG && $TERM == 'linux' ]] && less "$DBG"
2316 msg "Install Error" "${txt}Errors at this stage are non-fatal and may be fixed or ignored depending on the error.\n"
2324 if (( $1 >= 0 )) && ! grep -qw "$MNT" /proc/mounts; then
2325 msg "Not Mounted" "\nPartition(s) must be mounted first.\n" 2
2327 elif [[ $1 -ge 1 && -z $BOOTLDR ]]; then
2328 msg "No Bootloader" "\nBootloader must be selected first.\n" 2
2330 elif [[ $1 -ge 2 && (-z $NEWUSER || -z $USER_PASS) ]]; then
2331 msg "No User" "\nA user must be created first.\n" 2
2333 elif [[ $1 -ge 3 && -z $CONFIG_DONE ]]; then
2334 msg "Not Configured" "\nSystem configuration must be done first.\n" 2
2337 (( i )) # return code
2342 mount | grep -q 'swap' && swapoff -a
2344 if [[ -d $dir ]] && mount | grep -q "on $dir "; then
2345 if ! umount "$dir" 2>/dev/null; then
2347 umount -f "$dir" 2>/dev/null || umount -l "$dir"
2355 msg "Network Connect" "\nVerifying network connection\n" 0
2356 curl -sIN --connect-timeout 5 'https://www.archlinux.org/' | sed '1q' | grep -q '200'
2361 if chk_connect; then
2363 elif hash nmtui >/dev/null 2>&1; then
2365 if [[ $TERM == 'linux' ]]; then
2366 printf "%b" "\e]P1191919" "\e]P4191919"
2368 printf "%b" "\e]P1D15355" "\e]P4255a9b"
2373 elif hash wifi-menu >dev/null 2>&1; then
2383 [[ $BG_PID ]] || return 0
2384 msg "Install Running" "\nA background install process is currently running.\n" 2
2390 IGNORE_DEV="$(lsblk -lno NAME,MOUNTPOINT | awk '/\/run\/archiso\/bootmnt/ {sub(/[1-9]/, ""); print $1}')"
2392 if [[ $IGNORE_DEV ]]; then
2393 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ && !'"/$IGNORE_DEV/"' {print "/dev/" $1 " " $2}')"
2395 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ {print "/dev/" $1 " " $2}')"
2398 if [[ -z $SYS_DEVS ]]; then
2399 msg "Device Error" "\nNo available devices...\n\nExiting..\n" 2
2404 while read -r line; do
2406 done <<< "$SYS_DEVS"
2413 # amd-ucode is not needed it's provided by linux-firmware
2414 # elif grep -q 'AuthenticAMD' /proc/cpuinfo; then
2416 elif grep -q 'GenuineIntel' /proc/cpuinfo; then
2420 modprobe -q efivarfs >/dev/null 2>&1
2422 _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."
2423 if [[ -d /sys/firmware/efi/efivars ]]; then
2425 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars
2426 _prep+="\n - An EFI boot partition mounted."
2430 _prep+="\n\nOnce finished mounting, a portion of the install can be done in the background while you continue configuring the system:\n"
2431 _prep+="\n - Choose the system bootloader.\n - Create a user and password."
2432 _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."
2435 ###############################################################################
2438 # enable some nicer colours in the linux console
2441 if (( UID != 0 )); then
2442 msg "Not Root" "\nThis installer must be run as root or using sudo.\n\nExiting..\n" 2
2444 elif ! grep -qwm 1 'lm' /proc/cpuinfo; then
2445 msg "Not x86_64 Architecture" "\nThis installer only supports x86_64 architectures.\n\nExiting..\n" 2
2449 -d|--debug) debug ;;
2450 -h|--help) usage "$0" ;;
2451 -l|--live) shift; live "$@" ;;
2455 # trap ^C to perform cleanup
2456 trap 'printf "\n^C\n" && die 1' INT
2461 msg "Welcome to the $DIST Installer" "$_welcome"
2463 if ! select_keymap; then
2465 elif ! net_connect; then
2466 msg "Not Connected" "\nThis installer requires an active internet connection.\n\nExiting..\n" 2
2474 # vim:fdm=marker:fmr={,}