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.42" # installer version
9 DIST="ArchLabs" # linux distributor
10 MNT="/mnt" # install mountpoint
11 ANS="/tmp/ans" # dialog answer file
14 # --------------------------------------------- #
15 # if you manually mount your partitions then you
16 # need to set these values to avoid issues.
17 # --------------------------------------------- #
19 # root partition, eg/ /dev/sda2
22 # boot partition, required on UEFI eg. /dev/sda1
25 # device used for some bootloader install process, eg. /dev/sda
28 # bootloader to use, can be:
29 # UEFI: grub, syslinux, efistub, systemd-boot, refind-efi
30 # BIOS: grub, syslinux
33 # directory to mount the boot partition (if any) for most bootloaders
34 # this will need to be 'boot' however a popular one for grub is 'boot/efi'
37 # swap partition or file path
40 # swap size, only used when creating a swapfile
43 # --------------------------------------------- #
45 # bulk default values {
47 EXMNT='' # holder for additional partitions while mounting
48 EXMNTS='' # when an extra partition is mounted append it's info
50 FONT="ter-i16n" # font used for the linux console
51 HOOKS="shutdown" # list of additional HOOKS to add in /etc/mkinitcpio.conf
53 LOGINRC='' # login shell rc file, eg. .zprofile, .bash_profile, .profile
54 LOGIN_WM='' # default login session to be placed in ~/.xinitrc
55 LOGIN_TYPE='' # login manager can be: lightdm, xinit
56 INSTALL_WMS='' # space separated list of chosen wm/de
58 UCODE='' # cpu microcode (if any), eg. amd-ucode, intel-ucode
59 KERNEL='' # can be linux, linux-lts, linux-zen, or linux-hardened
60 MYSHELL='' # full path for the shell, eg. /usr/bin/zsh
62 WM_PKGS='' # full list of packages added during wm/de choice
63 PACKAGES='' # list of all packages to install including WM_PKGS
64 USER_PKGS='' # packages selected by the user during install
66 NEWUSER='' # username for the new user
67 USER_PASS='' # new user's password
68 ROOT_PASS='' # root password
70 LUKS='' # empty when not using encryption
71 LUKS_DEV='' # boot parameter string for LUKS
72 LUKS_PART='' # partition used for encryption
73 LUKS_PASS='' # encryption password
74 LUKS_UUID='' # encrypted partition UUID
75 LUKS_NAME='' # name used for encryption
77 LVM='' # empty when not using lvm
78 LVM_PARTS='' # partitions used for volume group
79 VGROUP_MB=0 # available space in volume group
81 WARN='' # issued mounting/partitioning warning
82 SEP_BOOT='' # separate boot partition for BIOS
83 AUTOLOGIN='' # enable autologin for xinit
84 CONFIG_DONE='' # basic configuration is finished
85 BROADCOM_WL='' # fixes for broadcom cards eg. BCM4352
87 FORMATTED='' # partitions we formatted and should allow skipping
88 AUTO_ROOT_PART='' # root value from auto partition
89 AUTO_BOOT_PART='' # boot value from auto partition
91 # iso base, pacstrap when running the installer from a stock arch iso
92 ISO_BASE="b43-firmware b43-fwcutter broadcom-wl clonezilla dhclient dhcpcd ethtool wpa_supplicant "
93 ISO_BASE+="exfat-utils f2fs-tools gptfdisk vim hdparm ipw2100-fw ipw2200-fw nfs-utils nilfs-utils ntfs-3g "
94 ISO_BASE+="pacman-contrib parted rsync sdparm smartmontools wget wireless_tools wpa_actiond xl2tpd dialog parted "
95 ISO_BASE+="alsa-firmware alsa-lib alsa-plugins pulseaudio pulseaudio-alsa networkmanager w3m htop wireless-regdb "
96 ISO_BASE+="lm_sensors lsb-release p7zip pamixer reflector unrar ranger terminus-font ttf-dejavu archlabs-keyring"
98 # archlabs base packages
99 AL_BASE_PKGS="archlabs-skel-base archlabs-fonts archlabs-themes archlabs-dARK archlabs-icons archlabs-wallpapers archlabs-scripts"
101 # baseline (usually installed in the background)
102 BASE_PKGS="base-devel xorg xorg-drivers xorg-xinit sudo git gvfs gtk3 gtk-engines gtk-engine-murrine pavucontrol tumbler "
103 BASE_PKGS+="playerctl ffmpeg gstreamer libmad libmatroska gst-libav gst-plugins-base gst-plugins-good scrot"
105 # extras for window managers
106 WM_BASE_PKGS="arandr archlabs-networkmanager-dmenu xdg-user-dirs nitrogen polkit-gnome volumeicon xclip exo "
107 WM_BASE_PKGS+="xdotool compton wmctrl gnome-keyring dunst feh gsimplecal xfce4-power-manager xfce4-settings laptop-detect"
110 SEL=0 # currently selected menu item
111 ERR="/tmp/errlog" # error log used internally
112 DBG="/tmp/debuglog" # debug log when passed -d
113 RUN="/run/archiso/bootmnt/arch/boot" # path for live /boot
114 VM="$(dmesg | grep -i "hypervisor")" # is the system a vm
117 export DIALOGOPTS="--cr-wrap"
121 # giant ugly variable container :P {
123 # RAM in the system in MB
124 SYS_MEM="$(awk '/MemTotal/ {
125 print int($2 / 1024)"M"
128 # locales from /etc/locale.gen
129 LOCALES="$(awk '/\.UTF-8/ {
136 # linux console keyboard mappings
137 CMAPS="$(find /usr/share/kbd/keymaps -name '*.map.gz' | awk '{
138 gsub(/\.map\.gz|.*\//, "")
142 # terminal size definitions
144 [[ $LINES ]] || LINES=$(tput lines)
145 [[ $COLUMNS ]] || COLUMNS=$(tput cols)
146 SHL=$((LINES - 20)) # }
151 # commands used to install each bootloader (most get modified during runtime) {
153 [refind-efi]='refind-install'
154 [grub]='grub-install --recheck --force'
155 [syslinux]='syslinux-install_update -i -a -m'
156 [efistub]='efibootmgr -v -d /dev/sda -p 1 -c -l'
157 [systemd-boot]='bootctl --path=/boot install'
160 # executable name for each wm/de {
161 declare -A WM_SESSIONS=(
167 [gnome]='gnome-session'
168 [fluxbox]='startfluxbox'
169 [openbox]='openbox-session'
170 [cinnamon]='cinnamon-session'
173 # packages installed for each wm/de {
177 [plasma]='kdebase-meta'
178 [bspwm]='sxhkd archlabs-skel-bspwm rofi archlabs-polybar'
179 [fluxbox]='archlabs-skel-fluxbox archlabs-polybar jgmenu rofi lxmenu-data'
180 [i3-gaps]='i3status perl-anyevent-i3 archlabs-skel-i3-gaps rofi archlabs-polybar'
181 [openbox]='obconf archlabs-skel-openbox jgmenu archlabs-polybar tint2 conky rofi lxmenu-data'
182 [xfce4]='xfce4-goodies xfce4-pulseaudio-plugin network-manager-applet volumeicon rofi archlabs-skel-xfce4'
185 # files that can be edited after install is complete {
186 declare -A EDIT_FILES=(
189 [sudoers]='/etc/sudoers'
190 [crypttab]='/etc/crypttab'
191 [pacman]='/etc/pacman.conf'
192 [console]='/etc/vconsole.conf'
193 [mkinitcpio]='/etc/mkinitcpio.conf'
194 [hostname]='/etc/hostname /etc/hosts'
195 [bootloader]="/boot/loader/entries/$DIST.conf"
196 [locale]='/etc/locale.conf /etc/default/locale'
197 [keyboard]='/etc/X11/xorg.conf.d/00-keyboard.conf /etc/default/keyboard'
200 # mkfs command for formatting each offered filesystem {
205 [ntfs]='mkfs.ntfs -q'
206 [ext2]='mkfs.ext2 -q'
207 [ext3]='mkfs.ext3 -q'
208 [ext4]='mkfs.ext4 -q'
209 [vfat]='mkfs.vfat -F32'
210 [nilfs2]='mkfs.nilfs2 -q'
211 [reiserfs]='mkfs.reiserfs -q'
214 # mount options for each offered filesystem (if any {
220 [jfs]='discard errors=continue errors=panic nointegrity'
221 [reiserfs]='acl nolog notail replayonly user_xattr off'
222 [ext4]='discard dealloc nofail noacl relatime noatime nobarrier nodelalloc'
223 [xfs]='discard filestreams ikeep largeio noalign nobarrier norecovery noquota wsync'
224 [nilfs2]='discard nobarrier errors=continue errors=panic order=relaxed order=strict norecovery'
225 [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'
228 # PKG_EXT: if you add a package to $PACKAGES in any dialog {
229 # and it uses/requires some additional packages,
230 # you can add them here to keep it simple: [package]="extra"
231 # duplicates are removed with `uniq` before install
235 [mupdf]='mupdf-tools'
236 [qt5ct]='qt5-styleplugins'
237 [vlc]='qt5ct qt5-styleplugins'
238 [zathura]='zathura-pdf-poppler'
239 [noto-fonts]='noto-fonts-emoji'
240 [cairo-dock]='cairo-dock-plug-ins'
241 [qutebrowser]='qt5ct qt5-styleplugins'
242 [qbittorrent]='qt5ct qt5-styleplugins'
243 [transmission-qt]='qt5ct qt5-styleplugins'
244 [kdenlive]='kdebase-meta dvdauthor frei0r-plugins breeze breeze-gtk qt5ct qt5-styleplugins'
252 # Basics (somewhat in order)
253 _keymap="\nPick which keymap to use for the system from the list below\n\nThis is used once a graphical environment is running (Xorg).\n\nSystem default: us"
254 _vconsole="\nSelect the console keymap, the console is the tty shell you reach before starting a graphical environment (Xorg).\n\nIts keymap is seperate from the one used by the graphical environments, though many do use the same such as 'us' English.\n\nSystem default: us"
255 _device="\nSelect a device to use from the list below.\n\nDevices (/dev) are the available drives on the system. /sda, /sdb, /sdc ..."
256 _resize="\nSelect a new filesystem size in MB, a new partition will be created from the free space but will be left unformatted.\nThe lowest size is just enough to fit the currently in use space on the partition while the default is set to split the free space evenly.\n\nUse Tab or the arrow keys move the cursor between the buttons and the value, when the cursor is on the value, you can edit it by:\n\n - left/right cursor movement to select a digit to modify\n - +/- characters to increment/decrement the digit by one\n - 0 through 9 to set the digit to the given value\n\nSome keys are also recognized in all cursor positions:\n\n - Home/End set the value to its maximum or minimum\n - Pageup/Pagedown increment the value so that the slider moves by one column."
257 _mount="\nUse [Space] to toggle mount options from below, press [Enter] when done to confirm selection.\n\nNot selecting any and confirming will run an automatic mount."
258 _warn="\nIMPORTANT:\n\nChoose carefully when editing, formatting, and mounting partitions or your DATA MAY BE LOST.\n\nTo mount a partition without formatting it, select 'skip' when prompted to choose a filesystem during the mounting stage.\nThis can only be used for partitions that already contain a filesystem and cannot be the root (/) partition, it needs to be formatted before install.\n"
259 _part="\nFull device auto partitioning is available for beginners otherwise cfdisk is recommended.\n\n - All systems will require a root partition (8G or greater).\n - UEFI (and BIOS using LUKS without LVM) require a separate boot partition (100-512M)."
260 _uefi="\nSelect the EFI boot partition (/boot), required for UEFI boot.\n\nIt's usually the first partition on the device, 100-512M, and will be formatted as vfat/fat32 if not already."
261 _bios="\nDo you want to use a separate boot partition? (optional)\n\nIt's usually the first partition on the device, 100-512M, and will be formatted as ext3/4 if not already."
262 _biosluks="\nSelect the boot partition (/boot), required for LUKS.\n\nIt's usually the first partition on the device, 100-512M, and will be formatted as ext3/4 if not already."
263 _format="is already formatted correctly.\n\nFor a clean install, previously existing partitions should be reformatted, however this removes ALL data (bootloaders) on the partition so choose carefully.\n\nDo you want to reformat the partition?\n"
264 _swapsize="\nEnter the size of the swapfile in megabytes (M) or gigabytes (G).\n\neg. 100M will create a 100 megabyte swapfile, while 10G will create a 10 gigabyte swapfile.\n\nFor ease of use and as an example it is filled in to match the size of your system memory (RAM).\n\nMust be greater than 1, contain only whole numbers, and end with either M or G."
265 _expart="\nYou can now choose any additional partitions you want mounted, you'll be asked for a mountpoint after.\n\nSelect 'done' to finish the mounting step and begin unpacking the base system in the background."
266 _exmnt="\nWhere do you want the partition mounted?\n\nEnsure the name begins with a slash (/).\nExamples include: /usr, /home, /var, etc."
267 _user="\nEnter a name and password for the new user account.\n\nThe name must not use capital letters, contain any periods (.), end with a hyphen (-), or include any colons (:)\n\nNOTE: Use the [Up] and [Down] arrows to switch between input fields, [Tab] to toggle between input fields and the buttons, and [Enter] to accept."
268 _hostname="\nEnter a hostname for the new system.\n\nA hostname is used to identify systems on the network.\n\nIt's restricted to alphanumeric characters (a-z, A-Z, 0-9).\nIt can contain hyphens (-) BUT NOT at the beggining or end."
269 _locale="\nLocale determines the system language and currency formats.\n\nThe format for locale names is languagecode_COUNTRYCODE\n\neg. en_US is: english United States\n en_GB is: english Great Britain"
270 _timez="\nThe time zone is used to set the system clock.\n\nSelect your country or continent from the list below"
271 _timesubz="\nSelect the nearest city to you or one with the same time zone.\n\nTIP: Pressing the first letter of the city name repeatedly will navigate between entries beggining with that letter."
272 _sessions="\nUse [Space] to toggle available sessions, use [Enter] to accept the selection and continue.\n\nA basic package set will be installed for compatibility and functionality."
273 _login="\nSelect which of your session choices to use for the initial login.\n\nYou can be change this later by editing your ~/.xinitrc"
274 _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."
275 _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."
278 _luksnew="Basic LUKS Encryption"
279 _luksadv="Advanced LUKS Encryption"
280 _luksopen="Open Existing LUKS Partition"
281 _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."
282 _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."
283 _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)."
286 _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."
287 _lvmnew="Create Volume Group and Volume(s)"
288 _lvmdel="Delete an Existing Volume Group"
289 _lvmdelall="Delete ALL Volume Group(s) and Volume(s)"
290 _lvmvgname="\nEnter a name for the volume group (VG) being created from the partition(s) selected."
291 _lvmlvname="\nEnter a name for the logical volume (LV) being created.\n\nThis is similar to setting a label for a partition."
292 _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."
293 _lvmdelask="\nConfirm deletion of volume group(s) and logical volume(s).\n\nDeleting a volume group, will delete all logical volumes within it.\n"
296 _errexpart="\nCannot mount partition due to a problem with the mountpoint.\n\nEnsure it begins with a slash (/) followed by atleast one character.\n"
297 _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"
298 _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"
299 _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"
300 _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"
301 _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"
302 _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"
308 ###############################################################################
313 (( SEL < 12 )) && (( SEL++ ))
315 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Prepare " --default-item $SEL --cancel-label 'Exit' --menu "$_prep" 0 0 0 \
316 1 "Device tree (optional)" \
317 2 "Partitioning (optional)" \
318 3 "LUKS setup (optional)" \
319 4 "LVM setup (optional)" \
320 5 "Mount partitions" \
321 6 "System bootloader" \
322 7 "User and password" \
323 8 "System configuration" \
324 9 "Select WM/DE (optional)" \
325 10 "Select Packages (optional)" \
326 11 "View configuration (optional)" \
327 12 "Start the installation" 2>"$ANS"
330 [[ -z $WARN && $SEL =~ (2|5) ]] && { msg "Data Warning" "$_warn"; WARN=true; }
333 2) part_menu || (( SEL-- )) ;;
334 3) luks_menu || (( SEL-- )) ;;
335 4) lvm_menu || (( SEL-- )) ;;
336 5) select_menu || (( SEL-- )) ;;
337 6) prechecks 0 && { select_boot || (( SEL-- )); } ;;
338 7) prechecks 1 && { select_mkuser || (( SEL-- )); } ;;
339 8) prechecks 2 && { select_config || (( SEL-- )); } ;;
340 9) prechecks 3 && { select_sessions || (( SEL-- )); } ;;
341 10) prechecks 3 && { select_packages || (( SEL-- )); } ;;
342 11) prechecks 3 && select_show ;;
343 12) prechecks 3 && install_main ;;
344 *) yesno "Exit" "\nUnmount partitions (if any) and exit the installer?\n" && die 0
350 if [[ $SYS == 'BIOS' ]]; then
351 dlg BOOTLDR menu "BIOS Bootloader" "\nSelect which bootloader to use." \
352 "grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
353 "syslinux" "A collection of boot loaders for booting drives, CDs, or over the network" || return 1
355 dlg BOOTLDR menu "UEFI Bootloader" "\nSelect which bootloader to use." \
356 "systemd-boot" "A simple UEFI boot manager which executes configured EFI images" \
357 "grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
358 "refind-efi" "A UEFI boot manager that aims to be platform neutral and simplify multi-boot" \
359 "efistub" "Boot the kernel image directly (no chainloading support)" \
360 "syslinux" "A collection of boot loaders for booting drives, CDs, or over the network (no chainloading support)" || return 1
368 local cmd="${BCMDS[$BOOTLDR]}"
369 local pkgs="${USER_PKGS// / } ${PACKAGES// / }"
370 [[ $BOOT_PART ]] && mnt="/$BOOTDIR"
371 [[ $INSTALL_WMS == *dwm* ]] && pkgs="dwm st dmenu $pkgs"
373 msg "Show Configuration" "
375 ---------- PARTITION CONFIGURATION ------------
377 Root: ${ROOT_PART:-none}
378 Boot: ${BOOT_PART:-${BOOT_DEV:-none}}
380 Swap: ${SWAP_PART:-none}
381 Size: ${SWAP_SIZE:-none}
386 Extra: ${EXMNTS:-${EXMNT:-none}}
387 Hooks: ${HOOKS:-none}
390 ---------- BOOTLOADER CONFIGURATION -----------
392 Bootloader: ${BOOTLDR:-none}
393 Mountpoint: ${mnt:-none}
394 Command: ${cmd:-none}
397 ------------ SYSTEM CONFIGURATION -------------
399 Locale: ${MYLOCALE:-none}
400 Keymap: ${KEYMAP:-none}
401 Hostname: ${MYHOST:-none}
402 Timezone: ${ZONE:-none}/${SUBZ:-none}
405 ------------ USER CONFIGURATION --------------
407 User: ${NEWUSER:-none}
408 Shell: ${MYSHELL:-none}
409 Session: ${LOGIN_WM:-none}
410 Autologin: ${AUTOLOGIN:-none}
411 Login Method: ${LOGIN_TYPE:-none}
414 ------------ PACKAGES AND MIRRORS -------------
416 Kernel: ${KERNEL:-none}
417 Sessions: ${INSTALL_WMS:-none}
418 Packages: $(print4 "${pkgs:-none}")
424 if [[ -z $LOGIN_TYPE ]]; then
425 dlg LOGIN_TYPE menu "Login Management" "\nSelect what kind of login management to use." \
426 "xinit" "Console login without a display manager" \
427 "lightdm" "Lightweight display manager with a gtk greeter" || return 1
430 if [[ $LOGIN_TYPE == 'lightdm' ]]; then
431 LOGIN_PKGS="lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings accountsservice"
432 EDIT_FILES[login]="/etc/lightdm/lightdm.conf /etc/lightdm/lightdm-gtk-greeter.conf"
435 if (( WM_NUM == 1 )); then
436 LOGIN_WM="${WM_SESSIONS[$INSTALL_WMS]}"
438 dlg LOGIN_WM menu "Login Management" "$_login" $LOGIN_CHOICES || return 1
439 LOGIN_WM="${WM_SESSIONS[$LOGIN_WM]}"
442 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"
443 yesno "Autologin" "$txt" && AUTOLOGIN=true || AUTOLOGIN=''
444 LOGIN_PKGS="xorg-xinit"
445 EDIT_FILES[login]="/home/$NEWUSER/.xinitrc /home/$NEWUSER/.xprofile"
454 until [[ $CONFIG_DONE ]]; do
457 dlg MYSHELL menu "Shell" "\nChoose which shell to use." \
458 /usr/bin/zsh 'A very advanced and programmable command interpreter (shell) for UNIX' \
459 /bin/bash 'The GNU Bourne Again shell, standard in many GNU/Linux distributions' \
460 /usr/bin/mksh 'The MirBSD Korn Shell - an enhanced version of the public domain ksh' || return 1
463 1) dlg MYHOST input "Hostname" "$_hostname" "${DIST,,}" limit || { i=0; continue; } ;;
464 2) dlg MYLOCALE menu "Locale" "$_locale" $LOCALES || { i=1; continue; } ;;
466 until [[ $ZONE && $SUBZ ]]; do
467 dlg ZONE menu "Timezone" "$_timez" America - Australia - Asia - Atlantic - Africa - Europe - Indian - Pacific - Arctic - Antarctica - || break
468 dlg SUBZ menu "Timezone" "$_timesubz" $(awk '/'"$ZONE"'\// {gsub(/'"$ZONE"'\//, ""); print $3 " - "}' /usr/share/zoneinfo/zone.tab | sort) || continue
469 yesno "Timezone" "\nConfirm time zone: $ZONE/$SUBZ\n" || unset ZONE
471 [[ $ZONE && $SUBZ ]] || { i=2; continue; } ;;
473 dlg KERNEL menu "Kernel" "\nChoose which kernel to use." \
474 linux 'Vanilla linux kernel and modules, with a few patches applied' \
475 linux-lts 'Long-term support (LTS) linux kernel and modules' \
476 linux-zen 'A effort of kernel hackers to provide the best kernel for everyday systems' \
477 linux-hardened 'A security-focused linux kernel with hardening patches to mitigate exploits' || { i=3; continue; }
482 (( i++ )) # progress through to the next choice
486 '/bin/bash') LOGINRC='.bash_profile' ;;
487 '/usr/bin/zsh') LOGINRC='.zprofile' ;;
488 '/usr/bin/mksh') LOGINRC='.profile' ;;
497 local v='' u='' p='' p2='' rp='' rp2=''
499 until [[ $NEWUSER ]]; do
502 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " User " --mixedform "$_user" 0 0 0 \
503 "Username:" 1 1 "$u" 1 11 "$COLUMNS" 0 0 \
504 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
505 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 \
506 "--- Root password, if left empty the user password will be used ---" 6 1 '' 6 68 "$COLUMNS" 0 2 \
507 "Password:" 8 1 '' 8 11 "$COLUMNS" 0 1 \
508 "Password2:" 9 1 '' 9 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
510 while read -r line; do
521 # root passwords empty, so use the user passwords
522 [[ -z $rp && -z $rp2 ]] && { rp="$p"; rp2="$p2"; }
524 # make sure a username was entered and that the passwords match
525 if [[ ${#u} -eq 0 || $u =~ \ |\' || $u =~ [^a-z0-9] ]]; then
526 msg "Invalid Username" "\nIncorrect user name.\n\nPlease try again.\n"; u=''
527 elif [[ -z $p ]]; then
528 msg "Empty Password" "\nThe user password cannot be left empty.\n\nPlease try again.\n"
529 elif [[ "$p" != "$p2" ]]; then
530 msg "Password Mismatch" "\nThe user passwords do not match.\n\nPlease try again.\n"
531 elif [[ "$rp" != "$rp2" ]]; then
532 msg "Password Mismatch" "\nThe root passwords do not match.\n\nPlease try again.\n"
544 dlg KEYMAP menu "Keyboard Layout" "$_keymap" \
545 us English cm English gb English au English gh English \
546 za English ng English ca French 'cd' French gn French \
547 tg French fr French de German at German ch German \
548 es Spanish latam Spanish br Portuguese pt Portuguese ma Arabic \
549 sy Arabic ara Arabic ua Ukrainian cz Czech ru Russian \
550 sk Slovak nl Dutch it Italian hu Hungarian cn Chinese \
551 tw Taiwanese vn Vietnamese kr Korean jp Japanese th Thai \
552 la Lao pl Polish se Swedish is Icelandic 'fi' Finnish \
553 dk Danish be Belgian in Indian al Albanian am Armenian \
554 bd Bangla ba Bosnian 'bg' Bulgarian dz Berber mm Burmese \
555 hr Croatian gr Greek il Hebrew ir Persian iq Iraqi \
556 af Afghani fo Faroese ge Georgian ee Estonian kg Kyrgyz \
557 kz Kazakh lt Lithuanian mt Maltese mn Mongolian ro Romanian \
558 no Norwegian rs Serbian si Slovenian tj Tajik lk Sinhala \
559 tr Turkish uz Uzbek ie Irish pk Urdu 'mv' Dhivehi \
560 np Nepali et Amharic sn Wolof ml Bambara tz Swahili \
561 ke Swahili bw Tswana ph Filipino my Malay tm Turkmen \
562 id Indonesian bt Dzongkha lv Latvian md Moldavian mao Maori \
563 by Belarusian az Azerbaijani mk Macedonian kh Khmer epo Esperanto \
564 me Montenegrin || return 1
566 if [[ $CMAPS == *"$KEYMAP"* ]]; then
569 dlg CMAP menu "Console Keymap" "$_vconsole" $CMAPS || return 1
572 if [[ $DISPLAY && $TERM != 'linux' ]]; then
573 setxkbmap "$KEYMAP" >/dev/null 2>&1
575 loadkeys "$CMAP" >/dev/null 2>&1
585 dlg INSTALL_WMS check "Sessions" "$_sessions\n" \
586 i3-gaps "A fork of i3wm with more features including gaps" "$(ofn i3-gaps "${INSTALL_WMS[*]}")" \
587 openbox "A lightweight, powerful, and highly configurable stacking wm" "$(ofn openbox "${INSTALL_WMS[*]}")" \
588 bspwm "A tiling wm that represents windows as the leaves of a binary tree" "$(ofn bspwm "${INSTALL_WMS[*]}")" \
589 dwm "A fork of dwm, with more layouts and features" "$(ofn dwm "${INSTALL_WMS[*]}")" \
590 fluxbox "A lightweight and highly-configurable window manager" "$(ofn fluxbox "${INSTALL_WMS[*]}")" \
591 gnome "A desktop environment that aims to be simple and easy to use" "$(ofn gnome "${INSTALL_WMS[*]}")" \
592 cinnamon "A desktop environment combining traditional desktop with modern effects" "$(ofn cinnamon "${INSTALL_WMS[*]}")" \
593 plasma "A kde software project currently comprising a full desktop environment" "$(ofn plasma "${INSTALL_WMS[*]}")" \
594 xfce4 "A lightweight and modular desktop environment based on gtk+2/3" "$(ofn xfce4 "${INSTALL_WMS[*]}")" || return 1
597 while IFS=' ' read -r i; do
599 done <<< "$INSTALL_WMS"
602 WM_PKGS="${INSTALL_WMS/dwm/}" # remove dwm from package list
603 WM_PKGS="${WM_PKGS// / }" # remove double spaces
604 WM_PKGS="${WM_PKGS# }" # remove leading space
606 # add archlabs base when choosing any session
607 [[ $WM_PKGS ]] && WM_PKGS+=" $AL_BASE_PKGS"
609 for i in $INSTALL_WMS; do
610 LOGIN_CHOICES+="$i - "
611 [[ ${WM_EXT[$i]} && $WM_PKGS != *"${WM_EXT[$i]}"* ]] && WM_PKGS+=" ${WM_EXT[$i]}"
614 select_login || return 1
615 [[ $WM_PKGS != *"$LOGIN_PKGS"* ]] && WM_PKGS+=" $LOGIN_PKGS"
617 while IFS=' ' read -r pkg; do
618 [[ $PACKAGES != *"$pkg"* ]] && PACKAGES+=" $pkg"
626 dlg USER_PKGS check " Packages " "$_packages" \
627 abiword "A Fully-featured word processor" "$(ofn abiword "${USER_PKGS[*]}")" \
628 alacritty "A cross-platform, GPU-accelerated terminal emulator" "$(ofn alacritty "${USER_PKGS[*]}")" \
629 atom "An open-source text editor developed by GitHub" "$(ofn atom "${USER_PKGS[*]}")" \
630 audacious "A free and advanced audio player based on GTK+" "$(ofn audacious "${USER_PKGS[*]}")" \
631 audacity "A program that lets you manipulate digital audio waveforms" "$(ofn audacity "${USER_PKGS[*]}")" \
632 cairo-dock "Light eye-candy fully themable animated dock" "$(ofn cairo-dock "${USER_PKGS[*]}")" \
633 calligra "A set of applications for productivity" "$(ofn calligra "${USER_PKGS[*]}")" \
634 chromium "An open-source web browser based on the Blink rendering engine" "$(ofn chromium "${USER_PKGS[*]}")" \
635 clementine "A modern music player and library organizer" "$(ofn clementine "${USER_PKGS[*]}")" \
636 cmus "A small, fast and powerful console music player" "$(ofn cmus "${USER_PKGS[*]}")" \
637 deadbeef "A GTK+ audio player for GNU/Linux" "$(ofn deadbeef "${USER_PKGS[*]}")" \
638 deluge "A BitTorrent client written in python" "$(ofn deluge "${USER_PKGS[*]}")" \
639 docky "Full fledged dock for opening applications and managing windows" "$(ofn docky "${USER_PKGS[*]}")" \
640 emacs "An extensible, customizable, self-documenting real-time display editor" "$(ofn emacs "${USER_PKGS[*]}")" \
641 epiphany "A GNOME web browser based on the WebKit rendering engine" "$(ofn epiphany "${USER_PKGS[*]}")" \
642 evince "A document viewer" "$(ofn evince "${USER_PKGS[*]}")" \
643 evolution "Manage your email, contacts and schedule" "$(ofn evolution "${USER_PKGS[*]}")" \
644 file-roller "Create and modify archives" "$(ofn file-roller "${USER_PKGS[*]}")" \
645 firefox "A popular open-source web browser from Mozilla" "$(ofn firefox "${USER_PKGS[*]}")" \
646 gcolor2 "A simple GTK+2 color selector" "$(ofn gcolor2 "${USER_PKGS[*]}")" \
647 geany "A fast and lightweight IDE" "$(ofn geany "${USER_PKGS[*]}")" \
648 geary "A lightweight email client for the GNOME desktop" "$(ofn geary "${USER_PKGS[*]}")" \
649 gimp "GNU Image Manipulation Program" "$(ofn gimp "${USER_PKGS[*]}")" \
650 gnome-disk-utility "Disk Management Utility" "$(ofn gnome-disk-utility "${USER_PKGS[*]}")" \
651 gnome-system-monitor "View current processes and monitor system state" "$(ofn gnome-system-monitor "${USER_PKGS[*]}")" \
652 gparted "A GUI frontend for creating and manipulating partition tables" "$(ofn gparted "${USER_PKGS[*]}")" \
653 gpick "Advanced color picker using GTK+ toolkit" "$(ofn gpick "${USER_PKGS[*]}")" \
654 gpicview "Lightweight image viewer" "$(ofn gpicview "${USER_PKGS[*]}")" \
655 guvcview "Capture video from camera devices" "$(ofn guvcview "${USER_PKGS[*]}")" \
656 hexchat "A popular and easy to use graphical IRC client" "$(ofn hexchat "${USER_PKGS[*]}")" \
657 inkscape "Professional vector graphics editor" "$(ofn inkscape "${USER_PKGS[*]}")" \
658 irssi "Modular text mode IRC client" "$(ofn irssi "${USER_PKGS[*]}")" \
659 kdenlive "A popular non-linear video editor for Linux" "$(ofn kdenlive "${USER_PKGS[*]}")" \
660 krita "Edit and paint images" "$(ofn krita "${USER_PKGS[*]}")" \
661 libreoffice-fresh "Full featured office suite" "$(ofn libreoffice-fresh "${USER_PKGS[*]}")" \
662 lollypop "A new music playing application" "$(ofn lollypop "${USER_PKGS[*]}")" \
663 mousepad "A simple text editor" "$(ofn mousepad "${USER_PKGS[*]}")" \
664 mpd "A flexible, powerful, server-side application for playing music" "$(ofn mpd "${USER_PKGS[*]}")" \
665 mpv "A media player based on mplayer" "$(ofn mpv "${USER_PKGS[*]}")" \
666 mupdf "Lightweight PDF and XPS viewer" "$(ofn mupdf "${USER_PKGS[*]}")" \
667 mutt "Small but very powerful text-based mail client" "$(ofn mutt "${USER_PKGS[*]}")" \
668 nautilus "The default file manager for Gnome" "$(ofn nautilus "${USER_PKGS[*]}")" \
669 ncmpcpp "A mpd client and almost exact clone of ncmpc with some new features" "$(ofn ncmpcpp "${USER_PKGS[*]}")" \
670 neovim "A fork of Vim aiming to improve user experience, plugins, and GUIs." "$(ofn neovim "${USER_PKGS[*]}")" \
671 nicotine+ "A graphical client for Soulseek" "$(ofn nicotine+ "${USER_PKGS[*]}")" \
672 noto-fonts "Google Noto fonts" "$(ofn noto-fonts "${USER_PKGS[*]}")" \
673 noto-fonts-cjk "Google Noto CJK fonts (Chinese, Japanese, Korean)" "$(ofn noto-fonts-cjk "${USER_PKGS[*]}")" \
674 obs-studio "Free opensource streaming/recording software" "$(ofn obs-studio "${USER_PKGS[*]}")" \
675 openshot "An open-source, non-linear video editor for Linux" "$(ofn openshot "${USER_PKGS[*]}")" \
676 opera "A Fast and secure, free of charge web browser from Opera Software" "$(ofn opera "${USER_PKGS[*]}")" \
677 pcmanfm "A fast and lightweight file manager based in Lxde" "$(ofn pcmanfm "${USER_PKGS[*]}")" \
678 pidgin "Multi-protocol instant messaging client" "$(ofn pidgin "${USER_PKGS[*]}")" \
679 plank "An elegant, simple, and clean dock" "$(ofn plank "${USER_PKGS[*]}")" \
680 qbittorrent "An advanced BitTorrent client" "$(ofn qbittorrent "${USER_PKGS[*]}")" \
681 qpdfview "A tabbed PDF viewer" "$(ofn qpdfview "${USER_PKGS[*]}")" \
682 qt5ct "GUI for managing Qt based application themes, icons, and fonts" "$(ofn qt5ct "${USER_PKGS[*]}")" \
683 qutebrowser "A keyboard-focused vim-like web browser based on Python and PyQt5" "$(ofn qutebrowser "${USER_PKGS[*]}")" \
684 rhythmbox "A Music playback and management application" "$(ofn rhythmbox "${USER_PKGS[*]}")" \
685 rxvt-unicode "A unicode enabled rxvt-clone terminal emulator" "$(ofn rxvt-unicode "${USER_PKGS[*]}")" \
686 sakura "A terminal emulator based on GTK and VTE" "$(ofn sakura "${USER_PKGS[*]}")" \
687 simplescreenrecorder "A feature-rich screen recorder" "$(ofn simplescreenrecorder "${USER_PKGS[*]}")" \
688 steam "A popular game distribution platform by Valve" "$(ofn steam "${USER_PKGS[*]}")" \
689 surf "A simple web browser based on WebKit2/GTK+" "$(ofn surf "${USER_PKGS[*]}")" \
690 terminator "Terminal emulator that supports tabs and grids" "$(ofn terminator "${USER_PKGS[*]}")" \
691 termite "A minimal VTE-based terminal emulator" "$(ofn termite "${USER_PKGS[*]}")" \
692 thunar "A modern file manager for the Xfce Desktop Environment" "$(ofn thunar "${USER_PKGS[*]}")" \
693 thunderbird "Standalone mail and news reader from mozilla" "$(ofn thunderbird "${USER_PKGS[*]}")" \
694 tilda "A GTK based drop down terminal for Linux and Unix" "$(ofn tilda "${USER_PKGS[*]}")" \
695 tilix "A tiling terminal emulator for Linux using GTK+ 3" "$(ofn tilix "${USER_PKGS[*]}")" \
696 transmission-cli "Free BitTorrent client CLI" "$(ofn transmission-cli "${USER_PKGS[*]}")" \
697 transmission-gtk "Free BitTorrent client GTK+ GUI" "$(ofn transmission-gtk "${USER_PKGS[*]}")" \
698 transmission-qt "Free BitTorrent client Qt GUI" "$(ofn transmission-qt "${USER_PKGS[*]}")" \
699 ttf-anonymous-pro "A family fixed-width fonts designed with code in mind" "$(ofn ttf-anonymous-pro "${USER_PKGS[*]}")" \
700 ttf-fira-code "Monospaced font with programming ligatures" "$(ofn ttf-fira-code "${USER_PKGS[*]}")" \
701 ttf-font-awesome "Iconic font designed for Bootstrap" "$(ofn ttf-font-awesome "${USER_PKGS[*]}")" \
702 ttf-hack "A hand groomed typeface based on Bitstream Vera Mono" "$(ofn ttf-hack "${USER_PKGS[*]}")" \
703 vlc "A free and open source cross-platform multimedia player" "$(ofn vlc "${USER_PKGS[*]}")" \
704 weechat "Fast, light and extensible IRC client" "$(ofn weechat "${USER_PKGS[*]}")" \
705 xarchiver "A GTK+ frontend to various command line archivers" "$(ofn xarchiver "${USER_PKGS[*]}")" \
706 xfce-terminal "A terminal emulator based in the Xfce Desktop Environment" "$(ofn xfce-terminal "${USER_PKGS[*]}")" \
707 xterm "The standard terminal emulator for the X window system" "$(ofn xterm "${USER_PKGS[*]}")" \
708 zathura "Minimalistic document viewer" "$(ofn zathura "${USER_PKGS[*]}")"
710 if [[ $USER_PKGS ]]; then
711 for i in $USER_PKGS; do
712 [[ ${PKG_EXT[$i]} && $USER_PKGS != *"${PKG_EXT[$i]}"* ]] && USER_PKGS+=" ${PKG_EXT[$i]}"
719 ###############################################################################
724 check_background_install || return 0
725 local device choice devhash
726 devhash="$(lsblk -f | base64)"
728 part_device || return 1
733 if [[ $DISPLAY && $TERM != 'linux' ]] && hash gparted >/dev/null 2>&1; then
734 dlg choice menu "Edit Partitions" "$_part" \
735 "auto" "Whole device automatic partitioning" \
736 "shrink" "Shrink an existing ext2/3/4 or ntfs partition to make room for a new partition" \
737 "gparted" "GUI front end to parted" \
738 "cfdisk" "Curses based variant of fdisk" \
739 "parted" "GNU partition editor" \
740 "fdisk" "Dialog-driven creation and manipulation of partitions" \
741 "done" "Return to the main menu" || return 0
743 dlg choice menu "Edit Partitions" "$_part" \
744 "auto" "Whole device automatic partitioning" \
745 "shrink" "Shrink an existing ext2/3/4 or ntfs partition to make room for a new partition" \
746 "cfdisk" "Curses based variant of fdisk" \
747 "parted" "GNU partition editor" \
748 "fdisk" "Dialog-driven creation and manipulation of partitions" \
749 "done" "Return to the main menu" || return 0
752 if [[ $choice == 'done' ]]; then
754 elif [[ $choice == 'shrink' ]]; then
755 part_shrink "$device"
756 elif [[ $choice == 'auto' ]]; then
757 local root_size txt table boot_fs
758 root_size=$(lsblk -lno SIZE "$device" | awk 'NR == 1 {
761 print ($1 * 1000 - 512) / 1000 "G"
767 txt="\nWARNING:\n\nALL data on $device will be destroyed and the following partitions will be created\n\n- "
768 if [[ $SYS == 'BIOS' ]]; then
769 table="msdos" boot_fs="ext4"
770 txt+="An $boot_fs boot partition with the boot flag enabled (512M)\n- "
772 table="gpt" boot_fs="fat32"
773 txt+="A $boot_fs efi boot partition (512M)\n- "
775 txt+="An ext4 partition using all remaining space ($root_size)\n\nDo you want to continue?\n"
776 yesno "Auto Partition" "$txt" && part_auto "$device" "$table" "$boot_fs" "$root_size"
782 if [[ $devhash != "$(lsblk -f | base64)" ]]; then
783 msg "Probing Partitions" "\nInforming the kernel of partition changes using partprobe.\n" 0
784 partprobe >/dev/null 2>&1
792 if [[ $IGNORE_DEV ]]; then
793 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk "!/$IGNORE_DEV/"' && /disk|part|lvm|crypt|NAME/')"
795 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk '/disk|part|lvm|crypt|NAME/')"
797 msg "Device Tree" "\n\n$txt\n\n"
802 if [[ $1 == "$MNT/swapfile" && $SWAP_SIZE ]]; then
803 fallocate -l $SWAP_SIZE "$1" 2>$ERR
804 errshow "fallocate -l $SWAP_SIZE $1"
805 chmod 600 "$1" 2>$ERR
806 errshow "chmod 600 $1"
808 mkswap "$1" >/dev/null 2>$ERR
810 swapon "$1" >/dev/null 2>$ERR
817 local device="$1" table="$2" boot_fs="$3" size="$4" dev_info=""
818 dev_info="$(parted -s "$device" print)"
820 msg "Auto Partition" "\nRemoving partitions on $device and setting table to $table\n" 1
823 while read -r PART; do
824 parted -s "$device" rm "$PART" >/dev/null 2>&1
825 done <<< "$(awk '/^ [1-9][0-9]?/ {print $1}' <<< "$dev_info" | sort -r)"
827 [[ $(awk '/Table:/ {print $3}' <<< "$dev_info") != "$table" ]] && parted -s "$device" mklabel "$table" >/dev/null 2>&1
829 msg "Auto Partition" "\nCreating a 512M $boot_fs boot partition.\n" 1
830 if [[ $SYS == "BIOS" ]]; then
831 parted -s "$device" mkpart primary "$boot_fs" 1MiB 513MiB >/dev/null 2>&1
833 parted -s "$device" mkpart ESP "$boot_fs" 1MiB 513MiB >/dev/null 2>&1
838 AUTO_BOOT_PART=$(lsblk -lno NAME,TYPE "$device" | awk 'NR==2 {print "/dev/" $1}')
840 if [[ $SYS == "BIOS" ]]; then
841 mkfs.ext4 -q "$AUTO_BOOT_PART" >/dev/null 2>&1
843 mkfs.vfat -F32 "$AUTO_BOOT_PART" >/dev/null 2>&1
846 msg "Auto Partition" "\nCreating a $size ext4 root partition.\n" 0
847 parted -s "$device" mkpart primary ext4 513MiB 100% >/dev/null 2>&1
849 AUTO_ROOT_PART="$(lsblk -lno NAME,TYPE "$device" | awk 'NR==3 {print "/dev/" $1}')"
850 mkfs.ext4 -q "$AUTO_ROOT_PART" >/dev/null 2>&1
852 FORMATTED+="$AUTO_BOOT_PART $AUTO_ROOT_PART "
853 msg "Auto Partition" "\nProcess complete.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$device")\n"
858 local regexp="$1" err=''
860 # string of partitions as /TYPE/PART SIZE
861 if [[ $IGNORE_DEV ]]; then
862 PARTS="$(lsblk -lno TYPE,NAME,SIZE |
863 awk "/$regexp/"' && !'"/$IGNORE_DEV/"' {
864 sub(/^part/, "/dev/")
865 sub(/^lvm|^crypt/, "/dev/mapper/")
869 PARTS="$(lsblk -lno TYPE,NAME,SIZE |
871 sub(/^part/, "/dev/")
872 sub(/^lvm|^crypt/, "/dev/mapper/")
877 # number of partitions total
879 while read -r line; do
883 # ensure we have enough partitions for the system and action type
885 'part|lvm|crypt') [[ $COUNT -lt 1 || ($SYS == 'UEFI' && $COUNT -lt 2) ]] && err="$_errpart" ;;
886 'part|crypt') (( COUNT < 1 )) && err="$_lvmerr" ;;
887 'part|lvm') (( COUNT < 2 )) && err="$_lukserr" ;;
890 # if there aren't enough partitions show the relevant error message
891 [[ $err ]] && { msg "Not Enough Partitions" "$err" 2; return 1; }
898 local part="$1" mountp="${MNT}$2" fs=""
899 fs="$(lsblk -lno FSTYPE "$part")"
902 if [[ $fs && ${FS_OPTS[$fs]} && $part != "$BOOT_PART" ]] && select_mntopts "$fs"; then
903 mount -o "$MNT_OPTS" "$part" "$mountp" >/dev/null 2>&1
905 mount "$part" "$mountp" >/dev/null 2>&1
908 part_mountconf "$part" "$mountp" || return 1
916 local part="$1" fs="$2" delay="$3"
918 msg "Format" "\nFormatting $part as $fs\n" 0
919 ${FS_CMDS[$fs]} "$part" >/dev/null 2>$ERR
920 errshow "${FS_CMDS[$fs]} $part" || return 1
929 local device="$1" fs=""
931 part_find "${device##*/}[^ ]" || return 1
932 (( COUNT == 1 )) && part="$(awk '{print $1}' <<< "${PARTS[@]}" )"
934 if (( COUNT == 1 )) || dlg part menu "Resize" "\nWhich partition on $device do you want to resize?" $PARTS && [[ $part ]]; then
935 fs=$(lsblk -lno FSTYPE "$part")
938 msg "Resize" "\nGathering device size info.\n" 0
940 # get device size info
942 end=$(parted -s "$device" unit KiB print | awk '/^\s*'"$num"'/ {print int($3)}') # part size in KiB
943 devsize=$(parted -s "$device" unit KiB print | awk '/Disk '"${device//\//\\/}"':/ {print int($3)}') # whole device size in KiB
945 # minimum in KiB (2^10)
948 mount "$part" $MNT >/dev/null 2>&1; sleep 0.5
949 min=$(df --output=used --block-size=KiB "$part" | awk 'NR == 2 {print int($1)}')
950 umount $MNT >/dev/null 2>&1
951 ntfs) min=$(ntfsresize -f -m "$part" | awk 'NR == 2 {print int(($NF * 1000 * 1000) / 1024)}') >/dev/null 2>&1 ;;
955 mbmin=$(((min / 1024) + 200))
956 mbend=$((end / 1024))
958 # get new size from user
960 if dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Resize: $part " --rangebox "$_resize" 17 "$COLUMNS" "$mbmin" "$mbend" $((mbend / 2)) 2>$ANS; then
961 (( (size = $(< "$ANS")) < mbend )) || return 1
962 size=$((size * 1024))
970 e2fsck -f "$part"; sleep 0.5
971 resize2fs -f "$part" ${size}K 2>$ERR # K=2^10 bytes
972 errshow "resize2fs -f $part ${size}K" || return 1
975 ntfsresize -fc "$part" || { 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"; return 1; }
976 ntfsresize -ff --size $(( (size * 1024) / 1000 ))k "$part" 2>$ERR # k=10^3 bytes
977 errshow "ntfsresize -f -s $(( (size * 1024) / 1000 ))k $part" || return 1
981 echo "filesystem shrunk successfully, now the partition"
983 parted "$device" resizepart "$num" ${size}KiB || return 1
987 if [[ $devsize == "$end" ]]; then
988 parted -s "$device" mkpart primary ext4 ${size}KiB 100% 2>$ERR
989 errshow "parted -s $device mkpart primary ext4 ${size}KiB 100%" || return 1
991 parted -s "$device" mkpart primary ext4 ${size}KiB ${end}KiB 2>$ERR
992 errshow "parted -s $device mkpart primary ext4 ${size}KiB ${end}KiB" || return 1
995 msg "Resize Complete" "\n$part has been successfully resized to $((size / 1024))M.\n"
997 *) msg "Invalid Filesystem: $fs" "\nResizing only supports ext and ntfs.\n\nFor unformatted partitions, cfdisk can be used.\n" ;;
1004 if [[ $DEV_COUNT -eq 1 && $SYS_DEVS ]]; then
1005 DEVICE="$(awk '{print $1}' <<< "$SYS_DEVS")"
1006 elif (( DEV_COUNT > 1 )); then
1008 dlg DEVICE menu "Boot Device" "\nSelect the device to use for bootloader install." $SYS_DEVS
1010 dlg DEVICE menu "Select Device" "$_device" $SYS_DEVS
1012 [[ $DEVICE ]] || return 1
1013 elif [[ $DEV_COUNT -lt 1 && ! $1 ]]; then
1014 msg "Device Error" "\nNo available devices.\n\nExiting..\n" 2; die 1
1017 [[ $1 ]] && BOOT_DEV="$DEVICE"
1024 BOOT_DEV="${BOOT_PART%[1-9]}"
1025 BOOT_PART_NUM="${BOOT_PART: -1}"
1026 [[ $BOOT_PART = /dev/nvme* ]] && BOOT_DEV="${BOOT_PART%p[1-9]}"
1027 if [[ $SYS == 'UEFI' ]]; then
1028 parted -s $BOOT_DEV set $BOOT_PART_NUM esp on >/dev/null 2>&1
1030 parted -s $BOOT_DEV set $BOOT_PART_NUM boot on >/dev/null 2>&1
1037 local part="$1" devs=""
1038 devs="$(lsblk -lno NAME,FSTYPE,TYPE)"
1040 # Identify if $part is LUKS+LVM, LVM+LUKS, LVM alone, or LUKS alone
1041 if lsblk -lno TYPE "$part" | grep -q 'crypt'; then
1043 LUKS_NAME="${part#/dev/mapper/}"
1045 for dev in $(awk '/lvm/ && /crypto_LUKS/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
1046 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1047 LUKS_DEV="$LUKS_DEV cryptdevice=$dev:$LUKS_NAME"
1048 LVM='logical volume'
1053 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
1054 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1055 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
1056 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
1061 elif lsblk -lno TYPE "$part" | grep -q 'lvm'; then
1062 LVM='logical volume'
1063 VNAME="${part#/dev/mapper/}"
1065 for dev in $(awk '/crypt/ && /lvm2_member/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
1066 if lsblk -lno NAME "$dev" | grep -q "$VNAME"; then
1067 LUKS_NAME="${dev/\/dev\/mapper\//}"
1072 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
1073 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1074 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
1075 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
1086 if (( COUNT > 0 )); then
1087 PARTS="$(sed "/${i//\//\\/}/d" <<< "$PARTS")"
1095 if grep -qw "$1" /proc/mounts; then
1096 msg "Mount Success" "\nPartition $1 mounted at $2\n" 1
1100 msg "Mount Fail" "\nPartition $1 failed to mount at $2\n" 2
1105 ###############################################################################
1110 check_background_install || return 0
1113 part_find 'part|lvm|crypt' || { SEL=2; return 1; }
1115 [[ $LUKS && $LUKS_PART ]] && part_countdec $LUKS_PART
1116 [[ $LVM && $LVM_PARTS ]] && part_countdec $LVM_PARTS
1118 select_root_partition || return 1
1120 if [[ $SYS == 'UEFI' ]]; then
1121 select_efi_partition || { BOOT_PART=''; return 1; }
1122 elif (( COUNT > 0 )); then
1123 select_boot_partition || { BOOT_PART=''; return 1; }
1126 if [[ $BOOT_PART ]]; then
1127 part_mount "$BOOT_PART" "/$BOOTDIR" && SEP_BOOT=true || return 1
1131 select_swap || return 1
1132 select_extra_partitions || return 1
1133 install_background || return 1
1140 dlg SWAP_PART menu "Swap Setup" "\nSelect whether to use a swapfile, swap partition, or none." \
1141 "none" "Don't allocate any swap space" \
1142 "swapfile" "Allocate $SYS_MEM at /swapfile" \
1145 if [[ -z $SWAP_PART || $SWAP_PART == "none" ]]; then
1148 elif [[ $SWAP_PART == "swapfile" ]]; then
1150 until [[ ${SWAP_SIZE:0:1} =~ [1-9] && ${SWAP_SIZE: -1} =~ (M|G) ]]; do
1151 (( 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
1152 dlg SWAP_SIZE input "Swap Setup" "$_swapsize" "$SYS_MEM" || { SWAP_PART=''; SWAP_SIZE=''; return 1; }
1155 part_swap "$MNT/$SWAP_PART"
1156 SWAP_PART="/$SWAP_PART"
1157 elif [[ $PARTS == *"$SWAP_PART"* ]]; then
1158 part_swap $SWAP_PART
1159 part_countdec $SWAP_PART
1160 SWAP_SIZE="$(lsblk -lno SIZE $SWAP_PART)"
1170 local fs="$1" opts=''
1171 local title="${fs^} Mount Options"
1173 for i in ${FS_OPTS[$fs]}; do
1177 until [[ $MNT_OPTS ]]; do
1178 dlg MNT_OPTS check "$title" "$_mount" $opts
1179 [[ $MNT_OPTS ]] || return 1
1180 MNT_OPTS="${MNT_OPTS// /,}"
1181 yesno "$title" "\nConfirm the following options: $MNT_OPTS\n" || MNT_OPTS=''
1190 until [[ $EXMNT ]]; do
1191 dlg EXMNT input "Extra Mount $part" "$_exmnt" "/" || return 1
1192 if [[ ${EXMNT:0:1} != "/" || ${#EXMNT} -le 1 || $EXMNT =~ \ |\' || $EXMNTS == *"$EXMNT"* ]]; then
1193 msg "Mountpoint Error" "$_errexpart"
1202 local part="$1" fs='' cur=''
1203 local txt="\nSelect which filesystem to use for: $part\n\nDefault: ext4"
1204 cur="$(lsblk -lno FSTYPE "$part" 2>/dev/null)"
1207 if [[ $cur && ($part != "$ROOT_PART" || $FORMATTED == *"$part"*) ]]; then
1208 dlg fs menu "Filesystem" "$txt\nCurrent: $cur" skip - ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1210 dlg fs menu "Filesystem" "$txt" ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1212 [[ $fs == 'skip' ]] && return 0
1213 yesno "Filesystem" "\nFormat $part as $fs?\n" || fs=''
1215 part_format "$part" "$fs"
1218 select_efi_partition()
1220 if (( COUNT == 1 )); then
1221 BOOT_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
1222 elif [[ $AUTO_BOOT_PART ]]; then
1223 BOOT_PART="$AUTO_BOOT_PART"
1224 return 0 # were done here
1226 dlg BOOT_PART menu "EFI Partition" "$_uefi" $PARTS
1229 [[ $BOOT_PART ]] || return 1
1231 if grep -q 'fat' <<< "$(fsck -N "$BOOT_PART")"; then
1232 local txt="\nIMPORTANT:\n\nThe EFI partition $BOOT_PART $_format"
1233 if yesno "Format EFI Partition" "$txt" "Format $BOOT_PART" "Skip Formatting" 1; then
1234 part_format "$BOOT_PART" "vfat" 2
1237 part_format "$BOOT_PART" "vfat" 2
1243 select_boot_partition()
1245 if [[ $AUTO_BOOT_PART && ! $LVM ]]; then
1246 BOOT_PART="$AUTO_BOOT_PART"; return 0 # were done here
1247 elif [[ $LUKS && ! $LVM ]]; then
1248 dlg BOOT_PART menu "Boot Partition" "$_biosluks" $PARTS
1249 [[ $BOOT_PART ]] || return 1
1251 dlg BOOT_PART menu "Boot Partition" "$_bios" "skip" "don't use a separate boot" $PARTS
1252 [[ -z $BOOT_PART || $BOOT_PART == "skip" ]] && { BOOT_PART=''; return 0; }
1255 if grep -q 'ext[34]' <<< "$(fsck -N "$BOOT_PART")"; then
1256 local txt="\nIMPORTANT:\n\nThe boot partition $BOOT_PART $_format"
1257 if yesno "Format Boot Partition" "$txt" "Format $BOOT_PART" "Skip Formatting" 1; then
1258 part_format "$BOOT_PART" "ext4" 2
1261 part_format "$BOOT_PART" "ext4" 2
1266 select_root_partition()
1268 if [[ $AUTO_ROOT_PART && -z $LVM && -z $LUKS ]]; then
1269 ROOT_PART="$AUTO_ROOT_PART"
1270 elif (( COUNT == 1 )); then
1271 ROOT_PART="$(awk 'NR==1 {print $1}' <<< "$PARTS")"
1273 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
1275 [[ $ROOT_PART ]] || return 1
1277 select_filesystem "$ROOT_PART" || { ROOT_PART=''; return 1; }
1278 part_mount "$ROOT_PART" || { ROOT_PART=''; return 1; }
1283 select_extra_partitions()
1286 while (( COUNT > 0 )); do
1288 dlg part menu 'Mount Extra' "$_expart" 'done' 'finish mounting step' $PARTS || break
1289 if [[ $part == 'done' ]]; then
1291 elif select_filesystem "$part" && select_mountpoint && part_mount "$part" "$EXMNT"; then
1292 EXMNTS+="$part: $EXMNT "
1293 [[ $EXMNT == '/usr' && $HOOKS != *usr* ]] && HOOKS="usr $HOOKS"
1301 ###############################################################################
1309 genfstab -U $MNT >$MNT/etc/fstab 2>$ERR
1310 errshow 1 "genfstab -U $MNT >$MNT/etc/fstab"
1311 [[ -f $MNT/swapfile ]] && sed -i "s~${MNT}~~" $MNT/etc/fstab
1315 chrun "hwclock --systohc --utc" || chrun "hwclock --systohc --utc --directisa"
1318 chrun "chown -Rf $NEWUSER:users /home/$NEWUSER"
1322 dlg choice menu "Finalization" "$_edit" \
1323 finished "exit the installer and reboot" \
1324 keyboard "${EDIT_FILES[keyboard]}" \
1325 console "${EDIT_FILES[console]}" \
1326 locale "${EDIT_FILES[locale]}" \
1327 hostname "${EDIT_FILES[hostname]}" \
1328 sudoers "${EDIT_FILES[sudoers]}" \
1329 mkinitcpio "${EDIT_FILES[mkinitcpio]}" \
1330 fstab "${EDIT_FILES[fstab]}" \
1331 crypttab "${EDIT_FILES[crypttab]}" \
1332 bootloader "${EDIT_FILES[bootloader]}" \
1333 pacman "${EDIT_FILES[pacman]}" \
1334 login "${EDIT_FILES[login]}"
1336 if [[ -z $choice || $choice == 'finished' ]]; then
1337 [[ $DEBUG == true && -r $DBG ]] && vim $DBG
1341 for f in ${EDIT_FILES[$choice]}; do
1342 [[ -e ${MNT}$f ]] && exists+=" ${MNT}$f"
1344 if [[ $exists ]]; then
1347 msg "File Missing" "\nThe file(s) selected do not exist:\n\n${EDIT_FILES[$choice]}\n"
1355 if [[ $RSYNC_PID || $MIRROR_PID ]]; then
1356 while kill -0 "$RSYNC_PID" 2>/dev/null || kill -0 "$MIRROR_PID" 2>/dev/null; do
1357 clear; printf "\nOne or more background install processes are still running...\n"; sleep 1
1360 unset RSYNC_PID MIRROR_PID
1361 elif [[ -d /run/archiso/sfs/airootfs/etc/skel ]]; then
1362 rsync -ahv /run/archiso/sfs/airootfs/ $MNT/ 2>$ERR
1363 errshow 1 "rsync -ahv /run/archiso/sfs/airootfs/ $MNT/"
1364 install_mirrorlist "$MNT/etc/pacman.d/mirrorlist"
1365 chrun "pacman -Syyu --noconfirm && pacman -S $BASE_PKGS --needed --noconfirm"
1367 mkdir -p /etc/pacman.d/mirrorlist
1368 install_mirrorlist "/etc/pacman.d/mirrorlist"
1369 pacstrap $MNT base $ISO_BASE 2>$ERR
1370 errshow 1 "pacstrap $MNT base $KERNEL $ISO_BASE"
1371 mkdir -p $MNT/etc/pacman.d/mirrorlist
1372 cp -f "/etc/pacman.d/mirrorlist" "$MNT/etc/pacman.d/mirrorlist"
1373 chrun "pacman -Syyu --noconfirm && pacman -S $BASE_PKGS --needed --noconfirm"
1376 rm -rf $MNT/etc/mkinitcpio-archiso.conf
1377 find $MNT/usr/lib/initcpio -name 'archiso*' -type f -delete
1378 sed -i 's/volatile/auto/g' $MNT/etc/systemd/journald.conf
1379 find $MNT/boot -name '*-ucode.img' -delete
1382 find $MNT/etc/X11/xorg.conf.d/ -name '*.conf' -delete
1383 elif lspci | grep ' VGA ' | grep -q 'Intel'; then
1384 cat > $MNT/etc/X11/xorg.conf.d/20-intel.conf << EOF
1386 Identifier "Intel Graphics"
1388 Option "TearFree" "true"
1393 [[ -e /run/archiso/sfs/airootfs && $KERNEL == 'linux' ]] && cp -vf $RUN/x86_64/vmlinuz $MNT/boot/vmlinuz-linux
1395 cp -fv /etc/resolv.conf $MNT/etc/
1396 [[ -e /etc/NetworkManager/system-connections ]] && cp -rvf /etc/NetworkManager/system-connections $MNT/etc/NetworkManager/
1398 echo "LANG=$MYLOCALE" > $MNT/etc/locale.conf
1399 cp -f $MNT/etc/locale.conf $MNT/etc/default/locale
1400 sed -i "s/#en_US.UTF-8/en_US.UTF-8/g; s/#${MYLOCALE}/${MYLOCALE}/g" $MNT/etc/locale.gen
1402 chrun "ln -svf /usr/share/zoneinfo/$ZONE/$SUBZ /etc/localtime"
1404 if [[ $BROADCOM_WL ]]; then
1405 echo 'blacklist bcma' >> $MNT/etc/modprobe.d/blacklist.conf
1406 rm -f $MNT/etc/modprobe/
1409 cat > $MNT/etc/X11/xorg.conf.d/00-keyboard.conf << EOF
1410 # Use localectl(1) to instruct systemd-localed to update it.
1411 Section "InputClass"
1412 Identifier "system-keyboard"
1413 MatchIsKeyboard "on"
1414 Option "XkbLayout" "$KEYMAP"
1417 cat > $MNT/etc/default/keyboard << EOF
1418 # KEYBOARD CONFIGURATION FILE
1419 # Consult the keyboard(5) manual page.
1426 printf "KEYMAP=%s\nFONT=%s\n" "$CMAP" "$FONT" > $MNT/etc/vconsole.conf
1427 echo "$MYHOST" > $MNT/etc/hostname
1428 cat > $MNT/etc/hosts << EOF
1431 ::1 localhost ip6-localhost ip6-loopback
1432 ff02::1 ip6-allnodes
1433 ff02::2 ip6-allrouters
1439 if [[ $ROOT_PART == /dev/mapper* ]]; then
1440 ROOT_PART_ID="$ROOT_PART"
1442 local uuid_type="UUID"
1443 [[ $BOOTLDR =~ (systemd-boot|refind-efi|efistub) ]] && uuid_type="PARTUUID"
1444 ROOT_PART_ID="$uuid_type=$(blkid -s $uuid_type -o value $ROOT_PART)"
1447 if [[ $SYS == 'UEFI' ]]; then
1448 find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname "$DIST" -type d -delete
1449 find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname 'boot' -type d -delete
1453 chrun "${BCMDS[$BOOTLDR]}" 2>$ERR
1454 errshow 1 "${BCMDS[$BOOTLDR]}"
1456 if [[ -d $MNT/hostrun ]]; then
1457 umount $MNT/hostrun/udev >/dev/null 2>&1
1458 umount $MNT/hostrun/lvm >/dev/null 2>&1
1459 rm -rf $MNT/hostrun >/dev/null 2>&1
1462 if [[ $SYS == 'UEFI' ]]; then
1463 # some UEFI firmware requires a generic esp/BOOT/BOOTX64.EFI
1464 mkdir -pv $MNT/$BOOTDIR/EFI/BOOT
1465 if [[ $BOOTLDR == 'grub' ]]; then
1466 cp -fv $MNT/$BOOTDIR/EFI/$DIST/grubx64.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI
1467 elif [[ $BOOTLDR == 'syslinux' ]]; then
1468 cp -rf $MNT/$BOOTDIR/EFI/syslinux/* $MNT/$BOOTDIR/EFI/BOOT/
1469 cp -f $MNT/$BOOTDIR/EFI/syslinux/syslinux.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI
1470 elif [[ $BOOTLDR == 'refind-efi' ]]; then
1471 sed -i '/#extra_kernel_version_strings/ c extra_kernel_version_strings linux-hardened,linux-zen,linux-lts,linux' $MNT/$BOOTDIR/EFI/refind/refind.conf
1472 cp -fv $MNT/$BOOTDIR/EFI/refind/refind_x64.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI
1481 chrun "chpasswd <<< 'root:$ROOT_PASS'" 2>$ERR
1482 errshow 1 "set root password"
1483 if [[ $MYSHELL != *zsh ]]; then
1484 chrun "usermod -s $MYSHELL root" 2>$ERR
1485 errshow 1 "usermod -s $MYSHELL root"
1486 [[ $MYSHELL == "/usr/bin/mksh" ]] && cp -fv $MNT/etc/skel/.mkshrc /root/.mkshrc
1489 local groups='audio,autologin,floppy,log,network,rfkill,scanner,storage,optical,power,wheel'
1491 chrun "groupadd -r autologin" 2>$ERR
1492 errshow 1 "groupadd -r autologin"
1493 chrun "useradd -m -u 1000 -g users -G $groups -s $MYSHELL $NEWUSER" 2>$ERR
1494 errshow 1 "useradd -m -u 1000 -g users -G $groups -s $MYSHELL $NEWUSER"
1495 chrun "chpasswd <<< '$NEWUSER:$USER_PASS'" 2>$ERR
1496 errshow 1 "set $NEWUSER password"
1498 if [[ $USER_PKGS == *neovim* ]]; then
1499 mkdir -p $MNT/home/$NEWUSER/.config/nvim
1500 cp -fv $MNT/home/$NEWUSER/.vimrc $MNT/home/$NEWUSER/.config/nvim/init.vim
1501 cp -rfv $MNT/home/$NEWUSER/.vim/colors $MNT/home/$NEWUSER/.config/nvim/colors
1504 [[ $INSTALL_WMS == *dwm* ]] && install_suckless
1505 [[ $LOGIN_WM =~ (startkde|gnome-session) ]] && sed -i '/super/d' $MNT/home/$NEWUSER/.xprofile /root/.xprofile
1512 if [[ -e $MNT/home/$NEWUSER/.xinitrc ]] && grep -q 'exec' $MNT/home/$NEWUSER/.xinitrc; then
1513 sed -i "/exec/ c exec ${LOGIN_WM}" $MNT/home/$NEWUSER/.xinitrc
1515 printf "exec %s\n" "$LOGIN_WM" >> $MNT/home/$NEWUSER/.xinitrc
1518 [[ ${EDIT_FILES[login]} == *"$LOGINRC"* ]] || EDIT_FILES[login]+=" /home/$NEWUSER/$LOGINRC"
1520 if [[ $AUTOLOGIN ]]; then
1521 sed -i "s/root/${NEWUSER}/g" $SERVICE/autologin.conf
1522 cat > $MNT/home/$NEWUSER/$LOGINRC <<EOF
1524 # sourced by ${MYSHELL##*/} when used as a login shell
1526 # automatically run startx when logging in on tty1
1527 [[ -z \$DISPLAY && \$XDG_VTNR -eq 1 ]] && exec startx -- vt1
1531 rm -rf $MNT/home/$NEWUSER/.{profile,zprofile,bash_profile}
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
1564 local inpkg="$PACKAGES $USER_PKGS"
1566 if pacman -Qsq 'archlabs-installer' >/dev/null 2>&1; then
1567 rmpkg+=" archlabs-installer"
1568 elif [[ -e "$MNT/usr/bin/archlabs-installer" ]]; then
1569 rm -f "$MNT/usr/bin/archlabs-installer"
1572 [[ $UCODE ]] && inpkg+=" $UCODE"
1573 [[ $MYSHELL == *mksh ]] && inpkg+=" mksh"
1574 [[ $KERNEL == 'linux' ]] || { inpkg+=" $KERNEL"; rmpkg+=" linux"; }
1575 [[ $inpkg =~ (term|urxvt|tilix|alacritty|sakura|tilda|plasma|cinnamon) || $INSTALL_WMS == *dwm* ]] || inpkg+=" xterm"
1576 [[ $MYSHELL == '/usr/bin/zsh' ]] && inpkg+=" zsh-completions"
1577 [[ $INSTALL_WMS =~ ^(plasma|gnome|cinnamon)$ ]] || inpkg+=" archlabs-ksuperkey"
1578 [[ $INSTALL_WMS =~ (openbox|bspwm|i3-gaps|dwm|fluxbox) ]] && inpkg+=" $WM_BASE_PKGS"
1580 chrun "pacman -Syyu --noconfirm"
1581 [[ $rmpkg ]] && chrun "pacman -Rns $rmpkg --noconfirm"
1582 chrun "pacman -S iputils --noconfirm"
1583 chrun "pacman -Q xorg-xinit 2>/dev/null || pacman -S $BASE_PKGS --needed --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
1610 for i in dwm dmenu st; do
1611 if chrun "git clone https://git.suckless.org/$i /home/$NEWUSER/suckless/$i"; then
1612 chrun "cd /home/$NEWUSER/suckless/$i; make PREFIX=/usr install; make clean; rm config.h"
1614 printf "failed to clone %s repo\n" "$i"
1618 if [[ -d $MNT/home/$NEWUSER/suckless/dwm && -x $MNT/usr/bin/dwm ]]; then
1619 printf "To configure dwm edit %s\n" "/home/$NEWUSER/suckless/dwm/config.h"
1620 printf "You can then recompile it with 'sudo make clean install'\n"
1625 install_mkinitcpio()
1629 # luks keyfile creation
1630 # currently not used due to not prompting for passphrase on startup
1631 # [[ $LUKS_UUID && $LUKS_PASS && $SYS == 'UEFI' && $BOOTLDR == 'grub' ]] && luks_keyfile
1633 [[ $LUKS ]] && add="encrypt"
1634 [[ $LVM ]] && { [[ $add ]] && add+=" lvm2" || add+="lvm2"; }
1635 sed -i "s/block filesystems/block ${add} filesystems ${HOOKS}/g" $MNT/etc/mkinitcpio.conf
1636 chrun "mkinitcpio -p $KERNEL" 2>$ERR
1637 errshow 1 "mkinitcpio -p $KERNEL"
1640 install_mirrorlist()
1644 if hash reflector >/dev/null 2>&1; then
1645 reflector --score 120 -l 50 -f 5 --sort rate --save "$mfile"
1646 elif hash rankmirrors >/dev/null 2>&1; then
1647 i="$(json 'ip' "check&?access_key=5f29642060ab983b31fdf4c2935d8c56&fields=ip")"
1648 c="$(json 'country_code' "${i}?access_key=5f29642060ab983b31fdf4c2935d8c56&fields=country_code")"
1649 if [[ $c && $c =~ (CA|US) ]]; then
1650 m="https://www.archlinux.org/mirrorlist/?country=US&country=CA&use_mirror_status=on"
1652 m="https://www.archlinux.org/mirrorlist/?country=${c}&use_mirror_status=on"
1654 m="https://www.archlinux.org/mirrorlist/?country=US&country=CA&country=NZ&country=GB&country=AU&use_mirror_status=on"
1656 curl -s "$m" | sed -e 's/^#Server/Server/' -e '/^#/d' | rankmirrors -t -n 10 - | tail -n 10 >"$mfile"
1661 install_background()
1663 if [[ -d /run/archiso/sfs/airootfs/etc/skel ]] && grep -qw "$MNT" /proc/mounts && (grep -qw "$MNT/$BOOTDIR" /proc/mounts || [[ $SYS == 'BIOS' && -z $LUKS ]]); then
1664 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
1665 rsync -a /run/archiso/sfs/airootfs/ $MNT/ &
1667 ( install_mirrorlist "$MNT/etc/pacman.d/mirrorlist" && chrun "pacman -Syyu $BASE_PKGS --needed --noconfirm" ) &
1669 trap "kill $RSYNC_PID 2>/dev/null; kill $MIRROR_PID 2>/dev/null" EXIT
1674 ###############################################################################
1679 EDIT_FILES[bootloader]="/etc/default/grub"
1681 if [[ $SYS == 'BIOS' ]]; then
1682 [[ $BOOT_DEV ]] || { part_device 1 || return 1; }
1683 BCMDS[grub]="grub-install --recheck --force --target=i386-pc $BOOT_DEV"
1685 if [[ $ROOT_PART == */dev/mapper/* && -z $LVM && -z $LUKS_PASS ]]; then
1686 luks_pass "$_luksopen" 1 || return 1
1688 BCMDS[grub]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1689 grub-install --recheck --force --target=x86_64-efi --efi-directory=/$BOOTDIR --bootloader-id=$DIST"
1690 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1693 BCMDS[grub]="mkdir -p /run/udev /run/lvm &&
1694 mount --bind /hostrun/udev /run/udev &&
1695 mount --bind /hostrun/lvm /run/lvm &&
1697 grub-mkconfig -o /boot/grub/grub.cfg &&
1698 sleep 1 && umount /run/udev /run/lvm"
1705 sed -i "s/GRUB_DISTRIBUTOR=.*/GRUB_DISTRIBUTOR=\"${DIST}\"/g;
1706 s/GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT=\"\"/g" $MNT/etc/default/grub
1708 if [[ $LUKS_DEV ]]; then
1709 sed -i "s~#GRUB_ENABLE_CRYPTODISK~GRUB_ENABLE_CRYPTODISK~g;
1710 s~GRUB_CMDLINE_LINUX=.*~GRUB_CMDLINE_LINUX=\"${LUKS_DEV}\"~g" $MNT/etc/default/grub 2>$ERR
1711 errshow 1 "sed -i 's~#GRUB_ENABLE_CRYPTODISK~GRUB_ENABLE_CRYPTODISK~g;
1712 s~GRUB_CMDLINE_LINUX=.*~GRUB_CMDLINE_LINUX=\"${LUKS_DEV}\"~g' $MNT/etc/default/grub"
1715 if [[ $SYS == 'BIOS' && $LVM && -z $SEP_BOOT ]]; then
1716 sed -i "s/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g" $MNT/etc/default/grub 2>$ERR
1717 errshow 1 "sed -i 's/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g' $MNT/etc/default/grub"
1720 # setup for os-prober module
1721 mkdir -p /run/{lvm,udev}
1722 mkdir -p $MNT/hostrun/{lvm,udev}
1723 mount --bind /run/lvm $MNT/hostrun/lvm
1724 mount --bind /run/udev $MNT/hostrun/udev
1731 EDIT_FILES[bootloader]=""
1736 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1737 efibootmgr -v -d $BOOT_DEV -p $BOOT_PART_NUM -c -L '${DIST} Linux' -l /vmlinuz-${KERNEL} \
1738 -u 'root=$ROOT_PART_ID rw $([[ $UCODE ]] && printf 'initrd=\%s.img ' "$UCODE")initrd=\initramfs-${KERNEL}.img'"
1744 if [[ $SYS == 'BIOS' ]]; then
1745 EDIT_FILES[bootloader]="/boot/syslinux/syslinux.cfg"
1747 EDIT_FILES[bootloader]="/boot/EFI/syslinux/syslinux.cfg"
1748 BCMDS[syslinux]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1749 efibootmgr -v -c -d $BOOT_DEV -p $BOOT_PART_NUM -l /EFI/syslinux/syslinux.efi -L $DIST"
1756 local c="$MNT/boot/syslinux" s="/usr/lib/syslinux/bios" d=".."
1757 [[ $SYS == 'UEFI' ]] && { c="$MNT/boot/EFI/syslinux"; s="/usr/lib/syslinux/efi64/"; d=''; }
1759 mkdir -pv "$c" && cp -rfv $s/* "$c/" && cp -f "$RUN/syslinux/splash.png" "$c/"
1760 cat > "$c/syslinux.cfg" << EOF
1762 MENU TITLE $DIST Boot Menu
1763 MENU BACKGROUND splash.png
1767 # see: https://www.syslinux.org/wiki/index.php/Comboot/menu.c32
1776 MENU HELPMSGENDROW 29
1777 MENU COLOR border 30;44 #40ffffff #a0000000 std
1778 MENU COLOR title 1;36;44 #9033ccff #a0000000 std
1779 MENU COLOR sel 7;37;40 #e0ffffff #20ffffff all
1780 MENU COLOR unsel 37;44 #50ffffff #a0000000 std
1781 MENU COLOR help 37;40 #c0ffffff #a0000000 std
1782 MENU COLOR timeout_msg 37;40 #80ffffff #00000000 std
1783 MENU COLOR timeout 1;37;40 #c0ffffff #00000000 std
1784 MENU COLOR msg07 37;40 #90ffffff #a0000000 std
1785 MENU COLOR tabmsg 31;40 #30ffffff #00000000 std
1788 MENU LABEL $DIST Linux
1789 LINUX $d/vmlinuz-$KERNEL
1790 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1791 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL.img
1793 LABEL ${DIST}fallback
1794 MENU LABEL $DIST Linux Fallback
1795 LINUX $d/vmlinuz-$KERNEL
1796 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1797 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL-fallback.img
1798 $([[ $SYS == 'BIOS' ]] && printf "\n%s" "# examples of chainloading other bootloaders
1803 #APPEND file=$d/grub/boot.img
1815 EDIT_FILES[bootloader]="/boot/refind_linux.conf"
1816 BCMDS[refind-efi]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1822 cat > $MNT/boot/refind_linux.conf << EOF
1823 "$DIST Linux" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] &&
1824 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1825 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL.img"
1826 "$DIST Linux Fallback" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] &&
1827 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1828 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL-fallback.img"
1830 mkdir -p $MNT/etc/pacman.d/hooks
1831 cat > $MNT/etc/pacman.d/hooks/refind.hook << EOF
1838 Description = Updating rEFInd on ESP
1839 When = PostTransaction
1840 Exec = /usr/bin/refind-install
1844 setup_systemd-boot()
1846 EDIT_FILES[bootloader]="/boot/loader/entries/$DIST.conf"
1847 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1848 bootctl --path=/boot install"
1851 prerun_systemd-boot()
1853 mkdir -p $MNT/boot/loader/entries
1854 cat > $MNT/boot/loader/loader.conf << EOF
1859 cat > $MNT/boot/loader/entries/$DIST.conf << EOF
1861 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1862 initrd /initramfs-$KERNEL.img
1863 options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1865 cat > $MNT/boot/loader/entries/$DIST-fallback.conf << EOF
1866 title $DIST Linux Fallback
1867 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1868 initrd /initramfs-$KERNEL-fallback.img
1869 options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1871 mkdir -p $MNT/etc/pacman.d/hooks
1872 cat > $MNT/etc/pacman.d/hooks/systemd-boot.hook << EOF
1879 Description = Updating systemd-boot
1880 When = PostTransaction
1881 Exec = /usr/bin/bootctl update
1883 systemd-machine-id-setup --root="$MNT"
1887 ###############################################################################
1892 check_background_install || return 1
1895 dlg choice menu "Logical Volume Management" "$_lvmmenu" \
1896 "$_lvmnew" "vgcreate -f, lvcreate -L -n" \
1897 "$_lvmdel" "vgremove -f" \
1898 "$_lvmdelall" "lvrmeove, vgremove, pvremove -f" \
1899 "back" "return to the main menu"
1902 "$_lvmnew") lvm_create || return 1 ;;
1903 "$_lvmdel") lvm_delgroup && yesno "$_lvmdel" "$_lvmdelask" && vgremove -f "$DEL_VG" >/dev/null 2>&1 ;;
1904 "$_lvmdelall") lvm_del_all ;;
1913 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
1914 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
1915 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
1917 if [[ $VGROUP && $v && $pv ]]; then
1918 msg "Logical Volume Management" "\nActivating existing logical volume management (LVM).\n\n" 1
1919 modprobe dm-mod >/dev/null 2>$ERR
1920 errshow 'modprobe dm-mod'
1921 vgscan >/dev/null 2>&1
1922 vgchange -ay >/dev/null 2>&1
1928 VGROUP='' LVM_PARTS='' VGROUP_MB=0
1930 lvm_mkgroup || return 1
1931 local txt="\nThe last (or only) logical volume will automatically use all remaining space in the volume group."
1932 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
1933 [[ $VOL_COUNT ]] || return 1
1934 lvm_extra_lvs || return 1
1935 lvm_volume_name "$_lvmlvname\nNOTE: This LV will use up all remaining space in the volume group (${VGROUP_MB}MB)" || return 1
1936 lvcreate -l +100%FREE "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
1937 errshow "lvcreate -l +100%FREE $VGROUP -n $VNAME" || return 1
1938 LVM='logical volume'; sleep 0.5
1939 txt="\nDone, volume: $VGROUP-$VNAME (${VOLUME_SIZE:-${VGROUP_MB}MB}) has been created.\n"
1940 msg "$_lvmnew (LV:$VOL_COUNT)" "$txt\n$(lsblk -o NAME,MODEL,TYPE,FSTYPE,SIZE $LVM_PARTS)\n"
1946 local txt="${VGROUP}: ${SIZE}$SIZE_UNIT (${VGROUP_MB}MB remaining).$_lvmlvsize"
1950 dlg VOLUME_SIZE input "$_lvmnew (LV:$VOL_COUNT)" "$txt" ''
1951 if [[ -z $VOLUME_SIZE ]]; then
1953 break # allow bailing with escape or an empty choice
1954 elif (( ${VOLUME_SIZE:0:1} == 0 )); then
1955 ERR_SIZE=1 # size values can't begin with '0'
1957 # walk the string and make sure all but the last char are digits
1958 local lv=$((${#VOLUME_SIZE} - 1))
1959 for (( i=0; i<lv; i++ )); do
1960 [[ ${VOLUME_SIZE:$i:1} =~ [0-9] ]] || { ERR_SIZE=1; break; }
1962 if (( ERR_SIZE != 1 )); then
1963 case ${VOLUME_SIZE:$lv:1} in
1964 [mMgG]) local s=${VOLUME_SIZE:0:$lv} m=$((s * 1000))
1965 case ${VOLUME_SIZE:$lv:1} in
1966 [Gg]) (( m >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - m)) ;;
1967 [Mm]) (( ${VOLUME_SIZE:0:$lv} >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - s)) ;;
1974 if (( ERR_SIZE )); then
1975 msg "Invalid Logical Volume Size" "$_lvmerrlvsize"
1987 local txt="\nConfirm creation of volume group: $VGROUP\n\nwith the following partition(s):"
1989 until [[ $named ]]; do
1990 lvm_partitions || return 1
1991 lvm_group_name || return 1
1992 yesno "$_lvmnew" "$txt $LVM_PARTS\n" && named=true
1995 vgcreate -f "$VGROUP" $LVM_PARTS >/dev/null 2>$ERR
1996 errshow "vgcreate -f $VGROUP $LVM_PARTS" || return 1
1998 SIZE=$(vgdisplay "$VGROUP" | awk '/VG Size/ { gsub(/[^0-9.]/, ""); print int($0) }')
1999 SIZE_UNIT="$(vgdisplay "$VGROUP" | awk '/VG Size/ { print substr($NF, 0, 1) }')"
2001 if [[ $SIZE_UNIT == 'G' ]]; then
2002 VGROUP_MB=$((SIZE * 1000))
2007 msg "$_lvmnew" "\nVolume group: $VGROUP ($SIZE $SIZE_UNIT) has been created\n"
2014 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
2015 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
2016 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
2018 if [[ $VGROUP || $v || $pv ]]; then
2019 if yesno "$_lvmdelall" "$_lvmdelask"; then
2020 for i in $v; do lvremove -f "/dev/mapper/$i" >/dev/null 2>&1; done
2021 for i in $VGROUP; do vgremove -f "$i" >/dev/null 2>&1; done
2022 for i in $pv; do pvremove -f "$i" >/dev/null 2>&1; done
2026 msg "Delete LVM" "\nNo LVMs to remove...\n" 2
2036 for i in $(lvs --noheadings | awk '{print $2}' | uniq); do
2037 VOL_GROUP_LIST+="$i $(vgdisplay "$i" | awk '/VG Size/ {print $3$4}') "
2039 [[ $VOL_GROUP_LIST ]] || { msg "No Groups" "\nNo volume groups found."; return 1; }
2041 dlg DEL_VG menu "Logical Volume Management" "\nSelect volume group to delete.\n\nAll logical volumes within will also be deleted." $VOL_GROUP_LIST
2047 while (( VOL_COUNT > 1 )); do
2048 lvm_volume_name "$_lvmlvname" && get_lv_size || return 1
2049 lvcreate -L "$VOLUME_SIZE" "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
2050 errshow "lvcreate -L $VOLUME_SIZE $VGROUP -n $VNAME" || return 1
2051 msg "$_lvmnew (LV:$VOL_COUNT)" "\nDone, logical volume (LV) $VNAME ($VOLUME_SIZE) has been created.\n"
2059 part_find 'part|crypt' || return 1
2060 PARTS="$(awk 'NF > 0 {print $0 " off"}' <<< "$PARTS")"
2061 dlg LVM_PARTS check "$_lvmnew" "\nSelect the partition(s) to use for the physical volume (PV)." $PARTS
2068 until [[ $VGROUP ]]; do
2069 dlg VGROUP input "$_lvmnew" "$_lvmvgname" "mygroup"
2070 if [[ -z $VGROUP ]]; then
2072 elif [[ ${VGROUP:0:1} == "/" || $VGROUP =~ \ |\' ]] || lsblk | grep -q "$VGROUP"; then
2073 msg "LVM Name Error" "$_lvmerrvgname"
2083 local txt="$1" default="mainvolume"
2084 (( VOL_COUNT > 1 )) && default="extravolume$VOL_COUNT"
2085 until [[ $VNAME ]]; do
2086 dlg VNAME input "$_lvmnew (LV:$VOL_COUNT)" "\n$txt" "$default"
2087 if [[ -z $VNAME ]]; then
2089 elif [[ ${VNAME:0:1} == "/" || $VNAME =~ \ |\' ]] || lsblk | grep -q "$VNAME"; then
2090 msg "LVM Name Error" "$_lvmerlvname"
2097 ###############################################################################
2103 check_background_install || return 1
2104 dlg choice menu "LUKS Encryption" "$_luksmenu" \
2105 "$_luksnew" "cryptsetup -q luksFormat" \
2106 "$_luksopen" "cryptsetup open --type luks" \
2107 "$_luksadv" "cryptsetup -q -s -c luksFormat" \
2108 "back" "Return to the main menu"
2111 "$_luksnew") luks_basic || return 1 ;;
2112 "$_luksopen") luks_open || return 1 ;;
2113 "$_luksadv") luks_advanced || return 1 ;;
2121 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
2123 part_find 'part|crypt|lvm' || return 1
2125 if (( COUNT == 1 )); then
2126 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2128 dlg LUKS_PART menu "$_luksopen" "\nSelect which partition to open." $PARTS
2131 [[ $LUKS_PART ]] || return 1
2133 luks_pass "$_luksopen" || return 1
2134 msg "$_luksopen" "\nOpening encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2135 cryptsetup open --type luks "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2136 errshow "cryptsetup open --type luks $LUKS_PART $LUKS_NAME" || return 1
2137 LUKS='encrypted'; luks_show
2144 local t="$1" op="$2" v='' p='' p2=''
2146 until [[ $LUKS_PASS ]]; do
2150 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " $t " \
2151 --mixedform "\nEnter the password to decrypt $ROOT_PART\n\nThis is needed to create a keyfile." 0 0 0 \
2152 "Password:" 1 1 '' 1 11 "$COLUMNS" 0 1 \
2153 "Password2:" 2 1 '' 2 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
2156 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " $t " --mixedform "$_luksomenu" 0 0 0 \
2157 "Name:" 1 1 "${LUKS_NAME:-cryptroot}" 1 7 "$COLUMNS" 0 0 \
2158 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
2159 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
2163 while read -r line; do
2179 if [[ -z $op && -z $n ]]; then
2180 msg "Name Empty" "\nEncrypted device name cannot be empty.\n\nPlease try again.\n" 2
2181 elif [[ -z $p || "$p" != "$p2" ]]; then
2182 [[ $op ]] || LUKS_NAME="$n"
2183 msg "Password Mismatch" "\nThe passwords entered do not match.\n\nPlease try again.\n" 2
2185 [[ $op ]] || LUKS_NAME="$n"
2196 msg "$_luksnew" "\nEncrypted partition opened and ready for mounting.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$LUKS_PART")\n\n"
2201 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
2203 part_find 'part|lvm' || return 1
2205 if [[ $AUTO_ROOT_PART ]]; then
2206 LUKS_PART="$AUTO_ROOT_PART"
2207 elif (( COUNT == 1 )); then
2208 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2210 dlg LUKS_PART menu "$_luksnew" "\nSelect the partition you want to encrypt." $PARTS
2213 [[ $LUKS_PART ]] || return 1
2214 luks_pass "$_luksnew"
2219 luks_setup || return 1
2220 msg "$_luksnew" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2221 cryptsetup -q luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2222 errshow "cryptsetup -q luksFormat $LUKS_PART" || return 1
2223 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2224 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2225 LUKS='encrypted'; luks_show
2231 if [[ ! -e $MNT/crypto_keyfile.bin ]]; then
2232 # printf "Creating LUKS keyfile /crypto_keyfile.bin\n"
2234 n="$(lsblk -lno NAME,UUID,TYPE | awk "/$LUKS_UUID/"' && /part|crypt|lvm/ {print $1}')"
2235 local mkkey="dd bs=512 count=8 if=/dev/urandom of=/crypto_keyfile.bin"
2236 mkkey="$mkkey && chmod 000 /crypto_keyfile.bin"
2237 mkkey="$mkkey && cryptsetup luksAddKey /dev/$n /crypto_keyfile.bin <<< '$LUKS_PASS'"
2239 sed -i 's/FILES=()/FILES=(\/crypto_keyfile.bin)/g' $MNT/etc/mkinitcpio.conf 2>$ERR
2249 dlg cipher input "LUKS Encryption" "$_lukskey" "-s 512 -c aes-xts-plain64"
2250 [[ $cipher ]] || return 1
2251 msg "$_luksadv" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2252 cryptsetup -q $cipher luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2253 errshow "cryptsetup -q $cipher luksFormat $LUKS_PART" || return 1
2254 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2255 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2262 ###############################################################################
2267 [[ "$2" == *"$1"* ]] && printf "on" || printf "off"
2276 if [[ -d $MNT ]] && command cd /; then
2278 if (( exitcode == 127 )); then
2279 umount -l /run/archiso/bootmnt
2285 # restore custom linux console 0-15 colors when not rebooting
2286 if [[ $TERM == 'linux' ]]; then
2287 colors=("\e]P0191919" "\e]P1D15355" "\e]P2609960" "\e]P3FFCC66"
2288 "\e]P4255A9B" "\e]P5AF86C8" "\e]P62EC8D3" "\e]P7949494" "\e]P8191919" "\e]P9D15355"
2289 "\e]PA609960" "\e]PBFF9157" "\e]PC4E88CF" "\e]PDAF86C8" "\e]PE2ec8d3" "\e]PFE1E1E1")
2290 printf "%b" "${colors[@]}" && clear && unset col
2298 local var="$1" dialog_type="$2" title="$3" body="$4" n=0
2300 (( ($# / 2) > SHL )) && n=$SHL
2303 case "$dialog_type" in
2305 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --menu "$body" 0 0 $n "$@" 2>"$ANS" || return 1
2308 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --checklist "$body" 0 0 $n "$@" 2>"$ANS" || return 1
2314 if [[ $1 == 'limit' ]]; then
2315 dialog --backtitle "$DIST Installer - $SYS - v$VER" --max-input 63 --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2317 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2321 [[ -s "$ANS" ]] && printf -v "$var" "%s" "$(< "$ANS")"
2326 local title="$1" body="$2"
2328 if (( $# == 3 )); then
2329 dialog --backtitle "$DIST Installer - $SYS - v$VER" --sleep "$3" --title " $title " --infobox "$body\n" 0 0
2331 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --msgbox "$body\n" 0 0
2337 curl -s "http://api.ipstack.com/$2" | python3 -c "import sys, json; print(json.load(sys.stdin)['$1'])"
2342 local title="$1" body="$2" yes='Yes' no='No'
2343 (( $# >= 3 )) && local yes="$3"
2344 (( $# >= 4 )) && local no="$4"
2346 if (( $# == 5 )); then
2347 dialog --backtitle "$DIST Installer - $SYS - v$VER" --defaultno --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2349 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2355 arch-chroot "$MNT" bash -c "$1"
2360 export PS4='| ${BASH_SOURCE} LINE:${LINENO} FUNC:${FUNCNAME[0]:+ ${FUNCNAME[0]}()} |> '
2369 printf "\n^C caught, cleaning up...\n"
2376 if [[ $COLUMNS -ge 110 && ${#str} -gt $((COLUMNS - 30)) ]]; then
2378 i = 2; p1 = p2 = p3 = p4 = ""; p1 = $1; q = int(NF / 4)
2379 for (; i <= q; i++) { p1 = p1 " " $i }
2380 for (; i <= q * 2; i++) { p2 = p2 " " $i }
2381 for (; i <= q * 3; i++) { p3 = p3 " " $i }
2382 for (; i <= NF; i++) { p4 = p4 " " $i }
2383 printf "%s\n %s\n %s\n %s", p1, p2, p3, p4
2385 printf "%s\n" "$str"
2386 elif [[ $str ]]; then
2387 printf "%s\n" "$str"
2394 (( exit_code == 0 )) && return 0
2396 local fatal=0 err=""
2397 err="$(sed 's/[^[:print:]]//g; s/\[[0-9\;:]*\?m//g; s/==> //g; s/] ERROR:/]\nERROR:/g' "$ERR")"
2398 (( $1 == 1 )) && { fatal=1; shift; }
2399 local txt="\nThe command exited abnormally:\n\n$1\n\n"
2402 txt+="With the following message:\n\n$err\n\n"
2404 txt+="With no error message:\n\n"
2407 if (( fatal == 1 )); then
2408 txt+="Errors at this stage are fatal and the install cannot continue.\n"
2410 txt+="Errors at this stage are non-fatal and can be either fixed or ignored depending on the error.\n"
2413 msg "Install Error" "$txt"
2415 if (( fatal == 1 )); then
2416 [[ -r $DBG && $TERM == 'linux' ]] && less "$DBG"
2425 msg "Broadcom Wireless Setup" "\nDetected chipset is Broadcom BCM4352\n\nDisabling bcma/b43 modules and loading wl module.\n" 1
2426 { rmmod wl; rmmod bcma; rmmod b43; rmmod ssb; modprobe wl; depmod -a; } >/dev/null 2>&1
2432 if [[ $1 -ge 0 ]] && ! grep -qw "$MNT" /proc/mounts; then
2433 msg "Not Mounted" "\nPartition(s) must be mounted first.\n" 2
2436 elif [[ $1 -ge 1 && -z $BOOTLDR ]]; then
2437 msg "No Bootloader" "\nBootloader must be selected first.\n" 2
2440 elif [[ $1 -ge 2 && (-z $NEWUSER || -z $USER_PASS) ]]; then
2441 msg "No User" "\nA user must be created first.\n" 2
2444 elif [[ $1 -ge 3 && -z $CONFIG_DONE ]]; then
2445 msg "Not Configured" "\nSystem configuration must be done first.\n" 2
2455 [[ -d $1 ]] && umount -R "$1" >/dev/null 2>&1
2461 msg "Network Connect" "\nVerifying network connection\n" 1
2462 curl -sIN --connect-timeout 5 'https://www.archlinux.org/' | sed '1q' | grep -q '200'
2467 if chk_connect; then
2470 if hash nmtui >/dev/null 2>&1; then
2472 [[ $TERM == 'linux' ]] && printf "%b" "\e]P1191919" "\e]P4191919"
2474 [[ $TERM == 'linux' ]] && printf "%b" "\e]P1D15355" "\e]P4255a9b"
2484 IGNORE_DEV="$(lsblk -lno NAME,MOUNTPOINT | awk '/\/run\/archiso\/bootmnt/ {sub(/[1-9]/, ""); print $1}')"
2486 if [[ $IGNORE_DEV ]]; then
2487 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ && !'"/$IGNORE_DEV/"' {print "/dev/" $1 " " $2}')"
2489 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ {print "/dev/" $1 " " $2}')"
2492 if [[ -z $SYS_DEVS ]]; then
2493 msg "Device Error" "\nNo available devices...\n\nExiting..\n" 2
2498 while read -r line; do
2500 done <<< "$SYS_DEVS"
2507 elif grep -q 'AuthenticAMD' /proc/cpuinfo; then
2509 elif grep -q 'GenuineIntel' /proc/cpuinfo; then
2513 modprobe -q efivarfs >/dev/null 2>&1
2515 _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."
2516 if [[ -d /sys/firmware/efi/efivars ]]; then
2518 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars
2519 _prep+="\n - An EFI boot partition mounted."
2523 _prep+="\n\nOnce finished mounting, a portion of the install can be done in the background while you continue configuring the system:\n"
2524 _prep+="\n - Choose the system bootloader.\n - Create a user and password."
2525 _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."
2528 check_background_install()
2530 [[ $RSYNC_PID || $MIRROR_PID ]] || return 0
2531 msg "Install Running" "\nA background install process is currently running.\n" 2
2535 ###############################################################################
2538 if (( UID != 0 )); then
2539 msg "Not Root" "\nThis installer must be run as root or using sudo.\n\nExiting..\n" 2
2541 elif ! grep -qwm 1 'lm' /proc/cpuinfo; then
2542 msg "Not x86_64 Architecture" "\nThis installer only supports x86_64 architectures.\n\nExiting..\n" 2
2544 elif [[ $1 =~ (-d|--debug) ]]; then
2548 # trap ^C to perform cleanup
2554 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"
2556 select_keymap || { clear; die 0; }
2558 if lspci -vnn -d 14e4: | grep -q 'BCM4352'; then
2562 if ! net_connect; then
2563 msg "Not Connected" "\nThis installer requires an active internet connection.\n\nExiting..\n" 2
2571 # vim:fdm=marker:fmr={,}