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
8 VER="2.0.36" # installer version
9 DIST="ArchLabs" # linux distributor
10 MNT="/mnt" # install mountpoint
11 ANS="/tmp/ans" # dialog answer file
14 # --------------------------------------------- #
15 # if you manually mount your partitions then you
16 # need to set these values to avoid issues.
17 # --------------------------------------------- #
19 # root partition, eg/ /dev/sda2
22 # boot partition, required on UEFI eg. /dev/sda1
25 # device used for some bootloader install process, eg. /dev/sda
28 # bootloader to use, can be:
29 # UEFI: grub, syslinux, efistub, systemd-boot, refind-efi
30 # BIOS: grub, syslinux
33 # directory to mount the boot partition (if any) for most bootloaders
34 # this will need to be 'boot' however a popular one for grub is 'boot/efi'
37 # swap partition or file path
40 # swap size, only used when creating a swapfile
43 # --------------------------------------------- #
45 # bulk default values {
47 EXMNT='' # holder for additional partitions while mounting
48 EXMNTS='' # when an extra partition is mounted append it's info
50 FONT="ter-i16n" # font used for the linux console
51 HOOKS="shutdown" # list of additional HOOKS to add in /etc/mkinitcpio.conf
53 LOGINRC='' # login shell rc file, eg. .zprofile, .bash_profile, .profile
54 LOGIN_WM='' # default login session to be placed in ~/.xinitrc
55 INSTALL_WMS='' # space separated list of chosen wm/de
57 UCODE='' # cpu microcode (if any), eg. amd-ucode, intel-ucode
58 KERNEL='' # can be linux, linux-lts, linux-zen, or linux-hardened
59 MYSHELL='' # full path for the shell, eg. /usr/bin/zsh
61 WM_PKGS='' # full list of packages added during wm/de choice
62 PACKAGES='' # list of all packages to install including WM_PKGS
63 USER_PKGS='' # packages selected by the user during install
65 NEWUSER='' # username for the new user
66 USER_PASS='' # new user's password
67 ROOT_PASS='' # root password
69 LUKS='' # empty when not using encryption
70 LUKS_DEV='' # boot parameter string for LUKS
71 LUKS_PART='' # partition used for encryption
72 LUKS_PASS='' # encryption password
73 LUKS_UUID='' # encrypted partition UUID
74 LUKS_NAME='' # name used for encryption
76 LVM='' # empty when not using lvm
77 LVM_PARTS='' # partitions used for volume group
78 VGROUP_MB=0 # available space in volume group
80 WARN='' # issued mounting/partitioning warning
81 SEP_BOOT='' # separate boot partition for BIOS
82 AUTOLOGIN='' # enable autologin for xinit
83 CONFIG_DONE='' # basic configuration is finished
84 BROADCOM_WL='' # fixes for broadcom cards eg. BCM4352
86 FORMATTED='' # partitions we formatted and should allow skipping
87 AUTO_ROOT_PART='' # root value from auto partition
88 AUTO_BOOT_PART='' # boot value from auto partition
90 # iso base, pacstrap when running the installer from a stock arch iso
91 ISO_BASE="arch-install-scripts b43-firmware b43-fwcutter broadcom-wl clonezilla dhclient dhcpcd ethtool "
92 ISO_BASE+="exfat-utils f2fs-tools gptfdisk vim hdparm ipw2100-fw ipw2200-fw nfs-utils nilfs-utils ntfs-3g "
93 ISO_BASE+="pacman-contrib parted rsync sdparm smartmontools wget wireless_tools wpa_actiond xl2tpd dialog parted "
94 ISO_BASE+="alsa-firmware alsa-lib alsa-plugins pulseaudio pulseaudio-alsa networkmanager w3m htop wireless-regdb "
95 ISO_BASE+="wpa_supplicant lm_sensors lsb-release p7zip pamixer reflector unrar ranger terminus-font ttf-dejavu archlabs-keyring"
97 # archlabs base packages
98 AL_BASE_PKGS="archlabs-skel-base archlabs-fonts archlabs-themes archlabs-dARK archlabs-icons archlabs-wallpapers archlabs-scripts"
100 # baseline (usually installed in the background)
101 BASE_PKGS="base-devel xorg xorg-drivers xorg-xinit sudo git gvfs gtk3 gtk-engines gtk-engine-murrine pavucontrol tumbler "
102 BASE_PKGS+="playerctl ffmpeg gstreamer libmad libmatroska gst-libav gst-plugins-base gst-plugins-good scrot"
104 # extras for window managers
105 WM_BASE_PKGS="arandr archlabs-networkmanager-dmenu xdg-user-dirs nitrogen polkit-gnome volumeicon xclip exo "
106 WM_BASE_PKGS+="xdotool compton wmctrl gnome-keyring dunst feh gsimplecal xfce4-power-manager xfce4-settings laptop-detect"
109 SEL=0 # currently selected menu item
110 ERR="/tmp/errlog" # error log used internally
111 DBG="/tmp/debuglog" # debug log when passed -d
112 RUN="/run/archiso/bootmnt/arch/boot" # path for live /boot
113 VM="$(dmesg | grep -i "hypervisor")" # is the system a vm
116 export DIALOGOPTS="--cr-wrap"
120 # giant ugly variable container :P {
122 # RAM in the system in MB
123 SYS_MEM="$(awk '/MemTotal/ {
124 print int($2 / 1024)"M"
127 # locales from /etc/locale.gen
128 LOCALES="$(awk '/\.UTF-8/ {
135 # linux console keyboard mappings
136 CMAPS="$(find /usr/share/kbd/keymaps -name '*.map.gz' | awk '{
137 gsub(/\.map\.gz|.*\//, "")
141 # terminal size definitions
143 [[ $LINES ]] || LINES=$(tput lines)
144 [[ $COLUMNS ]] || COLUMNS=$(tput cols)
145 SHL=$((LINES - 20)) # }
150 # commands used to install each bootloader (most get modified during runtime) {
152 [refind-efi]='refind-install'
153 [grub]='grub-install --recheck --force'
154 [syslinux]='syslinux-install_update -i -a -m'
155 [efistub]='efibootmgr -v -d /dev/sda -p 1 -c -l'
156 [systemd-boot]='bootctl --path=/boot install'
159 # executable name for each wm/de {
160 declare -A WM_SESSIONS=(
166 [gnome]='gnome-session'
167 [fluxbox]='startfluxbox'
168 [openbox]='openbox-session'
169 [cinnamon]='cinnamon-session'
172 # packages installed for each wm/de {
176 [plasma]='kdebase-meta'
177 [bspwm]='sxhkd archlabs-skel-bspwm rofi archlabs-polybar'
178 [fluxbox]='archlabs-skel-fluxbox archlabs-polybar jgmenu rofi lxmenu-data'
179 [i3-gaps]='i3status perl-anyevent-i3 archlabs-skel-i3-gaps rofi archlabs-polybar'
180 [openbox]='obconf archlabs-skel-openbox jgmenu archlabs-polybar tint2 conky rofi lxmenu-data'
181 [xfce4]='xfce4-goodies xfce4-pulseaudio-plugin network-manager-applet volumeicon rofi archlabs-skel-xfce4'
184 # files that can be edited after install is complete {
185 declare -A EDIT_FILES=(
188 [sudoers]='/etc/sudoers'
189 [crypttab]='/etc/crypttab'
190 [pacman]='/etc/pacman.conf'
191 [console]='/etc/vconsole.conf'
192 [mkinitcpio]='/etc/mkinitcpio.conf'
193 [hostname]='/etc/hostname /etc/hosts'
194 [bootloader]="/boot/loader/entries/$DIST.conf"
195 [locale]='/etc/locale.conf /etc/default/locale'
196 [keyboard]='/etc/X11/xorg.conf.d/00-keyboard.conf /etc/default/keyboard'
199 # mkfs command for formatting each offered filesystem {
204 [ntfs]='mkfs.ntfs -q'
205 [ext2]='mkfs.ext2 -q'
206 [ext3]='mkfs.ext3 -q'
207 [ext4]='mkfs.ext4 -q'
208 [vfat]='mkfs.vfat -F32'
209 [nilfs2]='mkfs.nilfs2 -q'
210 [reiserfs]='mkfs.reiserfs -q'
213 # mount options for each offered filesystem (if any {
219 [jfs]='discard errors=continue errors=panic nointegrity'
220 [reiserfs]='acl nolog notail replayonly user_xattr off'
221 [ext4]='discard dealloc nofail noacl relatime noatime nobarrier nodelalloc'
222 [xfs]='discard filestreams ikeep largeio noalign nobarrier norecovery noquota wsync'
223 [nilfs2]='discard nobarrier errors=continue errors=panic order=relaxed order=strict norecovery'
224 [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'
227 # PKG_EXT: if you add a package to $PACKAGES in any dialog {
228 # and it uses/requires some additional packages,
229 # you can add them here to keep it simple: [package]="extra"
230 # duplicates are removed with `uniq` before install
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 [kdenlive]='kdebase-meta dvdauthor frei0r-plugins breeze breeze-gtk qt5ct qt5-styleplugins'
251 # Basics (somewhat in order)
252 _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"
253 _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"
254 _device="\nSelect a device to use from the list below.\n\nDevices (/dev) are the available drives on the system. /sda, /sdb, /sdc ..."
255 _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."
256 _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."
257 _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"
258 _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)."
259 _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."
260 _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."
261 _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."
262 _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"
263 _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."
264 _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."
265 _exmnt="\nWhere do you want the partition mounted?\n\nEnsure the name begins with a slash (/).\nExamples include: /usr, /home, /var, etc."
266 _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 the [Up] and [Down] arrows to switch between input fields, [Tab] to toggle between input fields and the buttons, and [Enter] to accept."
267 _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."
268 _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"
269 _timez="\nThe time zone is used to set the system clock.\n\nSelect your country or continent from the list below"
270 _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."
271 _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."
272 _login="\nSelect which of your session choices to use for the initial login.\n\nYou can be change this later by editing your ~/.xinitrc"
273 _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."
274 _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."
277 _luksnew="Basic LUKS Encryption"
278 _luksadv="Advanced LUKS Encryption"
279 _luksopen="Open Existing LUKS Partition"
280 _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."
281 _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."
282 _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)."
285 _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."
286 _lvmnew="Create Volume Group and Volume(s)"
287 _lvmdel="Delete an Existing Volume Group"
288 _lvmdelall="Delete ALL Volume Group(s) and Volume(s)"
289 _lvmvgname="\nEnter a name for the volume group (VG) being created from the partition(s) selected."
290 _lvmlvname="\nEnter a name for the logical volume (LV) being created.\n\nThis is similar to setting a label for a partition."
291 _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."
292 _lvmdelask="\nConfirm deletion of volume group(s) and logical volume(s).\n\nDeleting a volume group, will delete all logical volumes within it.\n"
295 _errexpart="\nCannot mount partition due to a problem with the mountpoint.\n\nEnsure it begins with a slash (/) followed by atleast one character.\n"
296 _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"
297 _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"
298 _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"
299 _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"
300 _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"
301 _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"
307 ###############################################################################
312 (( SEL < 12 )) && (( SEL++ ))
314 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Prepare " --default-item $SEL --cancel-label 'Exit' --menu "$_prep" 0 0 0 \
315 1 "Device tree (optional)" \
316 2 "Partitioning (optional)" \
317 3 "LUKS setup (optional)" \
318 4 "LVM setup (optional)" \
319 5 "Mount partitions" \
320 6 "System bootloader" \
321 7 "User and password" \
322 8 "System configuration" \
323 9 "Select WM/DE (optional)" \
324 10 "Select Packages (optional)" \
325 11 "View configuration (optional)" \
326 12 "Start the installation" 2>"$ANS"
329 [[ -z $WARN && $SEL =~ (2|5) ]] && { msg "Data Warning" "$_warn"; WARN=true; }
332 2) part_menu || (( SEL-- )) ;;
333 3) luks_menu || (( SEL-- )) ;;
334 4) lvm_menu || (( SEL-- )) ;;
335 5) select_menu || (( SEL-- )) ;;
336 6) prechecks 0 && { select_boot || (( SEL-- )); } ;;
337 7) prechecks 1 && { select_mkuser || (( SEL-- )); } ;;
338 8) prechecks 2 && { select_config || (( SEL-- )); } ;;
339 9) prechecks 3 && { select_sessions || (( SEL-- )); } ;;
340 10) prechecks 3 && { select_packages || (( SEL-- )); } ;;
341 11) prechecks 3 && select_show ;;
342 12) prechecks 3 && install_main ;;
343 *) yesno "Exit" "\nUnmount partitions (if any) and exit the installer?\n" && die 0
349 if [[ $SYS == 'BIOS' ]]; then
350 dlg BOOTLDR menu "BIOS Bootloader" "\nSelect which bootloader to use." \
351 "grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
352 "syslinux" "A collection of boot loaders for booting drives, CDs, or over the network" || return 1
354 dlg BOOTLDR menu "UEFI Bootloader" "\nSelect which bootloader to use." \
355 "systemd-boot" "A simple UEFI boot manager which executes configured EFI images" \
356 "grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
357 "refind-efi" "A UEFI boot manager that aims to be platform neutral and simplify multi-boot" \
358 "efistub" "Boot the kernel image directly (no chainloading support)" \
359 "syslinux" "A collection of boot loaders for booting drives, CDs, or over the network (no chainloading support)" || return 1
367 local cmd="${BCMDS[$BOOTLDR]}"
368 local pkgs="${USER_PKGS// / } ${PACKAGES// / }"
369 [[ $BOOT_PART ]] && mnt="/$BOOTDIR"
370 [[ $INSTALL_WMS == *dwm* ]] && pkgs="dwm st dmenu $pkgs"
371 msg "Show Configuration" "
373 ---------- PARTITION CONFIGURATION ------------
375 Root: ${ROOT_PART:-none}
376 Boot: ${BOOT_PART:-${BOOT_DEV:-none}}
378 Swap: ${SWAP_PART:-none}
379 Size: ${SWAP_SIZE:-none}
384 Extra: ${EXMNTS:-${EXMNT:-none}}
385 Hooks: ${HOOKS:-none}
388 ---------- BOOTLOADER CONFIGURATION -----------
390 Bootloader: ${BOOTLDR:-none}
391 Mountpoint: ${mnt:-none}
392 Command: ${cmd:-none}
395 ------------ SYSTEM CONFIGURATION -------------
397 Locale: ${MYLOCALE:-none}
398 Keymap: ${KEYMAP:-none}
399 Hostname: ${MYHOST:-none}
400 Timezone: ${ZONE:-none}/${SUBZ:-none}
403 ------------ USER CONFIGURATION --------------
405 User: ${NEWUSER:-none}
406 Shell: ${MYSHELL:-none}
407 Session: ${LOGIN_WM:-none}
408 Autologin: ${AUTOLOGIN:-none}
409 Login Method: ${LOGIN_TYPE:-none}
412 ------------ PACKAGES AND MIRRORS -------------
414 Kernel: ${KERNEL:-none}
415 Sessions: ${INSTALL_WMS:-none}
416 Packages: $(print4 "${pkgs:-none}")
422 if (( WM_NUM == 1 )); then
423 LOGIN_WM="${WM_SESSIONS[$INSTALL_WMS]}"
425 dlg LOGIN_WM menu "Login Session" "$_login" $LOGIN_CHOICES || return 1
426 LOGIN_WM="${WM_SESSIONS[$LOGIN_WM]}"
429 local txt="\nDo you want autologin enabled for $NEWUSER?\n\nThe following two files will be created (disable autologin by remove them):\n\n - /home/$NEWUSER/$LOGINRC (this runs startx when logging in on tty1)\n - /etc/systemd/system/getty@tty1.service.d/autologin.conf (this logs in $NEWUSER without a password)\n"
430 yesno "Autologin" "$txt" && AUTOLOGIN=true || AUTOLOGIN=''
431 EDIT_FILES[login]="/home/$NEWUSER/.xinitrc /home/$NEWUSER/.xprofile"
439 until [[ $CONFIG_DONE ]]; do
442 dlg MYSHELL menu "Shell" "\nChoose which shell to use." \
443 /usr/bin/zsh 'A very advanced and programmable command interpreter (shell) for UNIX' \
444 /bin/bash 'The GNU Bourne Again shell, standard in many GNU/Linux distributions' \
445 /usr/bin/mksh 'The MirBSD Korn Shell - an enhanced version of the public domain ksh' || return 1
448 1) dlg MYHOST input "Hostname" "$_hostname" "${DIST,,}" limit || { i=0; continue; } ;;
449 2) dlg MYLOCALE menu "Locale" "$_locale" $LOCALES || { i=1; continue; } ;;
451 until [[ $ZONE && $SUBZ ]]; do
452 dlg ZONE menu "Timezone" "$_timez" America - Australia - Asia - Atlantic - Africa - Europe - Indian - Pacific - Arctic - Antarctica - || break
453 dlg SUBZ menu "Timezone" "$_timesubz" $(awk '/'"$ZONE"'\// {gsub(/'"$ZONE"'\//, ""); print $3 " - "}' /usr/share/zoneinfo/zone.tab | sort) || continue
454 yesno "Timezone" "\nConfirm time zone: $ZONE/$SUBZ\n" || unset ZONE
456 [[ $ZONE && $SUBZ ]] || { i=2; continue; } ;;
458 dlg KERNEL menu "Kernel" "\nChoose which kernel to use." \
459 linux 'Vanilla linux kernel and modules, with a few patches applied' \
460 linux-lts 'Long-term support (LTS) linux kernel and modules' \
461 linux-zen 'A effort of kernel hackers to provide the best kernel for everyday systems' \
462 linux-hardened 'A security-focused linux kernel with hardening patches to mitigate exploits' || { i=3; continue; }
467 (( i++ )) # progress through to the next choice
471 '/bin/bash') LOGINRC='.bash_profile' ;;
472 '/usr/bin/zsh') LOGINRC='.zprofile' ;;
473 '/usr/bin/mksh') LOGINRC='.profile' ;;
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
506 # root passwords empty, so use the user passwords
507 [[ -z $rp && -z $rp2 ]] && { rp="$p"; rp2="$p2"; }
509 # make sure a username was entered and that the passwords match
510 if [[ ${#u} -eq 0 || $u =~ \ |\' || $u =~ [^a-z0-9] ]]; then
511 msg "Invalid Username" "\nIncorrect user name.\n\nPlease try again.\n"; u=''
512 elif [[ -z $p ]]; then
513 msg "Empty Password" "\nThe user password cannot be left empty.\n\nPlease try again.\n"
514 elif [[ "$p" != "$p2" ]]; then
515 msg "Password Mismatch" "\nThe user passwords do not match.\n\nPlease try again.\n"
516 elif [[ "$rp" != "$rp2" ]]; then
517 msg "Password Mismatch" "\nThe root passwords do not match.\n\nPlease try again.\n"
529 dlg KEYMAP menu "Keyboard Layout" "$_keymap" \
530 us English cm English gb English au English gh English \
531 za English ng English ca French 'cd' French gn French \
532 tg French fr French de German at German ch German \
533 es Spanish latam Spanish br Portuguese pt Portuguese ma Arabic \
534 sy Arabic ara Arabic ua Ukrainian cz Czech ru Russian \
535 sk Slovak nl Dutch it Italian hu Hungarian cn Chinese \
536 tw Taiwanese vn Vietnamese kr Korean jp Japanese th Thai \
537 la Lao pl Polish se Swedish is Icelandic 'fi' Finnish \
538 dk Danish be Belgian in Indian al Albanian am Armenian \
539 bd Bangla ba Bosnian 'bg' Bulgarian dz Berber mm Burmese \
540 hr Croatian gr Greek il Hebrew ir Persian iq Iraqi \
541 af Afghani fo Faroese ge Georgian ee Estonian kg Kyrgyz \
542 kz Kazakh lt Lithuanian mt Maltese mn Mongolian ro Romanian \
543 no Norwegian rs Serbian si Slovenian tj Tajik lk Sinhala \
544 tr Turkish uz Uzbek ie Irish pk Urdu 'mv' Dhivehi \
545 np Nepali et Amharic sn Wolof ml Bambara tz Swahili \
546 ke Swahili bw Tswana ph Filipino my Malay tm Turkmen \
547 id Indonesian bt Dzongkha lv Latvian md Moldavian mao Maori \
548 by Belarusian az Azerbaijani mk Macedonian kh Khmer epo Esperanto \
549 me Montenegrin || return 1
551 if [[ $CMAPS == *"$KEYMAP"* ]]; then
554 dlg CMAP menu "Console Keymap" "$_vconsole" $CMAPS || return 1
557 if [[ $DISPLAY && $TERM != 'linux' ]]; then
558 setxkbmap "$KEYMAP" >/dev/null 2>&1
560 loadkeys "$CMAP" >/dev/null 2>&1
570 dlg INSTALL_WMS check "Sessions" "$_sessions\n" \
571 i3-gaps "A fork of i3wm with more features including gaps" "$(ofn i3-gaps "${INSTALL_WMS[*]}")" \
572 openbox "A lightweight, powerful, and highly configurable stacking wm" "$(ofn openbox "${INSTALL_WMS[*]}")" \
573 bspwm "A tiling wm that represents windows as the leaves of a binary tree" "$(ofn bspwm "${INSTALL_WMS[*]}")" \
574 dwm "A fork of dwm, with more layouts and features" "$(ofn dwm "${INSTALL_WMS[*]}")" \
575 fluxbox "A lightweight and highly-configurable window manager" "$(ofn fluxbox "${INSTALL_WMS[*]}")" \
576 gnome "A desktop environment that aims to be simple and easy to use" "$(ofn gnome "${INSTALL_WMS[*]}")" \
577 cinnamon "A desktop environment combining traditional desktop with modern effects" "$(ofn cinnamon "${INSTALL_WMS[*]}")" \
578 plasma "A kde software project currently comprising a full desktop environment" "$(ofn plasma "${INSTALL_WMS[*]}")" \
579 xfce4 "A lightweight and modular desktop environment based on gtk+2/3" "$(ofn xfce4 "${INSTALL_WMS[*]}")" || return 1
582 while IFS=' ' read -r i; do
584 done <<< "$INSTALL_WMS"
587 WM_PKGS="${INSTALL_WMS/dwm/}" # remove dwm from package list
588 WM_PKGS="${WM_PKGS// / }" # remove double spaces
589 WM_PKGS="${WM_PKGS# }" # remove leading space
591 # add archlabs base when choosing any session
592 [[ $WM_PKGS ]] && WM_PKGS+=" $AL_BASE_PKGS"
594 for i in $INSTALL_WMS; do
595 LOGIN_CHOICES+="$i - "
596 [[ ${WM_EXT[$i]} && $WM_PKGS != *"${WM_EXT[$i]}"* ]] && WM_PKGS+=" ${WM_EXT[$i]}"
599 select_login || return 1
601 while IFS=' ' read -r pkg; do
602 [[ $PACKAGES != *"$pkg"* ]] && PACKAGES+=" $pkg"
610 dlg USER_PKGS check " Packages " "$_packages" \
611 abiword "A Fully-featured word processor" "$(ofn abiword "${USER_PKGS[*]}")" \
612 alacritty "A cross-platform, GPU-accelerated terminal emulator" "$(ofn alacritty "${USER_PKGS[*]}")" \
613 atom "An open-source text editor developed by GitHub" "$(ofn atom "${USER_PKGS[*]}")" \
614 audacious "A free and advanced audio player based on GTK+" "$(ofn audacious "${USER_PKGS[*]}")" \
615 audacity "A program that lets you manipulate digital audio waveforms" "$(ofn audacity "${USER_PKGS[*]}")" \
616 cairo-dock "Light eye-candy fully themable animated dock" "$(ofn cairo-dock "${USER_PKGS[*]}")" \
617 calligra "A set of applications for productivity" "$(ofn calligra "${USER_PKGS[*]}")" \
618 chromium "An open-source web browser based on the Blink rendering engine" "$(ofn chromium "${USER_PKGS[*]}")" \
619 clementine "A modern music player and library organizer" "$(ofn clementine "${USER_PKGS[*]}")" \
620 cmus "A small, fast and powerful console music player" "$(ofn cmus "${USER_PKGS[*]}")" \
621 deadbeef "A GTK+ audio player for GNU/Linux" "$(ofn deadbeef "${USER_PKGS[*]}")" \
622 deluge "A BitTorrent client written in python" "$(ofn deluge "${USER_PKGS[*]}")" \
623 docky "Full fledged dock for opening applications and managing windows" "$(ofn docky "${USER_PKGS[*]}")" \
624 emacs "An extensible, customizable, self-documenting real-time display editor" "$(ofn emacs "${USER_PKGS[*]}")" \
625 epiphany "A GNOME web browser based on the WebKit rendering engine" "$(ofn epiphany "${USER_PKGS[*]}")" \
626 evince "A document viewer" "$(ofn evince "${USER_PKGS[*]}")" \
627 evolution "Manage your email, contacts and schedule" "$(ofn evolution "${USER_PKGS[*]}")" \
628 file-roller "Create and modify archives" "$(ofn file-roller "${USER_PKGS[*]}")" \
629 firefox "A popular open-source web browser from Mozilla" "$(ofn firefox "${USER_PKGS[*]}")" \
630 gcolor2 "A simple GTK+2 color selector" "$(ofn gcolor2 "${USER_PKGS[*]}")" \
631 geany "A fast and lightweight IDE" "$(ofn geany "${USER_PKGS[*]}")" \
632 geary "A lightweight email client for the GNOME desktop" "$(ofn geary "${USER_PKGS[*]}")" \
633 gimp "GNU Image Manipulation Program" "$(ofn gimp "${USER_PKGS[*]}")" \
634 gnome-disk-utility "Disk Management Utility" "$(ofn gnome-disk-utility "${USER_PKGS[*]}")" \
635 gnome-system-monitor "View current processes and monitor system state" "$(ofn gnome-system-monitor "${USER_PKGS[*]}")" \
636 gparted "A GUI frontend for creating and manipulating partition tables" "$(ofn gparted "${USER_PKGS[*]}")" \
637 gpick "Advanced color picker using GTK+ toolkit" "$(ofn gpick "${USER_PKGS[*]}")" \
638 gpicview "Lightweight image viewer" "$(ofn gpicview "${USER_PKGS[*]}")" \
639 guvcview "Capture video from camera devices" "$(ofn guvcview "${USER_PKGS[*]}")" \
640 hexchat "A popular and easy to use graphical IRC client" "$(ofn hexchat "${USER_PKGS[*]}")" \
641 inkscape "Professional vector graphics editor" "$(ofn inkscape "${USER_PKGS[*]}")" \
642 irssi "Modular text mode IRC client" "$(ofn irssi "${USER_PKGS[*]}")" \
643 kdenlive "A popular non-linear video editor for Linux" "$(ofn kdenlive "${USER_PKGS[*]}")" \
644 krita "Edit and paint images" "$(ofn krita "${USER_PKGS[*]}")" \
645 libreoffice-fresh "Full featured office suite" "$(ofn libreoffice-fresh "${USER_PKGS[*]}")" \
646 lollypop "A new music playing application" "$(ofn lollypop "${USER_PKGS[*]}")" \
647 mousepad "A simple text editor" "$(ofn mousepad "${USER_PKGS[*]}")" \
648 mpd "A flexible, powerful, server-side application for playing music" "$(ofn mpd "${USER_PKGS[*]}")" \
649 mpv "A media player based on mplayer" "$(ofn mpv "${USER_PKGS[*]}")" \
650 mupdf "Lightweight PDF and XPS viewer" "$(ofn mupdf "${USER_PKGS[*]}")" \
651 mutt "Small but very powerful text-based mail client" "$(ofn mutt "${USER_PKGS[*]}")" \
652 nautilus "The default file manager for Gnome" "$(ofn nautilus "${USER_PKGS[*]}")" \
653 ncmpcpp "A mpd client and almost exact clone of ncmpc with some new features" "$(ofn ncmpcpp "${USER_PKGS[*]}")" \
654 neovim "A fork of Vim aiming to improve user experience, plugins, and GUIs." "$(ofn neovim "${USER_PKGS[*]}")" \
655 nicotine+ "A graphical client for Soulseek" "$(ofn nicotine+ "${USER_PKGS[*]}")" \
656 noto-fonts "Google Noto fonts" "$(ofn noto-fonts "${USER_PKGS[*]}")" \
657 noto-fonts-cjk "Google Noto CJK fonts (Chinese, Japanese, Korean)" "$(ofn noto-fonts-cjk "${USER_PKGS[*]}")" \
658 obs-studio "Free opensource streaming/recording software" "$(ofn obs-studio "${USER_PKGS[*]}")" \
659 openshot "An open-source, non-linear video editor for Linux" "$(ofn openshot "${USER_PKGS[*]}")" \
660 opera "A Fast and secure, free of charge web browser from Opera Software" "$(ofn opera "${USER_PKGS[*]}")" \
661 pcmanfm "A fast and lightweight file manager based in Lxde" "$(ofn pcmanfm "${USER_PKGS[*]}")" \
662 pidgin "Multi-protocol instant messaging client" "$(ofn pidgin "${USER_PKGS[*]}")" \
663 plank "An elegant, simple, and clean dock" "$(ofn plank "${USER_PKGS[*]}")" \
664 qbittorrent "An advanced BitTorrent client" "$(ofn qbittorrent "${USER_PKGS[*]}")" \
665 qpdfview "A tabbed PDF viewer" "$(ofn qpdfview "${USER_PKGS[*]}")" \
666 qt5ct "GUI for managing Qt based application themes, icons, and fonts" "$(ofn qt5ct "${USER_PKGS[*]}")" \
667 qutebrowser "A keyboard-focused vim-like web browser based on Python and PyQt5" "$(ofn qutebrowser "${USER_PKGS[*]}")" \
668 rhythmbox "A Music playback and management application" "$(ofn rhythmbox "${USER_PKGS[*]}")" \
669 rxvt-unicode "A unicode enabled rxvt-clone terminal emulator" "$(ofn rxvt-unicode "${USER_PKGS[*]}")" \
670 sakura "A terminal emulator based on GTK and VTE" "$(ofn sakura "${USER_PKGS[*]}")" \
671 simplescreenrecorder "A feature-rich screen recorder" "$(ofn simplescreenrecorder "${USER_PKGS[*]}")" \
672 steam "A popular game distribution platform by Valve" "$(ofn steam "${USER_PKGS[*]}")" \
673 surf "A simple web browser based on WebKit2/GTK+" "$(ofn surf "${USER_PKGS[*]}")" \
674 terminator "Terminal emulator that supports tabs and grids" "$(ofn terminator "${USER_PKGS[*]}")" \
675 termite "A minimal VTE-based terminal emulator" "$(ofn termite "${USER_PKGS[*]}")" \
676 thunar "A modern file manager for the Xfce Desktop Environment" "$(ofn thunar "${USER_PKGS[*]}")" \
677 thunderbird "Standalone mail and news reader from mozilla" "$(ofn thunderbird "${USER_PKGS[*]}")" \
678 tilda "A GTK based drop down terminal for Linux and Unix" "$(ofn tilda "${USER_PKGS[*]}")" \
679 tilix "A tiling terminal emulator for Linux using GTK+ 3" "$(ofn tilix "${USER_PKGS[*]}")" \
680 transmission-cli "Free BitTorrent client CLI" "$(ofn transmission-cli "${USER_PKGS[*]}")" \
681 transmission-gtk "Free BitTorrent client GTK+ GUI" "$(ofn transmission-gtk "${USER_PKGS[*]}")" \
682 transmission-qt "Free BitTorrent client Qt GUI" "$(ofn transmission-qt "${USER_PKGS[*]}")" \
683 ttf-anonymous-pro "A family fixed-width fonts designed with code in mind" "$(ofn ttf-anonymous-pro "${USER_PKGS[*]}")" \
684 ttf-fira-code "Monospaced font with programming ligatures" "$(ofn ttf-fira-code "${USER_PKGS[*]}")" \
685 ttf-font-awesome "Iconic font designed for Bootstrap" "$(ofn ttf-font-awesome "${USER_PKGS[*]}")" \
686 ttf-hack "A hand groomed typeface based on Bitstream Vera Mono" "$(ofn ttf-hack "${USER_PKGS[*]}")" \
687 vlc "A free and open source cross-platform multimedia player" "$(ofn vlc "${USER_PKGS[*]}")" \
688 weechat "Fast, light and extensible IRC client" "$(ofn weechat "${USER_PKGS[*]}")" \
689 xarchiver "A GTK+ frontend to various command line archivers" "$(ofn xarchiver "${USER_PKGS[*]}")" \
690 xfce-terminal "A terminal emulator based in the Xfce Desktop Environment" "$(ofn xfce-terminal "${USER_PKGS[*]}")" \
691 xterm "The standard terminal emulator for the X window system" "$(ofn xterm "${USER_PKGS[*]}")" \
692 zathura "Minimalistic document viewer" "$(ofn zathura "${USER_PKGS[*]}")"
694 if [[ $USER_PKGS ]]; then
695 for i in $USER_PKGS; do
696 [[ ${PKG_EXT[$i]} && $USER_PKGS != *"${PKG_EXT[$i]}"* ]] && USER_PKGS+=" ${PKG_EXT[$i]}"
703 ###############################################################################
708 check_background_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 "resize" "Resize an existing ext2/3/4 or ntfs 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 "resize" "Resize an existing ext2/3/4 or ntfs 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 == 'resize' ]]; then
739 part_resize "$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" && part_auto "$device" "$table" "$boot_fs" "$root_size"
766 if [[ $devhash != "$(lsblk -f | base64)" ]]; then
767 msg "Probing Partitions" "\nInforming the kernel of partition changes using partprobe.\n" 0
768 partprobe >/dev/null 2>&1
776 if [[ $IGNORE_DEV ]]; then
777 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk "!/$IGNORE_DEV/"' && /disk|part|lvm|crypt|NAME/')"
779 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk '/disk|part|lvm|crypt|NAME/')"
781 msg "Device Tree" "\n\n$txt\n\n"
786 if [[ $1 == "$MNT/swapfile" && $SWAP_SIZE ]]; then
787 fallocate -l $SWAP_SIZE "$1" 2>$ERR
788 errshow "fallocate -l $SWAP_SIZE $1"
789 chmod 600 "$1" 2>$ERR
790 errshow "chmod 600 $1"
792 mkswap "$1" >/dev/null 2>$ERR
794 swapon "$1" >/dev/null 2>$ERR
801 local device="$1" table="$2" boot_fs="$3" size="$4" dev_info=""
802 dev_info="$(parted -s "$device" print)"
804 msg "Auto Partition" "\nRemoving partitions on $device and setting table to $table\n" 1
807 while read -r PART; do
808 parted -s "$device" rm "$PART" >/dev/null 2>&1
809 done <<< "$(awk '/^ [1-9][0-9]?/ {print $1}' <<< "$dev_info" | sort -r)"
811 [[ $(awk '/Table:/ {print $3}' <<< "$dev_info") != "$table" ]] && parted -s "$device" mklabel "$table" >/dev/null 2>&1
813 msg "Auto Partition" "\nCreating a 512M $boot_fs boot partition.\n" 1
814 if [[ $SYS == "BIOS" ]]; then
815 parted -s "$device" mkpart primary "$boot_fs" 1MiB 513MiB >/dev/null 2>&1
817 parted -s "$device" mkpart ESP "$boot_fs" 1MiB 513MiB >/dev/null 2>&1
822 AUTO_BOOT_PART=$(lsblk -lno NAME,TYPE "$device" | awk 'NR==2 {print "/dev/" $1}')
824 if [[ $SYS == "BIOS" ]]; then
825 mkfs.ext4 -q "$AUTO_BOOT_PART" >/dev/null 2>&1
827 mkfs.vfat -F32 "$AUTO_BOOT_PART" >/dev/null 2>&1
830 msg "Auto Partition" "\nCreating a $size ext4 root partition.\n" 0
831 parted -s "$device" mkpart primary ext4 513MiB 100% >/dev/null 2>&1
833 AUTO_ROOT_PART="$(lsblk -lno NAME,TYPE "$device" | awk 'NR==3 {print "/dev/" $1}')"
834 mkfs.ext4 -q "$AUTO_ROOT_PART" >/dev/null 2>&1
836 FORMATTED+="$AUTO_BOOT_PART $AUTO_ROOT_PART "
837 msg "Auto Partition" "\nProcess complete.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$device")\n"
842 local regexp="$1" err=''
844 # string of partitions as /TYPE/PART SIZE
845 if [[ $IGNORE_DEV ]]; then
846 PARTS="$(lsblk -lno TYPE,NAME,SIZE |
847 awk "/$regexp/"' && !'"/$IGNORE_DEV/"' {
848 sub(/^part/, "/dev/")
849 sub(/^lvm|^crypt/, "/dev/mapper/")
853 PARTS="$(lsblk -lno TYPE,NAME,SIZE |
855 sub(/^part/, "/dev/")
856 sub(/^lvm|^crypt/, "/dev/mapper/")
861 # number of partitions total
863 while read -r line; do
867 # ensure we have enough partitions for the system and action type
869 'part|lvm|crypt') [[ $COUNT -lt 1 || ($SYS == 'UEFI' && $COUNT -lt 2) ]] && err="$_errpart" ;;
870 'part|crypt') (( COUNT < 1 )) && err="$_lvmerr" ;;
871 'part|lvm') (( COUNT < 2 )) && err="$_lukserr" ;;
874 # if there aren't enough partitions show the relevant error message
875 [[ $err ]] && { msg "Not Enough Partitions" "$err" 2; return 1; }
882 local part="$1" mountp="${MNT}$2" fs=""
883 fs="$(lsblk -lno FSTYPE "$part")"
886 if [[ $fs && ${FS_OPTS[$fs]} && $part != "$BOOT_PART" ]] && select_mntopts "$fs"; then
887 mount -o "$MNT_OPTS" "$part" "$mountp" >/dev/null 2>&1
889 mount "$part" "$mountp" >/dev/null 2>&1
892 part_mountconf "$part" "$mountp" || return 1
900 local part="$1" fs="$2" delay="$3"
902 msg "Format" "\nFormatting $part as $fs\n" 0
903 ${FS_CMDS[$fs]} "$part" >/dev/null 2>$ERR
904 errshow "${FS_CMDS[$fs]} $part" || return 1
913 local device="$1" fs=""
915 part_find "${device##*/}[^ ]" || return 1
916 (( COUNT == 1 )) && part="$(awk '{print $1}' <<< "${PARTS[@]}" )"
918 if (( COUNT == 1 )) || dlg part menu "Resize" "\nWhich partition on $device do you want to resize?" $PARTS && [[ $part ]]; then
919 fs=$(lsblk -lno FSTYPE "$part")
922 msg "Resize" "\nGathering device size info.\n" 0
924 # shit hacks to get device size info
926 end=$(parted -s "$device" print | awk '/^\s*'"$num"'/ {print $3}')
927 devsize=$(parted -s "$device" print | awk '/Disk '"${device//\//\\/}"':/ {print $3}')
928 mount "$part" $MNT >/dev/null 2>&1; sleep 0.5
929 min=$(df "$part" | awk '/'"${part//\//\\/}"'/ {print int($3 / 1024)}') # used
930 max=$(df "$part" | awk '/'"${part//\//\\/}"'/ {print int($4 / 1024)}') # available
931 umount $MNT >/dev/null 2>&1
933 # get new size from user
935 if dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Resize: $part " --rangebox "$_resize" 17 "$COLUMNS" "$min" "$max" $((max / 2)) 2>$ANS; then
936 (( (size = $(< "$ANS")) + 1025 <= max )) || return 1
937 size=$((( (size * 1024) / 4 ) * 4)) # 4K block alignment
945 e2fsck -f "$part"; sleep 0.5
946 resize2fs -f "$part" ${size}K 2>$ERR
947 errshow "resize2fs -f $part ${size}K" { echo 'press enter to continue'; read; return 1; }
949 ntfs) ntfsresize -f -s ${size}k "$part" || { echo 'press enter to continue'; read; return 1; } ;;
954 parted "$device" resizepart "$num" ${size}Kib || return 1
957 if (( ++size < (max * 1024) )); then
958 if [[ $devsize == "$end" ]]; then
959 parted -s "$device" mkpart primary ext4 ${size}Kib 100% 2>$ERR
961 parted -s "$device" mkpart primary ext4 ${size}Kib "$end" 2>$ERR
963 errshow "parted -s $device mkpart primary ext4 ${size}Kib 100%" || return 1
967 msg "Resize Complete" "\n$part has been successfully resized to $(( (size - 1025) / 1024 ))M.\n"
969 *) msg "Invalid Filesystem: $fs" "\nResizing only supports ext and ntfs.\n\nFor unformatted partitions, cfdisk can be used.\n" ;;
976 if [[ $DEV_COUNT -eq 1 && $SYS_DEVS ]]; then
977 DEVICE="$(awk '{print $1}' <<< "$SYS_DEVS")"
978 elif (( DEV_COUNT > 1 )); then
980 dlg DEVICE menu "Boot Device" "\nSelect the device to use for bootloader install." $SYS_DEVS
982 dlg DEVICE menu "Select Device" "$_device" $SYS_DEVS
984 [[ $DEVICE ]] || return 1
985 elif [[ $DEV_COUNT -lt 1 && ! $1 ]]; then
986 msg "Device Error" "\nNo available devices.\n\nExiting..\n" 2; die 1
989 [[ $1 ]] && BOOT_DEV="$DEVICE"
996 BOOT_DEV="${BOOT_PART%[1-9]}"
997 BOOT_PART_NUM="${BOOT_PART: -1}"
998 [[ $BOOT_PART = /dev/nvme* ]] && BOOT_DEV="${BOOT_PART%p[1-9]}"
999 if [[ $SYS == 'UEFI' ]]; then
1000 parted -s $BOOT_DEV set $BOOT_PART_NUM esp on >/dev/null 2>&1
1002 parted -s $BOOT_DEV set $BOOT_PART_NUM boot on >/dev/null 2>&1
1009 local part="$1" devs=""
1010 devs="$(lsblk -lno NAME,FSTYPE,TYPE)"
1012 # Identify if $part is LUKS+LVM, LVM+LUKS, LVM alone, or LUKS alone
1013 if lsblk -lno TYPE "$part" | grep -q 'crypt'; then
1015 LUKS_NAME="${part#/dev/mapper/}"
1017 for dev in $(awk '/lvm/ && /crypto_LUKS/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
1018 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1019 LUKS_DEV="$LUKS_DEV cryptdevice=$dev:$LUKS_NAME"
1020 LVM='logical volume'
1025 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
1026 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1027 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
1028 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
1033 elif lsblk -lno TYPE "$part" | grep -q 'lvm'; then
1034 LVM='logical volume'
1035 VNAME="${part#/dev/mapper/}"
1037 for dev in $(awk '/crypt/ && /lvm2_member/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
1038 if lsblk -lno NAME "$dev" | grep -q "$VNAME"; then
1039 LUKS_NAME="${dev/\/dev\/mapper\//}"
1044 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
1045 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1046 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
1047 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
1058 if (( COUNT > 0 )); then
1059 PARTS="$(sed "/${i//\//\\/}/d" <<< "$PARTS")"
1067 if grep -qw "$1" /proc/mounts; then
1068 msg "Mount Success" "\nPartition $1 mounted at $2\n" 1
1072 msg "Mount Fail" "\nPartition $1 failed to mount at $2\n" 2
1077 ###############################################################################
1082 check_background_install || return 0
1085 part_find 'part|lvm|crypt' || { SEL=2; return 1; }
1087 [[ $LUKS && $LUKS_PART ]] && part_countdec $LUKS_PART
1088 [[ $LVM && $LVM_PARTS ]] && part_countdec $LVM_PARTS
1090 select_root_partition || return 1
1092 if [[ $SYS == 'UEFI' ]]; then
1093 select_efi_partition || { BOOT_PART=''; return 1; }
1094 elif (( COUNT > 0 )); then
1095 select_boot_partition || { BOOT_PART=''; return 1; }
1098 if [[ $BOOT_PART ]]; then
1099 part_mount "$BOOT_PART" "/$BOOTDIR" && SEP_BOOT=true || return 1
1103 select_swap || return 1
1104 select_extra_partitions || return 1
1105 install_background || return 1
1112 dlg SWAP_PART menu "Swap Setup" "\nSelect whether to use a swapfile, swap partition, or none." \
1113 "none" "Don't allocate any swap space" \
1114 "swapfile" "Allocate $SYS_MEM at /swapfile" \
1117 if [[ -z $SWAP_PART || $SWAP_PART == "none" ]]; then
1120 elif [[ $SWAP_PART == "swapfile" ]]; then
1122 until [[ ${SWAP_SIZE:0:1} =~ [1-9] && ${SWAP_SIZE: -1} =~ (M|G) ]]; do
1123 (( 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
1124 dlg SWAP_SIZE input "Swap Setup" "$_swapsize" "$SYS_MEM" || { SWAP_PART=''; SWAP_SIZE=''; return 1; }
1127 part_swap "$MNT/$SWAP_PART"
1128 SWAP_PART="/$SWAP_PART"
1129 elif [[ $PARTS == *"$SWAP_PART"* ]]; then
1130 part_swap $SWAP_PART
1131 part_countdec $SWAP_PART
1132 SWAP_SIZE="$(lsblk -lno SIZE $SWAP_PART)"
1142 local fs="$1" opts=''
1143 local title="${fs^} Mount Options"
1145 for i in ${FS_OPTS[$fs]}; do
1149 until [[ $MNT_OPTS ]]; do
1150 dlg MNT_OPTS check "$title" "$_mount" $opts
1151 [[ $MNT_OPTS ]] || return 1
1152 MNT_OPTS="${MNT_OPTS// /,}"
1153 yesno "$title" "\nConfirm the following options: $MNT_OPTS\n" || MNT_OPTS=''
1162 until [[ $EXMNT ]]; do
1163 dlg EXMNT input "Extra Mount $part" "$_exmnt" "/" || return 1
1164 if [[ ${EXMNT:0:1} != "/" || ${#EXMNT} -le 1 || $EXMNT =~ \ |\' || $EXMNTS == *"$EXMNT"* ]]; then
1165 msg "Mountpoint Error" "$_errexpart"
1174 local part="$1" fs='' cur=''
1175 local txt="\nSelect which filesystem to use for: $part\n\nDefault: ext4"
1176 cur="$(lsblk -lno FSTYPE "$part" 2>/dev/null)"
1179 if [[ $cur && ($part != "$ROOT_PART" || $FORMATTED == *"$part"*) ]]; then
1180 dlg fs menu "Filesystem" "$txt\nCurrent: $cur" skip - ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1182 dlg fs menu "Filesystem" "$txt" ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1184 [[ $fs == 'skip' ]] && return 0
1185 yesno "Filesystem" "\nFormat $part as $fs?\n" || fs=''
1187 part_format "$part" "$fs"
1190 select_efi_partition()
1192 if (( COUNT == 1 )); then
1193 BOOT_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
1194 elif [[ $AUTO_BOOT_PART ]]; then
1195 BOOT_PART="$AUTO_BOOT_PART"
1196 return 0 # were done here
1198 dlg BOOT_PART menu "EFI Partition" "$_uefi" $PARTS
1201 [[ $BOOT_PART ]] || return 1
1203 if grep -q 'fat' <<< "$(fsck -N "$BOOT_PART")"; then
1204 local txt="\nIMPORTANT:\n\nThe EFI partition $BOOT_PART $_format"
1205 if yesno "Format EFI Partition" "$txt" "Format $BOOT_PART" "Skip Formatting" 1; then
1206 part_format "$BOOT_PART" "vfat" 2
1209 part_format "$BOOT_PART" "vfat" 2
1215 select_boot_partition()
1217 if [[ $AUTO_BOOT_PART && ! $LVM ]]; then
1218 BOOT_PART="$AUTO_BOOT_PART"; return 0 # were done here
1219 elif [[ $LUKS && ! $LVM ]]; then
1220 dlg BOOT_PART menu "Boot Partition" "$_biosluks" $PARTS
1221 [[ $BOOT_PART ]] || return 1
1223 dlg BOOT_PART menu "Boot Partition" "$_bios" "skip" "don't use a separate boot" $PARTS
1224 [[ -z $BOOT_PART || $BOOT_PART == "skip" ]] && { BOOT_PART=''; return 0; }
1227 if grep -q 'ext[34]' <<< "$(fsck -N "$BOOT_PART")"; then
1228 local txt="\nIMPORTANT:\n\nThe boot partition $BOOT_PART $_format"
1229 if yesno "Format Boot Partition" "$txt" "Format $BOOT_PART" "Skip Formatting" 1; then
1230 part_format "$BOOT_PART" "ext4" 2
1233 part_format "$BOOT_PART" "ext4" 2
1238 select_root_partition()
1240 if [[ $AUTO_ROOT_PART && -z $LVM && -z $LUKS ]]; then
1241 ROOT_PART="$AUTO_ROOT_PART"
1242 elif (( COUNT == 1 )); then
1243 ROOT_PART="$(awk 'NR==1 {print $1}' <<< "$PARTS")"
1245 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." $PARTS
1247 [[ $ROOT_PART ]] || return 1
1249 select_filesystem "$ROOT_PART" || { ROOT_PART=''; return 1; }
1250 part_mount "$ROOT_PART" || { ROOT_PART=''; return 1; }
1255 select_extra_partitions()
1258 while (( COUNT > 0 )); do
1260 dlg part menu 'Mount Extra' "$_expart" 'done' 'finish mounting step' $PARTS || break
1261 if [[ $part == 'done' ]]; then
1263 elif select_filesystem "$part" && select_mountpoint && part_mount "$part" "$EXMNT"; then
1264 EXMNTS+="$part: $EXMNT "
1265 [[ $EXMNT == '/usr' && $HOOKS != *usr* ]] && HOOKS="usr $HOOKS"
1273 ###############################################################################
1281 genfstab -U $MNT >$MNT/etc/fstab 2>$ERR
1282 errshow 1 "genfstab -U $MNT >$MNT/etc/fstab"
1283 [[ -f $MNT/swapfile ]] && sed -i "s~${MNT}~~" $MNT/etc/fstab
1287 chrun "hwclock --systohc --utc" || chrun "hwclock --systohc --utc --directisa"
1290 chrun "chown -Rf $NEWUSER:users /home/$NEWUSER"
1294 dlg choice menu "Finalization" "$_edit" \
1295 finished "exit the installer and reboot" \
1296 keyboard "${EDIT_FILES[keyboard]}" \
1297 console "${EDIT_FILES[console]}" \
1298 locale "${EDIT_FILES[locale]}" \
1299 hostname "${EDIT_FILES[hostname]}" \
1300 sudoers "${EDIT_FILES[sudoers]}" \
1301 mkinitcpio "${EDIT_FILES[mkinitcpio]}" \
1302 fstab "${EDIT_FILES[fstab]}" \
1303 crypttab "${EDIT_FILES[crypttab]}" \
1304 bootloader "${EDIT_FILES[bootloader]}" \
1305 pacman "${EDIT_FILES[pacman]}" \
1306 login "${EDIT_FILES[login]}"
1308 if [[ -z $choice || $choice == 'finished' ]]; then
1309 [[ $DEBUG == true && -r $DBG ]] && vim $DBG
1313 for f in ${EDIT_FILES[$choice]}; do
1314 [[ -e ${MNT}$f ]] && exists+=" ${MNT}$f"
1316 if [[ $exists ]]; then
1319 msg "File Missing" "\nThe file(s) selected do not exist:\n\n${EDIT_FILES[$choice]}\n"
1327 if [[ $RSYNC_PID || $MIRROR_PID ]]; then
1328 while kill -0 "$RSYNC_PID" 2>/dev/null || kill -0 "$MIRROR_PID" 2>/dev/null; do
1329 clear; printf "\nOne or more background install processes are still running...\n"; sleep 1
1332 unset RSYNC_PID MIRROR_PID
1333 elif [[ -d /run/archiso/sfs/airootfs/etc/skel ]]; then
1334 rsync -ahv /run/archiso/sfs/airootfs/ $MNT/ 2>$ERR
1335 errshow 1 "rsync -ahv /run/archiso/sfs/airootfs/ $MNT/"
1336 install_mirrorlist "$MNT/etc/pacman.d/mirrorlist"
1337 chrun "pacman -Syyu --noconfirm && pacman -S $BASE_PKGS --needed --noconfirm"
1339 mkdir -p /etc/pacman.d/mirrorlist
1340 install_mirrorlist "/etc/pacman.d/mirrorlist"
1341 pacstrap $MNT base $ISO_BASE 2>$ERR
1342 errshow 1 "pacstrap $MNT base $KERNEL $ISO_BASE"
1343 mkdir -p $MNT/etc/pacman.d/mirrorlist
1344 cp -f "/etc/pacman.d/mirrorlist" "$MNT/etc/pacman.d/mirrorlist"
1345 chrun "pacman -Syyu --noconfirm && pacman -S $BASE_PKGS --needed --noconfirm"
1348 rm -rf $MNT/etc/mkinitcpio-archiso.conf
1349 find $MNT/usr/lib/initcpio -name 'archiso*' -type f -delete
1350 sed -i 's/volatile/auto/g' $MNT/etc/systemd/journald.conf
1351 find $MNT/boot -name '*-ucode.img' -delete
1354 find $MNT/etc/X11/xorg.conf.d/ -name '*.conf' -delete
1355 elif lspci | grep ' VGA ' | grep -q 'Intel'; then
1356 cat > $MNT/etc/X11/xorg.conf.d/20-intel.conf << EOF
1358 Identifier "Intel Graphics"
1360 Option "TearFree" "true"
1365 [[ -e /run/archiso/sfs/airootfs && $KERNEL == 'linux' ]] && cp -vf $RUN/x86_64/vmlinuz $MNT/boot/vmlinuz-linux
1367 cp -fv /etc/resolv.conf $MNT/etc/
1368 [[ -e /etc/NetworkManager/system-connections ]] && cp -rvf /etc/NetworkManager/system-connections $MNT/etc/NetworkManager/
1370 echo "LANG=$MYLOCALE" > $MNT/etc/locale.conf
1371 cp -f $MNT/etc/locale.conf $MNT/etc/default/locale
1372 sed -i "s/#en_US.UTF-8/en_US.UTF-8/g; s/#${MYLOCALE}/${MYLOCALE}/g" $MNT/etc/locale.gen
1374 chrun "ln -svf /usr/share/zoneinfo/$ZONE/$SUBZ /etc/localtime"
1376 if [[ $BROADCOM_WL ]]; then
1377 echo 'blacklist bcma' >> $MNT/etc/modprobe.d/blacklist.conf
1378 rm -f $MNT/etc/modprobe/
1381 cat > $MNT/etc/X11/xorg.conf.d/00-keyboard.conf << EOF
1382 # Use localectl(1) to instruct systemd-localed to update it.
1383 Section "InputClass"
1384 Identifier "system-keyboard"
1385 MatchIsKeyboard "on"
1386 Option "XkbLayout" "$KEYMAP"
1389 cat > $MNT/etc/default/keyboard << EOF
1390 # KEYBOARD CONFIGURATION FILE
1391 # Consult the keyboard(5) manual page.
1398 printf "KEYMAP=%s\nFONT=%s\n" "$CMAP" "$FONT" > $MNT/etc/vconsole.conf
1399 echo "$MYHOST" > $MNT/etc/hostname
1400 cat > $MNT/etc/hosts << EOF
1403 ::1 localhost ip6-localhost ip6-loopback
1404 ff02::1 ip6-allnodes
1405 ff02::2 ip6-allrouters
1411 if [[ $ROOT_PART == /dev/mapper* ]]; then
1412 ROOT_PART_ID="$ROOT_PART"
1414 local uuid_type="UUID"
1415 [[ $BOOTLDR =~ (systemd-boot|refind-efi|efistub) ]] && uuid_type="PARTUUID"
1416 ROOT_PART_ID="$uuid_type=$(blkid -s $uuid_type -o value $ROOT_PART)"
1419 if [[ $SYS == 'UEFI' ]]; then
1420 find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname "$DIST" -type d -delete
1421 find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname 'boot' -type d -delete
1425 chrun "${BCMDS[$BOOTLDR]}" 2>$ERR
1426 errshow 1 "${BCMDS[$BOOTLDR]}"
1428 if [[ -d $MNT/hostrun ]]; then
1429 umount $MNT/hostrun/udev >/dev/null 2>&1
1430 umount $MNT/hostrun/lvm >/dev/null 2>&1
1431 rm -rf $MNT/hostrun >/dev/null 2>&1
1434 if [[ $SYS == 'UEFI' ]]; then
1435 # some UEFI firmware requires a generic esp/BOOT/BOOTX64.EFI
1436 mkdir -pv $MNT/$BOOTDIR/EFI/BOOT
1437 if [[ $BOOTLDR == 'grub' ]]; then
1438 cp -fv $MNT/$BOOTDIR/EFI/$DIST/grubx64.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI
1439 elif [[ $BOOTLDR == 'syslinux' ]]; then
1440 cp -rf $MNT/$BOOTDIR/EFI/syslinux/* $MNT/$BOOTDIR/EFI/BOOT/
1441 cp -f $MNT/$BOOTDIR/EFI/syslinux/syslinux.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI
1442 elif [[ $BOOTLDR == 'refind-efi' ]]; then
1443 sed -i '/#extra_kernel_version_strings/ c extra_kernel_version_strings linux-hardened,linux-zen,linux-lts,linux' $MNT/$BOOTDIR/EFI/refind/refind.conf
1444 cp -fv $MNT/$BOOTDIR/EFI/refind/refind_x64.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI
1453 chrun "chpasswd <<< 'root:$ROOT_PASS'" 2>$ERR
1454 errshow 1 "set root password"
1455 if [[ $MYSHELL != *zsh ]]; then
1456 chrun "usermod -s $MYSHELL root" 2>$ERR
1457 errshow 1 "usermod -s $MYSHELL root"
1458 [[ $MYSHELL == "/usr/bin/mksh" ]] && cp -fv $MNT/etc/skel/.mkshrc /root/.mkshrc
1461 local groups='audio,autologin,floppy,log,network,rfkill,scanner,storage,optical,power,wheel'
1463 chrun "groupadd -r autologin" 2>$ERR
1464 errshow 1 "groupadd -r autologin"
1465 chrun "useradd -m -u 1000 -g users -G $groups -s $MYSHELL $NEWUSER" 2>$ERR
1466 errshow 1 "useradd -m -u 1000 -g users -G $groups -s $MYSHELL $NEWUSER"
1467 chrun "chpasswd <<< '$NEWUSER:$USER_PASS'" 2>$ERR
1468 errshow 1 "set $NEWUSER password"
1470 if [[ $USER_PKGS == *neovim* ]]; then
1471 mkdir -p $MNT/home/$NEWUSER/.config/nvim
1472 cp -fv $MNT/home/$NEWUSER/.vimrc $MNT/home/$NEWUSER/.config/nvim/init.vim
1473 cp -rfv $MNT/home/$NEWUSER/.vim/colors $MNT/home/$NEWUSER/.config/nvim/colors
1476 [[ $INSTALL_WMS == *dwm* ]] && install_suckless
1477 [[ $LOGIN_WM =~ (startkde|gnome-session) ]] && sed -i '/super/d' $MNT/home/$NEWUSER/.xprofile /root/.xprofile
1484 SERVICE="$MNT/etc/systemd/system/getty@tty1.service.d"
1485 sed -i '/printf/d' $MNT/root/.zshrc
1487 if [[ -e $MNT/home/$NEWUSER/.xinitrc ]] && grep -q 'exec' $MNT/home/$NEWUSER/.xinitrc; then
1488 sed -i "/exec/ c exec ${LOGIN_WM}" $MNT/home/$NEWUSER/.xinitrc
1490 printf "exec %s\n" "$LOGIN_WM" >> $MNT/home/$NEWUSER/.xinitrc
1493 [[ ${EDIT_FILES[login]} == *"$LOGINRC"* ]] || EDIT_FILES[login]+=" /home/$NEWUSER/$LOGINRC"
1495 if [[ $AUTOLOGIN ]]; then
1496 sed -i "s/root/${NEWUSER}/g" $SERVICE/autologin.conf
1497 cat > $MNT/home/$NEWUSER/$LOGINRC <<EOF
1499 # sourced by ${MYSHELL##*/} when used as a login shell
1501 # automatically run startx when logging in on tty1
1502 [[ -z \$DISPLAY && \$XDG_VTNR -eq 1 ]] && exec startx -- vt1
1506 rm -rf $MNT/home/$NEWUSER/.{profile,zprofile,bash_profile}
1513 local inpkg="$PACKAGES $USER_PKGS"
1515 if pacman -Qsq 'archlabs-installer' >/dev/null 2>&1; then
1516 rmpkg+=" archlabs-installer"
1517 elif [[ -e "$MNT/usr/bin/archlabs-installer" ]]; then
1518 rm -f "$MNT/usr/bin/archlabs-installer"
1521 [[ $UCODE ]] && inpkg+=" $UCODE"
1522 [[ $MYSHELL == *mksh ]] && inpkg+=" mksh"
1523 [[ $KERNEL == 'linux' ]] || { inpkg+=" $KERNEL"; rmpkg+=" linux"; }
1524 [[ $inpkg =~ (term|urxvt|tilix|alacritty|sakura|tilda|plasma|cinnamon) || $INSTALL_WMS == *dwm* ]] || inpkg+=" xterm"
1525 [[ $MYSHELL == '/usr/bin/zsh' ]] && inpkg+=" zsh-completions"
1526 [[ $INSTALL_WMS =~ ^(plasma|gnome|cinnamon)$ ]] || inpkg+=" archlabs-ksuperkey"
1527 [[ $INSTALL_WMS =~ (openbox|bspwm|i3-gaps|dwm|fluxbox) ]] && inpkg+=" $WM_BASE_PKGS"
1529 chrun "pacman -Syyu --noconfirm"
1530 [[ $rmpkg ]] && chrun "pacman -Rns $rmpkg --noconfirm"
1531 chrun "pacman -S iputils --noconfirm"
1532 chrun "pacman -S $inpkg --needed --noconfirm" 2>$ERR
1533 errshow 1 "pacman -S $inpkg --needed --noconfirm"
1535 if [[ $BOOTLDR == 'grub' ]]; then
1536 if [[ $SYS == 'BIOS' ]]; then
1537 chrun "pacman -S grub os-prober --needed --noconfirm" 2>$ERR
1538 errshow 1 "pacman -S grub os-prober --needed --noconfirm"
1540 chrun "pacman -S grub os-prober efibootmgr --needed --noconfirm" 2>$ERR
1541 errshow 1 "pacman -S grub os-prober efibootmgr --needed --noconfirm"
1543 elif [[ $BOOTLDR == 'refind-efi' ]]; then
1544 chrun "pacman -S refind-efi efibootmgr --needed --noconfirm" 2>$ERR
1545 errshow 1 "pacman -S refind-efi efibootmgr --needed --noconfirm"
1546 elif [[ $SYS == 'UEFI' ]]; then
1547 chrun "pacman -S efibootmgr --needed --noconfirm" 2>$ERR
1548 errshow 1 "pacman -S efibootmgr --needed --noconfirm"
1550 sed -i "s/# %wheel ALL=(ALL) ALL/%wheel ALL=(ALL) ALL/g" $MNT/etc/sudoers
1556 mkdir -pv $MNT/home/$NEWUSER/suckless
1558 for i in dwm dmenu st; do
1559 if chrun "git clone https://git.suckless.org/$i /home/$NEWUSER/suckless/$i"; then
1560 chrun "cd /home/$NEWUSER/suckless/$i; make PREFIX=/usr install; make clean; rm config.h"
1562 printf "failed to clone %s repo\n" "$i"
1566 if [[ -d $MNT/home/$NEWUSER/suckless/dwm && -x $MNT/usr/bin/dwm ]]; then
1567 printf "To configure dwm edit %s\n" "/home/$NEWUSER/suckless/dwm/config.h"
1568 printf "You can then recompile it with 'sudo make clean install'\n"
1573 install_mkinitcpio()
1577 # luks keyfile creation
1578 # currently not used due to not prompting for passphrase on startup
1579 # [[ $LUKS_UUID && $LUKS_PASS && $SYS == 'UEFI' && $BOOTLDR == 'grub' ]] && luks_keyfile
1581 [[ $LUKS ]] && add="encrypt"
1582 [[ $LVM ]] && { [[ $add ]] && add+=" lvm2" || add+="lvm2"; }
1583 sed -i "s/block filesystems/block ${add} filesystems ${HOOKS}/g" $MNT/etc/mkinitcpio.conf
1584 chrun "mkinitcpio -p $KERNEL" 2>$ERR
1585 errshow 1 "mkinitcpio -p $KERNEL"
1588 install_mirrorlist()
1592 if hash reflector >/dev/null 2>&1; then
1593 reflector --score 120 -l 50 -f 5 --sort rate --save "$mfile"
1594 elif hash rankmirrors >/dev/null 2>&1; then
1595 i="$(json 'ip' "check&?access_key=5f29642060ab983b31fdf4c2935d8c56&fields=ip")"
1596 c="$(json 'country_code' "${i}?access_key=5f29642060ab983b31fdf4c2935d8c56&fields=country_code")"
1597 if [[ $c && $c =~ (CA|US) ]]; then
1598 m="https://www.archlinux.org/mirrorlist/?country=US&country=CA&use_mirror_status=on"
1600 m="https://www.archlinux.org/mirrorlist/?country=${c}&use_mirror_status=on"
1602 m="https://www.archlinux.org/mirrorlist/?country=US&country=CA&country=NZ&country=GB&country=AU&use_mirror_status=on"
1604 curl -s "$m" | sed -e 's/^#Server/Server/' -e '/^#/d' | rankmirrors -t -n 10 - | tail -n 10 >"$mfile"
1609 install_background()
1611 if [[ -d /run/archiso/sfs/airootfs/etc/skel ]] && grep -qw "$MNT" /proc/mounts && (grep -qw "$MNT/$BOOTDIR" /proc/mounts || [[ $SYS == 'BIOS' && -z $LUKS ]]); then
1612 yesno "Background Install" "\nSome parts of the install can be done in the background now, base unpack, mirrorlist sort, system update, and base packages.\n\nDo you want to start the background process?\n" || return 0
1613 rsync -a /run/archiso/sfs/airootfs/ $MNT/ &
1615 ( install_mirrorlist "$MNT/etc/pacman.d/mirrorlist" && chrun "pacman -Syyu $BASE_PKGS --needed --noconfirm" ) >/dev/null 2>&1 &
1617 trap "kill $RSYNC_PID 2>/dev/null; kill $MIRROR_PID 2>/dev/null" EXIT
1622 ###############################################################################
1627 EDIT_FILES[bootloader]="/etc/default/grub"
1629 if [[ $SYS == 'BIOS' ]]; then
1630 [[ $BOOT_DEV ]] || { part_device 1 || return 1; }
1631 BCMDS[grub]="grub-install --recheck --force --target=i386-pc $BOOT_DEV"
1633 if [[ $ROOT_PART == */dev/mapper/* && -z $LVM && -z $LUKS_PASS ]]; then
1634 luks_pass "$_luksopen" 1 || return 1
1636 BCMDS[grub]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1637 grub-install --recheck --force --target=x86_64-efi --efi-directory=/$BOOTDIR --bootloader-id=$DIST"
1638 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1641 BCMDS[grub]="mkdir -p /run/udev /run/lvm &&
1642 mount --bind /hostrun/udev /run/udev &&
1643 mount --bind /hostrun/lvm /run/lvm &&
1645 grub-mkconfig -o /boot/grub/grub.cfg &&
1646 sleep 1 && umount /run/udev /run/lvm"
1653 sed -i "s/GRUB_DISTRIBUTOR=.*/GRUB_DISTRIBUTOR=\"${DIST}\"/g;
1654 s/GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT=\"\"/g" $MNT/etc/default/grub
1656 if [[ $LUKS_DEV ]]; then
1657 sed -i "s~#GRUB_ENABLE_CRYPTODISK~GRUB_ENABLE_CRYPTODISK~g;
1658 s~GRUB_CMDLINE_LINUX=.*~GRUB_CMDLINE_LINUX=\"${LUKS_DEV}\"~g" $MNT/etc/default/grub 2>$ERR
1659 errshow 1 "sed -i 's~#GRUB_ENABLE_CRYPTODISK~GRUB_ENABLE_CRYPTODISK~g;
1660 s~GRUB_CMDLINE_LINUX=.*~GRUB_CMDLINE_LINUX=\"${LUKS_DEV}\"~g' $MNT/etc/default/grub"
1663 if [[ $SYS == 'BIOS' && $LVM && -z $SEP_BOOT ]]; then
1664 sed -i "s/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g" $MNT/etc/default/grub 2>$ERR
1665 errshow 1 "sed -i 's/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g' $MNT/etc/default/grub"
1668 # setup for os-prober module
1669 mkdir -p /run/{lvm,udev}
1670 mkdir -p $MNT/hostrun/{lvm,udev}
1671 mount --bind /run/lvm $MNT/hostrun/lvm
1672 mount --bind /run/udev $MNT/hostrun/udev
1679 EDIT_FILES[bootloader]=""
1684 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1685 efibootmgr -v -d $BOOT_DEV -p $BOOT_PART_NUM -c -L '${DIST} Linux' -l /vmlinuz-${KERNEL} \
1686 -u 'root=$ROOT_PART_ID rw $([[ $UCODE ]] && printf 'initrd=\%s.img ' "$UCODE")initrd=\initramfs-${KERNEL}.img'"
1692 if [[ $SYS == 'BIOS' ]]; then
1693 EDIT_FILES[bootloader]="/boot/syslinux/syslinux.cfg"
1695 EDIT_FILES[bootloader]="/boot/EFI/syslinux/syslinux.cfg"
1696 BCMDS[syslinux]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1697 efibootmgr -v -c -d $BOOT_DEV -p $BOOT_PART_NUM -l /EFI/syslinux/syslinux.efi -L $DIST"
1704 local c="$MNT/boot/syslinux" s="/usr/lib/syslinux/bios" d=".."
1705 [[ $SYS == 'UEFI' ]] && { c="$MNT/boot/EFI/syslinux"; s="/usr/lib/syslinux/efi64/"; d=''; }
1707 mkdir -pv "$c" && cp -rfv $s/* "$c/" && cp -f "$RUN/syslinux/splash.png" "$c/"
1708 cat > "$c/syslinux.cfg" << EOF
1710 MENU TITLE $DIST Boot Menu
1711 MENU BACKGROUND splash.png
1715 # see: https://www.syslinux.org/wiki/index.php/Comboot/menu.c32
1724 MENU HELPMSGENDROW 29
1725 MENU COLOR border 30;44 #40ffffff #a0000000 std
1726 MENU COLOR title 1;36;44 #9033ccff #a0000000 std
1727 MENU COLOR sel 7;37;40 #e0ffffff #20ffffff all
1728 MENU COLOR unsel 37;44 #50ffffff #a0000000 std
1729 MENU COLOR help 37;40 #c0ffffff #a0000000 std
1730 MENU COLOR timeout_msg 37;40 #80ffffff #00000000 std
1731 MENU COLOR timeout 1;37;40 #c0ffffff #00000000 std
1732 MENU COLOR msg07 37;40 #90ffffff #a0000000 std
1733 MENU COLOR tabmsg 31;40 #30ffffff #00000000 std
1736 MENU LABEL $DIST Linux
1737 LINUX $d/vmlinuz-$KERNEL
1738 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1739 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL.img
1741 LABEL ${DIST}fallback
1742 MENU LABEL $DIST Linux Fallback
1743 LINUX $d/vmlinuz-$KERNEL
1744 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1745 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL-fallback.img
1746 $([[ $SYS == 'BIOS' ]] && printf "\n%s" "# examples of chainloading other bootloaders
1751 #APPEND file=$d/grub/boot.img
1763 EDIT_FILES[bootloader]="/boot/refind_linux.conf"
1764 BCMDS[refind-efi]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1770 cat > $MNT/boot/refind_linux.conf << EOF
1771 "$DIST Linux" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] &&
1772 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1773 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL.img"
1774 "$DIST Linux Fallback" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] &&
1775 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1776 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL-fallback.img"
1778 mkdir -p $MNT/etc/pacman.d/hooks
1779 cat > $MNT/etc/pacman.d/hooks/refind.hook << EOF
1786 Description = Updating rEFInd on ESP
1787 When = PostTransaction
1788 Exec = /usr/bin/refind-install
1792 setup_systemd-boot()
1794 EDIT_FILES[bootloader]="/boot/loader/entries/$DIST.conf"
1795 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1796 bootctl --path=/boot install"
1799 prerun_systemd-boot()
1801 mkdir -p $MNT/boot/loader/entries
1802 cat > $MNT/boot/loader/loader.conf << EOF
1807 cat > $MNT/boot/loader/entries/$DIST.conf << EOF
1809 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1810 initrd /initramfs-$KERNEL.img
1811 options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1813 cat > $MNT/boot/loader/entries/$DIST-fallback.conf << EOF
1814 title $DIST Linux Fallback
1815 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1816 initrd /initramfs-$KERNEL-fallback.img
1817 options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1819 mkdir -p $MNT/etc/pacman.d/hooks
1820 cat > $MNT/etc/pacman.d/hooks/systemd-boot.hook << EOF
1827 Description = Updating systemd-boot
1828 When = PostTransaction
1829 Exec = /usr/bin/bootctl update
1831 systemd-machine-id-setup --root="$MNT"
1835 ###############################################################################
1840 check_background_install || return 1
1843 dlg choice menu "Logical Volume Management" "$_lvmmenu" \
1844 "$_lvmnew" "vgcreate -f, lvcreate -L -n" \
1845 "$_lvmdel" "vgremove -f" \
1846 "$_lvmdelall" "lvrmeove, vgremove, pvremove -f" \
1847 "back" "return to the main menu"
1850 "$_lvmnew") lvm_create || return 1 ;;
1851 "$_lvmdel") lvm_delgroup && yesno "$_lvmdel" "$_lvmdelask" && vgremove -f "$DEL_VG" >/dev/null 2>&1 ;;
1852 "$_lvmdelall") lvm_del_all ;;
1861 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
1862 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
1863 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
1865 if [[ $VGROUP && $v && $pv ]]; then
1866 msg "Logical Volume Management" "\nActivating existing logical volume management (LVM).\n\n" 1
1867 modprobe dm-mod >/dev/null 2>$ERR
1868 errshow 'modprobe dm-mod'
1869 vgscan >/dev/null 2>&1
1870 vgchange -ay >/dev/null 2>&1
1876 VGROUP='' LVM_PARTS='' VGROUP_MB=0
1878 lvm_mkgroup || return 1
1879 local txt="\nThe last (or only) logical volume will automatically use all remaining space in the volume group."
1880 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
1881 [[ $VOL_COUNT ]] || return 1
1882 lvm_extra_lvs || return 1
1883 lvm_volume_name "$_lvmlvname\nNOTE: This LV will use up all remaining space in the volume group (${VGROUP_MB}MB)" || return 1
1884 lvcreate -l +100%FREE "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
1885 errshow "lvcreate -l +100%FREE $VGROUP -n $VNAME" || return 1
1886 LVM='logical volume'; sleep 0.5
1887 txt="\nDone, volume: $VGROUP-$VNAME (${VOLUME_SIZE:-${VGROUP_MB}MB}) has been created.\n"
1888 msg "$_lvmnew (LV:$VOL_COUNT)" "$txt\n$(lsblk -o NAME,MODEL,TYPE,FSTYPE,SIZE $LVM_PARTS)\n"
1894 local txt="${VGROUP}: ${SIZE}$SIZE_UNIT (${VGROUP_MB}MB remaining).$_lvmlvsize"
1898 dlg VOLUME_SIZE input "$_lvmnew (LV:$VOL_COUNT)" "$txt" ''
1899 if [[ -z $VOLUME_SIZE ]]; then
1901 break # allow bailing with escape or an empty choice
1902 elif (( ${VOLUME_SIZE:0:1} == 0 )); then
1903 ERR_SIZE=1 # size values can't begin with '0'
1905 # walk the string and make sure all but the last char are digits
1906 local lv=$((${#VOLUME_SIZE} - 1))
1907 for (( i=0; i<lv; i++ )); do
1908 [[ ${VOLUME_SIZE:$i:1} =~ [0-9] ]] || { ERR_SIZE=1; break; }
1910 if (( ERR_SIZE != 1 )); then
1911 case ${VOLUME_SIZE:$lv:1} in
1912 [mMgG]) local s=${VOLUME_SIZE:0:$lv} m=$((s * 1000))
1913 case ${VOLUME_SIZE:$lv:1} in
1914 [Gg]) (( m >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - m)) ;;
1915 [Mm]) (( ${VOLUME_SIZE:0:$lv} >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - s)) ;;
1922 if (( ERR_SIZE )); then
1923 msg "Invalid Logical Volume Size" "$_lvmerrlvsize"
1935 local txt="\nConfirm creation of volume group: $VGROUP\n\nwith the following partition(s):"
1937 until [[ $named ]]; do
1938 lvm_partitions || return 1
1939 lvm_group_name || return 1
1940 yesno "$_lvmnew" "$txt $LVM_PARTS\n" && named=true
1943 vgcreate -f "$VGROUP" $LVM_PARTS >/dev/null 2>$ERR
1944 errshow "vgcreate -f $VGROUP $LVM_PARTS" || return 1
1946 SIZE=$(vgdisplay "$VGROUP" | awk '/VG Size/ { gsub(/[^0-9.]/, ""); print int($0) }')
1947 SIZE_UNIT="$(vgdisplay "$VGROUP" | awk '/VG Size/ { print substr($NF, 0, 1) }')"
1949 if [[ $SIZE_UNIT == 'G' ]]; then
1950 VGROUP_MB=$((SIZE * 1000))
1955 msg "$_lvmnew" "\nVolume group: $VGROUP ($SIZE $SIZE_UNIT) has been created\n"
1962 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
1963 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
1964 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
1966 if [[ $VGROUP || $v || $pv ]]; then
1967 if yesno "$_lvmdelall" "$_lvmdelask"; then
1968 for i in $v; do lvremove -f "/dev/mapper/$i" >/dev/null 2>&1; done
1969 for i in $VGROUP; do vgremove -f "$i" >/dev/null 2>&1; done
1970 for i in $pv; do pvremove -f "$i" >/dev/null 2>&1; done
1974 msg "Delete LVM" "\nNo LVMs to remove...\n" 2
1984 for i in $(lvs --noheadings | awk '{print $2}' | uniq); do
1985 VOL_GROUP_LIST+="$i $(vgdisplay "$i" | awk '/VG Size/ {print $3$4}') "
1987 [[ $VOL_GROUP_LIST ]] || { msg "No Groups" "\nNo volume groups found."; return 1; }
1989 dlg DEL_VG menu "Logical Volume Management" "\nSelect volume group to delete.\n\nAll logical volumes within will also be deleted." $VOL_GROUP_LIST
1995 while (( VOL_COUNT > 1 )); do
1996 lvm_volume_name "$_lvmlvname" && get_lv_size || return 1
1997 lvcreate -L "$VOLUME_SIZE" "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
1998 errshow "lvcreate -L $VOLUME_SIZE $VGROUP -n $VNAME" || return 1
1999 msg "$_lvmnew (LV:$VOL_COUNT)" "\nDone, logical volume (LV) $VNAME ($VOLUME_SIZE) has been created.\n"
2007 part_find 'part|crypt' || return 1
2008 PARTS="$(awk 'NF > 0 {print $0 " off"}' <<< "$PARTS")"
2009 dlg LVM_PARTS check "$_lvmnew" "\nSelect the partition(s) to use for the physical volume (PV)." $PARTS
2016 until [[ $VGROUP ]]; do
2017 dlg VGROUP input "$_lvmnew" "$_lvmvgname" "mygroup"
2018 if [[ -z $VGROUP ]]; then
2020 elif [[ ${VGROUP:0:1} == "/" || $VGROUP =~ \ |\' ]] || lsblk | grep -q "$VGROUP"; then
2021 msg "LVM Name Error" "$_lvmerrvgname"
2031 local txt="$1" default="mainvolume"
2032 (( VOL_COUNT > 1 )) && default="extravolume$VOL_COUNT"
2033 until [[ $VNAME ]]; do
2034 dlg VNAME input "$_lvmnew (LV:$VOL_COUNT)" "\n$txt" "$default"
2035 if [[ -z $VNAME ]]; then
2037 elif [[ ${VNAME:0:1} == "/" || $VNAME =~ \ |\' ]] || lsblk | grep -q "$VNAME"; then
2038 msg "LVM Name Error" "$_lvmerlvname"
2045 ###############################################################################
2051 check_background_install || return 1
2052 dlg choice menu "LUKS Encryption" "$_luksmenu" \
2053 "$_luksnew" "cryptsetup -q luksFormat" \
2054 "$_luksopen" "cryptsetup open --type luks" \
2055 "$_luksadv" "cryptsetup -q -s -c luksFormat" \
2056 "back" "Return to the main menu"
2059 "$_luksnew") luks_basic || return 1 ;;
2060 "$_luksopen") luks_open || return 1 ;;
2061 "$_luksadv") luks_advanced || return 1 ;;
2069 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
2071 part_find 'part|crypt|lvm' || return 1
2073 if (( COUNT == 1 )); then
2074 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2076 dlg LUKS_PART menu "$_luksopen" "\nSelect which partition to open." $PARTS
2079 [[ $LUKS_PART ]] || return 1
2081 luks_pass "$_luksopen" || return 1
2082 msg "$_luksopen" "\nOpening encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2083 cryptsetup open --type luks "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2084 errshow "cryptsetup open --type luks $LUKS_PART $LUKS_NAME" || return 1
2085 LUKS='encrypted'; luks_show
2092 local t="$1" op="$2" v='' p='' p2=''
2094 until [[ $LUKS_PASS ]]; do
2098 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " $t " \
2099 --mixedform "\nEnter the password to decrypt $ROOT_PART\n\nThis is needed to create a keyfile." 0 0 0 \
2100 "Password:" 1 1 '' 1 11 "$COLUMNS" 0 1 \
2101 "Password2:" 2 1 '' 2 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
2104 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " $t " --mixedform "$_luksomenu" 0 0 0 \
2105 "Name:" 1 1 "${LUKS_NAME:-cryptroot}" 1 7 "$COLUMNS" 0 0 \
2106 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
2107 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
2111 while read -r line; do
2127 if [[ -z $op && -z $n ]]; then
2128 msg "Name Empty" "\nEncrypted device name cannot be empty.\n\nPlease try again.\n" 2
2129 elif [[ -z $p || "$p" != "$p2" ]]; then
2130 [[ $op ]] || LUKS_NAME="$n"
2131 msg "Password Mismatch" "\nThe passwords entered do not match.\n\nPlease try again.\n" 2
2133 [[ $op ]] || LUKS_NAME="$n"
2144 msg "$_luksnew" "\nEncrypted partition opened and ready for mounting.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$LUKS_PART")\n\n"
2149 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
2151 part_find 'part|lvm' || return 1
2153 if [[ $AUTO_ROOT_PART ]]; then
2154 LUKS_PART="$AUTO_ROOT_PART"
2155 elif (( COUNT == 1 )); then
2156 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2158 dlg LUKS_PART menu "$_luksnew" "\nSelect the partition you want to encrypt." $PARTS
2161 [[ $LUKS_PART ]] || return 1
2162 luks_pass "$_luksnew"
2167 luks_setup || return 1
2168 msg "$_luksnew" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2169 cryptsetup -q luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2170 errshow "cryptsetup -q luksFormat $LUKS_PART" || return 1
2171 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2172 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2173 LUKS='encrypted'; luks_show
2179 if [[ ! -e $MNT/crypto_keyfile.bin ]]; then
2180 # printf "Creating LUKS keyfile /crypto_keyfile.bin\n"
2182 n="$(lsblk -lno NAME,UUID,TYPE | awk "/$LUKS_UUID/"' && /part|crypt|lvm/ {print $1}')"
2183 local mkkey="dd bs=512 count=8 if=/dev/urandom of=/crypto_keyfile.bin"
2184 mkkey="$mkkey && chmod 000 /crypto_keyfile.bin"
2185 mkkey="$mkkey && cryptsetup luksAddKey /dev/$n /crypto_keyfile.bin <<< '$LUKS_PASS'"
2187 sed -i 's/FILES=()/FILES=(\/crypto_keyfile.bin)/g' $MNT/etc/mkinitcpio.conf 2>$ERR
2197 dlg cipher input "LUKS Encryption" "$_lukskey" "-s 512 -c aes-xts-plain64"
2198 [[ $cipher ]] || return 1
2199 msg "$_luksadv" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2200 cryptsetup -q $cipher luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2201 errshow "cryptsetup -q $cipher luksFormat $LUKS_PART" || return 1
2202 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2203 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2210 ###############################################################################
2215 [[ "$2" == *"$1"* ]] && printf "on" || printf "off"
2224 if [[ -d $MNT ]] && command cd /; then
2226 if (( exitcode == 127 )); then
2227 umount -l /run/archiso/bootmnt
2233 # restore custom linux console 0-15 colors when not rebooting
2234 if [[ $TERM == 'linux' ]]; then
2235 colors=("\e]P0191919" "\e]P1D15355" "\e]P2609960" "\e]P3FFCC66"
2236 "\e]P4255A9B" "\e]P5AF86C8" "\e]P62EC8D3" "\e]P7949494" "\e]P8191919" "\e]P9D15355"
2237 "\e]PA609960" "\e]PBFF9157" "\e]PC4E88CF" "\e]PDAF86C8" "\e]PE2ec8d3" "\e]PFE1E1E1")
2238 printf "%b" "${colors[@]}" && clear && unset col
2246 local var="$1" dialog_type="$2" title="$3" body="$4" n=0
2248 (( ($# / 2) > SHL )) && n=$SHL
2251 case "$dialog_type" in
2253 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --menu "$body" 0 0 $n "$@" 2>"$ANS" || return 1
2256 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --checklist "$body" 0 0 $n "$@" 2>"$ANS" || return 1
2262 if [[ $1 == 'limit' ]]; then
2263 dialog --backtitle "$DIST Installer - $SYS - v$VER" --max-input 63 --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2265 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2269 [[ -s "$ANS" ]] && printf -v "$var" "%s" "$(< "$ANS")"
2274 local title="$1" body="$2"
2276 if (( $# == 3 )); then
2277 dialog --backtitle "$DIST Installer - $SYS - v$VER" --sleep "$3" --title " $title " --infobox "$body\n" 0 0
2279 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --msgbox "$body\n" 0 0
2285 curl -s "http://api.ipstack.com/$2" | python3 -c "import sys, json; print(json.load(sys.stdin)['$1'])"
2290 local title="$1" body="$2" yes='Yes' no='No'
2291 (( $# >= 3 )) && local yes="$3"
2292 (( $# >= 4 )) && local no="$4"
2294 if (( $# == 5 )); then
2295 dialog --backtitle "$DIST Installer - $SYS - v$VER" --defaultno --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2297 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2303 arch-chroot "$MNT" bash -c "$1"
2308 export PS4='| ${BASH_SOURCE} LINE:${LINENO} FUNC:${FUNCNAME[0]:+ ${FUNCNAME[0]}()} |> '
2317 printf "\n^C caught, cleaning up...\n"
2324 if [[ $COLUMNS -ge 110 && ${#str} -gt $((COLUMNS - 30)) ]]; then
2326 i = 2; p1 = p2 = p3 = p4 = ""; p1 = $1; q = int(NF / 4)
2327 for (; i <= q; i++) { p1 = p1 " " $i }
2328 for (; i <= q * 2; i++) { p2 = p2 " " $i }
2329 for (; i <= q * 3; i++) { p3 = p3 " " $i }
2330 for (; i <= NF; i++) { p4 = p4 " " $i }
2331 printf "%s\n %s\n %s\n %s", p1, p2, p3, p4
2333 printf "%s\n" "$str"
2334 elif [[ $str ]]; then
2335 printf "%s\n" "$str"
2342 (( exit_code == 0 )) && return 0
2344 local fatal=0 err=""
2345 err="$(sed 's/[^[:print:]]//g; s/\[[0-9\;:]*\?m//g; s/==> //g; s/] ERROR:/]\nERROR:/g' "$ERR")"
2346 (( $1 == 1 )) && { fatal=1; shift; }
2347 local txt="\nThe command exited abnormally:\n\n$1\n\n"
2350 txt+="With the following message:\n\n$err\n\n"
2352 txt+="With no error message:\n\n"
2355 if (( fatal == 1 )); then
2356 txt+="Errors at this stage are fatal and the install cannot continue.\n"
2358 txt+="Errors at this stage are non-fatal and can be either fixed or ignored depending on the error.\n"
2361 msg "Install Error" "$txt"
2363 if (( fatal == 1 )); then
2364 [[ -r $DBG && $TERM == 'linux' ]] && less "$DBG"
2373 msg "Broadcom Wireless Setup" "\nDetected chipset is Broadcom BCM4352\n\nDisabling bcma/b43 modules and loading wl module.\n" 1
2374 { rmmod wl; rmmod bcma; rmmod b43; rmmod ssb; modprobe wl; depmod -a; } >/dev/null 2>&1
2380 if [[ $1 -ge 0 ]] && ! grep -qw "$MNT" /proc/mounts; then
2381 msg "Not Mounted" "\nPartition(s) must be mounted first.\n" 2
2384 elif [[ $1 -ge 1 && -z $BOOTLDR ]]; then
2385 msg "No Bootloader" "\nBootloader must be selected first.\n" 2
2388 elif [[ $1 -ge 2 && (-z $NEWUSER || -z $USER_PASS) ]]; then
2389 msg "No User" "\nA user must be created first.\n" 2
2392 elif [[ $1 -ge 3 && -z $CONFIG_DONE ]]; then
2393 msg "Not Configured" "\nSystem configuration must be done first.\n" 2
2403 [[ -d $1 ]] && umount -R "$1" >/dev/null 2>&1
2409 msg "Network Connect" "\nVerifying network connection\n" 1
2410 curl -sIN --connect-timeout 5 'https://www.archlinux.org/' | sed '1q' | grep -q '200'
2415 if chk_connect; then
2418 if hash nmtui >/dev/null 2>&1; then
2420 [[ $TERM == 'linux' ]] && printf "%b" "\e]P1191919" "\e]P4191919"
2422 [[ $TERM == 'linux' ]] && printf "%b" "\e]P1D15355" "\e]P4255a9b"
2432 IGNORE_DEV="$(lsblk -lno NAME,MOUNTPOINT | awk '/\/run\/archiso\/bootmnt/ {sub(/[1-9]/, ""); print $1}')"
2434 if [[ $IGNORE_DEV ]]; then
2435 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ && !'"/$IGNORE_DEV/"' {print "/dev/" $1 " " $2}')"
2437 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ {print "/dev/" $1 " " $2}')"
2440 if [[ -z $SYS_DEVS ]]; then
2441 msg "Device Error" "\nNo available devices...\n\nExiting..\n" 2
2446 while read -r line; do
2448 done <<< "$SYS_DEVS"
2455 elif grep -q 'AuthenticAMD' /proc/cpuinfo; then
2457 elif grep -q 'GenuineIntel' /proc/cpuinfo; then
2461 modprobe -q efivarfs >/dev/null 2>&1
2463 _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."
2464 if [[ -d /sys/firmware/efi/efivars ]]; then
2466 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars
2467 _prep+="\n - An EFI boot partition mounted."
2471 _prep+="\n\nOnce finished mounting, a portion of the install can be done in the background while you continue configuring the system:\n"
2472 _prep+="\n - Choose the system bootloader.\n - Create a user and password."
2473 _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."
2476 check_background_install()
2478 [[ $RSYNC_PID || $MIRROR_PID ]] || return 0
2479 msg "Install Running" "\nA background install process is currently running.\n" 2
2483 ###############################################################################
2486 if (( UID != 0 )); then
2487 msg "Not Root" "\nThis installer must be run as root or using sudo.\n\nExiting..\n" 2
2489 elif ! grep -qwm 1 'lm' /proc/cpuinfo; then
2490 msg "Not x86_64 Architecture" "\nThis installer only supports x86_64 architectures.\n\nExiting..\n" 2
2492 elif [[ $1 =~ (-d|--debug) ]]; then
2496 # trap ^C to perform cleanup
2502 msg "Welcome to the $DIST Installer" "\nThis will help you get $DIST setup on your system.\nHaving previous GNU/Linux and shell experience will be an asset, however we try our best to keep things simple.\n\nIf you are unsure about an option, a default will be listed or\nthe first selected option will usually be the default (excluding language and timezone).\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"
2504 select_keymap || { clear; die 0; }
2506 if lspci -vnn -d 14e4: | grep -q 'BCM4352'; then
2510 if ! net_connect; then
2511 msg "Not Connected" "\nThis installer requires an active internet connection.\n\nExiting..\n" 2
2519 # vim:fdm=marker:fmr={,}