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
9 # linux distributor, if unset will be ArchLabs
10 # this can be set in the environment prior to install, eg.
12 # $ DIST="My Distro" archlabs-installer
14 # will result in "My Distro Linux" used where needed
18 VER="2.0.60" # installer version
19 MNT="/mnt" # install mountpoint
20 ANS="/tmp/ans" # dialog answer file
22 # ------------------------------------------------------ #
23 # When manually mounting your partitions, you need
24 # to set these values to avoid using the mount menu.
25 # ------------------------------------------------------ #
27 # root partition, eg. /dev/sda2
30 # boot partition, required on UEFI eg. /dev/sda1
33 # boot device, used for some bootloaders eg. /dev/sda
36 # bootloader to use, can be:
37 # UEFI: grub, syslinux, efistub, systemd-boot, refind-efi
38 # BIOS: grub, syslinux
41 # directory to mount the boot partition (if any) for most bootloaders
42 # this will need to be 'boot' however a popular one for grub is 'boot/efi'
45 # ------------------------------------------------------ #
47 # bulk default values {
49 # these values will be selected during the install, it is not recommended
50 # to edit them here unless you know what you're doing.
52 UCODE='' # cpu microcode (if any), can be: amd-ucode, intel-ucode
53 KERNEL='' # linux kernel, can be: linux, linux-lts, linux-zen, or linux-hardened
54 MYSHELL='' # full path for the shell, eg. /usr/bin/zsh
56 SWAP_PART='' # swap partition or file path
57 SWAP_SIZE='' # swap size, only used when creating a swapfile
59 EXMNT='' # holder for additional partitions while mounting
60 EXMNTS='' # when an extra partition is mounted append it's info
62 FONT="ter-i16n" # font used for the linux console
63 HOOKS="shutdown" # list of additional HOOKS to add in /etc/mkinitcpio.conf
65 LOGIN_TYPE='' # login manager can be: lightdm, xinit, ly
66 LOGIN_WM='' # default login session to be placed in ~/.xinitrc
67 LOGINRC='' # login shell rc file, eg. .zprofile, .bash_profile, .profile
69 INSTALL_WMS='' # space separated list of chosen wm/de
71 WM_PKGS='' # list of packages added during wm/de choice (not user edited)
72 PACKAGES='' # list of all packages to install including WM_PKGS (not user edited)
73 USER_PKGS='' # packages selected by the user during install
75 NEWUSER='' # username for the new user
76 USER_PASS='' # new user's password
77 ROOT_PASS='' # root password
79 LUKS='' # empty when not using encryption
80 LUKS_DEV='' # boot parameter string for LUKS
81 LUKS_PART='' # partition used for encryption
82 LUKS_PASS='' # encryption password
83 LUKS_UUID='' # encrypted partition UUID
84 LUKS_NAME='' # name used for encryption
86 LVM='' # empty when not using lvm
87 LVM_PARTS='' # partitions used for volume group
88 VGROUP_MB=0 # available space in volume group
90 WARN='' # issued mounting/partitioning warning
91 SEP_BOOT='' # separate boot partition for BIOS
92 AUTOLOGIN='' # enable autologin for xinit
93 CONFIG_DONE='' # basic configuration is finished
95 FORMATTED='' # partitions we formatted and should allow skipping
96 AUTO_ROOT_PART='' # root value from auto partition
97 AUTO_BOOT_PART='' # boot value from auto partition
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 sudo git gvfs gtk3 gtk-engines gtk-engine-murrine pavucontrol tumbler xdg-user-dirs "
104 BASE_PKGS+="playerctl ffmpeg gstreamer libmad libmatroska gst-libav gst-plugins-base gst-plugins-good scrot bash-completion"
106 # extras for window managers
107 WM_BASE_PKGS="arandr archlabs-networkmanager-dmenu nitrogen polkit-gnome volumeicon xclip exo laptop-detect "
108 WM_BASE_PKGS+="xdotool compton wmctrl gnome-keyring dunst feh gsimplecal xfce4-power-manager xfce4-settings"
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 {
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 # console keyboard mappings
131 CMAPS="$(find /usr/share/kbd/keymaps -name '*.map.gz' | awk '{gsub(/\.map\.gz|.*\//, ""); print $1 " - "}' | sort)"
134 [[ $LINES ]] || LINES=$(tput lines)
135 [[ $COLUMNS ]] || COLUMNS=$(tput cols)
141 # commands used to install each bootloader, however 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 used in ~/.xinitrc {
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 {
168 [cinnamon]='gnome-terminal' # doesn't install a terminal on it's own
169 [plasma]='kdebase-meta' # base plasma application set
170 [awesome]='archlabs-skel-awesome' # see deps of archlabs-skel-awesome
171 [bspwm]='archlabs-skel-bspwm' # see deps of archlabs-skel-bspwm
172 [fluxbox]='archlabs-skel-fluxbox' # see deps of archlabs-skel-fluxbox
173 [i3-gaps]='archlabs-skel-i3-gaps' # see deps of archlabs-skel-i3-gaps
174 [openbox]='archlabs-skel-openbox' # see deps of archlabs-skel-openbox
175 [xfce4]='archlabs-skel-xfce4 xfce4-goodies' # see deps of archlabs-skel-xfce4
178 # files offered for editing after install is complete {
179 declare -A EDIT_FILES=(
180 [login]='' # login is populated once we know the username and shell
182 [sudoers]='/etc/sudoers'
183 [crypttab]='/etc/crypttab'
184 [pacman]='/etc/pacman.conf'
185 [console]='/etc/vconsole.conf'
186 [mkinitcpio]='/etc/mkinitcpio.conf'
187 [hostname]='/etc/hostname /etc/hosts'
188 [bootloader]="/boot/loader/entries/$DIST.conf"
189 [locale]='/etc/locale.conf /etc/default/locale'
190 [keyboard]='/etc/X11/xorg.conf.d/00-keyboard.conf /etc/default/keyboard'
193 # mkfs command and flags for filesystem formatting {
198 [ntfs]='mkfs.ntfs -q'
199 [ext2]='mkfs.ext2 -q'
200 [ext3]='mkfs.ext3 -q'
201 [ext4]='mkfs.ext4 -q'
202 [vfat]='mkfs.vfat -F32'
203 [nilfs2]='mkfs.nilfs2 -q'
204 [reiserfs]='mkfs.reiserfs -q'
207 # mount options for each filesystem {
213 [jfs]='discard errors=continue errors=panic nointegrity'
214 [reiserfs]='acl nolog notail replayonly user_xattr off'
215 [ext4]='discard dealloc nofail noacl relatime noatime nobarrier nodelalloc'
216 [xfs]='discard filestreams ikeep largeio noalign nobarrier norecovery noquota wsync'
217 [nilfs2]='discard nobarrier errors=continue errors=panic order=relaxed order=strict norecovery'
218 [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'
221 # packages installed for each login option {
222 declare -A LOGIN_PKGS=(
227 [lightdm]='lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings accountsservice'
230 # extras installed for user selected packages {
231 # if a package requires additional packages that aren't already dependencies
232 # they can be added here eg. [package]="extra"
236 [mupdf]='mupdf-tools'
237 [qt5ct]='qt5-styleplugins'
238 [vlc]='qt5ct qt5-styleplugins'
239 [zathura]='zathura-pdf-poppler'
240 [noto-fonts]='noto-fonts-emoji'
241 [cairo-dock]='cairo-dock-plug-ins'
242 [qutebrowser]='qt5ct qt5-styleplugins'
243 [qbittorrent]='qt5ct qt5-styleplugins'
244 [transmission-qt]='qt5ct qt5-styleplugins'
245 [bluez]='bluez-libs bluez-utils bluez-tools bluez-plugins bluez-hid2hci'
246 [kdenlive]='kdebase-meta dvdauthor frei0r-plugins breeze breeze-gtk qt5ct qt5-styleplugins'
251 # dialog text variables
254 # Basics (somewhat in order)
255 _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"
256 _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"
257 _device="\nSelect a device to use from the list below.\n\nDevices (/dev) are the available drives on the system. /sda, /sdb, /sdc ..."
258 _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."
259 _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."
260 _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"
261 _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)."
262 _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."
263 _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."
264 _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."
265 _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"
266 _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."
267 _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."
268 _exmnt="\nWhere do you want the partition mounted?\n\nEnsure the name begins with a slash (/).\nExamples include: /usr, /home, /var, etc."
269 _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 [Up], [Down], or [Tab] to switch between fields, and [Enter] to accept."
270 _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."
271 _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"
272 _timez="\nThe time zone is used to set the system clock.\n\nSelect your country or continent from the list below"
273 _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."
274 _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."
275 _login="\nSelect which of your session choices to use for the initial login.\n\nYou can be change this later by editing your ~/.xinitrc"
276 _autologin="\nDo you want autologin enabled for USER?\n\nIf so the following two files will be created (disable autologin by removing them):\n\n - /home/USER/RC (run startx when logging in on tty1)\n - /etc/systemd/system/getty@tty1.service.d/autologin.conf (login USER without password)\n"
277 _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."
278 _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."
281 _luksnew="Basic LUKS Encryption"
282 _luksadv="Advanced LUKS Encryption"
283 _luksopen="Open Existing LUKS Partition"
284 _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."
285 _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."
286 _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)."
289 _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."
290 _lvmnew="Create Volume Group and Volume(s)"
291 _lvmdel="Delete an Existing Volume Group"
292 _lvmdelall="Delete ALL Volume Group(s) and Volume(s)"
293 _lvmvgname="\nEnter a name for the volume group (VG) being created from the partition(s) selected."
294 _lvmlvname="\nEnter a name for the logical volume (LV) being created.\n\nThis is similar to setting a label for a partition."
295 _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."
296 _lvmdelask="\nConfirm deletion of volume group(s) and logical volume(s).\n\nDeleting a volume group, will delete all logical volumes within it.\n"
299 _errexpart="\nCannot mount partition due to a problem with the mountpoint.\n\nEnsure it begins with a slash (/) followed by atleast one character.\n"
300 _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"
301 _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"
302 _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"
303 _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"
304 _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"
305 _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"
311 ###############################################################################
313 # main is the entry point which calls functions including outside of its block
314 # once those functions finished they always are returned here with the
315 # exception of install_main(), it exits upon completion
319 (( SEL < 12 )) && (( SEL++ ))
321 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Prepare " --default-item $SEL --cancel-label 'Exit' --menu "$_prep" 0 0 0 \
322 1 "Device tree (optional)" \
323 2 "Partitioning (optional)" \
324 3 "LUKS setup (optional)" \
325 4 "LVM setup (optional)" \
326 5 "Mount partitions" \
327 6 "System bootloader" \
328 7 "User and password" \
329 8 "System configuration" \
330 9 "Select WM/DE (optional)" \
331 10 "Select Packages (optional)" \
332 11 "View configuration (optional)" \
333 12 "Start the installation" 2>"$ANS"
336 [[ -z $WARN && $SEL =~ (2|5) ]] && { msg "Data Warning" "$_warn"; WARN=true; }
339 2) part_menu || (( SEL-- )) ;;
340 3) luks_menu || (( SEL-- )) ;;
341 4) lvm_menu || (( SEL-- )) ;;
342 5) mount_menu || (( SEL-- )) ;;
343 6) prechecks 0 && { select_boot || (( SEL-- )); } ;;
344 7) prechecks 1 && { select_mkuser || (( SEL-- )); } ;;
345 8) prechecks 2 && { select_config || (( SEL-- )); } ;;
346 9) prechecks 3 && { select_sessions || (( SEL-- )); } ;;
347 10) prechecks 3 && { select_packages || (( SEL-- )); } ;;
348 11) prechecks 3 && select_show ;;
349 12) prechecks 3 && install_main ;;
350 *) yesno "Exit" "\nUnmount partitions (if any) and exit the installer?\n" && die 0
356 if [[ $SYS == 'BIOS' ]]; then
357 dlg BOOTLDR menu "BIOS Bootloader" "\nSelect which bootloader to use." \
358 "grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
359 "syslinux" "A collection of boot loaders for booting drives, CDs, or over the network" || return 1
361 dlg BOOTLDR menu "UEFI Bootloader" "\nSelect which bootloader to use." \
362 "systemd-boot" "A simple UEFI boot manager which executes configured EFI images" \
363 "grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
364 "refind-efi" "A UEFI boot manager that aims to be platform neutral and simplify multi-boot" \
365 "efistub" "Boot the kernel image directly (no chainloading support)" \
366 "syslinux" "A collection of boot loaders for booting drives, CDs, or over the network (no chainloading support)" || return 1
373 local pkgs="${USER_PKGS// / } ${PACKAGES// / }"
374 [[ $BOOT_PART ]] && local mnt="/$BOOTDIR"
375 [[ $INSTALL_WMS == *dwm* ]] && pkgs="dwm st dmenu $pkgs"
376 pkgs="${pkgs// / }" pkgs="${pkgs# }"
377 msg "Show Configuration" "
378 ---------- PARTITION CONFIGURATION ------------
380 Root: ${ROOT_PART:-none}
381 Boot: ${BOOT_PART:-${BOOT_DEV:-none}}
383 Swap: ${SWAP_PART:-none}
384 Size: ${SWAP_SIZE:-none}
385 Extra: ${EXMNTS:-${EXMNT:-none}}
386 Hooks: ${HOOKS:-none}
392 ------------ SYSTEM CONFIGURATION -------------
394 Locale: ${MYLOCALE:-none}
395 Keymap: ${KEYMAP:-none}
396 Hostname: ${MYHOST:-none}
397 Timezone: ${ZONE:-none}/${SUBZ:-none}
400 ------------ USER CONFIGURATION ---------------
402 Username: ${NEWUSER:-none}
403 Login Shell: ${MYSHELL:-none}
404 Login Session: ${LOGIN_WM:-none}
405 Autologin: ${AUTOLOGIN:-none}
406 Login Type: ${LOGIN_TYPE:-none}
409 ----------- PACKAGE CONFIGURATION -------------
411 Kernel: ${KERNEL:-none}
412 Bootloader: ${BOOTLDR:-none}
413 Packages: ${pkgs:-none}
419 [[ $INSTALL_WMS ]] || return 0
421 AUTOLOGIN='' # no autologin unless using xinit
423 if [[ -z $LOGIN_TYPE ]]; then
424 dlg LOGIN_TYPE menu "Login Management" "\nSelect what kind of login management to use." \
425 "xinit" "Console login without a display manager" \
426 "ly" "TUI display manager with a ncurses-like interface" \
427 "lightdm" "Lightweight display manager with a gtk greeter" \
428 "gdm" "Gnome display manager" \
429 "sddm" "Simple desktop display manager" || return 1
433 ly) EDIT_FILES[login]="/etc/ly/config.ini" ;;
434 gdm|sddm) EDIT_FILES[login]="" ;;
435 lightdm) EDIT_FILES[login]="/etc/lightdm/lightdm.conf /etc/lightdm/lightdm-gtk-greeter.conf" ;;
436 xinit) EDIT_FILES[login]="/home/$NEWUSER/.xinitrc /home/$NEWUSER/.xprofile"
437 if (( $(wc -w <<< "$INSTALL_WMS") > 1 )); then
438 dlg LOGIN_WM menu "Login Management" "$_login" $LOGIN_CHOICES || return 1
439 LOGIN_WM="${WM_SESSIONS[$LOGIN_WM]}"
441 [[ -z $LOGIN_WM ]] && LOGIN_WM="${WM_SESSIONS[${INSTALL_WMS%% *}]}"
442 yesno "Autologin" "$(sed "s|USER|$NEWUSER|g; s|RC|$LOGINRC|g" <<< "$_autologin")" && AUTOLOGIN=true || AUTOLOGIN=''
452 until [[ $CONFIG_DONE ]]; do
454 0) dlg MYSHELL menu "Shell" "\nChoose which shell to use." \
455 /usr/bin/zsh 'A very advanced and programmable command interpreter (shell) for UNIX' \
456 /bin/bash 'The GNU Bourne Again shell, standard in many GNU/Linux distributions' \
457 /usr/bin/mksh 'The MirBSD Korn Shell - an enhanced version of the public domain ksh' || return 1
459 1) dlg MYHOST input "Hostname" "$_hostname" "${DIST,,}" limit || { i=0; continue; } ;;
460 2) dlg MYLOCALE menu "Locale" "$_locale" $LOCALES || { i=1; continue; } ;;
462 until [[ $ZONE && $SUBZ ]]; do
463 dlg ZONE menu "Timezone" "$_timez" America - Australia - Asia - Atlantic - Africa - Europe - Indian - Pacific - Arctic - Antarctica - || break
464 dlg SUBZ menu "Timezone" "$_timesubz" $(awk '/'"$ZONE"'\// {gsub(/'"$ZONE"'\//, ""); print $3 " - "}' /usr/share/zoneinfo/zone.tab | sort) || continue
466 [[ $ZONE && $SUBZ ]] || { i=2; continue; } ;;
467 4) dlg KERNEL menu "Kernel" "\nChoose which kernel to use." \
468 linux 'Vanilla linux kernel and modules, with a few patches applied' \
469 linux-lts 'Long-term support (LTS) linux kernel and modules' \
470 linux-zen 'A effort of kernel hackers to provide the best kernel for everyday systems' \
471 linux-hardened 'A security-focused linux kernel with hardening patches to mitigate exploits' || { i=3; continue; }
475 (( i++ )) # progress through to the next choice
478 case $MYSHELL in *bash) LOGINRC='.bash_profile' ;; *zsh) LOGINRC='.zprofile' ;; *mksh) LOGINRC='.profile' ;; esac
486 local v='' u='' p='' p2='' rp='' rp2=''
488 until [[ $NEWUSER ]]; do
491 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " User " --mixedform "$_user" 0 0 0 \
492 "Username:" 1 1 "$u" 1 11 "$COLUMNS" 0 0 \
493 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
494 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 \
495 "--- Root password, if left empty the user password will be used ---" 6 1 '' 6 68 "$COLUMNS" 0 2 \
496 "Password:" 8 1 '' 8 11 "$COLUMNS" 0 1 \
497 "Password2:" 9 1 '' 9 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
499 while read -r line; do
500 case $i in 0) u="$line" ;; 1) p="$line" ;; 2) p2="$line" ;; 3) rp="$line" ;; 4) rp2="$line" ;; esac
504 # root passwords empty, so use the user passwords
505 [[ -z $rp && -z $rp2 ]] && { rp="$p"; rp2="$p2"; }
507 # make sure a username was entered and that the passwords match
508 if [[ ${#u} -eq 0 || $u =~ \ |\' || $u =~ [^a-z0-9] ]]; then
509 msg "Invalid Username" "\nIncorrect user name.\n\nPlease try again.\n"; u=''
510 elif [[ -z $p ]]; then
511 msg "Empty Password" "\nThe user password cannot be left empty.\n\nPlease try again.\n"
512 elif [[ "$p" != "$p2" ]]; then
513 msg "Password Mismatch" "\nThe user passwords do not match.\n\nPlease try again.\n"
514 elif [[ "$rp" != "$rp2" ]]; then
515 msg "Password Mismatch" "\nThe root passwords do not match.\n\nPlease try again.\n"
527 dlg KEYMAP menu "Keyboard Layout" "$_keymap" \
528 us English cm English gb English au English gh English \
529 za English ng English ca French 'cd' French gn French \
530 tg French fr French de German at German ch German \
531 es Spanish latam Spanish br Portuguese pt Portuguese ma Arabic \
532 sy Arabic ara Arabic ua Ukrainian cz Czech ru Russian \
533 sk Slovak nl Dutch it Italian hu Hungarian cn Chinese \
534 tw Taiwanese vn Vietnamese kr Korean jp Japanese th Thai \
535 la Lao pl Polish se Swedish is Icelandic 'fi' Finnish \
536 dk Danish be Belgian in Indian al Albanian am Armenian \
537 bd Bangla ba Bosnian 'bg' Bulgarian dz Berber mm Burmese \
538 hr Croatian gr Greek il Hebrew ir Persian iq Iraqi \
539 af Afghani fo Faroese ge Georgian ee Estonian kg Kyrgyz \
540 kz Kazakh lt Lithuanian mt Maltese mn Mongolian ro Romanian \
541 no Norwegian rs Serbian si Slovenian tj Tajik lk Sinhala \
542 tr Turkish uz Uzbek ie Irish pk Urdu 'mv' Dhivehi \
543 np Nepali et Amharic sn Wolof ml Bambara tz Swahili \
544 ke Swahili bw Tswana ph Filipino my Malay tm Turkmen \
545 id Indonesian bt Dzongkha lv Latvian md Moldavian mao Maori \
546 by Belarusian az Azerbaijani mk Macedonian kh Khmer epo Esperanto \
547 me Montenegrin || return 1
549 if [[ $CMAPS == *"$KEYMAP"* ]]; then
552 dlg CMAP menu "Console Keymap" "$_vconsole" $CMAPS || return 1
555 if [[ $DISPLAY && $TERM != 'linux' ]]; then
556 setxkbmap "$KEYMAP" >/dev/null 2>&1
558 loadkeys "$CMAP" >/dev/null 2>&1
568 dlg INSTALL_WMS check "Sessions" "$_sessions\n" \
569 i3-gaps "A fork of i3wm with more features including gaps" "$(ofn i3-gaps "${INSTALL_WMS[*]}")" \
570 openbox "A lightweight, powerful, and highly configurable stacking wm" "$(ofn openbox "${INSTALL_WMS[*]}")" \
571 awesome "A customized Awesome WM session created by @elanapan" "$(ofn awesome "${INSTALL_WMS[*]}")" \
572 dwm "A dynamic WM for X that manages windows in tiled, floating, or monocle layouts" "$(ofn dwm "${INSTALL_WMS[*]}")" \
573 bspwm "A tiling wm that represents windows as the leaves of a binary tree" "$(ofn bspwm "${INSTALL_WMS[*]}")" \
574 fluxbox "A lightweight and highly-configurable window manager" "$(ofn fluxbox "${INSTALL_WMS[*]}")" \
575 gnome "A desktop environment that aims to be simple and easy to use" "$(ofn gnome "${INSTALL_WMS[*]}")" \
576 cinnamon "A desktop environment combining traditional desktop with modern effects" "$(ofn cinnamon "${INSTALL_WMS[*]}")" \
577 plasma "A kde software project currently comprising a full desktop environment" "$(ofn plasma "${INSTALL_WMS[*]}")" \
578 xfce4 "A lightweight and modular desktop environment based on gtk+2/3" "$(ofn xfce4 "${INSTALL_WMS[*]}")"
580 [[ $INSTALL_WMS ]] || return 0
582 WM_PKGS="${INSTALL_WMS/dwm/}" # remove dwm from package list
583 WM_PKGS="${WM_PKGS// / }" # remove double spaces
584 WM_PKGS="${WM_PKGS# }" # remove leading space
586 # add archlabs base when choosing any session
587 [[ $WM_PKGS ]] && WM_PKGS+=" $AL_BASE_PKGS"
589 for i in $INSTALL_WMS; do
590 LOGIN_CHOICES+="$i - "
591 [[ ${WM_EXT[$i]} && $WM_PKGS != *"${WM_EXT[$i]}"* ]] && WM_PKGS+=" ${WM_EXT[$i]}"
594 select_login || return 1
596 while IFS=' ' read -r pkg; do
597 [[ $PACKAGES != *"$pkg"* ]] && PACKAGES+=" $pkg"
605 dlg USER_PKGS check " Packages " "$_packages" \
606 abiword "A Fully-featured word processor" "$(ofn abiword "${USER_PKGS[*]}")" \
607 alacritty "A cross-platform, GPU-accelerated terminal emulator" "$(ofn alacritty "${USER_PKGS[*]}")" \
608 atom "An open-source text editor developed by GitHub" "$(ofn atom "${USER_PKGS[*]}")" \
609 audacious "A free and advanced audio player based on GTK+" "$(ofn audacious "${USER_PKGS[*]}")" \
610 audacity "A program that lets you manipulate digital audio waveforms" "$(ofn audacity "${USER_PKGS[*]}")" \
611 blueman "GUI bluetooth device manager" "$(ofn blueman "${USER_PKGS[*]}")" \
612 bluez "Simple CLI based bluetooth support" "$(ofn bluez "${USER_PKGS[*]}")" \
613 cairo-dock "Light eye-candy fully themable animated dock" "$(ofn cairo-dock "${USER_PKGS[*]}")" \
614 calligra "A set of applications for productivity" "$(ofn calligra "${USER_PKGS[*]}")" \
615 chromium "An open-source web browser based on the Blink rendering engine" "$(ofn chromium "${USER_PKGS[*]}")" \
616 clementine "A modern music player and library organizer" "$(ofn clementine "${USER_PKGS[*]}")" \
617 cmus "A small, fast and powerful console music player" "$(ofn cmus "${USER_PKGS[*]}")" \
618 deadbeef "A GTK+ audio player for GNU/Linux" "$(ofn deadbeef "${USER_PKGS[*]}")" \
619 deluge "A BitTorrent client written in python" "$(ofn deluge "${USER_PKGS[*]}")" \
620 docky "Full fledged dock for opening applications and managing windows" "$(ofn docky "${USER_PKGS[*]}")" \
621 emacs "An extensible, customizable, self-documenting real-time display editor" "$(ofn emacs "${USER_PKGS[*]}")" \
622 epiphany "A GNOME web browser based on the WebKit rendering engine" "$(ofn epiphany "${USER_PKGS[*]}")" \
623 evince "A document viewer" "$(ofn evince "${USER_PKGS[*]}")" \
624 evolution "Manage your email, contacts and schedule" "$(ofn evolution "${USER_PKGS[*]}")" \
625 file-roller "Create and modify archives" "$(ofn file-roller "${USER_PKGS[*]}")" \
626 firefox "A popular open-source web browser from Mozilla" "$(ofn firefox "${USER_PKGS[*]}")" \
627 gcolor2 "A simple GTK+2 color selector" "$(ofn gcolor2 "${USER_PKGS[*]}")" \
628 geany "A fast and lightweight IDE" "$(ofn geany "${USER_PKGS[*]}")" \
629 geary "A lightweight email client for the GNOME desktop" "$(ofn geary "${USER_PKGS[*]}")" \
630 gimp "GNU Image Manipulation Program" "$(ofn gimp "${USER_PKGS[*]}")" \
631 gnome-calculator "GNOME Scientific calculator" "$(ofn gnome-calculator "${USER_PKGS[*]}")" \
632 gnome-disk-utility "Disk Management Utility" "$(ofn gnome-disk-utility "${USER_PKGS[*]}")" \
633 gnome-system-monitor "View current processes and monitor system state" "$(ofn gnome-system-monitor "${USER_PKGS[*]}")" \
634 gparted "A GUI frontend for creating and manipulating partition tables" "$(ofn gparted "${USER_PKGS[*]}")" \
635 gpick "Advanced color picker using GTK+ toolkit" "$(ofn gpick "${USER_PKGS[*]}")" \
636 gpicview "Lightweight image viewer" "$(ofn gpicview "${USER_PKGS[*]}")" \
637 guvcview "Capture video from camera devices" "$(ofn guvcview "${USER_PKGS[*]}")" \
638 hexchat "A popular and easy to use graphical IRC client" "$(ofn hexchat "${USER_PKGS[*]}")" \
639 inkscape "Professional vector graphics editor" "$(ofn inkscape "${USER_PKGS[*]}")" \
640 irssi "Modular text mode IRC client" "$(ofn irssi "${USER_PKGS[*]}")" \
641 kdenlive "A popular non-linear video editor for Linux" "$(ofn kdenlive "${USER_PKGS[*]}")" \
642 krita "Edit and paint images" "$(ofn krita "${USER_PKGS[*]}")" \
643 libreoffice-fresh "Full featured office suite" "$(ofn libreoffice-fresh "${USER_PKGS[*]}")" \
644 lollypop "A new music playing application" "$(ofn lollypop "${USER_PKGS[*]}")" \
645 mousepad "A simple text editor" "$(ofn mousepad "${USER_PKGS[*]}")" \
646 mpd "A flexible, powerful, server-side application for playing music" "$(ofn mpd "${USER_PKGS[*]}")" \
647 mpv "A media player based on mplayer" "$(ofn mpv "${USER_PKGS[*]}")" \
648 mupdf "Lightweight PDF and XPS viewer" "$(ofn mupdf "${USER_PKGS[*]}")" \
649 mutt "Small but very powerful text-based mail client" "$(ofn mutt "${USER_PKGS[*]}")" \
650 nautilus "The default file manager for Gnome" "$(ofn nautilus "${USER_PKGS[*]}")" \
651 ncmpcpp "A mpd client and almost exact clone of ncmpc with some new features" "$(ofn ncmpcpp "${USER_PKGS[*]}")" \
652 neovim "A fork of Vim aiming to improve user experience, plugins, and GUIs." "$(ofn neovim "${USER_PKGS[*]}")" \
653 nicotine+ "A graphical client for Soulseek" "$(ofn nicotine+ "${USER_PKGS[*]}")" \
654 noto-fonts "Google Noto fonts" "$(ofn noto-fonts "${USER_PKGS[*]}")" \
655 noto-fonts-cjk "Google Noto CJK fonts (Chinese, Japanese, Korean)" "$(ofn noto-fonts-cjk "${USER_PKGS[*]}")" \
656 obs-studio "Free opensource streaming/recording software" "$(ofn obs-studio "${USER_PKGS[*]}")" \
657 openshot "An open-source, non-linear video editor for Linux" "$(ofn openshot "${USER_PKGS[*]}")" \
658 opera "A Fast and secure, free of charge web browser from Opera Software" "$(ofn opera "${USER_PKGS[*]}")" \
659 pcmanfm "A fast and lightweight file manager based in Lxde" "$(ofn pcmanfm "${USER_PKGS[*]}")" \
660 pidgin "Multi-protocol instant messaging client" "$(ofn pidgin "${USER_PKGS[*]}")" \
661 plank "An elegant, simple, and clean dock" "$(ofn plank "${USER_PKGS[*]}")" \
662 qbittorrent "An advanced BitTorrent client" "$(ofn qbittorrent "${USER_PKGS[*]}")" \
663 qpdfview "A tabbed PDF viewer" "$(ofn qpdfview "${USER_PKGS[*]}")" \
664 qt5ct "GUI for managing Qt based application themes, icons, and fonts" "$(ofn qt5ct "${USER_PKGS[*]}")" \
665 qutebrowser "A keyboard-focused vim-like web browser based on Python and PyQt5" "$(ofn qutebrowser "${USER_PKGS[*]}")" \
666 rhythmbox "A Music playback and management application" "$(ofn rhythmbox "${USER_PKGS[*]}")" \
667 rxvt-unicode "A unicode enabled rxvt-clone terminal emulator" "$(ofn rxvt-unicode "${USER_PKGS[*]}")" \
668 sakura "A terminal emulator based on GTK and VTE" "$(ofn sakura "${USER_PKGS[*]}")" \
669 simple-scan "Simple scanning utility" "$(ofn simple-scan "${USER_PKGS[*]}")" \
670 simplescreenrecorder "A feature-rich screen recorder" "$(ofn simplescreenrecorder "${USER_PKGS[*]}")" \
671 steam "A popular game distribution platform by Valve" "$(ofn steam "${USER_PKGS[*]}")" \
672 surf "A simple web browser based on WebKit2/GTK+" "$(ofn surf "${USER_PKGS[*]}")" \
673 terminator "Terminal emulator that supports tabs and grids" "$(ofn terminator "${USER_PKGS[*]}")" \
674 termite "A minimal VTE-based terminal emulator" "$(ofn termite "${USER_PKGS[*]}")" \
675 thunar "A modern file manager for the Xfce Desktop Environment" "$(ofn thunar "${USER_PKGS[*]}")" \
676 thunderbird "Standalone mail and news reader from mozilla" "$(ofn thunderbird "${USER_PKGS[*]}")" \
677 tilda "A GTK based drop down terminal for Linux and Unix" "$(ofn tilda "${USER_PKGS[*]}")" \
678 tilix "A tiling terminal emulator for Linux using GTK+ 3" "$(ofn tilix "${USER_PKGS[*]}")" \
679 transmission-cli "Free BitTorrent client CLI" "$(ofn transmission-cli "${USER_PKGS[*]}")" \
680 transmission-gtk "GTK+ Front end for transmission" "$(ofn transmission-gtk "${USER_PKGS[*]}")" \
681 transmission-qt "Qt Front end for transmission" "$(ofn transmission-qt "${USER_PKGS[*]}")" \
682 ttf-anonymous-pro "A family fixed-width fonts designed with code in mind" "$(ofn ttf-anonymous-pro "${USER_PKGS[*]}")" \
683 ttf-fira-code "Monospaced font with programming ligatures" "$(ofn ttf-fira-code "${USER_PKGS[*]}")" \
684 ttf-font-awesome "Iconic font designed for Bootstrap" "$(ofn ttf-font-awesome "${USER_PKGS[*]}")" \
685 ttf-hack "A hand groomed typeface based on Bitstream Vera Mono" "$(ofn ttf-hack "${USER_PKGS[*]}")" \
686 vlc "A free and open source cross-platform multimedia player" "$(ofn vlc "${USER_PKGS[*]}")" \
687 weechat "Fast, light and extensible IRC client" "$(ofn weechat "${USER_PKGS[*]}")" \
688 xapps "Common library for X-Apps project" "$(ofn xapps "${USER_PKGS[*]}")" \
689 xarchiver "A GTK+ frontend to various command line archivers" "$(ofn xarchiver "${USER_PKGS[*]}")" \
690 xed "A small and lightweight text editor. X-Apps Project." "$(ofn xed "${USER_PKGS[*]}")" \
691 xfce-terminal "A terminal emulator based in the Xfce Desktop Environment" "$(ofn xfce-terminal "${USER_PKGS[*]}")" \
692 xreader "Document viewer for files like PDF and Postscript. X-Apps Project." "$(ofn xed "${USER_PKGS[*]}")" \
693 xterm "The standard terminal emulator for the X window system" "$(ofn xterm "${USER_PKGS[*]}")" \
694 zathura "Minimalistic document viewer" "$(ofn zathura "${USER_PKGS[*]}")"
696 if [[ $USER_PKGS ]]; then
697 for i in $USER_PKGS; do
698 [[ ${PKG_EXT[$i]} && $USER_PKGS != *"${PKG_EXT[$i]}"* ]] && USER_PKGS+=" ${PKG_EXT[$i]}"
705 ###############################################################################
707 # non-essential partitioning helpers called by the user when using the optional
708 # partition menu and selecting a device to edit
712 is_bg_install || return 0
713 local device choice devhash
714 devhash="$(lsblk -f | base64)"
716 part_device || return 1
721 if [[ $DISPLAY && $TERM != 'linux' ]] && hash gparted >/dev/null 2>&1; then
722 dlg choice menu "Edit Partitions" "$_part" \
723 "auto" "Whole device automatic partitioning" \
724 "shrink" "Shrink an existing ext2/3/4 or ntfs partition to make room for a new partition" \
725 "gparted" "GUI front end to parted" \
726 "cfdisk" "Curses based variant of fdisk" \
727 "parted" "GNU partition editor" \
728 "fdisk" "Dialog-driven creation and manipulation of partitions" \
729 "done" "Return to the main menu" || return 0
731 dlg choice menu "Edit Partitions" "$_part" \
732 "auto" "Whole device automatic partitioning" \
733 "shrink" "Shrink an existing ext2/3/4 or ntfs partition to make room for a new partition" \
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
740 if [[ $choice == 'done' ]]; then
742 elif [[ $choice == 'shrink' ]]; then
743 part_shrink "$device"
744 elif [[ $choice == 'auto' ]]; then
745 local root_size txt table boot_fs
746 root_size=$(lsblk -lno SIZE "$device" | awk 'NR == 1 {
749 print ($1 * 1000 - 512) / 1000 "G"
755 txt="\nWARNING:\n\nALL data on $device will be destroyed and the following partitions will be created\n\n- "
756 if [[ $SYS == 'BIOS' ]]; then
757 table="msdos" boot_fs="ext4"
758 txt+="An $boot_fs boot partition with the boot flag enabled (512M)\n- "
760 table="gpt" boot_fs="fat32"
761 txt+="A $boot_fs efi boot partition (512M)\n- "
763 txt+="An ext4 partition using all remaining space ($root_size)\n\nDo you want to continue?\n"
764 yesno "Auto Partition" "$txt" && msg "Info" "\nGathering device info.\n" 0 && part_auto "$device" "$table" "$boot_fs" "$root_size"
771 if [[ $devhash != "$(lsblk -f | base64)" ]]; then
772 msg "Probing Partitions" "\nInforming the kernel of partition changes using partprobe.\n" 0
773 partprobe >/dev/null 2>&1
774 [[ $choice == 'auto' ]] && return
782 if [[ $IGNORE_DEV ]]; then
783 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk "!/$IGNORE_DEV/"' && /disk|part|lvm|crypt|NAME/')"
785 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk '/disk|part|lvm|crypt|NAME/')"
787 msg "Device Tree" "\n\n$txt\n\n"
792 local device="$1" table="$2" boot_fs="$3" size="$4" dev_info=""
793 dev_info="$(parted -s "$device" print)"
795 msg "Auto Partition" "\nRemoving partitions on $device and setting table to $table\n" 1
798 while read -r PART; do
799 parted -s "$device" rm "$PART" >/dev/null 2>&1
800 done <<< "$(awk '/^ [1-9][0-9]?/ {print $1}' <<< "$dev_info" | sort -r)"
802 [[ $(awk '/Table:/ {print $3}' <<< "$dev_info") != "$table" ]] && parted -s "$device" mklabel "$table" >/dev/null 2>&1
804 msg "Auto Partition" "\nCreating a 512M $boot_fs boot partition.\n" 1
805 if [[ $SYS == "BIOS" ]]; then
806 parted -s "$device" mkpart primary "$boot_fs" 1MiB 513MiB >/dev/null 2>&1
808 parted -s "$device" mkpart ESP "$boot_fs" 1MiB 513MiB >/dev/null 2>&1
813 AUTO_BOOT_PART=$(lsblk -lno NAME,TYPE "$device" | awk 'NR==2 {print "/dev/" $1}')
815 if [[ $SYS == "BIOS" ]]; then
816 mkfs.ext4 -q "$AUTO_BOOT_PART" >/dev/null 2>&1
818 mkfs.vfat -F32 "$AUTO_BOOT_PART" >/dev/null 2>&1
821 msg "Auto Partition" "\nCreating a $size ext4 root partition.\n" 0
822 parted -s "$device" mkpart primary ext4 513MiB 100% >/dev/null 2>&1
824 AUTO_ROOT_PART="$(lsblk -lno NAME,TYPE "$device" | awk 'NR==3 {print "/dev/" $1}')"
825 mkfs.ext4 -q "$AUTO_ROOT_PART" >/dev/null 2>&1
827 FORMATTED+="$AUTO_BOOT_PART $AUTO_ROOT_PART "
828 msg "Auto Partition" "\nProcess complete.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$device")\n"
835 local device="$1" fs=""
837 part_find "${device##*/}[^ ]" || return 1
838 (( COUNT == 1 )) && part="$(awk '{print $1}' <<< "${PARTS[@]}" )"
840 if (( COUNT == 1 )) || dlg part menu "Resize" "\nWhich partition on $device do you want to resize?" $PARTS; then
841 fs=$(lsblk -lno FSTYPE "$part")
844 msg "Resize" "\nGathering device size info.\n" 0
846 end=$(parted -s "$device" unit KiB print | awk '/^\s*'"$num"'/ {print $3}') # part size in KiB
847 devsize=$(parted -s "$device" unit KiB print | awk '/Disk '"${device//\//\\/}"':/ {print $3}') # whole device size in KiB
848 mount "$part" $MNT >/dev/null 2>&1; sleep 0.5
849 min=$(df --output=used --block-size=MiB "$part" | awk 'NR == 2 {print int($1) + 256}')
850 max=$(df --output=avail --block-size=MiB "$part" | awk 'NR == 2 {print int($1)}')
853 if dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Resize: $part " --rangebox "$_resize" 17 "$COLUMNS" "$min" "$max" $((max / 2)) 2>$ANS; then
855 size=$((size * 1024))
862 if ntfsresize -fc "$part"; then
863 ntfsresize -ff --size $(( (size * 1024) / 1000 ))k "$part" 2>$ERR # k=10^3 bytes
864 errshow "ntfsresize -f -s $(( (size * 1024) / 1000 ))k $part" || return 1
866 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"
871 e2fsck -f "$part"; sleep 0.5
872 resize2fs -f "$part" ${size}K 2>$ERR # K=2^10 bytes
873 errshow "resize2fs -f $part ${size}K" || return 1
877 parted "$device" resizepart "$num" ${size}KiB || return 1
880 if [[ $devsize == "$end" ]]; then
881 parted -s "$device" mkpart primary ext4 ${size}KiB 100% 2>$ERR
882 errshow "parted -s $device mkpart primary ext4 ${size}KiB 100%" || return 1
884 parted -s "$device" mkpart primary ext4 ${size}KiB ${end}KiB 2>$ERR
885 errshow "parted -s $device mkpart primary ext4 ${size}KiB ${end}KiB" || return 1
887 msg "Resize Complete" "\n$part has been successfully resized to $((size / 1024))M.\n" 1
889 "") msg "No Filesystem" "\nFor unformatted partitions, cfdisk can be used in the partition menu.\n" ;;
890 *) msg "Invalid Filesystem: $fs" "\nResizing only supports ext and ntfs.\n" ;;
895 ###############################################################################
896 # partition management functions
897 # these are helpers for use by other functions to do essential setup/teardown
901 local regexp="$1" err=''
903 # string of partitions as /TYPE/PART SIZE
904 if [[ $IGNORE_DEV ]]; then
905 PARTS="$(lsblk -lno TYPE,NAME,SIZE |
906 awk "/$regexp/"' && !'"/$IGNORE_DEV/"' {
907 sub(/^part/, "/dev/")
908 sub(/^lvm|^crypt/, "/dev/mapper/")
912 PARTS="$(lsblk -lno TYPE,NAME,SIZE |
914 sub(/^part/, "/dev/")
915 sub(/^lvm|^crypt/, "/dev/mapper/")
920 # number of partitions total
922 while read -r line; do
926 # ensure we have enough partitions for the system and action type
928 'part|lvm|crypt') [[ $COUNT -lt 1 || ($SYS == 'UEFI' && $COUNT -lt 2) ]] && err="$_errpart" ;;
929 'part|crypt') (( COUNT < 1 )) && err="$_lvmerr" ;;
930 'part|lvm') (( COUNT < 2 )) && err="$_lukserr" ;;
933 # if there aren't enough partitions show the relevant error message
934 [[ $err ]] && { msg "Not Enough Partitions" "$err" 2; return 1; }
941 if [[ $1 == "$MNT/swapfile" && $SWAP_SIZE ]]; then
942 fallocate -l $SWAP_SIZE "$1" 2>$ERR
943 errshow "fallocate -l $SWAP_SIZE $1"
944 chmod 600 "$1" 2>$ERR
945 errshow "chmod 600 $1"
947 mkswap "$1" >/dev/null 2>$ERR
949 swapon "$1" >/dev/null 2>$ERR
956 local part="$1" mountp="${MNT}$2" fs=""
957 fs="$(lsblk -lno FSTYPE "$part")"
960 if [[ $fs && ${FS_OPTS[$fs]} && $part != "$BOOT_PART" ]] && select_mntopts "$fs"; then
961 mount -o "$MNT_OPTS" "$part" "$mountp" >/dev/null 2>&1
963 mount "$part" "$mountp" >/dev/null 2>&1
966 part_mountconf "$part" "$mountp" || return 1
974 local part="$1" fs="$2" delay="$3"
976 msg "Format" "\nFormatting $part as $fs\n" 0
977 ${FS_CMDS[$fs]} "$part" >/dev/null 2>$ERR
978 errshow "${FS_CMDS[$fs]} $part" || return 1
985 if [[ $DEV_COUNT -eq 1 && $SYS_DEVS ]]; then
986 DEVICE="$(awk '{print $1}' <<< "$SYS_DEVS")"
987 elif (( DEV_COUNT > 1 )); then
989 dlg DEVICE menu "Boot Device" "\nSelect the device to use for bootloader install." $SYS_DEVS
991 dlg DEVICE menu "Select Device" "$_device" $SYS_DEVS
993 [[ $DEVICE ]] || return 1
994 elif [[ $DEV_COUNT -lt 1 && ! $1 ]]; then
995 msg "Device Error" "\nNo available devices.\n\nExiting..\n" 2
999 [[ $1 ]] && BOOT_DEV="$DEVICE"
1006 BOOT_DEV="${BOOT_PART%[1-9]}"
1007 BOOT_PART_NUM="${BOOT_PART: -1}"
1008 [[ $BOOT_PART = /dev/nvme* ]] && BOOT_DEV="${BOOT_PART%p[1-9]}"
1009 if [[ $SYS == 'UEFI' ]]; then
1010 parted -s $BOOT_DEV set $BOOT_PART_NUM esp on >/dev/null 2>&1
1012 parted -s $BOOT_DEV set $BOOT_PART_NUM boot on >/dev/null 2>&1
1019 local part="$1" devs=""
1020 devs="$(lsblk -lno NAME,FSTYPE,TYPE)"
1022 # Identify if $part is LUKS+LVM, LVM+LUKS, LVM alone, or LUKS alone
1023 if lsblk -lno TYPE "$part" | grep -q 'crypt'; then
1025 LUKS_NAME="${part#/dev/mapper/}"
1027 for dev in $(awk '/lvm/ && /crypto_LUKS/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
1028 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1029 LUKS_DEV="$LUKS_DEV cryptdevice=$dev:$LUKS_NAME"
1030 LVM='logical volume'
1035 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
1036 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1037 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
1038 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
1043 elif lsblk -lno TYPE "$part" | grep -q 'lvm'; then
1044 LVM='logical volume'
1045 VNAME="${part#/dev/mapper/}"
1047 for dev in $(awk '/crypt/ && /lvm2_member/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
1048 if lsblk -lno NAME "$dev" | grep -q "$VNAME"; then
1049 LUKS_NAME="${dev/\/dev\/mapper\//}"
1054 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
1055 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1056 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
1057 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
1068 if (( COUNT > 0 )); then
1069 PARTS="$(sed "/${pt//\//\\/}/d" <<< "$PARTS")"
1077 if grep -qw "$1" /proc/mounts; then
1078 msg "Mount Success" "\nPartition $1 mounted at $2\n" 1
1082 msg "Mount Fail" "\nPartition $1 failed to mount at $2\n" 2
1087 ###############################################################################
1089 # mount_menu is the entry point which calls all other functions
1090 # once finished it returns to the main menu: main()
1094 msg "Info" "\nGathering device info.\n" 0
1095 is_bg_install || return 0
1098 part_find 'part|lvm|crypt' || { SEL=2; return 1; }
1100 [[ $LUKS && $LUKS_PART ]] && part_countdec $LUKS_PART
1101 [[ $LVM && $LVM_PARTS ]] && part_countdec $LVM_PARTS
1103 select_root_partition || return 1
1105 if [[ $SYS == 'UEFI' ]]; then
1106 select_efi_partition || { BOOT_PART=''; return 1; }
1107 elif (( COUNT > 0 )); then
1108 select_boot_partition || { BOOT_PART=''; return 1; }
1111 if [[ $BOOT_PART ]]; then
1112 part_mount "$BOOT_PART" "/$BOOTDIR" && SEP_BOOT=true || return 1
1116 select_swap || return 1
1117 select_extra_partitions || return 1
1125 dlg SWAP_PART menu "Swap Setup" "\nSelect whether to use a swapfile, swap partition, or none." \
1126 "none" "Don't allocate any swap space" \
1127 "swapfile" "Allocate $SYS_MEM at /swapfile" \
1130 if [[ -z $SWAP_PART || $SWAP_PART == "none" ]]; then
1133 elif [[ $SWAP_PART == "swapfile" ]]; then
1135 until [[ ${SWAP_SIZE:0:1} =~ [1-9] && ${SWAP_SIZE: -1} =~ (M|G) ]]; do
1136 (( 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
1137 dlg SWAP_SIZE input "Swap Setup" "$_swapsize" "$SYS_MEM" || { SWAP_PART=''; SWAP_SIZE=''; return 1; }
1140 part_swap "$MNT/$SWAP_PART"
1141 SWAP_PART="/$SWAP_PART"
1142 elif [[ $PARTS == *"$SWAP_PART"* ]]; then
1143 part_swap $SWAP_PART
1144 part_countdec $SWAP_PART
1145 SWAP_SIZE="$(lsblk -lno SIZE $SWAP_PART)"
1155 local fs="$1" opts=''
1156 local title="${fs^} Mount Options"
1158 for i in ${FS_OPTS[$fs]}; do
1162 until [[ $MNT_OPTS ]]; do
1163 dlg MNT_OPTS check "$title" "$_mount" $opts
1164 [[ $MNT_OPTS ]] || return 1
1165 MNT_OPTS="${MNT_OPTS// /,}"
1166 yesno "$title" "\nConfirm the following options: $MNT_OPTS\n" || MNT_OPTS=''
1175 until [[ $EXMNT ]]; do
1176 dlg EXMNT input "Extra Mount $part" "$_exmnt" "/" || return 1
1177 if [[ ${EXMNT:0:1} != "/" || ${#EXMNT} -le 1 || $EXMNT =~ \ |\' || $EXMNTS == *"$EXMNT"* ]]; then
1178 msg "Mountpoint Error" "$_errexpart"
1187 local part="$1" fs='' cur=''
1188 local txt="\nSelect which filesystem to use for: $part\n\nDefault: ext4"
1189 cur="$(lsblk -lno FSTYPE "$part" 2>/dev/null)"
1192 if [[ $cur && ($part != "$ROOT_PART" || $FORMATTED == *"$part"*) ]]; then
1193 dlg fs menu "Filesystem" "$txt\nCurrent: $cur" skip - ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1195 dlg fs menu "Filesystem" "$txt" ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1197 [[ $fs == 'skip' ]] && return 0
1198 yesno "Filesystem" "\nFormat $part as $fs?\n" || fs=''
1200 part_format "$part" "$fs"
1203 select_efi_partition()
1205 if [[ $AUTO_BOOT_PART ]]; then
1206 msg "EFI Boot Partition" "\nUsing partition created during automatic format.\n" 2
1207 BOOT_PART="$AUTO_BOOT_PART"; return 0 # were done here
1209 local pts size dev isize bsize ptcount=0
1211 # walk partition list and skip ones that are too small/big for boot
1212 while read -r dev size; do
1213 size_t="${size: -1:1}" # size type eg. K, M, G, T
1214 isize=${size:0:-1} # remove trailing size type character
1215 isize=${isize%.*} # remove any decimal (round down)
1216 [[ $size_t =~ [KT] || ($size_t == 'G' && $isize -gt 2) || ($size_t == 'M' && $isize -lt 100) ]] || { pts+="$dev $size "; (( ptcount++ )); }
1219 if (( ptcount == 1 )); then
1220 msg "EFI Boot Partition" "\nOnly one partition available that meets size requirements.\n" 1
1221 BOOT_PART="$(awk 'NF > 0 {print $1}' <<< "$pts")"
1223 dlg BOOT_PART menu "EFI Partition" "$_uefi" $pts
1227 [[ $BOOT_PART ]] || return 1
1229 if grep -q 'fat' <<< "$(fsck -N "$BOOT_PART")"; then
1230 local txt="\nIMPORTANT:\n\nThe EFI partition $BOOT_PART $_format"
1231 if yesno "Format EFI Partition" "$txt" "Format $BOOT_PART" "Skip Formatting" 1; then
1232 part_format "$BOOT_PART" "vfat" 2
1235 part_format "$BOOT_PART" "vfat" 2
1241 select_boot_partition()
1243 if [[ $AUTO_BOOT_PART && ! $LVM ]]; then
1244 msg "BIOS Boot Partition" "\nUsing partition created during automatic format.\n" 2
1245 BOOT_PART="$AUTO_BOOT_PART"; return 0 # were done here
1247 local pts size dev isize bsize ptcount=0
1249 # walk partition list and skip ones that are too small/big for boot
1250 while read -r dev size; do
1251 size_t="${size: -1:1}" # size type eg. K, M, G, T
1252 isize=${size:0:-1} # remove trailing size type character
1253 isize=${isize%.*} # remove any decimal (round down)
1254 [[ $size_t =~ [KT] || ($size_t == 'G' && $isize -gt 2) || ($size_t == 'M' && $isize -lt 100) ]] || { pts+="$dev $size "; (( ptcount++ )); }
1257 if [[ $LUKS && ! $LVM ]]; then
1258 dlg BOOT_PART menu "Boot Partition" "$_biosluks" $pts
1259 [[ $BOOT_PART ]] || return 1
1261 dlg BOOT_PART menu "Boot Partition" "$_bios" "skip" "don't use a separate boot" $pts
1262 [[ -z $BOOT_PART || $BOOT_PART == "skip" ]] && { BOOT_PART=''; return 0; }
1266 if grep -q 'ext[34]' <<< "$(fsck -N "$BOOT_PART")"; then
1267 local txt="\nIMPORTANT:\n\nThe boot partition $BOOT_PART $_format"
1268 if yesno "Format Boot Partition" "$txt" "Format $BOOT_PART" "Skip Formatting" 1; then
1269 part_format "$BOOT_PART" "ext4" 2
1272 part_format "$BOOT_PART" "ext4" 2
1277 select_root_partition()
1279 if [[ $AUTO_ROOT_PART && -z $LVM && -z $LUKS ]]; then
1280 ROOT_PART="$AUTO_ROOT_PART"
1281 msg "Select Root Partition (/)" "\nUsing partition created during automatic format.\n" 2
1282 part_mount "$ROOT_PART" || { ROOT_PART=''; return 1; }
1283 return 0 # we're done here
1285 local pts size dev isize bsize ptcount=0
1287 # walk partition list and skip ones that are too small for / (root)
1288 while read -r dev size; do
1289 size_t="${size: -1:1}" # size type eg. K, M, G, T
1290 isize=${size:0:-1} # remove trailing size type character
1291 isize=${isize%.*} # remove any decimal (round down)
1292 [[ $size_t =~ [MK] || ($size_t == 'G' && $isize -lt 4) ]] || { pts+="$dev $size "; (( ptcount++ )); }
1295 if (( ptcount == 1 )); then # only one available device
1296 msg "Select Root Partition (/)" "\nOnly one partition available that meets size requirements.\n" 2
1297 ROOT_PART="$(awk 'NR==1 {print $1}' <<< "$pts")"
1299 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." $pts
1302 [[ $ROOT_PART ]] || return 1
1304 select_filesystem "$ROOT_PART" || { ROOT_PART=''; return 1; }
1305 part_mount "$ROOT_PART" || { ROOT_PART=''; return 1; }
1310 select_extra_partitions()
1314 # walk partition list and skip ones that are too small to be usable
1315 while read -r dev size; do
1316 [[ ${size: -1:1} =~ [KM] ]] && part_countdec "$dev"
1319 while (( COUNT > 0 )); do
1321 dlg part menu 'Mount Extra' "$_expart" 'done' 'finish mounting step' $PARTS || break
1322 if [[ $part == 'done' ]]; then
1324 elif select_filesystem "$part" && select_mountpoint && part_mount "$part" "$EXMNT"; then
1325 EXMNTS+="$part: $EXMNT "
1326 [[ $EXMNT == '/usr' && $HOOKS != *usr* ]] && HOOKS="usr $HOOKS"
1334 ###############################################################################
1336 # main is the entry point which calls all other install functions, once
1337 # complete it shows a dialog to edit files on the new system before reboot
1344 genfstab -U $MNT >$MNT/etc/fstab 2>$ERR
1345 errshow 1 "genfstab -U $MNT >$MNT/etc/fstab"
1346 [[ -f $MNT/swapfile ]] && sed -i "s~${MNT}~~" $MNT/etc/fstab
1350 chrun "hwclock --systohc --utc" || chrun "hwclock --systohc --utc --directisa"
1353 chrun "chown -Rf $NEWUSER:users /home/$NEWUSER"
1356 dlg choice menu "Finalization" "$_edit" \
1357 finished "exit the installer and reboot" \
1358 keyboard "${EDIT_FILES[keyboard]}" \
1359 console "${EDIT_FILES[console]}" \
1360 locale "${EDIT_FILES[locale]}" \
1361 hostname "${EDIT_FILES[hostname]}" \
1362 sudoers "${EDIT_FILES[sudoers]}" \
1363 mkinitcpio "${EDIT_FILES[mkinitcpio]}" \
1364 fstab "${EDIT_FILES[fstab]}" \
1365 crypttab "${EDIT_FILES[crypttab]}" \
1366 bootloader "${EDIT_FILES[bootloader]}" \
1367 pacman "${EDIT_FILES[pacman]}" \
1368 login "${EDIT_FILES[login]}"
1370 if [[ -z $choice || $choice == 'finished' ]]; then
1371 [[ $DEBUG == true && -r $DBG ]] && vim $DBG
1375 for f in ${EDIT_FILES[$choice]}; do
1376 [[ -e ${MNT}$f ]] && exists+=" ${MNT}$f"
1378 if [[ $exists ]]; then
1381 msg "File Missing" "\nThe file(s) selected do not exist:\n\n${EDIT_FILES[$choice]}\n"
1389 if kill -0 "$RSYNC_PID" 2>/dev/null || kill -0 "$MIRROR_PID" 2>/dev/null; then
1390 printf "\nOne or more background install processes are still running, grabbing their output...\n" && cat /tmp/bg_out
1391 while kill -0 "$RSYNC_PID" 2>/dev/null || kill -0 "$MIRROR_PID" 2>/dev/null; do
1396 unset RSYNC_PID MIRROR_PID
1398 rm -rf $MNT/etc/mkinitcpio-archiso.conf
1399 find $MNT/usr/lib/initcpio -name 'archiso*' -type f -delete
1400 sed -i 's/volatile/auto/g' $MNT/etc/systemd/journald.conf
1401 find $MNT/boot -name '*-ucode.img' -delete
1403 if [[ $DIST != "ArchLabs" ]]; then
1404 for f in $MNT/etc/{lsb-release,os-release}; do
1405 sed -i "s/ArchLabs/$DIST/g" $MNT/etc/{lsb-release,os-release}
1410 find $MNT/etc/X11/xorg.conf.d/ -name '*.conf' -delete
1411 elif lspci | grep ' VGA ' | grep -q 'Intel'; then
1412 cat > $MNT/etc/X11/xorg.conf.d/20-intel.conf <<- EOF
1414 Identifier "Intel Graphics"
1416 Option "TearFree" "true"
1421 [[ -e /run/archiso/sfs/airootfs && $KERNEL == 'linux' ]] && cp -vf $RUN/x86_64/vmlinuz $MNT/boot/vmlinuz-linux
1423 cp -fv /etc/resolv.conf $MNT/etc/
1424 [[ -e /etc/NetworkManager/system-connections ]] && cp -rvf /etc/NetworkManager/system-connections $MNT/etc/NetworkManager/
1426 echo "LANG=$MYLOCALE" > $MNT/etc/locale.conf
1427 cp -f $MNT/etc/locale.conf $MNT/etc/default/locale
1428 sed -i "s/#en_US.UTF-8/en_US.UTF-8/g; s/#${MYLOCALE}/${MYLOCALE}/g" $MNT/etc/locale.gen
1430 chrun "ln -svf /usr/share/zoneinfo/$ZONE/$SUBZ /etc/localtime"
1432 cat > $MNT/etc/X11/xorg.conf.d/00-keyboard.conf <<- EOF
1433 # Use localectl(1) to instruct systemd-localed to update it.
1434 Section "InputClass"
1435 Identifier "system-keyboard"
1436 MatchIsKeyboard "on"
1437 Option "XkbLayout" "$KEYMAP"
1441 cat > $MNT/etc/default/keyboard <<- EOF
1442 # KEYBOARD CONFIGURATION FILE
1443 # Consult the keyboard(5) manual page.
1450 printf "KEYMAP=%s\nFONT=%s\n" "$CMAP" "$FONT" > $MNT/etc/vconsole.conf
1451 echo "$MYHOST" > $MNT/etc/hostname
1452 cat > $MNT/etc/hosts <<- EOF
1455 ::1 localhost ip6-localhost ip6-loopback
1456 ff02::1 ip6-allnodes
1457 ff02::2 ip6-allrouters
1463 echo "Installing $BOOTLDR"
1465 if [[ $ROOT_PART == /dev/mapper* ]]; then
1466 ROOT_PART_ID="$ROOT_PART"
1468 local uuid_type="UUID"
1469 [[ $BOOTLDR =~ (systemd-boot|refind-efi|efistub) ]] && uuid_type="PARTUUID"
1470 ROOT_PART_ID="$uuid_type=$(blkid -s $uuid_type -o value $ROOT_PART)"
1473 if [[ $SYS == 'UEFI' ]]; then
1474 # remove our old install and generic BOOT/ dir
1475 find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname "$DIST" -type d -delete
1476 find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname 'BOOT' -type d -delete
1480 chrun "${BCMDS[$BOOTLDR]}" 2>$ERR
1481 errshow 1 "${BCMDS[$BOOTLDR]}"
1483 if [[ -d $MNT/hostrun ]]; then
1484 # cleanup the bind mounts we made earlier for the grub-probe module
1485 umount_dir $MNT/hostrun/{udev,lvm}
1486 rm -rf $MNT/hostrun >/dev/null 2>&1
1489 if [[ $SYS == 'UEFI' ]]; then
1490 # some UEFI firmware requires a generic esp/BOOT/BOOTX64.EFI
1491 mkdir -pv $MNT/$BOOTDIR/EFI/BOOT
1492 if [[ $BOOTLDR == 'grub' ]]; then
1493 cp -fv $MNT/$BOOTDIR/EFI/$DIST/grubx64.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI
1494 elif [[ $BOOTLDR == 'syslinux' ]]; then
1495 cp -rf $MNT/$BOOTDIR/EFI/syslinux/* $MNT/$BOOTDIR/EFI/BOOT/
1496 cp -f $MNT/$BOOTDIR/EFI/syslinux/syslinux.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI
1497 elif [[ $BOOTLDR == 'refind-efi' ]]; then
1498 sed -i '/#extra_kernel_version_strings/ c extra_kernel_version_strings linux-hardened,linux-zen,linux-lts,linux' $MNT/$BOOTDIR/EFI/refind/refind.conf
1499 cp -fv $MNT/$BOOTDIR/EFI/refind/refind_x64.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI
1508 echo "Creating new user $NEWUSER and setting password"
1509 rm -f $MNT/root/.zshrc # remove welcome message from root zshrc
1511 chrun "chpasswd <<< 'root:$ROOT_PASS'" 2>$ERR
1512 errshow 1 "set root password"
1513 if [[ $MYSHELL != "/usr/bin/zsh" ]]; then # root uses zsh by default, change it if something else was chosen
1514 chrun "usermod -s $MYSHELL root" 2>$ERR
1515 errshow 1 "usermod -s $MYSHELL root"
1516 # copy the default mkshrc to /root if mksh was picked
1517 [[ $MYSHELL == '/usr/bin/mksh' ]] && cp -fv $MNT/etc/skel/.mkshrc $MNT/root/.mkshrc
1520 local groups='audio,floppy,log,network,rfkill,scanner,storage,optical,power,wheel'
1522 chrun "useradd -m -u 1000 -g users -G $groups -s $MYSHELL $NEWUSER" 2>$ERR
1523 errshow 1 "useradd -m -u 1000 -g users -G $groups -s $MYSHELL $NEWUSER"
1524 chrun "chpasswd <<< '$NEWUSER:$USER_PASS'" 2>$ERR
1525 errshow 1 "set $NEWUSER password"
1527 # if neovim was picked copy vim configs to ~/.config/nvim
1528 if [[ $USER_PKGS == *neovim* ]]; then
1529 mkdir -p $MNT/home/$NEWUSER/.config/nvim
1530 cp -fv $MNT/home/$NEWUSER/.vimrc $MNT/home/$NEWUSER/.config/nvim/init.vim
1531 cp -rfv $MNT/home/$NEWUSER/.vim/colors $MNT/home/$NEWUSER/.config/nvim/colors
1534 [[ $INSTALL_WMS == *dwm* ]] && install_suckless
1536 [[ $WM_PKGS == *xfce* ]] && echo 'volumeicon &' >> $MNT/home/$NEWUSER/.xprofile
1538 # remove some commands from ~/.xprofile when using KDE or Gnome as the login session
1539 if [[ $LOGIN_WM =~ (startkde|gnome-session) || ($LOGIN_TYPE =~ (lightdm|ly) && $WM_PKGS =~ (plasma|gnome)) ]]; then
1540 sed -i '/super/d' $MNT/home/$NEWUSER/.xprofile $MNT/root/.xprofile
1541 sed -i '/nitrogen/d' $MNT/home/$NEWUSER/.xprofile $MNT/root/.xprofile
1542 sed -i '/compton/d' $MNT/home/$NEWUSER/.xprofile $MNT/root/.xprofile
1545 # create user home directories (Music, Documents, Downloads, etc..)
1546 chrun 'xdg-user-dirs-update'
1553 local serv="$MNT/etc/systemd/system/getty@tty1.service.d"
1555 echo "Setting up $LOGIN_TYPE"
1558 ly|sddm|gdm|lightdm)
1559 rm -rf "$serv" "$MNT/home/$NEWUSER/.xinitrc"
1560 chrun "systemctl enable $LOGIN_TYPE.service" 2>$ERR
1561 errshow 1 "systemctl enable $LOGIN_TYPE.service"
1562 if [[ $LOGIN_TYPE == 'lightdm' ]]; then
1563 cat > $MNT/etc/lightdm/lightdm-gtk-greeter.conf <<- EOF
1565 default-user-image=/usr/share/icons/ArchLabs-Dark/64x64/places/distributor-logo-archlabs.png
1566 background=/usr/share/backgrounds/archlabs/archlabs.jpg
1567 theme-name=Adwaita-dark
1568 icon-theme-name=Adwaita
1569 font-name=DejaVu Sans Mono 11
1570 position=30%,end 50%,end
1575 if [[ $INSTALL_WMS ]]; then
1576 sed -i "/exec/ c exec ${LOGIN_WM}" "$MNT/home/$NEWUSER/.xinitrc"
1577 elif [[ -e $MNT/home/$NEWUSER/.xinitrc ]]; then
1578 sed -i '/exec/d' "$MNT/home/$NEWUSER/.xinitrc"
1581 if [[ $AUTOLOGIN ]]; then
1582 sed -i "s/root/${NEWUSER}/g" $serv/autologin.conf
1583 cat > "$MNT/home/$NEWUSER/$LOGINRC" <<- EOF
1584 # automatically run startx when logging in on tty1
1585 [ -z \$DISPLAY ] && [ \$XDG_VTNR -eq 1 ] && exec startx
1596 local rmpkg="archlabs-installer "
1597 local inpkg="$BASE_PKGS ${LOGIN_PKGS[$LOGIN_TYPE]} $PACKAGES $USER_PKGS "
1599 # add extra packages chosen throughout the install
1600 if [[ $MYSHELL == '/usr/bin/zsh' ]]; then
1601 inpkg+="zsh-completions "
1604 [[ $MYSHELL == '/usr/bin/mksh' ]] && inpkg+="mksh "
1607 # using a different kernel, remove the stock one
1608 if [[ $KERNEL != 'linux' ]]; then
1613 # gnome, plasma, and cinnamon have their own superkey bind and ksuperkey conflicts
1614 [[ $INSTALL_WMS =~ ^(plasma|gnome|cinnamon)$ ]] || inpkg+="archlabs-ksuperkey "
1616 # window manager only packages
1617 [[ $INSTALL_WMS =~ (openbox|bspwm|i3-gaps|dwm|fluxbox) ]] && inpkg+="$WM_BASE_PKGS "
1619 # ensure a terminal gets installed if one wasn't chosen or a DE that installs one
1620 [[ $inpkg =~ (term|urxvt|tilix|alacritty|sakura|tilda|plasma|cinnamon) || $INSTALL_WMS == *dwm* ]] || inpkg+="xterm "
1622 # update first to avoid issues
1623 chrun "pacman -Syyu --noconfirm"
1625 # remove the packages we don't want on the installed system
1626 [[ $rmpkg ]] && chrun "pacman -Rnsc $rmpkg --noconfirm"
1628 # reinstalling iputils fixes the network issue for non-root users
1629 chrun "pacman -S iputils $UCODE --noconfirm"
1631 # install the packages chosen throughout the install
1632 chrun "pacman -S $inpkg --needed --noconfirm" 2>$ERR
1633 errshow 1 "pacman -S $inpkg --needed --noconfirm"
1635 # bootloader packages
1636 if [[ $BOOTLDR == 'grub' ]]; then
1637 [[ $SYS == 'UEFI' ]] && local efib="efibootmgr"
1638 chrun "pacman -S os-prober grub $efib --needed --noconfirm" 2>$ERR
1639 errshow 1 "pacman -S os-prober grub $efib --needed --noconfirm"
1640 elif [[ $BOOTLDR == 'refind-efi' ]]; then
1641 chrun "pacman -S refind-efi efibootmgr --needed --noconfirm" 2>$ERR
1642 errshow 1 "pacman -S refind-efi efibootmgr --needed --noconfirm"
1643 elif [[ $SYS == 'UEFI' ]]; then
1644 chrun "pacman -S efibootmgr --needed --noconfirm" 2>$ERR
1645 errshow 1 "pacman -S efibootmgr --needed --noconfirm"
1648 # allow members of the wheel group to run commands as root
1649 sed -i "s/# %wheel ALL=(ALL) ALL/%wheel ALL=(ALL) ALL/g" $MNT/etc/sudoers
1656 mkdir -pv "$MNT/home/$NEWUSER/suckless"
1658 for i in dwm dmenu st; do
1659 if chrun "git clone https://git.suckless.org/$i /home/$NEWUSER/suckless/$i"; then
1660 chrun "cd /home/$NEWUSER/suckless/$i; make PREFIX=/usr install; make clean; rm config.h"
1662 printf "failed to clone %s repo\n" "$i"
1666 if [[ -x $MNT/usr/bin/dwm ]]; then
1667 printf "To configure dwm edit %s\n" "/home/$NEWUSER/suckless/dwm/config.h"
1668 printf "You can then recompile it with 'sudo make clean install'\n"
1673 install_mkinitcpio()
1677 # luks keyfile creation
1678 # currently not used due to not prompting for passphrase on startup
1679 # [[ $LUKS_UUID && $LUKS_PASS && $SYS == 'UEFI' && $BOOTLDR == 'grub' ]] && luks_keyfile
1681 [[ $LUKS ]] && add="encrypt"
1682 [[ $LVM ]] && { [[ $add ]] && add+=" lvm2" || add+="lvm2"; }
1683 sed -i "s/block filesystems/block ${add} filesystems ${HOOKS}/g" $MNT/etc/mkinitcpio.conf
1684 chrun "mkinitcpio -p $KERNEL" 2>$ERR
1685 errshow 1 "mkinitcpio -p $KERNEL"
1688 install_mirrorlist()
1690 local mfile="$1" # output mirrorlist file
1692 if hash reflector >/dev/null 2>&1; then
1693 reflector --verbose --score 80 -l 40 -f 5 --sort rate --save "$mfile"
1694 elif hash rankmirrors >/dev/null 2>&1; then
1695 echo "Sorting mirrorlist"
1696 local key="access_key=5f29642060ab983b31fdf4c2935d8c56"
1697 ip_add="$(curl -fsSL "http://api.ipstack.com/check&?$key&fields=ip" | python -c "import sys, json; print(json.load(sys.stdin)['ip'])")"
1698 country="$(curl -fsSL "http://api.ipstack.com/$ip_add?$key&fields=country_code" | python -c "import sys, json; print(json.load(sys.stdin)['country_code'])")"
1699 if [[ "$country" ]]; then
1700 if [[ $country =~ (CA|US) ]]; then
1701 # use both CA and US mirrors for CA or US countries
1702 mirror="https://www.archlinux.org/mirrorlist/?country=US&country=CA&use_mirror_status=on"
1703 elif [[ $country =~ (AU|NZ) ]]; then
1704 # use both AU and NZ mirrors for AU or NZ countries
1705 mirror="https://www.archlinux.org/mirrorlist/?country=AU&country=NZ&use_mirror_status=on"
1707 mirror="https://www.archlinux.org/mirrorlist/?country=${country}&use_mirror_status=on"
1709 else # no country code so just grab all mirrors, will be a very slow sort but we don't have other options
1710 mirror="https://www.archlinux.org/mirrorlist/?country=all&use_mirror_status=on"
1712 curl -fsSL "$mirror" | sed -e 's/^#Server/Server/' -e '/^#/d' | rankmirrors -n 6 - >"$mfile"
1718 install_background()
1720 msg "Background Install" "\nInstall will now begin in the background?\n" 2
1721 rsync -a /run/archiso/sfs/airootfs/ $MNT/ &
1723 ( install_mirrorlist "$MNT/etc/pacman.d/mirrorlist" >>/tmp/bg_out 2>&1 ) &
1725 # end the background processes before exiting
1726 trap "kill $RSYNC_PID $MIRROR_PID 2>/dev/null" EXIT
1729 ###############################################################################
1731 # prerun_* set up the configs needed before actually running the commands
1732 # setup_* are run after selecting a bootloader and build the command used later
1733 # they can also be used for further user input as these run before control is taken away
1737 EDIT_FILES[bootloader]="/etc/default/grub"
1739 if [[ $SYS == 'BIOS' ]]; then
1740 [[ $BOOT_DEV ]] || { part_device 1 || return 1; }
1741 BCMDS[grub]="grub-install --recheck --force --target=i386-pc $BOOT_DEV"
1743 # since we're not using the keyfile this is dead code
1744 # if [[ $ROOT_PART == */dev/mapper/* && -z $LVM && -z $LUKS_PASS ]]; then
1745 # luks_pass "$_luksopen" 1 || return 1
1747 BCMDS[grub]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1748 grub-install --recheck --force --target=x86_64-efi --efi-directory=/$BOOTDIR --bootloader-id=$DIST"
1749 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1752 BCMDS[grub]="mkdir -p /run/udev /run/lvm &&
1753 mount --bind /hostrun/udev /run/udev &&
1754 mount --bind /hostrun/lvm /run/lvm &&
1756 grub-mkconfig -o /boot/grub/grub.cfg &&
1757 sleep 1 && umount /run/udev /run/lvm"
1764 sed -i "s/GRUB_DISTRIBUTOR=.*/GRUB_DISTRIBUTOR=\"${DIST}\"/g; s/GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT=\"\"/g" $MNT/etc/default/grub
1766 if [[ $LUKS_DEV ]]; then
1767 sed -i "s~#GRUB_ENABLE_CRYPTODISK~GRUB_ENABLE_CRYPTODISK~g; s~GRUB_CMDLINE_LINUX=.*~GRUB_CMDLINE_LINUX=\"${LUKS_DEV}\"~g" $MNT/etc/default/grub 2>$ERR
1768 errshow 1 "sed -i 's~#GRUB_ENABLE_CRYPTODISK~GRUB_ENABLE_CRYPTODISK~g; s~GRUB_CMDLINE_LINUX=.*~GRUB_CMDLINE_LINUX=\"${LUKS_DEV}\"~g' $MNT/etc/default/grub"
1771 if [[ $SYS == 'BIOS' && $LVM && -z $SEP_BOOT ]]; then
1772 sed -i "s/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g" $MNT/etc/default/grub 2>$ERR
1773 errshow 1 "sed -i 's/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g' $MNT/etc/default/grub"
1776 # setup for os-prober module
1777 mkdir -p /run/{lvm,udev} $MNT/hostrun/{lvm,udev}
1778 mount --bind /run/lvm $MNT/hostrun/lvm
1779 mount --bind /run/udev $MNT/hostrun/udev
1786 EDIT_FILES[bootloader]=""
1791 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1792 efibootmgr -v -d $BOOT_DEV -p $BOOT_PART_NUM -c -L '${DIST} Linux' -l /vmlinuz-${KERNEL} \
1793 -u 'root=$ROOT_PART_ID rw $([[ $UCODE ]] && printf 'initrd=\%s.img ' "$UCODE")initrd=\initramfs-${KERNEL}.img'"
1798 if [[ $SYS == 'BIOS' ]]; then
1799 EDIT_FILES[bootloader]="/boot/syslinux/syslinux.cfg"
1801 EDIT_FILES[bootloader]="/boot/EFI/syslinux/syslinux.cfg"
1802 BCMDS[syslinux]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1803 efibootmgr -v -c -d $BOOT_DEV -p $BOOT_PART_NUM -l /EFI/syslinux/syslinux.efi -L $DIST"
1809 local c="$MNT/boot/syslinux" s="/usr/lib/syslinux/bios" d=".."
1810 [[ $SYS == 'UEFI' ]] && { c="$MNT/boot/EFI/syslinux"; s="/usr/lib/syslinux/efi64/"; d=''; }
1812 mkdir -pv "$c" && cp -rfv $s/* "$c/" && cp -f "$RUN/syslinux/splash.png" "$c/"
1813 cat > "$c/syslinux.cfg" <<- EOF
1815 MENU TITLE $DIST Boot Menu
1816 MENU BACKGROUND splash.png
1820 # see: https://www.syslinux.org/wiki/index.php/Comboot/menu.c32
1829 MENU HELPMSGENDROW 29
1830 MENU COLOR border 30;44 #40ffffff #a0000000 std
1831 MENU COLOR title 1;36;44 #9033ccff #a0000000 std
1832 MENU COLOR sel 7;37;40 #e0ffffff #20ffffff all
1833 MENU COLOR unsel 37;44 #50ffffff #a0000000 std
1834 MENU COLOR help 37;40 #c0ffffff #a0000000 std
1835 MENU COLOR timeout_msg 37;40 #80ffffff #00000000 std
1836 MENU COLOR timeout 1;37;40 #c0ffffff #00000000 std
1837 MENU COLOR msg07 37;40 #90ffffff #a0000000 std
1838 MENU COLOR tabmsg 31;40 #30ffffff #00000000 std
1841 MENU LABEL $DIST Linux
1842 LINUX $d/vmlinuz-$KERNEL
1843 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1844 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL.img
1846 LABEL ${DIST}fallback
1847 MENU LABEL $DIST Linux Fallback
1848 LINUX $d/vmlinuz-$KERNEL
1849 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1850 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL-fallback.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 msg "Info" "\nGathering device info.\n" 0
1935 is_bg_install || return 1
1938 dlg choice menu "Logical Volume Management" "$_lvmmenu" \
1939 "$_lvmnew" "vgcreate -f, lvcreate -L -n" \
1940 "$_lvmdel" "vgremove -f" \
1941 "$_lvmdelall" "lvrmeove, vgremove, pvremove -f" \
1942 "back" "return to the main menu"
1945 "$_lvmnew") lvm_create || return 1 ;;
1946 "$_lvmdel") lvm_delgroup && yesno "$_lvmdel" "$_lvmdelask" && vgremove -f "$DEL_VG" >/dev/null 2>&1 ;;
1947 "$_lvmdelall") lvm_del_all ;;
1956 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
1957 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
1958 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
1960 if [[ $VGROUP && $v && $pv ]]; then
1961 msg "Logical Volume Management" "\nActivating existing logical volume management (LVM).\n\n" 1
1962 modprobe dm-mod >/dev/null 2>$ERR
1963 errshow 'modprobe dm-mod'
1964 vgscan >/dev/null 2>&1
1965 vgchange -ay >/dev/null 2>&1
1971 VGROUP='' LVM_PARTS='' VGROUP_MB=0
1973 lvm_mkgroup || return 1
1974 local txt="\nThe last (or only) logical volume will automatically use all remaining space in the volume group."
1975 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
1976 [[ $VOL_COUNT ]] || return 1
1977 lvm_extra_lvs || return 1
1978 lvm_volume_name "$_lvmlvname\nNOTE: This LV will use up all remaining space in the volume group (${VGROUP_MB}MB)" || return 1
1979 lvcreate -l +100%FREE "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
1980 errshow "lvcreate -l +100%FREE $VGROUP -n $VNAME" || return 1
1981 LVM='logical volume'; sleep 0.5
1982 txt="\nDone, volume: $VGROUP-$VNAME (${VOLUME_SIZE:-${VGROUP_MB}MB}) has been created.\n"
1983 msg "$_lvmnew (LV:$VOL_COUNT)" "$txt\n$(lsblk -o NAME,MODEL,TYPE,FSTYPE,SIZE $LVM_PARTS)\n"
1989 local txt="${VGROUP}: ${SIZE}$SIZE_UNIT (${VGROUP_MB}MB remaining).$_lvmlvsize"
1993 dlg VOLUME_SIZE input "$_lvmnew (LV:$VOL_COUNT)" "$txt" ''
1994 if [[ -z $VOLUME_SIZE ]]; then
1996 break # allow bailing with escape or an empty choice
1997 elif (( ${VOLUME_SIZE:0:1} == 0 )); then
1998 ERR_SIZE=1 # size values can't begin with '0'
2000 # walk the string and make sure all but the last char are digits
2001 local lv=$((${#VOLUME_SIZE} - 1))
2002 for (( i=0; i<lv; i++ )); do
2003 [[ ${VOLUME_SIZE:$i:1} =~ [0-9] ]] || { ERR_SIZE=1; break; }
2005 if (( ERR_SIZE != 1 )); then
2006 case ${VOLUME_SIZE:$lv:1} in
2007 [mMgG]) local s=${VOLUME_SIZE:0:$lv} m=$((s * 1000))
2008 case ${VOLUME_SIZE:$lv:1} in
2009 [Gg]) (( m >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - m)) ;;
2010 [Mm]) (( ${VOLUME_SIZE:0:$lv} >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - s)) ;;
2017 if (( ERR_SIZE )); then
2018 msg "Invalid Logical Volume Size" "$_lvmerrlvsize"
2031 until [[ $named ]]; do
2032 lvm_partitions || return 1
2033 lvm_group_name || return 1
2034 yesno "$_lvmnew" "\nConfirm creation of volume group: $VGROUP\n\nwith the following partition(s): $LVM_PARTS\n" && named=true
2037 msg "$_lvmnew" "\nCreating group: $VGROUP (${SIZE}$SIZE_UNIT)\n" 0
2038 vgcreate -f "$VGROUP" $LVM_PARTS >/dev/null 2>$ERR
2039 errshow "vgcreate -f $VGROUP $LVM_PARTS" || return 1
2041 SIZE=$(vgdisplay "$VGROUP" | awk '/VG Size/ { gsub(/[^0-9.]/, ""); print int($0) }')
2042 SIZE_UNIT="$(vgdisplay "$VGROUP" | awk '/VG Size/ { print substr($NF, 0, 1) }')"
2044 if [[ $SIZE_UNIT == 'G' ]]; then
2045 VGROUP_MB=$((SIZE * 1000))
2050 msg "$_lvmnew" "\nVolume group: $VGROUP (${SIZE}$SIZE_UNIT) has been created\n"
2057 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
2058 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
2059 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
2061 if [[ $VGROUP || $v || $pv ]]; then
2062 if yesno "$_lvmdelall" "$_lvmdelask"; then
2063 for i in $v; do lvremove -f "/dev/mapper/$i" >/dev/null 2>&1; done
2064 for i in $VGROUP; do vgremove -f "$i" >/dev/null 2>&1; done
2065 for i in $pv; do pvremove -f "$i" >/dev/null 2>&1; done
2069 msg "Delete LVM" "\nNo LVMs to remove...\n" 2
2079 for i in $(lvs --noheadings | awk '{print $2}' | uniq); do
2080 VOL_GROUP_LIST+="$i $(vgdisplay "$i" | awk '/VG Size/ {print $3$4}') "
2082 [[ $VOL_GROUP_LIST ]] || { msg "No Groups" "\nNo volume groups found."; return 1; }
2084 dlg DEL_VG menu "Logical Volume Management" "\nSelect volume group to delete.\n\nAll logical volumes within will also be deleted." $VOL_GROUP_LIST
2090 while (( VOL_COUNT > 1 )); do
2091 lvm_volume_name "$_lvmlvname" && get_lv_size || return 1
2092 lvcreate -L "$VOLUME_SIZE" "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
2093 errshow "lvcreate -L $VOLUME_SIZE $VGROUP -n $VNAME" || return 1
2094 msg "$_lvmnew (LV:$VOL_COUNT)" "\nDone, logical volume (LV) $VNAME ($VOLUME_SIZE) has been created.\n"
2102 part_find 'part|crypt' || return 1
2103 PARTS="$(awk 'NF > 0 {print $0 " off"}' <<< "$PARTS")"
2104 dlg LVM_PARTS check "$_lvmnew" "\nSelect the partition(s) to use for the physical volume (PV)." $PARTS
2111 until [[ $VGROUP ]]; do
2112 dlg VGROUP input "$_lvmnew" "$_lvmvgname" "mygroup"
2113 if [[ -z $VGROUP ]]; then
2115 elif [[ ${VGROUP:0:1} == "/" || $VGROUP =~ \ |\' ]] || vgdisplay | grep -q "$VGROUP"; then
2116 msg "LVM Name Error" "$_lvmerrvgname"
2126 local txt="$1" default="mainvolume"
2127 (( VOL_COUNT > 1 )) && default="extravolume$VOL_COUNT"
2128 until [[ $VNAME ]]; do
2129 dlg VNAME input "$_lvmnew (LV:$VOL_COUNT)" "\n$txt" "$default"
2130 if [[ -z $VNAME ]]; then
2132 elif [[ ${VNAME:0:1} == "/" || $VNAME =~ \ |\' ]] || lsblk | grep -q "$VNAME"; then
2133 msg "LVM Name Error" "$_lvmerlvname"
2140 ###############################################################################
2146 is_bg_install || return 1
2147 dlg choice menu "LUKS Encryption" "$_luksmenu" \
2148 "$_luksnew" "cryptsetup -q luksFormat" \
2149 "$_luksopen" "cryptsetup open --type luks" \
2150 "$_luksadv" "cryptsetup -q -s -c luksFormat" \
2151 "back" "Return to the main menu"
2154 "$_luksnew") luks_basic || return 1 ;;
2155 "$_luksopen") luks_open || return 1 ;;
2156 "$_luksadv") luks_advanced || return 1 ;;
2164 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
2166 part_find 'part|crypt|lvm' || return 1
2168 if (( COUNT == 1 )); then
2169 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2171 dlg LUKS_PART menu "$_luksopen" "\nSelect which partition to open." $PARTS
2174 [[ $LUKS_PART ]] || return 1
2176 luks_pass "$_luksopen" || return 1
2177 msg "$_luksopen" "\nOpening encrypted partition: $LUKS_NAME\n\nUsing device/volume: $LUKS_PART\n" 0
2178 cryptsetup open --type luks "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2179 errshow "cryptsetup open --type luks $LUKS_PART $LUKS_NAME" || return 1
2180 LUKS='encrypted'; luks_show
2187 local t="$1" op="$2" v='' p='' p2=''
2189 until [[ $LUKS_PASS ]]; do
2193 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " $t " \
2194 --mixedform "\nEnter the password to decrypt $ROOT_PART\n\nThis is needed to create a keyfile." 0 0 0 \
2195 "Password:" 1 1 '' 1 11 "$COLUMNS" 0 1 \
2196 "Password2:" 2 1 '' 2 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
2199 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " $t " --mixedform "$_luksomenu" 0 0 0 \
2200 "Name:" 1 1 "${LUKS_NAME:-cryptroot}" 1 7 "$COLUMNS" 0 0 \
2201 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
2202 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
2206 while read -r line; do
2222 if [[ -z $op && -z $n ]]; then
2223 msg "Name Empty" "\nEncrypted device name cannot be empty.\n\nPlease try again.\n" 2
2224 elif [[ -z $p || "$p" != "$p2" ]]; then
2225 [[ $op ]] || LUKS_NAME="$n"
2226 msg "Password Mismatch" "\nThe passwords entered do not match.\n\nPlease try again.\n" 2
2228 [[ $op ]] || LUKS_NAME="$n"
2239 msg "$_luksnew" "\nEncrypted partition ready for mounting.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$LUKS_PART")\n\n"
2244 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
2246 part_find 'part|lvm' || return 1
2248 if [[ $AUTO_ROOT_PART ]]; then
2249 LUKS_PART="$AUTO_ROOT_PART"
2250 elif (( COUNT == 1 )); then
2251 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2253 dlg LUKS_PART menu "$_luksnew" "\nSelect the partition you want to encrypt." $PARTS
2256 [[ $LUKS_PART ]] || return 1
2257 luks_pass "$_luksnew"
2262 luks_setup || return 1
2263 msg "$_luksnew" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2264 cryptsetup -q luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2265 errshow "cryptsetup -q luksFormat $LUKS_PART" || return 1
2266 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2267 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2268 LUKS='encrypted'; luks_show
2274 if [[ ! -e $MNT/crypto_keyfile.bin ]]; then
2275 # printf "Creating LUKS keyfile /crypto_keyfile.bin\n"
2277 n="$(lsblk -lno NAME,UUID,TYPE | awk "/$LUKS_UUID/"' && /part|crypt|lvm/ {print $1}')"
2278 local mkkey="dd bs=512 count=8 if=/dev/urandom of=/crypto_keyfile.bin"
2279 mkkey="$mkkey && chmod 000 /crypto_keyfile.bin"
2280 mkkey="$mkkey && cryptsetup luksAddKey /dev/$n /crypto_keyfile.bin <<< '$LUKS_PASS'"
2282 sed -i 's/FILES=()/FILES=(\/crypto_keyfile.bin)/g' $MNT/etc/mkinitcpio.conf 2>$ERR
2292 dlg cipher input "LUKS Encryption" "$_lukskey" "-s 512 -c aes-xts-plain64"
2293 [[ $cipher ]] || return 1
2294 msg "$_luksadv" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2295 cryptsetup -q $cipher luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2296 errshow "cryptsetup -q $cipher luksFormat $LUKS_PART" || return 1
2297 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2298 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2305 ###############################################################################
2307 # some help avoid repetition and improve usability of some commands
2308 # others are initial setup functions used before reaching the main loop
2312 # does $2 contain $1
2313 [[ "$2" == *"$1"* ]] && printf "on" || printf "off"
2318 # cleanup and exit the installer cleanly with exit code $1
2319 # when ecode is 127 unmount /run/archiso/bootmnt and reboot
2324 if [[ -d $MNT ]] && command cd /; then
2326 if (( ecode == 127 )); then
2327 umount_dir /run/archiso/bootmnt
2338 local var="$1" # assign output from dialog to var
2339 local dlg_t="$2" # dialog type (menu, check, input)
2340 local title="$3" # dialog title
2341 local body="$4" # dialog message
2342 local n=0 # number of items to display
2344 shift 4 # shift off args assigned above
2346 # when passed a large amount of arguments (menu list) adjust menu height
2347 (( ($# / 2) > SHL )) && n=$SHL
2351 menu) dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --menu "$body" 0 0 $n "$@" 2>"$ANS" || return 1 ;;
2352 check) dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --checklist "$body" 0 0 $n "$@" 2>"$ANS" || return 1 ;;
2355 local def="$1" # assign default value for input
2357 if [[ $1 == 'limit' ]]; then
2358 dialog --backtitle "$DIST Installer - $SYS - v$VER" --max-input 63 --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2360 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2364 # if answer file isn't empty read from it into $var
2365 [[ -s "$ANS" ]] && printf -v "$var" "%s" "$(< "$ANS")"
2370 # displays a message dialog
2371 # when more than 2 args the message will disappear after sleep time ($3)
2377 dialog --backtitle "$DIST Installer - $SYS - v$VER" --sleep "$1" --title " $title " --infobox "$body\n" 0 0
2379 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --msgbox "$body\n" 0 0
2385 local title="$1" body="$2" yes='Yes' no='No'
2386 (( $# >= 3 )) && yes="$3"
2387 (( $# >= 4 )) && no="$4"
2389 if (( $# == 5 )); then
2390 dialog --backtitle "$DIST Installer - $SYS - v$VER" --defaultno --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2392 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2398 arch-chroot "$MNT" bash -c "$1"
2403 export PS4='| ${BASH_SOURCE} LINE:${LINENO} FUNC:${FUNCNAME[0]:+ ${FUNCNAME[0]}()} |> '
2412 printf "\n^C caught, cleaning up...\n"
2419 "\e]P0191919" # #191919
2420 "\e]P1D15355" # #D15355
2421 "\e]P2609960" # #609960
2422 "\e]P3FFCC66" # #FFCC66
2423 "\e]P4255A9B" # #255A9B
2424 "\e]P5AF86C8" # #AF86C8
2425 "\e]P62EC8D3" # #2EC8D3
2426 "\e]P7949494" # #949494
2427 "\e]P8191919" # #191919
2428 "\e]P9D15355" # #D15355
2429 "\e]PA609960" # #609960
2430 "\e]PBFF9157" # #FF9157
2431 "\e]PC4E88CF" # #4E88CF
2432 "\e]PDAF86C8" # #AF86C8
2433 "\e]PE2ec8d3" # #2ec8d3
2434 "\e]PFE1E1E1" # #E1E1E1
2437 [[ $TERM == 'linux' ]] && printf "%b" "${colors[@]}" && clear
2442 [ $? -eq 0 ] && return 0
2444 local fatal=0 err=""
2445 err="$(sed 's/[^[:print:]]//g; s/\[[0-9\;:]*\?m//g; s/==> //g; s/] ERROR:/]\nERROR:/g' "$ERR")"
2447 (( $1 == 1 )) && { fatal=1; shift; }
2449 local txt="\nThe command exited abnormally:\n\n$1\n\n"
2452 txt+="With the following message:\n\n$err\n\n"
2454 txt+="With no error message:\n\n"
2457 if (( fatal )); then
2458 txt+="Errors at this stage are fatal and the install cannot continue.\n"
2460 txt+="Errors at this stage are non-fatal and can be either fixed or ignored depending on the error.\n"
2462 msg "Install Error" "$txt"
2464 if (( fatal )); then
2465 [[ -r $DBG && $TERM == 'linux' ]] && less "$DBG"
2476 if (( $1 >= 0 )) && ! grep -qw "$MNT" /proc/mounts; then
2477 msg "Not Mounted" "\nPartition(s) must be mounted first.\n" 2
2479 elif [[ $1 -ge 1 && -z $BOOTLDR ]]; then
2480 msg "No Bootloader" "\nBootloader must be selected first.\n" 2
2482 elif [[ $1 -ge 2 && (-z $NEWUSER || -z $USER_PASS) ]]; then
2483 msg "No User" "\nA user must be created first.\n" 2
2485 elif [[ $1 -ge 3 && -z $CONFIG_DONE ]]; then
2486 msg "Not Configured" "\nSystem configuration must be done first.\n" 2
2489 (( i )) # return code
2494 mount | grep -q 'swap' && swapoff -a
2496 [[ -d $dir && "$(mount | grep "on $dir ")" ]] || continue
2497 umount "$dir" 2>/dev/null || { sleep 0.5; umount -f "$dir" 2>/dev/null || umount -l "$dir"; }
2503 msg "Network Connect" "\nVerifying network connection\n" 1
2504 curl -sIN --connect-timeout 5 'https://www.archlinux.org/' | sed '1q' | grep -q '200'
2509 if chk_connect; then
2512 if hash nmtui >/dev/null 2>&1; then
2514 if [[ $TERM == 'linux' ]]; then
2515 printf "%b" "\e]P1191919" "\e]P4191919"
2517 printf "%b" "\e]P1D15355" "\e]P4255a9b"
2530 [[ $RSYNC_PID || $MIRROR_PID ]] || return 0
2531 msg "Install Running" "\nA background install process is currently running.\n" 2
2537 IGNORE_DEV="$(lsblk -lno NAME,MOUNTPOINT | awk '/\/run\/archiso\/bootmnt/ {sub(/[1-9]/, ""); print $1}')"
2539 if [[ $IGNORE_DEV ]]; then
2540 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ && !'"/$IGNORE_DEV/"' {print "/dev/" $1 " " $2}')"
2542 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ {print "/dev/" $1 " " $2}')"
2545 if [[ -z $SYS_DEVS ]]; then
2546 msg "Device Error" "\nNo available devices...\n\nExiting..\n" 2
2551 while read -r line; do
2553 done <<< "$SYS_DEVS"
2560 elif grep -q 'AuthenticAMD' /proc/cpuinfo; then
2562 elif grep -q 'GenuineIntel' /proc/cpuinfo; then
2566 modprobe -q efivarfs >/dev/null 2>&1
2568 _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."
2569 if [[ -d /sys/firmware/efi/efivars ]]; then
2571 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars
2572 _prep+="\n - An EFI boot partition mounted."
2576 _prep+="\n\nOnce finished mounting, a portion of the install can be done in the background while you continue configuring the system:\n"
2577 _prep+="\n - Choose the system bootloader.\n - Create a user and password."
2578 _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."
2581 ###############################################################################
2584 # enable some nicer colours in the linux console
2587 if (( UID != 0 )); then
2588 msg "Not Root" "\nThis installer must be run as root or using sudo.\n\nExiting..\n" 2
2590 elif ! grep -qwm 1 'lm' /proc/cpuinfo; then
2591 msg "Not x86_64 Architecture" "\nThis installer only supports x86_64 architectures.\n\nExiting..\n" 2
2593 elif [[ $1 =~ (-d|--debug) ]]; then
2597 # trap ^C to perform cleanup
2603 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"
2605 select_keymap || { clear; die 0; }
2606 net_connect || { msg "Not Connected" "\nThis installer requires an active internet connection.\n\nExiting..\n" 2; die 1; }
2612 # vim:fdm=marker:fmr={,}