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 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-icons archlabs-fonts archlabs-themes archlabs-baph "
31 AL_BASE_PKGS+="archlabs-wallpapers archlabs-scripts archlabs-skel-base"
33 WM_BASE_PKGS="arandr archlabs-networkmanager-dmenu nitrogen polkit-gnome "
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 (and 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
329 case $MYSHELL in bash) LOGINRC='.bash_profile' ;; zsh) LOGINRC='.zprofile' ;; mksh) LOGINRC='.profile' ;; esac
337 local v='' u='' p='' p2='' rp='' rp2=''
339 until [[ $NEWUSER ]]; do
342 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " User " --mixedform "$_user" 0 0 0 \
343 "Username:" 1 1 "$u" 1 11 "$COLUMNS" 0 0 \
344 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
345 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 \
346 "--- Root password, if left empty the user password will be used ---" 6 1 '' 6 68 "$COLUMNS" 0 2 \
347 "Password:" 8 1 '' 8 11 "$COLUMNS" 0 1 \
348 "Password2:" 9 1 '' 9 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
350 while read -r line; do
351 case $i in 0) u="$line" ;; 1) p="$line" ;; 2) p2="$line" ;; 4) rp="$line" ;; 5) rp2="$line" ;; esac
355 # root passwords empty, so use the user passwords
356 [[ -z $rp && -z $rp2 ]] && { rp="$p"; rp2="$p2"; }
358 # make sure a username was entered and that the passwords match
359 if [[ ${#u} -eq 0 || $u =~ \ |\' || $u =~ [^a-z0-9] ]]; then
360 msg "Invalid Username" "\nInvalid user name.\n\nPlease try again.\n"; u=''
361 elif [[ -z $p ]]; then
362 msg "Empty Password" "\nThe user password cannot be left empty.\n\nPlease try again.\n"
363 elif [[ "$p" != "$p2" ]]; then
364 msg "Password Mismatch" "\nThe user passwords do not match.\n\nPlease try again.\n"
365 elif [[ "$rp" != "$rp2" ]]; then
366 msg "Password Mismatch" "\nThe root passwords do not match.\n\nPlease try again.\n"
378 dlg KEYMAP menu "Keyboard Layout" "$_keymap" \
379 us English cm English gb English au English gh English \
380 za English ng English ca French 'cd' French gn French \
381 tg French fr French de German at German ch German \
382 es Spanish latam Spanish br Portuguese pt Portuguese ma Arabic \
383 sy Arabic ara Arabic ua Ukrainian cz Czech ru Russian \
384 sk Slovak nl Dutch it Italian hu Hungarian cn Chinese \
385 tw Taiwanese vn Vietnamese kr Korean jp Japanese th Thai \
386 la Lao pl Polish se Swedish is Icelandic 'fi' Finnish \
387 dk Danish be Belgian in Indian al Albanian am Armenian \
388 bd Bangla ba Bosnian 'bg' Bulgarian dz Berber mm Burmese \
389 hr Croatian gr Greek il Hebrew ir Persian iq Iraqi \
390 af Afghani fo Faroese ge Georgian ee Estonian kg Kyrgyz \
391 kz Kazakh lt Lithuanian mt Maltese mn Mongolian ro Romanian \
392 no Norwegian rs Serbian si Slovenian tj Tajik lk Sinhala \
393 tr Turkish uz Uzbek ie Irish pk Urdu 'mv' Dhivehi \
394 np Nepali et Amharic sn Wolof ml Bambara tz Swahili \
395 ke Swahili bw Tswana ph Filipino my Malay tm Turkmen \
396 id Indonesian bt Dzongkha lv Latvian md Moldavian mao Maori \
397 by Belarusian az Azerbaijani mk Macedonian kh Khmer epo Esperanto \
398 me Montenegrin || return 1
400 if [[ $CMAPS == *"$KEYMAP"* ]]; then
403 dlg CMAP menu "Console Keymap" "$_vconsole" $CMAPS || return 1
406 if [[ $TERM == 'linux' ]]; then
407 loadkeys "$CMAP" >/dev/null 2>&1
409 setxkbmap "$KEYMAP" >/dev/null 2>&1
418 dlg INSTALL_WMS check "Sessions" "$_sessions\n" \
419 openbox "A lightweight, powerful, and highly configurable stacking wm" "$(ofn openbox "${INSTALL_WMS[*]}")" \
420 i3-gaps "A fork of i3wm with more features including gaps" "$(ofn i3-gaps "${INSTALL_WMS[*]}")" \
421 dwm "A dynamic WM for X that manages windows in tiled, floating, or monocle layouts" "$(ofn dwm "${INSTALL_WMS[*]}")" \
422 bspwm "A tiling wm that represents windows as the leaves of a binary tree" "$(ofn bspwm "${INSTALL_WMS[*]}")" \
423 xfce4 "A lightweight and modular desktop environment based on gtk+2/3" "$(ofn xfce4 "${INSTALL_WMS[*]}")" \
424 awesome "A customized Awesome WM session created by @elanapan" "$(ofn awesome "${INSTALL_WMS[*]}")" \
425 fluxbox "A lightweight and highly-configurable window manager" "$(ofn fluxbox "${INSTALL_WMS[*]}")" \
426 plasma "A kde software project currently comprising a full desktop environment" "$(ofn plasma "${INSTALL_WMS[*]}")" \
427 gnome "A desktop environment that aims to be simple and easy to use" "$(ofn gnome "${INSTALL_WMS[*]}")" \
428 cinnamon "A desktop environment combining traditional desktop with modern effects" "$(ofn cinnamon "${INSTALL_WMS[*]}")"
430 [[ $INSTALL_WMS ]] || return 0
432 WM_PKGS="${INSTALL_WMS/dwm/}" # remove dwm from package list
433 WM_PKGS="${WM_PKGS// / }" # remove double spaces
434 WM_PKGS="${WM_PKGS# }" # remove leading space
436 for i in $INSTALL_WMS; do
437 LOGIN_CHOICES+="$i - "
438 [[ ${WM_EXT[$i]} && $WM_PKGS != *"${WM_EXT[$i]}"* ]] && WM_PKGS+=" ${WM_EXT[$i]}"
441 select_login || return 1
443 while IFS=' ' read -r pkg; do
444 [[ $PACKAGES != *"$pkg"* ]] && PACKAGES+=" $pkg"
452 dlg USER_PKGS check " Packages " "$_packages" \
453 abiword "A Fully-featured word processor" "$(ofn abiword "${USER_PKGS[*]}")" \
454 alacritty "A cross-platform, GPU-accelerated terminal emulator" "$(ofn alacritty "${USER_PKGS[*]}")" \
455 atom "An open-source text editor developed by GitHub" "$(ofn atom "${USER_PKGS[*]}")" \
456 audacious "A free and advanced audio player based on GTK+" "$(ofn audacious "${USER_PKGS[*]}")" \
457 audacity "A program that lets you manipulate digital audio waveforms" "$(ofn audacity "${USER_PKGS[*]}")" \
458 blueman "GUI bluetooth device manager" "$(ofn blueman "${USER_PKGS[*]}")" \
459 bluez "Simple CLI based bluetooth support" "$(ofn bluez "${USER_PKGS[*]}")" \
460 cairo-dock "Light eye-candy fully themable animated dock" "$(ofn cairo-dock "${USER_PKGS[*]}")" \
461 calligra "A set of applications for productivity" "$(ofn calligra "${USER_PKGS[*]}")" \
462 chromium "An open-source web browser based on the Blink rendering engine" "$(ofn chromium "${USER_PKGS[*]}")" \
463 clementine "A modern music player and library organizer" "$(ofn clementine "${USER_PKGS[*]}")" \
464 cmus "A small, fast and powerful console music player" "$(ofn cmus "${USER_PKGS[*]}")" \
465 deadbeef "A GTK+ audio player for GNU/Linux" "$(ofn deadbeef "${USER_PKGS[*]}")" \
466 deluge "A BitTorrent client written in python" "$(ofn deluge "${USER_PKGS[*]}")" \
467 emacs "An extensible, customizable, self-documenting real-time display editor" "$(ofn emacs "${USER_PKGS[*]}")" \
468 epiphany "A GNOME web browser based on the WebKit rendering engine" "$(ofn epiphany "${USER_PKGS[*]}")" \
469 evince "A document viewer" "$(ofn evince "${USER_PKGS[*]}")" \
470 evolution "Manage your email, contacts and schedule" "$(ofn evolution "${USER_PKGS[*]}")" \
471 file-roller "Create and modify archives" "$(ofn file-roller "${USER_PKGS[*]}")" \
472 firefox "A popular open-source web browser from Mozilla" "$(ofn firefox "${USER_PKGS[*]}")" \
473 gcolor2 "A simple GTK+2 color selector" "$(ofn gcolor2 "${USER_PKGS[*]}")" \
474 geany "A fast and lightweight IDE" "$(ofn geany "${USER_PKGS[*]}")" \
475 geary "A lightweight email client for the GNOME desktop" "$(ofn geary "${USER_PKGS[*]}")" \
476 gimp "GNU Image Manipulation Program" "$(ofn gimp "${USER_PKGS[*]}")" \
477 gnome-calculator "GNOME Scientific calculator" "$(ofn gnome-calculator "${USER_PKGS[*]}")" \
478 gnome-disk-utility "Disk Management Utility" "$(ofn gnome-disk-utility "${USER_PKGS[*]}")" \
479 gnome-system-monitor "View current processes and monitor system state" "$(ofn gnome-system-monitor "${USER_PKGS[*]}")" \
480 gparted "A GUI frontend for creating and manipulating partition tables" "$(ofn gparted "${USER_PKGS[*]}")" \
481 gpick "Advanced color picker using GTK+ toolkit" "$(ofn gpick "${USER_PKGS[*]}")" \
482 gpicview "Lightweight image viewer" "$(ofn gpicview "${USER_PKGS[*]}")" \
483 guvcview "Capture video from camera devices" "$(ofn guvcview "${USER_PKGS[*]}")" \
484 hexchat "A popular and easy to use graphical IRC client" "$(ofn hexchat "${USER_PKGS[*]}")" \
485 inkscape "Professional vector graphics editor" "$(ofn inkscape "${USER_PKGS[*]}")" \
486 irssi "Modular text mode IRC client" "$(ofn irssi "${USER_PKGS[*]}")" \
487 kdenlive "A popular non-linear video editor for Linux" "$(ofn kdenlive "${USER_PKGS[*]}")" \
488 krita "Edit and paint images" "$(ofn krita "${USER_PKGS[*]}")" \
489 libreoffice-fresh "Full featured office suite" "$(ofn libreoffice-fresh "${USER_PKGS[*]}")" \
490 lollypop "A new music playing application" "$(ofn lollypop "${USER_PKGS[*]}")" \
491 mousepad "A simple text editor" "$(ofn mousepad "${USER_PKGS[*]}")" \
492 mpd "A flexible, powerful, server-side application for playing music" "$(ofn mpd "${USER_PKGS[*]}")" \
493 mpv "A media player based on mplayer" "$(ofn mpv "${USER_PKGS[*]}")" \
494 mupdf "Lightweight PDF and XPS viewer" "$(ofn mupdf "${USER_PKGS[*]}")" \
495 mutt "Small but very powerful text-based mail client" "$(ofn mutt "${USER_PKGS[*]}")" \
496 nautilus "The default file manager for Gnome" "$(ofn nautilus "${USER_PKGS[*]}")" \
497 ncmpcpp "A mpd client and almost exact clone of ncmpc with some new features" "$(ofn ncmpcpp "${USER_PKGS[*]}")" \
498 neovim "A fork of Vim aiming to improve user experience, plugins, and GUIs." "$(ofn neovim "${USER_PKGS[*]}")" \
499 noto-fonts "Google Noto fonts" "$(ofn noto-fonts "${USER_PKGS[*]}")" \
500 noto-fonts-cjk "Google Noto CJK fonts (Chinese, Japanese, Korean)" "$(ofn noto-fonts-cjk "${USER_PKGS[*]}")" \
501 obs-studio "Free opensource streaming/recording software" "$(ofn obs-studio "${USER_PKGS[*]}")" \
502 openshot "An open-source, non-linear video editor for Linux" "$(ofn openshot "${USER_PKGS[*]}")" \
503 opera "A Fast and secure, free of charge web browser from Opera Software" "$(ofn opera "${USER_PKGS[*]}")" \
504 pcmanfm "A fast and lightweight file manager based in Lxde" "$(ofn pcmanfm "${USER_PKGS[*]}")" \
505 pidgin "Multi-protocol instant messaging client" "$(ofn pidgin "${USER_PKGS[*]}")" \
506 plank "An elegant, simple, and clean dock" "$(ofn plank "${USER_PKGS[*]}")" \
507 qbittorrent "An advanced BitTorrent client" "$(ofn qbittorrent "${USER_PKGS[*]}")" \
508 qpdfview "A tabbed PDF viewer" "$(ofn qpdfview "${USER_PKGS[*]}")" \
509 qt5ct "GUI for managing Qt based application themes, icons, and fonts" "$(ofn qt5ct "${USER_PKGS[*]}")" \
510 qutebrowser "A keyboard-focused vim-like web browser based on Python and PyQt5" "$(ofn qutebrowser "${USER_PKGS[*]}")" \
511 rhythmbox "A Music playback and management application" "$(ofn rhythmbox "${USER_PKGS[*]}")" \
512 rxvt-unicode "A unicode enabled rxvt-clone terminal emulator" "$(ofn rxvt-unicode "${USER_PKGS[*]}")" \
513 sakura "A terminal emulator based on GTK and VTE" "$(ofn sakura "${USER_PKGS[*]}")" \
514 simple-scan "Simple scanning utility" "$(ofn simple-scan "${USER_PKGS[*]}")" \
515 simplescreenrecorder "A feature-rich screen recorder" "$(ofn simplescreenrecorder "${USER_PKGS[*]}")" \
516 steam "A popular game distribution platform by Valve" "$(ofn steam "${USER_PKGS[*]}")" \
517 surf "A simple web browser based on WebKit2/GTK+" "$(ofn surf "${USER_PKGS[*]}")" \
518 terminator "Terminal emulator that supports tabs and grids" "$(ofn terminator "${USER_PKGS[*]}")" \
519 termite "A minimal VTE-based terminal emulator" "$(ofn termite "${USER_PKGS[*]}")" \
520 thunar "A modern file manager for the Xfce Desktop Environment" "$(ofn thunar "${USER_PKGS[*]}")" \
521 thunderbird "Standalone mail and news reader from mozilla" "$(ofn thunderbird "${USER_PKGS[*]}")" \
522 tilda "A GTK based drop down terminal for Linux and Unix" "$(ofn tilda "${USER_PKGS[*]}")" \
523 tilix "A tiling terminal emulator for Linux using GTK+ 3" "$(ofn tilix "${USER_PKGS[*]}")" \
524 transmission-cli "Free BitTorrent client CLI" "$(ofn transmission-cli "${USER_PKGS[*]}")" \
525 transmission-gtk "GTK+ Front end for transmission" "$(ofn transmission-gtk "${USER_PKGS[*]}")" \
526 transmission-qt "Qt Front end for transmission" "$(ofn transmission-qt "${USER_PKGS[*]}")" \
527 ttf-anonymous-pro "A family fixed-width fonts designed with code in mind" "$(ofn ttf-anonymous-pro "${USER_PKGS[*]}")" \
528 ttf-fira-code "Monospaced font with programming ligatures" "$(ofn ttf-fira-code "${USER_PKGS[*]}")" \
529 ttf-font-awesome "Iconic font designed for Bootstrap" "$(ofn ttf-font-awesome "${USER_PKGS[*]}")" \
530 ttf-hack "A hand groomed typeface based on Bitstream Vera Mono" "$(ofn ttf-hack "${USER_PKGS[*]}")" \
531 vlc "A free and open source cross-platform multimedia player" "$(ofn vlc "${USER_PKGS[*]}")" \
532 weechat "Fast, light and extensible IRC client" "$(ofn weechat "${USER_PKGS[*]}")" \
533 xapps "Common library for X-Apps project" "$(ofn xapps "${USER_PKGS[*]}")" \
534 xarchiver "A GTK+ frontend to various command line archivers" "$(ofn xarchiver "${USER_PKGS[*]}")" \
535 xed "A small and lightweight text editor. X-Apps Project." "$(ofn xed "${USER_PKGS[*]}")" \
536 xfce4-terminal "A terminal emulator based in the Xfce Desktop Environment" "$(ofn xfce4-terminal "${USER_PKGS[*]}")" \
537 xreader "Document viewer for files like PDF and Postscript. X-Apps Project." "$(ofn xed "${USER_PKGS[*]}")" \
538 xterm "The standard terminal emulator for the X window system" "$(ofn xterm "${USER_PKGS[*]}")" \
539 zathura "Minimalistic document viewer" "$(ofn zathura "${USER_PKGS[*]}")"
541 if [[ $USER_PKGS ]]; then # add any needed PKG_EXT to the list
542 for i in $USER_PKGS; do
543 [[ ${PKG_EXT[$i]} && $USER_PKGS != *"${PKG_EXT[$i]}"* ]] && USER_PKGS+=" ${PKG_EXT[$i]}"
550 ###############################################################################
552 # non-essential partitioning helpers called by the user when using the optional
553 # partition menu and selecting a device to edit
557 no_bg_install || return 0
558 local device choice devhash
559 devhash="$(lsblk -f | base64)"
561 part_device || return 1
566 dlg choice menu "Edit Partitions" "$_part" \
567 "auto" "Whole device automatic partitioning" \
568 "shrink" "Shrink an existing ext2/3/4 or ntfs partition to make room for a new partition" \
569 "cfdisk" "Curses based variant of fdisk" \
570 "parted" "GNU partition editor" \
571 "fdisk" "Dialog-driven creation and manipulation of partitions" \
572 "done" "Return to the main menu"
574 if [[ -z $choice || $choice == 'done' ]]; then
576 elif [[ $choice == 'shrink' ]]; then
577 part_shrink "$device"
578 elif [[ $choice == 'auto' ]]; then
579 local root_size txt table boot_fs
580 root_size=$(lsblk -lno SIZE "$device" | awk 'NR == 1 {
583 print ($1 * 1000 - 512) / 1000 "G"
589 txt="\nWARNING:\n\nALL data on $device will be destroyed and the following partitions will be created\n\n- "
590 if [[ $SYS == 'BIOS' ]]; then
591 table="msdos" boot_fs="ext4"
592 txt+="An $boot_fs boot partition with the boot flag enabled (512M)\n- "
594 table="gpt" boot_fs="fat32"
595 txt+="A $boot_fs efi boot partition (512M)\n- "
597 txt+="An ext4 partition using all remaining space ($root_size)\n\nDo you want to continue?\n"
598 yesno "Auto Partition" "$txt" && part_auto "$device" "$table" "$boot_fs" "$root_size"
604 if [[ $devhash != "$(lsblk -f | base64)" ]]; then
605 msg "Probing Partitions" "\nInforming kernel of partition changes using partprobe\n" 0
606 partprobe >/dev/null 2>&1
607 [[ $choice == 'auto' ]] && return
615 if [[ $IGNORE_DEV ]]; then
616 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk "!/$IGNORE_DEV/"' && /disk|part|lvm|crypt|NAME/')"
618 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk '/disk|part|lvm|crypt|NAME/')"
620 msg "Device Tree" "\n\n$txt\n\n"
625 local device="$1" table="$2" boot_fs="$3" size="$4" dev_info=""
626 dev_info="$(parted -s "$device" print)"
628 msg "Auto Partition" "\nRemoving partitions on $device and setting table to $table\n" 1
631 while read -r PART; do
632 parted -s "$device" rm "$PART" >/dev/null 2>&1
633 done <<< "$(awk '/^ [1-9][0-9]?/ {print $1}' <<< "$dev_info" | sort -r)"
635 [[ $(awk '/Table:/ {print $3}' <<< "$dev_info") != "$table" ]] && parted -s "$device" mklabel "$table" >/dev/null 2>&1
637 msg "Auto Partition" "\nCreating a 512M $boot_fs boot partition.\n" 1
638 if [[ $SYS == "BIOS" ]]; then
639 parted -s "$device" mkpart primary "$boot_fs" 1MiB 513MiB >/dev/null 2>&1
641 parted -s "$device" mkpart ESP "$boot_fs" 1MiB 513MiB >/dev/null 2>&1
646 AUTO_BOOT_PART=$(lsblk -lno NAME,TYPE "$device" | awk 'NR==2 {print "/dev/" $1}')
648 if [[ $SYS == "BIOS" ]]; then
649 mkfs.ext4 -q "$AUTO_BOOT_PART" >/dev/null 2>&1
651 mkfs.vfat -F32 "$AUTO_BOOT_PART" >/dev/null 2>&1
654 msg "Auto Partition" "\nCreating a $size ext4 root partition.\n" 0
655 parted -s "$device" mkpart primary ext4 513MiB 100% >/dev/null 2>&1
657 AUTO_ROOT_PART="$(lsblk -lno NAME,TYPE "$device" | awk 'NR==3 {print "/dev/" $1}')"
658 mkfs.ext4 -q "$AUTO_ROOT_PART" >/dev/null 2>&1
660 msg "Auto Partition" "\nProcess complete.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$device")\n"
667 local device="$1" fs=""
669 part_find "${device##*/}[^ ]" || return 1
670 (( COUNT == 1 )) && part="$(awk '{print $1}' <<< "${PARTS[@]}" )"
672 if (( COUNT == 1 )) || dlg part menu "Resize" "\nWhich partition on $device do you want to resize?" $PARTS; then
673 fs=$(lsblk -lno FSTYPE "$part")
676 msg "Resize" "\nGathering device size info.\n" 0
678 end=$(parted -s "$device" unit KiB print | awk '/^\s*'"$num"'/ {print $3}') # part size in KiB
679 devsize=$(parted -s "$device" unit KiB print | awk '/Disk '"${device//\//\\/}"':/ {print $3}') # whole device size in KiB
680 mount "$part" $MNT >/dev/null 2>&1; sleep 0.5
681 min=$(df --output=used --block-size=MiB "$part" | awk 'NR == 2 {print int($1) + 256}')
682 max=$(df --output=avail --block-size=MiB "$part" | awk 'NR == 2 {print int($1)}')
685 if dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Resize: $part " --rangebox "$_resize" 17 "$COLUMNS" "$min" "$max" $((max / 2)) 2>$ANS; then
687 size=$((size * 1024))
694 if ntfsresize -fc "$part"; then
695 ntfsresize -ff --size $(( (size * 1024) / 1000 ))k "$part" 2>$ERR # k=10^3 bytes
696 errshow "ntfsresize -f -s $(( (size * 1024) / 1000 ))k $part" || return 1
698 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"
703 e2fsck -f "$part"; sleep 0.5
704 resize2fs -f "$part" ${size}K 2>$ERR # K=2^10 bytes
705 errshow "resize2fs -f $part ${size}K" || return 1
709 parted "$device" resizepart "$num" ${size}KiB || return 1
712 if [[ $devsize == "$end" ]]; then
713 parted -s "$device" mkpart primary ext4 ${size}KiB 100% 2>$ERR
714 errshow "parted -s $device mkpart primary ext4 ${size}KiB 100%" || return 1
716 parted -s "$device" mkpart primary ext4 ${size}KiB ${end}KiB 2>$ERR
717 errshow "parted -s $device mkpart primary ext4 ${size}KiB ${end}KiB" || return 1
719 msg "Resize Complete" "\n$part has been successfully resized to $((size / 1024))M.\n" 1
721 "") msg "No Filesystem" "\nFor unformatted partitions, cfdisk can be used in the partition menu.\n" ;;
722 *) msg "Invalid Filesystem: $fs" "\nResizing only supports ext and ntfs.\n" ;;
727 ###############################################################################
728 # partition management functions
729 # these are helpers for use by other functions to do essential setup/teardown
733 local regexp="$1" err=''
735 # string of partitions as /TYPE/PART SIZE
736 if [[ $IGNORE_DEV ]]; then
737 PARTS="$(lsblk -lno TYPE,NAME,SIZE |
738 awk "/$regexp/"' && !'"/$IGNORE_DEV/"' {
739 sub(/^part/, "/dev/")
740 sub(/^lvm|^crypt/, "/dev/mapper/")
744 PARTS="$(lsblk -lno TYPE,NAME,SIZE |
746 sub(/^part/, "/dev/")
747 sub(/^lvm|^crypt/, "/dev/mapper/")
752 # number of partitions total
754 while read -r line; do
758 # ensure we have enough partitions for the system and action type
760 'part|lvm|crypt') [[ $COUNT -lt 1 || ($SYS == 'UEFI' && $COUNT -lt 2) ]] && err="$_errpart" ;;
761 'part|crypt') (( COUNT < 1 )) && err="$_lvmerr" ;;
762 'part|lvm') (( COUNT < 2 )) && err="$_lukserr" ;;
765 # if there aren't enough partitions show the relevant error message
766 [[ $err ]] && { msg "Not Enough Partitions" "$err" 2; return 1; }
773 if [[ $1 == "$MNT/swapfile" && $SWAP_SIZE ]]; then
774 fallocate -l $SWAP_SIZE "$1" 2>$ERR
775 errshow "fallocate -l $SWAP_SIZE $1"
776 chmod 600 "$1" 2>$ERR
777 errshow "chmod 600 $1"
779 mkswap "$1" >/dev/null 2>$ERR
781 swapon "$1" >/dev/null 2>$ERR
788 local part="$1" mountp="${MNT}$2" fs=""
789 fs="$(lsblk -lno FSTYPE "$part")"
792 if [[ $fs && ${FS_OPTS[$fs]} && $part != "$BOOT_PART" && $part != "$AUTO_ROOT_PART" ]] && select_mntopts "$fs"; then
793 mount -o "$MNT_OPTS" "$part" "$mountp" >/dev/null 2>&1
795 mount "$part" "$mountp" >/dev/null 2>&1
798 part_mountconf "$part" "$mountp" || return 1
806 local part="$1" fs="$2" delay="$3"
808 msg "Format" "\nFormatting $part as $fs\n" 0
809 mkfs.$fs ${FS_CMD_FLAGS[$fs]} "$part" >/dev/null 2>$ERR
810 errshow "mkfs.$fs ${FS_CMD_FLAGS[$fs]} "$part"" || return 1
817 if [[ $DEV_COUNT -eq 1 && $SYS_DEVS ]]; then
818 DEVICE="$(awk '{print $1}' <<< "$SYS_DEVS")"
819 elif (( DEV_COUNT > 1 )); then
821 dlg DEVICE menu "Boot Device" "\nSelect the device to use for bootloader install." $SYS_DEVS
823 dlg DEVICE menu "Select Device" "$_device" $SYS_DEVS
825 [[ $DEVICE ]] || return 1
826 elif [[ $DEV_COUNT -lt 1 && ! $1 ]]; then
827 msg "Device Error" "\nNo available devices.\n\nExiting..\n" 2
831 [[ $1 ]] && BOOT_DEV="$DEVICE"
838 BOOT_DEV="${BOOT_PART%[1-9]}"
839 BOOT_PART_NUM="${BOOT_PART: -1}"
840 [[ $BOOT_PART = /dev/nvme* ]] && BOOT_DEV="${BOOT_PART%p[1-9]}"
841 if [[ $SYS == 'UEFI' ]]; then
842 parted -s $BOOT_DEV set $BOOT_PART_NUM esp on >/dev/null 2>&1
844 parted -s $BOOT_DEV set $BOOT_PART_NUM boot on >/dev/null 2>&1
851 local part="$1" devs=""
852 devs="$(lsblk -lno NAME,FSTYPE,TYPE)"
854 # Identify if $part is LUKS+LVM, LVM+LUKS, LVM alone, or LUKS alone
855 if lsblk -lno TYPE "$part" | grep -q 'crypt'; then
857 LUKS_NAME="${part#/dev/mapper/}"
858 for dev in $(awk '/lvm/ && /crypto_LUKS/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
859 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
860 LUKS_DEV="$LUKS_DEV cryptdevice=$dev:$LUKS_NAME"
865 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
866 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
867 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
868 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
872 elif lsblk -lno TYPE "$part" | grep -q 'lvm'; then
874 VNAME="${part#/dev/mapper/}"
875 for dev in $(awk '/crypt/ && /lvm2_member/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
876 if lsblk -lno NAME "$dev" | grep -q "$VNAME"; then
877 LUKS_NAME="${dev/\/dev\/mapper\//}"
881 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
882 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
883 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
884 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
895 if (( COUNT > 0 )); then
896 PARTS="$(sed "/${pt//\//\\/}/d" <<< "$PARTS")"
904 if grep -qw "$1" /proc/mounts; then
905 msg "Mount Success" "\nPartition $1 mounted at $2\n" 1
909 msg "Mount Fail" "\nPartition $1 failed to mount at $2\n" 2
914 ###############################################################################
916 # mount_menu is the entry point which calls all other functions
917 # once finished it returns to the main menu: main()
921 msg "Info" "\nGathering device info.\n" 0
922 no_bg_install || return 0
925 part_find 'part|lvm|crypt' || { SEL=2; return 1; }
927 [[ $LUKS && $LUKS_PART ]] && part_countdec $LUKS_PART
928 [[ $LVM && $LVM_PARTS ]] && part_countdec $LVM_PARTS
930 select_root_partition || return 1
932 if [[ $SYS == 'UEFI' ]]; then
933 select_efi_partition || { BOOT_PART=''; return 1; }
934 elif (( COUNT > 0 )); then
935 select_boot_partition || { BOOT_PART=''; return 1; }
938 if [[ $BOOT_PART ]]; then
939 part_mount "$BOOT_PART" "/$BOOTDIR" && SEP_BOOT=true || return 1
943 select_swap || return 1
944 select_extra_partitions || return 1
952 dlg SWAP_PART menu "Swap Setup" "\nSelect whether to use a swapfile, swap partition, or none." \
953 "none" "Don't allocate any swap space" \
954 "swapfile" "Allocate $SYS_MEM at /swapfile" \
957 if [[ -z $SWAP_PART || $SWAP_PART == "none" ]]; then
960 elif [[ $SWAP_PART == "swapfile" ]]; then
962 until [[ ${SWAP_SIZE:0:1} =~ [1-9] && ${SWAP_SIZE: -1} =~ (M|G) ]]; do
963 (( 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
964 dlg SWAP_SIZE input "Swap Setup" "$_swapsize" "$SYS_MEM" || { SWAP_PART=''; SWAP_SIZE=''; return 1; }
967 part_swap "$MNT/$SWAP_PART"
968 SWAP_PART="/$SWAP_PART"
969 elif [[ $PARTS == *"$SWAP_PART"* ]]; then
971 part_countdec $SWAP_PART
972 SWAP_SIZE="$(lsblk -lno SIZE $SWAP_PART)"
982 local fs="$1" opts=''
983 local title="${fs^} Mount Options"
985 for i in ${FS_OPTS[$fs]}; do
989 until [[ $MNT_OPTS ]]; do
990 dlg MNT_OPTS check "$title" "$_mount" $opts
991 [[ $MNT_OPTS ]] || return 1
992 MNT_OPTS="${MNT_OPTS// /,}"
993 yesno "$title" "\nConfirm the following options: $MNT_OPTS\n" || MNT_OPTS=''
1002 until [[ $EXMNT ]]; do
1003 dlg EXMNT input "Extra Mount $part" "$_exmnt" "/" || return 1
1004 if [[ ${EXMNT:0:1} != "/" || ${#EXMNT} -le 1 || $EXMNT =~ \ |\' || $EXMNTS == *"$EXMNT"* ]]; then
1005 msg "Mountpoint Error" "$_errexpart"
1014 local part="$1" fs='' cur=''
1015 local txt="\nSelect which filesystem to use for: $part\n\nDefault: ext4"
1016 cur="$(lsblk -lno FSTYPE "$part" 2>/dev/null)"
1018 # bail early if the partition was created in part_auto()
1019 [[ $cur && $part == "$AUTO_ROOT_PART" ]] && return 0
1022 if [[ $cur && $FORMATTED == *"$part"* ]]; then
1023 dlg fs menu "Filesystem" "$txt\nCurrent: $cur" skip - ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1025 dlg fs menu "Filesystem" "$txt" ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1027 [[ $fs == 'skip' ]] && return 0
1028 yesno "Filesystem" "\nFormat $part as $fs?\n" || fs=''
1030 part_format "$part" "$fs"
1033 select_efi_partition()
1035 if [[ $AUTO_BOOT_PART ]]; then
1036 msg "EFI Boot Partition" "\nUsing partition created during automatic format.\n" 2
1037 BOOT_PART="$AUTO_BOOT_PART"
1038 return 0 # were done here
1040 local pts size dev isize bsize ptcount=0
1042 # walk partition list and skip ones that are too small/big for boot
1043 while read -r dev size; do
1044 size_t="${size: -1:1}" # size type eg. K, M, G, T
1045 isize=${size:0:-1} # remove trailing size type character
1046 isize=${isize%.*} # remove any decimal (round down)
1047 [[ $size_t =~ [KT] || ($size_t == 'G' && $isize -gt 2) || ($size_t == 'M' && $isize -lt 100) ]] || { pts+="$dev $size "; (( ptcount++ )); }
1050 if (( ptcount == 1 )); then
1051 msg "EFI Boot Partition" "\nOnly one partition available that meets size requirements.\n" 1
1052 BOOT_PART="$(awk 'NF > 0 {print $1}' <<< "$pts")"
1054 dlg BOOT_PART menu "EFI Partition" "$_uefi" $pts
1058 if [[ -z $BOOT_PART ]]; then
1060 elif grep -q 'fat' <<< "$(fsck -N "$BOOT_PART")"; then
1061 local txt="\nIMPORTANT:\n\nThe EFI partition $BOOT_PART $_format"
1062 if yesno "Format EFI Partition" "$txt" "Format $BOOT_PART" "Skip Formatting" 1; then
1063 part_format "$BOOT_PART" "vfat" 2
1066 part_format "$BOOT_PART" "vfat" 2
1072 select_boot_partition()
1074 if [[ $AUTO_BOOT_PART && ! $LVM ]]; then
1075 msg "Boot Partition" "\nUsing partition created during automatic format.\n" 2
1076 BOOT_PART="$AUTO_BOOT_PART"
1077 return 0 # were done here
1079 local pts size dev isize bsize ptcount=0
1081 # walk partition list and skip ones that are too small/big for boot
1082 while read -r dev size; do
1083 size_t="${size: -1:1}" # size type eg. K, M, G, T
1084 isize=${size:0:-1} # remove trailing size type character
1085 isize=${isize%.*} # remove any decimal (round down)
1086 [[ $size_t =~ [KT] || ($size_t == 'G' && $isize -gt 2) || ($size_t == 'M' && $isize -lt 100) ]] || { pts+="$dev $size "; (( ptcount++ )); }
1089 if [[ $LUKS && ! $LVM ]]; then
1090 dlg BOOT_PART menu "Boot Partition" "$_biosluks" $pts
1091 [[ $BOOT_PART ]] || return 1
1093 dlg BOOT_PART menu "Boot Partition" "$_bios" "skip" "don't use a separate boot" $pts
1094 [[ -z $BOOT_PART || $BOOT_PART == "skip" ]] && { BOOT_PART=''; return 0; }
1098 if grep -q 'ext[34]' <<< "$(fsck -N "$BOOT_PART")"; then
1099 local txt="\nIMPORTANT:\n\nThe boot partition $BOOT_PART $_format"
1100 if yesno "Format Boot Partition" "$txt" "Format $BOOT_PART" "Skip Formatting" 1; then
1101 part_format "$BOOT_PART" "ext4" 2
1104 part_format "$BOOT_PART" "ext4" 2
1109 select_root_partition()
1111 if [[ $AUTO_ROOT_PART && -z $LVM && -z $LUKS ]]; then
1112 ROOT_PART="$AUTO_ROOT_PART"
1113 msg "Root Partition (/)" "\nUsing partition created during automatic format.\n" 2
1114 part_mount "$ROOT_PART" || { ROOT_PART=''; return 1; }
1115 return 0 # we're done here
1117 local pts size dev isize bsize ptcount=0
1119 # walk partition list and skip ones that are too small for / (root)
1120 while read -r dev size; do
1121 size_t="${size: -1:1}" # size type eg. K, M, G, T
1122 isize=${size:0:-1} # remove trailing size type character
1123 isize=${isize%.*} # remove any decimal (round down)
1124 [[ $size_t =~ [MK] || ($size_t == 'G' && $isize -lt 4) ]] || { pts+="$dev $size "; (( ptcount++ )); }
1127 if (( ptcount == 1 )); then # only one available device
1128 msg "Root Partition (/)" "\nOnly one partition available that meets size requirements.\n" 2
1129 ROOT_PART="$(awk 'NF > 0 {print $1}' <<< "$pts")"
1131 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
1135 if [[ -z $ROOT_PART ]] || ! select_filesystem "$ROOT_PART" || ! part_mount "$ROOT_PART"; then
1143 select_extra_partitions()
1147 # walk partition list and skip ones that are too small to be usable
1148 while read -r dev size; do
1149 [[ ${size: -1:1} =~ [KM] ]] && part_countdec "$dev"
1152 while (( COUNT > 0 )); do
1154 dlg part menu 'Mount Extra' "$_expart" 'done' 'finish mounting step' $PARTS || break
1155 if [[ $part == 'done' ]]; then
1157 elif select_filesystem "$part" && select_mountpoint && part_mount "$part" "$EXMNT"; then
1158 EXMNTS+="$part: $EXMNT "
1159 [[ $EXMNT == '/usr' && $HOOKS != *usr* ]] && HOOKS="usr $HOOKS"
1167 ###############################################################################
1169 # main is the entry point which calls all other install functions, once
1170 # complete it shows a dialog to edit files on the new system before reboot
1175 genfstab -U $MNT >$MNT/etc/fstab 2>$ERR
1176 errshow 1 "genfstab -U $MNT >$MNT/etc/fstab"
1177 [[ -f $MNT/swapfile ]] && sed -i "s~${MNT}~~" $MNT/etc/fstab
1181 chrun "hwclock --systohc --utc" || chrun "hwclock --systohc --utc --directisa"
1184 chrun "chown -Rf $NEWUSER:users /home/$NEWUSER"
1187 dlg choice menu "Finalization" "$_edit" \
1188 finished "exit the installer and reboot" \
1189 keyboard "${EDIT_FILES[keyboard]}" \
1190 console "${EDIT_FILES[console]}" \
1191 locale "${EDIT_FILES[locale]}" \
1192 hostname "${EDIT_FILES[hostname]}" \
1193 sudoers "${EDIT_FILES[sudoers]}" \
1194 mkinitcpio "${EDIT_FILES[mkinitcpio]}" \
1195 fstab "${EDIT_FILES[fstab]}" \
1196 crypttab "${EDIT_FILES[crypttab]}" \
1197 bootloader "${EDIT_FILES[bootloader]}" \
1198 pacman "${EDIT_FILES[pacman]}" \
1199 login "${EDIT_FILES[login]}"
1201 if [[ -z $choice || $choice == 'finished' ]]; then
1202 [[ $DEBUG == true && -r $DBG ]] && $EDITOR $DBG
1206 for f in ${EDIT_FILES[$choice]}; do
1207 [[ -e ${MNT}$f ]] && exists+=" ${MNT}$f"
1209 if [[ $exists ]]; then
1212 msg "File Missing" "\nThe file(s) selected do not exist:\n\n${EDIT_FILES[$choice]}\n"
1222 while kill -0 $BG_PID 2>/dev/null; do
1223 clear; printf "\nA background install process is still running...\n"; sleep 1
1228 rm -rf $MNT/etc/mkinitcpio-archiso.conf
1229 find $MNT/usr/lib/initcpio -name 'archiso*' -type f -delete
1230 sed -i 's/#\(Storage=\)volatile/\1auto/' $MNT/etc/systemd/journald.conf
1231 find $MNT/boot -name '*-ucode.img' -delete
1233 [[ $DIST != "ArchLabs" ]] || sed -i "s/ArchLabs/$DIST/g" $MNT/etc/{lsb-release,os-release}
1236 find $MNT/etc/X11/xorg.conf.d/ -name '*.conf' -delete
1237 elif lspci | grep ' VGA ' | grep -q 'Intel'; then
1238 echo "Creating Intel VGA Tear Free config /etc/X11/xorg.conf.d/20-intel.conf"
1239 cat > $MNT/etc/X11/xorg.conf.d/20-intel.conf <<- EOF
1241 Identifier "Intel Graphics"
1243 Option "TearFree" "true"
1248 [[ -e /run/archiso/sfs/airootfs && $KERNEL == 'linux' ]] && cp -vf $RUN/x86_64/vmlinuz $MNT/boot/vmlinuz-linux
1249 [[ -d /etc/netctl ]] && cp -rfv /etc/netctl $MNT/etc/
1250 [[ -f /etc/resolv.conf ]] && cp -fv /etc/resolv.conf $MNT/etc/
1251 [[ -e /etc/NetworkManager/system-connections ]] && cp -rvf /etc/NetworkManager/system-connections $MNT/etc/NetworkManager/
1253 echo "LANG=$MYLOCALE" > $MNT/etc/locale.conf
1254 cp -fv $MNT/etc/locale.conf $MNT/etc/default/locale
1255 sed -i "s/#en_US.UTF-8/en_US.UTF-8/g; s/#${MYLOCALE}/${MYLOCALE}/g" $MNT/etc/locale.gen
1257 chrun "ln -svf /usr/share/zoneinfo/$ZONE/$SUBZ /etc/localtime"
1259 cat > $MNT/etc/X11/xorg.conf.d/00-keyboard.conf <<- EOF
1260 # Use localectl(1) to instruct systemd-localed to update it.
1261 Section "InputClass"
1262 Identifier "system-keyboard"
1263 MatchIsKeyboard "on"
1264 Option "XkbLayout" "$KEYMAP"
1268 cat > $MNT/etc/default/keyboard <<- EOF
1269 # KEYBOARD CONFIGURATION FILE
1270 # Consult the keyboard(5) manual page.
1277 printf "KEYMAP=%s\nFONT=%s\n" "$CMAP" "$FONT" > $MNT/etc/vconsole.conf
1278 echo "$MYHOST" > $MNT/etc/hostname
1279 cat > $MNT/etc/hosts <<- EOF
1282 ::1 localhost ip6-localhost ip6-loopback
1283 ff02::1 ip6-allnodes
1284 ff02::2 ip6-allrouters
1290 echo "Installing $BOOTLDR"
1292 if [[ $ROOT_PART == /dev/mapper* ]]; then
1293 ROOT_PART_ID="$ROOT_PART"
1295 local uuid_type="UUID"
1296 [[ $BOOTLDR =~ (systemd-boot|refind-efi|efistub) ]] && uuid_type="PARTUUID"
1297 ROOT_PART_ID="$uuid_type=$(blkid -s $uuid_type -o value $ROOT_PART)"
1300 if [[ $SYS == 'UEFI' ]]; then
1301 # remove our old install and generic BOOT/ dir
1302 find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname "$DIST" -type d -delete
1303 find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname 'BOOT' -type d -delete
1307 chrun "${BCMDS[$BOOTLDR]}" 2>$ERR
1308 errshow 1 "${BCMDS[$BOOTLDR]}"
1310 if [[ -d $MNT/hostrun ]]; then
1311 # cleanup the bind mounts we made earlier for the grub-probe module
1312 umount_dir $MNT/hostrun/{udev,lvm}
1313 rm -rf $MNT/hostrun >/dev/null 2>&1
1316 if [[ $SYS == 'UEFI' ]]; then
1317 # some UEFI firmware requires a generic esp/BOOT/BOOTX64.EFI
1318 mkdir -pv $MNT/$BOOTDIR/EFI/BOOT
1320 grub) cp -fv $MNT/$BOOTDIR/EFI/$DIST/grubx64.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI ;;
1321 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 ;;
1322 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
1323 cp -fv $MNT/$BOOTDIR/EFI/refind/refind_x64.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI ;;
1332 rm -f $MNT/root/.zshrc # remove welcome message from root zshrc
1334 chrun "chpasswd <<< 'root:$ROOT_PASS'" 2>$ERR
1335 errshow 1 "set root password"
1336 if [[ $MYSHELL != 'zsh' ]]; then # root uses zsh by default
1337 chrun "usermod -s /bin/$MYSHELL root" 2>$ERR
1338 errshow 1 "usermod -s /bin/$MYSHELL root"
1339 # copy the default mkshrc to /root if it was selected
1340 [[ $MYSHELL == 'mksh' ]] && cp -fv $MNT/etc/skel/.mkshrc $MNT/root/.mkshrc
1343 echo "Creating new user $NEWUSER and setting password"
1344 local groups='audio,floppy,log,network,rfkill,scanner,storage,optical,power,wheel'
1346 chrun "useradd -m -u 1000 -g users -G $groups -s /bin/$MYSHELL $NEWUSER" 2>$ERR
1347 errshow 1 "useradd -m -u 1000 -g users -G $groups -s /bin/$MYSHELL $NEWUSER"
1348 chrun "chpasswd <<< '$NEWUSER:$USER_PASS'" 2>$ERR
1349 errshow 1 "set $NEWUSER password"
1351 if [[ $INSTALL_WMS == *dwm* ]];then
1352 mkdir -pv "$MNT/home/$NEWUSER/suckless"
1353 for i in dwm dmenu st; do
1354 if chrun "git clone https://git.suckless.org/$i /home/$NEWUSER/suckless/$i"; then
1355 chrun "cd /home/$NEWUSER/suckless/$i; make prefix=/usr install; make clean"
1357 printf "failed to clone %s repo\n" "$i"
1362 [[ $MYSHELL != 'bash' ]] && rm -f "$MNT/home/$NEWUSER/.bash_profile"
1363 [[ $WM_PKGS == *xfce* ]] && echo 'volumeicon &' >> "$MNT/home/$NEWUSER/.xprofile"
1365 # remove some commands from ~/.xprofile when using KDE or Gnome as the login session
1366 if [[ $LOGIN_WM =~ (startkde|gnome-session) || ($LOGIN_TYPE != 'xinit' && $WM_PKGS =~ (plasma|gnome)) ]]; then
1367 sed -i '/super/d; /nitrogen/d; /compton/d' "$MNT/home/$NEWUSER/.xprofile" "$MNT/root/.xprofile"
1368 elif [[ $INSTALL_WMS == 'dwm' ]]; then
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 rm -rf "$serv" "$MNT/home/$NEWUSER/.xinitrc"
1386 chrun "systemctl enable $LOGIN_TYPE.service" 2>$ERR
1387 errshow 1 "systemctl enable $LOGIN_TYPE.service"
1388 ${LOGIN_TYPE}_config
1391 if [[ $INSTALL_WMS ]]; then
1392 sed -i "/exec/ c exec ${LOGIN_WM}" "$MNT/home/$NEWUSER/.xinitrc"
1393 elif [[ -e $MNT/home/$NEWUSER/.xinitrc ]]; then
1394 sed -i '/exec/d' "$MNT/home/$NEWUSER/.xinitrc"
1397 if [[ $AUTOLOGIN ]]; then
1398 sed -i "s/root/${NEWUSER}/g" $serv/autologin.conf
1399 cat > "$MNT/home/$NEWUSER/$LOGINRC" <<- EOF
1400 # automatically run startx when logging in on tty1
1401 [ -z "\$DISPLAY" ] && [ \$XDG_VTNR -eq 1 ] && startx
1412 local rmpkg="archlabs-installer "
1413 local inpkg="$PACKAGES $USER_PKGS $AL_BASE_PKGS "
1415 if [[ $MYSHELL == 'zsh' ]]; then
1416 inpkg+="zsh-completions "
1421 [[ $KERNEL != 'linux' ]] && rmpkg+='linux '
1423 if [[ $INSTALL_WMS == 'dwm' ]]; then
1424 inpkg+="nitrogen polkit-gnome xclip gnome-keyring dunst feh "
1426 [[ $INSTALL_WMS =~ ^(plasma|gnome|cinnamon)$ ]] || inpkg+="archlabs-ksuperkey "
1427 [[ $INSTALL_WMS =~ (openbox|bspwm|i3-gaps|fluxbox) ]] && inpkg+="$WM_BASE_PKGS "
1430 # update and install crucial packages first to avoid issues
1431 chrun "pacman -Syyu $KERNEL $BASE_PKGS ${LOGIN_PKGS[$LOGIN_TYPE]} $MYSHELL --noconfirm --needed" 2>$ERR
1432 errshow 1 "pacman -Syyu $KERNEL $BASE_PKGS ${LOGIN_PKGS[$LOGIN_TYPE]} $MYSHELL --noconfirm --needed"
1434 # remove the packages we don't want on the installed system
1435 chrun "pacman -Rnsc $rmpkg --noconfirm"
1437 # reinstalling iputils fixes the network issue for non-root users
1438 chrun "pacman -S iputils $UCODE --noconfirm"
1440 # install the packages chosen throughout the install
1441 chrun "pacman -S $inpkg --needed --noconfirm" 2>$ERR
1442 errshow 1 "pacman -S $inpkg --needed --noconfirm"
1444 # bootloader packages
1445 if [[ $BOOTLDR == 'grub' ]]; then
1446 [[ $SYS == 'UEFI' ]] && local efib="efibootmgr"
1447 chrun "pacman -S os-prober grub $efib --needed --noconfirm" 2>$ERR
1448 errshow 1 "pacman -S os-prober grub $efib --needed --noconfirm"
1449 elif [[ $BOOTLDR == 'refind-efi' ]]; then
1450 chrun "pacman -S refind-efi efibootmgr --needed --noconfirm" 2>$ERR
1451 errshow 1 "pacman -S refind-efi efibootmgr --needed --noconfirm"
1452 elif [[ $SYS == 'UEFI' ]]; then
1453 chrun "pacman -S efibootmgr --needed --noconfirm" 2>$ERR
1454 errshow 1 "pacman -S efibootmgr --needed --noconfirm"
1457 # allow members of the wheel group to run commands as root
1458 sed -i "s/# %wheel ALL=(ALL) ALL/%wheel ALL=(ALL) ALL/g" $MNT/etc/sudoers
1463 install_mkinitcpio()
1466 [[ $LUKS ]] && add="encrypt"
1467 [[ $LVM ]] && { [[ $add ]] && add+=" lvm2" || add+="lvm2"; }
1468 sed -i "s/block filesystems/block ${add} filesystems ${HOOKS}/g" $MNT/etc/mkinitcpio.conf
1469 chrun "mkinitcpio -p $KERNEL" 2>$ERR
1470 errshow 1 "mkinitcpio -p $KERNEL"
1473 install_mirrorlist()
1475 if hash reflector >/dev/null 2>&1; then
1476 reflector --verbose --score 80 -l 40 -f 5 --sort rate --save "$1"
1477 elif hash rankmirrors >/dev/null 2>&1; then
1478 echo "Sorting mirrorlist"
1479 local key="access_key=5f29642060ab983b31fdf4c2935d8c56"
1480 ip_add="$(curl -fsSL "http://api.ipstack.com/check&?$key&fields=ip" | python -c "import sys, json; print(json.load(sys.stdin)['ip'])")"
1481 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'])")"
1482 if [[ "$country" ]]; then
1483 if [[ $country =~ (CA|US) ]]; then
1484 # use both CA and US mirrors for CA or US countries
1485 mirror="https://www.archlinux.org/mirrorlist/?country=US&country=CA&use_mirror_status=on"
1486 elif [[ $country =~ (AU|NZ) ]]; then
1487 # use both AU and NZ mirrors for AU or NZ countries
1488 mirror="https://www.archlinux.org/mirrorlist/?country=AU&country=NZ&use_mirror_status=on"
1490 mirror="https://www.archlinux.org/mirrorlist/?country=${country}&use_mirror_status=on"
1492 else # no country code so just grab all mirrors, will be a very slow sort but we don't have other options
1493 mirror="https://www.archlinux.org/mirrorlist/?country=all&use_mirror_status=on"
1495 curl -fsSL "$mirror" | sed -e 's/^#Server/Server/' -e '/^#/d' | rankmirrors -n 6 - >"$1"
1501 install_background()
1503 ( rsync -a /run/archiso/sfs/airootfs/ $MNT/ && install_mirrorlist "$MNT/etc/pacman.d/mirrorlist" >/dev/null 2>&1 ) &
1505 trap "kill $BG_PID 2>/dev/null" EXIT
1508 ###############################################################################
1509 # display manager config
1510 # these are called based on which DM is chosen after it is installed
1511 # additional config can be handled here, for now only lightdm has one
1515 cat > $MNT/etc/lightdm/lightdm-gtk-greeter.conf <<- EOF
1517 default-user-image=/usr/share/icons/ArchLabs-Dark/64x64/places/distributor-logo-archlabs.png
1518 background=/usr/share/backgrounds/archlabs/archlabs.jpg
1519 theme-name=Adwaita-dark
1520 icon-theme-name=Adwaita
1521 font-name=DejaVu Sans Mono 11
1522 position=30%,end 50%,end
1541 ###############################################################################
1543 # prerun_* set up the configs needed before actually running the commands
1544 # setup_* are run after selecting a bootloader and build the command used later
1545 # they can also be used for further user input as these run before control is taken away
1549 EDIT_FILES[bootloader]="/etc/default/grub"
1551 if [[ $SYS == 'BIOS' ]]; then
1552 [[ $BOOT_DEV ]] || { part_device 1 || return 1; }
1553 BCMDS[grub]="grub-install --recheck --force --target=i386-pc $BOOT_DEV"
1555 BCMDS[grub]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1556 grub-install --recheck --force --target=x86_64-efi --efi-directory=/$BOOTDIR --bootloader-id=$DIST"
1557 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1560 BCMDS[grub]="mkdir -p /run/udev /run/lvm &&
1561 mount --bind /hostrun/udev /run/udev &&
1562 mount --bind /hostrun/lvm /run/lvm &&
1564 grub-mkconfig -o /boot/grub/grub.cfg &&
1565 sleep 1 && umount /run/udev /run/lvm"
1572 sed -i "s/GRUB_DISTRIBUTOR=.*/GRUB_DISTRIBUTOR=\"${DIST}\"/g; s/GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT=\"\"/g" $MNT/etc/default/grub
1574 if [[ $LUKS_DEV ]]; then
1575 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
1576 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"
1579 if [[ $SYS == 'BIOS' && $LVM && -z $SEP_BOOT ]]; then
1580 sed -i "s/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g" $MNT/etc/default/grub 2>$ERR
1581 errshow 1 "sed -i 's/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g' $MNT/etc/default/grub"
1584 # setup for os-prober module
1585 mkdir -p /run/{lvm,udev} $MNT/hostrun/{lvm,udev}
1586 mount --bind /run/lvm $MNT/hostrun/lvm
1587 mount --bind /run/udev $MNT/hostrun/udev
1594 EDIT_FILES[bootloader]=""
1599 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1600 efibootmgr -v -d $BOOT_DEV -p $BOOT_PART_NUM -c -L '${DIST} Linux' -l /vmlinuz-${KERNEL} \
1601 -u 'root=$ROOT_PART_ID rw $([[ $UCODE ]] && printf 'initrd=\%s.img ' "$UCODE")initrd=\initramfs-${KERNEL}.img'"
1606 if [[ $SYS == 'BIOS' ]]; then
1607 EDIT_FILES[bootloader]="/boot/syslinux/syslinux.cfg"
1609 EDIT_FILES[bootloader]="/boot/EFI/syslinux/syslinux.cfg"
1610 BCMDS[syslinux]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1611 efibootmgr -v -c -d $BOOT_DEV -p $BOOT_PART_NUM -l /EFI/syslinux/syslinux.efi -L $DIST"
1617 local c="$MNT/boot/syslinux" s="/usr/lib/syslinux/bios" d=".."
1618 [[ $SYS == 'UEFI' ]] && { c="$MNT/boot/EFI/syslinux"; s="/usr/lib/syslinux/efi64"; d=''; }
1621 cp -rfv "$s/"* "$c/"
1622 cat > "$c/syslinux.cfg" <<- EOF
1625 MENU TITLE $DIST Boot Menu
1630 MENU LABEL $DIST Linux
1631 LINUX $d/vmlinuz-$KERNEL
1632 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1633 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL.img
1635 LABEL ${DIST}fallback
1636 MENU LABEL $DIST Linux Fallback
1637 LINUX $d/vmlinuz-$KERNEL
1638 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1639 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL-fallback.img
1646 EDIT_FILES[bootloader]="/boot/refind_linux.conf"
1647 BCMDS[refind-efi]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1; refind-install"
1652 cat > $MNT/boot/refind_linux.conf <<- EOF
1653 "$DIST Linux" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] &&
1654 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1655 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL.img"
1656 "$DIST Linux Fallback" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] &&
1657 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1658 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL-fallback.img"
1660 mkdir -p $MNT/etc/pacman.d/hooks
1661 cat > $MNT/etc/pacman.d/hooks/refind.hook <<- EOF
1668 Description = Updating rEFInd on ESP
1669 When = PostTransaction
1670 Exec = /usr/bin/refind-install
1674 setup_systemd-boot()
1676 EDIT_FILES[bootloader]="/boot/loader/entries/$DIST.conf"
1677 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1; bootctl --path=/boot install"
1680 prerun_systemd-boot()
1682 mkdir -p $MNT/boot/loader/entries
1683 cat > $MNT/boot/loader/loader.conf <<- EOF
1688 cat > $MNT/boot/loader/entries/$DIST.conf <<- EOF
1690 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1691 initrd /initramfs-$KERNEL.img
1692 options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1694 cat > $MNT/boot/loader/entries/$DIST-fallback.conf <<- EOF
1695 title $DIST Linux Fallback
1696 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1697 initrd /initramfs-$KERNEL-fallback.img
1698 options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1700 mkdir -p $MNT/etc/pacman.d/hooks
1701 cat > $MNT/etc/pacman.d/hooks/systemd-boot.hook <<- EOF
1708 Description = Updating systemd-boot
1709 When = PostTransaction
1710 Exec = /usr/bin/bootctl update
1712 systemd-machine-id-setup --root="$MNT"
1716 ###############################################################################
1721 msg "Info" "\nGathering device info.\n" 0
1722 no_bg_install || return 1
1726 dlg choice menu "Logical Volume Management" "$_lvmmenu" \
1727 "$_lvmnew" "vgcreate -f, lvcreate -L -n" \
1728 "$_lvmdel" "vgremove -f" \
1729 "$_lvmdelall" "lvrmeove, vgremove, pvremove -f" \
1730 "Back" "Return to the main menu"
1732 "$_lvmnew") lvm_create && break ;;
1733 "$_lvmdel") lvm_delgroup && yesno "$_lvmdel" "$_lvmdelask" && vgremove -f "$DEL_VG" >/dev/null 2>&1 ;;
1734 "$_lvmdelall") lvm_del_all ;;
1745 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
1746 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
1747 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
1749 if [[ $VGROUP && $v && $pv ]]; then
1750 msg "LVM Setup" "\nActivating existing logical volume management.\n" 0
1751 modprobe dm-mod >/dev/null 2>$ERR
1752 errshow 'modprobe dm-mod'
1753 vgscan >/dev/null 2>&1
1754 vgchange -ay >/dev/null 2>&1
1760 VGROUP='' LVM_PARTS='' VGROUP_MB=0
1762 lvm_mkgroup || return 1
1763 local txt="\nThe last (or only) logical volume will automatically use all remaining space in the volume group."
1764 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 -
1765 [[ $VOL_COUNT ]] || return 1
1766 lvm_extra_lvs || return 1
1767 lvm_volume_name "$_lvmlvname\nNOTE: This LV will use up all remaining space in the volume group (${VGROUP_MB}MB)" || return 1
1768 msg "$_lvmnew (LV:$VOL_COUNT)" "\nCreating volume $VNAME from remaining space in $VGROUP\n" 0
1769 lvcreate -l +100%FREE "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
1770 errshow "lvcreate -l +100%FREE $VGROUP -n $VNAME" || return 1
1771 LVM='logical volume'; sleep 0.5
1772 txt="\nDone, volume: $VGROUP-$VNAME (${VOLUME_SIZE:-${VGROUP_MB}MB}) has been created.\n"
1773 msg "$_lvmnew (LV:$VOL_COUNT)" "$txt\n$(lsblk -o NAME,MODEL,TYPE,FSTYPE,SIZE $LVM_PARTS)\n"
1779 local txt="${VGROUP}: ${SIZE}$SIZE_UNIT (${VGROUP_MB}MB remaining).$_lvmlvsize"
1783 dlg VOLUME_SIZE input "$_lvmnew (LV:$VOL_COUNT)" "$txt" ''
1784 if [[ -z $VOLUME_SIZE ]]; then
1786 break # allow bailing with escape or an empty choice
1787 elif (( ${VOLUME_SIZE:0:1} == 0 )); then
1788 ERR_SIZE=1 # size values can't begin with '0'
1790 # walk the string and make sure all but the last char are digits
1791 local lv=$((${#VOLUME_SIZE} - 1))
1792 for (( i=0; i<lv; i++ )); do
1793 [[ ${VOLUME_SIZE:$i:1} =~ [0-9] ]] || { ERR_SIZE=1; break; }
1795 if (( ERR_SIZE != 1 )); then
1796 case ${VOLUME_SIZE:$lv:1} in
1797 [mMgG]) local s=${VOLUME_SIZE:0:$lv} m=$((s * 1000))
1798 case ${VOLUME_SIZE:$lv:1} in
1799 [Gg]) (( m >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - m)) ;;
1800 [Mm]) (( ${VOLUME_SIZE:0:$lv} >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - s)) ;;
1807 if (( ERR_SIZE )); then
1808 msg "Invalid Logical Volume Size" "$_lvmerrlvsize"
1821 until [[ $named ]]; do
1822 lvm_partitions || return 1
1823 lvm_group_name || return 1
1824 yesno "$_lvmnew" "\nCreate volume group: $VGROUP\n\nusing these partition(s): $LVM_PARTS\n" && named=true
1827 msg "$_lvmnew" "\nCreating volume group: $VGROUP\n" 0
1828 vgcreate -f "$VGROUP" $LVM_PARTS >/dev/null 2>$ERR
1829 errshow "vgcreate -f $VGROUP $LVM_PARTS" || return 1
1831 SIZE=$(vgdisplay "$VGROUP" | awk '/VG Size/ { gsub(/[^0-9.]/, ""); print int($0) }')
1832 SIZE_UNIT="$(vgdisplay "$VGROUP" | awk '/VG Size/ { print substr($NF, 0, 1) }')"
1834 if [[ $SIZE_UNIT == 'G' ]]; then
1835 VGROUP_MB=$((SIZE * 1000))
1840 msg "$_lvmnew" "\nVolume group $VGROUP (${SIZE}$SIZE_UNIT) successfully created\n"
1846 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
1847 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
1848 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
1850 if [[ $VGROUP || $v || $pv ]]; then
1851 if yesno "$_lvmdelall" "$_lvmdelask"; then
1852 for i in $v; do lvremove -f "/dev/mapper/$i" >/dev/null 2>&1; done
1853 for i in $VGROUP; do vgremove -f "$i" >/dev/null 2>&1; done
1854 for i in $pv; do pvremove -f "$i" >/dev/null 2>&1; done
1858 msg "Delete LVM" "\nNo LVMs to remove...\n" 2
1868 for i in $(lvs --noheadings | awk '{print $2}' | uniq); do
1869 VOL_GROUP_LIST+="$i $(vgdisplay "$i" | awk '/VG Size/ {print $3$4}') "
1872 [[ $VOL_GROUP_LIST ]] || { msg "No Groups" "\nNo volume groups found."; return 1; }
1874 dlg DEL_VG menu "Logical Volume Management" "\nSelect volume group to delete.\n\nAll logical volumes within will also be deleted." $VOL_GROUP_LIST
1880 while (( VOL_COUNT > 1 )); do
1881 lvm_volume_name "$_lvmlvname" && lvm_lv_size || return 1
1882 msg "$_lvmnew (LV:$VOL_COUNT)" "\nCreating a $VOLUME_SIZE volume $VNAME in $VGROUP\n" 0
1883 lvcreate -L "$VOLUME_SIZE" "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
1884 errshow "lvcreate -L $VOLUME_SIZE $VGROUP -n $VNAME" || return 1
1885 msg "$_lvmnew (LV:$VOL_COUNT)" "\nDone, logical volume (LV) $VNAME ($VOLUME_SIZE) has been created.\n"
1893 part_find 'part|crypt' || return 1
1894 PARTS="$(awk 'NF > 0 {print $0 " off"}' <<< "$PARTS")"
1895 dlg LVM_PARTS check "$_lvmnew" "\nSelect the partition(s) to use for the physical volume (PV)." $PARTS
1902 until [[ $VGROUP ]]; do
1903 dlg VGROUP input "$_lvmnew" "$_lvmvgname" "lvgroup"
1904 if [[ -z $VGROUP ]]; then
1906 elif [[ ${VGROUP:0:1} == "/" || $VGROUP =~ \ |\' ]] || vgdisplay | grep -q "$VGROUP"; then
1907 msg "LVM Name Error" "$_lvmerrvgname"
1917 local txt="$1" default="mainvolume"
1918 (( VOL_COUNT > 1 )) && default="extvolume$VOL_COUNT"
1919 until [[ $VNAME ]]; do
1920 dlg VNAME input "$_lvmnew (LV:$VOL_COUNT)" "\n$txt" "$default"
1921 if [[ -z $VNAME ]]; then
1923 elif [[ ${VNAME:0:1} == "/" || $VNAME =~ \ |\' ]] || lsblk | grep -q "$VNAME"; then
1924 msg "LVM Name Error" "$_lvmerlvname"
1931 ###############################################################################
1937 no_bg_install || return 1
1938 dlg choice menu "LUKS Encryption" "$_luksmenu" \
1939 "$_luksnew" "cryptsetup -q luksFormat" \
1940 "$_luksopen" "cryptsetup open --type luks" \
1941 "$_luksadv" "cryptsetup -q -s -c luksFormat" \
1942 "Back" "Return to the main menu"
1945 "$_luksnew") luks_basic || return 1 ;;
1946 "$_luksopen") luks_open || return 1 ;;
1947 "$_luksadv") luks_advanced || return 1 ;;
1955 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
1957 part_find 'part|crypt|lvm' || return 1
1959 if (( COUNT == 1 )); then
1960 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
1962 dlg LUKS_PART menu "$_luksopen" "\nSelect which partition to open." $PARTS
1965 [[ $LUKS_PART ]] || return 1
1967 luks_pass "$_luksopen" || return 1
1968 msg "$_luksopen" "\nOpening encrypted partition: $LUKS_NAME\n\nUsing device/volume: $LUKS_PART\n" 0
1969 cryptsetup open --type luks "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
1970 errshow "cryptsetup open --type luks $LUKS_PART $LUKS_NAME" || return 1
1971 LUKS='encrypted'; luks_show
1978 local t="$1" n='' p='' p2=''
1980 until [[ $LUKS_PASS ]]; do
1983 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " $t " --mixedform "$_luksomenu" 0 0 0 \
1984 "Name:" 1 1 "${LUKS_NAME:-cryptroot}" 1 7 "$COLUMNS" 0 0 \
1985 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
1986 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
1988 while read -r line; do
1997 if [[ -z $n ]]; then
1998 msg "Name Empty" "\nEncrypted device name cannot be empty.\n\nPlease try again.\n" 2
1999 elif [[ -z $p || "$p" != "$p2" ]]; then
2001 msg "Password Mismatch" "\nThe passwords entered do not match.\n\nPlease try again.\n" 2
2003 LUKS_NAME="$n" LUKS_PASS="$p"
2013 msg "$_luksnew" "\nEncrypted partition ready for mounting.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$LUKS_PART")\n\n"
2018 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
2020 part_find 'part|lvm' || return 1
2022 if [[ $AUTO_ROOT_PART ]]; then
2023 LUKS_PART="$AUTO_ROOT_PART"
2024 elif (( COUNT == 1 )); then
2025 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2027 dlg LUKS_PART menu "$_luksnew" "\nSelect the partition you want to encrypt." $PARTS
2030 [[ $LUKS_PART ]] || return 1
2031 luks_pass "$_luksnew"
2036 luks_setup || return 1
2037 msg "$_luksnew" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2038 cryptsetup -q luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2039 errshow "cryptsetup -q luksFormat $LUKS_PART" || return 1
2040 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2041 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2042 LUKS='encrypted'; luks_show
2050 dlg cipher input "LUKS Encryption" "$_lukskey" "-s 512 -c aes-xts-plain64"
2051 [[ $cipher ]] || return 1
2052 msg "$_luksadv" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2053 cryptsetup -q $cipher luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2054 errshow "cryptsetup -q $cipher luksFormat $LUKS_PART" || return 1
2055 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2056 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2063 ###############################################################################
2065 # some help avoid repetition and improve usability of some commands
2066 # others are initial setup functions used before reaching the main loop
2070 [[ "$2" == *"$1"* ]] && printf "on" || printf "off"
2075 # cleanup and exit the installer cleanly with exit code $1
2076 local e="$1" # when e is 127 unmount /run/archiso/bootmnt and reboot
2080 if [[ -d $MNT ]]; then
2082 if (( e == 127 )); then
2083 umount_dir /run/archiso/bootmnt && sleep 0.5 && reboot -f
2091 local var="$1" # assign output from dialog to var
2092 local dlg_t="$2" # dialog type (menu, check, input)
2093 local title="$3" # dialog title
2094 local body="$4" # dialog message
2095 local n=0 # number of items to display for menu and check dialogs
2097 shift 4 # shift off args assigned above
2099 # adjust n when passed a large list
2100 local l=$((LINES - 20))
2101 (( ($# / 2) > l )) && n=$l
2105 menu) dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --menu "$body" 0 0 $n "$@" 2>"$ANS" || return 1 ;;
2106 check) dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --checklist "$body" 0 0 $n "$@" 2>"$ANS" || return 1 ;;
2109 local def="$1" # assign default value for input
2111 if [[ $1 == 'limit' ]]; then
2112 dialog --backtitle "$DIST Installer - $SYS - v$VER" --max-input 63 --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2114 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2118 # if answer file isn't empty read from it into $var
2119 [[ -s "$ANS" ]] && printf -v "$var" "%s" "$(< "$ANS")"
2124 # displays a message dialog
2125 # when more than 2 args the message will disappear after sleep time ($3)
2131 dialog --backtitle "$DIST Installer - $SYS - v$VER" --sleep "$1" --title " $title " --infobox "$body\n" 0 0
2133 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --msgbox "$body\n" 0 0
2141 if ! select_keymap; then
2144 elif ! net_connect; then
2145 msg "Not Connected" "\nRunning live requires an active internet connection.\n\nExiting..\n" 2
2149 pacman -Syyu --noconfirm || die 1
2150 pacman -S $AL_BASE_PKGS $WM_BASE_PKGS xorg-xinit xorg-server --needed --noconfirm || die 1
2154 pacman -S git --needed --noconfirm || die 1
2155 mkdir -pv /root/suckless
2156 for i in dwm dmenu st; do
2157 git clone https://git.suckless.org/$i /root/suckless/$i && cd /root/suckless/$i && make PREFIX=/usr install
2160 i3-gaps|oepnbox|fluxbox|bspwm|xfce4|gnome|plasma|cinnamon|awesome)
2161 pacman -S "$ses" ${WM_EXT[$ses]} xterm --needed --noconfirm || die 1
2163 *) echo "error: invalid session for -l, --live, see -h, --help"; die 1 ;;
2166 pacman -Scc --noconfirm
2167 rm -rf "/var/cache/pacman/pkg/"*
2168 cp -rfT /etc/skel /root || die 1
2169 sed -i "/exec/ c exec ${WM_SESSIONS[$ses]}" /root/.xinitrc
2170 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]}"
2178 usage: $1 [-hdl] [session]
2181 -h, --help print this message and exit
2182 -l, --live install and setup a live session
2183 -d, --debug enable debugging and log output to $DBG
2186 i3-gaps - A fork of i3wm with more features including gaps
2187 openbox - A lightweight, powerful, and highly configurable stacking wm
2188 dwm - A dynamic WM for X that manages windows in tiled, floating, or monocle layouts
2189 awesome - A customized Awesome WM session created by @elanapan
2190 bspwm - A tiling wm that represents windows as the leaves of a binary tree
2191 fluxbox - A lightweight and highly-configurable window manager
2192 gnome - A desktop environment that aims to be simple and easy to use
2193 cinnamon - A desktop environment combining traditional desktop with modern effects
2194 plasma - A kde software project currently comprising a full desktop environment
2195 xfce4 - A lightweight and modular desktop environment based on gtk+2/3
2203 local title="$1" body="$2" yes='Yes' no='No'
2204 (( $# >= 3 )) && yes="$3"
2205 (( $# >= 4 )) && no="$4"
2207 if (( $# == 5 )); then
2208 dialog --backtitle "$DIST Installer - $SYS - v$VER" --defaultno --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2210 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2216 arch-chroot "$MNT" bash -c "$1"
2221 export PS4='| ${BASH_SOURCE} LINE:${LINENO} FUNC:${FUNCNAME[0]:+ ${FUNCNAME[0]}()} |> '
2231 "\e]P0191919" # #191919
2232 "\e]P1D15355" # #D15355
2233 "\e]P2609960" # #609960
2234 "\e]P3FFCC66" # #FFCC66
2235 "\e]P4255A9B" # #255A9B
2236 "\e]P5AF86C8" # #AF86C8
2237 "\e]P62EC8D3" # #2EC8D3
2238 "\e]P7949494" # #949494
2239 "\e]P8191919" # #191919
2240 "\e]P9D15355" # #D15355
2241 "\e]PA609960" # #609960
2242 "\e]PBFF9157" # #FF9157
2243 "\e]PC4E88CF" # #4E88CF
2244 "\e]PDAF86C8" # #AF86C8
2245 "\e]PE2ec8d3" # #2ec8d3
2246 "\e]PFE1E1E1" # #E1E1E1
2249 [[ $TERM == 'linux' ]] && printf "%b" "${colors[@]}" && clear
2254 [ $? -eq 0 ] && return 0
2256 local fatal=0 err=""
2257 err="$(sed 's/[^[:print:]]//g; s/\[[0-9\;:]*\?m//g; s/==> //g; s/] ERROR:/]\nERROR:/g' "$ERR")"
2258 [[ -z $err ]] && err="no error message was found"
2260 (( $1 == 1 )) && { fatal=1; shift; }
2262 local txt="\nCommand: $1\n\n\n\nError: $err\n\n"
2264 if (( fatal )); then
2265 msg "Install Error" "${txt}Errors at this stage are fatal, the install cannot continue.\n"
2266 [[ -r $DBG && $TERM == 'linux' ]] && less "$DBG"
2270 msg "Install Error" "${txt}Errors at this stage are non-fatal and may be fixed or ignored depending on the error.\n"
2278 if (( $1 >= 0 )) && ! grep -qw "$MNT" /proc/mounts; then
2279 msg "Not Mounted" "\nPartition(s) must be mounted first.\n" 2
2281 elif [[ $1 -ge 1 && -z $BOOTLDR ]]; then
2282 msg "No Bootloader" "\nBootloader must be selected first.\n" 2
2284 elif [[ $1 -ge 2 && (-z $NEWUSER || -z $USER_PASS) ]]; then
2285 msg "No User" "\nA user must be created first.\n" 2
2287 elif [[ $1 -ge 3 && -z $CONFIG_DONE ]]; then
2288 msg "Not Configured" "\nSystem configuration must be done first.\n" 2
2291 (( i )) # return code
2296 mount | grep -q 'swap' && swapoff -a
2298 if [[ -d $dir ]] && mount | grep -q "on $dir "; then
2299 if ! umount "$dir" 2>/dev/null; then
2301 umount -f "$dir" 2>/dev/null || umount -l "$dir"
2309 msg "Network Connect" "\nVerifying network connection\n" 0
2310 curl -sIN --connect-timeout 5 'https://www.archlinux.org/' | sed '1q' | grep -q '200'
2315 if chk_connect; then
2317 elif hash nmtui >/dev/null 2>&1; then
2319 if [[ $TERM == 'linux' ]]; then
2320 printf "%b" "\e]P1191919" "\e]P4191919"
2322 printf "%b" "\e]P1D15355" "\e]P4255a9b"
2327 elif hash wifi-menu >dev/null 2>&1; then
2337 [[ $BG_PID ]] || return 0
2338 msg "Install Running" "\nA background install process is currently running.\n" 2
2344 IGNORE_DEV="$(lsblk -lno NAME,MOUNTPOINT | awk '/\/run\/archiso\/bootmnt/ {sub(/[1-9]/, ""); print $1}')"
2346 if [[ $IGNORE_DEV ]]; then
2347 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ && !'"/$IGNORE_DEV/"' {print "/dev/" $1 " " $2}')"
2349 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ {print "/dev/" $1 " " $2}')"
2352 if [[ -z $SYS_DEVS ]]; then
2353 msg "Device Error" "\nNo available devices...\n\nExiting..\n" 2
2358 while read -r line; do
2360 done <<< "$SYS_DEVS"
2367 # amd-ucode is not needed it's provided by linux-firmware
2368 # elif grep -q 'AuthenticAMD' /proc/cpuinfo; then
2370 elif grep -q 'GenuineIntel' /proc/cpuinfo; then
2374 modprobe -q efivarfs >/dev/null 2>&1
2376 _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."
2377 if [[ -d /sys/firmware/efi/efivars ]]; then
2379 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars
2380 _prep+="\n - An EFI boot partition mounted."
2384 _prep+="\n\nOnce finished mounting, a portion of the install can be done in the background while you continue configuring the system:\n"
2385 _prep+="\n - Choose the system bootloader.\n - Create a user and password."
2386 _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."
2389 ###############################################################################
2392 # enable some nicer colours in the linux console
2395 if (( UID != 0 )); then
2396 msg "Not Root" "\nThis installer must be run as root or using sudo.\n\nExiting..\n" 2
2398 elif ! grep -qwm 1 'lm' /proc/cpuinfo; then
2399 msg "Not x86_64 Architecture" "\nThis installer only supports x86_64 architectures.\n\nExiting..\n" 2
2402 case "$1" in -d|--debug) debug ;; -h|--help) usage "$0" ;; -l|--live) shift; live "$@" ;; esac
2405 # trap ^C to perform cleanup
2406 trap 'printf "\n^C\n" && die 1' INT
2411 msg "Welcome to the $DIST Installer" "$_welcome"
2413 if ! select_keymap; then
2415 elif ! net_connect; then
2416 msg "Not Connected" "\nThis installer requires an active internet connection.\n\nExiting..\n" 2
2425 # vim:fdm=marker:fmr={,}