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.49" # 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' # minor modification
144 [grub]='grub-install --recheck --force' # heavily modified
145 [syslinux]='syslinux-install_update -i -a -m' # modified on UEFI
146 [efistub]='efibootmgr -v -d /dev/sda -p 1 -c -l' # heavily modified
147 [systemd-boot]='bootctl --path=/boot install' # not modified
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, most are depends of the skel packages {
169 [plasma]='kdebase-meta' # base plasma application set
170 [bspwm]='' # see deps of bspwm-skel
171 [fluxbox]='' # see deps of fluxbox-skel
172 [i3-gaps]='' # see deps of i3-gaps-skel
173 [openbox]='' # see deps of openbox-skel
174 [xfce4]='xfce4-goodies' # see deps of xfce4-skel
177 # files that can be edited after install is complete {
178 declare -A EDIT_FILES=(
179 [login]='' # populated once we know the new username and shell
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 not added
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 [[ $MYSHELL == '/usr/bin/mksh' ]] && 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 [[ -x $MNT/usr/bin/X ]] || inpkg+=" $BASE_PKGS"
1583 if pacman -Qsq 'archlabs-installer' >/dev/null 2>&1; then
1584 rmpkg+=" archlabs-installer"
1585 elif [[ -e "$MNT/usr/bin/archlabs-installer" ]]; then
1586 rm -f "$MNT/usr/bin/archlabs-installer"
1589 # add extras or missed packages gathered throughout the install
1590 [[ $UCODE ]] && inpkg+=" $UCODE"
1591 [[ $KERNEL == 'linux' ]] || { inpkg+=" $KERNEL"; rmpkg+=" linux"; }
1592 [[ $MYSHELL == "/usr/bin/mksh" ]] && inpkg+=" mksh"
1593 if [[ $MYSHELL == '/usr/bin/zsh' ]]; then
1594 inpkg+=" zsh-completions"
1599 # packages only installed for certain WM/DE
1600 [[ $INSTALL_WMS =~ ^(plasma|gnome|cinnamon)$ ]] || inpkg+=" archlabs-ksuperkey"
1601 [[ $INSTALL_WMS =~ (openbox|bspwm|i3-gaps|dwm|fluxbox) ]] && inpkg+=" $WM_BASE_PKGS"
1603 # ensure a terminal gets installed
1604 [[ $inpkg =~ (term|urxvt|tilix|alacritty|sakura|tilda|plasma|cinnamon) || $INSTALL_WMS == *dwm* ]] || inpkg+=" xterm"
1606 # update fully first to avoid issues
1607 chrun "pacman -Syyu --noconfirm"
1609 # remove packages we no longer want
1610 [[ $rmpkg ]] && chrun "pacman -Rns $rmpkg --noconfirm"
1612 # for some reason the user has "no network" after install even though the
1613 # system is connected, reinstalling iputils fixes it
1614 chrun "pacman -S iputils --noconfirm"
1616 # install all the packages chosen throughout the install
1617 chrun "pacman -S $inpkg --needed --noconfirm" 2>$ERR
1618 errshow 1 "pacman -S $inpkg --needed --noconfirm"
1620 # extras for bootloaders
1621 if [[ $BOOTLDR == 'grub' ]]; then
1622 if [[ $SYS == 'BIOS' ]]; then
1623 chrun "pacman -S grub os-prober --needed --noconfirm" 2>$ERR
1624 errshow 1 "pacman -S grub os-prober --needed --noconfirm"
1626 chrun "pacman -S grub os-prober efibootmgr --needed --noconfirm" 2>$ERR
1627 errshow 1 "pacman -S grub os-prober efibootmgr --needed --noconfirm"
1629 elif [[ $BOOTLDR == 'refind-efi' ]]; then
1630 chrun "pacman -S refind-efi efibootmgr --needed --noconfirm" 2>$ERR
1631 errshow 1 "pacman -S refind-efi efibootmgr --needed --noconfirm"
1632 elif [[ $SYS == 'UEFI' ]]; then
1633 chrun "pacman -S efibootmgr --needed --noconfirm" 2>$ERR
1634 errshow 1 "pacman -S efibootmgr --needed --noconfirm"
1637 sed -i "s/# %wheel ALL=(ALL) ALL/%wheel ALL=(ALL) ALL/g" $MNT/etc/sudoers
1644 mkdir -pv $MNT/home/$NEWUSER/suckless
1646 for i in dwm dmenu st; do
1647 if chrun "git clone https://git.suckless.org/$i /home/$NEWUSER/suckless/$i"; then
1648 chrun "cd /home/$NEWUSER/suckless/$i; make PREFIX=/usr install; make clean; rm config.h"
1650 printf "failed to clone %s repo\n" "$i"
1654 if [[ -d $MNT/home/$NEWUSER/suckless/dwm && -x $MNT/usr/bin/dwm ]]; then
1655 printf "To configure dwm edit %s\n" "/home/$NEWUSER/suckless/dwm/config.h"
1656 printf "You can then recompile it with 'sudo make clean install'\n"
1661 install_mkinitcpio()
1665 # luks keyfile creation
1666 # currently not used due to not prompting for passphrase on startup
1667 # [[ $LUKS_UUID && $LUKS_PASS && $SYS == 'UEFI' && $BOOTLDR == 'grub' ]] && luks_keyfile
1669 [[ $LUKS ]] && add="encrypt"
1670 [[ $LVM ]] && { [[ $add ]] && add+=" lvm2" || add+="lvm2"; }
1671 sed -i "s/block filesystems/block ${add} filesystems ${HOOKS}/g" $MNT/etc/mkinitcpio.conf
1672 chrun "mkinitcpio -p $KERNEL" 2>$ERR
1673 errshow 1 "mkinitcpio -p $KERNEL"
1676 install_mirrorlist()
1678 local mfile="$1" # output mirrorlist file
1680 if hash reflector >/dev/null 2>&1; then
1681 reflector --score 120 -l 50 -f 5 --sort rate --save "$mfile"
1682 elif hash rankmirrors >/dev/null 2>&1; then
1683 ip_add="$(curl -fsSL "http://api.ipstack.com/check&?access_key=5f29642060ab983b31fdf4c2935d8c56&fields=ip" |
1684 python -c "import sys, json; print(json.load(sys.stdin)['ip'])")"
1685 country="$(curl -fsSL "http://api.ipstack.com/${ip_add}?access_key=5f29642060ab983b31fdf4c2935d8c56&fields=country_code" |
1686 python -c "import sys, json; print(json.load(sys.stdin)['country_code'])")"
1687 if [[ "$country" ]]; then
1688 if [[ $country =~ (CA|US) ]]; then
1689 mirror="https://www.archlinux.org/mirrorlist/?country=US&country=CA&use_mirror_status=on"
1690 elif [[ $country =~ (AU|NZ) ]]; then
1691 mirror="https://www.archlinux.org/mirrorlist/?country=AU&country=NZ&use_mirror_status=on"
1693 mirror="https://www.archlinux.org/mirrorlist/?country=${country}&use_mirror_status=on"
1696 mirror="https://www.archlinux.org/mirrorlist/?country=all&use_mirror_status=on"
1699 curl -fsSL "$mirror" | sed -e 's/^#Server/Server/' -e '/^#/d' | rankmirrors -n 6 - >"$mfile"
1705 install_background()
1707 if [[ -d /run/archiso/sfs/airootfs/etc/skel ]] && grep -qw "$MNT" /proc/mounts && (grep -qw "$MNT/$BOOTDIR" /proc/mounts || [[ $SYS == 'BIOS' && -z $LUKS ]]); then
1708 yesno "Background Install" "\nBegin install in the background?\n" || return 0
1709 rsync -a /run/archiso/sfs/airootfs/ $MNT/ &
1711 ( install_mirrorlist "$MNT/etc/pacman.d/mirrorlist" && sleep 1 && mkdir -p $MNT/var/lib/pacman && chrun "pacman -Syyu $BASE_PKGS --needed --noconfirm" >> /tmp/bg_out 2>&1 ) &
1713 # end the background processes before exiting
1714 trap "kill $RSYNC_PID $MIRROR_PID 2>/dev/null" EXIT
1719 ###############################################################################
1724 EDIT_FILES[bootloader]="/etc/default/grub"
1726 if [[ $SYS == 'BIOS' ]]; then
1727 [[ $BOOT_DEV ]] || { part_device 1 || return 1; }
1728 BCMDS[grub]="grub-install --recheck --force --target=i386-pc $BOOT_DEV"
1730 # if [[ $ROOT_PART == */dev/mapper/* && -z $LVM && -z $LUKS_PASS ]]; then
1731 # luks_pass "$_luksopen" 1 || return 1
1733 BCMDS[grub]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1734 grub-install --recheck --force --target=x86_64-efi --efi-directory=/$BOOTDIR --bootloader-id=$DIST"
1735 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1738 BCMDS[grub]="mkdir -p /run/udev /run/lvm &&
1739 mount --bind /hostrun/udev /run/udev &&
1740 mount --bind /hostrun/lvm /run/lvm &&
1742 grub-mkconfig -o /boot/grub/grub.cfg &&
1743 sleep 1 && umount /run/udev /run/lvm"
1750 sed -i "s/GRUB_DISTRIBUTOR=.*/GRUB_DISTRIBUTOR=\"${DIST}\"/g;
1751 s/GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT=\"\"/g" $MNT/etc/default/grub
1753 if [[ $LUKS_DEV ]]; then
1754 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 2>$ERR
1756 errshow 1 "sed -i 's~#GRUB_ENABLE_CRYPTODISK~GRUB_ENABLE_CRYPTODISK~g;
1757 s~GRUB_CMDLINE_LINUX=.*~GRUB_CMDLINE_LINUX=\"${LUKS_DEV}\"~g' $MNT/etc/default/grub"
1760 if [[ $SYS == 'BIOS' && $LVM && -z $SEP_BOOT ]]; then
1761 sed -i "s/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g" $MNT/etc/default/grub 2>$ERR
1762 errshow 1 "sed -i 's/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g' $MNT/etc/default/grub"
1765 # setup for os-prober module
1766 mkdir -p /run/{lvm,udev} $MNT/hostrun/{lvm,udev}
1767 mount --bind /run/lvm $MNT/hostrun/lvm
1768 mount --bind /run/udev $MNT/hostrun/udev
1775 EDIT_FILES[bootloader]=""
1780 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1781 efibootmgr -v -d $BOOT_DEV -p $BOOT_PART_NUM -c -L '${DIST} Linux' -l /vmlinuz-${KERNEL} \
1782 -u 'root=$ROOT_PART_ID rw $([[ $UCODE ]] && printf 'initrd=\%s.img ' "$UCODE")initrd=\initramfs-${KERNEL}.img'"
1787 if [[ $SYS == 'BIOS' ]]; then
1788 EDIT_FILES[bootloader]="/boot/syslinux/syslinux.cfg"
1790 EDIT_FILES[bootloader]="/boot/EFI/syslinux/syslinux.cfg"
1791 BCMDS[syslinux]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1792 efibootmgr -v -c -d $BOOT_DEV -p $BOOT_PART_NUM -l /EFI/syslinux/syslinux.efi -L $DIST"
1798 local c="$MNT/boot/syslinux" s="/usr/lib/syslinux/bios" d=".."
1799 [[ $SYS == 'UEFI' ]] && { c="$MNT/boot/EFI/syslinux"; s="/usr/lib/syslinux/efi64/"; d=''; }
1801 mkdir -pv "$c" && cp -rfv $s/* "$c/" && cp -f "$RUN/syslinux/splash.png" "$c/"
1802 cat > "$c/syslinux.cfg" << EOF
1804 MENU TITLE $DIST Boot Menu
1805 MENU BACKGROUND splash.png
1809 # see: https://www.syslinux.org/wiki/index.php/Comboot/menu.c32
1818 MENU HELPMSGENDROW 29
1819 MENU COLOR border 30;44 #40ffffff #a0000000 std
1820 MENU COLOR title 1;36;44 #9033ccff #a0000000 std
1821 MENU COLOR sel 7;37;40 #e0ffffff #20ffffff all
1822 MENU COLOR unsel 37;44 #50ffffff #a0000000 std
1823 MENU COLOR help 37;40 #c0ffffff #a0000000 std
1824 MENU COLOR timeout_msg 37;40 #80ffffff #00000000 std
1825 MENU COLOR timeout 1;37;40 #c0ffffff #00000000 std
1826 MENU COLOR msg07 37;40 #90ffffff #a0000000 std
1827 MENU COLOR tabmsg 31;40 #30ffffff #00000000 std
1830 MENU LABEL $DIST Linux
1831 LINUX $d/vmlinuz-$KERNEL
1832 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1833 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL.img
1835 LABEL ${DIST}fallback
1836 MENU LABEL $DIST Linux Fallback
1837 LINUX $d/vmlinuz-$KERNEL
1838 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1839 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL-fallback.img
1840 $([[ $SYS == 'BIOS' ]] && printf "\n%s" "# examples of chainloading other bootloaders
1845 #APPEND file=$d/grub/boot.img
1857 EDIT_FILES[bootloader]="/boot/refind_linux.conf"
1858 BCMDS[refind-efi]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1864 cat > $MNT/boot/refind_linux.conf << EOF
1865 "$DIST Linux" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] &&
1866 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1867 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL.img"
1868 "$DIST Linux Fallback" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] &&
1869 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1870 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL-fallback.img"
1872 mkdir -p $MNT/etc/pacman.d/hooks
1873 cat > $MNT/etc/pacman.d/hooks/refind.hook << EOF
1880 Description = Updating rEFInd on ESP
1881 When = PostTransaction
1882 Exec = /usr/bin/refind-install
1886 setup_systemd-boot()
1888 EDIT_FILES[bootloader]="/boot/loader/entries/$DIST.conf"
1889 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1890 bootctl --path=/boot install"
1893 prerun_systemd-boot()
1895 mkdir -p $MNT/boot/loader/entries
1896 cat > $MNT/boot/loader/loader.conf << EOF
1901 cat > $MNT/boot/loader/entries/$DIST.conf << EOF
1903 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1904 initrd /initramfs-$KERNEL.img
1905 options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1907 cat > $MNT/boot/loader/entries/$DIST-fallback.conf << EOF
1908 title $DIST Linux Fallback
1909 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1910 initrd /initramfs-$KERNEL-fallback.img
1911 options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1913 mkdir -p $MNT/etc/pacman.d/hooks
1914 cat > $MNT/etc/pacman.d/hooks/systemd-boot.hook << EOF
1921 Description = Updating systemd-boot
1922 When = PostTransaction
1923 Exec = /usr/bin/bootctl update
1925 systemd-machine-id-setup --root="$MNT"
1929 ###############################################################################
1934 is_bg_install || return 1
1937 dlg choice menu "Logical Volume Management" "$_lvmmenu" \
1938 "$_lvmnew" "vgcreate -f, lvcreate -L -n" \
1939 "$_lvmdel" "vgremove -f" \
1940 "$_lvmdelall" "lvrmeove, vgremove, pvremove -f" \
1941 "back" "return to the main menu"
1944 "$_lvmnew") lvm_create || return 1 ;;
1945 "$_lvmdel") lvm_delgroup && yesno "$_lvmdel" "$_lvmdelask" && vgremove -f "$DEL_VG" >/dev/null 2>&1 ;;
1946 "$_lvmdelall") lvm_del_all ;;
1955 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
1956 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
1957 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
1959 if [[ $VGROUP && $v && $pv ]]; then
1960 msg "Logical Volume Management" "\nActivating existing logical volume management (LVM).\n\n" 1
1961 modprobe dm-mod >/dev/null 2>$ERR
1962 errshow 'modprobe dm-mod'
1963 vgscan >/dev/null 2>&1
1964 vgchange -ay >/dev/null 2>&1
1970 VGROUP='' LVM_PARTS='' VGROUP_MB=0
1972 lvm_mkgroup || return 1
1973 local txt="\nThe last (or only) logical volume will automatically use all remaining space in the volume group."
1974 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
1975 [[ $VOL_COUNT ]] || return 1
1976 lvm_extra_lvs || return 1
1977 lvm_volume_name "$_lvmlvname\nNOTE: This LV will use up all remaining space in the volume group (${VGROUP_MB}MB)" || return 1
1978 lvcreate -l +100%FREE "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
1979 errshow "lvcreate -l +100%FREE $VGROUP -n $VNAME" || return 1
1980 LVM='logical volume'; sleep 0.5
1981 txt="\nDone, volume: $VGROUP-$VNAME (${VOLUME_SIZE:-${VGROUP_MB}MB}) has been created.\n"
1982 msg "$_lvmnew (LV:$VOL_COUNT)" "$txt\n$(lsblk -o NAME,MODEL,TYPE,FSTYPE,SIZE $LVM_PARTS)\n"
1988 local txt="${VGROUP}: ${SIZE}$SIZE_UNIT (${VGROUP_MB}MB remaining).$_lvmlvsize"
1992 dlg VOLUME_SIZE input "$_lvmnew (LV:$VOL_COUNT)" "$txt" ''
1993 if [[ -z $VOLUME_SIZE ]]; then
1995 break # allow bailing with escape or an empty choice
1996 elif (( ${VOLUME_SIZE:0:1} == 0 )); then
1997 ERR_SIZE=1 # size values can't begin with '0'
1999 # walk the string and make sure all but the last char are digits
2000 local lv=$((${#VOLUME_SIZE} - 1))
2001 for (( i=0; i<lv; i++ )); do
2002 [[ ${VOLUME_SIZE:$i:1} =~ [0-9] ]] || { ERR_SIZE=1; break; }
2004 if (( ERR_SIZE != 1 )); then
2005 case ${VOLUME_SIZE:$lv:1} in
2006 [mMgG]) local s=${VOLUME_SIZE:0:$lv} m=$((s * 1000))
2007 case ${VOLUME_SIZE:$lv:1} in
2008 [Gg]) (( m >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - m)) ;;
2009 [Mm]) (( ${VOLUME_SIZE:0:$lv} >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - s)) ;;
2016 if (( ERR_SIZE )); then
2017 msg "Invalid Logical Volume Size" "$_lvmerrlvsize"
2029 local txt="\nConfirm creation of volume group: $VGROUP\n\nwith the following partition(s):"
2031 until [[ $named ]]; do
2032 lvm_partitions || return 1
2033 lvm_group_name || return 1
2034 yesno "$_lvmnew" "$txt $LVM_PARTS\n" && named=true
2037 vgcreate -f "$VGROUP" $LVM_PARTS >/dev/null 2>$ERR
2038 errshow "vgcreate -f $VGROUP $LVM_PARTS" || return 1
2040 SIZE=$(vgdisplay "$VGROUP" | awk '/VG Size/ { gsub(/[^0-9.]/, ""); print int($0) }')
2041 SIZE_UNIT="$(vgdisplay "$VGROUP" | awk '/VG Size/ { print substr($NF, 0, 1) }')"
2043 if [[ $SIZE_UNIT == 'G' ]]; then
2044 VGROUP_MB=$((SIZE * 1000))
2049 msg "$_lvmnew" "\nVolume group: $VGROUP ($SIZE $SIZE_UNIT) has been created\n"
2056 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
2057 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
2058 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
2060 if [[ $VGROUP || $v || $pv ]]; then
2061 if yesno "$_lvmdelall" "$_lvmdelask"; then
2062 for i in $v; do lvremove -f "/dev/mapper/$i" >/dev/null 2>&1; done
2063 for i in $VGROUP; do vgremove -f "$i" >/dev/null 2>&1; done
2064 for i in $pv; do pvremove -f "$i" >/dev/null 2>&1; done
2068 msg "Delete LVM" "\nNo LVMs to remove...\n" 2
2078 for i in $(lvs --noheadings | awk '{print $2}' | uniq); do
2079 VOL_GROUP_LIST+="$i $(vgdisplay "$i" | awk '/VG Size/ {print $3$4}') "
2081 [[ $VOL_GROUP_LIST ]] || { msg "No Groups" "\nNo volume groups found."; return 1; }
2083 dlg DEL_VG menu "Logical Volume Management" "\nSelect volume group to delete.\n\nAll logical volumes within will also be deleted." $VOL_GROUP_LIST
2089 while (( VOL_COUNT > 1 )); do
2090 lvm_volume_name "$_lvmlvname" && get_lv_size || return 1
2091 lvcreate -L "$VOLUME_SIZE" "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
2092 errshow "lvcreate -L $VOLUME_SIZE $VGROUP -n $VNAME" || return 1
2093 msg "$_lvmnew (LV:$VOL_COUNT)" "\nDone, logical volume (LV) $VNAME ($VOLUME_SIZE) has been created.\n"
2101 part_find 'part|crypt' || return 1
2102 PARTS="$(awk 'NF > 0 {print $0 " off"}' <<< "$PARTS")"
2103 dlg LVM_PARTS check "$_lvmnew" "\nSelect the partition(s) to use for the physical volume (PV)." $PARTS
2110 until [[ $VGROUP ]]; do
2111 dlg VGROUP input "$_lvmnew" "$_lvmvgname" "mygroup"
2112 if [[ -z $VGROUP ]]; then
2114 elif [[ ${VGROUP:0:1} == "/" || $VGROUP =~ \ |\' ]] || lsblk | grep -q "$VGROUP"; then
2115 msg "LVM Name Error" "$_lvmerrvgname"
2125 local txt="$1" default="mainvolume"
2126 (( VOL_COUNT > 1 )) && default="extravolume$VOL_COUNT"
2127 until [[ $VNAME ]]; do
2128 dlg VNAME input "$_lvmnew (LV:$VOL_COUNT)" "\n$txt" "$default"
2129 if [[ -z $VNAME ]]; then
2131 elif [[ ${VNAME:0:1} == "/" || $VNAME =~ \ |\' ]] || lsblk | grep -q "$VNAME"; then
2132 msg "LVM Name Error" "$_lvmerlvname"
2139 ###############################################################################
2145 is_bg_install || return 1
2146 dlg choice menu "LUKS Encryption" "$_luksmenu" \
2147 "$_luksnew" "cryptsetup -q luksFormat" \
2148 "$_luksopen" "cryptsetup open --type luks" \
2149 "$_luksadv" "cryptsetup -q -s -c luksFormat" \
2150 "back" "Return to the main menu"
2153 "$_luksnew") luks_basic || return 1 ;;
2154 "$_luksopen") luks_open || return 1 ;;
2155 "$_luksadv") luks_advanced || return 1 ;;
2163 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
2165 part_find 'part|crypt|lvm' || return 1
2167 if (( COUNT == 1 )); then
2168 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2170 dlg LUKS_PART menu "$_luksopen" "\nSelect which partition to open." $PARTS
2173 [[ $LUKS_PART ]] || return 1
2175 luks_pass "$_luksopen" || return 1
2176 msg "$_luksopen" "\nOpening encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2177 cryptsetup open --type luks "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2178 errshow "cryptsetup open --type luks $LUKS_PART $LUKS_NAME" || return 1
2179 LUKS='encrypted'; luks_show
2186 local t="$1" op="$2" v='' p='' p2=''
2188 until [[ $LUKS_PASS ]]; do
2192 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " $t " \
2193 --mixedform "\nEnter the password to decrypt $ROOT_PART\n\nThis is needed to create a keyfile." 0 0 0 \
2194 "Password:" 1 1 '' 1 11 "$COLUMNS" 0 1 \
2195 "Password2:" 2 1 '' 2 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
2198 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " $t " --mixedform "$_luksomenu" 0 0 0 \
2199 "Name:" 1 1 "${LUKS_NAME:-cryptroot}" 1 7 "$COLUMNS" 0 0 \
2200 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
2201 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
2205 while read -r line; do
2221 if [[ -z $op && -z $n ]]; then
2222 msg "Name Empty" "\nEncrypted device name cannot be empty.\n\nPlease try again.\n" 2
2223 elif [[ -z $p || "$p" != "$p2" ]]; then
2224 [[ $op ]] || LUKS_NAME="$n"
2225 msg "Password Mismatch" "\nThe passwords entered do not match.\n\nPlease try again.\n" 2
2227 [[ $op ]] || LUKS_NAME="$n"
2238 msg "$_luksnew" "\nEncrypted partition opened and ready for mounting.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$LUKS_PART")\n\n"
2243 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
2245 part_find 'part|lvm' || return 1
2247 if [[ $AUTO_ROOT_PART ]]; then
2248 LUKS_PART="$AUTO_ROOT_PART"
2249 elif (( COUNT == 1 )); then
2250 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2252 dlg LUKS_PART menu "$_luksnew" "\nSelect the partition you want to encrypt." $PARTS
2255 [[ $LUKS_PART ]] || return 1
2256 luks_pass "$_luksnew"
2261 luks_setup || return 1
2262 msg "$_luksnew" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2263 cryptsetup -q luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2264 errshow "cryptsetup -q luksFormat $LUKS_PART" || return 1
2265 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2266 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2267 LUKS='encrypted'; luks_show
2273 if [[ ! -e $MNT/crypto_keyfile.bin ]]; then
2274 # printf "Creating LUKS keyfile /crypto_keyfile.bin\n"
2276 n="$(lsblk -lno NAME,UUID,TYPE | awk "/$LUKS_UUID/"' && /part|crypt|lvm/ {print $1}')"
2277 local mkkey="dd bs=512 count=8 if=/dev/urandom of=/crypto_keyfile.bin"
2278 mkkey="$mkkey && chmod 000 /crypto_keyfile.bin"
2279 mkkey="$mkkey && cryptsetup luksAddKey /dev/$n /crypto_keyfile.bin <<< '$LUKS_PASS'"
2281 sed -i 's/FILES=()/FILES=(\/crypto_keyfile.bin)/g' $MNT/etc/mkinitcpio.conf 2>$ERR
2291 dlg cipher input "LUKS Encryption" "$_lukskey" "-s 512 -c aes-xts-plain64"
2292 [[ $cipher ]] || return 1
2293 msg "$_luksadv" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2294 cryptsetup -q $cipher luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2295 errshow "cryptsetup -q $cipher luksFormat $LUKS_PART" || return 1
2296 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2297 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2304 ###############################################################################
2309 [[ "$2" == *"$1"* ]] && printf "on" || printf "off"
2318 if [[ -d $MNT ]] && command cd /; then
2320 if (( ecode == 127 )); then
2321 umount_dir /run/archiso/bootmnt
2332 local var="$1" dialog_type="$2" title="$3" body="$4" n=0
2334 (( ($# / 2) > SHL )) && n=$SHL
2337 case "$dialog_type" in
2338 menu) dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --menu "$body" 0 0 $n "$@" 2>"$ANS" || return 1 ;;
2339 check) dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --checklist "$body" 0 0 $n "$@" 2>"$ANS" || return 1 ;;
2344 if [[ $1 == 'limit' ]]; then
2345 dialog --backtitle "$DIST Installer - $SYS - v$VER" --max-input 63 --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2347 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2351 [[ -s "$ANS" ]] && printf -v "$var" "%s" "$(< "$ANS")"
2356 local title="$1" body="$2"
2358 if (( $# == 3 )); then
2359 dialog --backtitle "$DIST Installer - $SYS - v$VER" --sleep "$3" --title " $title " --infobox "$body\n" 0 0
2361 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --msgbox "$body\n" 0 0
2367 local title="$1" body="$2" yes='Yes' no='No'
2368 (( $# >= 3 )) && yes="$3"
2369 (( $# >= 4 )) && no="$4"
2371 if (( $# == 5 )); then
2372 dialog --backtitle "$DIST Installer - $SYS - v$VER" --defaultno --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2374 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2380 arch-chroot "$MNT" bash -c "$1"
2385 export PS4='| ${BASH_SOURCE} LINE:${LINENO} FUNC:${FUNCNAME[0]:+ ${FUNCNAME[0]}()} |> '
2394 printf "\n^C caught, cleaning up...\n"
2402 if [[ $COLUMNS -ge 110 && ${#str} -gt $((COLUMNS - 30)) ]]; then
2404 i = 2; p1 = p2 = p3 = p4 = ""; p1 = $1; q = int(NF / 4)
2405 for (; i <= q; i++) { p1 = p1 " " $i }
2406 for (; i <= q * 2; i++) { p2 = p2 " " $i }
2407 for (; i <= q * 3; i++) { p3 = p3 " " $i }
2408 for (; i <= NF; i++) { p4 = p4 " " $i }
2409 printf "%s\n %s\n %s\n %s", p1, p2, p3, p4
2411 printf "%s\n" "$str"
2412 elif [[ $str ]]; then
2413 printf "%s\n" "$str"
2420 "\e]P0191919" # #191919
2421 "\e]P1D15355" # #D15355
2422 "\e]P2609960" # #609960
2423 "\e]P3FFCC66" # #FFCC66
2424 "\e]P4255A9B" # #255A9B
2425 "\e]P5AF86C8" # #AF86C8
2426 "\e]P62EC8D3" # #2EC8D3
2427 "\e]P7949494" # #949494
2428 "\e]P8191919" # #191919
2429 "\e]P9D15355" # #D15355
2430 "\e]PA609960" # #609960
2431 "\e]PBFF9157" # #FF9157
2432 "\e]PC4E88CF" # #4E88CF
2433 "\e]PDAF86C8" # #AF86C8
2434 "\e]PE2ec8d3" # #2ec8d3
2435 "\e]PFE1E1E1" # #E1E1E1
2438 [[ $TERM == 'linux' ]] && printf "%b" "${colors[@]}" && clear
2443 [ $? -eq 0 ] && return 0
2445 local fatal=0 err=""
2446 err="$(sed 's/[^[:print:]]//g; s/\[[0-9\;:]*\?m//g; s/==> //g; s/] ERROR:/]\nERROR:/g' "$ERR")"
2448 (( $1 == 1 )) && { fatal=1; shift; }
2450 local txt="\nThe command exited abnormally:\n\n$1\n\n"
2453 txt+="With the following message:\n\n$err\n\n"
2455 txt+="With no error message:\n\n"
2458 if (( fatal )); then
2459 txt+="Errors at this stage are fatal and the install cannot continue.\n"
2461 txt+="Errors at this stage are non-fatal and can be either fixed or ignored depending on the error.\n"
2463 msg "Install Error" "$txt"
2465 if (( fatal )); then
2466 [[ -r $DBG && $TERM == 'linux' ]] && less "$DBG"
2475 msg "Broadcom Wireless Setup" "\nDetected chipset is Broadcom BCM4352\n\nDisabling bcma/b43 modules and loading wl module.\n" 1
2476 { rmmod wl; rmmod bcma; rmmod b43; rmmod ssb; modprobe wl; depmod -a; } >/dev/null 2>&1
2484 if (( $1 >= 0 )) && ! grep -qw "$MNT" /proc/mounts; then
2485 msg "Not Mounted" "\nPartition(s) must be mounted first.\n" 2
2487 elif [[ $1 -ge 1 && -z $BOOTLDR ]]; then
2488 msg "No Bootloader" "\nBootloader must be selected first.\n" 2
2490 elif [[ $1 -ge 2 && (-z $NEWUSER || -z $USER_PASS) ]]; then
2491 msg "No User" "\nA user must be created first.\n" 2
2493 elif [[ $1 -ge 3 && -z $CONFIG_DONE ]]; then
2494 msg "Not Configured" "\nSystem configuration must be done first.\n" 2
2497 (( i )) # return code
2502 mount | grep -q 'swap' && swapoff -a
2504 [[ -d $dir ]] || continue
2505 umount "$dir" 2>/dev/null || { sleep 0.5; umount -f "$dir" 2>/dev/null || umount -l "$dir"; }
2511 msg "Network Connect" "\nVerifying network connection\n" 1
2512 curl -sIN --connect-timeout 5 'https://www.archlinux.org/' | sed '1q' | grep -q '200'
2517 if chk_connect; then
2520 if hash nmtui >/dev/null 2>&1; then
2522 if [[ $TERM == 'linux' ]]; then
2523 printf "%b" "\e]P1191919" "\e]P4191919"
2525 printf "%b" "\e]P1D15355" "\e]P4255a9b"
2538 [[ $RSYNC_PID || $MIRROR_PID ]] || return 0
2539 msg "Install Running" "\nA background install process is currently running.\n" 2
2545 IGNORE_DEV="$(lsblk -lno NAME,MOUNTPOINT | awk '/\/run\/archiso\/bootmnt/ {sub(/[1-9]/, ""); print $1}')"
2547 if [[ $IGNORE_DEV ]]; then
2548 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ && !'"/$IGNORE_DEV/"' {print "/dev/" $1 " " $2}')"
2550 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ {print "/dev/" $1 " " $2}')"
2553 if [[ -z $SYS_DEVS ]]; then
2554 msg "Device Error" "\nNo available devices...\n\nExiting..\n" 2
2559 while read -r line; do
2561 done <<< "$SYS_DEVS"
2568 elif grep -q 'AuthenticAMD' /proc/cpuinfo; then
2570 elif grep -q 'GenuineIntel' /proc/cpuinfo; then
2574 modprobe -q efivarfs >/dev/null 2>&1
2576 _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."
2577 if [[ -d /sys/firmware/efi/efivars ]]; then
2579 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars
2580 _prep+="\n - An EFI boot partition mounted."
2584 _prep+="\n\nOnce finished mounting, a portion of the install can be done in the background while you continue configuring the system:\n"
2585 _prep+="\n - Choose the system bootloader.\n - Create a user and password."
2586 _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."
2589 ###############################################################################
2592 # enable some nicer colours in the linux console
2595 if (( UID != 0 )); then
2596 msg "Not Root" "\nThis installer must be run as root or using sudo.\n\nExiting..\n" 2
2598 elif ! grep -qwm 1 'lm' /proc/cpuinfo; then
2599 msg "Not x86_64 Architecture" "\nThis installer only supports x86_64 architectures.\n\nExiting..\n" 2
2601 elif [[ $1 =~ (-d|--debug) ]]; then
2605 # trap ^C to perform cleanup
2611 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"
2613 select_keymap || { clear; die 0; }
2615 if lspci -vnn -d 14e4: | grep -q 'BCM4352'; then
2619 if ! net_connect; then
2620 msg "Not Connected" "\nThis installer requires an active internet connection.\n\nExiting..\n" 2
2628 # vim:fdm=marker:fmr={,}