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.48" # installer version
9 DIST="ArchLabs" # linux distributor
10 MNT="/mnt" # install mountpoint
11 ANS="/tmp/ans" # dialog answer file
14 # ------------------------------------------------------ #
15 # When manually mounting your partitions, you need
16 # 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 # boot device, used for some bootloaders 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 # these values will be selected during the install, it is not recommended
42 # to edit them here unless you know what you're doing.
44 UCODE='' # cpu microcode (if any), can be: amd-ucode, intel-ucode
45 KERNEL='' # linux kernel, can be: linux, linux-lts, linux-zen, or linux-hardened
46 MYSHELL='' # full path for the shell, eg. /usr/bin/zsh
48 SWAP_PART='' # swap partition or file path
49 SWAP_SIZE='' # swap size, only used when creating a swapfile
51 EXMNT='' # holder for additional partitions while mounting
52 EXMNTS='' # when an extra partition is mounted append it's info
54 FONT="ter-i16n" # font used for the linux console
55 HOOKS="shutdown" # list of additional HOOKS to add in /etc/mkinitcpio.conf
57 LOGIN_TYPE='' # login manager can be: lightdm, xinit
58 LOGIN_WM='' # default login session to be placed in ~/.xinitrc
59 LOGINRC='' # login shell rc file, eg. .zprofile, .bash_profile, .profile
61 INSTALL_WMS='' # space separated list of chosen wm/de
63 WM_PKGS='' # full list of packages added during wm/de choice (not user edited)
64 PACKAGES='' # list of all packages to install including WM_PKGS (not user edited)
65 USER_PKGS='' # packages selected by the user during install
67 NEWUSER='' # username for the new user
68 USER_PASS='' # new user's password
69 ROOT_PASS='' # root password
71 LUKS='' # empty when not using encryption
72 LUKS_DEV='' # boot parameter string for LUKS
73 LUKS_PART='' # partition used for encryption
74 LUKS_PASS='' # encryption password
75 LUKS_UUID='' # encrypted partition UUID
76 LUKS_NAME='' # name used for encryption
78 LVM='' # empty when not using lvm
79 LVM_PARTS='' # partitions used for volume group
80 VGROUP_MB=0 # available space in volume group
82 WARN='' # issued mounting/partitioning warning
83 SEP_BOOT='' # separate boot partition for BIOS
84 AUTOLOGIN='' # enable autologin for xinit
85 CONFIG_DONE='' # basic configuration is finished
86 BROADCOM_WL='' # fixes for broadcom cards eg. BCM4352
88 FORMATTED='' # partitions we formatted and should allow skipping
89 AUTO_ROOT_PART='' # root value from auto partition
90 AUTO_BOOT_PART='' # boot value from auto partition
92 # iso base, pacstrap when running the installer from a stock arch iso
93 ISO_BASE="b43-firmware b43-fwcutter broadcom-wl clonezilla dhclient dhcpcd ethtool wpa_supplicant "
94 ISO_BASE+="exfat-utils f2fs-tools gptfdisk vim hdparm ipw2100-fw ipw2200-fw nfs-utils nilfs-utils ntfs-3g "
95 ISO_BASE+="pacman-contrib parted rsync sdparm smartmontools wget wireless_tools wpa_actiond xl2tpd dialog parted "
96 ISO_BASE+="alsa-firmware alsa-lib alsa-plugins pulseaudio pulseaudio-alsa networkmanager w3m htop wireless-regdb "
97 ISO_BASE+="lm_sensors lsb-release p7zip pamixer reflector unrar ranger terminus-font ttf-dejavu archlabs-keyring"
99 # archlabs base packages
100 AL_BASE_PKGS="archlabs-skel-base archlabs-fonts archlabs-themes archlabs-dARK archlabs-icons archlabs-wallpapers archlabs-scripts"
102 # baseline (usually installed in the background)
103 BASE_PKGS="base-devel xorg xorg-drivers xorg-xinit sudo git gvfs gtk3 gtk-engines gtk-engine-murrine pavucontrol tumbler "
104 BASE_PKGS+="playerctl ffmpeg gstreamer libmad libmatroska gst-libav gst-plugins-base gst-plugins-good scrot"
106 # extras for window managers
107 WM_BASE_PKGS="arandr archlabs-networkmanager-dmenu xdg-user-dirs nitrogen polkit-gnome volumeicon xclip exo "
108 WM_BASE_PKGS+="xdotool compton wmctrl gnome-keyring dunst feh gsimplecal xfce4-power-manager xfce4-settings laptop-detect"
111 SEL=0 # currently selected menu item
112 ERR="/tmp/errlog" # error log used internally
113 DBG="/tmp/debuglog" # debug log when passed -d
114 RUN="/run/archiso/bootmnt/arch/boot" # path for live /boot
115 VM="$(dmesg | grep -i "hypervisor")" # is the system a vm
118 export DIALOGOPTS="--cr-wrap"
122 # giant ugly variable container :P {
124 # RAM in the system in MB
125 SYS_MEM="$(awk '/MemTotal/ {print int($2 / 1024) "M"}' /proc/meminfo)"
127 # locales from /etc/locale.gen
128 LOCALES="$(awk '/\.UTF-8/ {gsub(/# .*|#/, ""); if ($1) {print $1 " - "}}' /etc/locale.gen)"
130 # linux console keyboard mappings
131 CMAPS="$(find /usr/share/kbd/keymaps -name '*.map.gz' | awk '{gsub(/\.map\.gz|.*\//, ""); print $1 " - "}' | sort)"
133 # terminal size definitions
134 [[ $LINES ]] || LINES=$(tput lines)
135 [[ $COLUMNS ]] || COLUMNS=$(tput cols)
141 # commands used to install each bootloader (most get modified during runtime) {
143 [refind-efi]='refind-install'
144 [grub]='grub-install --recheck --force'
145 [syslinux]='syslinux-install_update -i -a -m'
146 [efistub]='efibootmgr -v -d /dev/sda -p 1 -c -l'
147 [systemd-boot]='bootctl --path=/boot install'
150 # executable name for each wm/de {
151 declare -A WM_SESSIONS=(
158 [gnome]='gnome-session'
159 [fluxbox]='startfluxbox'
160 [openbox]='openbox-session'
161 [cinnamon]='cinnamon-session'
164 # packages installed for each wm/de {
169 [plasma]='kdebase-meta'
170 [bspwm]='sxhkd archlabs-skel-bspwm rofi archlabs-polybar'
171 [fluxbox]='archlabs-skel-fluxbox archlabs-polybar jgmenu rofi lxmenu-data'
172 [i3-gaps]='i3status perl-anyevent-i3 archlabs-skel-i3-gaps rofi archlabs-polybar'
173 [openbox]='obconf archlabs-skel-openbox jgmenu archlabs-polybar tint2 conky rofi lxmenu-data'
174 [xfce4]='xfce4-goodies xfce4-pulseaudio-plugin network-manager-applet volumeicon rofi archlabs-skel-xfce4'
177 # files that can be edited after install is complete {
178 declare -A EDIT_FILES=(
181 [sudoers]='/etc/sudoers'
182 [crypttab]='/etc/crypttab'
183 [pacman]='/etc/pacman.conf'
184 [console]='/etc/vconsole.conf'
185 [mkinitcpio]='/etc/mkinitcpio.conf'
186 [hostname]='/etc/hostname /etc/hosts'
187 [bootloader]="/boot/loader/entries/$DIST.conf"
188 [locale]='/etc/locale.conf /etc/default/locale'
189 [keyboard]='/etc/X11/xorg.conf.d/00-keyboard.conf /etc/default/keyboard'
192 # mkfs command for formatting each offered filesystem {
197 [ntfs]='mkfs.ntfs -q'
198 [ext2]='mkfs.ext2 -q'
199 [ext3]='mkfs.ext3 -q'
200 [ext4]='mkfs.ext4 -q'
201 [vfat]='mkfs.vfat -F32'
202 [nilfs2]='mkfs.nilfs2 -q'
203 [reiserfs]='mkfs.reiserfs -q'
206 # mount options for each offered filesystem (if any {
212 [jfs]='discard errors=continue errors=panic nointegrity'
213 [reiserfs]='acl nolog notail replayonly user_xattr off'
214 [ext4]='discard dealloc nofail noacl relatime noatime nobarrier nodelalloc'
215 [xfs]='discard filestreams ikeep largeio noalign nobarrier norecovery noquota wsync'
216 [nilfs2]='discard nobarrier errors=continue errors=panic order=relaxed order=strict norecovery'
217 [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'
220 # PKG_EXT: if you add a package to $PACKAGES in any dialog {
221 # and it uses/requires some additional packages,
222 # you can add them here to keep it simple: [package]="extra"
223 # duplicates are removed with `uniq` before install
227 [mupdf]='mupdf-tools'
228 [qt5ct]='qt5-styleplugins'
229 [vlc]='qt5ct qt5-styleplugins'
230 [zathura]='zathura-pdf-poppler'
231 [noto-fonts]='noto-fonts-emoji'
232 [cairo-dock]='cairo-dock-plug-ins'
233 [qutebrowser]='qt5ct qt5-styleplugins'
234 [qbittorrent]='qt5ct qt5-styleplugins'
235 [transmission-qt]='qt5ct qt5-styleplugins'
236 [kdenlive]='kdebase-meta dvdauthor frei0r-plugins breeze breeze-gtk qt5ct qt5-styleplugins'
244 # Basics (somewhat in order)
245 _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"
246 _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"
247 _device="\nSelect a device to use from the list below.\n\nDevices (/dev) are the available drives on the system. /sda, /sdb, /sdc ..."
248 _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."
249 _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."
250 _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"
251 _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)."
252 _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."
253 _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."
254 _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."
255 _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"
256 _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."
257 _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."
258 _exmnt="\nWhere do you want the partition mounted?\n\nEnsure the name begins with a slash (/).\nExamples include: /usr, /home, /var, etc."
259 _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."
260 _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."
261 _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"
262 _timez="\nThe time zone is used to set the system clock.\n\nSelect your country or continent from the list below"
263 _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."
264 _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."
265 _login="\nSelect which of your session choices to use for the initial login.\n\nYou can be change this later by editing your ~/.xinitrc"
266 _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."
267 _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."
270 _luksnew="Basic LUKS Encryption"
271 _luksadv="Advanced LUKS Encryption"
272 _luksopen="Open Existing LUKS Partition"
273 _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."
274 _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."
275 _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)."
278 _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."
279 _lvmnew="Create Volume Group and Volume(s)"
280 _lvmdel="Delete an Existing Volume Group"
281 _lvmdelall="Delete ALL Volume Group(s) and Volume(s)"
282 _lvmvgname="\nEnter a name for the volume group (VG) being created from the partition(s) selected."
283 _lvmlvname="\nEnter a name for the logical volume (LV) being created.\n\nThis is similar to setting a label for a partition."
284 _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."
285 _lvmdelask="\nConfirm deletion of volume group(s) and logical volume(s).\n\nDeleting a volume group, will delete all logical volumes within it.\n"
288 _errexpart="\nCannot mount partition due to a problem with the mountpoint.\n\nEnsure it begins with a slash (/) followed by atleast one character.\n"
289 _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"
290 _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"
291 _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"
292 _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"
293 _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"
294 _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"
300 ###############################################################################
305 (( SEL < 12 )) && (( SEL++ ))
307 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Prepare " --default-item $SEL --cancel-label 'Exit' --menu "$_prep" 0 0 0 \
308 1 "Device tree (optional)" \
309 2 "Partitioning (optional)" \
310 3 "LUKS setup (optional)" \
311 4 "LVM setup (optional)" \
312 5 "Mount partitions" \
313 6 "System bootloader" \
314 7 "User and password" \
315 8 "System configuration" \
316 9 "Select WM/DE (optional)" \
317 10 "Select Packages (optional)" \
318 11 "View configuration (optional)" \
319 12 "Start the installation" 2>"$ANS"
322 [[ -z $WARN && $SEL =~ (2|5) ]] && { msg "Data Warning" "$_warn"; WARN=true; }
325 2) part_menu || (( SEL-- )) ;;
326 3) luks_menu || (( SEL-- )) ;;
327 4) lvm_menu || (( SEL-- )) ;;
328 5) select_menu || (( SEL-- )) ;;
329 6) prechecks 0 && { select_boot || (( SEL-- )); } ;;
330 7) prechecks 1 && { select_mkuser || (( SEL-- )); } ;;
331 8) prechecks 2 && { select_config || (( SEL-- )); } ;;
332 9) prechecks 3 && { select_sessions || (( SEL-- )); } ;;
333 10) prechecks 3 && { select_packages || (( SEL-- )); } ;;
334 11) prechecks 3 && select_show ;;
335 12) prechecks 3 && install_main ;;
336 *) yesno "Exit" "\nUnmount partitions (if any) and exit the installer?\n" && die 0
342 if [[ $SYS == 'BIOS' ]]; then
343 dlg BOOTLDR menu "BIOS Bootloader" "\nSelect which bootloader to use." \
344 "grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
345 "syslinux" "A collection of boot loaders for booting drives, CDs, or over the network" || return 1
347 dlg BOOTLDR menu "UEFI Bootloader" "\nSelect which bootloader to use." \
348 "systemd-boot" "A simple UEFI boot manager which executes configured EFI images" \
349 "grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
350 "refind-efi" "A UEFI boot manager that aims to be platform neutral and simplify multi-boot" \
351 "efistub" "Boot the kernel image directly (no chainloading support)" \
352 "syslinux" "A collection of boot loaders for booting drives, CDs, or over the network (no chainloading support)" || return 1
360 local cmd="${BCMDS[$BOOTLDR]}"
361 local pkgs="${USER_PKGS// / } ${PACKAGES// / }"
362 [[ $BOOT_PART ]] && mnt="/$BOOTDIR"
363 [[ $INSTALL_WMS == *dwm* ]] && pkgs="dwm st dmenu $pkgs"
365 msg "Show Configuration" "
367 ---------- PARTITION CONFIGURATION ------------
369 Root: ${ROOT_PART:-none}
370 Boot: ${BOOT_PART:-${BOOT_DEV:-none}}
372 Swap: ${SWAP_PART:-none}
373 Size: ${SWAP_SIZE:-none}
378 Extra: ${EXMNTS:-${EXMNT:-none}}
379 Hooks: ${HOOKS:-none}
382 ---------- BOOTLOADER CONFIGURATION -----------
384 Bootloader: ${BOOTLDR:-none}
385 Mountpoint: ${mnt:-none}
386 Command: ${cmd:-none}
389 ------------ SYSTEM CONFIGURATION -------------
391 Locale: ${MYLOCALE:-none}
392 Keymap: ${KEYMAP:-none}
393 Hostname: ${MYHOST:-none}
394 Timezone: ${ZONE:-none}/${SUBZ:-none}
397 ------------ USER CONFIGURATION --------------
399 User: ${NEWUSER:-none}
400 Shell: ${MYSHELL:-none}
401 Session: ${LOGIN_WM:-none}
402 Autologin: ${AUTOLOGIN:-none}
403 Login Method: ${LOGIN_TYPE:-none}
406 ------------ PACKAGES AND MIRRORS -------------
408 Kernel: ${KERNEL:-none}
409 Sessions: ${INSTALL_WMS:-none}
410 Packages: $(print4 "${pkgs:-none}")
416 if [[ -z $LOGIN_TYPE ]]; then
417 dlg LOGIN_TYPE menu "Login Management" "\nSelect what kind of login management to use." \
418 "xinit" "Console login without a display manager" \
419 "lightdm" "Lightweight display manager with a gtk greeter" || return 1
422 if [[ $LOGIN_TYPE == 'lightdm' ]]; then
424 LOGIN_PKGS="lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings accountsservice"
425 EDIT_FILES[login]="/etc/lightdm/lightdm.conf /etc/lightdm/lightdm-gtk-greeter.conf"
427 if (( WM_NUM == 1 )); then
428 LOGIN_WM="${WM_SESSIONS[$INSTALL_WMS]}"
430 dlg LOGIN_WM menu "Login Management" "$_login" $LOGIN_CHOICES || return 1
431 LOGIN_WM="${WM_SESSIONS[$LOGIN_WM]}"
434 local txt="\nDo you want autologin enabled for $NEWUSER?\n\n"
435 txt+="If so the following two files will be created (disable autologin by removing them):\n\n"
436 txt+="- /home/$NEWUSER/$LOGINRC (run startx when logging in on tty1)\n"
437 txt+="- /etc/systemd/system/getty@tty1.service.d/autologin.conf (login $NEWUSER without password)\n"
438 yesno "Autologin" "$txt" && AUTOLOGIN=true || AUTOLOGIN=''
439 LOGIN_PKGS="xorg-xinit"
440 EDIT_FILES[login]="/home/$NEWUSER/.xinitrc /home/$NEWUSER/.xprofile"
449 until [[ $CONFIG_DONE ]]; do
452 dlg MYSHELL menu "Shell" "\nChoose which shell to use." \
453 /usr/bin/zsh 'A very advanced and programmable command interpreter (shell) for UNIX' \
454 /bin/bash 'The GNU Bourne Again shell, standard in many GNU/Linux distributions' \
455 /usr/bin/mksh 'The MirBSD Korn Shell - an enhanced version of the public domain ksh' || return 1
458 1) dlg MYHOST input "Hostname" "$_hostname" "${DIST,,}" limit || { i=0; continue; } ;;
459 2) dlg MYLOCALE menu "Locale" "$_locale" $LOCALES || { i=1; continue; } ;;
461 until [[ $ZONE && $SUBZ ]]; do
462 dlg ZONE menu "Timezone" "$_timez" America - Australia - Asia - Atlantic - Africa - Europe - Indian - Pacific - Arctic - Antarctica - || break
463 dlg SUBZ menu "Timezone" "$_timesubz" $(awk '/'"$ZONE"'\// {gsub(/'"$ZONE"'\//, ""); print $3 " - "}' /usr/share/zoneinfo/zone.tab | sort) || continue
464 yesno "Timezone" "\nConfirm time zone: $ZONE/$SUBZ\n" || unset ZONE
466 [[ $ZONE && $SUBZ ]] || { i=2; continue; } ;;
468 dlg KERNEL menu "Kernel" "\nChoose which kernel to use." \
469 linux 'Vanilla linux kernel and modules, with a few patches applied' \
470 linux-lts 'Long-term support (LTS) linux kernel and modules' \
471 linux-zen 'A effort of kernel hackers to provide the best kernel for everyday systems' \
472 linux-hardened 'A security-focused linux kernel with hardening patches to mitigate exploits' || { i=3; continue; }
477 (( i++ )) # progress through to the next choice
481 '/bin/bash') LOGINRC='.bash_profile' ;;
482 '/usr/bin/zsh') LOGINRC='.zprofile' ;;
483 '/usr/bin/mksh') LOGINRC='.profile' ;;
492 local v='' u='' p='' p2='' rp='' rp2=''
494 until [[ $NEWUSER ]]; do
497 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " User " --mixedform "$_user" 0 0 0 \
498 "Username:" 1 1 "$u" 1 11 "$COLUMNS" 0 0 \
499 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
500 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 \
501 "--- Root password, if left empty the user password will be used ---" 6 1 '' 6 68 "$COLUMNS" 0 2 \
502 "Password:" 8 1 '' 8 11 "$COLUMNS" 0 1 \
503 "Password2:" 9 1 '' 9 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
505 while read -r line; do
516 # root passwords empty, so use the user passwords
517 [[ -z $rp && -z $rp2 ]] && { rp="$p"; rp2="$p2"; }
519 # make sure a username was entered and that the passwords match
520 if [[ ${#u} -eq 0 || $u =~ \ |\' || $u =~ [^a-z0-9] ]]; then
521 msg "Invalid Username" "\nIncorrect user name.\n\nPlease try again.\n"; u=''
522 elif [[ -z $p ]]; then
523 msg "Empty Password" "\nThe user password cannot be left empty.\n\nPlease try again.\n"
524 elif [[ "$p" != "$p2" ]]; then
525 msg "Password Mismatch" "\nThe user passwords do not match.\n\nPlease try again.\n"
526 elif [[ "$rp" != "$rp2" ]]; then
527 msg "Password Mismatch" "\nThe root passwords do not match.\n\nPlease try again.\n"
539 dlg KEYMAP menu "Keyboard Layout" "$_keymap" \
540 us English cm English gb English au English gh English \
541 za English ng English ca French 'cd' French gn French \
542 tg French fr French de German at German ch German \
543 es Spanish latam Spanish br Portuguese pt Portuguese ma Arabic \
544 sy Arabic ara Arabic ua Ukrainian cz Czech ru Russian \
545 sk Slovak nl Dutch it Italian hu Hungarian cn Chinese \
546 tw Taiwanese vn Vietnamese kr Korean jp Japanese th Thai \
547 la Lao pl Polish se Swedish is Icelandic 'fi' Finnish \
548 dk Danish be Belgian in Indian al Albanian am Armenian \
549 bd Bangla ba Bosnian 'bg' Bulgarian dz Berber mm Burmese \
550 hr Croatian gr Greek il Hebrew ir Persian iq Iraqi \
551 af Afghani fo Faroese ge Georgian ee Estonian kg Kyrgyz \
552 kz Kazakh lt Lithuanian mt Maltese mn Mongolian ro Romanian \
553 no Norwegian rs Serbian si Slovenian tj Tajik lk Sinhala \
554 tr Turkish uz Uzbek ie Irish pk Urdu 'mv' Dhivehi \
555 np Nepali et Amharic sn Wolof ml Bambara tz Swahili \
556 ke Swahili bw Tswana ph Filipino my Malay tm Turkmen \
557 id Indonesian bt Dzongkha lv Latvian md Moldavian mao Maori \
558 by Belarusian az Azerbaijani mk Macedonian kh Khmer epo Esperanto \
559 me Montenegrin || return 1
561 if [[ $CMAPS == *"$KEYMAP"* ]]; then
564 dlg CMAP menu "Console Keymap" "$_vconsole" $CMAPS || return 1
567 if [[ $DISPLAY && $TERM != 'linux' ]]; then
568 setxkbmap "$KEYMAP" >/dev/null 2>&1
570 loadkeys "$CMAP" >/dev/null 2>&1
580 dlg INSTALL_WMS check "Sessions" "$_sessions\n" \
581 i3-gaps "A fork of i3wm with more features including gaps" "$(ofn i3-gaps "${INSTALL_WMS[*]}")" \
582 openbox "A lightweight, powerful, and highly configurable stacking wm" "$(ofn openbox "${INSTALL_WMS[*]}")" \
583 awesome "A customized Awesome WM session created by @elanapan" "$(ofn awesome "${INSTALL_WMS[*]}")" \
584 dwm "A dynamic WM for X that manages windows in tiled, floating, or monocle layouts" "$(ofn dwm "${INSTALL_WMS[*]}")" \
585 bspwm "A tiling wm that represents windows as the leaves of a binary tree" "$(ofn bspwm "${INSTALL_WMS[*]}")" \
586 fluxbox "A lightweight and highly-configurable window manager" "$(ofn fluxbox "${INSTALL_WMS[*]}")" \
587 gnome "A desktop environment that aims to be simple and easy to use" "$(ofn gnome "${INSTALL_WMS[*]}")" \
588 cinnamon "A desktop environment combining traditional desktop with modern effects" "$(ofn cinnamon "${INSTALL_WMS[*]}")" \
589 plasma "A kde software project currently comprising a full desktop environment" "$(ofn plasma "${INSTALL_WMS[*]}")" \
590 xfce4 "A lightweight and modular desktop environment based on gtk+2/3" "$(ofn xfce4 "${INSTALL_WMS[*]}")" || return 1
593 while IFS=' ' read -r i; do
595 done <<< "$INSTALL_WMS"
598 WM_PKGS="${INSTALL_WMS/dwm/}" # remove dwm from package list
599 WM_PKGS="${WM_PKGS// / }" # remove double spaces
600 WM_PKGS="${WM_PKGS# }" # remove leading space
602 # add archlabs base when choosing any session
603 [[ $WM_PKGS ]] && WM_PKGS+=" $AL_BASE_PKGS"
605 for i in $INSTALL_WMS; do
606 LOGIN_CHOICES+="$i - "
607 [[ ${WM_EXT[$i]} && $WM_PKGS != *"${WM_EXT[$i]}"* ]] && WM_PKGS+=" ${WM_EXT[$i]}"
610 select_login || return 1
611 [[ $WM_PKGS != *"$LOGIN_PKGS"* ]] && WM_PKGS+=" $LOGIN_PKGS"
613 while IFS=' ' read -r pkg; do
614 [[ $PACKAGES != *"$pkg"* ]] && PACKAGES+=" $pkg"
622 dlg USER_PKGS check " Packages " "$_packages" \
623 abiword "A Fully-featured word processor" "$(ofn abiword "${USER_PKGS[*]}")" \
624 alacritty "A cross-platform, GPU-accelerated terminal emulator" "$(ofn alacritty "${USER_PKGS[*]}")" \
625 atom "An open-source text editor developed by GitHub" "$(ofn atom "${USER_PKGS[*]}")" \
626 audacious "A free and advanced audio player based on GTK+" "$(ofn audacious "${USER_PKGS[*]}")" \
627 audacity "A program that lets you manipulate digital audio waveforms" "$(ofn audacity "${USER_PKGS[*]}")" \
628 cairo-dock "Light eye-candy fully themable animated dock" "$(ofn cairo-dock "${USER_PKGS[*]}")" \
629 calligra "A set of applications for productivity" "$(ofn calligra "${USER_PKGS[*]}")" \
630 chromium "An open-source web browser based on the Blink rendering engine" "$(ofn chromium "${USER_PKGS[*]}")" \
631 clementine "A modern music player and library organizer" "$(ofn clementine "${USER_PKGS[*]}")" \
632 cmus "A small, fast and powerful console music player" "$(ofn cmus "${USER_PKGS[*]}")" \
633 deadbeef "A GTK+ audio player for GNU/Linux" "$(ofn deadbeef "${USER_PKGS[*]}")" \
634 deluge "A BitTorrent client written in python" "$(ofn deluge "${USER_PKGS[*]}")" \
635 docky "Full fledged dock for opening applications and managing windows" "$(ofn docky "${USER_PKGS[*]}")" \
636 emacs "An extensible, customizable, self-documenting real-time display editor" "$(ofn emacs "${USER_PKGS[*]}")" \
637 epiphany "A GNOME web browser based on the WebKit rendering engine" "$(ofn epiphany "${USER_PKGS[*]}")" \
638 evince "A document viewer" "$(ofn evince "${USER_PKGS[*]}")" \
639 evolution "Manage your email, contacts and schedule" "$(ofn evolution "${USER_PKGS[*]}")" \
640 file-roller "Create and modify archives" "$(ofn file-roller "${USER_PKGS[*]}")" \
641 firefox "A popular open-source web browser from Mozilla" "$(ofn firefox "${USER_PKGS[*]}")" \
642 gcolor2 "A simple GTK+2 color selector" "$(ofn gcolor2 "${USER_PKGS[*]}")" \
643 geany "A fast and lightweight IDE" "$(ofn geany "${USER_PKGS[*]}")" \
644 geary "A lightweight email client for the GNOME desktop" "$(ofn geary "${USER_PKGS[*]}")" \
645 gimp "GNU Image Manipulation Program" "$(ofn gimp "${USER_PKGS[*]}")" \
646 gnome-disk-utility "Disk Management Utility" "$(ofn gnome-disk-utility "${USER_PKGS[*]}")" \
647 gnome-system-monitor "View current processes and monitor system state" "$(ofn gnome-system-monitor "${USER_PKGS[*]}")" \
648 gparted "A GUI frontend for creating and manipulating partition tables" "$(ofn gparted "${USER_PKGS[*]}")" \
649 gpick "Advanced color picker using GTK+ toolkit" "$(ofn gpick "${USER_PKGS[*]}")" \
650 gpicview "Lightweight image viewer" "$(ofn gpicview "${USER_PKGS[*]}")" \
651 guvcview "Capture video from camera devices" "$(ofn guvcview "${USER_PKGS[*]}")" \
652 hexchat "A popular and easy to use graphical IRC client" "$(ofn hexchat "${USER_PKGS[*]}")" \
653 inkscape "Professional vector graphics editor" "$(ofn inkscape "${USER_PKGS[*]}")" \
654 irssi "Modular text mode IRC client" "$(ofn irssi "${USER_PKGS[*]}")" \
655 kdenlive "A popular non-linear video editor for Linux" "$(ofn kdenlive "${USER_PKGS[*]}")" \
656 krita "Edit and paint images" "$(ofn krita "${USER_PKGS[*]}")" \
657 libreoffice-fresh "Full featured office suite" "$(ofn libreoffice-fresh "${USER_PKGS[*]}")" \
658 lollypop "A new music playing application" "$(ofn lollypop "${USER_PKGS[*]}")" \
659 mousepad "A simple text editor" "$(ofn mousepad "${USER_PKGS[*]}")" \
660 mpd "A flexible, powerful, server-side application for playing music" "$(ofn mpd "${USER_PKGS[*]}")" \
661 mpv "A media player based on mplayer" "$(ofn mpv "${USER_PKGS[*]}")" \
662 mupdf "Lightweight PDF and XPS viewer" "$(ofn mupdf "${USER_PKGS[*]}")" \
663 mutt "Small but very powerful text-based mail client" "$(ofn mutt "${USER_PKGS[*]}")" \
664 nautilus "The default file manager for Gnome" "$(ofn nautilus "${USER_PKGS[*]}")" \
665 ncmpcpp "A mpd client and almost exact clone of ncmpc with some new features" "$(ofn ncmpcpp "${USER_PKGS[*]}")" \
666 neovim "A fork of Vim aiming to improve user experience, plugins, and GUIs." "$(ofn neovim "${USER_PKGS[*]}")" \
667 nicotine+ "A graphical client for Soulseek" "$(ofn nicotine+ "${USER_PKGS[*]}")" \
668 noto-fonts "Google Noto fonts" "$(ofn noto-fonts "${USER_PKGS[*]}")" \
669 noto-fonts-cjk "Google Noto CJK fonts (Chinese, Japanese, Korean)" "$(ofn noto-fonts-cjk "${USER_PKGS[*]}")" \
670 obs-studio "Free opensource streaming/recording software" "$(ofn obs-studio "${USER_PKGS[*]}")" \
671 openshot "An open-source, non-linear video editor for Linux" "$(ofn openshot "${USER_PKGS[*]}")" \
672 opera "A Fast and secure, free of charge web browser from Opera Software" "$(ofn opera "${USER_PKGS[*]}")" \
673 pcmanfm "A fast and lightweight file manager based in Lxde" "$(ofn pcmanfm "${USER_PKGS[*]}")" \
674 pidgin "Multi-protocol instant messaging client" "$(ofn pidgin "${USER_PKGS[*]}")" \
675 plank "An elegant, simple, and clean dock" "$(ofn plank "${USER_PKGS[*]}")" \
676 qbittorrent "An advanced BitTorrent client" "$(ofn qbittorrent "${USER_PKGS[*]}")" \
677 qpdfview "A tabbed PDF viewer" "$(ofn qpdfview "${USER_PKGS[*]}")" \
678 qt5ct "GUI for managing Qt based application themes, icons, and fonts" "$(ofn qt5ct "${USER_PKGS[*]}")" \
679 qutebrowser "A keyboard-focused vim-like web browser based on Python and PyQt5" "$(ofn qutebrowser "${USER_PKGS[*]}")" \
680 rhythmbox "A Music playback and management application" "$(ofn rhythmbox "${USER_PKGS[*]}")" \
681 rxvt-unicode "A unicode enabled rxvt-clone terminal emulator" "$(ofn rxvt-unicode "${USER_PKGS[*]}")" \
682 sakura "A terminal emulator based on GTK and VTE" "$(ofn sakura "${USER_PKGS[*]}")" \
683 simplescreenrecorder "A feature-rich screen recorder" "$(ofn simplescreenrecorder "${USER_PKGS[*]}")" \
684 steam "A popular game distribution platform by Valve" "$(ofn steam "${USER_PKGS[*]}")" \
685 surf "A simple web browser based on WebKit2/GTK+" "$(ofn surf "${USER_PKGS[*]}")" \
686 terminator "Terminal emulator that supports tabs and grids" "$(ofn terminator "${USER_PKGS[*]}")" \
687 termite "A minimal VTE-based terminal emulator" "$(ofn termite "${USER_PKGS[*]}")" \
688 thunar "A modern file manager for the Xfce Desktop Environment" "$(ofn thunar "${USER_PKGS[*]}")" \
689 thunderbird "Standalone mail and news reader from mozilla" "$(ofn thunderbird "${USER_PKGS[*]}")" \
690 tilda "A GTK based drop down terminal for Linux and Unix" "$(ofn tilda "${USER_PKGS[*]}")" \
691 tilix "A tiling terminal emulator for Linux using GTK+ 3" "$(ofn tilix "${USER_PKGS[*]}")" \
692 transmission-cli "Free BitTorrent client CLI" "$(ofn transmission-cli "${USER_PKGS[*]}")" \
693 transmission-gtk "Free BitTorrent client GTK+ GUI" "$(ofn transmission-gtk "${USER_PKGS[*]}")" \
694 transmission-qt "Free BitTorrent client Qt GUI" "$(ofn transmission-qt "${USER_PKGS[*]}")" \
695 ttf-anonymous-pro "A family fixed-width fonts designed with code in mind" "$(ofn ttf-anonymous-pro "${USER_PKGS[*]}")" \
696 ttf-fira-code "Monospaced font with programming ligatures" "$(ofn ttf-fira-code "${USER_PKGS[*]}")" \
697 ttf-font-awesome "Iconic font designed for Bootstrap" "$(ofn ttf-font-awesome "${USER_PKGS[*]}")" \
698 ttf-hack "A hand groomed typeface based on Bitstream Vera Mono" "$(ofn ttf-hack "${USER_PKGS[*]}")" \
699 vlc "A free and open source cross-platform multimedia player" "$(ofn vlc "${USER_PKGS[*]}")" \
700 weechat "Fast, light and extensible IRC client" "$(ofn weechat "${USER_PKGS[*]}")" \
701 xarchiver "A GTK+ frontend to various command line archivers" "$(ofn xarchiver "${USER_PKGS[*]}")" \
702 xfce-terminal "A terminal emulator based in the Xfce Desktop Environment" "$(ofn xfce-terminal "${USER_PKGS[*]}")" \
703 xterm "The standard terminal emulator for the X window system" "$(ofn xterm "${USER_PKGS[*]}")" \
704 zathura "Minimalistic document viewer" "$(ofn zathura "${USER_PKGS[*]}")"
706 if [[ $USER_PKGS ]]; then
707 for i in $USER_PKGS; do
708 [[ ${PKG_EXT[$i]} && $USER_PKGS != *"${PKG_EXT[$i]}"* ]] && USER_PKGS+=" ${PKG_EXT[$i]}"
715 ###############################################################################
720 is_bg_install || return 0
721 local device choice devhash
722 devhash="$(lsblk -f | base64)"
724 part_device || return 1
729 if [[ $DISPLAY && $TERM != 'linux' ]] && hash gparted >/dev/null 2>&1; then
730 dlg choice menu "Edit Partitions" "$_part" \
731 "auto" "Whole device automatic partitioning" \
732 "shrink" "Shrink an existing ext2/3/4 or ntfs partition to make room for a new partition" \
733 "gparted" "GUI front end to parted" \
734 "cfdisk" "Curses based variant of fdisk" \
735 "parted" "GNU partition editor" \
736 "fdisk" "Dialog-driven creation and manipulation of partitions" \
737 "done" "Return to the main menu" || return 0
739 dlg choice menu "Edit Partitions" "$_part" \
740 "auto" "Whole device automatic partitioning" \
741 "shrink" "Shrink an existing ext2/3/4 or ntfs partition to make room for a new partition" \
742 "cfdisk" "Curses based variant of fdisk" \
743 "parted" "GNU partition editor" \
744 "fdisk" "Dialog-driven creation and manipulation of partitions" \
745 "done" "Return to the main menu" || return 0
748 if [[ $choice == 'done' ]]; then
750 elif [[ $choice == 'shrink' ]]; then
751 part_shrink "$device"
752 elif [[ $choice == 'auto' ]]; then
753 local root_size txt table boot_fs
754 root_size=$(lsblk -lno SIZE "$device" | awk 'NR == 1 {
757 print ($1 * 1000 - 512) / 1000 "G"
763 txt="\nWARNING:\n\nALL data on $device will be destroyed and the following partitions will be created\n\n- "
764 if [[ $SYS == 'BIOS' ]]; then
765 table="msdos" boot_fs="ext4"
766 txt+="An $boot_fs boot partition with the boot flag enabled (512M)\n- "
768 table="gpt" boot_fs="fat32"
769 txt+="A $boot_fs efi boot partition (512M)\n- "
771 txt+="An ext4 partition using all remaining space ($root_size)\n\nDo you want to continue?\n"
772 yesno "Auto Partition" "$txt" && part_auto "$device" "$table" "$boot_fs" "$root_size"
778 if [[ $devhash != "$(lsblk -f | base64)" ]]; then
779 msg "Probing Partitions" "\nInforming the kernel of partition changes using partprobe.\n" 0
780 partprobe >/dev/null 2>&1
788 if [[ $IGNORE_DEV ]]; then
789 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk "!/$IGNORE_DEV/"' && /disk|part|lvm|crypt|NAME/')"
791 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk '/disk|part|lvm|crypt|NAME/')"
793 msg "Device Tree" "\n\n$txt\n\n"
798 if [[ $1 == "$MNT/swapfile" && $SWAP_SIZE ]]; then
799 fallocate -l $SWAP_SIZE "$1" 2>$ERR
800 errshow "fallocate -l $SWAP_SIZE $1"
801 chmod 600 "$1" 2>$ERR
802 errshow "chmod 600 $1"
804 mkswap "$1" >/dev/null 2>$ERR
806 swapon "$1" >/dev/null 2>$ERR
813 local device="$1" table="$2" boot_fs="$3" size="$4" dev_info=""
814 dev_info="$(parted -s "$device" print)"
816 msg "Auto Partition" "\nRemoving partitions on $device and setting table to $table\n" 1
819 while read -r PART; do
820 parted -s "$device" rm "$PART" >/dev/null 2>&1
821 done <<< "$(awk '/^ [1-9][0-9]?/ {print $1}' <<< "$dev_info" | sort -r)"
823 [[ $(awk '/Table:/ {print $3}' <<< "$dev_info") != "$table" ]] && parted -s "$device" mklabel "$table" >/dev/null 2>&1
825 msg "Auto Partition" "\nCreating a 512M $boot_fs boot partition.\n" 1
826 if [[ $SYS == "BIOS" ]]; then
827 parted -s "$device" mkpart primary "$boot_fs" 1MiB 513MiB >/dev/null 2>&1
829 parted -s "$device" mkpart ESP "$boot_fs" 1MiB 513MiB >/dev/null 2>&1
834 AUTO_BOOT_PART=$(lsblk -lno NAME,TYPE "$device" | awk 'NR==2 {print "/dev/" $1}')
836 if [[ $SYS == "BIOS" ]]; then
837 mkfs.ext4 -q "$AUTO_BOOT_PART" >/dev/null 2>&1
839 mkfs.vfat -F32 "$AUTO_BOOT_PART" >/dev/null 2>&1
842 msg "Auto Partition" "\nCreating a $size ext4 root partition.\n" 0
843 parted -s "$device" mkpart primary ext4 513MiB 100% >/dev/null 2>&1
845 AUTO_ROOT_PART="$(lsblk -lno NAME,TYPE "$device" | awk 'NR==3 {print "/dev/" $1}')"
846 mkfs.ext4 -q "$AUTO_ROOT_PART" >/dev/null 2>&1
848 FORMATTED+="$AUTO_BOOT_PART $AUTO_ROOT_PART "
849 msg "Auto Partition" "\nProcess complete.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$device")\n"
854 local regexp="$1" err=''
856 # string of partitions as /TYPE/PART SIZE
857 if [[ $IGNORE_DEV ]]; then
858 PARTS="$(lsblk -lno TYPE,NAME,SIZE |
859 awk "/$regexp/"' && !'"/$IGNORE_DEV/"' {
860 sub(/^part/, "/dev/")
861 sub(/^lvm|^crypt/, "/dev/mapper/")
865 PARTS="$(lsblk -lno TYPE,NAME,SIZE |
867 sub(/^part/, "/dev/")
868 sub(/^lvm|^crypt/, "/dev/mapper/")
873 # number of partitions total
875 while read -r line; do
879 # ensure we have enough partitions for the system and action type
881 'part|lvm|crypt') [[ $COUNT -lt 1 || ($SYS == 'UEFI' && $COUNT -lt 2) ]] && err="$_errpart" ;;
882 'part|crypt') (( COUNT < 1 )) && err="$_lvmerr" ;;
883 'part|lvm') (( COUNT < 2 )) && err="$_lukserr" ;;
886 # if there aren't enough partitions show the relevant error message
887 [[ $err ]] && { msg "Not Enough Partitions" "$err" 2; return 1; }
894 local part="$1" mountp="${MNT}$2" fs=""
895 fs="$(lsblk -lno FSTYPE "$part")"
898 if [[ $fs && ${FS_OPTS[$fs]} && $part != "$BOOT_PART" ]] && select_mntopts "$fs"; then
899 mount -o "$MNT_OPTS" "$part" "$mountp" >/dev/null 2>&1
901 mount "$part" "$mountp" >/dev/null 2>&1
904 part_mountconf "$part" "$mountp" || return 1
912 local part="$1" fs="$2" delay="$3"
914 msg "Format" "\nFormatting $part as $fs\n" 0
915 ${FS_CMDS[$fs]} "$part" >/dev/null 2>$ERR
916 errshow "${FS_CMDS[$fs]} $part" || return 1
925 local device="$1" fs=""
927 part_find "${device##*/}[^ ]" || return 1
928 (( COUNT == 1 )) && part="$(awk '{print $1}' <<< "${PARTS[@]}" )"
930 if (( COUNT == 1 )) || dlg part menu "Resize" "\nWhich partition on $device do you want to resize?" $PARTS; then
931 fs=$(lsblk -lno FSTYPE "$part")
934 msg "Resize" "\nGathering device size info.\n" 0
936 end=$(parted -s "$device" unit KiB print | awk '/^\s*'"$num"'/ {print $3}') # part size in KiB
937 devsize=$(parted -s "$device" unit KiB print | awk '/Disk '"${device//\//\\/}"':/ {print $3}') # whole device size in KiB
938 mount "$part" $MNT >/dev/null 2>&1; sleep 0.5
939 min=$(df --output=used --block-size=MiB "$part" | awk 'NR == 2 {print int($1) + 256}')
940 max=$(df --output=avail --block-size=MiB "$part" | awk 'NR == 2 {print int($1)}')
943 if dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Resize: $part " --rangebox "$_resize" 17 "$COLUMNS" "$min" "$max" $((max / 2)) 2>$ANS; then
945 size=$((size * 1024))
952 if ntfsresize -fc "$part"; then
953 ntfsresize -ff --size $(( (size * 1024) / 1000 ))k "$part" 2>$ERR # k=10^3 bytes
954 errshow "ntfsresize -f -s $(( (size * 1024) / 1000 ))k $part" || return 1
956 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"
961 e2fsck -f "$part"; sleep 0.5
962 resize2fs -f "$part" ${size}K 2>$ERR # K=2^10 bytes
963 errshow "resize2fs -f $part ${size}K" || return 1
967 parted "$device" resizepart "$num" ${size}KiB || return 1
970 if [[ $devsize == "$end" ]]; then
971 parted -s "$device" mkpart primary ext4 ${size}KiB 100% 2>$ERR
972 errshow "parted -s $device mkpart primary ext4 ${size}KiB 100%" || return 1
974 parted -s "$device" mkpart primary ext4 ${size}KiB ${end}KiB 2>$ERR
975 errshow "parted -s $device mkpart primary ext4 ${size}KiB ${end}KiB" || return 1
977 msg "Resize Complete" "\n$part has been successfully resized to $((size / 1024))M.\n" 1
979 "") msg "No Filesystem" "\nFor unformatted partitions, cfdisk can be used in the partition menu.\n" ;;
980 *) msg "Invalid Filesystem: $fs" "\nResizing only supports ext and ntfs.\n" ;;
987 if [[ $DEV_COUNT -eq 1 && $SYS_DEVS ]]; then
988 DEVICE="$(awk '{print $1}' <<< "$SYS_DEVS")"
989 elif (( DEV_COUNT > 1 )); then
991 dlg DEVICE menu "Boot Device" "\nSelect the device to use for bootloader install." $SYS_DEVS
993 dlg DEVICE menu "Select Device" "$_device" $SYS_DEVS
995 [[ $DEVICE ]] || return 1
996 elif [[ $DEV_COUNT -lt 1 && ! $1 ]]; then
997 msg "Device Error" "\nNo available devices.\n\nExiting..\n" 2; die 1
1000 [[ $1 ]] && BOOT_DEV="$DEVICE"
1007 BOOT_DEV="${BOOT_PART%[1-9]}"
1008 BOOT_PART_NUM="${BOOT_PART: -1}"
1009 [[ $BOOT_PART = /dev/nvme* ]] && BOOT_DEV="${BOOT_PART%p[1-9]}"
1010 if [[ $SYS == 'UEFI' ]]; then
1011 parted -s $BOOT_DEV set $BOOT_PART_NUM esp on >/dev/null 2>&1
1013 parted -s $BOOT_DEV set $BOOT_PART_NUM boot on >/dev/null 2>&1
1020 local part="$1" devs=""
1021 devs="$(lsblk -lno NAME,FSTYPE,TYPE)"
1023 # Identify if $part is LUKS+LVM, LVM+LUKS, LVM alone, or LUKS alone
1024 if lsblk -lno TYPE "$part" | grep -q 'crypt'; then
1026 LUKS_NAME="${part#/dev/mapper/}"
1028 for dev in $(awk '/lvm/ && /crypto_LUKS/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
1029 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1030 LUKS_DEV="$LUKS_DEV cryptdevice=$dev:$LUKS_NAME"
1031 LVM='logical volume'
1036 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
1037 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1038 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
1039 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
1044 elif lsblk -lno TYPE "$part" | grep -q 'lvm'; then
1045 LVM='logical volume'
1046 VNAME="${part#/dev/mapper/}"
1048 for dev in $(awk '/crypt/ && /lvm2_member/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
1049 if lsblk -lno NAME "$dev" | grep -q "$VNAME"; then
1050 LUKS_NAME="${dev/\/dev\/mapper\//}"
1055 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
1056 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1057 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
1058 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
1069 if (( COUNT > 0 )); then
1070 PARTS="$(sed "/${i//\//\\/}/d" <<< "$PARTS")"
1078 if grep -qw "$1" /proc/mounts; then
1079 msg "Mount Success" "\nPartition $1 mounted at $2\n" 1
1083 msg "Mount Fail" "\nPartition $1 failed to mount at $2\n" 2
1088 ###############################################################################
1093 is_bg_install || return 0
1096 part_find 'part|lvm|crypt' || { SEL=2; return 1; }
1098 [[ $LUKS && $LUKS_PART ]] && part_countdec $LUKS_PART
1099 [[ $LVM && $LVM_PARTS ]] && part_countdec $LVM_PARTS
1101 select_root_partition || return 1
1103 if [[ $SYS == 'UEFI' ]]; then
1104 select_efi_partition || { BOOT_PART=''; return 1; }
1105 elif (( COUNT > 0 )); then
1106 select_boot_partition || { BOOT_PART=''; return 1; }
1109 if [[ $BOOT_PART ]]; then
1110 part_mount "$BOOT_PART" "/$BOOTDIR" && SEP_BOOT=true || return 1
1114 select_swap || return 1
1115 select_extra_partitions || return 1
1116 install_background || return 1
1123 dlg SWAP_PART menu "Swap Setup" "\nSelect whether to use a swapfile, swap partition, or none." \
1124 "none" "Don't allocate any swap space" \
1125 "swapfile" "Allocate $SYS_MEM at /swapfile" \
1128 if [[ -z $SWAP_PART || $SWAP_PART == "none" ]]; then
1131 elif [[ $SWAP_PART == "swapfile" ]]; then
1133 until [[ ${SWAP_SIZE:0:1} =~ [1-9] && ${SWAP_SIZE: -1} =~ (M|G) ]]; do
1134 (( 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
1135 dlg SWAP_SIZE input "Swap Setup" "$_swapsize" "$SYS_MEM" || { SWAP_PART=''; SWAP_SIZE=''; return 1; }
1138 part_swap "$MNT/$SWAP_PART"
1139 SWAP_PART="/$SWAP_PART"
1140 elif [[ $PARTS == *"$SWAP_PART"* ]]; then
1141 part_swap $SWAP_PART
1142 part_countdec $SWAP_PART
1143 SWAP_SIZE="$(lsblk -lno SIZE $SWAP_PART)"
1153 local fs="$1" opts=''
1154 local title="${fs^} Mount Options"
1156 for i in ${FS_OPTS[$fs]}; do
1160 until [[ $MNT_OPTS ]]; do
1161 dlg MNT_OPTS check "$title" "$_mount" $opts
1162 [[ $MNT_OPTS ]] || return 1
1163 MNT_OPTS="${MNT_OPTS// /,}"
1164 yesno "$title" "\nConfirm the following options: $MNT_OPTS\n" || MNT_OPTS=''
1173 until [[ $EXMNT ]]; do
1174 dlg EXMNT input "Extra Mount $part" "$_exmnt" "/" || return 1
1175 if [[ ${EXMNT:0:1} != "/" || ${#EXMNT} -le 1 || $EXMNT =~ \ |\' || $EXMNTS == *"$EXMNT"* ]]; then
1176 msg "Mountpoint Error" "$_errexpart"
1185 local part="$1" fs='' cur=''
1186 local txt="\nSelect which filesystem to use for: $part\n\nDefault: ext4"
1187 cur="$(lsblk -lno FSTYPE "$part" 2>/dev/null)"
1190 if [[ $cur && ($part != "$ROOT_PART" || $FORMATTED == *"$part"*) ]]; then
1191 dlg fs menu "Filesystem" "$txt\nCurrent: $cur" skip - ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1193 dlg fs menu "Filesystem" "$txt" ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1195 [[ $fs == 'skip' ]] && return 0
1196 yesno "Filesystem" "\nFormat $part as $fs?\n" || fs=''
1198 part_format "$part" "$fs"
1201 select_efi_partition()
1203 if (( COUNT == 1 )); then
1204 BOOT_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
1205 elif [[ $AUTO_BOOT_PART ]]; then
1206 BOOT_PART="$AUTO_BOOT_PART"
1207 return 0 # were done here
1209 dlg BOOT_PART menu "EFI Partition" "$_uefi" $PARTS
1212 [[ $BOOT_PART ]] || return 1
1214 if grep -q 'fat' <<< "$(fsck -N "$BOOT_PART")"; then
1215 local txt="\nIMPORTANT:\n\nThe EFI partition $BOOT_PART $_format"
1216 if yesno "Format EFI Partition" "$txt" "Format $BOOT_PART" "Skip Formatting" 1; then
1217 part_format "$BOOT_PART" "vfat" 2
1220 part_format "$BOOT_PART" "vfat" 2
1226 select_boot_partition()
1228 if [[ $AUTO_BOOT_PART && ! $LVM ]]; then
1229 BOOT_PART="$AUTO_BOOT_PART"; return 0 # were done here
1230 elif [[ $LUKS && ! $LVM ]]; then
1231 dlg BOOT_PART menu "Boot Partition" "$_biosluks" $PARTS
1232 [[ $BOOT_PART ]] || return 1
1234 dlg BOOT_PART menu "Boot Partition" "$_bios" "skip" "don't use a separate boot" $PARTS
1235 [[ -z $BOOT_PART || $BOOT_PART == "skip" ]] && { BOOT_PART=''; return 0; }
1238 if grep -q 'ext[34]' <<< "$(fsck -N "$BOOT_PART")"; then
1239 local txt="\nIMPORTANT:\n\nThe boot partition $BOOT_PART $_format"
1240 if yesno "Format Boot Partition" "$txt" "Format $BOOT_PART" "Skip Formatting" 1; then
1241 part_format "$BOOT_PART" "ext4" 2
1244 part_format "$BOOT_PART" "ext4" 2
1249 select_root_partition()
1251 if [[ $AUTO_ROOT_PART && -z $LVM && -z $LUKS ]]; then
1252 ROOT_PART="$AUTO_ROOT_PART"
1253 elif (( COUNT == 1 )); then
1254 ROOT_PART="$(awk 'NR==1 {print $1}' <<< "$PARTS")"
1256 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
1258 [[ $ROOT_PART ]] || return 1
1260 select_filesystem "$ROOT_PART" || { ROOT_PART=''; return 1; }
1261 part_mount "$ROOT_PART" || { ROOT_PART=''; return 1; }
1266 select_extra_partitions()
1269 while (( COUNT > 0 )); do
1271 dlg part menu 'Mount Extra' "$_expart" 'done' 'finish mounting step' $PARTS || break
1272 if [[ $part == 'done' ]]; then
1274 elif select_filesystem "$part" && select_mountpoint && part_mount "$part" "$EXMNT"; then
1275 EXMNTS+="$part: $EXMNT "
1276 [[ $EXMNT == '/usr' && $HOOKS != *usr* ]] && HOOKS="usr $HOOKS"
1284 ###############################################################################
1292 genfstab -U $MNT >$MNT/etc/fstab 2>$ERR
1293 errshow 1 "genfstab -U $MNT >$MNT/etc/fstab"
1294 [[ -f $MNT/swapfile ]] && sed -i "s~${MNT}~~" $MNT/etc/fstab
1298 chrun "hwclock --systohc --utc" || chrun "hwclock --systohc --utc --directisa"
1301 chrun "chown -Rf $NEWUSER:users /home/$NEWUSER"
1305 dlg choice menu "Finalization" "$_edit" \
1306 finished "exit the installer and reboot" \
1307 keyboard "${EDIT_FILES[keyboard]}" \
1308 console "${EDIT_FILES[console]}" \
1309 locale "${EDIT_FILES[locale]}" \
1310 hostname "${EDIT_FILES[hostname]}" \
1311 sudoers "${EDIT_FILES[sudoers]}" \
1312 mkinitcpio "${EDIT_FILES[mkinitcpio]}" \
1313 fstab "${EDIT_FILES[fstab]}" \
1314 crypttab "${EDIT_FILES[crypttab]}" \
1315 bootloader "${EDIT_FILES[bootloader]}" \
1316 pacman "${EDIT_FILES[pacman]}" \
1317 login "${EDIT_FILES[login]}"
1319 if [[ -z $choice || $choice == 'finished' ]]; then
1320 [[ $DEBUG == true && -r $DBG ]] && vim $DBG
1324 for f in ${EDIT_FILES[$choice]}; do
1325 [[ -e ${MNT}$f ]] && exists+=" ${MNT}$f"
1327 if [[ $exists ]]; then
1330 msg "File Missing" "\nThe file(s) selected do not exist:\n\n${EDIT_FILES[$choice]}\n"
1338 if [[ $RSYNC_PID || $MIRROR_PID ]]; then
1340 printf "\nOne or more background install processes are still running, grabbing their output...\n"
1342 while kill -0 "$RSYNC_PID" 2>/dev/null || kill -0 "$MIRROR_PID" 2>/dev/null; do
1343 tail -n 1 /tmp/bg_out
1347 unset RSYNC_PID MIRROR_PID
1348 elif hash rsync >/dev/null 2>&1 && [[ -d /run/archiso/sfs/airootfs/etc/skel ]]; then
1349 rsync -ahv /run/archiso/sfs/airootfs/ $MNT/ 2>$ERR
1350 errshow 1 "rsync -ahv /run/archiso/sfs/airootfs/ $MNT/"
1351 install_mirrorlist "$MNT/etc/pacman.d/mirrorlist"
1352 chrun "pacman -Syyu --noconfirm && pacman -S $BASE_PKGS --needed --noconfirm"
1354 mkdir -p /etc/pacman.d/mirrorlist
1355 install_mirrorlist "/etc/pacman.d/mirrorlist"
1356 pacstrap "$MNT" base $ISO_BASE 2>$ERR
1357 errshow 1 "pacstrap $MNT base $KERNEL $ISO_BASE"
1358 mkdir -p "$MNT/etc/pacman.d/mirrorlist"
1359 cp -f /etc/pacman.d/mirrorlist "$MNT/etc/pacman.d/mirrorlist"
1360 chrun "pacman -Syyu --noconfirm && pacman -S $BASE_PKGS --needed --noconfirm"
1363 rm -rf $MNT/etc/mkinitcpio-archiso.conf
1364 find $MNT/usr/lib/initcpio -name 'archiso*' -type f -delete
1365 sed -i 's/volatile/auto/g' $MNT/etc/systemd/journald.conf
1366 find $MNT/boot -name '*-ucode.img' -delete
1369 find $MNT/etc/X11/xorg.conf.d/ -name '*.conf' -delete
1370 elif lspci | grep ' VGA ' | grep -q 'Intel'; then
1371 cat > $MNT/etc/X11/xorg.conf.d/20-intel.conf << EOF
1373 Identifier "Intel Graphics"
1375 Option "TearFree" "true"
1380 [[ -e /run/archiso/sfs/airootfs && $KERNEL == 'linux' ]] && cp -vf $RUN/x86_64/vmlinuz $MNT/boot/vmlinuz-linux
1382 cp -fv /etc/resolv.conf $MNT/etc/
1383 [[ -e /etc/NetworkManager/system-connections ]] && cp -rvf /etc/NetworkManager/system-connections $MNT/etc/NetworkManager/
1385 echo "LANG=$MYLOCALE" > $MNT/etc/locale.conf
1386 cp -f $MNT/etc/locale.conf $MNT/etc/default/locale
1387 sed -i "s/#en_US.UTF-8/en_US.UTF-8/g; s/#${MYLOCALE}/${MYLOCALE}/g" $MNT/etc/locale.gen
1389 chrun "ln -svf /usr/share/zoneinfo/$ZONE/$SUBZ /etc/localtime"
1391 if [[ $BROADCOM_WL ]]; then
1392 echo 'blacklist bcma' >> $MNT/etc/modprobe.d/blacklist.conf
1393 rm -f $MNT/etc/modprobe/
1396 cat > $MNT/etc/X11/xorg.conf.d/00-keyboard.conf << EOF
1397 # Use localectl(1) to instruct systemd-localed to update it.
1398 Section "InputClass"
1399 Identifier "system-keyboard"
1400 MatchIsKeyboard "on"
1401 Option "XkbLayout" "$KEYMAP"
1404 cat > $MNT/etc/default/keyboard << EOF
1405 # KEYBOARD CONFIGURATION FILE
1406 # Consult the keyboard(5) manual page.
1413 printf "KEYMAP=%s\nFONT=%s\n" "$CMAP" "$FONT" > $MNT/etc/vconsole.conf
1414 echo "$MYHOST" > $MNT/etc/hostname
1415 cat > $MNT/etc/hosts << EOF
1418 ::1 localhost ip6-localhost ip6-loopback
1419 ff02::1 ip6-allnodes
1420 ff02::2 ip6-allrouters
1426 if [[ $ROOT_PART == /dev/mapper* ]]; then
1427 ROOT_PART_ID="$ROOT_PART"
1429 local uuid_type="UUID"
1430 [[ $BOOTLDR =~ (systemd-boot|refind-efi|efistub) ]] && uuid_type="PARTUUID"
1431 ROOT_PART_ID="$uuid_type=$(blkid -s $uuid_type -o value $ROOT_PART)"
1434 if [[ $SYS == 'UEFI' ]]; then
1436 find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname "$DIST" -type d -delete
1438 find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname 'BOOT' -type d -delete
1442 chrun "${BCMDS[$BOOTLDR]}" 2>$ERR
1443 errshow 1 "${BCMDS[$BOOTLDR]}"
1445 if [[ -d $MNT/hostrun ]]; then
1446 # cleanup the bind mounts we made earlier for the grub-probe module
1447 umount_dir $MNT/hostrun/{udev,lvm}
1448 rm -rf $MNT/hostrun >/dev/null 2>&1
1451 if [[ $SYS == 'UEFI' ]]; then
1452 # some UEFI firmware requires a generic esp/BOOT/BOOTX64.EFI
1453 mkdir -pv $MNT/$BOOTDIR/EFI/BOOT
1454 if [[ $BOOTLDR == 'grub' ]]; then
1455 cp -fv $MNT/$BOOTDIR/EFI/$DIST/grubx64.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI
1456 elif [[ $BOOTLDR == 'syslinux' ]]; then
1457 cp -rf $MNT/$BOOTDIR/EFI/syslinux/* $MNT/$BOOTDIR/EFI/BOOT/
1458 cp -f $MNT/$BOOTDIR/EFI/syslinux/syslinux.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI
1459 elif [[ $BOOTLDR == 'refind-efi' ]]; then
1460 sed -i '/#extra_kernel_version_strings/ c extra_kernel_version_strings linux-hardened,linux-zen,linux-lts,linux' $MNT/$BOOTDIR/EFI/refind/refind.conf
1461 cp -fv $MNT/$BOOTDIR/EFI/refind/refind_x64.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI
1470 chrun "chpasswd <<< 'root:$ROOT_PASS'" 2>$ERR
1471 errshow 1 "set root password"
1472 if [[ $MYSHELL != "/usr/bin/zsh" ]]; then
1473 # root uses zsh by default, change it if something else was chosen
1474 chrun "usermod -s $MYSHELL root" 2>$ERR
1475 errshow 1 "usermod -s $MYSHELL root"
1476 cp -fv $MNT/etc/skel/.mkshrc $MNT/root/.mkshrc
1479 local groups='audio,autologin,floppy,log,network,rfkill,scanner,storage,optical,power,wheel'
1481 chrun "groupadd -r autologin" 2>$ERR
1482 errshow 1 "groupadd -r autologin"
1483 chrun "useradd -m -u 1000 -g users -G $groups -s $MYSHELL $NEWUSER" 2>$ERR
1484 errshow 1 "useradd -m -u 1000 -g users -G $groups -s $MYSHELL $NEWUSER"
1485 chrun "chpasswd <<< '$NEWUSER:$USER_PASS'" 2>$ERR
1486 errshow 1 "set $NEWUSER password"
1488 if [[ $USER_PKGS == *neovim* && -d $MNT/home/$NEWUSER/.vim ]]; then
1489 mkdir -p $MNT/home/$NEWUSER/.config/nvim
1490 cp -fv $MNT/home/$NEWUSER/.vimrc $MNT/home/$NEWUSER/.config/nvim/init.vim
1491 cp -rfv $MNT/home/$NEWUSER/.vim/colors $MNT/home/$NEWUSER/.config/nvim/colors
1494 [[ $INSTALL_WMS == *dwm* ]] && install_suckless
1495 [[ $INSTALL_WMS == *awesome* ]] && install_awesome
1496 [[ $WM_PKGS == *xfce* ]] && echo 'volumeicon &' >> $MNT/home/$NEWUSER/.xprofile
1498 # remove some commands from ~/.xprofile when using KDE or Gnome as the login session
1499 if [[ $LOGIN_WM =~ (startkde|gnome-session) || ($LOGIN_TYPE == 'lightdm' && $WM_PKGS =~ (plasma|gnome)) ]]; then
1500 sed -i '/super/d' $MNT/home/$NEWUSER/.xprofile $MNT/root/.xprofile
1501 sed -i '/nitrogen/d' $MNT/home/$NEWUSER/.xprofile $MNT/root/.xprofile
1502 sed -i '/al-compositor/d' $MNT/home/$NEWUSER/.xprofile $MNT/root/.xprofile
1503 sed -i '/compton/d' $MNT/home/$NEWUSER/.xprofile $MNT/root/.xprofile
1511 if [[ -e $MNT/home/$NEWUSER/.xinitrc ]] && grep -q 'exec' $MNT/home/$NEWUSER/.xinitrc; then
1512 sed -i "/exec/ c exec ${LOGIN_WM}" $MNT/home/$NEWUSER/.xinitrc
1514 printf "exec %s\n" "$LOGIN_WM" >> $MNT/home/$NEWUSER/.xinitrc
1517 [[ ${EDIT_FILES[login]} == *"$LOGINRC"* ]] || EDIT_FILES[login]+=" /home/$NEWUSER/$LOGINRC"
1519 if [[ $AUTOLOGIN ]]; then
1520 sed -i "s/root/${NEWUSER}/g" $SERVICE/autologin.conf
1521 cat > $MNT/home/$NEWUSER/$LOGINRC <<EOF
1523 # sourced by ${MYSHELL##*/} when used as a login shell
1525 # automatically run startx when logging in on tty1
1526 if [ -z \$DISPLAY ] && [ \$XDG_VTNR -eq 1 ]; then
1537 SERVICE="$MNT/etc/systemd/system/getty@tty1.service.d"
1538 sed -i '/printf/d' $MNT/root/.zshrc
1539 install_${LOGIN_TYPE:-xinit}
1545 rm -rf $MNT/home/$NEWUSER/.{xinitrc,profile,zprofile,bash_profile}
1546 chrun 'systemctl set-default graphical.target && systemctl enable lightdm.service' 2>$ERR
1547 errshow 1 "systemctl set-default graphical.target && systemctl enable lightdm.service"
1548 cat > $MNT/etc/lightdm/lightdm-gtk-greeter.conf << EOF
1549 # LightDM GTK+ Configuration
1552 default-user-image=/usr/share/icons/ArchLabs-Dark/64x64/places/distributor-logo-archlabs.png
1553 background=/usr/share/backgrounds/archlabs/archlabs.jpg
1554 theme-name=Adwaita-dark
1555 icon-theme-name=Adwaita
1556 font-name=DejaVu Sans Mono 11
1557 position=30%,end 50%,end
1563 # downloads and sets up @elenapan's awesome WM config hosted on github
1565 if chrun "git clone https://github.com/elenapan/archlabs-awesome /home/$NEWUSER/archlabs-awesome"; then
1566 cp -rT "/mnt/home/$NEWUSER/archlabs-awesome" "/mnt/home/$NEWUSER"
1567 cp -rT "/mnt/home/$NEWUSER/archlabs-awesome" /mnt/etc/skel
1568 rm -rf "/home/$NEWUSER/"{.git,archlabs-awesome,screenshots}
1569 printf "You will need to instal pamac seperately if needed using: 'baph -i pamac-aur'\n"
1572 printf "failed to clone awesome config repo\n"
1579 local inpkg="$PACKAGES $USER_PKGS"
1581 if pacman -Qsq 'archlabs-installer' >/dev/null 2>&1; then
1582 rmpkg+=" archlabs-installer"
1583 elif [[ -e "$MNT/usr/bin/archlabs-installer" ]]; then
1584 rm -f "$MNT/usr/bin/archlabs-installer"
1587 # add extras or missed packages gathered throughout the install
1588 [[ $UCODE ]] && inpkg+=" $UCODE"
1589 [[ $KERNEL == 'linux' ]] || { inpkg+=" $KERNEL"; rmpkg+=" linux"; }
1590 [[ $MYSHELL == "/usr/bin/mksh" ]] && inpkg+=" mksh"
1591 if [[ $MYSHELL == '/usr/bin/zsh' ]]; then
1592 inpkg+=" zsh-completions"
1597 # packages only installed for certain WM/DE
1598 [[ $INSTALL_WMS =~ ^(plasma|gnome|cinnamon)$ ]] || inpkg+=" archlabs-ksuperkey"
1599 [[ $INSTALL_WMS =~ (openbox|bspwm|i3-gaps|dwm|fluxbox) ]] && inpkg+=" $WM_BASE_PKGS"
1601 # ensure a terminal gets installed
1602 [[ $inpkg =~ (term|urxvt|tilix|alacritty|sakura|tilda|plasma|cinnamon) || $INSTALL_WMS == *dwm* ]] || inpkg+=" xterm"
1604 # update fully first to avoid issues
1605 chrun "pacman -Syyu --noconfirm"
1607 # remove packages we no longer want
1608 [[ $rmpkg ]] && chrun "pacman -Rns $rmpkg --noconfirm"
1610 # for some reason the user has "no network" after install even though the
1611 # system is connected, reinstalling iputils fixes it
1612 chrun "pacman -S iputils --noconfirm"
1614 # install all the packages chosen throughout the install
1615 chrun "pacman -S $inpkg --needed --noconfirm" 2>$ERR
1616 errshow 1 "pacman -S $inpkg --needed --noconfirm"
1618 # extras for bootloaders
1619 if [[ $BOOTLDR == 'grub' ]]; then
1620 if [[ $SYS == 'BIOS' ]]; then
1621 chrun "pacman -S grub os-prober --needed --noconfirm" 2>$ERR
1622 errshow 1 "pacman -S grub os-prober --needed --noconfirm"
1624 chrun "pacman -S grub os-prober efibootmgr --needed --noconfirm" 2>$ERR
1625 errshow 1 "pacman -S grub os-prober efibootmgr --needed --noconfirm"
1627 elif [[ $BOOTLDR == 'refind-efi' ]]; then
1628 chrun "pacman -S refind-efi efibootmgr --needed --noconfirm" 2>$ERR
1629 errshow 1 "pacman -S refind-efi efibootmgr --needed --noconfirm"
1630 elif [[ $SYS == 'UEFI' ]]; then
1631 chrun "pacman -S efibootmgr --needed --noconfirm" 2>$ERR
1632 errshow 1 "pacman -S efibootmgr --needed --noconfirm"
1635 sed -i "s/# %wheel ALL=(ALL) ALL/%wheel ALL=(ALL) ALL/g" $MNT/etc/sudoers
1642 mkdir -pv $MNT/home/$NEWUSER/suckless
1644 for i in dwm dmenu st; do
1645 if chrun "git clone https://git.suckless.org/$i /home/$NEWUSER/suckless/$i"; then
1646 chrun "cd /home/$NEWUSER/suckless/$i; make PREFIX=/usr install; make clean; rm config.h"
1648 printf "failed to clone %s repo\n" "$i"
1652 if [[ -d $MNT/home/$NEWUSER/suckless/dwm && -x $MNT/usr/bin/dwm ]]; then
1653 printf "To configure dwm edit %s\n" "/home/$NEWUSER/suckless/dwm/config.h"
1654 printf "You can then recompile it with 'sudo make clean install'\n"
1659 install_mkinitcpio()
1663 # luks keyfile creation
1664 # currently not used due to not prompting for passphrase on startup
1665 # [[ $LUKS_UUID && $LUKS_PASS && $SYS == 'UEFI' && $BOOTLDR == 'grub' ]] && luks_keyfile
1667 [[ $LUKS ]] && add="encrypt"
1668 [[ $LVM ]] && { [[ $add ]] && add+=" lvm2" || add+="lvm2"; }
1669 sed -i "s/block filesystems/block ${add} filesystems ${HOOKS}/g" $MNT/etc/mkinitcpio.conf
1670 chrun "mkinitcpio -p $KERNEL" 2>$ERR
1671 errshow 1 "mkinitcpio -p $KERNEL"
1674 install_mirrorlist()
1676 local mfile="$1" # output mirrorlist file
1678 if hash reflector >/dev/null 2>&1; then
1679 reflector --score 120 -l 50 -f 5 --sort rate --save "$mfile"
1680 elif hash rankmirrors >/dev/null 2>&1; then
1681 ip_add="$(curl -fsSL "http://api.ipstack.com/check&?access_key=5f29642060ab983b31fdf4c2935d8c56&fields=ip" |
1682 python -c "import sys, json; print(json.load(sys.stdin)['ip'])")"
1683 country="$(curl -fsSL "http://api.ipstack.com/${ip_add}?access_key=5f29642060ab983b31fdf4c2935d8c56&fields=country_code" |
1684 python -c "import sys, json; print(json.load(sys.stdin)['country_code'])")"
1685 if [[ "$country" ]]; then
1686 if [[ $country =~ (CA|US) ]]; then
1687 mirror="https://www.archlinux.org/mirrorlist/?country=US&country=CA&use_mirror_status=on"
1688 elif [[ $country =~ (AU|NZ) ]]; then
1689 mirror="https://www.archlinux.org/mirrorlist/?country=AU&country=NZ&use_mirror_status=on"
1691 mirror="https://www.archlinux.org/mirrorlist/?country=${country}&use_mirror_status=on"
1694 mirror="https://www.archlinux.org/mirrorlist/?country=all&use_mirror_status=on"
1697 curl -fsSL "$mirror" | sed -e 's/^#Server/Server/' -e '/^#/d' | rankmirrors -n 6 - >"$mfile"
1703 install_background()
1705 if [[ -d /run/archiso/sfs/airootfs/etc/skel ]] && grep -qw "$MNT" /proc/mounts && (grep -qw "$MNT/$BOOTDIR" /proc/mounts || [[ $SYS == 'BIOS' && -z $LUKS ]]); then
1706 yesno "Background Install" "\nBegin install in the background?\n" || return 0
1707 rsync -a /run/archiso/sfs/airootfs/ $MNT/ &
1709 ( install_mirrorlist "$MNT/etc/pacman.d/mirrorlist"; chrun "pacman -Syyu $BASE_PKGS --needed --noconfirm" >> /tmp/bg_out 2>&1 ) &
1711 # end the background processes before exiting
1712 trap "kill $RSYNC_PID $MIRROR_PID 2>/dev/null" EXIT
1717 ###############################################################################
1722 EDIT_FILES[bootloader]="/etc/default/grub"
1724 if [[ $SYS == 'BIOS' ]]; then
1725 [[ $BOOT_DEV ]] || { part_device 1 || return 1; }
1726 BCMDS[grub]="grub-install --recheck --force --target=i386-pc $BOOT_DEV"
1728 # if [[ $ROOT_PART == */dev/mapper/* && -z $LVM && -z $LUKS_PASS ]]; then
1729 # luks_pass "$_luksopen" 1 || return 1
1731 BCMDS[grub]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1732 grub-install --recheck --force --target=x86_64-efi --efi-directory=/$BOOTDIR --bootloader-id=$DIST"
1733 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1736 BCMDS[grub]="mkdir -p /run/udev /run/lvm &&
1737 mount --bind /hostrun/udev /run/udev &&
1738 mount --bind /hostrun/lvm /run/lvm &&
1740 grub-mkconfig -o /boot/grub/grub.cfg &&
1741 sleep 1 && umount /run/udev /run/lvm"
1748 sed -i "s/GRUB_DISTRIBUTOR=.*/GRUB_DISTRIBUTOR=\"${DIST}\"/g;
1749 s/GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT=\"\"/g" $MNT/etc/default/grub
1751 if [[ $LUKS_DEV ]]; then
1752 sed -i "s~#GRUB_ENABLE_CRYPTODISK~GRUB_ENABLE_CRYPTODISK~g;
1753 s~GRUB_CMDLINE_LINUX=.*~GRUB_CMDLINE_LINUX=\"${LUKS_DEV}\"~g" $MNT/etc/default/grub 2>$ERR
1754 errshow 1 "sed -i 's~#GRUB_ENABLE_CRYPTODISK~GRUB_ENABLE_CRYPTODISK~g;
1755 s~GRUB_CMDLINE_LINUX=.*~GRUB_CMDLINE_LINUX=\"${LUKS_DEV}\"~g' $MNT/etc/default/grub"
1758 if [[ $SYS == 'BIOS' && $LVM && -z $SEP_BOOT ]]; then
1759 sed -i "s/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g" $MNT/etc/default/grub 2>$ERR
1760 errshow 1 "sed -i 's/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g' $MNT/etc/default/grub"
1763 # setup for os-prober module
1764 mkdir -p /run/{lvm,udev} $MNT/hostrun/{lvm,udev}
1765 mount --bind /run/lvm $MNT/hostrun/lvm
1766 mount --bind /run/udev $MNT/hostrun/udev
1773 EDIT_FILES[bootloader]=""
1778 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1779 efibootmgr -v -d $BOOT_DEV -p $BOOT_PART_NUM -c -L '${DIST} Linux' -l /vmlinuz-${KERNEL} \
1780 -u 'root=$ROOT_PART_ID rw $([[ $UCODE ]] && printf 'initrd=\%s.img ' "$UCODE")initrd=\initramfs-${KERNEL}.img'"
1785 if [[ $SYS == 'BIOS' ]]; then
1786 EDIT_FILES[bootloader]="/boot/syslinux/syslinux.cfg"
1788 EDIT_FILES[bootloader]="/boot/EFI/syslinux/syslinux.cfg"
1789 BCMDS[syslinux]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1790 efibootmgr -v -c -d $BOOT_DEV -p $BOOT_PART_NUM -l /EFI/syslinux/syslinux.efi -L $DIST"
1796 local c="$MNT/boot/syslinux" s="/usr/lib/syslinux/bios" d=".."
1797 [[ $SYS == 'UEFI' ]] && { c="$MNT/boot/EFI/syslinux"; s="/usr/lib/syslinux/efi64/"; d=''; }
1799 mkdir -pv "$c" && cp -rfv $s/* "$c/" && cp -f "$RUN/syslinux/splash.png" "$c/"
1800 cat > "$c/syslinux.cfg" << EOF
1802 MENU TITLE $DIST Boot Menu
1803 MENU BACKGROUND splash.png
1807 # see: https://www.syslinux.org/wiki/index.php/Comboot/menu.c32
1816 MENU HELPMSGENDROW 29
1817 MENU COLOR border 30;44 #40ffffff #a0000000 std
1818 MENU COLOR title 1;36;44 #9033ccff #a0000000 std
1819 MENU COLOR sel 7;37;40 #e0ffffff #20ffffff all
1820 MENU COLOR unsel 37;44 #50ffffff #a0000000 std
1821 MENU COLOR help 37;40 #c0ffffff #a0000000 std
1822 MENU COLOR timeout_msg 37;40 #80ffffff #00000000 std
1823 MENU COLOR timeout 1;37;40 #c0ffffff #00000000 std
1824 MENU COLOR msg07 37;40 #90ffffff #a0000000 std
1825 MENU COLOR tabmsg 31;40 #30ffffff #00000000 std
1828 MENU LABEL $DIST Linux
1829 LINUX $d/vmlinuz-$KERNEL
1830 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1831 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL.img
1833 LABEL ${DIST}fallback
1834 MENU LABEL $DIST Linux Fallback
1835 LINUX $d/vmlinuz-$KERNEL
1836 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1837 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL-fallback.img
1838 $([[ $SYS == 'BIOS' ]] && printf "\n%s" "# examples of chainloading other bootloaders
1843 #APPEND file=$d/grub/boot.img
1855 EDIT_FILES[bootloader]="/boot/refind_linux.conf"
1856 BCMDS[refind-efi]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1862 cat > $MNT/boot/refind_linux.conf << EOF
1863 "$DIST Linux" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] &&
1864 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1865 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL.img"
1866 "$DIST Linux Fallback" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] &&
1867 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1868 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL-fallback.img"
1870 mkdir -p $MNT/etc/pacman.d/hooks
1871 cat > $MNT/etc/pacman.d/hooks/refind.hook << EOF
1878 Description = Updating rEFInd on ESP
1879 When = PostTransaction
1880 Exec = /usr/bin/refind-install
1884 setup_systemd-boot()
1886 EDIT_FILES[bootloader]="/boot/loader/entries/$DIST.conf"
1887 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1888 bootctl --path=/boot install"
1891 prerun_systemd-boot()
1893 mkdir -p $MNT/boot/loader/entries
1894 cat > $MNT/boot/loader/loader.conf << EOF
1899 cat > $MNT/boot/loader/entries/$DIST.conf << EOF
1901 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1902 initrd /initramfs-$KERNEL.img
1903 options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1905 cat > $MNT/boot/loader/entries/$DIST-fallback.conf << EOF
1906 title $DIST Linux Fallback
1907 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1908 initrd /initramfs-$KERNEL-fallback.img
1909 options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1911 mkdir -p $MNT/etc/pacman.d/hooks
1912 cat > $MNT/etc/pacman.d/hooks/systemd-boot.hook << EOF
1919 Description = Updating systemd-boot
1920 When = PostTransaction
1921 Exec = /usr/bin/bootctl update
1923 systemd-machine-id-setup --root="$MNT"
1927 ###############################################################################
1932 is_bg_install || return 1
1935 dlg choice menu "Logical Volume Management" "$_lvmmenu" \
1936 "$_lvmnew" "vgcreate -f, lvcreate -L -n" \
1937 "$_lvmdel" "vgremove -f" \
1938 "$_lvmdelall" "lvrmeove, vgremove, pvremove -f" \
1939 "back" "return to the main menu"
1942 "$_lvmnew") lvm_create || return 1 ;;
1943 "$_lvmdel") lvm_delgroup && yesno "$_lvmdel" "$_lvmdelask" && vgremove -f "$DEL_VG" >/dev/null 2>&1 ;;
1944 "$_lvmdelall") lvm_del_all ;;
1953 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
1954 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
1955 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
1957 if [[ $VGROUP && $v && $pv ]]; then
1958 msg "Logical Volume Management" "\nActivating existing logical volume management (LVM).\n\n" 1
1959 modprobe dm-mod >/dev/null 2>$ERR
1960 errshow 'modprobe dm-mod'
1961 vgscan >/dev/null 2>&1
1962 vgchange -ay >/dev/null 2>&1
1968 VGROUP='' LVM_PARTS='' VGROUP_MB=0
1970 lvm_mkgroup || return 1
1971 local txt="\nThe last (or only) logical volume will automatically use all remaining space in the volume group."
1972 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
1973 [[ $VOL_COUNT ]] || return 1
1974 lvm_extra_lvs || return 1
1975 lvm_volume_name "$_lvmlvname\nNOTE: This LV will use up all remaining space in the volume group (${VGROUP_MB}MB)" || return 1
1976 lvcreate -l +100%FREE "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
1977 errshow "lvcreate -l +100%FREE $VGROUP -n $VNAME" || return 1
1978 LVM='logical volume'; sleep 0.5
1979 txt="\nDone, volume: $VGROUP-$VNAME (${VOLUME_SIZE:-${VGROUP_MB}MB}) has been created.\n"
1980 msg "$_lvmnew (LV:$VOL_COUNT)" "$txt\n$(lsblk -o NAME,MODEL,TYPE,FSTYPE,SIZE $LVM_PARTS)\n"
1986 local txt="${VGROUP}: ${SIZE}$SIZE_UNIT (${VGROUP_MB}MB remaining).$_lvmlvsize"
1990 dlg VOLUME_SIZE input "$_lvmnew (LV:$VOL_COUNT)" "$txt" ''
1991 if [[ -z $VOLUME_SIZE ]]; then
1993 break # allow bailing with escape or an empty choice
1994 elif (( ${VOLUME_SIZE:0:1} == 0 )); then
1995 ERR_SIZE=1 # size values can't begin with '0'
1997 # walk the string and make sure all but the last char are digits
1998 local lv=$((${#VOLUME_SIZE} - 1))
1999 for (( i=0; i<lv; i++ )); do
2000 [[ ${VOLUME_SIZE:$i:1} =~ [0-9] ]] || { ERR_SIZE=1; break; }
2002 if (( ERR_SIZE != 1 )); then
2003 case ${VOLUME_SIZE:$lv:1} in
2004 [mMgG]) local s=${VOLUME_SIZE:0:$lv} m=$((s * 1000))
2005 case ${VOLUME_SIZE:$lv:1} in
2006 [Gg]) (( m >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - m)) ;;
2007 [Mm]) (( ${VOLUME_SIZE:0:$lv} >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - s)) ;;
2014 if (( ERR_SIZE )); then
2015 msg "Invalid Logical Volume Size" "$_lvmerrlvsize"
2027 local txt="\nConfirm creation of volume group: $VGROUP\n\nwith the following partition(s):"
2029 until [[ $named ]]; do
2030 lvm_partitions || return 1
2031 lvm_group_name || return 1
2032 yesno "$_lvmnew" "$txt $LVM_PARTS\n" && named=true
2035 vgcreate -f "$VGROUP" $LVM_PARTS >/dev/null 2>$ERR
2036 errshow "vgcreate -f $VGROUP $LVM_PARTS" || return 1
2038 SIZE=$(vgdisplay "$VGROUP" | awk '/VG Size/ { gsub(/[^0-9.]/, ""); print int($0) }')
2039 SIZE_UNIT="$(vgdisplay "$VGROUP" | awk '/VG Size/ { print substr($NF, 0, 1) }')"
2041 if [[ $SIZE_UNIT == 'G' ]]; then
2042 VGROUP_MB=$((SIZE * 1000))
2047 msg "$_lvmnew" "\nVolume group: $VGROUP ($SIZE $SIZE_UNIT) has been created\n"
2054 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
2055 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
2056 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
2058 if [[ $VGROUP || $v || $pv ]]; then
2059 if yesno "$_lvmdelall" "$_lvmdelask"; then
2060 for i in $v; do lvremove -f "/dev/mapper/$i" >/dev/null 2>&1; done
2061 for i in $VGROUP; do vgremove -f "$i" >/dev/null 2>&1; done
2062 for i in $pv; do pvremove -f "$i" >/dev/null 2>&1; done
2066 msg "Delete LVM" "\nNo LVMs to remove...\n" 2
2076 for i in $(lvs --noheadings | awk '{print $2}' | uniq); do
2077 VOL_GROUP_LIST+="$i $(vgdisplay "$i" | awk '/VG Size/ {print $3$4}') "
2079 [[ $VOL_GROUP_LIST ]] || { msg "No Groups" "\nNo volume groups found."; return 1; }
2081 dlg DEL_VG menu "Logical Volume Management" "\nSelect volume group to delete.\n\nAll logical volumes within will also be deleted." $VOL_GROUP_LIST
2087 while (( VOL_COUNT > 1 )); do
2088 lvm_volume_name "$_lvmlvname" && get_lv_size || return 1
2089 lvcreate -L "$VOLUME_SIZE" "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
2090 errshow "lvcreate -L $VOLUME_SIZE $VGROUP -n $VNAME" || return 1
2091 msg "$_lvmnew (LV:$VOL_COUNT)" "\nDone, logical volume (LV) $VNAME ($VOLUME_SIZE) has been created.\n"
2099 part_find 'part|crypt' || return 1
2100 PARTS="$(awk 'NF > 0 {print $0 " off"}' <<< "$PARTS")"
2101 dlg LVM_PARTS check "$_lvmnew" "\nSelect the partition(s) to use for the physical volume (PV)." $PARTS
2108 until [[ $VGROUP ]]; do
2109 dlg VGROUP input "$_lvmnew" "$_lvmvgname" "mygroup"
2110 if [[ -z $VGROUP ]]; then
2112 elif [[ ${VGROUP:0:1} == "/" || $VGROUP =~ \ |\' ]] || lsblk | grep -q "$VGROUP"; then
2113 msg "LVM Name Error" "$_lvmerrvgname"
2123 local txt="$1" default="mainvolume"
2124 (( VOL_COUNT > 1 )) && default="extravolume$VOL_COUNT"
2125 until [[ $VNAME ]]; do
2126 dlg VNAME input "$_lvmnew (LV:$VOL_COUNT)" "\n$txt" "$default"
2127 if [[ -z $VNAME ]]; then
2129 elif [[ ${VNAME:0:1} == "/" || $VNAME =~ \ |\' ]] || lsblk | grep -q "$VNAME"; then
2130 msg "LVM Name Error" "$_lvmerlvname"
2137 ###############################################################################
2143 is_bg_install || return 1
2144 dlg choice menu "LUKS Encryption" "$_luksmenu" \
2145 "$_luksnew" "cryptsetup -q luksFormat" \
2146 "$_luksopen" "cryptsetup open --type luks" \
2147 "$_luksadv" "cryptsetup -q -s -c luksFormat" \
2148 "back" "Return to the main menu"
2151 "$_luksnew") luks_basic || return 1 ;;
2152 "$_luksopen") luks_open || return 1 ;;
2153 "$_luksadv") luks_advanced || return 1 ;;
2161 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
2163 part_find 'part|crypt|lvm' || return 1
2165 if (( COUNT == 1 )); then
2166 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2168 dlg LUKS_PART menu "$_luksopen" "\nSelect which partition to open." $PARTS
2171 [[ $LUKS_PART ]] || return 1
2173 luks_pass "$_luksopen" || return 1
2174 msg "$_luksopen" "\nOpening encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2175 cryptsetup open --type luks "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2176 errshow "cryptsetup open --type luks $LUKS_PART $LUKS_NAME" || return 1
2177 LUKS='encrypted'; luks_show
2184 local t="$1" op="$2" v='' p='' p2=''
2186 until [[ $LUKS_PASS ]]; do
2190 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " $t " \
2191 --mixedform "\nEnter the password to decrypt $ROOT_PART\n\nThis is needed to create a keyfile." 0 0 0 \
2192 "Password:" 1 1 '' 1 11 "$COLUMNS" 0 1 \
2193 "Password2:" 2 1 '' 2 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
2196 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " $t " --mixedform "$_luksomenu" 0 0 0 \
2197 "Name:" 1 1 "${LUKS_NAME:-cryptroot}" 1 7 "$COLUMNS" 0 0 \
2198 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
2199 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
2203 while read -r line; do
2219 if [[ -z $op && -z $n ]]; then
2220 msg "Name Empty" "\nEncrypted device name cannot be empty.\n\nPlease try again.\n" 2
2221 elif [[ -z $p || "$p" != "$p2" ]]; then
2222 [[ $op ]] || LUKS_NAME="$n"
2223 msg "Password Mismatch" "\nThe passwords entered do not match.\n\nPlease try again.\n" 2
2225 [[ $op ]] || LUKS_NAME="$n"
2236 msg "$_luksnew" "\nEncrypted partition opened and ready for mounting.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$LUKS_PART")\n\n"
2241 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
2243 part_find 'part|lvm' || return 1
2245 if [[ $AUTO_ROOT_PART ]]; then
2246 LUKS_PART="$AUTO_ROOT_PART"
2247 elif (( COUNT == 1 )); then
2248 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2250 dlg LUKS_PART menu "$_luksnew" "\nSelect the partition you want to encrypt." $PARTS
2253 [[ $LUKS_PART ]] || return 1
2254 luks_pass "$_luksnew"
2259 luks_setup || return 1
2260 msg "$_luksnew" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2261 cryptsetup -q luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2262 errshow "cryptsetup -q 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
2265 LUKS='encrypted'; luks_show
2271 if [[ ! -e $MNT/crypto_keyfile.bin ]]; then
2272 # printf "Creating LUKS keyfile /crypto_keyfile.bin\n"
2274 n="$(lsblk -lno NAME,UUID,TYPE | awk "/$LUKS_UUID/"' && /part|crypt|lvm/ {print $1}')"
2275 local mkkey="dd bs=512 count=8 if=/dev/urandom of=/crypto_keyfile.bin"
2276 mkkey="$mkkey && chmod 000 /crypto_keyfile.bin"
2277 mkkey="$mkkey && cryptsetup luksAddKey /dev/$n /crypto_keyfile.bin <<< '$LUKS_PASS'"
2279 sed -i 's/FILES=()/FILES=(\/crypto_keyfile.bin)/g' $MNT/etc/mkinitcpio.conf 2>$ERR
2289 dlg cipher input "LUKS Encryption" "$_lukskey" "-s 512 -c aes-xts-plain64"
2290 [[ $cipher ]] || return 1
2291 msg "$_luksadv" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2292 cryptsetup -q $cipher luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2293 errshow "cryptsetup -q $cipher luksFormat $LUKS_PART" || return 1
2294 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2295 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2302 ###############################################################################
2307 [[ "$2" == *"$1"* ]] && printf "on" || printf "off"
2316 if [[ -d $MNT ]] && command cd /; then
2318 if (( ecode == 127 )); then
2319 umount_dir /run/archiso/bootmnt
2330 local var="$1" dialog_type="$2" title="$3" body="$4" n=0
2332 (( ($# / 2) > SHL )) && n=$SHL
2335 case "$dialog_type" in
2336 menu) dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --menu "$body" 0 0 $n "$@" 2>"$ANS" || return 1 ;;
2337 check) dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --checklist "$body" 0 0 $n "$@" 2>"$ANS" || return 1 ;;
2342 if [[ $1 == 'limit' ]]; then
2343 dialog --backtitle "$DIST Installer - $SYS - v$VER" --max-input 63 --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2345 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2349 [[ -s "$ANS" ]] && printf -v "$var" "%s" "$(< "$ANS")"
2354 local title="$1" body="$2"
2356 if (( $# == 3 )); then
2357 dialog --backtitle "$DIST Installer - $SYS - v$VER" --sleep "$3" --title " $title " --infobox "$body\n" 0 0
2359 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --msgbox "$body\n" 0 0
2365 local title="$1" body="$2" yes='Yes' no='No'
2366 (( $# >= 3 )) && yes="$3"
2367 (( $# >= 4 )) && no="$4"
2369 if (( $# == 5 )); then
2370 dialog --backtitle "$DIST Installer - $SYS - v$VER" --defaultno --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2372 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2378 arch-chroot "$MNT" bash -c "$1"
2383 export PS4='| ${BASH_SOURCE} LINE:${LINENO} FUNC:${FUNCNAME[0]:+ ${FUNCNAME[0]}()} |> '
2392 printf "\n^C caught, cleaning up...\n"
2400 if [[ $COLUMNS -ge 110 && ${#str} -gt $((COLUMNS - 30)) ]]; then
2402 i = 2; p1 = p2 = p3 = p4 = ""; p1 = $1; q = int(NF / 4)
2403 for (; i <= q; i++) { p1 = p1 " " $i }
2404 for (; i <= q * 2; i++) { p2 = p2 " " $i }
2405 for (; i <= q * 3; i++) { p3 = p3 " " $i }
2406 for (; i <= NF; i++) { p4 = p4 " " $i }
2407 printf "%s\n %s\n %s\n %s", p1, p2, p3, p4
2409 printf "%s\n" "$str"
2410 elif [[ $str ]]; then
2411 printf "%s\n" "$str"
2418 "\e]P0191919" # #191919
2419 "\e]P1D15355" # #D15355
2420 "\e]P2609960" # #609960
2421 "\e]P3FFCC66" # #FFCC66
2422 "\e]P4255A9B" # #255A9B
2423 "\e]P5AF86C8" # #AF86C8
2424 "\e]P62EC8D3" # #2EC8D3
2425 "\e]P7949494" # #949494
2426 "\e]P8191919" # #191919
2427 "\e]P9D15355" # #D15355
2428 "\e]PA609960" # #609960
2429 "\e]PBFF9157" # #FF9157
2430 "\e]PC4E88CF" # #4E88CF
2431 "\e]PDAF86C8" # #AF86C8
2432 "\e]PE2ec8d3" # #2ec8d3
2433 "\e]PFE1E1E1" # #E1E1E1
2436 [[ $TERM == 'linux' ]] && printf "%b" "${colors[@]}" && clear
2441 [ $? -eq 0 ] && return 0
2443 local fatal=0 err=""
2444 err="$(sed 's/[^[:print:]]//g; s/\[[0-9\;:]*\?m//g; s/==> //g; s/] ERROR:/]\nERROR:/g' "$ERR")"
2446 (( $1 == 1 )) && { fatal=1; shift; }
2448 local txt="\nThe command exited abnormally:\n\n$1\n\n"
2451 txt+="With the following message:\n\n$err\n\n"
2453 txt+="With no error message:\n\n"
2456 if (( fatal )); then
2457 txt+="Errors at this stage are fatal and the install cannot continue.\n"
2459 txt+="Errors at this stage are non-fatal and can be either fixed or ignored depending on the error.\n"
2461 msg "Install Error" "$txt"
2463 if (( fatal )); then
2464 [[ -r $DBG && $TERM == 'linux' ]] && less "$DBG"
2473 msg "Broadcom Wireless Setup" "\nDetected chipset is Broadcom BCM4352\n\nDisabling bcma/b43 modules and loading wl module.\n" 1
2474 { rmmod wl; rmmod bcma; rmmod b43; rmmod ssb; modprobe wl; depmod -a; } >/dev/null 2>&1
2482 if (( $1 >= 0 )) && ! grep -qw "$MNT" /proc/mounts; then
2483 msg "Not Mounted" "\nPartition(s) must be mounted first.\n" 2
2485 elif [[ $1 -ge 1 && -z $BOOTLDR ]]; then
2486 msg "No Bootloader" "\nBootloader must be selected first.\n" 2
2488 elif [[ $1 -ge 2 && (-z $NEWUSER || -z $USER_PASS) ]]; then
2489 msg "No User" "\nA user must be created first.\n" 2
2491 elif [[ $1 -ge 3 && -z $CONFIG_DONE ]]; then
2492 msg "Not Configured" "\nSystem configuration must be done first.\n" 2
2495 (( i )) # return code
2500 mount | grep -q 'swap' && swapoff -a
2502 [[ -d $dir ]] || continue
2503 umount "$dir" 2>/dev/null || { sleep 0.5; umount -f "$dir" 2>/dev/null || umount -l "$dir"; }
2509 msg "Network Connect" "\nVerifying network connection\n" 1
2510 curl -sIN --connect-timeout 5 'https://www.archlinux.org/' | sed '1q' | grep -q '200'
2515 if chk_connect; then
2518 if hash nmtui >/dev/null 2>&1; then
2520 if [[ $TERM == 'linux' ]]; then
2521 printf "%b" "\e]P1191919" "\e]P4191919"
2523 printf "%b" "\e]P1D15355" "\e]P4255a9b"
2536 [[ $RSYNC_PID || $MIRROR_PID ]] || return 0
2537 msg "Install Running" "\nA background install process is currently running.\n" 2
2543 IGNORE_DEV="$(lsblk -lno NAME,MOUNTPOINT | awk '/\/run\/archiso\/bootmnt/ {sub(/[1-9]/, ""); print $1}')"
2545 if [[ $IGNORE_DEV ]]; then
2546 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ && !'"/$IGNORE_DEV/"' {print "/dev/" $1 " " $2}')"
2548 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ {print "/dev/" $1 " " $2}')"
2551 if [[ -z $SYS_DEVS ]]; then
2552 msg "Device Error" "\nNo available devices...\n\nExiting..\n" 2
2557 while read -r line; do
2559 done <<< "$SYS_DEVS"
2566 elif grep -q 'AuthenticAMD' /proc/cpuinfo; then
2568 elif grep -q 'GenuineIntel' /proc/cpuinfo; then
2572 modprobe -q efivarfs >/dev/null 2>&1
2574 _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."
2575 if [[ -d /sys/firmware/efi/efivars ]]; then
2577 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars
2578 _prep+="\n - An EFI boot partition mounted."
2582 _prep+="\n\nOnce finished mounting, a portion of the install can be done in the background while you continue configuring the system:\n"
2583 _prep+="\n - Choose the system bootloader.\n - Create a user and password."
2584 _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."
2587 ###############################################################################
2590 # enable some nicer colours in the linux console
2593 if (( UID != 0 )); then
2594 msg "Not Root" "\nThis installer must be run as root or using sudo.\n\nExiting..\n" 2
2596 elif ! grep -qwm 1 'lm' /proc/cpuinfo; then
2597 msg "Not x86_64 Architecture" "\nThis installer only supports x86_64 architectures.\n\nExiting..\n" 2
2599 elif [[ $1 =~ (-d|--debug) ]]; then
2603 # trap ^C to perform cleanup
2609 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"
2611 select_keymap || { clear; die 0; }
2613 if lspci -vnn -d 14e4: | grep -q 'BCM4352'; then
2617 if ! net_connect; then
2618 msg "Not Connected" "\nThis installer requires an active internet connection.\n\nExiting..\n" 2
2626 # vim:fdm=marker:fmr={,}