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
9 # linux distributor, if unset will be ArchLabs
10 # this can be set in the environment prior to install, eg.
12 # $ DIST="My Distro" archlabs-installer
14 # will result in "My Distro Linux" used where needed
17 VER="2.0.64" # installer version
18 MNT="/mnt" # install mountpoint
19 ANS="/tmp/ans" # dialog answer file
21 # ------------------------------------------------------ #
22 # When manually mounting your partitions, you need
23 # to set these values to avoid using the mount menu.
24 # ------------------------------------------------------ #
26 # root partition, eg. /dev/sda2
29 # boot partition, required on UEFI eg. /dev/sda1
32 # boot device, used for some bootloaders eg. /dev/sda
35 # bootloader to use, can be:
36 # UEFI: grub, syslinux, efistub, systemd-boot, refind-efi
37 # BIOS: grub, syslinux
40 # directory to mount the boot partition (if any) for most bootloaders
41 # this will need to be 'boot' however a popular one for grub is 'boot/efi'
44 # ------------------------------------------------------ #
46 # bulk default values {
48 # these values will be selected during the install, it is not recommended
49 # to edit them here unless you know what you're doing.
51 UCODE='' # cpu microcode (if any), can be: amd-ucode, intel-ucode
52 KERNEL='' # linux kernel, can be: linux, linux-lts, linux-zen, or linux-hardened
53 MYSHELL='' # full path for the shell, eg. /usr/bin/zsh
55 SWAP_PART='' # swap partition or file path
56 SWAP_SIZE='' # swap size, only used when creating a swapfile
58 EXMNT='' # holder for additional partitions while mounting
59 EXMNTS='' # when an extra partition is mounted append it's info
61 FONT="ter-i16n" # font used for the linux console
62 HOOKS="shutdown" # list of additional HOOKS to add in /etc/mkinitcpio.conf
64 LOGIN_TYPE='' # login manager can be: lightdm, xinit, ly
65 LOGIN_WM='' # default login session to be placed in ~/.xinitrc
66 LOGINRC='' # login shell rc file, eg. .zprofile, .bash_profile, .profile
68 INSTALL_WMS='' # space separated list of chosen wm/de
70 WM_PKGS='' # list of packages added during wm/de choice (not user edited)
71 PACKAGES='' # list of all packages to install including WM_PKGS (not user edited)
72 USER_PKGS='' # packages selected by the user during install
74 NEWUSER='' # username for the new user
75 USER_PASS='' # new user's password
76 ROOT_PASS='' # root password
78 LUKS='' # empty when not using encryption
79 LUKS_DEV='' # boot parameter string for LUKS
80 LUKS_PART='' # partition used for encryption
81 LUKS_PASS='' # encryption password
82 LUKS_UUID='' # encrypted partition UUID
83 LUKS_NAME='' # name used for encryption
85 LVM='' # empty when not using lvm
86 LVM_PARTS='' # partitions used for volume group
87 VGROUP_MB=0 # available space in volume group
89 WARN='' # issued mounting/partitioning warning
90 SEP_BOOT='' # separate boot partition for BIOS
91 AUTOLOGIN='' # enable autologin for xinit
92 CONFIG_DONE='' # basic configuration is finished
94 FORMATTED='' # partitions we formatted and should allow skipping
95 AUTO_ROOT_PART='' # root value from auto partition
96 AUTO_BOOT_PART='' # boot value from auto partition
99 AL_BASE_PKGS="archlabs-skel-base archlabs-fonts archlabs-themes archlabs-dARK archlabs-icons archlabs-wallpapers archlabs-scripts"
101 # baseline (usually installed in the background)
102 BASE_PKGS="base-devel xorg xorg-drivers sudo git gvfs gtk3 gtk-engines gtk-engine-murrine pavucontrol tumbler xdg-user-dirs "
103 BASE_PKGS+="playerctl ffmpeg gstreamer libmad libmatroska gst-libav gst-plugins-base gst-plugins-good scrot"
105 # extras for window managers
106 WM_BASE_PKGS="arandr archlabs-networkmanager-dmenu nitrogen polkit-gnome volumeicon xclip exo laptop-detect "
107 WM_BASE_PKGS+="xdotool compton wmctrl gnome-keyring dunst feh gsimplecal xfce4-power-manager xfce4-settings"
110 SEL=0 # currently selected menu item
111 ERR="/tmp/errlog" # error log used internally
112 DBG="/tmp/debuglog" # debug log when passed -d
113 RUN="/run/archiso/bootmnt/arch/boot" # path for live system /boot
114 VM="$(dmesg | grep -i "hypervisor")" # system running in a virtual machine
115 SYS='Unknown' # bios type to be determined: UEFI/BIOS
117 export DIALOGOPTS="--cr-wrap" # see `man dialog`
121 # giant ugly variable container :P {
124 SYS_MEM="$(awk '/MemTotal/ {print int($2 / 1024) "M"}' /proc/meminfo)"
126 # locales from /etc/locale.gen
127 LOCALES="$(awk '/\.UTF-8/ {gsub(/# .*|#/, ""); if ($1) {print $1 " - "}}' /etc/locale.gen)"
129 # console keyboard mappings
130 CMAPS="$(find /usr/share/kbd/keymaps -name '*.map.gz' | awk '{gsub(/\.map\.gz|.*\//, ""); print $1 " - "}' | sort)"
133 [[ $LINES ]] || LINES=$(tput lines)
134 [[ $COLUMNS ]] || COLUMNS=$(tput cols)
139 # commands used to install each bootloader, however most get modified during runtime {
141 [refind-efi]='refind-install' # minor modification
142 [grub]='grub-install --recheck --force' # heavily modified
143 [syslinux]='syslinux-install_update -i -a -m' # modified on UEFI
144 [efistub]='efibootmgr -v -d /dev/sda -p 1 -c -l' # heavily modified
145 [systemd-boot]='bootctl --path=/boot install' # not modified
148 # executable name for each wm/de used in ~/.xinitrc {
149 declare -A WM_SESSIONS=(
156 [gnome]='gnome-session'
157 [fluxbox]='startfluxbox'
158 [openbox]='openbox-session'
159 [cinnamon]='cinnamon-session'
162 # packages installed for each wm/de, most are depends of the skel packages {
166 [cinnamon]='gnome-terminal' # doesn't install a terminal on it's own
167 [plasma]='kdebase-meta' # base plasma application set
168 [awesome]='archlabs-skel-awesome' # see deps of archlabs-skel-awesome
169 [bspwm]='archlabs-skel-bspwm' # see deps of archlabs-skel-bspwm
170 [fluxbox]='archlabs-skel-fluxbox' # see deps of archlabs-skel-fluxbox
171 [i3-gaps]='archlabs-skel-i3-gaps' # see deps of archlabs-skel-i3-gaps
172 [openbox]='archlabs-skel-openbox' # see deps of archlabs-skel-openbox
173 [xfce4]='archlabs-skel-xfce4 xfce4-goodies' # see deps of archlabs-skel-xfce4
176 # files offered for editing after install is complete {
177 declare -A EDIT_FILES=(
178 [login]='' # login is populated once we know the username and shell
180 [sudoers]='/etc/sudoers'
181 [crypttab]='/etc/crypttab'
182 [pacman]='/etc/pacman.conf'
183 [console]='/etc/vconsole.conf'
184 [mkinitcpio]='/etc/mkinitcpio.conf'
185 [hostname]='/etc/hostname /etc/hosts'
186 [bootloader]="/boot/loader/entries/$DIST.conf" # ** based on bootloader
187 [locale]='/etc/locale.conf /etc/default/locale'
188 [keyboard]='/etc/X11/xorg.conf.d/00-keyboard.conf /etc/default/keyboard'
191 # mkfs command and flags for filesystem formatting {
196 [ntfs]='mkfs.ntfs -q'
197 [ext2]='mkfs.ext2 -q'
198 [ext3]='mkfs.ext3 -q'
199 [ext4]='mkfs.ext4 -q'
200 [vfat]='mkfs.vfat -F32'
201 [nilfs2]='mkfs.nilfs2 -q'
202 [reiserfs]='mkfs.reiserfs -q'
205 # mount options for each filesystem {
211 [jfs]='discard errors=continue errors=panic nointegrity'
212 [reiserfs]='acl nolog notail replayonly user_xattr off'
213 [ext4]='discard dealloc nofail noacl relatime noatime nobarrier nodelalloc'
214 [xfs]='discard filestreams ikeep largeio noalign nobarrier norecovery noquota wsync'
215 [nilfs2]='discard nobarrier errors=continue errors=panic order=relaxed order=strict norecovery'
216 [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'
219 # packages installed for each login option {
220 declare -A LOGIN_PKGS=(
225 [lightdm]='lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings accountsservice'
228 # extras installed for user selected packages {
229 # if a package requires additional packages that aren't already dependencies
230 # they can be added here eg. [package]="extra"
234 [mupdf]='mupdf-tools'
235 [qt5ct]='qt5-styleplugins'
236 [vlc]='qt5ct qt5-styleplugins'
237 [zathura]='zathura-pdf-poppler'
238 [noto-fonts]='noto-fonts-emoji'
239 [cairo-dock]='cairo-dock-plug-ins'
240 [qutebrowser]='qt5ct qt5-styleplugins'
241 [qbittorrent]='qt5ct qt5-styleplugins'
242 [transmission-qt]='qt5ct qt5-styleplugins'
243 [bluez]='bluez-libs bluez-utils bluez-tools bluez-plugins bluez-hid2hci'
244 [kdenlive]='kdebase-meta dvdauthor frei0r-plugins breeze breeze-gtk qt5ct qt5-styleplugins'
249 # dialog text variables
252 # Basics (somewhat in order)
253 _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"
254 _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"
255 _device="\nSelect a device to use from the list below.\n\nDevices (/dev) are the available drives on the system. /sda, /sdb, /sdc ..."
256 _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."
257 _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."
258 _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"
259 _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)."
260 _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."
261 _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."
262 _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."
263 _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"
264 _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."
265 _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."
266 _exmnt="\nWhere do you want the partition mounted?\n\nEnsure the name begins with a slash (/).\nExamples include: /usr, /home, /var, etc."
267 _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."
268 _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."
269 _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"
270 _timez="\nThe time zone is used to set the system clock.\n\nSelect your country or continent from the list below"
271 _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."
272 _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."
273 _login="\nSelect which of your session choices to use for the initial login.\n\nYou can be change this later by editing your ~/.xinitrc"
274 _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"
275 _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."
276 _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] or Ctrl-z again to resume the installer, if you want to avoid the automatic reboot using Ctrl-c will cleanly exit."
279 _luksnew="Basic LUKS Encryption"
280 _luksadv="Advanced LUKS Encryption"
281 _luksopen="Open Existing LUKS Partition"
282 _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."
283 _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."
284 _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)."
287 _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."
288 _lvmnew="Create Volume Group and Volume(s)"
289 _lvmdel="Delete an Existing Volume Group"
290 _lvmdelall="Delete ALL Volume Group(s) and Volume(s)"
291 _lvmvgname="\nEnter a name for the volume group (VG) being created from the partition(s) selected."
292 _lvmlvname="\nEnter a name for the logical volume (LV) being created.\n\nThis is similar to setting a label for a partition."
293 _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."
294 _lvmdelask="\nConfirm deletion of volume group(s) and logical volume(s).\n\nDeleting a volume group, will delete all logical volumes within it.\n"
297 _errexpart="\nCannot mount partition due to a problem with the mountpoint.\n\nEnsure it begins with a slash (/) followed by atleast one character.\n"
298 _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"
299 _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"
300 _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"
301 _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"
302 _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"
303 _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"
309 ###############################################################################
311 # main is the entry point which calls functions including outside of its block
312 # once those functions finished they always are returned here with the
313 # exception of install_main(), it exits upon completion
317 (( SEL < 12 )) && (( SEL++ ))
319 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Prepare " --default-item $SEL --cancel-label 'Exit' --menu "$_prep" 0 0 0 \
320 1 "Device tree (optional)" \
321 2 "Partitioning (optional)" \
322 3 "LUKS setup (optional)" \
323 4 "LVM setup (optional)" \
324 5 "Mount partitions" \
325 6 "System bootloader" \
326 7 "User and password" \
327 8 "System configuration" \
328 9 "Select WM/DE (optional)" \
329 10 "Select Packages (optional)" \
330 11 "View configuration (optional)" \
331 12 "Start the installation" 2>"$ANS"
334 [[ -z $WARN && $SEL =~ (2|5) ]] && { msg "Data Warning" "$_warn"; WARN=true; }
337 2) part_menu || (( SEL-- )) ;;
338 3) luks_menu || (( SEL-- )) ;;
339 4) lvm_menu || (( SEL-- )) ;;
340 5) mount_menu || (( SEL-- )) ;;
341 6) prechecks 0 && { select_boot || (( SEL-- )); } ;;
342 7) prechecks 1 && { select_mkuser || (( SEL-- )); } ;;
343 8) prechecks 2 && { select_config || (( SEL-- )); } ;;
344 9) prechecks 3 && { select_sessions || (( SEL-- )); } ;;
345 10) prechecks 3 && { select_packages || (( SEL-- )); } ;;
346 11) prechecks 3 && select_show ;;
347 12) prechecks 3 && install_main ;;
348 *) yesno "Exit" "\nUnmount partitions (if any) and exit the installer?\n" && die 0
354 if [[ $SYS == 'BIOS' ]]; then
355 dlg BOOTLDR menu "BIOS Bootloader" "\nSelect which bootloader to use." \
356 "grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
357 "syslinux" "A collection of boot loaders for booting drives, CDs, or over the network" || return 1
359 dlg BOOTLDR menu "UEFI Bootloader" "\nSelect which bootloader to use." \
360 "systemd-boot" "A simple UEFI boot manager which executes configured EFI images" \
361 "grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
362 "refind-efi" "A UEFI boot manager that aims to be platform neutral and simplify multi-boot" \
363 "efistub" "Boot the kernel image directly (no chainloading support)" \
364 "syslinux" "A collection of boot loaders for booting drives, CDs, or over the network (no chainloading support)" || return 1
371 local pkgs="${USER_PKGS// / } ${PACKAGES// / }"
372 [[ $BOOT_PART ]] && local mnt="/$BOOTDIR"
373 [[ $INSTALL_WMS == *dwm* ]] && pkgs="dwm st dmenu $pkgs"
374 pkgs="${pkgs// / }" pkgs="${pkgs# }"
375 msg "Show Configuration" "
376 ---------- PARTITION CONFIGURATION ------------
378 Root: ${ROOT_PART:-none}
379 Boot: ${BOOT_PART:-${BOOT_DEV:-none}}
381 Swap: ${SWAP_PART:-none}
382 Size: ${SWAP_SIZE:-none}
383 Extra: ${EXMNTS:-${EXMNT:-none}}
384 Hooks: ${HOOKS:-none}
390 ------------ SYSTEM CONFIGURATION -------------
392 Locale: ${MYLOCALE:-none}
393 Keymap: ${KEYMAP:-none}
394 Hostname: ${MYHOST:-none}
395 Timezone: ${ZONE:-none}/${SUBZ:-none}
398 ------------ USER CONFIGURATION ---------------
400 Username: ${NEWUSER:-none}
401 Login Shell: ${MYSHELL:-none}
402 Login Session: ${LOGIN_WM:-none}
403 Autologin: ${AUTOLOGIN:-none}
404 Login Type: ${LOGIN_TYPE:-none}
407 ----------- PACKAGE CONFIGURATION -------------
409 Kernel: ${KERNEL:-none}
410 Bootloader: ${BOOTLDR:-none}
411 Packages: ${pkgs:-none}
417 [[ $INSTALL_WMS ]] || return 0
419 AUTOLOGIN='' # no autologin unless using xinit
421 dlg LOGIN_TYPE menu "Login Management" "\nSelect what kind of login management to use." \
422 "xinit" "Console login without a display manager" \
423 "ly" "TUI display manager with a ncurses-like interface" \
424 "lightdm" "Lightweight display manager with a gtk greeter" \
425 "gdm" "Gnome display manager" \
426 "sddm" "Simple desktop display manager" || return 1
429 ly) EDIT_FILES[login]="/etc/ly/config.ini" ;;
430 gdm|sddm) EDIT_FILES[login]="" ;;
431 lightdm) EDIT_FILES[login]="/etc/lightdm/lightdm.conf /etc/lightdm/lightdm-gtk-greeter.conf" ;;
432 xinit) EDIT_FILES[login]="/home/$NEWUSER/.xinitrc /home/$NEWUSER/.xprofile"
433 if (( $(wc -w <<< "$INSTALL_WMS") > 1 )); then
434 dlg LOGIN_WM menu "Login Management" "$_login" $LOGIN_CHOICES || return 1
435 LOGIN_WM="${WM_SESSIONS[$LOGIN_WM]}"
437 [[ -z $LOGIN_WM ]] && LOGIN_WM="${WM_SESSIONS[${INSTALL_WMS%% *}]}"
438 yesno "Autologin" "$(sed "s|USER|$NEWUSER|g; s|RC|$LOGINRC|g" <<< "$_autologin")" && AUTOLOGIN=true || AUTOLOGIN=''
448 until [[ $CONFIG_DONE ]]; do
450 0) dlg MYSHELL menu "Shell" "\nChoose which shell to use." \
451 /usr/bin/zsh 'A very advanced and programmable command interpreter (shell) for UNIX' \
452 /bin/bash 'The GNU Bourne Again shell, standard in many GNU/Linux distributions' \
453 /usr/bin/mksh 'The MirBSD Korn Shell - an enhanced version of the public domain ksh' || return 1
455 1) dlg MYHOST input "Hostname" "$_hostname" "${DIST,,}" limit || { i=0; continue; } ;;
456 2) dlg MYLOCALE menu "Locale" "$_locale" $LOCALES || { i=1; continue; } ;;
458 until [[ $ZONE && $SUBZ ]]; do
459 dlg ZONE menu "Timezone" "$_timez" America - Australia - Asia - Atlantic - Africa - Europe - Indian - Pacific - Arctic - Antarctica - || break
460 dlg SUBZ menu "Timezone" "$_timesubz" $(awk '/'"$ZONE"'\// {gsub(/'"$ZONE"'\//, ""); print $3 " - "}' /usr/share/zoneinfo/zone.tab | sort) || continue
462 [[ $ZONE && $SUBZ ]] || { i=2; continue; } ;;
463 4) dlg KERNEL menu "Kernel" "\nChoose which kernel to use." \
464 linux 'Vanilla linux kernel and modules, with a few patches applied' \
465 linux-lts 'Long-term support (LTS) linux kernel and modules' \
466 linux-zen 'A effort of kernel hackers to provide the best kernel for everyday systems' \
467 linux-hardened 'A security-focused linux kernel with hardening patches to mitigate exploits' || { i=3; continue; }
471 (( i++ )) # progress through to the next choice
474 case $MYSHELL in *bash) LOGINRC='.bash_profile' ;; *zsh) LOGINRC='.zprofile' ;; *mksh) LOGINRC='.profile' ;; esac
482 local v='' u='' p='' p2='' rp='' rp2=''
484 until [[ $NEWUSER ]]; do
487 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " User " --mixedform "$_user" 0 0 0 \
488 "Username:" 1 1 "$u" 1 11 "$COLUMNS" 0 0 \
489 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
490 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 \
491 "--- Root password, if left empty the user password will be used ---" 6 1 '' 6 68 "$COLUMNS" 0 2 \
492 "Password:" 8 1 '' 8 11 "$COLUMNS" 0 1 \
493 "Password2:" 9 1 '' 9 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
495 while read -r line; do
496 case $i in 0) u="$line" ;; 1) p="$line" ;; 2) p2="$line" ;; 3) rp="$line" ;; 4) rp2="$line" ;; esac
500 # root passwords empty, so use the user passwords
501 [[ -z $rp && -z $rp2 ]] && { rp="$p"; rp2="$p2"; }
503 # make sure a username was entered and that the passwords match
504 if [[ ${#u} -eq 0 || $u =~ \ |\' || $u =~ [^a-z0-9] ]]; then
505 msg "Invalid Username" "\nIncorrect user name.\n\nPlease try again.\n"; u=''
506 elif [[ -z $p ]]; then
507 msg "Empty Password" "\nThe user password cannot be left empty.\n\nPlease try again.\n"
508 elif [[ "$p" != "$p2" ]]; then
509 msg "Password Mismatch" "\nThe user passwords do not match.\n\nPlease try again.\n"
510 elif [[ "$rp" != "$rp2" ]]; then
511 msg "Password Mismatch" "\nThe root passwords do not match.\n\nPlease try again.\n"
523 dlg KEYMAP menu "Keyboard Layout" "$_keymap" \
524 us English cm English gb English au English gh English \
525 za English ng English ca French 'cd' French gn French \
526 tg French fr French de German at German ch German \
527 es Spanish latam Spanish br Portuguese pt Portuguese ma Arabic \
528 sy Arabic ara Arabic ua Ukrainian cz Czech ru Russian \
529 sk Slovak nl Dutch it Italian hu Hungarian cn Chinese \
530 tw Taiwanese vn Vietnamese kr Korean jp Japanese th Thai \
531 la Lao pl Polish se Swedish is Icelandic 'fi' Finnish \
532 dk Danish be Belgian in Indian al Albanian am Armenian \
533 bd Bangla ba Bosnian 'bg' Bulgarian dz Berber mm Burmese \
534 hr Croatian gr Greek il Hebrew ir Persian iq Iraqi \
535 af Afghani fo Faroese ge Georgian ee Estonian kg Kyrgyz \
536 kz Kazakh lt Lithuanian mt Maltese mn Mongolian ro Romanian \
537 no Norwegian rs Serbian si Slovenian tj Tajik lk Sinhala \
538 tr Turkish uz Uzbek ie Irish pk Urdu 'mv' Dhivehi \
539 np Nepali et Amharic sn Wolof ml Bambara tz Swahili \
540 ke Swahili bw Tswana ph Filipino my Malay tm Turkmen \
541 id Indonesian bt Dzongkha lv Latvian md Moldavian mao Maori \
542 by Belarusian az Azerbaijani mk Macedonian kh Khmer epo Esperanto \
543 me Montenegrin || return 1
545 if [[ $CMAPS == *"$KEYMAP"* ]]; then
548 dlg CMAP menu "Console Keymap" "$_vconsole" $CMAPS || return 1
551 if [[ $DISPLAY && $TERM != 'linux' ]]; then
552 setxkbmap "$KEYMAP" >/dev/null 2>&1
554 loadkeys "$CMAP" >/dev/null 2>&1
564 dlg INSTALL_WMS check "Sessions" "$_sessions\n" \
565 i3-gaps "A fork of i3wm with more features including gaps" "$(ofn i3-gaps "${INSTALL_WMS[*]}")" \
566 openbox "A lightweight, powerful, and highly configurable stacking wm" "$(ofn openbox "${INSTALL_WMS[*]}")" \
567 awesome "A customized Awesome WM session created by @elanapan" "$(ofn awesome "${INSTALL_WMS[*]}")" \
568 dwm "A dynamic WM for X that manages windows in tiled, floating, or monocle layouts" "$(ofn dwm "${INSTALL_WMS[*]}")" \
569 bspwm "A tiling wm that represents windows as the leaves of a binary tree" "$(ofn bspwm "${INSTALL_WMS[*]}")" \
570 fluxbox "A lightweight and highly-configurable window manager" "$(ofn fluxbox "${INSTALL_WMS[*]}")" \
571 gnome "A desktop environment that aims to be simple and easy to use" "$(ofn gnome "${INSTALL_WMS[*]}")" \
572 cinnamon "A desktop environment combining traditional desktop with modern effects" "$(ofn cinnamon "${INSTALL_WMS[*]}")" \
573 plasma "A kde software project currently comprising a full desktop environment" "$(ofn plasma "${INSTALL_WMS[*]}")" \
574 xfce4 "A lightweight and modular desktop environment based on gtk+2/3" "$(ofn xfce4 "${INSTALL_WMS[*]}")"
576 [[ $INSTALL_WMS ]] || return 0
578 WM_PKGS="${INSTALL_WMS/dwm/}" # remove dwm from package list
579 WM_PKGS="${WM_PKGS// / }" # remove double spaces
580 WM_PKGS="${WM_PKGS# }" # remove leading space
582 # add archlabs base when choosing any session
583 [[ $WM_PKGS ]] && WM_PKGS+=" $AL_BASE_PKGS"
585 for i in $INSTALL_WMS; do
586 LOGIN_CHOICES+="$i - "
587 [[ ${WM_EXT[$i]} && $WM_PKGS != *"${WM_EXT[$i]}"* ]] && WM_PKGS+=" ${WM_EXT[$i]}"
590 select_login || return 1
592 while IFS=' ' read -r pkg; do
593 [[ $PACKAGES != *"$pkg"* ]] && PACKAGES+=" $pkg"
601 dlg USER_PKGS check " Packages " "$_packages" \
602 abiword "A Fully-featured word processor" "$(ofn abiword "${USER_PKGS[*]}")" \
603 alacritty "A cross-platform, GPU-accelerated terminal emulator" "$(ofn alacritty "${USER_PKGS[*]}")" \
604 atom "An open-source text editor developed by GitHub" "$(ofn atom "${USER_PKGS[*]}")" \
605 audacious "A free and advanced audio player based on GTK+" "$(ofn audacious "${USER_PKGS[*]}")" \
606 audacity "A program that lets you manipulate digital audio waveforms" "$(ofn audacity "${USER_PKGS[*]}")" \
607 blueman "GUI bluetooth device manager" "$(ofn blueman "${USER_PKGS[*]}")" \
608 bluez "Simple CLI based bluetooth support" "$(ofn bluez "${USER_PKGS[*]}")" \
609 cairo-dock "Light eye-candy fully themable animated dock" "$(ofn cairo-dock "${USER_PKGS[*]}")" \
610 calligra "A set of applications for productivity" "$(ofn calligra "${USER_PKGS[*]}")" \
611 chromium "An open-source web browser based on the Blink rendering engine" "$(ofn chromium "${USER_PKGS[*]}")" \
612 clementine "A modern music player and library organizer" "$(ofn clementine "${USER_PKGS[*]}")" \
613 cmus "A small, fast and powerful console music player" "$(ofn cmus "${USER_PKGS[*]}")" \
614 deadbeef "A GTK+ audio player for GNU/Linux" "$(ofn deadbeef "${USER_PKGS[*]}")" \
615 deluge "A BitTorrent client written in python" "$(ofn deluge "${USER_PKGS[*]}")" \
616 docky "Full fledged dock for opening applications and managing windows" "$(ofn docky "${USER_PKGS[*]}")" \
617 emacs "An extensible, customizable, self-documenting real-time display editor" "$(ofn emacs "${USER_PKGS[*]}")" \
618 epiphany "A GNOME web browser based on the WebKit rendering engine" "$(ofn epiphany "${USER_PKGS[*]}")" \
619 evince "A document viewer" "$(ofn evince "${USER_PKGS[*]}")" \
620 evolution "Manage your email, contacts and schedule" "$(ofn evolution "${USER_PKGS[*]}")" \
621 file-roller "Create and modify archives" "$(ofn file-roller "${USER_PKGS[*]}")" \
622 firefox "A popular open-source web browser from Mozilla" "$(ofn firefox "${USER_PKGS[*]}")" \
623 gcolor2 "A simple GTK+2 color selector" "$(ofn gcolor2 "${USER_PKGS[*]}")" \
624 geany "A fast and lightweight IDE" "$(ofn geany "${USER_PKGS[*]}")" \
625 geary "A lightweight email client for the GNOME desktop" "$(ofn geary "${USER_PKGS[*]}")" \
626 gimp "GNU Image Manipulation Program" "$(ofn gimp "${USER_PKGS[*]}")" \
627 gnome-calculator "GNOME Scientific calculator" "$(ofn gnome-calculator "${USER_PKGS[*]}")" \
628 gnome-disk-utility "Disk Management Utility" "$(ofn gnome-disk-utility "${USER_PKGS[*]}")" \
629 gnome-system-monitor "View current processes and monitor system state" "$(ofn gnome-system-monitor "${USER_PKGS[*]}")" \
630 gparted "A GUI frontend for creating and manipulating partition tables" "$(ofn gparted "${USER_PKGS[*]}")" \
631 gpick "Advanced color picker using GTK+ toolkit" "$(ofn gpick "${USER_PKGS[*]}")" \
632 gpicview "Lightweight image viewer" "$(ofn gpicview "${USER_PKGS[*]}")" \
633 guvcview "Capture video from camera devices" "$(ofn guvcview "${USER_PKGS[*]}")" \
634 hexchat "A popular and easy to use graphical IRC client" "$(ofn hexchat "${USER_PKGS[*]}")" \
635 inkscape "Professional vector graphics editor" "$(ofn inkscape "${USER_PKGS[*]}")" \
636 irssi "Modular text mode IRC client" "$(ofn irssi "${USER_PKGS[*]}")" \
637 kdenlive "A popular non-linear video editor for Linux" "$(ofn kdenlive "${USER_PKGS[*]}")" \
638 krita "Edit and paint images" "$(ofn krita "${USER_PKGS[*]}")" \
639 libreoffice-fresh "Full featured office suite" "$(ofn libreoffice-fresh "${USER_PKGS[*]}")" \
640 lollypop "A new music playing application" "$(ofn lollypop "${USER_PKGS[*]}")" \
641 mousepad "A simple text editor" "$(ofn mousepad "${USER_PKGS[*]}")" \
642 mpd "A flexible, powerful, server-side application for playing music" "$(ofn mpd "${USER_PKGS[*]}")" \
643 mpv "A media player based on mplayer" "$(ofn mpv "${USER_PKGS[*]}")" \
644 mupdf "Lightweight PDF and XPS viewer" "$(ofn mupdf "${USER_PKGS[*]}")" \
645 mutt "Small but very powerful text-based mail client" "$(ofn mutt "${USER_PKGS[*]}")" \
646 nautilus "The default file manager for Gnome" "$(ofn nautilus "${USER_PKGS[*]}")" \
647 ncmpcpp "A mpd client and almost exact clone of ncmpc with some new features" "$(ofn ncmpcpp "${USER_PKGS[*]}")" \
648 neovim "A fork of Vim aiming to improve user experience, plugins, and GUIs." "$(ofn neovim "${USER_PKGS[*]}")" \
649 nicotine+ "A graphical client for Soulseek" "$(ofn nicotine+ "${USER_PKGS[*]}")" \
650 noto-fonts "Google Noto fonts" "$(ofn noto-fonts "${USER_PKGS[*]}")" \
651 noto-fonts-cjk "Google Noto CJK fonts (Chinese, Japanese, Korean)" "$(ofn noto-fonts-cjk "${USER_PKGS[*]}")" \
652 obs-studio "Free opensource streaming/recording software" "$(ofn obs-studio "${USER_PKGS[*]}")" \
653 openshot "An open-source, non-linear video editor for Linux" "$(ofn openshot "${USER_PKGS[*]}")" \
654 opera "A Fast and secure, free of charge web browser from Opera Software" "$(ofn opera "${USER_PKGS[*]}")" \
655 pcmanfm "A fast and lightweight file manager based in Lxde" "$(ofn pcmanfm "${USER_PKGS[*]}")" \
656 pidgin "Multi-protocol instant messaging client" "$(ofn pidgin "${USER_PKGS[*]}")" \
657 plank "An elegant, simple, and clean dock" "$(ofn plank "${USER_PKGS[*]}")" \
658 qbittorrent "An advanced BitTorrent client" "$(ofn qbittorrent "${USER_PKGS[*]}")" \
659 qpdfview "A tabbed PDF viewer" "$(ofn qpdfview "${USER_PKGS[*]}")" \
660 qt5ct "GUI for managing Qt based application themes, icons, and fonts" "$(ofn qt5ct "${USER_PKGS[*]}")" \
661 qutebrowser "A keyboard-focused vim-like web browser based on Python and PyQt5" "$(ofn qutebrowser "${USER_PKGS[*]}")" \
662 rhythmbox "A Music playback and management application" "$(ofn rhythmbox "${USER_PKGS[*]}")" \
663 rxvt-unicode "A unicode enabled rxvt-clone terminal emulator" "$(ofn rxvt-unicode "${USER_PKGS[*]}")" \
664 sakura "A terminal emulator based on GTK and VTE" "$(ofn sakura "${USER_PKGS[*]}")" \
665 simple-scan "Simple scanning utility" "$(ofn simple-scan "${USER_PKGS[*]}")" \
666 simplescreenrecorder "A feature-rich screen recorder" "$(ofn simplescreenrecorder "${USER_PKGS[*]}")" \
667 steam "A popular game distribution platform by Valve" "$(ofn steam "${USER_PKGS[*]}")" \
668 surf "A simple web browser based on WebKit2/GTK+" "$(ofn surf "${USER_PKGS[*]}")" \
669 terminator "Terminal emulator that supports tabs and grids" "$(ofn terminator "${USER_PKGS[*]}")" \
670 termite "A minimal VTE-based terminal emulator" "$(ofn termite "${USER_PKGS[*]}")" \
671 thunar "A modern file manager for the Xfce Desktop Environment" "$(ofn thunar "${USER_PKGS[*]}")" \
672 thunderbird "Standalone mail and news reader from mozilla" "$(ofn thunderbird "${USER_PKGS[*]}")" \
673 tilda "A GTK based drop down terminal for Linux and Unix" "$(ofn tilda "${USER_PKGS[*]}")" \
674 tilix "A tiling terminal emulator for Linux using GTK+ 3" "$(ofn tilix "${USER_PKGS[*]}")" \
675 transmission-cli "Free BitTorrent client CLI" "$(ofn transmission-cli "${USER_PKGS[*]}")" \
676 transmission-gtk "GTK+ Front end for transmission" "$(ofn transmission-gtk "${USER_PKGS[*]}")" \
677 transmission-qt "Qt Front end for transmission" "$(ofn transmission-qt "${USER_PKGS[*]}")" \
678 ttf-anonymous-pro "A family fixed-width fonts designed with code in mind" "$(ofn ttf-anonymous-pro "${USER_PKGS[*]}")" \
679 ttf-fira-code "Monospaced font with programming ligatures" "$(ofn ttf-fira-code "${USER_PKGS[*]}")" \
680 ttf-font-awesome "Iconic font designed for Bootstrap" "$(ofn ttf-font-awesome "${USER_PKGS[*]}")" \
681 ttf-hack "A hand groomed typeface based on Bitstream Vera Mono" "$(ofn ttf-hack "${USER_PKGS[*]}")" \
682 vlc "A free and open source cross-platform multimedia player" "$(ofn vlc "${USER_PKGS[*]}")" \
683 weechat "Fast, light and extensible IRC client" "$(ofn weechat "${USER_PKGS[*]}")" \
684 xapps "Common library for X-Apps project" "$(ofn xapps "${USER_PKGS[*]}")" \
685 xarchiver "A GTK+ frontend to various command line archivers" "$(ofn xarchiver "${USER_PKGS[*]}")" \
686 xed "A small and lightweight text editor. X-Apps Project." "$(ofn xed "${USER_PKGS[*]}")" \
687 xfce-terminal "A terminal emulator based in the Xfce Desktop Environment" "$(ofn xfce-terminal "${USER_PKGS[*]}")" \
688 xreader "Document viewer for files like PDF and Postscript. X-Apps Project." "$(ofn xed "${USER_PKGS[*]}")" \
689 xterm "The standard terminal emulator for the X window system" "$(ofn xterm "${USER_PKGS[*]}")" \
690 zathura "Minimalistic document viewer" "$(ofn zathura "${USER_PKGS[*]}")"
692 if [[ $USER_PKGS ]]; then # add any needed PKG_EXT to the list
693 for i in $USER_PKGS; do
694 [[ ${PKG_EXT[$i]} && $USER_PKGS != *"${PKG_EXT[$i]}"* ]] && USER_PKGS+=" ${PKG_EXT[$i]}"
701 ###############################################################################
703 # non-essential partitioning helpers called by the user when using the optional
704 # partition menu and selecting a device to edit
708 no_bg_install || return 0
709 local device choice devhash
710 devhash="$(lsblk -f | base64)"
712 part_device || return 1
717 if [[ $DISPLAY && $TERM != 'linux' ]] && hash gparted >/dev/null 2>&1; then
718 dlg choice menu "Edit Partitions" "$_part" \
719 "auto" "Whole device automatic partitioning" \
720 "shrink" "Shrink an existing ext2/3/4 or ntfs partition to make room for a new partition" \
721 "gparted" "GUI front end to parted" \
722 "cfdisk" "Curses based variant of fdisk" \
723 "parted" "GNU partition editor" \
724 "fdisk" "Dialog-driven creation and manipulation of partitions" \
725 "done" "Return to the main menu" || return 0
727 dlg choice menu "Edit Partitions" "$_part" \
728 "auto" "Whole device automatic partitioning" \
729 "shrink" "Shrink an existing ext2/3/4 or ntfs partition to make room for a new partition" \
730 "cfdisk" "Curses based variant of fdisk" \
731 "parted" "GNU partition editor" \
732 "fdisk" "Dialog-driven creation and manipulation of partitions" \
733 "done" "Return to the main menu" || return 0
736 if [[ $choice == 'done' ]]; then
738 elif [[ $choice == 'shrink' ]]; then
739 part_shrink "$device"
740 elif [[ $choice == 'auto' ]]; then
741 local root_size txt table boot_fs
742 root_size=$(lsblk -lno SIZE "$device" | awk 'NR == 1 {
745 print ($1 * 1000 - 512) / 1000 "G"
751 txt="\nWARNING:\n\nALL data on $device will be destroyed and the following partitions will be created\n\n- "
752 if [[ $SYS == 'BIOS' ]]; then
753 table="msdos" boot_fs="ext4"
754 txt+="An $boot_fs boot partition with the boot flag enabled (512M)\n- "
756 table="gpt" boot_fs="fat32"
757 txt+="A $boot_fs efi boot partition (512M)\n- "
759 txt+="An ext4 partition using all remaining space ($root_size)\n\nDo you want to continue?\n"
760 yesno "Auto Partition" "$txt" && msg "Info" "\nGathering device info.\n" 1 && part_auto "$device" "$table" "$boot_fs" "$root_size"
767 if [[ $devhash != "$(lsblk -f | base64)" ]]; then
768 msg "Probing Partitions" "\nInforming kernel of partition changes using partprobe\n" 0
769 partprobe >/dev/null 2>&1
770 [[ $choice == 'auto' ]] && return
778 if [[ $IGNORE_DEV ]]; then
779 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk "!/$IGNORE_DEV/"' && /disk|part|lvm|crypt|NAME/')"
781 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk '/disk|part|lvm|crypt|NAME/')"
783 msg "Device Tree" "\n\n$txt\n\n"
788 local device="$1" table="$2" boot_fs="$3" size="$4" dev_info=""
789 dev_info="$(parted -s "$device" print)"
791 msg "Auto Partition" "\nRemoving partitions on $device and setting table to $table\n" 1
794 while read -r PART; do
795 parted -s "$device" rm "$PART" >/dev/null 2>&1
796 done <<< "$(awk '/^ [1-9][0-9]?/ {print $1}' <<< "$dev_info" | sort -r)"
798 [[ $(awk '/Table:/ {print $3}' <<< "$dev_info") != "$table" ]] && parted -s "$device" mklabel "$table" >/dev/null 2>&1
800 msg "Auto Partition" "\nCreating a 512M $boot_fs boot partition.\n" 1
801 if [[ $SYS == "BIOS" ]]; then
802 parted -s "$device" mkpart primary "$boot_fs" 1MiB 513MiB >/dev/null 2>&1
804 parted -s "$device" mkpart ESP "$boot_fs" 1MiB 513MiB >/dev/null 2>&1
809 AUTO_BOOT_PART=$(lsblk -lno NAME,TYPE "$device" | awk 'NR==2 {print "/dev/" $1}')
811 if [[ $SYS == "BIOS" ]]; then
812 mkfs.ext4 -q "$AUTO_BOOT_PART" >/dev/null 2>&1
814 mkfs.vfat -F32 "$AUTO_BOOT_PART" >/dev/null 2>&1
817 msg "Auto Partition" "\nCreating a $size ext4 root partition.\n" 0
818 parted -s "$device" mkpart primary ext4 513MiB 100% >/dev/null 2>&1
820 AUTO_ROOT_PART="$(lsblk -lno NAME,TYPE "$device" | awk 'NR==3 {print "/dev/" $1}')"
821 mkfs.ext4 -q "$AUTO_ROOT_PART" >/dev/null 2>&1
823 FORMATTED+="$AUTO_BOOT_PART $AUTO_ROOT_PART "
824 msg "Auto Partition" "\nProcess complete.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$device")\n"
831 local device="$1" fs=""
833 part_find "${device##*/}[^ ]" || return 1
834 (( COUNT == 1 )) && part="$(awk '{print $1}' <<< "${PARTS[@]}" )"
836 if (( COUNT == 1 )) || dlg part menu "Resize" "\nWhich partition on $device do you want to resize?" $PARTS; then
837 fs=$(lsblk -lno FSTYPE "$part")
840 msg "Resize" "\nGathering device size info.\n" 0
842 end=$(parted -s "$device" unit KiB print | awk '/^\s*'"$num"'/ {print $3}') # part size in KiB
843 devsize=$(parted -s "$device" unit KiB print | awk '/Disk '"${device//\//\\/}"':/ {print $3}') # whole device size in KiB
844 mount "$part" $MNT >/dev/null 2>&1; sleep 0.5
845 min=$(df --output=used --block-size=MiB "$part" | awk 'NR == 2 {print int($1) + 256}')
846 max=$(df --output=avail --block-size=MiB "$part" | awk 'NR == 2 {print int($1)}')
849 if dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Resize: $part " --rangebox "$_resize" 17 "$COLUMNS" "$min" "$max" $((max / 2)) 2>$ANS; then
851 size=$((size * 1024))
858 if ntfsresize -fc "$part"; then
859 ntfsresize -ff --size $(( (size * 1024) / 1000 ))k "$part" 2>$ERR # k=10^3 bytes
860 errshow "ntfsresize -f -s $(( (size * 1024) / 1000 ))k $part" || return 1
862 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"
867 e2fsck -f "$part"; sleep 0.5
868 resize2fs -f "$part" ${size}K 2>$ERR # K=2^10 bytes
869 errshow "resize2fs -f $part ${size}K" || return 1
873 parted "$device" resizepart "$num" ${size}KiB || return 1
876 if [[ $devsize == "$end" ]]; then
877 parted -s "$device" mkpart primary ext4 ${size}KiB 100% 2>$ERR
878 errshow "parted -s $device mkpart primary ext4 ${size}KiB 100%" || return 1
880 parted -s "$device" mkpart primary ext4 ${size}KiB ${end}KiB 2>$ERR
881 errshow "parted -s $device mkpart primary ext4 ${size}KiB ${end}KiB" || return 1
883 msg "Resize Complete" "\n$part has been successfully resized to $((size / 1024))M.\n" 1
885 "") msg "No Filesystem" "\nFor unformatted partitions, cfdisk can be used in the partition menu.\n" ;;
886 *) msg "Invalid Filesystem: $fs" "\nResizing only supports ext and ntfs.\n" ;;
891 ###############################################################################
892 # partition management functions
893 # these are helpers for use by other functions to do essential setup/teardown
897 local regexp="$1" err=''
899 # string of partitions as /TYPE/PART SIZE
900 if [[ $IGNORE_DEV ]]; then
901 PARTS="$(lsblk -lno TYPE,NAME,SIZE |
902 awk "/$regexp/"' && !'"/$IGNORE_DEV/"' {
903 sub(/^part/, "/dev/")
904 sub(/^lvm|^crypt/, "/dev/mapper/")
908 PARTS="$(lsblk -lno TYPE,NAME,SIZE |
910 sub(/^part/, "/dev/")
911 sub(/^lvm|^crypt/, "/dev/mapper/")
916 # number of partitions total
918 while read -r line; do
922 # ensure we have enough partitions for the system and action type
924 'part|lvm|crypt') [[ $COUNT -lt 1 || ($SYS == 'UEFI' && $COUNT -lt 2) ]] && err="$_errpart" ;;
925 'part|crypt') (( COUNT < 1 )) && err="$_lvmerr" ;;
926 'part|lvm') (( COUNT < 2 )) && err="$_lukserr" ;;
929 # if there aren't enough partitions show the relevant error message
930 [[ $err ]] && { msg "Not Enough Partitions" "$err" 2; return 1; }
937 if [[ $1 == "$MNT/swapfile" && $SWAP_SIZE ]]; then
938 fallocate -l $SWAP_SIZE "$1" 2>$ERR
939 errshow "fallocate -l $SWAP_SIZE $1"
940 chmod 600 "$1" 2>$ERR
941 errshow "chmod 600 $1"
943 mkswap "$1" >/dev/null 2>$ERR
945 swapon "$1" >/dev/null 2>$ERR
952 local part="$1" mountp="${MNT}$2" fs=""
953 fs="$(lsblk -lno FSTYPE "$part")"
956 if [[ $fs && ${FS_OPTS[$fs]} && $part != "$BOOT_PART" ]] && select_mntopts "$fs"; then
957 mount -o "$MNT_OPTS" "$part" "$mountp" >/dev/null 2>&1
959 mount "$part" "$mountp" >/dev/null 2>&1
962 part_mountconf "$part" "$mountp" || return 1
970 local part="$1" fs="$2" delay="$3"
972 msg "Format" "\nFormatting $part as $fs\n" 0
973 ${FS_CMDS[$fs]} "$part" >/dev/null 2>$ERR
974 errshow "${FS_CMDS[$fs]} $part" || return 1
981 if [[ $DEV_COUNT -eq 1 && $SYS_DEVS ]]; then
982 DEVICE="$(awk '{print $1}' <<< "$SYS_DEVS")"
983 elif (( DEV_COUNT > 1 )); then
985 dlg DEVICE menu "Boot Device" "\nSelect the device to use for bootloader install." $SYS_DEVS
987 dlg DEVICE menu "Select Device" "$_device" $SYS_DEVS
989 [[ $DEVICE ]] || return 1
990 elif [[ $DEV_COUNT -lt 1 && ! $1 ]]; then
991 msg "Device Error" "\nNo available devices.\n\nExiting..\n" 2
995 [[ $1 ]] && BOOT_DEV="$DEVICE"
1002 BOOT_DEV="${BOOT_PART%[1-9]}"
1003 BOOT_PART_NUM="${BOOT_PART: -1}"
1004 [[ $BOOT_PART = /dev/nvme* ]] && BOOT_DEV="${BOOT_PART%p[1-9]}"
1005 if [[ $SYS == 'UEFI' ]]; then
1006 parted -s $BOOT_DEV set $BOOT_PART_NUM esp on >/dev/null 2>&1
1008 parted -s $BOOT_DEV set $BOOT_PART_NUM boot on >/dev/null 2>&1
1015 local part="$1" devs=""
1016 devs="$(lsblk -lno NAME,FSTYPE,TYPE)"
1018 # Identify if $part is LUKS+LVM, LVM+LUKS, LVM alone, or LUKS alone
1019 if lsblk -lno TYPE "$part" | grep -q 'crypt'; then
1021 LUKS_NAME="${part#/dev/mapper/}"
1023 for dev in $(awk '/lvm/ && /crypto_LUKS/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
1024 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1025 LUKS_DEV="$LUKS_DEV cryptdevice=$dev:$LUKS_NAME"
1026 LVM='logical volume'
1031 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
1032 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1033 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
1034 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
1039 elif lsblk -lno TYPE "$part" | grep -q 'lvm'; then
1040 LVM='logical volume'
1041 VNAME="${part#/dev/mapper/}"
1043 for dev in $(awk '/crypt/ && /lvm2_member/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
1044 if lsblk -lno NAME "$dev" | grep -q "$VNAME"; then
1045 LUKS_NAME="${dev/\/dev\/mapper\//}"
1050 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
1051 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1052 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
1053 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
1064 if (( COUNT > 0 )); then
1065 PARTS="$(sed "/${pt//\//\\/}/d" <<< "$PARTS")"
1073 if grep -qw "$1" /proc/mounts; then
1074 msg "Mount Success" "\nPartition $1 mounted at $2\n" 1
1078 msg "Mount Fail" "\nPartition $1 failed to mount at $2\n" 2
1083 ###############################################################################
1085 # mount_menu is the entry point which calls all other functions
1086 # once finished it returns to the main menu: main()
1090 msg "Info" "\nGathering device info.\n" 0
1091 no_bg_install || return 0
1094 part_find 'part|lvm|crypt' || { SEL=2; return 1; }
1096 [[ $LUKS && $LUKS_PART ]] && part_countdec $LUKS_PART
1097 [[ $LVM && $LVM_PARTS ]] && part_countdec $LVM_PARTS
1099 select_root_partition || return 1
1101 if [[ $SYS == 'UEFI' ]]; then
1102 select_efi_partition || { BOOT_PART=''; return 1; }
1103 elif (( COUNT > 0 )); then
1104 select_boot_partition || { BOOT_PART=''; return 1; }
1107 if [[ $BOOT_PART ]]; then
1108 part_mount "$BOOT_PART" "/$BOOTDIR" && SEP_BOOT=true || return 1
1112 select_swap || return 1
1113 select_extra_partitions || return 1
1121 dlg SWAP_PART menu "Swap Setup" "\nSelect whether to use a swapfile, swap partition, or none." \
1122 "none" "Don't allocate any swap space" \
1123 "swapfile" "Allocate $SYS_MEM at /swapfile" \
1126 if [[ -z $SWAP_PART || $SWAP_PART == "none" ]]; then
1129 elif [[ $SWAP_PART == "swapfile" ]]; then
1131 until [[ ${SWAP_SIZE:0:1} =~ [1-9] && ${SWAP_SIZE: -1} =~ (M|G) ]]; do
1132 (( 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
1133 dlg SWAP_SIZE input "Swap Setup" "$_swapsize" "$SYS_MEM" || { SWAP_PART=''; SWAP_SIZE=''; return 1; }
1136 part_swap "$MNT/$SWAP_PART"
1137 SWAP_PART="/$SWAP_PART"
1138 elif [[ $PARTS == *"$SWAP_PART"* ]]; then
1139 part_swap $SWAP_PART
1140 part_countdec $SWAP_PART
1141 SWAP_SIZE="$(lsblk -lno SIZE $SWAP_PART)"
1151 local fs="$1" opts=''
1152 local title="${fs^} Mount Options"
1154 for i in ${FS_OPTS[$fs]}; do
1158 until [[ $MNT_OPTS ]]; do
1159 dlg MNT_OPTS check "$title" "$_mount" $opts
1160 [[ $MNT_OPTS ]] || return 1
1161 MNT_OPTS="${MNT_OPTS// /,}"
1162 yesno "$title" "\nConfirm the following options: $MNT_OPTS\n" || MNT_OPTS=''
1171 until [[ $EXMNT ]]; do
1172 dlg EXMNT input "Extra Mount $part" "$_exmnt" "/" || return 1
1173 if [[ ${EXMNT:0:1} != "/" || ${#EXMNT} -le 1 || $EXMNT =~ \ |\' || $EXMNTS == *"$EXMNT"* ]]; then
1174 msg "Mountpoint Error" "$_errexpart"
1183 local part="$1" fs='' cur=''
1184 local txt="\nSelect which filesystem to use for: $part\n\nDefault: ext4"
1185 cur="$(lsblk -lno FSTYPE "$part" 2>/dev/null)"
1188 if [[ $cur && ($part != "$ROOT_PART" || $FORMATTED == *"$part"*) ]]; then
1189 dlg fs menu "Filesystem" "$txt\nCurrent: $cur" skip - ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1191 dlg fs menu "Filesystem" "$txt" ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1193 [[ $fs == 'skip' ]] && return 0
1194 yesno "Filesystem" "\nFormat $part as $fs?\n" || fs=''
1196 part_format "$part" "$fs"
1199 select_efi_partition()
1201 if [[ $AUTO_BOOT_PART ]]; then
1202 msg "EFI Boot Partition" "\nUsing partition created during automatic format.\n" 2
1203 BOOT_PART="$AUTO_BOOT_PART"; return 0 # were done here
1205 local pts size dev isize bsize ptcount=0
1207 # walk partition list and skip ones that are too small/big for boot
1208 while read -r dev size; do
1209 size_t="${size: -1:1}" # size type eg. K, M, G, T
1210 isize=${size:0:-1} # remove trailing size type character
1211 isize=${isize%.*} # remove any decimal (round down)
1212 [[ $size_t =~ [KT] || ($size_t == 'G' && $isize -gt 2) || ($size_t == 'M' && $isize -lt 100) ]] || { pts+="$dev $size "; (( ptcount++ )); }
1215 if (( ptcount == 1 )); then
1216 msg "EFI Boot Partition" "\nOnly one partition available that meets size requirements.\n" 1
1217 BOOT_PART="$(awk 'NF > 0 {print $1}' <<< "$pts")"
1219 dlg BOOT_PART menu "EFI Partition" "$_uefi" $pts
1223 [[ $BOOT_PART ]] || return 1
1225 if grep -q 'fat' <<< "$(fsck -N "$BOOT_PART")"; then
1226 local txt="\nIMPORTANT:\n\nThe EFI partition $BOOT_PART $_format"
1227 if yesno "Format EFI Partition" "$txt" "Format $BOOT_PART" "Skip Formatting" 1; then
1228 part_format "$BOOT_PART" "vfat" 2
1231 part_format "$BOOT_PART" "vfat" 2
1237 select_boot_partition()
1239 if [[ $AUTO_BOOT_PART && ! $LVM ]]; then
1240 msg "BIOS Boot Partition" "\nUsing partition created during automatic format.\n" 2
1241 BOOT_PART="$AUTO_BOOT_PART"; return 0 # were done here
1243 local pts size dev isize bsize ptcount=0
1245 # walk partition list and skip ones that are too small/big for boot
1246 while read -r dev size; do
1247 size_t="${size: -1:1}" # size type eg. K, M, G, T
1248 isize=${size:0:-1} # remove trailing size type character
1249 isize=${isize%.*} # remove any decimal (round down)
1250 [[ $size_t =~ [KT] || ($size_t == 'G' && $isize -gt 2) || ($size_t == 'M' && $isize -lt 100) ]] || { pts+="$dev $size "; (( ptcount++ )); }
1253 if [[ $LUKS && ! $LVM ]]; then
1254 dlg BOOT_PART menu "Boot Partition" "$_biosluks" $pts
1255 [[ $BOOT_PART ]] || return 1
1257 dlg BOOT_PART menu "Boot Partition" "$_bios" "skip" "don't use a separate boot" $pts
1258 [[ -z $BOOT_PART || $BOOT_PART == "skip" ]] && { BOOT_PART=''; return 0; }
1262 if grep -q 'ext[34]' <<< "$(fsck -N "$BOOT_PART")"; then
1263 local txt="\nIMPORTANT:\n\nThe boot partition $BOOT_PART $_format"
1264 if yesno "Format Boot Partition" "$txt" "Format $BOOT_PART" "Skip Formatting" 1; then
1265 part_format "$BOOT_PART" "ext4" 2
1268 part_format "$BOOT_PART" "ext4" 2
1273 select_root_partition()
1275 if [[ $AUTO_ROOT_PART && -z $LVM && -z $LUKS ]]; then
1276 ROOT_PART="$AUTO_ROOT_PART"
1277 msg "Select Root Partition (/)" "\nUsing partition created during automatic format.\n" 2
1278 part_mount "$ROOT_PART" || { ROOT_PART=''; return 1; }
1279 return 0 # we're done here
1281 local pts size dev isize bsize ptcount=0
1283 # walk partition list and skip ones that are too small for / (root)
1284 while read -r dev size; do
1285 size_t="${size: -1:1}" # size type eg. K, M, G, T
1286 isize=${size:0:-1} # remove trailing size type character
1287 isize=${isize%.*} # remove any decimal (round down)
1288 [[ $size_t =~ [MK] || ($size_t == 'G' && $isize -lt 4) ]] || { pts+="$dev $size "; (( ptcount++ )); }
1291 if (( ptcount == 1 )); then # only one available device
1292 msg "Select Root Partition (/)" "\nOnly one partition available that meets size requirements.\n" 2
1293 ROOT_PART="$(awk 'NR==1 {print $1}' <<< "$pts")"
1295 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
1298 [[ $ROOT_PART ]] || return 1
1300 select_filesystem "$ROOT_PART" || { ROOT_PART=''; return 1; }
1301 part_mount "$ROOT_PART" || { ROOT_PART=''; return 1; }
1306 select_extra_partitions()
1310 # walk partition list and skip ones that are too small to be usable
1311 while read -r dev size; do
1312 [[ ${size: -1:1} =~ [KM] ]] && part_countdec "$dev"
1315 while (( COUNT > 0 )); do
1317 dlg part menu 'Mount Extra' "$_expart" 'done' 'finish mounting step' $PARTS || break
1318 if [[ $part == 'done' ]]; then
1320 elif select_filesystem "$part" && select_mountpoint && part_mount "$part" "$EXMNT"; then
1321 EXMNTS+="$part: $EXMNT "
1322 [[ $EXMNT == '/usr' && $HOOKS != *usr* ]] && HOOKS="usr $HOOKS"
1330 ###############################################################################
1332 # main is the entry point which calls all other install functions, once
1333 # complete it shows a dialog to edit files on the new system before reboot
1340 genfstab -U $MNT >$MNT/etc/fstab 2>$ERR
1341 errshow 1 "genfstab -U $MNT >$MNT/etc/fstab"
1342 [[ -f $MNT/swapfile ]] && sed -i "s~${MNT}~~" $MNT/etc/fstab
1346 chrun "hwclock --systohc --utc" || chrun "hwclock --systohc --utc --directisa"
1349 chrun "chown -Rf $NEWUSER:users /home/$NEWUSER"
1352 dlg choice menu "Finalization" "$_edit" \
1353 finished "exit the installer and reboot" \
1354 keyboard "${EDIT_FILES[keyboard]}" \
1355 console "${EDIT_FILES[console]}" \
1356 locale "${EDIT_FILES[locale]}" \
1357 hostname "${EDIT_FILES[hostname]}" \
1358 sudoers "${EDIT_FILES[sudoers]}" \
1359 mkinitcpio "${EDIT_FILES[mkinitcpio]}" \
1360 fstab "${EDIT_FILES[fstab]}" \
1361 crypttab "${EDIT_FILES[crypttab]}" \
1362 bootloader "${EDIT_FILES[bootloader]}" \
1363 pacman "${EDIT_FILES[pacman]}" \
1364 login "${EDIT_FILES[login]}"
1366 if [[ -z $choice || $choice == 'finished' ]]; then
1367 [[ $DEBUG == true && -r $DBG ]] && vim $DBG
1371 for f in ${EDIT_FILES[$choice]}; do
1372 [[ -e ${MNT}$f ]] && exists+=" ${MNT}$f"
1374 if [[ $exists ]]; then
1377 msg "File Missing" "\nThe file(s) selected do not exist:\n\n${EDIT_FILES[$choice]}\n"
1385 if kill -0 "$RSYNC_PID" 2>/dev/null || kill -0 "$MIRROR_PID" 2>/dev/null; then
1386 printf "\nOne or more background install processes are still running, grabbing their output...\n" && cat /tmp/bg_out
1387 while kill -0 "$RSYNC_PID" 2>/dev/null || kill -0 "$MIRROR_PID" 2>/dev/null; do
1392 unset RSYNC_PID MIRROR_PID
1394 rm -rf $MNT/etc/mkinitcpio-archiso.conf
1395 find $MNT/usr/lib/initcpio -name 'archiso*' -type f -delete
1396 sed -i 's/volatile/auto/g' $MNT/etc/systemd/journald.conf
1397 find $MNT/boot -name '*-ucode.img' -delete
1399 if [[ $DIST != "ArchLabs" ]]; then
1400 for f in $MNT/etc/{lsb-release,os-release}; do
1401 sed -i "s/ArchLabs/$DIST/g" $MNT/etc/{lsb-release,os-release}
1406 find $MNT/etc/X11/xorg.conf.d/ -name '*.conf' -delete
1407 elif lspci | grep ' VGA ' | grep -q 'Intel'; then
1408 echo "Creating Intel VGA Tear Free config /etc/X11/xorg.conf.d/20-intel.conf"
1409 cat > $MNT/etc/X11/xorg.conf.d/20-intel.conf <<- EOF
1411 Identifier "Intel Graphics"
1413 Option "TearFree" "true"
1418 [[ -e /run/archiso/sfs/airootfs && $KERNEL == 'linux' ]] && cp -vf $RUN/x86_64/vmlinuz $MNT/boot/vmlinuz-linux
1420 cp -fv /etc/resolv.conf $MNT/etc/
1421 [[ -e /etc/NetworkManager/system-connections ]] && cp -rvf /etc/NetworkManager/system-connections $MNT/etc/NetworkManager/
1423 echo "LANG=$MYLOCALE" > $MNT/etc/locale.conf
1424 cp -f $MNT/etc/locale.conf $MNT/etc/default/locale
1425 sed -i "s/#en_US.UTF-8/en_US.UTF-8/g; s/#${MYLOCALE}/${MYLOCALE}/g" $MNT/etc/locale.gen
1427 chrun "ln -svf /usr/share/zoneinfo/$ZONE/$SUBZ /etc/localtime"
1429 cat > $MNT/etc/X11/xorg.conf.d/00-keyboard.conf <<- EOF
1430 # Use localectl(1) to instruct systemd-localed to update it.
1431 Section "InputClass"
1432 Identifier "system-keyboard"
1433 MatchIsKeyboard "on"
1434 Option "XkbLayout" "$KEYMAP"
1438 cat > $MNT/etc/default/keyboard <<- EOF
1439 # KEYBOARD CONFIGURATION FILE
1440 # Consult the keyboard(5) manual page.
1447 printf "KEYMAP=%s\nFONT=%s\n" "$CMAP" "$FONT" > $MNT/etc/vconsole.conf
1448 echo "$MYHOST" > $MNT/etc/hostname
1449 cat > $MNT/etc/hosts <<- EOF
1452 ::1 localhost ip6-localhost ip6-loopback
1453 ff02::1 ip6-allnodes
1454 ff02::2 ip6-allrouters
1460 echo "Installing $BOOTLDR"
1462 if [[ $ROOT_PART == /dev/mapper* ]]; then
1463 ROOT_PART_ID="$ROOT_PART"
1465 local uuid_type="UUID"
1466 [[ $BOOTLDR =~ (systemd-boot|refind-efi|efistub) ]] && uuid_type="PARTUUID"
1467 ROOT_PART_ID="$uuid_type=$(blkid -s $uuid_type -o value $ROOT_PART)"
1470 if [[ $SYS == 'UEFI' ]]; then
1471 # remove our old install and generic BOOT/ dir
1472 find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname "$DIST" -type d -delete
1473 find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname 'BOOT' -type d -delete
1477 chrun "${BCMDS[$BOOTLDR]}" 2>$ERR
1478 errshow 1 "${BCMDS[$BOOTLDR]}"
1480 if [[ -d $MNT/hostrun ]]; then
1481 # cleanup the bind mounts we made earlier for the grub-probe module
1482 umount_dir $MNT/hostrun/{udev,lvm}
1483 rm -rf $MNT/hostrun >/dev/null 2>&1
1486 if [[ $SYS == 'UEFI' ]]; then
1487 # some UEFI firmware requires a generic esp/BOOT/BOOTX64.EFI
1488 mkdir -pv $MNT/$BOOTDIR/EFI/BOOT
1489 if [[ $BOOTLDR == 'grub' ]]; then
1490 cp -fv $MNT/$BOOTDIR/EFI/$DIST/grubx64.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI
1491 elif [[ $BOOTLDR == 'syslinux' ]]; then
1492 cp -rf $MNT/$BOOTDIR/EFI/syslinux/* $MNT/$BOOTDIR/EFI/BOOT/
1493 cp -f $MNT/$BOOTDIR/EFI/syslinux/syslinux.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI
1494 elif [[ $BOOTLDR == 'refind-efi' ]]; then
1495 sed -i '/#extra_kernel_version_strings/ c extra_kernel_version_strings linux-hardened,linux-zen,linux-lts,linux' $MNT/$BOOTDIR/EFI/refind/refind.conf
1496 cp -fv $MNT/$BOOTDIR/EFI/refind/refind_x64.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI
1505 rm -f $MNT/root/.zshrc # remove welcome message from root zshrc
1507 chrun "chpasswd <<< 'root:$ROOT_PASS'" 2>$ERR
1508 errshow 1 "set root password"
1509 if [[ $MYSHELL != "/usr/bin/zsh" ]]; then # root uses zsh by default, change it if something else was chosen
1510 chrun "usermod -s $MYSHELL root" 2>$ERR
1511 errshow 1 "usermod -s $MYSHELL root"
1512 # copy the default mkshrc to /root if mksh was picked
1513 [[ $MYSHELL == '/usr/bin/mksh' ]] && cp -fv $MNT/etc/skel/.mkshrc $MNT/root/.mkshrc
1516 echo "Creating new user $NEWUSER and setting password"
1517 local groups='audio,floppy,log,network,rfkill,scanner,storage,optical,power,wheel'
1519 chrun "useradd -m -u 1000 -g users -G $groups -s $MYSHELL $NEWUSER" 2>$ERR
1520 errshow 1 "useradd -m -u 1000 -g users -G $groups -s $MYSHELL $NEWUSER"
1521 chrun "chpasswd <<< '$NEWUSER:$USER_PASS'" 2>$ERR
1522 errshow 1 "set $NEWUSER password"
1524 # if neovim was picked copy vim configs to ~/.config/nvim
1525 if [[ $USER_PKGS == *neovim* ]]; then
1526 mkdir -p $MNT/home/$NEWUSER/.config/nvim
1527 cp -fv $MNT/home/$NEWUSER/.vimrc $MNT/home/$NEWUSER/.config/nvim/init.vim
1528 cp -rfv $MNT/home/$NEWUSER/.vim/colors $MNT/home/$NEWUSER/.config/nvim/colors
1531 [[ $INSTALL_WMS == *dwm* ]] && install_suckless
1532 [[ $WM_PKGS == *xfce* ]] && echo 'volumeicon &' >> $MNT/home/$NEWUSER/.xprofile
1534 # remove some commands from ~/.xprofile when using KDE or Gnome as the login session
1535 if [[ $LOGIN_WM =~ (startkde|gnome-session) || ($LOGIN_TYPE =~ (lightdm|ly) && $WM_PKGS =~ (plasma|gnome)) ]]; then
1536 sed -i '/super/d' $MNT/home/$NEWUSER/.xprofile $MNT/root/.xprofile
1537 sed -i '/nitrogen/d' $MNT/home/$NEWUSER/.xprofile $MNT/root/.xprofile
1538 sed -i '/compton/d' $MNT/home/$NEWUSER/.xprofile $MNT/root/.xprofile
1541 # create user home directories (Music, Documents, Downloads, etc..)
1542 chrun 'xdg-user-dirs-update'
1549 local serv="$MNT/etc/systemd/system/getty@tty1.service.d"
1550 echo "Setting up $LOGIN_TYPE"
1552 ly|sddm|gdm|lightdm)
1553 rm -rf "$serv" "$MNT/home/$NEWUSER/.xinitrc"
1554 chrun "systemctl enable $LOGIN_TYPE.service" 2>$ERR
1555 errshow 1 "systemctl enable $LOGIN_TYPE.service"
1556 if [[ $LOGIN_TYPE == 'lightdm' ]]; then
1557 cat > $MNT/etc/lightdm/lightdm-gtk-greeter.conf <<- EOF
1559 default-user-image=/usr/share/icons/ArchLabs-Dark/64x64/places/distributor-logo-archlabs.png
1560 background=/usr/share/backgrounds/archlabs/archlabs.jpg
1561 theme-name=Adwaita-dark
1562 icon-theme-name=Adwaita
1563 font-name=DejaVu Sans Mono 11
1564 position=30%,end 50%,end
1569 if [[ $INSTALL_WMS ]]; then
1570 sed -i "/exec/ c exec ${LOGIN_WM}" "$MNT/home/$NEWUSER/.xinitrc"
1571 elif [[ -e $MNT/home/$NEWUSER/.xinitrc ]]; then
1572 sed -i '/exec/d' "$MNT/home/$NEWUSER/.xinitrc"
1575 if [[ $AUTOLOGIN ]]; then
1576 sed -i "s/root/${NEWUSER}/g" $serv/autologin.conf
1577 cat > "$MNT/home/$NEWUSER/$LOGINRC" <<- EOF
1578 # automatically run startx when logging in on tty1
1579 [ -z \$DISPLAY ] && [ \$XDG_VTNR -eq 1 ] && exec startx
1590 local rmpkg="archlabs-installer "
1591 local inpkg="$BASE_PKGS ${LOGIN_PKGS[$LOGIN_TYPE]} $PACKAGES $USER_PKGS "
1594 *zsh) inpkg+="zsh-completions " ;;
1595 *mksh) inpkg+="mksh " rmpkg+="zsh " ;;
1596 *bash) inpkg+="bash-completion " rmpkg+="zsh " ;;
1599 # using a different kernel, remove the stock one
1600 [[ $KERNEL != 'linux' ]] && inpkg+="$KERNEL " rmpkg+="linux "
1602 # don't install extras on dwm only installs
1603 if [[ $INSTALL_WMS != 'dwm' ]]; then
1604 # gnome, plasma, and cinnamon have their own superkey bind and ksuperkey conflicts
1605 [[ $INSTALL_WMS =~ ^(plasma|gnome|cinnamon)$ ]] || inpkg+="archlabs-ksuperkey "
1606 # window manager only packages
1607 [[ $INSTALL_WMS =~ (openbox|bspwm|i3-gaps|fluxbox) ]] && inpkg+="$WM_BASE_PKGS "
1609 inpkg+="arandr nitrogen polkit-gnome xclip xdotool compton gnome-keyring dunst feh "
1612 # update first to avoid issues
1613 chrun "pacman -Syyu --noconfirm"
1615 # remove the packages we don't want on the installed system
1616 [[ $rmpkg ]] && chrun "pacman -Rnsc $rmpkg --noconfirm"
1618 # reinstalling iputils fixes the network issue for non-root users
1619 chrun "pacman -S iputils $UCODE --noconfirm"
1621 # install the packages chosen throughout the install
1622 chrun "pacman -S $inpkg --needed --noconfirm" 2>$ERR
1623 errshow 1 "pacman -S $inpkg --needed --noconfirm"
1625 # bootloader packages
1626 if [[ $BOOTLDR == 'grub' ]]; then
1627 [[ $SYS == 'UEFI' ]] && local efib="efibootmgr"
1628 chrun "pacman -S os-prober grub $efib --needed --noconfirm" 2>$ERR
1629 errshow 1 "pacman -S os-prober grub $efib --needed --noconfirm"
1630 elif [[ $BOOTLDR == 'refind-efi' ]]; then
1631 chrun "pacman -S refind-efi efibootmgr --needed --noconfirm" 2>$ERR
1632 errshow 1 "pacman -S refind-efi efibootmgr --needed --noconfirm"
1633 elif [[ $SYS == 'UEFI' ]]; then
1634 chrun "pacman -S efibootmgr --needed --noconfirm" 2>$ERR
1635 errshow 1 "pacman -S efibootmgr --needed --noconfirm"
1638 # allow members of the wheel group to run commands as root
1639 sed -i "s/# %wheel ALL=(ALL) ALL/%wheel ALL=(ALL) ALL/g" $MNT/etc/sudoers
1646 mkdir -pv "$MNT/home/$NEWUSER/suckless"
1648 for i in dwm dmenu st; do
1649 if chrun "git clone https://git.suckless.org/$i /home/$NEWUSER/suckless/$i"; then
1650 chrun "cd /home/$NEWUSER/suckless/$i; make PREFIX=/usr install; make clean; rm config.h"
1652 printf "failed to clone %s repo\n" "$i"
1657 install_mkinitcpio()
1660 [[ $LUKS ]] && add="encrypt"
1661 [[ $LVM ]] && { [[ $add ]] && add+=" lvm2" || add+="lvm2"; }
1662 sed -i "s/block filesystems/block ${add} filesystems ${HOOKS}/g" $MNT/etc/mkinitcpio.conf
1663 chrun "mkinitcpio -p $KERNEL" 2>$ERR
1664 errshow 1 "mkinitcpio -p $KERNEL"
1667 install_mirrorlist()
1669 local mfile="$1" # output mirrorlist file
1671 if hash reflector >/dev/null 2>&1; then
1672 reflector --verbose --score 80 -l 40 -f 5 --sort rate --save "$mfile"
1673 elif hash rankmirrors >/dev/null 2>&1; then
1674 echo "Sorting mirrorlist"
1675 local key="access_key=5f29642060ab983b31fdf4c2935d8c56"
1676 ip_add="$(curl -fsSL "http://api.ipstack.com/check&?$key&fields=ip" | python -c "import sys, json; print(json.load(sys.stdin)['ip'])")"
1677 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'])")"
1678 if [[ "$country" ]]; then
1679 if [[ $country =~ (CA|US) ]]; then
1680 # use both CA and US mirrors for CA or US countries
1681 mirror="https://www.archlinux.org/mirrorlist/?country=US&country=CA&use_mirror_status=on"
1682 elif [[ $country =~ (AU|NZ) ]]; then
1683 # use both AU and NZ mirrors for AU or NZ countries
1684 mirror="https://www.archlinux.org/mirrorlist/?country=AU&country=NZ&use_mirror_status=on"
1686 mirror="https://www.archlinux.org/mirrorlist/?country=${country}&use_mirror_status=on"
1688 else # no country code so just grab all mirrors, will be a very slow sort but we don't have other options
1689 mirror="https://www.archlinux.org/mirrorlist/?country=all&use_mirror_status=on"
1691 curl -fsSL "$mirror" | sed -e 's/^#Server/Server/' -e '/^#/d' | rankmirrors -n 6 - >"$mfile"
1697 install_background()
1699 msg "Background Install" "\nInstall will now begin in the background\n" 1
1700 rsync -a /run/archiso/sfs/airootfs/ $MNT/ &
1702 ( install_mirrorlist "$MNT/etc/pacman.d/mirrorlist" >>/tmp/bg_out 2>&1 ) &
1704 # end the background processes before exiting
1705 trap "kill $RSYNC_PID $MIRROR_PID 2>/dev/null" EXIT
1708 ###############################################################################
1710 # prerun_* set up the configs needed before actually running the commands
1711 # setup_* are run after selecting a bootloader and build the command used later
1712 # they can also be used for further user input as these run before control is taken away
1716 EDIT_FILES[bootloader]="/etc/default/grub"
1718 if [[ $SYS == 'BIOS' ]]; then
1719 [[ $BOOT_DEV ]] || { part_device 1 || return 1; }
1720 BCMDS[grub]="grub-install --recheck --force --target=i386-pc $BOOT_DEV"
1722 BCMDS[grub]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1723 grub-install --recheck --force --target=x86_64-efi --efi-directory=/$BOOTDIR --bootloader-id=$DIST"
1724 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1727 BCMDS[grub]="mkdir -p /run/udev /run/lvm &&
1728 mount --bind /hostrun/udev /run/udev &&
1729 mount --bind /hostrun/lvm /run/lvm &&
1731 grub-mkconfig -o /boot/grub/grub.cfg &&
1732 sleep 1 && umount /run/udev /run/lvm"
1739 sed -i "s/GRUB_DISTRIBUTOR=.*/GRUB_DISTRIBUTOR=\"${DIST}\"/g; s/GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT=\"\"/g" $MNT/etc/default/grub
1741 if [[ $LUKS_DEV ]]; then
1742 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
1743 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"
1746 if [[ $SYS == 'BIOS' && $LVM && -z $SEP_BOOT ]]; then
1747 sed -i "s/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g" $MNT/etc/default/grub 2>$ERR
1748 errshow 1 "sed -i 's/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g' $MNT/etc/default/grub"
1751 # setup for os-prober module
1752 mkdir -p /run/{lvm,udev} $MNT/hostrun/{lvm,udev}
1753 mount --bind /run/lvm $MNT/hostrun/lvm
1754 mount --bind /run/udev $MNT/hostrun/udev
1761 EDIT_FILES[bootloader]=""
1766 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1767 efibootmgr -v -d $BOOT_DEV -p $BOOT_PART_NUM -c -L '${DIST} Linux' -l /vmlinuz-${KERNEL} \
1768 -u 'root=$ROOT_PART_ID rw $([[ $UCODE ]] && printf 'initrd=\%s.img ' "$UCODE")initrd=\initramfs-${KERNEL}.img'"
1773 if [[ $SYS == 'BIOS' ]]; then
1774 EDIT_FILES[bootloader]="/boot/syslinux/syslinux.cfg"
1776 EDIT_FILES[bootloader]="/boot/EFI/syslinux/syslinux.cfg"
1777 BCMDS[syslinux]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1778 efibootmgr -v -c -d $BOOT_DEV -p $BOOT_PART_NUM -l /EFI/syslinux/syslinux.efi -L $DIST"
1784 local c="$MNT/boot/syslinux" s="/usr/lib/syslinux/bios" d=".."
1785 [[ $SYS == 'UEFI' ]] && { c="$MNT/boot/EFI/syslinux"; s="/usr/lib/syslinux/efi64/"; d=''; }
1787 mkdir -pv "$c" && cp -rfv $s/* "$c/" && cp -f "$RUN/syslinux/splash.png" "$c/"
1788 cat > "$c/syslinux.cfg" <<- EOF
1790 MENU TITLE $DIST Boot Menu
1791 MENU BACKGROUND splash.png
1795 # see: https://www.syslinux.org/wiki/index.php/Comboot/menu.c32
1804 MENU HELPMSGENDROW 29
1805 MENU COLOR border 30;44 #40ffffff #a0000000 std
1806 MENU COLOR title 1;36;44 #9033ccff #a0000000 std
1807 MENU COLOR sel 7;37;40 #e0ffffff #20ffffff all
1808 MENU COLOR unsel 37;44 #50ffffff #a0000000 std
1809 MENU COLOR help 37;40 #c0ffffff #a0000000 std
1810 MENU COLOR timeout_msg 37;40 #80ffffff #00000000 std
1811 MENU COLOR timeout 1;37;40 #c0ffffff #00000000 std
1812 MENU COLOR msg07 37;40 #90ffffff #a0000000 std
1813 MENU COLOR tabmsg 31;40 #30ffffff #00000000 std
1816 MENU LABEL $DIST Linux
1817 LINUX $d/vmlinuz-$KERNEL
1818 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1819 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL.img
1821 LABEL ${DIST}fallback
1822 MENU LABEL $DIST Linux Fallback
1823 LINUX $d/vmlinuz-$KERNEL
1824 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1825 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL-fallback.img
1832 EDIT_FILES[bootloader]="/boot/refind_linux.conf"
1833 BCMDS[refind-efi]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1839 cat > $MNT/boot/refind_linux.conf <<- EOF
1840 "$DIST Linux" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] &&
1841 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1842 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL.img"
1843 "$DIST Linux Fallback" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] &&
1844 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1845 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL-fallback.img"
1847 mkdir -p $MNT/etc/pacman.d/hooks
1848 cat > $MNT/etc/pacman.d/hooks/refind.hook <<- EOF
1855 Description = Updating rEFInd on ESP
1856 When = PostTransaction
1857 Exec = /usr/bin/refind-install
1861 setup_systemd-boot()
1863 EDIT_FILES[bootloader]="/boot/loader/entries/$DIST.conf"
1864 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1865 bootctl --path=/boot install"
1868 prerun_systemd-boot()
1870 mkdir -p $MNT/boot/loader/entries
1871 cat > $MNT/boot/loader/loader.conf <<- EOF
1876 cat > $MNT/boot/loader/entries/$DIST.conf <<- EOF
1878 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1879 initrd /initramfs-$KERNEL.img
1880 options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1882 cat > $MNT/boot/loader/entries/$DIST-fallback.conf <<- EOF
1883 title $DIST Linux Fallback
1884 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1885 initrd /initramfs-$KERNEL-fallback.img
1886 options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1888 mkdir -p $MNT/etc/pacman.d/hooks
1889 cat > $MNT/etc/pacman.d/hooks/systemd-boot.hook <<- EOF
1896 Description = Updating systemd-boot
1897 When = PostTransaction
1898 Exec = /usr/bin/bootctl update
1900 systemd-machine-id-setup --root="$MNT"
1904 ###############################################################################
1909 msg "Info" "\nGathering device info.\n" 0
1910 no_bg_install || return 1
1914 dlg choice menu "Logical Volume Management" "$_lvmmenu" \
1915 "$_lvmnew" "vgcreate -f, lvcreate -L -n" \
1916 "$_lvmdel" "vgremove -f" \
1917 "$_lvmdelall" "lvrmeove, vgremove, pvremove -f" \
1918 "Back" "Return to the main menu"
1920 "$_lvmnew") lvm_create && break ;;
1921 "$_lvmdel") lvm_delgroup && yesno "$_lvmdel" "$_lvmdelask" && vgremove -f "$DEL_VG" >/dev/null 2>&1 ;;
1922 "$_lvmdelall") lvm_del_all ;;
1933 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
1934 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
1935 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
1937 if [[ $VGROUP && $v && $pv ]]; then
1938 msg "LVM Setup" "\nActivating existing logical volume management.\n" 0
1939 modprobe dm-mod >/dev/null 2>$ERR
1940 errshow 'modprobe dm-mod'
1941 vgscan >/dev/null 2>&1
1942 vgchange -ay >/dev/null 2>&1
1948 VGROUP='' LVM_PARTS='' VGROUP_MB=0
1950 lvm_mkgroup || return 1
1951 local txt="\nThe last (or only) logical volume will automatically use all remaining space in the volume group."
1952 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 -
1953 [[ $VOL_COUNT ]] || return 1
1954 lvm_extra_lvs || return 1
1955 lvm_volume_name "$_lvmlvname\nNOTE: This LV will use up all remaining space in the volume group (${VGROUP_MB}MB)" || return 1
1956 msg "$_lvmnew (LV:$VOL_COUNT)" "\nCreating volume $VNAME from remaining space in $VGROUP\n" 0
1957 lvcreate -l +100%FREE "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
1958 errshow "lvcreate -l +100%FREE $VGROUP -n $VNAME" || return 1
1959 LVM='logical volume'; sleep 0.5
1960 txt="\nDone, volume: $VGROUP-$VNAME (${VOLUME_SIZE:-${VGROUP_MB}MB}) has been created.\n"
1961 msg "$_lvmnew (LV:$VOL_COUNT)" "$txt\n$(lsblk -o NAME,MODEL,TYPE,FSTYPE,SIZE $LVM_PARTS)\n"
1967 local txt="${VGROUP}: ${SIZE}$SIZE_UNIT (${VGROUP_MB}MB remaining).$_lvmlvsize"
1971 dlg VOLUME_SIZE input "$_lvmnew (LV:$VOL_COUNT)" "$txt" ''
1972 if [[ -z $VOLUME_SIZE ]]; then
1974 break # allow bailing with escape or an empty choice
1975 elif (( ${VOLUME_SIZE:0:1} == 0 )); then
1976 ERR_SIZE=1 # size values can't begin with '0'
1978 # walk the string and make sure all but the last char are digits
1979 local lv=$((${#VOLUME_SIZE} - 1))
1980 for (( i=0; i<lv; i++ )); do
1981 [[ ${VOLUME_SIZE:$i:1} =~ [0-9] ]] || { ERR_SIZE=1; break; }
1983 if (( ERR_SIZE != 1 )); then
1984 case ${VOLUME_SIZE:$lv:1} in
1985 [mMgG]) local s=${VOLUME_SIZE:0:$lv} m=$((s * 1000))
1986 case ${VOLUME_SIZE:$lv:1} in
1987 [Gg]) (( m >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - m)) ;;
1988 [Mm]) (( ${VOLUME_SIZE:0:$lv} >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - s)) ;;
1995 if (( ERR_SIZE )); then
1996 msg "Invalid Logical Volume Size" "$_lvmerrlvsize"
2009 until [[ $named ]]; do
2010 lvm_partitions || return 1
2011 lvm_group_name || return 1
2012 yesno "$_lvmnew" "\nCreate volume group: $VGROUP\n\nusing these partition(s): $LVM_PARTS\n" && named=true
2015 msg "$_lvmnew" "\nCreating volume group: $VGROUP\n" 0
2016 vgcreate -f "$VGROUP" $LVM_PARTS >/dev/null 2>$ERR
2017 errshow "vgcreate -f $VGROUP $LVM_PARTS" || return 1
2019 SIZE=$(vgdisplay "$VGROUP" | awk '/VG Size/ { gsub(/[^0-9.]/, ""); print int($0) }')
2020 SIZE_UNIT="$(vgdisplay "$VGROUP" | awk '/VG Size/ { print substr($NF, 0, 1) }')"
2022 if [[ $SIZE_UNIT == 'G' ]]; then
2023 VGROUP_MB=$((SIZE * 1000))
2028 msg "$_lvmnew" "\nVolume group $VGROUP (${SIZE}$SIZE_UNIT) successfully created\n"
2034 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
2035 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
2036 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
2038 if [[ $VGROUP || $v || $pv ]]; then
2039 if yesno "$_lvmdelall" "$_lvmdelask"; then
2040 for i in $v; do lvremove -f "/dev/mapper/$i" >/dev/null 2>&1; done
2041 for i in $VGROUP; do vgremove -f "$i" >/dev/null 2>&1; done
2042 for i in $pv; do pvremove -f "$i" >/dev/null 2>&1; done
2046 msg "Delete LVM" "\nNo LVMs to remove...\n" 2
2056 for i in $(lvs --noheadings | awk '{print $2}' | uniq); do
2057 VOL_GROUP_LIST+="$i $(vgdisplay "$i" | awk '/VG Size/ {print $3$4}') "
2060 [[ $VOL_GROUP_LIST ]] || { msg "No Groups" "\nNo volume groups found."; return 1; }
2062 dlg DEL_VG menu "Logical Volume Management" "\nSelect volume group to delete.\n\nAll logical volumes within will also be deleted." $VOL_GROUP_LIST
2068 while (( VOL_COUNT > 1 )); do
2069 lvm_volume_name "$_lvmlvname" && lvm_lv_size || return 1
2070 msg "$_lvmnew (LV:$VOL_COUNT)" "\nCreating a $VOLUME_SIZE volume $VNAME in $VGROUP\n" 0
2071 lvcreate -L "$VOLUME_SIZE" "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
2072 errshow "lvcreate -L $VOLUME_SIZE $VGROUP -n $VNAME" || return 1
2073 msg "$_lvmnew (LV:$VOL_COUNT)" "\nDone, logical volume (LV) $VNAME ($VOLUME_SIZE) has been created.\n"
2081 part_find 'part|crypt' || return 1
2082 PARTS="$(awk 'NF > 0 {print $0 " off"}' <<< "$PARTS")"
2083 dlg LVM_PARTS check "$_lvmnew" "\nSelect the partition(s) to use for the physical volume (PV)." $PARTS
2090 until [[ $VGROUP ]]; do
2091 dlg VGROUP input "$_lvmnew" "$_lvmvgname" "lvgroup"
2092 if [[ -z $VGROUP ]]; then
2094 elif [[ ${VGROUP:0:1} == "/" || $VGROUP =~ \ |\' ]] || vgdisplay | grep -q "$VGROUP"; then
2095 msg "LVM Name Error" "$_lvmerrvgname"
2105 local txt="$1" default="mainvolume"
2106 (( VOL_COUNT > 1 )) && default="extvolume$VOL_COUNT"
2107 until [[ $VNAME ]]; do
2108 dlg VNAME input "$_lvmnew (LV:$VOL_COUNT)" "\n$txt" "$default"
2109 if [[ -z $VNAME ]]; then
2111 elif [[ ${VNAME:0:1} == "/" || $VNAME =~ \ |\' ]] || lsblk | grep -q "$VNAME"; then
2112 msg "LVM Name Error" "$_lvmerlvname"
2119 ###############################################################################
2125 no_bg_install || return 1
2126 dlg choice menu "LUKS Encryption" "$_luksmenu" \
2127 "$_luksnew" "cryptsetup -q luksFormat" \
2128 "$_luksopen" "cryptsetup open --type luks" \
2129 "$_luksadv" "cryptsetup -q -s -c luksFormat" \
2130 "Back" "Return to the main menu"
2133 "$_luksnew") luks_basic || return 1 ;;
2134 "$_luksopen") luks_open || return 1 ;;
2135 "$_luksadv") luks_advanced || return 1 ;;
2143 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
2145 part_find 'part|crypt|lvm' || return 1
2147 if (( COUNT == 1 )); then
2148 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2150 dlg LUKS_PART menu "$_luksopen" "\nSelect which partition to open." $PARTS
2153 [[ $LUKS_PART ]] || return 1
2155 luks_pass "$_luksopen" || return 1
2156 msg "$_luksopen" "\nOpening encrypted partition: $LUKS_NAME\n\nUsing device/volume: $LUKS_PART\n" 0
2157 cryptsetup open --type luks "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2158 errshow "cryptsetup open --type luks $LUKS_PART $LUKS_NAME" || return 1
2159 LUKS='encrypted'; luks_show
2166 local t="$1" op="$2" v='' p='' p2=''
2168 until [[ $LUKS_PASS ]]; do
2172 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " $t " \
2173 --mixedform "\nEnter the password to decrypt $ROOT_PART\n\nThis is needed to create a keyfile." 0 0 0 \
2174 "Password:" 1 1 '' 1 11 "$COLUMNS" 0 1 \
2175 "Password2:" 2 1 '' 2 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
2178 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " $t " --mixedform "$_luksomenu" 0 0 0 \
2179 "Name:" 1 1 "${LUKS_NAME:-cryptroot}" 1 7 "$COLUMNS" 0 0 \
2180 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
2181 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
2185 while read -r line; do
2201 if [[ -z $op && -z $n ]]; then
2202 msg "Name Empty" "\nEncrypted device name cannot be empty.\n\nPlease try again.\n" 2
2203 elif [[ -z $p || "$p" != "$p2" ]]; then
2204 [[ $op ]] || LUKS_NAME="$n"
2205 msg "Password Mismatch" "\nThe passwords entered do not match.\n\nPlease try again.\n" 2
2207 [[ $op ]] || LUKS_NAME="$n"
2218 msg "$_luksnew" "\nEncrypted partition ready for mounting.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$LUKS_PART")\n\n"
2223 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
2225 part_find 'part|lvm' || return 1
2227 if [[ $AUTO_ROOT_PART ]]; then
2228 LUKS_PART="$AUTO_ROOT_PART"
2229 elif (( COUNT == 1 )); then
2230 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2232 dlg LUKS_PART menu "$_luksnew" "\nSelect the partition you want to encrypt." $PARTS
2235 [[ $LUKS_PART ]] || return 1
2236 luks_pass "$_luksnew"
2241 luks_setup || return 1
2242 msg "$_luksnew" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2243 cryptsetup -q luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2244 errshow "cryptsetup -q luksFormat $LUKS_PART" || return 1
2245 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2246 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2247 LUKS='encrypted'; luks_show
2255 dlg cipher input "LUKS Encryption" "$_lukskey" "-s 512 -c aes-xts-plain64"
2256 [[ $cipher ]] || return 1
2257 msg "$_luksadv" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2258 cryptsetup -q $cipher luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2259 errshow "cryptsetup -q $cipher luksFormat $LUKS_PART" || return 1
2260 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2261 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2268 ###############################################################################
2270 # some help avoid repetition and improve usability of some commands
2271 # others are initial setup functions used before reaching the main loop
2275 [[ "$2" == *"$1"* ]] && printf "on" || printf "off"
2280 # cleanup and exit the installer cleanly with exit code $1
2281 # when ecode is 127 unmount /run/archiso/bootmnt and reboot
2286 if [[ -d $MNT ]] && command cd /; then
2288 if (( ecode == 127 )); then
2289 umount_dir /run/archiso/bootmnt
2300 local var="$1" # assign output from dialog to var
2301 local dlg_t="$2" # dialog type (menu, check, input)
2302 local title="$3" # dialog title
2303 local body="$4" # dialog message
2304 local n=0 # number of items to display for menu and check dialogs
2306 shift 4 # shift off args assigned above
2308 # adjust $n when passed a large list
2309 local l=$((LINES - 20))
2310 (( ($# / 2) > l )) && n=$l
2314 menu) dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --menu "$body" 0 0 $n "$@" 2>"$ANS" || return 1 ;;
2315 check) dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --checklist "$body" 0 0 $n "$@" 2>"$ANS" || return 1 ;;
2318 local def="$1" # assign default value for input
2320 if [[ $1 == 'limit' ]]; then
2321 dialog --backtitle "$DIST Installer - $SYS - v$VER" --max-input 63 --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2323 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2327 # if answer file isn't empty read from it into $var
2328 [[ -s "$ANS" ]] && printf -v "$var" "%s" "$(< "$ANS")"
2333 # displays a message dialog
2334 # when more than 2 args the message will disappear after sleep time ($3)
2340 dialog --backtitle "$DIST Installer - $SYS - v$VER" --sleep "$1" --title " $title " --infobox "$body\n" 0 0
2342 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --msgbox "$body\n" 0 0
2348 select_keymap || { clear; die 0; }
2349 net_connect || { msg "Not Connected" "\nRunning live requires an active internet connection.\n\nExiting..\n" 2; die 1; }
2351 pacman -Syyu --noconfirm || exit
2352 pacman -S $AL_BASE_PKGS archlabs-skel-openbox openbox xterm xorg-xinit xorg-server --needed --noconfirm || exit
2353 pacman -Scc --noconfirm # these get back some space
2354 rm -rf /var/cache/pacman/pkg/*
2355 cp -rfT /etc/skel /root || exit
2362 local title="$1" body="$2" yes='Yes' no='No'
2363 (( $# >= 3 )) && yes="$3"
2364 (( $# >= 4 )) && no="$4"
2366 if (( $# == 5 )); then
2367 dialog --backtitle "$DIST Installer - $SYS - v$VER" --defaultno --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2369 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2375 arch-chroot "$MNT" bash -c "$1"
2380 export PS4='| ${BASH_SOURCE} LINE:${LINENO} FUNC:${FUNCNAME[0]:+ ${FUNCNAME[0]}()} |> '
2389 printf "\n^C caught, cleaning up...\n"
2396 "\e]P0191919" # #191919
2397 "\e]P1D15355" # #D15355
2398 "\e]P2609960" # #609960
2399 "\e]P3FFCC66" # #FFCC66
2400 "\e]P4255A9B" # #255A9B
2401 "\e]P5AF86C8" # #AF86C8
2402 "\e]P62EC8D3" # #2EC8D3
2403 "\e]P7949494" # #949494
2404 "\e]P8191919" # #191919
2405 "\e]P9D15355" # #D15355
2406 "\e]PA609960" # #609960
2407 "\e]PBFF9157" # #FF9157
2408 "\e]PC4E88CF" # #4E88CF
2409 "\e]PDAF86C8" # #AF86C8
2410 "\e]PE2ec8d3" # #2ec8d3
2411 "\e]PFE1E1E1" # #E1E1E1
2414 [[ $TERM == 'linux' ]] && printf "%b" "${colors[@]}" && clear
2419 [ $? -eq 0 ] && return 0
2421 local fatal=0 err=""
2422 err="$(sed 's/[^[:print:]]//g; s/\[[0-9\;:]*\?m//g; s/==> //g; s/] ERROR:/]\nERROR:/g' "$ERR")"
2424 (( $1 == 1 )) && { fatal=1; shift; }
2427 local txt+="\nThe command exited abnormally:\n\n$1\n\nWith the following message:\n\n$err\n\n"
2429 local txt+="\nThe command exited abnormally:\n\n$1\n\nWith no error message:\n\n"
2432 if (( fatal )); then
2433 msg "Install Error" "${txt}Errors at this stage are fatal and the install cannot continue.\n"
2434 [[ -r $DBG && $TERM == 'linux' ]] && less "$DBG"
2438 msg "Install Error" "${txt}Errors at this stage are non-fatal and can be either fixed or ignored depending on the error.\n"
2446 if (( $1 >= 0 )) && ! grep -qw "$MNT" /proc/mounts; then
2447 msg "Not Mounted" "\nPartition(s) must be mounted first.\n" 2
2449 elif [[ $1 -ge 1 && -z $BOOTLDR ]]; then
2450 msg "No Bootloader" "\nBootloader must be selected first.\n" 2
2452 elif [[ $1 -ge 2 && (-z $NEWUSER || -z $USER_PASS) ]]; then
2453 msg "No User" "\nA user must be created first.\n" 2
2455 elif [[ $1 -ge 3 && -z $CONFIG_DONE ]]; then
2456 msg "Not Configured" "\nSystem configuration must be done first.\n" 2
2459 (( i )) # return code
2464 mount | grep -q 'swap' && swapoff -a
2466 [[ -d $dir && "$(mount | grep "on $dir ")" ]] || continue
2467 umount "$dir" 2>/dev/null || { sleep 0.5; umount -f "$dir" 2>/dev/null || umount -l "$dir"; }
2473 msg "Network Connect" "\nVerifying network connection\n" 1
2474 curl -sIN --connect-timeout 5 'https://www.archlinux.org/' | sed '1q' | grep -q '200'
2479 if chk_connect; then
2481 elif hash nmtui >/dev/null 2>&1; then
2483 if [[ $TERM == 'linux' ]]; then
2484 printf "%b" "\e]P1191919" "\e]P4191919"
2486 printf "%b" "\e]P1D15355" "\e]P4255a9b"
2491 elif hash wifi-menu >dev/null 2>&1; then
2501 [[ $RSYNC_PID || $MIRROR_PID ]] || return 0
2502 msg "Install Running" "\nA background install process is currently running.\n" 2
2508 IGNORE_DEV="$(lsblk -lno NAME,MOUNTPOINT | awk '/\/run\/archiso\/bootmnt/ {sub(/[1-9]/, ""); print $1}')"
2510 if [[ $IGNORE_DEV ]]; then
2511 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ && !'"/$IGNORE_DEV/"' {print "/dev/" $1 " " $2}')"
2513 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ {print "/dev/" $1 " " $2}')"
2516 if [[ -z $SYS_DEVS ]]; then
2517 msg "Device Error" "\nNo available devices...\n\nExiting..\n" 2
2522 while read -r line; do
2524 done <<< "$SYS_DEVS"
2531 elif grep -q 'AuthenticAMD' /proc/cpuinfo; then
2533 elif grep -q 'GenuineIntel' /proc/cpuinfo; then
2537 modprobe -q efivarfs >/dev/null 2>&1
2539 _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."
2540 if [[ -d /sys/firmware/efi/efivars ]]; then
2542 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars
2543 _prep+="\n - An EFI boot partition mounted."
2547 _prep+="\n\nOnce finished mounting, a portion of the install can be done in the background while you continue configuring the system:\n"
2548 _prep+="\n - Choose the system bootloader.\n - Create a user and password."
2549 _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."
2552 ###############################################################################
2555 # enable some nicer colours in the linux console
2558 if (( UID != 0 )); then
2559 msg "Not Root" "\nThis installer must be run as root or using sudo.\n\nExiting..\n" 2
2561 elif ! grep -qwm 1 'lm' /proc/cpuinfo; then
2562 msg "Not x86_64 Architecture" "\nThis installer only supports x86_64 architectures.\n\nExiting..\n" 2
2564 elif [[ $1 =~ (-d|--debug) ]]; then
2566 elif [[ $1 =~ (-l|--live) ]]; then
2570 # trap ^C to perform cleanup
2576 msg "Welcome to the $DIST Installer" "\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 options and [Enter] to confirm.\n - Switch between buttons 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"
2578 select_keymap || { clear; die 0; }
2579 net_connect || { msg "Not Connected" "\nThis installer requires an active internet connection.\n\nExiting..\n" 2; die 1; }
2586 # vim:fdm=marker:fmr={,}