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.47" # 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 using the mount menu.
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 # ------------------------------------------------------ #
39 # bulk default values {
41 EXMNT='' # holder for additional partitions while mounting
42 EXMNTS='' # when an extra partition is mounted append it's info
44 FONT="ter-i16n" # font used for the linux console
45 HOOKS="shutdown" # list of additional HOOKS to add in /etc/mkinitcpio.conf
47 LOGINRC='' # login shell rc file, eg. .zprofile, .bash_profile, .profile
48 LOGIN_WM='' # default login session to be placed in ~/.xinitrc
49 LOGIN_TYPE='' # login manager can be: lightdm, xinit
50 INSTALL_WMS='' # space separated list of chosen wm/de
52 UCODE='' # cpu microcode (if any), eg. amd-ucode, intel-ucode
53 KERNEL='' # can be linux, linux-lts, linux-zen, or linux-hardened
54 MYSHELL='' # full path for the shell, eg. /usr/bin/zsh
56 WM_PKGS='' # full list of packages added during wm/de choice
57 PACKAGES='' # list of all packages to install including WM_PKGS
58 USER_PKGS='' # packages selected by the user during install
60 NEWUSER='' # username for the new user
61 USER_PASS='' # new user's password
62 ROOT_PASS='' # root password
64 LUKS='' # empty when not using encryption
65 LUKS_DEV='' # boot parameter string for LUKS
66 LUKS_PART='' # partition used for encryption
67 LUKS_PASS='' # encryption password
68 LUKS_UUID='' # encrypted partition UUID
69 LUKS_NAME='' # name used for encryption
71 LVM='' # empty when not using lvm
72 LVM_PARTS='' # partitions used for volume group
73 VGROUP_MB=0 # available space in volume group
75 WARN='' # issued mounting/partitioning warning
76 SEP_BOOT='' # separate boot partition for BIOS
77 AUTOLOGIN='' # enable autologin for xinit
78 CONFIG_DONE='' # basic configuration is finished
79 BROADCOM_WL='' # fixes for broadcom cards eg. BCM4352
81 FORMATTED='' # partitions we formatted and should allow skipping
82 AUTO_ROOT_PART='' # root value from auto partition
83 AUTO_BOOT_PART='' # boot value from auto partition
85 SWAP_PART='' # swap partition or file path
86 SWAP_SIZE='' # swap size, only used when creating a swapfile
88 # iso base, pacstrap when running the installer from a stock arch iso
89 ISO_BASE="b43-firmware b43-fwcutter broadcom-wl clonezilla dhclient dhcpcd ethtool wpa_supplicant "
90 ISO_BASE+="exfat-utils f2fs-tools gptfdisk vim hdparm ipw2100-fw ipw2200-fw nfs-utils nilfs-utils ntfs-3g "
91 ISO_BASE+="pacman-contrib parted rsync sdparm smartmontools wget wireless_tools wpa_actiond xl2tpd dialog parted "
92 ISO_BASE+="alsa-firmware alsa-lib alsa-plugins pulseaudio pulseaudio-alsa networkmanager w3m htop wireless-regdb "
93 ISO_BASE+="lm_sensors lsb-release p7zip pamixer reflector unrar ranger terminus-font ttf-dejavu archlabs-keyring"
95 # archlabs base packages
96 AL_BASE_PKGS="archlabs-skel-base archlabs-fonts archlabs-themes archlabs-dARK archlabs-icons archlabs-wallpapers archlabs-scripts"
98 # baseline (usually installed in the background)
99 BASE_PKGS="base-devel xorg xorg-drivers xorg-xinit sudo git gvfs gtk3 gtk-engines gtk-engine-murrine pavucontrol tumbler "
100 BASE_PKGS+="playerctl ffmpeg gstreamer libmad libmatroska gst-libav gst-plugins-base gst-plugins-good scrot"
102 # extras for window managers
103 WM_BASE_PKGS="arandr archlabs-networkmanager-dmenu xdg-user-dirs nitrogen polkit-gnome volumeicon xclip exo "
104 WM_BASE_PKGS+="xdotool compton wmctrl gnome-keyring dunst feh gsimplecal xfce4-power-manager xfce4-settings laptop-detect"
107 SEL=0 # currently selected menu item
108 ERR="/tmp/errlog" # error log used internally
109 DBG="/tmp/debuglog" # debug log when passed -d
110 RUN="/run/archiso/bootmnt/arch/boot" # path for live /boot
111 VM="$(dmesg | grep -i "hypervisor")" # is the system a vm
114 export DIALOGOPTS="--cr-wrap"
118 # giant ugly variable container :P {
120 # RAM in the system in MB
121 SYS_MEM="$(awk '/MemTotal/ {print int($2 / 1024) "M"}' /proc/meminfo)"
123 # locales from /etc/locale.gen
124 LOCALES="$(awk '/\.UTF-8/ {gsub(/# .*|#/, ""); if ($1) {print $1 " - "}}' /etc/locale.gen)"
126 # linux console keyboard mappings
127 CMAPS="$(find /usr/share/kbd/keymaps -name '*.map.gz' | awk '{gsub(/\.map\.gz|.*\//, ""); print $1 " - "}' | sort)"
129 # terminal size definitions
130 [[ $LINES ]] || LINES=$(tput lines)
131 [[ $COLUMNS ]] || COLUMNS=$(tput cols)
137 # commands used to install each bootloader (most get modified during runtime) {
139 [refind-efi]='refind-install'
140 [grub]='grub-install --recheck --force'
141 [syslinux]='syslinux-install_update -i -a -m'
142 [efistub]='efibootmgr -v -d /dev/sda -p 1 -c -l'
143 [systemd-boot]='bootctl --path=/boot install'
146 # executable name for each wm/de {
147 declare -A WM_SESSIONS=(
154 [gnome]='gnome-session'
155 [fluxbox]='startfluxbox'
156 [openbox]='openbox-session'
157 [cinnamon]='cinnamon-session'
160 # packages installed for each wm/de {
165 [plasma]='kdebase-meta'
166 [bspwm]='sxhkd archlabs-skel-bspwm rofi archlabs-polybar'
167 [fluxbox]='archlabs-skel-fluxbox archlabs-polybar jgmenu rofi lxmenu-data'
168 [i3-gaps]='i3status perl-anyevent-i3 archlabs-skel-i3-gaps rofi archlabs-polybar'
169 [openbox]='obconf archlabs-skel-openbox jgmenu archlabs-polybar tint2 conky rofi lxmenu-data'
170 [xfce4]='xfce4-goodies xfce4-pulseaudio-plugin network-manager-applet volumeicon rofi archlabs-skel-xfce4'
173 # files that can be edited after install is complete {
174 declare -A EDIT_FILES=(
177 [sudoers]='/etc/sudoers'
178 [crypttab]='/etc/crypttab'
179 [pacman]='/etc/pacman.conf'
180 [console]='/etc/vconsole.conf'
181 [mkinitcpio]='/etc/mkinitcpio.conf'
182 [hostname]='/etc/hostname /etc/hosts'
183 [bootloader]="/boot/loader/entries/$DIST.conf"
184 [locale]='/etc/locale.conf /etc/default/locale'
185 [keyboard]='/etc/X11/xorg.conf.d/00-keyboard.conf /etc/default/keyboard'
188 # mkfs command for formatting each offered filesystem {
193 [ntfs]='mkfs.ntfs -q'
194 [ext2]='mkfs.ext2 -q'
195 [ext3]='mkfs.ext3 -q'
196 [ext4]='mkfs.ext4 -q'
197 [vfat]='mkfs.vfat -F32'
198 [nilfs2]='mkfs.nilfs2 -q'
199 [reiserfs]='mkfs.reiserfs -q'
202 # mount options for each offered filesystem (if any {
208 [jfs]='discard errors=continue errors=panic nointegrity'
209 [reiserfs]='acl nolog notail replayonly user_xattr off'
210 [ext4]='discard dealloc nofail noacl relatime noatime nobarrier nodelalloc'
211 [xfs]='discard filestreams ikeep largeio noalign nobarrier norecovery noquota wsync'
212 [nilfs2]='discard nobarrier errors=continue errors=panic order=relaxed order=strict norecovery'
213 [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'
216 # PKG_EXT: if you add a package to $PACKAGES in any dialog {
217 # and it uses/requires some additional packages,
218 # you can add them here to keep it simple: [package]="extra"
219 # duplicates are removed with `uniq` before install
223 [mupdf]='mupdf-tools'
224 [qt5ct]='qt5-styleplugins'
225 [vlc]='qt5ct qt5-styleplugins'
226 [zathura]='zathura-pdf-poppler'
227 [noto-fonts]='noto-fonts-emoji'
228 [cairo-dock]='cairo-dock-plug-ins'
229 [qutebrowser]='qt5ct qt5-styleplugins'
230 [qbittorrent]='qt5ct qt5-styleplugins'
231 [transmission-qt]='qt5ct qt5-styleplugins'
232 [kdenlive]='kdebase-meta dvdauthor frei0r-plugins breeze breeze-gtk qt5ct qt5-styleplugins'
240 # Basics (somewhat in order)
241 _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"
242 _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"
243 _device="\nSelect a device to use from the list below.\n\nDevices (/dev) are the available drives on the system. /sda, /sdb, /sdc ..."
244 _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."
245 _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."
246 _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"
247 _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)."
248 _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."
249 _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."
250 _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."
251 _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"
252 _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."
253 _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."
254 _exmnt="\nWhere do you want the partition mounted?\n\nEnsure the name begins with a slash (/).\nExamples include: /usr, /home, /var, etc."
255 _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."
256 _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."
257 _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"
258 _timez="\nThe time zone is used to set the system clock.\n\nSelect your country or continent from the list below"
259 _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."
260 _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."
261 _login="\nSelect which of your session choices to use for the initial login.\n\nYou can be change this later by editing your ~/.xinitrc"
262 _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."
263 _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."
266 _luksnew="Basic LUKS Encryption"
267 _luksadv="Advanced LUKS Encryption"
268 _luksopen="Open Existing LUKS Partition"
269 _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."
270 _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."
271 _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)."
274 _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."
275 _lvmnew="Create Volume Group and Volume(s)"
276 _lvmdel="Delete an Existing Volume Group"
277 _lvmdelall="Delete ALL Volume Group(s) and Volume(s)"
278 _lvmvgname="\nEnter a name for the volume group (VG) being created from the partition(s) selected."
279 _lvmlvname="\nEnter a name for the logical volume (LV) being created.\n\nThis is similar to setting a label for a partition."
280 _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."
281 _lvmdelask="\nConfirm deletion of volume group(s) and logical volume(s).\n\nDeleting a volume group, will delete all logical volumes within it.\n"
284 _errexpart="\nCannot mount partition due to a problem with the mountpoint.\n\nEnsure it begins with a slash (/) followed by atleast one character.\n"
285 _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"
286 _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"
287 _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"
288 _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"
289 _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"
290 _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"
296 ###############################################################################
301 (( SEL < 12 )) && (( SEL++ ))
303 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Prepare " --default-item $SEL --cancel-label 'Exit' --menu "$_prep" 0 0 0 \
304 1 "Device tree (optional)" \
305 2 "Partitioning (optional)" \
306 3 "LUKS setup (optional)" \
307 4 "LVM setup (optional)" \
308 5 "Mount partitions" \
309 6 "System bootloader" \
310 7 "User and password" \
311 8 "System configuration" \
312 9 "Select WM/DE (optional)" \
313 10 "Select Packages (optional)" \
314 11 "View configuration (optional)" \
315 12 "Start the installation" 2>"$ANS"
318 [[ -z $WARN && $SEL =~ (2|5) ]] && { msg "Data Warning" "$_warn"; WARN=true; }
321 2) part_menu || (( SEL-- )) ;;
322 3) luks_menu || (( SEL-- )) ;;
323 4) lvm_menu || (( SEL-- )) ;;
324 5) select_menu || (( SEL-- )) ;;
325 6) prechecks 0 && { select_boot || (( SEL-- )); } ;;
326 7) prechecks 1 && { select_mkuser || (( SEL-- )); } ;;
327 8) prechecks 2 && { select_config || (( SEL-- )); } ;;
328 9) prechecks 3 && { select_sessions || (( SEL-- )); } ;;
329 10) prechecks 3 && { select_packages || (( SEL-- )); } ;;
330 11) prechecks 3 && select_show ;;
331 12) prechecks 3 && install_main ;;
332 *) yesno "Exit" "\nUnmount partitions (if any) and exit the installer?\n" && die 0
338 if [[ $SYS == 'BIOS' ]]; then
339 dlg BOOTLDR menu "BIOS Bootloader" "\nSelect which bootloader to use." \
340 "grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
341 "syslinux" "A collection of boot loaders for booting drives, CDs, or over the network" || return 1
343 dlg BOOTLDR menu "UEFI Bootloader" "\nSelect which bootloader to use." \
344 "systemd-boot" "A simple UEFI boot manager which executes configured EFI images" \
345 "grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
346 "refind-efi" "A UEFI boot manager that aims to be platform neutral and simplify multi-boot" \
347 "efistub" "Boot the kernel image directly (no chainloading support)" \
348 "syslinux" "A collection of boot loaders for booting drives, CDs, or over the network (no chainloading support)" || return 1
356 local cmd="${BCMDS[$BOOTLDR]}"
357 local pkgs="${USER_PKGS// / } ${PACKAGES// / }"
358 [[ $BOOT_PART ]] && mnt="/$BOOTDIR"
359 [[ $INSTALL_WMS == *dwm* ]] && pkgs="dwm st dmenu $pkgs"
361 msg "Show Configuration" "
363 ---------- PARTITION CONFIGURATION ------------
365 Root: ${ROOT_PART:-none}
366 Boot: ${BOOT_PART:-${BOOT_DEV:-none}}
368 Swap: ${SWAP_PART:-none}
369 Size: ${SWAP_SIZE:-none}
374 Extra: ${EXMNTS:-${EXMNT:-none}}
375 Hooks: ${HOOKS:-none}
378 ---------- BOOTLOADER CONFIGURATION -----------
380 Bootloader: ${BOOTLDR:-none}
381 Mountpoint: ${mnt:-none}
382 Command: ${cmd:-none}
385 ------------ SYSTEM CONFIGURATION -------------
387 Locale: ${MYLOCALE:-none}
388 Keymap: ${KEYMAP:-none}
389 Hostname: ${MYHOST:-none}
390 Timezone: ${ZONE:-none}/${SUBZ:-none}
393 ------------ USER CONFIGURATION --------------
395 User: ${NEWUSER:-none}
396 Shell: ${MYSHELL:-none}
397 Session: ${LOGIN_WM:-none}
398 Autologin: ${AUTOLOGIN:-none}
399 Login Method: ${LOGIN_TYPE:-none}
402 ------------ PACKAGES AND MIRRORS -------------
404 Kernel: ${KERNEL:-none}
405 Sessions: ${INSTALL_WMS:-none}
406 Packages: $(print4 "${pkgs:-none}")
412 if [[ -z $LOGIN_TYPE ]]; then
413 dlg LOGIN_TYPE menu "Login Management" "\nSelect what kind of login management to use." \
414 "xinit" "Console login without a display manager" \
415 "lightdm" "Lightweight display manager with a gtk greeter" || return 1
418 if [[ $LOGIN_TYPE == 'lightdm' ]]; then
419 LOGIN_PKGS="lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings accountsservice"
420 EDIT_FILES[login]="/etc/lightdm/lightdm.conf /etc/lightdm/lightdm-gtk-greeter.conf"
423 if (( WM_NUM == 1 )); then
424 LOGIN_WM="${WM_SESSIONS[$INSTALL_WMS]}"
426 dlg LOGIN_WM menu "Login Management" "$_login" $LOGIN_CHOICES || return 1
427 LOGIN_WM="${WM_SESSIONS[$LOGIN_WM]}"
430 local txt="\nDo you want autologin enabled for $NEWUSER?\n\nIf so the following two files will be created (disable autologin by removing 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"
431 yesno "Autologin" "$txt" && AUTOLOGIN=true || AUTOLOGIN=''
432 LOGIN_PKGS="xorg-xinit"
433 EDIT_FILES[login]="/home/$NEWUSER/.xinitrc /home/$NEWUSER/.xprofile"
442 until [[ $CONFIG_DONE ]]; do
445 dlg MYSHELL menu "Shell" "\nChoose which shell to use." \
446 /usr/bin/zsh 'A very advanced and programmable command interpreter (shell) for UNIX' \
447 /bin/bash 'The GNU Bourne Again shell, standard in many GNU/Linux distributions' \
448 /usr/bin/mksh 'The MirBSD Korn Shell - an enhanced version of the public domain ksh' || return 1
451 1) dlg MYHOST input "Hostname" "$_hostname" "${DIST,,}" limit || { i=0; continue; } ;;
452 2) dlg MYLOCALE menu "Locale" "$_locale" $LOCALES || { i=1; continue; } ;;
454 until [[ $ZONE && $SUBZ ]]; do
455 dlg ZONE menu "Timezone" "$_timez" America - Australia - Asia - Atlantic - Africa - Europe - Indian - Pacific - Arctic - Antarctica - || break
456 dlg SUBZ menu "Timezone" "$_timesubz" $(awk '/'"$ZONE"'\// {gsub(/'"$ZONE"'\//, ""); print $3 " - "}' /usr/share/zoneinfo/zone.tab | sort) || continue
457 yesno "Timezone" "\nConfirm time zone: $ZONE/$SUBZ\n" || unset ZONE
459 [[ $ZONE && $SUBZ ]] || { i=2; continue; } ;;
461 dlg KERNEL menu "Kernel" "\nChoose which kernel to use." \
462 linux 'Vanilla linux kernel and modules, with a few patches applied' \
463 linux-lts 'Long-term support (LTS) linux kernel and modules' \
464 linux-zen 'A effort of kernel hackers to provide the best kernel for everyday systems' \
465 linux-hardened 'A security-focused linux kernel with hardening patches to mitigate exploits' || { i=3; continue; }
470 (( i++ )) # progress through to the next choice
474 '/bin/bash') LOGINRC='.bash_profile' ;;
475 '/usr/bin/zsh') LOGINRC='.zprofile' ;;
476 '/usr/bin/mksh') LOGINRC='.profile' ;;
485 local v='' u='' p='' p2='' rp='' rp2=''
487 until [[ $NEWUSER ]]; do
490 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " User " --mixedform "$_user" 0 0 0 \
491 "Username:" 1 1 "$u" 1 11 "$COLUMNS" 0 0 \
492 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
493 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 \
494 "--- Root password, if left empty the user password will be used ---" 6 1 '' 6 68 "$COLUMNS" 0 2 \
495 "Password:" 8 1 '' 8 11 "$COLUMNS" 0 1 \
496 "Password2:" 9 1 '' 9 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
498 while read -r line; do
509 # root passwords empty, so use the user passwords
510 [[ -z $rp && -z $rp2 ]] && { rp="$p"; rp2="$p2"; }
512 # make sure a username was entered and that the passwords match
513 if [[ ${#u} -eq 0 || $u =~ \ |\' || $u =~ [^a-z0-9] ]]; then
514 msg "Invalid Username" "\nIncorrect user name.\n\nPlease try again.\n"; u=''
515 elif [[ -z $p ]]; then
516 msg "Empty Password" "\nThe user password cannot be left empty.\n\nPlease try again.\n"
517 elif [[ "$p" != "$p2" ]]; then
518 msg "Password Mismatch" "\nThe user passwords do not match.\n\nPlease try again.\n"
519 elif [[ "$rp" != "$rp2" ]]; then
520 msg "Password Mismatch" "\nThe root passwords do not match.\n\nPlease try again.\n"
532 dlg KEYMAP menu "Keyboard Layout" "$_keymap" \
533 us English cm English gb English au English gh English \
534 za English ng English ca French 'cd' French gn French \
535 tg French fr French de German at German ch German \
536 es Spanish latam Spanish br Portuguese pt Portuguese ma Arabic \
537 sy Arabic ara Arabic ua Ukrainian cz Czech ru Russian \
538 sk Slovak nl Dutch it Italian hu Hungarian cn Chinese \
539 tw Taiwanese vn Vietnamese kr Korean jp Japanese th Thai \
540 la Lao pl Polish se Swedish is Icelandic 'fi' Finnish \
541 dk Danish be Belgian in Indian al Albanian am Armenian \
542 bd Bangla ba Bosnian 'bg' Bulgarian dz Berber mm Burmese \
543 hr Croatian gr Greek il Hebrew ir Persian iq Iraqi \
544 af Afghani fo Faroese ge Georgian ee Estonian kg Kyrgyz \
545 kz Kazakh lt Lithuanian mt Maltese mn Mongolian ro Romanian \
546 no Norwegian rs Serbian si Slovenian tj Tajik lk Sinhala \
547 tr Turkish uz Uzbek ie Irish pk Urdu 'mv' Dhivehi \
548 np Nepali et Amharic sn Wolof ml Bambara tz Swahili \
549 ke Swahili bw Tswana ph Filipino my Malay tm Turkmen \
550 id Indonesian bt Dzongkha lv Latvian md Moldavian mao Maori \
551 by Belarusian az Azerbaijani mk Macedonian kh Khmer epo Esperanto \
552 me Montenegrin || return 1
554 if [[ $CMAPS == *"$KEYMAP"* ]]; then
557 dlg CMAP menu "Console Keymap" "$_vconsole" $CMAPS || return 1
560 if [[ $DISPLAY && $TERM != 'linux' ]]; then
561 setxkbmap "$KEYMAP" >/dev/null 2>&1
563 loadkeys "$CMAP" >/dev/null 2>&1
573 dlg INSTALL_WMS check "Sessions" "$_sessions\n" \
574 i3-gaps "A fork of i3wm with more features including gaps" "$(ofn i3-gaps "${INSTALL_WMS[*]}")" \
575 openbox "A lightweight, powerful, and highly configurable stacking wm" "$(ofn openbox "${INSTALL_WMS[*]}")" \
576 awesome "A customized Awesome WM session created by @elanapan" "$(ofn awesome "${INSTALL_WMS[*]}")" \
577 dwm "A dynamic WM for X that manages windows in tiled, floating, or monocle layouts" "$(ofn dwm "${INSTALL_WMS[*]}")" \
578 bspwm "A tiling wm that represents windows as the leaves of a binary tree" "$(ofn bspwm "${INSTALL_WMS[*]}")" \
579 fluxbox "A lightweight and highly-configurable window manager" "$(ofn fluxbox "${INSTALL_WMS[*]}")" \
580 gnome "A desktop environment that aims to be simple and easy to use" "$(ofn gnome "${INSTALL_WMS[*]}")" \
581 cinnamon "A desktop environment combining traditional desktop with modern effects" "$(ofn cinnamon "${INSTALL_WMS[*]}")" \
582 plasma "A kde software project currently comprising a full desktop environment" "$(ofn plasma "${INSTALL_WMS[*]}")" \
583 xfce4 "A lightweight and modular desktop environment based on gtk+2/3" "$(ofn xfce4 "${INSTALL_WMS[*]}")" || return 1
586 while IFS=' ' read -r i; do
588 done <<< "$INSTALL_WMS"
591 WM_PKGS="${INSTALL_WMS/dwm/}" # remove dwm from package list
592 WM_PKGS="${WM_PKGS// / }" # remove double spaces
593 WM_PKGS="${WM_PKGS# }" # remove leading space
595 # add archlabs base when choosing any session
596 [[ $WM_PKGS ]] && WM_PKGS+=" $AL_BASE_PKGS"
598 for i in $INSTALL_WMS; do
599 LOGIN_CHOICES+="$i - "
600 [[ ${WM_EXT[$i]} && $WM_PKGS != *"${WM_EXT[$i]}"* ]] && WM_PKGS+=" ${WM_EXT[$i]}"
603 select_login || return 1
604 [[ $WM_PKGS != *"$LOGIN_PKGS"* ]] && WM_PKGS+=" $LOGIN_PKGS"
606 while IFS=' ' read -r pkg; do
607 [[ $PACKAGES != *"$pkg"* ]] && PACKAGES+=" $pkg"
615 dlg USER_PKGS check " Packages " "$_packages" \
616 abiword "A Fully-featured word processor" "$(ofn abiword "${USER_PKGS[*]}")" \
617 alacritty "A cross-platform, GPU-accelerated terminal emulator" "$(ofn alacritty "${USER_PKGS[*]}")" \
618 atom "An open-source text editor developed by GitHub" "$(ofn atom "${USER_PKGS[*]}")" \
619 audacious "A free and advanced audio player based on GTK+" "$(ofn audacious "${USER_PKGS[*]}")" \
620 audacity "A program that lets you manipulate digital audio waveforms" "$(ofn audacity "${USER_PKGS[*]}")" \
621 cairo-dock "Light eye-candy fully themable animated dock" "$(ofn cairo-dock "${USER_PKGS[*]}")" \
622 calligra "A set of applications for productivity" "$(ofn calligra "${USER_PKGS[*]}")" \
623 chromium "An open-source web browser based on the Blink rendering engine" "$(ofn chromium "${USER_PKGS[*]}")" \
624 clementine "A modern music player and library organizer" "$(ofn clementine "${USER_PKGS[*]}")" \
625 cmus "A small, fast and powerful console music player" "$(ofn cmus "${USER_PKGS[*]}")" \
626 deadbeef "A GTK+ audio player for GNU/Linux" "$(ofn deadbeef "${USER_PKGS[*]}")" \
627 deluge "A BitTorrent client written in python" "$(ofn deluge "${USER_PKGS[*]}")" \
628 docky "Full fledged dock for opening applications and managing windows" "$(ofn docky "${USER_PKGS[*]}")" \
629 emacs "An extensible, customizable, self-documenting real-time display editor" "$(ofn emacs "${USER_PKGS[*]}")" \
630 epiphany "A GNOME web browser based on the WebKit rendering engine" "$(ofn epiphany "${USER_PKGS[*]}")" \
631 evince "A document viewer" "$(ofn evince "${USER_PKGS[*]}")" \
632 evolution "Manage your email, contacts and schedule" "$(ofn evolution "${USER_PKGS[*]}")" \
633 file-roller "Create and modify archives" "$(ofn file-roller "${USER_PKGS[*]}")" \
634 firefox "A popular open-source web browser from Mozilla" "$(ofn firefox "${USER_PKGS[*]}")" \
635 gcolor2 "A simple GTK+2 color selector" "$(ofn gcolor2 "${USER_PKGS[*]}")" \
636 geany "A fast and lightweight IDE" "$(ofn geany "${USER_PKGS[*]}")" \
637 geary "A lightweight email client for the GNOME desktop" "$(ofn geary "${USER_PKGS[*]}")" \
638 gimp "GNU Image Manipulation Program" "$(ofn gimp "${USER_PKGS[*]}")" \
639 gnome-disk-utility "Disk Management Utility" "$(ofn gnome-disk-utility "${USER_PKGS[*]}")" \
640 gnome-system-monitor "View current processes and monitor system state" "$(ofn gnome-system-monitor "${USER_PKGS[*]}")" \
641 gparted "A GUI frontend for creating and manipulating partition tables" "$(ofn gparted "${USER_PKGS[*]}")" \
642 gpick "Advanced color picker using GTK+ toolkit" "$(ofn gpick "${USER_PKGS[*]}")" \
643 gpicview "Lightweight image viewer" "$(ofn gpicview "${USER_PKGS[*]}")" \
644 guvcview "Capture video from camera devices" "$(ofn guvcview "${USER_PKGS[*]}")" \
645 hexchat "A popular and easy to use graphical IRC client" "$(ofn hexchat "${USER_PKGS[*]}")" \
646 inkscape "Professional vector graphics editor" "$(ofn inkscape "${USER_PKGS[*]}")" \
647 irssi "Modular text mode IRC client" "$(ofn irssi "${USER_PKGS[*]}")" \
648 kdenlive "A popular non-linear video editor for Linux" "$(ofn kdenlive "${USER_PKGS[*]}")" \
649 krita "Edit and paint images" "$(ofn krita "${USER_PKGS[*]}")" \
650 libreoffice-fresh "Full featured office suite" "$(ofn libreoffice-fresh "${USER_PKGS[*]}")" \
651 lollypop "A new music playing application" "$(ofn lollypop "${USER_PKGS[*]}")" \
652 mousepad "A simple text editor" "$(ofn mousepad "${USER_PKGS[*]}")" \
653 mpd "A flexible, powerful, server-side application for playing music" "$(ofn mpd "${USER_PKGS[*]}")" \
654 mpv "A media player based on mplayer" "$(ofn mpv "${USER_PKGS[*]}")" \
655 mupdf "Lightweight PDF and XPS viewer" "$(ofn mupdf "${USER_PKGS[*]}")" \
656 mutt "Small but very powerful text-based mail client" "$(ofn mutt "${USER_PKGS[*]}")" \
657 nautilus "The default file manager for Gnome" "$(ofn nautilus "${USER_PKGS[*]}")" \
658 ncmpcpp "A mpd client and almost exact clone of ncmpc with some new features" "$(ofn ncmpcpp "${USER_PKGS[*]}")" \
659 neovim "A fork of Vim aiming to improve user experience, plugins, and GUIs." "$(ofn neovim "${USER_PKGS[*]}")" \
660 nicotine+ "A graphical client for Soulseek" "$(ofn nicotine+ "${USER_PKGS[*]}")" \
661 noto-fonts "Google Noto fonts" "$(ofn noto-fonts "${USER_PKGS[*]}")" \
662 noto-fonts-cjk "Google Noto CJK fonts (Chinese, Japanese, Korean)" "$(ofn noto-fonts-cjk "${USER_PKGS[*]}")" \
663 obs-studio "Free opensource streaming/recording software" "$(ofn obs-studio "${USER_PKGS[*]}")" \
664 openshot "An open-source, non-linear video editor for Linux" "$(ofn openshot "${USER_PKGS[*]}")" \
665 opera "A Fast and secure, free of charge web browser from Opera Software" "$(ofn opera "${USER_PKGS[*]}")" \
666 pcmanfm "A fast and lightweight file manager based in Lxde" "$(ofn pcmanfm "${USER_PKGS[*]}")" \
667 pidgin "Multi-protocol instant messaging client" "$(ofn pidgin "${USER_PKGS[*]}")" \
668 plank "An elegant, simple, and clean dock" "$(ofn plank "${USER_PKGS[*]}")" \
669 qbittorrent "An advanced BitTorrent client" "$(ofn qbittorrent "${USER_PKGS[*]}")" \
670 qpdfview "A tabbed PDF viewer" "$(ofn qpdfview "${USER_PKGS[*]}")" \
671 qt5ct "GUI for managing Qt based application themes, icons, and fonts" "$(ofn qt5ct "${USER_PKGS[*]}")" \
672 qutebrowser "A keyboard-focused vim-like web browser based on Python and PyQt5" "$(ofn qutebrowser "${USER_PKGS[*]}")" \
673 rhythmbox "A Music playback and management application" "$(ofn rhythmbox "${USER_PKGS[*]}")" \
674 rxvt-unicode "A unicode enabled rxvt-clone terminal emulator" "$(ofn rxvt-unicode "${USER_PKGS[*]}")" \
675 sakura "A terminal emulator based on GTK and VTE" "$(ofn sakura "${USER_PKGS[*]}")" \
676 simplescreenrecorder "A feature-rich screen recorder" "$(ofn simplescreenrecorder "${USER_PKGS[*]}")" \
677 steam "A popular game distribution platform by Valve" "$(ofn steam "${USER_PKGS[*]}")" \
678 surf "A simple web browser based on WebKit2/GTK+" "$(ofn surf "${USER_PKGS[*]}")" \
679 terminator "Terminal emulator that supports tabs and grids" "$(ofn terminator "${USER_PKGS[*]}")" \
680 termite "A minimal VTE-based terminal emulator" "$(ofn termite "${USER_PKGS[*]}")" \
681 thunar "A modern file manager for the Xfce Desktop Environment" "$(ofn thunar "${USER_PKGS[*]}")" \
682 thunderbird "Standalone mail and news reader from mozilla" "$(ofn thunderbird "${USER_PKGS[*]}")" \
683 tilda "A GTK based drop down terminal for Linux and Unix" "$(ofn tilda "${USER_PKGS[*]}")" \
684 tilix "A tiling terminal emulator for Linux using GTK+ 3" "$(ofn tilix "${USER_PKGS[*]}")" \
685 transmission-cli "Free BitTorrent client CLI" "$(ofn transmission-cli "${USER_PKGS[*]}")" \
686 transmission-gtk "Free BitTorrent client GTK+ GUI" "$(ofn transmission-gtk "${USER_PKGS[*]}")" \
687 transmission-qt "Free BitTorrent client Qt GUI" "$(ofn transmission-qt "${USER_PKGS[*]}")" \
688 ttf-anonymous-pro "A family fixed-width fonts designed with code in mind" "$(ofn ttf-anonymous-pro "${USER_PKGS[*]}")" \
689 ttf-fira-code "Monospaced font with programming ligatures" "$(ofn ttf-fira-code "${USER_PKGS[*]}")" \
690 ttf-font-awesome "Iconic font designed for Bootstrap" "$(ofn ttf-font-awesome "${USER_PKGS[*]}")" \
691 ttf-hack "A hand groomed typeface based on Bitstream Vera Mono" "$(ofn ttf-hack "${USER_PKGS[*]}")" \
692 vlc "A free and open source cross-platform multimedia player" "$(ofn vlc "${USER_PKGS[*]}")" \
693 weechat "Fast, light and extensible IRC client" "$(ofn weechat "${USER_PKGS[*]}")" \
694 xarchiver "A GTK+ frontend to various command line archivers" "$(ofn xarchiver "${USER_PKGS[*]}")" \
695 xfce-terminal "A terminal emulator based in the Xfce Desktop Environment" "$(ofn xfce-terminal "${USER_PKGS[*]}")" \
696 xterm "The standard terminal emulator for the X window system" "$(ofn xterm "${USER_PKGS[*]}")" \
697 zathura "Minimalistic document viewer" "$(ofn zathura "${USER_PKGS[*]}")"
699 if [[ $USER_PKGS ]]; then
700 for i in $USER_PKGS; do
701 [[ ${PKG_EXT[$i]} && $USER_PKGS != *"${PKG_EXT[$i]}"* ]] && USER_PKGS+=" ${PKG_EXT[$i]}"
708 ###############################################################################
713 check_background_install || return 0
714 local device choice devhash
715 devhash="$(lsblk -f | base64)"
717 part_device || return 1
722 if [[ $DISPLAY && $TERM != 'linux' ]] && hash gparted >/dev/null 2>&1; then
723 dlg choice menu "Edit Partitions" "$_part" \
724 "auto" "Whole device automatic partitioning" \
725 "shrink" "Shrink an existing ext2/3/4 or ntfs partition to make room for a new partition" \
726 "gparted" "GUI front end to parted" \
727 "cfdisk" "Curses based variant of fdisk" \
728 "parted" "GNU partition editor" \
729 "fdisk" "Dialog-driven creation and manipulation of partitions" \
730 "done" "Return to the main menu" || return 0
732 dlg choice menu "Edit Partitions" "$_part" \
733 "auto" "Whole device automatic partitioning" \
734 "shrink" "Shrink an existing ext2/3/4 or ntfs partition to make room for a new partition" \
735 "cfdisk" "Curses based variant of fdisk" \
736 "parted" "GNU partition editor" \
737 "fdisk" "Dialog-driven creation and manipulation of partitions" \
738 "done" "Return to the main menu" || return 0
741 if [[ $choice == 'done' ]]; then
743 elif [[ $choice == 'shrink' ]]; then
744 part_shrink "$device"
745 elif [[ $choice == 'auto' ]]; then
746 local root_size txt table boot_fs
747 root_size=$(lsblk -lno SIZE "$device" | awk 'NR == 1 {
750 print ($1 * 1000 - 512) / 1000 "G"
756 txt="\nWARNING:\n\nALL data on $device will be destroyed and the following partitions will be created\n\n- "
757 if [[ $SYS == 'BIOS' ]]; then
758 table="msdos" boot_fs="ext4"
759 txt+="An $boot_fs boot partition with the boot flag enabled (512M)\n- "
761 table="gpt" boot_fs="fat32"
762 txt+="A $boot_fs efi boot partition (512M)\n- "
764 txt+="An ext4 partition using all remaining space ($root_size)\n\nDo you want to continue?\n"
765 yesno "Auto Partition" "$txt" && part_auto "$device" "$table" "$boot_fs" "$root_size"
771 if [[ $devhash != "$(lsblk -f | base64)" ]]; then
772 msg "Probing Partitions" "\nInforming the kernel of partition changes using partprobe.\n" 0
773 partprobe >/dev/null 2>&1
781 if [[ $IGNORE_DEV ]]; then
782 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk "!/$IGNORE_DEV/"' && /disk|part|lvm|crypt|NAME/')"
784 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk '/disk|part|lvm|crypt|NAME/')"
786 msg "Device Tree" "\n\n$txt\n\n"
791 if [[ $1 == "$MNT/swapfile" && $SWAP_SIZE ]]; then
792 fallocate -l $SWAP_SIZE "$1" 2>$ERR
793 errshow "fallocate -l $SWAP_SIZE $1"
794 chmod 600 "$1" 2>$ERR
795 errshow "chmod 600 $1"
797 mkswap "$1" >/dev/null 2>$ERR
799 swapon "$1" >/dev/null 2>$ERR
806 local device="$1" table="$2" boot_fs="$3" size="$4" dev_info=""
807 dev_info="$(parted -s "$device" print)"
809 msg "Auto Partition" "\nRemoving partitions on $device and setting table to $table\n" 1
812 while read -r PART; do
813 parted -s "$device" rm "$PART" >/dev/null 2>&1
814 done <<< "$(awk '/^ [1-9][0-9]?/ {print $1}' <<< "$dev_info" | sort -r)"
816 [[ $(awk '/Table:/ {print $3}' <<< "$dev_info") != "$table" ]] && parted -s "$device" mklabel "$table" >/dev/null 2>&1
818 msg "Auto Partition" "\nCreating a 512M $boot_fs boot partition.\n" 1
819 if [[ $SYS == "BIOS" ]]; then
820 parted -s "$device" mkpart primary "$boot_fs" 1MiB 513MiB >/dev/null 2>&1
822 parted -s "$device" mkpart ESP "$boot_fs" 1MiB 513MiB >/dev/null 2>&1
827 AUTO_BOOT_PART=$(lsblk -lno NAME,TYPE "$device" | awk 'NR==2 {print "/dev/" $1}')
829 if [[ $SYS == "BIOS" ]]; then
830 mkfs.ext4 -q "$AUTO_BOOT_PART" >/dev/null 2>&1
832 mkfs.vfat -F32 "$AUTO_BOOT_PART" >/dev/null 2>&1
835 msg "Auto Partition" "\nCreating a $size ext4 root partition.\n" 0
836 parted -s "$device" mkpart primary ext4 513MiB 100% >/dev/null 2>&1
838 AUTO_ROOT_PART="$(lsblk -lno NAME,TYPE "$device" | awk 'NR==3 {print "/dev/" $1}')"
839 mkfs.ext4 -q "$AUTO_ROOT_PART" >/dev/null 2>&1
841 FORMATTED+="$AUTO_BOOT_PART $AUTO_ROOT_PART "
842 msg "Auto Partition" "\nProcess complete.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$device")\n"
847 local regexp="$1" err=''
849 # string of partitions as /TYPE/PART SIZE
850 if [[ $IGNORE_DEV ]]; then
851 PARTS="$(lsblk -lno TYPE,NAME,SIZE |
852 awk "/$regexp/"' && !'"/$IGNORE_DEV/"' {
853 sub(/^part/, "/dev/")
854 sub(/^lvm|^crypt/, "/dev/mapper/")
858 PARTS="$(lsblk -lno TYPE,NAME,SIZE |
860 sub(/^part/, "/dev/")
861 sub(/^lvm|^crypt/, "/dev/mapper/")
866 # number of partitions total
868 while read -r line; do
872 # ensure we have enough partitions for the system and action type
874 'part|lvm|crypt') [[ $COUNT -lt 1 || ($SYS == 'UEFI' && $COUNT -lt 2) ]] && err="$_errpart" ;;
875 'part|crypt') (( COUNT < 1 )) && err="$_lvmerr" ;;
876 'part|lvm') (( COUNT < 2 )) && err="$_lukserr" ;;
879 # if there aren't enough partitions show the relevant error message
880 [[ $err ]] && { msg "Not Enough Partitions" "$err" 2; return 1; }
887 local part="$1" mountp="${MNT}$2" fs=""
888 fs="$(lsblk -lno FSTYPE "$part")"
891 if [[ $fs && ${FS_OPTS[$fs]} && $part != "$BOOT_PART" ]] && select_mntopts "$fs"; then
892 mount -o "$MNT_OPTS" "$part" "$mountp" >/dev/null 2>&1
894 mount "$part" "$mountp" >/dev/null 2>&1
897 part_mountconf "$part" "$mountp" || return 1
905 local part="$1" fs="$2" delay="$3"
907 msg "Format" "\nFormatting $part as $fs\n" 0
908 ${FS_CMDS[$fs]} "$part" >/dev/null 2>$ERR
909 errshow "${FS_CMDS[$fs]} $part" || return 1
918 local device="$1" fs=""
920 part_find "${device##*/}[^ ]" || return 1
921 (( COUNT == 1 )) && part="$(awk '{print $1}' <<< "${PARTS[@]}" )"
923 if (( COUNT == 1 )) || dlg part menu "Resize" "\nWhich partition on $device do you want to resize?" $PARTS; then
924 fs=$(lsblk -lno FSTYPE "$part")
927 msg "Resize" "\nGathering device size info.\n" 0
929 end=$(parted -s "$device" unit KiB print | awk '/^\s*'"$num"'/ {print $3}') # part size in KiB
930 devsize=$(parted -s "$device" unit KiB print | awk '/Disk '"${device//\//\\/}"':/ {print $3}') # whole device size in KiB
931 mount "$part" $MNT >/dev/null 2>&1; sleep 0.5
932 min=$(df --output=used --block-size=MiB "$part" | awk 'NR == 2 {print int($1) + 256}')
933 max=$(df --output=avail --block-size=MiB "$part" | awk 'NR == 2 {print int($1)}')
934 umount $MNT >/dev/null 2>&1
936 if dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Resize: $part " --rangebox "$_resize" 17 "$COLUMNS" "$min" "$max" $((max / 2)) 2>$ANS; then
938 size=$((size * 1024))
945 if ntfsresize -fc "$part"; then
946 ntfsresize -ff --size $(( (size * 1024) / 1000 ))k "$part" 2>$ERR # k=10^3 bytes
947 errshow "ntfsresize -f -s $(( (size * 1024) / 1000 ))k $part" || return 1
949 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"
954 e2fsck -f "$part"; sleep 0.5
955 resize2fs -f "$part" ${size}K 2>$ERR # K=2^10 bytes
956 errshow "resize2fs -f $part ${size}K" || return 1
960 parted "$device" resizepart "$num" ${size}KiB || return 1
963 if [[ $devsize == "$end" ]]; then
964 parted -s "$device" mkpart primary ext4 ${size}KiB 100% 2>$ERR
965 errshow "parted -s $device mkpart primary ext4 ${size}KiB 100%" || return 1
967 parted -s "$device" mkpart primary ext4 ${size}KiB ${end}KiB 2>$ERR
968 errshow "parted -s $device mkpart primary ext4 ${size}KiB ${end}KiB" || return 1
970 msg "Resize Complete" "\n$part has been successfully resized to $((size / 1024))M.\n" 1
972 "") msg "No Filesystem" "\nFor unformatted partitions, cfdisk can be used in the partition menu.\n" ;;
973 *) msg "Invalid Filesystem: $fs" "\nResizing only supports ext and ntfs.\n" ;;
980 if [[ $DEV_COUNT -eq 1 && $SYS_DEVS ]]; then
981 DEVICE="$(awk '{print $1}' <<< "$SYS_DEVS")"
982 elif (( DEV_COUNT > 1 )); then
984 dlg DEVICE menu "Boot Device" "\nSelect the device to use for bootloader install." $SYS_DEVS
986 dlg DEVICE menu "Select Device" "$_device" $SYS_DEVS
988 [[ $DEVICE ]] || return 1
989 elif [[ $DEV_COUNT -lt 1 && ! $1 ]]; then
990 msg "Device Error" "\nNo available devices.\n\nExiting..\n" 2; die 1
993 [[ $1 ]] && BOOT_DEV="$DEVICE"
1000 BOOT_DEV="${BOOT_PART%[1-9]}"
1001 BOOT_PART_NUM="${BOOT_PART: -1}"
1002 [[ $BOOT_PART = /dev/nvme* ]] && BOOT_DEV="${BOOT_PART%p[1-9]}"
1003 if [[ $SYS == 'UEFI' ]]; then
1004 parted -s $BOOT_DEV set $BOOT_PART_NUM esp on >/dev/null 2>&1
1006 parted -s $BOOT_DEV set $BOOT_PART_NUM boot on >/dev/null 2>&1
1013 local part="$1" devs=""
1014 devs="$(lsblk -lno NAME,FSTYPE,TYPE)"
1016 # Identify if $part is LUKS+LVM, LVM+LUKS, LVM alone, or LUKS alone
1017 if lsblk -lno TYPE "$part" | grep -q 'crypt'; then
1019 LUKS_NAME="${part#/dev/mapper/}"
1021 for dev in $(awk '/lvm/ && /crypto_LUKS/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
1022 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1023 LUKS_DEV="$LUKS_DEV cryptdevice=$dev:$LUKS_NAME"
1024 LVM='logical volume'
1029 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
1030 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1031 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
1032 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
1037 elif lsblk -lno TYPE "$part" | grep -q 'lvm'; then
1038 LVM='logical volume'
1039 VNAME="${part#/dev/mapper/}"
1041 for dev in $(awk '/crypt/ && /lvm2_member/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
1042 if lsblk -lno NAME "$dev" | grep -q "$VNAME"; then
1043 LUKS_NAME="${dev/\/dev\/mapper\//}"
1048 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
1049 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1050 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
1051 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
1062 if (( COUNT > 0 )); then
1063 PARTS="$(sed "/${i//\//\\/}/d" <<< "$PARTS")"
1071 if grep -qw "$1" /proc/mounts; then
1072 msg "Mount Success" "\nPartition $1 mounted at $2\n" 1
1076 msg "Mount Fail" "\nPartition $1 failed to mount at $2\n" 2
1081 ###############################################################################
1086 check_background_install || return 0
1089 part_find 'part|lvm|crypt' || { SEL=2; return 1; }
1091 [[ $LUKS && $LUKS_PART ]] && part_countdec $LUKS_PART
1092 [[ $LVM && $LVM_PARTS ]] && part_countdec $LVM_PARTS
1094 select_root_partition || return 1
1096 if [[ $SYS == 'UEFI' ]]; then
1097 select_efi_partition || { BOOT_PART=''; return 1; }
1098 elif (( COUNT > 0 )); then
1099 select_boot_partition || { BOOT_PART=''; return 1; }
1102 if [[ $BOOT_PART ]]; then
1103 part_mount "$BOOT_PART" "/$BOOTDIR" && SEP_BOOT=true || return 1
1107 select_swap || return 1
1108 select_extra_partitions || return 1
1109 install_background || return 1
1116 dlg SWAP_PART menu "Swap Setup" "\nSelect whether to use a swapfile, swap partition, or none." \
1117 "none" "Don't allocate any swap space" \
1118 "swapfile" "Allocate $SYS_MEM at /swapfile" \
1121 if [[ -z $SWAP_PART || $SWAP_PART == "none" ]]; then
1124 elif [[ $SWAP_PART == "swapfile" ]]; then
1126 until [[ ${SWAP_SIZE:0:1} =~ [1-9] && ${SWAP_SIZE: -1} =~ (M|G) ]]; do
1127 (( 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
1128 dlg SWAP_SIZE input "Swap Setup" "$_swapsize" "$SYS_MEM" || { SWAP_PART=''; SWAP_SIZE=''; return 1; }
1131 part_swap "$MNT/$SWAP_PART"
1132 SWAP_PART="/$SWAP_PART"
1133 elif [[ $PARTS == *"$SWAP_PART"* ]]; then
1134 part_swap $SWAP_PART
1135 part_countdec $SWAP_PART
1136 SWAP_SIZE="$(lsblk -lno SIZE $SWAP_PART)"
1146 local fs="$1" opts=''
1147 local title="${fs^} Mount Options"
1149 for i in ${FS_OPTS[$fs]}; do
1153 until [[ $MNT_OPTS ]]; do
1154 dlg MNT_OPTS check "$title" "$_mount" $opts
1155 [[ $MNT_OPTS ]] || return 1
1156 MNT_OPTS="${MNT_OPTS// /,}"
1157 yesno "$title" "\nConfirm the following options: $MNT_OPTS\n" || MNT_OPTS=''
1166 until [[ $EXMNT ]]; do
1167 dlg EXMNT input "Extra Mount $part" "$_exmnt" "/" || return 1
1168 if [[ ${EXMNT:0:1} != "/" || ${#EXMNT} -le 1 || $EXMNT =~ \ |\' || $EXMNTS == *"$EXMNT"* ]]; then
1169 msg "Mountpoint Error" "$_errexpart"
1178 local part="$1" fs='' cur=''
1179 local txt="\nSelect which filesystem to use for: $part\n\nDefault: ext4"
1180 cur="$(lsblk -lno FSTYPE "$part" 2>/dev/null)"
1183 if [[ $cur && ($part != "$ROOT_PART" || $FORMATTED == *"$part"*) ]]; then
1184 dlg fs menu "Filesystem" "$txt\nCurrent: $cur" skip - ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1186 dlg fs menu "Filesystem" "$txt" ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1188 [[ $fs == 'skip' ]] && return 0
1189 yesno "Filesystem" "\nFormat $part as $fs?\n" || fs=''
1191 part_format "$part" "$fs"
1194 select_efi_partition()
1196 if (( COUNT == 1 )); then
1197 BOOT_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
1198 elif [[ $AUTO_BOOT_PART ]]; then
1199 BOOT_PART="$AUTO_BOOT_PART"
1200 return 0 # were done here
1202 dlg BOOT_PART menu "EFI Partition" "$_uefi" $PARTS
1205 [[ $BOOT_PART ]] || return 1
1207 if grep -q 'fat' <<< "$(fsck -N "$BOOT_PART")"; then
1208 local txt="\nIMPORTANT:\n\nThe EFI partition $BOOT_PART $_format"
1209 if yesno "Format EFI Partition" "$txt" "Format $BOOT_PART" "Skip Formatting" 1; then
1210 part_format "$BOOT_PART" "vfat" 2
1213 part_format "$BOOT_PART" "vfat" 2
1219 select_boot_partition()
1221 if [[ $AUTO_BOOT_PART && ! $LVM ]]; then
1222 BOOT_PART="$AUTO_BOOT_PART"; return 0 # were done here
1223 elif [[ $LUKS && ! $LVM ]]; then
1224 dlg BOOT_PART menu "Boot Partition" "$_biosluks" $PARTS
1225 [[ $BOOT_PART ]] || return 1
1227 dlg BOOT_PART menu "Boot Partition" "$_bios" "skip" "don't use a separate boot" $PARTS
1228 [[ -z $BOOT_PART || $BOOT_PART == "skip" ]] && { BOOT_PART=''; return 0; }
1231 if grep -q 'ext[34]' <<< "$(fsck -N "$BOOT_PART")"; then
1232 local txt="\nIMPORTANT:\n\nThe boot partition $BOOT_PART $_format"
1233 if yesno "Format Boot Partition" "$txt" "Format $BOOT_PART" "Skip Formatting" 1; then
1234 part_format "$BOOT_PART" "ext4" 2
1237 part_format "$BOOT_PART" "ext4" 2
1242 select_root_partition()
1244 if [[ $AUTO_ROOT_PART && -z $LVM && -z $LUKS ]]; then
1245 ROOT_PART="$AUTO_ROOT_PART"
1246 elif (( COUNT == 1 )); then
1247 ROOT_PART="$(awk 'NR==1 {print $1}' <<< "$PARTS")"
1249 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
1251 [[ $ROOT_PART ]] || return 1
1253 select_filesystem "$ROOT_PART" || { ROOT_PART=''; return 1; }
1254 part_mount "$ROOT_PART" || { ROOT_PART=''; return 1; }
1259 select_extra_partitions()
1262 while (( COUNT > 0 )); do
1264 dlg part menu 'Mount Extra' "$_expart" 'done' 'finish mounting step' $PARTS || break
1265 if [[ $part == 'done' ]]; then
1267 elif select_filesystem "$part" && select_mountpoint && part_mount "$part" "$EXMNT"; then
1268 EXMNTS+="$part: $EXMNT "
1269 [[ $EXMNT == '/usr' && $HOOKS != *usr* ]] && HOOKS="usr $HOOKS"
1277 ###############################################################################
1285 genfstab -U $MNT >$MNT/etc/fstab 2>$ERR
1286 errshow 1 "genfstab -U $MNT >$MNT/etc/fstab"
1287 [[ -f $MNT/swapfile ]] && sed -i "s~${MNT}~~" $MNT/etc/fstab
1291 chrun "hwclock --systohc --utc" || chrun "hwclock --systohc --utc --directisa"
1294 chrun "chown -Rf $NEWUSER:users /home/$NEWUSER"
1298 dlg choice menu "Finalization" "$_edit" \
1299 finished "exit the installer and reboot" \
1300 keyboard "${EDIT_FILES[keyboard]}" \
1301 console "${EDIT_FILES[console]}" \
1302 locale "${EDIT_FILES[locale]}" \
1303 hostname "${EDIT_FILES[hostname]}" \
1304 sudoers "${EDIT_FILES[sudoers]}" \
1305 mkinitcpio "${EDIT_FILES[mkinitcpio]}" \
1306 fstab "${EDIT_FILES[fstab]}" \
1307 crypttab "${EDIT_FILES[crypttab]}" \
1308 bootloader "${EDIT_FILES[bootloader]}" \
1309 pacman "${EDIT_FILES[pacman]}" \
1310 login "${EDIT_FILES[login]}"
1312 if [[ -z $choice || $choice == 'finished' ]]; then
1313 [[ $DEBUG == true && -r $DBG ]] && vim $DBG
1317 for f in ${EDIT_FILES[$choice]}; do
1318 [[ -e ${MNT}$f ]] && exists+=" ${MNT}$f"
1320 if [[ $exists ]]; then
1323 msg "File Missing" "\nThe file(s) selected do not exist:\n\n${EDIT_FILES[$choice]}\n"
1331 if [[ $RSYNC_PID || $MIRROR_PID ]]; then
1333 printf "\nOne or more background install processes are still running, grabbing their output...\n"
1335 while kill -0 "$RSYNC_PID" 2>/dev/null || kill -0 "$MIRROR_PID" 2>/dev/null; do
1336 tail -n 1 /tmp/bg_out
1340 unset RSYNC_PID MIRROR_PID
1341 elif [[ -d /run/archiso/sfs/airootfs/etc/skel ]]; then
1342 rsync -ahv /run/archiso/sfs/airootfs/ $MNT/ 2>$ERR
1343 errshow 1 "rsync -ahv /run/archiso/sfs/airootfs/ $MNT/"
1344 install_mirrorlist "$MNT/etc/pacman.d/mirrorlist"
1345 chrun "pacman -Syyu --noconfirm && pacman -S $BASE_PKGS --needed --noconfirm"
1347 mkdir -p /etc/pacman.d/mirrorlist
1348 install_mirrorlist "/etc/pacman.d/mirrorlist"
1349 pacstrap "$MNT" base $ISO_BASE 2>$ERR
1350 errshow 1 "pacstrap $MNT base $KERNEL $ISO_BASE"
1351 mkdir -p "$MNT/etc/pacman.d/mirrorlist"
1352 cp -f /etc/pacman.d/mirrorlist "$MNT/etc/pacman.d/mirrorlist"
1353 chrun "pacman -Syyu --noconfirm && pacman -S $BASE_PKGS --needed --noconfirm"
1356 rm -rf $MNT/etc/mkinitcpio-archiso.conf
1357 find $MNT/usr/lib/initcpio -name 'archiso*' -type f -delete
1358 sed -i 's/volatile/auto/g' $MNT/etc/systemd/journald.conf
1359 find $MNT/boot -name '*-ucode.img' -delete
1362 find $MNT/etc/X11/xorg.conf.d/ -name '*.conf' -delete
1363 elif lspci | grep ' VGA ' | grep -q 'Intel'; then
1364 cat > $MNT/etc/X11/xorg.conf.d/20-intel.conf << EOF
1366 Identifier "Intel Graphics"
1368 Option "TearFree" "true"
1373 [[ -e /run/archiso/sfs/airootfs && $KERNEL == 'linux' ]] && cp -vf $RUN/x86_64/vmlinuz $MNT/boot/vmlinuz-linux
1375 cp -fv /etc/resolv.conf $MNT/etc/
1376 [[ -e /etc/NetworkManager/system-connections ]] && cp -rvf /etc/NetworkManager/system-connections $MNT/etc/NetworkManager/
1378 echo "LANG=$MYLOCALE" > $MNT/etc/locale.conf
1379 cp -f $MNT/etc/locale.conf $MNT/etc/default/locale
1380 sed -i "s/#en_US.UTF-8/en_US.UTF-8/g; s/#${MYLOCALE}/${MYLOCALE}/g" $MNT/etc/locale.gen
1382 chrun "ln -svf /usr/share/zoneinfo/$ZONE/$SUBZ /etc/localtime"
1384 if [[ $BROADCOM_WL ]]; then
1385 echo 'blacklist bcma' >> $MNT/etc/modprobe.d/blacklist.conf
1386 rm -f $MNT/etc/modprobe/
1389 cat > $MNT/etc/X11/xorg.conf.d/00-keyboard.conf << EOF
1390 # Use localectl(1) to instruct systemd-localed to update it.
1391 Section "InputClass"
1392 Identifier "system-keyboard"
1393 MatchIsKeyboard "on"
1394 Option "XkbLayout" "$KEYMAP"
1397 cat > $MNT/etc/default/keyboard << EOF
1398 # KEYBOARD CONFIGURATION FILE
1399 # Consult the keyboard(5) manual page.
1406 printf "KEYMAP=%s\nFONT=%s\n" "$CMAP" "$FONT" > $MNT/etc/vconsole.conf
1407 echo "$MYHOST" > $MNT/etc/hostname
1408 cat > $MNT/etc/hosts << EOF
1411 ::1 localhost ip6-localhost ip6-loopback
1412 ff02::1 ip6-allnodes
1413 ff02::2 ip6-allrouters
1419 if [[ $ROOT_PART == /dev/mapper* ]]; then
1420 ROOT_PART_ID="$ROOT_PART"
1422 local uuid_type="UUID"
1423 [[ $BOOTLDR =~ (systemd-boot|refind-efi|efistub) ]] && uuid_type="PARTUUID"
1424 ROOT_PART_ID="$uuid_type=$(blkid -s $uuid_type -o value $ROOT_PART)"
1427 if [[ $SYS == 'UEFI' ]]; then
1428 find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname "$DIST" -type d -delete
1429 find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname 'boot' -type d -delete
1433 chrun "${BCMDS[$BOOTLDR]}" 2>$ERR
1434 errshow 1 "${BCMDS[$BOOTLDR]}"
1436 if [[ -d $MNT/hostrun ]]; then
1437 umount $MNT/hostrun/udev >/dev/null 2>&1
1438 umount $MNT/hostrun/lvm >/dev/null 2>&1
1439 rm -rf $MNT/hostrun >/dev/null 2>&1
1442 if [[ $SYS == 'UEFI' ]]; then
1443 # some UEFI firmware requires a generic esp/BOOT/BOOTX64.EFI
1444 mkdir -pv $MNT/$BOOTDIR/EFI/BOOT
1445 if [[ $BOOTLDR == 'grub' ]]; then
1446 cp -fv $MNT/$BOOTDIR/EFI/$DIST/grubx64.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI
1447 elif [[ $BOOTLDR == 'syslinux' ]]; then
1448 cp -rf $MNT/$BOOTDIR/EFI/syslinux/* $MNT/$BOOTDIR/EFI/BOOT/
1449 cp -f $MNT/$BOOTDIR/EFI/syslinux/syslinux.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI
1450 elif [[ $BOOTLDR == 'refind-efi' ]]; then
1451 sed -i '/#extra_kernel_version_strings/ c extra_kernel_version_strings linux-hardened,linux-zen,linux-lts,linux' $MNT/$BOOTDIR/EFI/refind/refind.conf
1452 cp -fv $MNT/$BOOTDIR/EFI/refind/refind_x64.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI
1461 chrun "chpasswd <<< 'root:$ROOT_PASS'" 2>$ERR
1462 errshow 1 "set root password"
1463 if [[ $MYSHELL != *zsh ]]; then
1464 chrun "usermod -s $MYSHELL root" 2>$ERR
1465 errshow 1 "usermod -s $MYSHELL root"
1466 [[ $MYSHELL == "/usr/bin/mksh" ]] && cp -fv $MNT/etc/skel/.mkshrc /root/.mkshrc
1469 local groups='audio,autologin,floppy,log,network,rfkill,scanner,storage,optical,power,wheel'
1471 chrun "groupadd -r autologin" 2>$ERR
1472 errshow 1 "groupadd -r autologin"
1473 chrun "useradd -m -u 1000 -g users -G $groups -s $MYSHELL $NEWUSER" 2>$ERR
1474 errshow 1 "useradd -m -u 1000 -g users -G $groups -s $MYSHELL $NEWUSER"
1475 chrun "chpasswd <<< '$NEWUSER:$USER_PASS'" 2>$ERR
1476 errshow 1 "set $NEWUSER password"
1478 if [[ $USER_PKGS == *neovim* && -d $MNT/home/$NEWUSER/.vim ]]; then
1479 mkdir -p $MNT/home/$NEWUSER/.config/nvim
1480 cp -fv $MNT/home/$NEWUSER/.vimrc $MNT/home/$NEWUSER/.config/nvim/init.vim
1481 cp -rfv $MNT/home/$NEWUSER/.vim/colors $MNT/home/$NEWUSER/.config/nvim/colors
1484 [[ $INSTALL_WMS == *dwm* ]] && install_suckless
1485 [[ $INSTALL_WMS == *awesome* ]] && install_awesome
1487 # remove some commands from ~/.xprofile when using KDE or Gnome as the login session
1488 if [[ $LOGIN_WM =~ (startkde|gnome-session) ]]; then
1489 sed -i '/super/d' $MNT/home/$NEWUSER/.xprofile $MNT/root/.xprofile
1490 sed -i '/nitrogen/d' $MNT/home/$NEWUSER/.xprofile $MNT/root/.xprofile
1491 sed -i '/al-compositor/d' $MNT/home/$NEWUSER/.xprofile $MNT/root/.xprofile
1492 sed -i '/compton/d' $MNT/home/$NEWUSER/.xprofile $MNT/root/.xprofile
1500 if [[ -e $MNT/home/$NEWUSER/.xinitrc ]] && grep -q 'exec' $MNT/home/$NEWUSER/.xinitrc; then
1501 sed -i "/exec/ c exec ${LOGIN_WM}" $MNT/home/$NEWUSER/.xinitrc
1503 printf "exec %s\n" "$LOGIN_WM" >> $MNT/home/$NEWUSER/.xinitrc
1506 [[ ${EDIT_FILES[login]} == *"$LOGINRC"* ]] || EDIT_FILES[login]+=" /home/$NEWUSER/$LOGINRC"
1508 if [[ $AUTOLOGIN ]]; then
1509 sed -i "s/root/${NEWUSER}/g" $SERVICE/autologin.conf
1510 cat > $MNT/home/$NEWUSER/$LOGINRC <<EOF
1512 # sourced by ${MYSHELL##*/} when used as a login shell
1514 # automatically run startx when logging in on tty1
1515 [[ -z \$DISPLAY && \$XDG_VTNR -eq 1 ]] && exec startx -- vt1
1519 rm -rf $MNT/home/$NEWUSER/.{profile,zprofile,bash_profile}
1525 SERVICE="$MNT/etc/systemd/system/getty@tty1.service.d"
1526 sed -i '/printf/d' $MNT/root/.zshrc
1527 install_${LOGIN_TYPE:-xinit}
1533 rm -rf $MNT/home/$NEWUSER/.{xinitrc,profile,zprofile,bash_profile}
1534 chrun 'systemctl set-default graphical.target && systemctl enable lightdm.service' 2>$ERR
1535 errshow 1 "systemctl set-default graphical.target && systemctl enable lightdm.service"
1536 cat > $MNT/etc/lightdm/lightdm-gtk-greeter.conf << EOF
1537 # LightDM GTK+ Configuration
1540 default-user-image=/usr/share/icons/ArchLabs-Dark/64x64/places/distributor-logo-archlabs.png
1541 background=/usr/share/backgrounds/archlabs/archlabs.jpg
1542 theme-name=Adwaita-dark
1543 icon-theme-name=Adwaita
1544 font-name=DejaVu Sans Mono 11
1545 position=30%,end 50%,end
1551 if chrun "git clone https://github.com/elenapan/archlabs-awesome /home/$NEWUSER/archlabs-awesome"; then
1552 cp -rT "/mnt/home/$NEWUSER/archlabs-awesome" "/mnt/home/$NEWUSER"
1553 cp -rT "/mnt/home/$NEWUSER/archlabs-awesome" /mnt/etc/skel
1554 rm -rf "/home/$NEWUSER/"{.git,archlabs-awesome,screenshots}
1555 printf "You will need to instal pamac seperately if needed using: 'baph -i pamac-aur'\n"
1558 printf "failed to clone awesome config repo\n"
1565 local inpkg="$PACKAGES $USER_PKGS"
1567 if pacman -Qsq 'archlabs-installer' >/dev/null 2>&1; then
1568 rmpkg+=" archlabs-installer"
1569 elif [[ -e "$MNT/usr/bin/archlabs-installer" ]]; then
1570 rm -f "$MNT/usr/bin/archlabs-installer"
1573 [[ $UCODE ]] && inpkg+=" $UCODE"
1574 [[ $MYSHELL == *mksh ]] && inpkg+=" mksh"
1575 [[ $KERNEL == 'linux' ]] || { inpkg+=" $KERNEL"; rmpkg+=" linux"; }
1576 [[ $inpkg =~ (term|urxvt|tilix|alacritty|sakura|tilda|plasma|cinnamon) || $INSTALL_WMS == *dwm* ]] || inpkg+=" xterm"
1577 [[ $MYSHELL == '/usr/bin/zsh' ]] && inpkg+=" zsh-completions"
1578 [[ $INSTALL_WMS =~ ^(plasma|gnome|cinnamon)$ ]] || inpkg+=" archlabs-ksuperkey"
1579 [[ $INSTALL_WMS =~ (openbox|bspwm|i3-gaps|dwm|fluxbox) ]] && inpkg+=" $WM_BASE_PKGS"
1581 chrun "pacman -Syyu --noconfirm"
1582 [[ $rmpkg ]] && chrun "pacman -Rns $rmpkg --noconfirm"
1583 chrun "pacman -S iputils --noconfirm"
1584 chrun "pacman -S $inpkg --needed --noconfirm" 2>$ERR
1585 errshow 1 "pacman -S $inpkg --needed --noconfirm"
1587 if [[ $BOOTLDR == 'grub' ]]; then
1588 if [[ $SYS == 'BIOS' ]]; then
1589 chrun "pacman -S grub os-prober --needed --noconfirm" 2>$ERR
1590 errshow 1 "pacman -S grub os-prober --needed --noconfirm"
1592 chrun "pacman -S grub os-prober efibootmgr --needed --noconfirm" 2>$ERR
1593 errshow 1 "pacman -S grub os-prober efibootmgr --needed --noconfirm"
1595 elif [[ $BOOTLDR == 'refind-efi' ]]; then
1596 chrun "pacman -S refind-efi efibootmgr --needed --noconfirm" 2>$ERR
1597 errshow 1 "pacman -S refind-efi efibootmgr --needed --noconfirm"
1598 elif [[ $SYS == 'UEFI' ]]; then
1599 chrun "pacman -S efibootmgr --needed --noconfirm" 2>$ERR
1600 errshow 1 "pacman -S efibootmgr --needed --noconfirm"
1602 sed -i "s/# %wheel ALL=(ALL) ALL/%wheel ALL=(ALL) ALL/g" $MNT/etc/sudoers
1608 mkdir -pv $MNT/home/$NEWUSER/suckless
1609 for i in dwm dmenu st; do
1610 if chrun "git clone https://git.suckless.org/$i /home/$NEWUSER/suckless/$i"; then
1611 chrun "cd /home/$NEWUSER/suckless/$i; make PREFIX=/usr install; make clean; rm config.h"
1613 printf "failed to clone %s repo\n" "$i"
1617 if [[ -d $MNT/home/$NEWUSER/suckless/dwm && -x $MNT/usr/bin/dwm ]]; then
1618 printf "To configure dwm edit %s\n" "/home/$NEWUSER/suckless/dwm/config.h"
1619 printf "You can then recompile it with 'sudo make clean install'\n"
1624 install_mkinitcpio()
1628 # luks keyfile creation
1629 # currently not used due to not prompting for passphrase on startup
1630 # [[ $LUKS_UUID && $LUKS_PASS && $SYS == 'UEFI' && $BOOTLDR == 'grub' ]] && luks_keyfile
1632 [[ $LUKS ]] && add="encrypt"
1633 [[ $LVM ]] && { [[ $add ]] && add+=" lvm2" || add+="lvm2"; }
1634 sed -i "s/block filesystems/block ${add} filesystems ${HOOKS}/g" $MNT/etc/mkinitcpio.conf
1635 chrun "mkinitcpio -p $KERNEL" 2>$ERR
1636 errshow 1 "mkinitcpio -p $KERNEL"
1639 install_mirrorlist()
1643 if hash reflector >/dev/null 2>&1; then
1644 reflector --score 120 -l 50 -f 5 --sort rate --save "$mfile"
1645 elif hash rankmirrors >/dev/null 2>&1; then
1646 ip_add="$(curl -fsSL "http://api.ipstack.com/check&?access_key=5f29642060ab983b31fdf4c2935d8c56&fields=ip" |
1647 python -c "import sys, json; print(json.load(sys.stdin)['ip'])")"
1649 country="$(curl -fsSL "http://api.ipstack.com/${ip_add}?access_key=5f29642060ab983b31fdf4c2935d8c56&fields=country_code" |
1650 python -c "import sys, json; print(json.load(sys.stdin)['country_code'])")"
1652 if [[ "$country" ]]; then
1653 if [[ $country =~ (CA|US) ]]; then
1654 mirror="https://www.archlinux.org/mirrorlist/?country=US&country=CA&use_mirror_status=on"
1655 elif [[ $country =~ (AU|NZ) ]]; then
1656 mirror="https://www.archlinux.org/mirrorlist/?country=AU&country=NZ&use_mirror_status=on"
1658 mirror="https://www.archlinux.org/mirrorlist/?country=${country}&use_mirror_status=on"
1661 mirror="https://www.archlinux.org/mirrorlist/?country=all&use_mirror_status=on"
1664 curl -fsSL "$mirror" | sed -e 's/^#Server/Server/' -e '/^#/d' | rankmirrors -n 6 - >/etc/pacman.d/mirrorlist
1670 install_background()
1672 if [[ -d /run/archiso/sfs/airootfs/etc/skel ]] && grep -qw "$MNT" /proc/mounts && (grep -qw "$MNT/$BOOTDIR" /proc/mounts || [[ $SYS == 'BIOS' && -z $LUKS ]]); then
1673 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
1674 rsync -a /run/archiso/sfs/airootfs/ $MNT/ &
1676 ( install_mirrorlist "$MNT/etc/pacman.d/mirrorlist" && chrun "pacman -Syyu $BASE_PKGS --needed --noconfirm" >> /tmp/bg_out 2>&1 ) &
1678 trap "kill $RSYNC_PID 2>/dev/null; kill $MIRROR_PID 2>/dev/null" EXIT
1683 ###############################################################################
1688 EDIT_FILES[bootloader]="/etc/default/grub"
1690 if [[ $SYS == 'BIOS' ]]; then
1691 [[ $BOOT_DEV ]] || { part_device 1 || return 1; }
1692 BCMDS[grub]="grub-install --recheck --force --target=i386-pc $BOOT_DEV"
1694 if [[ $ROOT_PART == */dev/mapper/* && -z $LVM && -z $LUKS_PASS ]]; then
1695 luks_pass "$_luksopen" 1 || return 1
1697 BCMDS[grub]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1698 grub-install --recheck --force --target=x86_64-efi --efi-directory=/$BOOTDIR --bootloader-id=$DIST"
1699 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1702 BCMDS[grub]="mkdir -p /run/udev /run/lvm &&
1703 mount --bind /hostrun/udev /run/udev &&
1704 mount --bind /hostrun/lvm /run/lvm &&
1706 grub-mkconfig -o /boot/grub/grub.cfg &&
1707 sleep 1 && umount /run/udev /run/lvm"
1714 sed -i "s/GRUB_DISTRIBUTOR=.*/GRUB_DISTRIBUTOR=\"${DIST}\"/g;
1715 s/GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT=\"\"/g" $MNT/etc/default/grub
1717 if [[ $LUKS_DEV ]]; then
1718 sed -i "s~#GRUB_ENABLE_CRYPTODISK~GRUB_ENABLE_CRYPTODISK~g;
1719 s~GRUB_CMDLINE_LINUX=.*~GRUB_CMDLINE_LINUX=\"${LUKS_DEV}\"~g" $MNT/etc/default/grub 2>$ERR
1720 errshow 1 "sed -i 's~#GRUB_ENABLE_CRYPTODISK~GRUB_ENABLE_CRYPTODISK~g;
1721 s~GRUB_CMDLINE_LINUX=.*~GRUB_CMDLINE_LINUX=\"${LUKS_DEV}\"~g' $MNT/etc/default/grub"
1724 if [[ $SYS == 'BIOS' && $LVM && -z $SEP_BOOT ]]; then
1725 sed -i "s/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g" $MNT/etc/default/grub 2>$ERR
1726 errshow 1 "sed -i 's/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g' $MNT/etc/default/grub"
1729 # setup for os-prober module
1730 mkdir -p /run/{lvm,udev}
1731 mkdir -p $MNT/hostrun/{lvm,udev}
1732 mount --bind /run/lvm $MNT/hostrun/lvm
1733 mount --bind /run/udev $MNT/hostrun/udev
1740 EDIT_FILES[bootloader]=""
1745 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1746 efibootmgr -v -d $BOOT_DEV -p $BOOT_PART_NUM -c -L '${DIST} Linux' -l /vmlinuz-${KERNEL} \
1747 -u 'root=$ROOT_PART_ID rw $([[ $UCODE ]] && printf 'initrd=\%s.img ' "$UCODE")initrd=\initramfs-${KERNEL}.img'"
1753 if [[ $SYS == 'BIOS' ]]; then
1754 EDIT_FILES[bootloader]="/boot/syslinux/syslinux.cfg"
1756 EDIT_FILES[bootloader]="/boot/EFI/syslinux/syslinux.cfg"
1757 BCMDS[syslinux]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1758 efibootmgr -v -c -d $BOOT_DEV -p $BOOT_PART_NUM -l /EFI/syslinux/syslinux.efi -L $DIST"
1765 local c="$MNT/boot/syslinux" s="/usr/lib/syslinux/bios" d=".."
1766 [[ $SYS == 'UEFI' ]] && { c="$MNT/boot/EFI/syslinux"; s="/usr/lib/syslinux/efi64/"; d=''; }
1768 mkdir -pv "$c" && cp -rfv $s/* "$c/" && cp -f "$RUN/syslinux/splash.png" "$c/"
1769 cat > "$c/syslinux.cfg" << EOF
1771 MENU TITLE $DIST Boot Menu
1772 MENU BACKGROUND splash.png
1776 # see: https://www.syslinux.org/wiki/index.php/Comboot/menu.c32
1785 MENU HELPMSGENDROW 29
1786 MENU COLOR border 30;44 #40ffffff #a0000000 std
1787 MENU COLOR title 1;36;44 #9033ccff #a0000000 std
1788 MENU COLOR sel 7;37;40 #e0ffffff #20ffffff all
1789 MENU COLOR unsel 37;44 #50ffffff #a0000000 std
1790 MENU COLOR help 37;40 #c0ffffff #a0000000 std
1791 MENU COLOR timeout_msg 37;40 #80ffffff #00000000 std
1792 MENU COLOR timeout 1;37;40 #c0ffffff #00000000 std
1793 MENU COLOR msg07 37;40 #90ffffff #a0000000 std
1794 MENU COLOR tabmsg 31;40 #30ffffff #00000000 std
1797 MENU LABEL $DIST Linux
1798 LINUX $d/vmlinuz-$KERNEL
1799 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1800 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL.img
1802 LABEL ${DIST}fallback
1803 MENU LABEL $DIST Linux Fallback
1804 LINUX $d/vmlinuz-$KERNEL
1805 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1806 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL-fallback.img
1807 $([[ $SYS == 'BIOS' ]] && printf "\n%s" "# examples of chainloading other bootloaders
1812 #APPEND file=$d/grub/boot.img
1824 EDIT_FILES[bootloader]="/boot/refind_linux.conf"
1825 BCMDS[refind-efi]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1831 cat > $MNT/boot/refind_linux.conf << EOF
1832 "$DIST Linux" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] &&
1833 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1834 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL.img"
1835 "$DIST Linux Fallback" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] &&
1836 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1837 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL-fallback.img"
1839 mkdir -p $MNT/etc/pacman.d/hooks
1840 cat > $MNT/etc/pacman.d/hooks/refind.hook << EOF
1847 Description = Updating rEFInd on ESP
1848 When = PostTransaction
1849 Exec = /usr/bin/refind-install
1853 setup_systemd-boot()
1855 EDIT_FILES[bootloader]="/boot/loader/entries/$DIST.conf"
1856 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1857 bootctl --path=/boot install"
1860 prerun_systemd-boot()
1862 mkdir -p $MNT/boot/loader/entries
1863 cat > $MNT/boot/loader/loader.conf << EOF
1868 cat > $MNT/boot/loader/entries/$DIST.conf << EOF
1870 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1871 initrd /initramfs-$KERNEL.img
1872 options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1874 cat > $MNT/boot/loader/entries/$DIST-fallback.conf << EOF
1875 title $DIST Linux Fallback
1876 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1877 initrd /initramfs-$KERNEL-fallback.img
1878 options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1880 mkdir -p $MNT/etc/pacman.d/hooks
1881 cat > $MNT/etc/pacman.d/hooks/systemd-boot.hook << EOF
1888 Description = Updating systemd-boot
1889 When = PostTransaction
1890 Exec = /usr/bin/bootctl update
1892 systemd-machine-id-setup --root="$MNT"
1896 ###############################################################################
1901 check_background_install || return 1
1904 dlg choice menu "Logical Volume Management" "$_lvmmenu" \
1905 "$_lvmnew" "vgcreate -f, lvcreate -L -n" \
1906 "$_lvmdel" "vgremove -f" \
1907 "$_lvmdelall" "lvrmeove, vgremove, pvremove -f" \
1908 "back" "return to the main menu"
1911 "$_lvmnew") lvm_create || return 1 ;;
1912 "$_lvmdel") lvm_delgroup && yesno "$_lvmdel" "$_lvmdelask" && vgremove -f "$DEL_VG" >/dev/null 2>&1 ;;
1913 "$_lvmdelall") lvm_del_all ;;
1922 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
1923 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
1924 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
1926 if [[ $VGROUP && $v && $pv ]]; then
1927 msg "Logical Volume Management" "\nActivating existing logical volume management (LVM).\n\n" 1
1928 modprobe dm-mod >/dev/null 2>$ERR
1929 errshow 'modprobe dm-mod'
1930 vgscan >/dev/null 2>&1
1931 vgchange -ay >/dev/null 2>&1
1937 VGROUP='' LVM_PARTS='' VGROUP_MB=0
1939 lvm_mkgroup || return 1
1940 local txt="\nThe last (or only) logical volume will automatically use all remaining space in the volume group."
1941 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
1942 [[ $VOL_COUNT ]] || return 1
1943 lvm_extra_lvs || return 1
1944 lvm_volume_name "$_lvmlvname\nNOTE: This LV will use up all remaining space in the volume group (${VGROUP_MB}MB)" || return 1
1945 lvcreate -l +100%FREE "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
1946 errshow "lvcreate -l +100%FREE $VGROUP -n $VNAME" || return 1
1947 LVM='logical volume'; sleep 0.5
1948 txt="\nDone, volume: $VGROUP-$VNAME (${VOLUME_SIZE:-${VGROUP_MB}MB}) has been created.\n"
1949 msg "$_lvmnew (LV:$VOL_COUNT)" "$txt\n$(lsblk -o NAME,MODEL,TYPE,FSTYPE,SIZE $LVM_PARTS)\n"
1955 local txt="${VGROUP}: ${SIZE}$SIZE_UNIT (${VGROUP_MB}MB remaining).$_lvmlvsize"
1959 dlg VOLUME_SIZE input "$_lvmnew (LV:$VOL_COUNT)" "$txt" ''
1960 if [[ -z $VOLUME_SIZE ]]; then
1962 break # allow bailing with escape or an empty choice
1963 elif (( ${VOLUME_SIZE:0:1} == 0 )); then
1964 ERR_SIZE=1 # size values can't begin with '0'
1966 # walk the string and make sure all but the last char are digits
1967 local lv=$((${#VOLUME_SIZE} - 1))
1968 for (( i=0; i<lv; i++ )); do
1969 [[ ${VOLUME_SIZE:$i:1} =~ [0-9] ]] || { ERR_SIZE=1; break; }
1971 if (( ERR_SIZE != 1 )); then
1972 case ${VOLUME_SIZE:$lv:1} in
1973 [mMgG]) local s=${VOLUME_SIZE:0:$lv} m=$((s * 1000))
1974 case ${VOLUME_SIZE:$lv:1} in
1975 [Gg]) (( m >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - m)) ;;
1976 [Mm]) (( ${VOLUME_SIZE:0:$lv} >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - s)) ;;
1983 if (( ERR_SIZE )); then
1984 msg "Invalid Logical Volume Size" "$_lvmerrlvsize"
1996 local txt="\nConfirm creation of volume group: $VGROUP\n\nwith the following partition(s):"
1998 until [[ $named ]]; do
1999 lvm_partitions || return 1
2000 lvm_group_name || return 1
2001 yesno "$_lvmnew" "$txt $LVM_PARTS\n" && named=true
2004 vgcreate -f "$VGROUP" $LVM_PARTS >/dev/null 2>$ERR
2005 errshow "vgcreate -f $VGROUP $LVM_PARTS" || return 1
2007 SIZE=$(vgdisplay "$VGROUP" | awk '/VG Size/ { gsub(/[^0-9.]/, ""); print int($0) }')
2008 SIZE_UNIT="$(vgdisplay "$VGROUP" | awk '/VG Size/ { print substr($NF, 0, 1) }')"
2010 if [[ $SIZE_UNIT == 'G' ]]; then
2011 VGROUP_MB=$((SIZE * 1000))
2016 msg "$_lvmnew" "\nVolume group: $VGROUP ($SIZE $SIZE_UNIT) has been created\n"
2023 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
2024 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
2025 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
2027 if [[ $VGROUP || $v || $pv ]]; then
2028 if yesno "$_lvmdelall" "$_lvmdelask"; then
2029 for i in $v; do lvremove -f "/dev/mapper/$i" >/dev/null 2>&1; done
2030 for i in $VGROUP; do vgremove -f "$i" >/dev/null 2>&1; done
2031 for i in $pv; do pvremove -f "$i" >/dev/null 2>&1; done
2035 msg "Delete LVM" "\nNo LVMs to remove...\n" 2
2045 for i in $(lvs --noheadings | awk '{print $2}' | uniq); do
2046 VOL_GROUP_LIST+="$i $(vgdisplay "$i" | awk '/VG Size/ {print $3$4}') "
2048 [[ $VOL_GROUP_LIST ]] || { msg "No Groups" "\nNo volume groups found."; return 1; }
2050 dlg DEL_VG menu "Logical Volume Management" "\nSelect volume group to delete.\n\nAll logical volumes within will also be deleted." $VOL_GROUP_LIST
2056 while (( VOL_COUNT > 1 )); do
2057 lvm_volume_name "$_lvmlvname" && get_lv_size || return 1
2058 lvcreate -L "$VOLUME_SIZE" "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
2059 errshow "lvcreate -L $VOLUME_SIZE $VGROUP -n $VNAME" || return 1
2060 msg "$_lvmnew (LV:$VOL_COUNT)" "\nDone, logical volume (LV) $VNAME ($VOLUME_SIZE) has been created.\n"
2068 part_find 'part|crypt' || return 1
2069 PARTS="$(awk 'NF > 0 {print $0 " off"}' <<< "$PARTS")"
2070 dlg LVM_PARTS check "$_lvmnew" "\nSelect the partition(s) to use for the physical volume (PV)." $PARTS
2077 until [[ $VGROUP ]]; do
2078 dlg VGROUP input "$_lvmnew" "$_lvmvgname" "mygroup"
2079 if [[ -z $VGROUP ]]; then
2081 elif [[ ${VGROUP:0:1} == "/" || $VGROUP =~ \ |\' ]] || lsblk | grep -q "$VGROUP"; then
2082 msg "LVM Name Error" "$_lvmerrvgname"
2092 local txt="$1" default="mainvolume"
2093 (( VOL_COUNT > 1 )) && default="extravolume$VOL_COUNT"
2094 until [[ $VNAME ]]; do
2095 dlg VNAME input "$_lvmnew (LV:$VOL_COUNT)" "\n$txt" "$default"
2096 if [[ -z $VNAME ]]; then
2098 elif [[ ${VNAME:0:1} == "/" || $VNAME =~ \ |\' ]] || lsblk | grep -q "$VNAME"; then
2099 msg "LVM Name Error" "$_lvmerlvname"
2106 ###############################################################################
2112 check_background_install || return 1
2113 dlg choice menu "LUKS Encryption" "$_luksmenu" \
2114 "$_luksnew" "cryptsetup -q luksFormat" \
2115 "$_luksopen" "cryptsetup open --type luks" \
2116 "$_luksadv" "cryptsetup -q -s -c luksFormat" \
2117 "back" "Return to the main menu"
2120 "$_luksnew") luks_basic || return 1 ;;
2121 "$_luksopen") luks_open || return 1 ;;
2122 "$_luksadv") luks_advanced || return 1 ;;
2130 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
2132 part_find 'part|crypt|lvm' || return 1
2134 if (( COUNT == 1 )); then
2135 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2137 dlg LUKS_PART menu "$_luksopen" "\nSelect which partition to open." $PARTS
2140 [[ $LUKS_PART ]] || return 1
2142 luks_pass "$_luksopen" || return 1
2143 msg "$_luksopen" "\nOpening encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2144 cryptsetup open --type luks "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2145 errshow "cryptsetup open --type luks $LUKS_PART $LUKS_NAME" || return 1
2146 LUKS='encrypted'; luks_show
2153 local t="$1" op="$2" v='' p='' p2=''
2155 until [[ $LUKS_PASS ]]; do
2159 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " $t " \
2160 --mixedform "\nEnter the password to decrypt $ROOT_PART\n\nThis is needed to create a keyfile." 0 0 0 \
2161 "Password:" 1 1 '' 1 11 "$COLUMNS" 0 1 \
2162 "Password2:" 2 1 '' 2 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
2165 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " $t " --mixedform "$_luksomenu" 0 0 0 \
2166 "Name:" 1 1 "${LUKS_NAME:-cryptroot}" 1 7 "$COLUMNS" 0 0 \
2167 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
2168 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
2172 while read -r line; do
2188 if [[ -z $op && -z $n ]]; then
2189 msg "Name Empty" "\nEncrypted device name cannot be empty.\n\nPlease try again.\n" 2
2190 elif [[ -z $p || "$p" != "$p2" ]]; then
2191 [[ $op ]] || LUKS_NAME="$n"
2192 msg "Password Mismatch" "\nThe passwords entered do not match.\n\nPlease try again.\n" 2
2194 [[ $op ]] || LUKS_NAME="$n"
2205 msg "$_luksnew" "\nEncrypted partition opened and ready for mounting.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$LUKS_PART")\n\n"
2210 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
2212 part_find 'part|lvm' || return 1
2214 if [[ $AUTO_ROOT_PART ]]; then
2215 LUKS_PART="$AUTO_ROOT_PART"
2216 elif (( COUNT == 1 )); then
2217 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2219 dlg LUKS_PART menu "$_luksnew" "\nSelect the partition you want to encrypt." $PARTS
2222 [[ $LUKS_PART ]] || return 1
2223 luks_pass "$_luksnew"
2228 luks_setup || return 1
2229 msg "$_luksnew" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2230 cryptsetup -q luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2231 errshow "cryptsetup -q luksFormat $LUKS_PART" || return 1
2232 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2233 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2234 LUKS='encrypted'; luks_show
2240 if [[ ! -e $MNT/crypto_keyfile.bin ]]; then
2241 # printf "Creating LUKS keyfile /crypto_keyfile.bin\n"
2243 n="$(lsblk -lno NAME,UUID,TYPE | awk "/$LUKS_UUID/"' && /part|crypt|lvm/ {print $1}')"
2244 local mkkey="dd bs=512 count=8 if=/dev/urandom of=/crypto_keyfile.bin"
2245 mkkey="$mkkey && chmod 000 /crypto_keyfile.bin"
2246 mkkey="$mkkey && cryptsetup luksAddKey /dev/$n /crypto_keyfile.bin <<< '$LUKS_PASS'"
2248 sed -i 's/FILES=()/FILES=(\/crypto_keyfile.bin)/g' $MNT/etc/mkinitcpio.conf 2>$ERR
2258 dlg cipher input "LUKS Encryption" "$_lukskey" "-s 512 -c aes-xts-plain64"
2259 [[ $cipher ]] || return 1
2260 msg "$_luksadv" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2261 cryptsetup -q $cipher luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2262 errshow "cryptsetup -q $cipher luksFormat $LUKS_PART" || return 1
2263 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2264 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2271 ###############################################################################
2276 [[ "$2" == *"$1"* ]] && printf "on" || printf "off"
2285 if [[ -d $MNT ]] && command cd /; then
2287 if (( exitcode == 127 )); then
2288 umount -l /run/archiso/bootmnt
2294 # restore custom linux console 0-15 colors when not rebooting
2295 if [[ $TERM == 'linux' ]]; then
2296 colors=("\e]P0191919" "\e]P1D15355" "\e]P2609960" "\e]P3FFCC66"
2297 "\e]P4255A9B" "\e]P5AF86C8" "\e]P62EC8D3" "\e]P7949494" "\e]P8191919" "\e]P9D15355"
2298 "\e]PA609960" "\e]PBFF9157" "\e]PC4E88CF" "\e]PDAF86C8" "\e]PE2ec8d3" "\e]PFE1E1E1")
2299 printf "%b" "${colors[@]}" && clear && unset col
2307 local var="$1" dialog_type="$2" title="$3" body="$4" n=0
2309 (( ($# / 2) > SHL )) && n=$SHL
2312 case "$dialog_type" in
2314 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --menu "$body" 0 0 $n "$@" 2>"$ANS" || return 1
2317 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --checklist "$body" 0 0 $n "$@" 2>"$ANS" || return 1
2323 if [[ $1 == 'limit' ]]; then
2324 dialog --backtitle "$DIST Installer - $SYS - v$VER" --max-input 63 --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2326 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2330 [[ -s "$ANS" ]] && printf -v "$var" "%s" "$(< "$ANS")"
2335 local title="$1" body="$2"
2337 if (( $# == 3 )); then
2338 dialog --backtitle "$DIST Installer - $SYS - v$VER" --sleep "$3" --title " $title " --infobox "$body\n" 0 0
2340 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --msgbox "$body\n" 0 0
2346 local title="$1" body="$2" yes='Yes' no='No'
2347 (( $# >= 3 )) && local yes="$3"
2348 (( $# >= 4 )) && local no="$4"
2350 if (( $# == 5 )); then
2351 dialog --backtitle "$DIST Installer - $SYS - v$VER" --defaultno --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2353 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2359 arch-chroot "$MNT" bash -c "$1"
2364 export PS4='| ${BASH_SOURCE} LINE:${LINENO} FUNC:${FUNCNAME[0]:+ ${FUNCNAME[0]}()} |> '
2373 printf "\n^C caught, cleaning up...\n"
2380 if [[ $COLUMNS -ge 110 && ${#str} -gt $((COLUMNS - 30)) ]]; then
2382 i = 2; p1 = p2 = p3 = p4 = ""; p1 = $1; q = int(NF / 4)
2383 for (; i <= q; i++) { p1 = p1 " " $i }
2384 for (; i <= q * 2; i++) { p2 = p2 " " $i }
2385 for (; i <= q * 3; i++) { p3 = p3 " " $i }
2386 for (; i <= NF; i++) { p4 = p4 " " $i }
2387 printf "%s\n %s\n %s\n %s", p1, p2, p3, p4
2389 printf "%s\n" "$str"
2390 elif [[ $str ]]; then
2391 printf "%s\n" "$str"
2398 (( exit_code == 0 )) && return 0
2400 local fatal=0 err=""
2401 err="$(sed 's/[^[:print:]]//g; s/\[[0-9\;:]*\?m//g; s/==> //g; s/] ERROR:/]\nERROR:/g' "$ERR")"
2402 (( $1 == 1 )) && { fatal=1; shift; }
2403 local txt="\nThe command exited abnormally:\n\n$1\n\n"
2406 txt+="With the following message:\n\n$err\n\n"
2408 txt+="With no error message:\n\n"
2411 if (( fatal == 1 )); then
2412 txt+="Errors at this stage are fatal and the install cannot continue.\n"
2414 txt+="Errors at this stage are non-fatal and can be either fixed or ignored depending on the error.\n"
2417 msg "Install Error" "$txt"
2419 if (( fatal == 1 )); then
2420 [[ -r $DBG && $TERM == 'linux' ]] && less "$DBG"
2429 msg "Broadcom Wireless Setup" "\nDetected chipset is Broadcom BCM4352\n\nDisabling bcma/b43 modules and loading wl module.\n" 1
2430 { rmmod wl; rmmod bcma; rmmod b43; rmmod ssb; modprobe wl; depmod -a; } >/dev/null 2>&1
2436 if [[ $1 -ge 0 ]] && ! grep -qw "$MNT" /proc/mounts; then
2437 msg "Not Mounted" "\nPartition(s) must be mounted first.\n" 2
2440 elif [[ $1 -ge 1 && -z $BOOTLDR ]]; then
2441 msg "No Bootloader" "\nBootloader must be selected first.\n" 2
2444 elif [[ $1 -ge 2 && (-z $NEWUSER || -z $USER_PASS) ]]; then
2445 msg "No User" "\nA user must be created first.\n" 2
2448 elif [[ $1 -ge 3 && -z $CONFIG_DONE ]]; then
2449 msg "Not Configured" "\nSystem configuration must be done first.\n" 2
2459 [[ -d $1 ]] && umount -R "$1" >/dev/null 2>&1
2465 msg "Network Connect" "\nVerifying network connection\n" 1
2466 curl -sIN --connect-timeout 5 'https://www.archlinux.org/' | sed '1q' | grep -q '200'
2471 if chk_connect; then
2474 if hash nmtui >/dev/null 2>&1; then
2476 [[ $TERM == 'linux' ]] && printf "%b" "\e]P1191919" "\e]P4191919"
2478 [[ $TERM == 'linux' ]] && printf "%b" "\e]P1D15355" "\e]P4255a9b"
2488 IGNORE_DEV="$(lsblk -lno NAME,MOUNTPOINT | awk '/\/run\/archiso\/bootmnt/ {sub(/[1-9]/, ""); print $1}')"
2490 if [[ $IGNORE_DEV ]]; then
2491 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ && !'"/$IGNORE_DEV/"' {print "/dev/" $1 " " $2}')"
2493 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ {print "/dev/" $1 " " $2}')"
2496 if [[ -z $SYS_DEVS ]]; then
2497 msg "Device Error" "\nNo available devices...\n\nExiting..\n" 2
2502 while read -r line; do
2504 done <<< "$SYS_DEVS"
2511 elif grep -q 'AuthenticAMD' /proc/cpuinfo; then
2513 elif grep -q 'GenuineIntel' /proc/cpuinfo; then
2517 modprobe -q efivarfs >/dev/null 2>&1
2519 _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."
2520 if [[ -d /sys/firmware/efi/efivars ]]; then
2522 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars
2523 _prep+="\n - An EFI boot partition mounted."
2527 _prep+="\n\nOnce finished mounting, a portion of the install can be done in the background while you continue configuring the system:\n"
2528 _prep+="\n - Choose the system bootloader.\n - Create a user and password."
2529 _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."
2532 check_background_install()
2534 [[ $RSYNC_PID || $MIRROR_PID ]] || return 0
2535 msg "Install Running" "\nA background install process is currently running.\n" 2
2539 ###############################################################################
2542 if (( UID != 0 )); then
2543 msg "Not Root" "\nThis installer must be run as root or using sudo.\n\nExiting..\n" 2
2545 elif ! grep -qwm 1 'lm' /proc/cpuinfo; then
2546 msg "Not x86_64 Architecture" "\nThis installer only supports x86_64 architectures.\n\nExiting..\n" 2
2548 elif [[ $1 =~ (-d|--debug) ]]; then
2552 # trap ^C to perform cleanup
2558 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"
2560 select_keymap || { clear; die 0; }
2562 if lspci -vnn -d 14e4: | grep -q 'BCM4352'; then
2566 if ! net_connect; then
2567 msg "Not Connected" "\nThis installer requires an active internet connection.\n\nExiting..\n" 2
2575 # vim:fdm=marker:fmr={,}