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
17 VER="2.0.70" # installer version
18 MNT="/mnt" # install mountpoint
19 ANS="/tmp/ans" # dialog answer file
21 # ------------------------------------------------------ #
22 # When manually mounting your partitions, you need
23 # to set these values to avoid using the mount menu.
24 # ------------------------------------------------------ #
26 # root partition, eg. /dev/sda2
29 # boot partition, required on UEFI eg. /dev/sda1
32 # boot device, used for some bootloaders eg. /dev/sda
35 # bootloader to use, can be:
36 # UEFI: grub, syslinux, efistub, systemd-boot, refind-efi
37 # BIOS: grub, syslinux
40 # directory to mount the boot partition (if any) for most bootloaders
41 # this will need to be 'boot' however a popular one for grub is 'boot/efi'
44 # ------------------------------------------------------ #
46 # bulk default values {
48 # these values will be selected during the install, it is not recommended
49 # to edit them here unless you know what you're doing.
51 SWAP_PART='' # swap partition or file path
52 SWAP_SIZE='' # swap size, only used when creating a swapfile
54 EXMNT='' # holder for additional partitions while mounting
55 EXMNTS='' # when an extra partition is mounted append it's info
57 FONT="ter-i16n" # font used for the linux console
58 HOOKS="shutdown" # list of additional HOOKS to add in /etc/mkinitcpio.conf
60 LOGIN_TYPE='' # login manager can be: lightdm, xinit, ly
61 LOGIN_WM='' # default login session to be placed in ~/.xinitrc
62 LOGINRC='' # login shell rc file, eg. .zprofile, .bash_profile, .profile
63 AUTOLOGIN='' # enable autologin for xinit
65 INSTALL_WMS='' # space separated list of chosen wm/de
67 WM_PKGS='' # list of packages added during wm/de choice (not user edited)
68 PACKAGES='' # list of all packages to install including WM_PKGS (not user edited)
69 USER_PKGS='' # packages selected by the user during install
71 NEWUSER='' # username for the new user
72 USER_PASS='' # new user's password
73 ROOT_PASS='' # root password
75 KERNEL='' # linux kernel, can be: linux, linux-lts, linux-zen, or linux-hardened
76 MYSHELL='' # shell to use for the system, eg. zsh
77 UCODE='' # cpu microcode (if any), can be: amd-ucode, intel-ucode
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 CONFIG_DONE='' # basic configuration is finished
94 FORMATTED='' # partitions we formatted and should allow skipping
95 AUTO_ROOT_PART='' # root value from auto partition
96 AUTO_BOOT_PART='' # boot value from auto partition
98 SEL=0 # currently selected menu item
99 ERR="/tmp/errlog" # error log used internally
100 DBG="/tmp/debuglog" # debug log when passed -d
101 RUN="/run/archiso/bootmnt/arch/boot" # path for live system /boot
102 VM="$(dmesg | grep -i "hypervisor")" # system running in a virtual machine
103 SYS='Unknown' # bios type to be determined: UEFI/BIOS
104 export DIALOGOPTS="--cr-wrap" # see `man dialog`
107 BASE_PKGS="base-devel xorg xorg-drivers sudo git gvfs gtk3 pavucontrol tumbler xdg-user-dirs playerctl "
108 BASE_PKGS+="ffmpeg gstreamer libmad libmatroska gst-libav gst-plugins-base gst-plugins-good scrot"
111 AL_BASE_PKGS="archlabs-skel-base archlabs-fonts archlabs-themes archlabs-icons archlabs-wallpapers archlabs-scripts archlabs-baph"
113 # extras for window managers
114 WM_BASE_PKGS="arandr archlabs-networkmanager-dmenu nitrogen polkit-gnome volumeicon xclip exo laptop-detect "
115 WM_BASE_PKGS+="xdotool compton wmctrl gnome-keyring dunst feh gsimplecal xfce4-power-manager xfce4-settings"
119 # giant ugly variable container :P {
122 SYS_MEM="$(awk '/MemTotal/ {print int($2 / 1024) "M"}' /proc/meminfo)"
124 # locales from /etc/locale.gen
125 LOCALES="$(awk '/\.UTF-8/ {gsub(/# .*|#/, ""); if ($1) {print $1 " - "}}' /etc/locale.gen)"
127 # console keyboard mappings
128 CMAPS="$(find /usr/share/kbd/keymaps -name '*.map.gz' | awk '{gsub(/\.map\.gz|.*\//, ""); print $1 " - "}' | sort)"
131 [[ $LINES ]] || LINES=$(tput lines)
132 [[ $COLUMNS ]] || COLUMNS=$(tput cols)
137 # commands used to install each bootloader, however most get modified during runtime {
139 [refind-efi]='refind-install' # minor modification
140 [grub]='grub-install --recheck --force' # heavily modified
141 [syslinux]='syslinux-install_update -i -a -m' # modified on UEFI
142 [efistub]='efibootmgr -v -d /dev/sda -p 1 -c -l' # heavily modified
143 [systemd-boot]='bootctl --path=/boot install' # not modified
146 # executable name for each wm/de used in ~/.xinitrc {
147 declare -A WM_SESSIONS=(
154 [gnome]='gnome-session'
155 [fluxbox]='startfluxbox'
156 [openbox]='openbox-session'
157 [cinnamon]='cinnamon-session'
160 # packages installed for each wm/de, most are depends of the skel packages {
164 [cinnamon]='gnome-terminal' # doesn't install a terminal on it's own
165 [plasma]='kdebase-meta' # base plasma application set
166 [awesome]='archlabs-skel-awesome' # see deps of archlabs-skel-awesome
167 [bspwm]='archlabs-skel-bspwm' # see deps of archlabs-skel-bspwm
168 [fluxbox]='archlabs-skel-fluxbox' # see deps of archlabs-skel-fluxbox
169 [i3-gaps]='archlabs-skel-i3-gaps' # see deps of archlabs-skel-i3-gaps
170 [openbox]='archlabs-skel-openbox' # see deps of archlabs-skel-openbox
171 [xfce4]='archlabs-skel-xfce4 xfce4-goodies' # see deps of archlabs-skel-xfce4
174 # files offered for editing after install is complete {
175 declare -A EDIT_FILES=(
176 [login]='' # login is populated once we know the username and shell
178 [sudoers]='/etc/sudoers'
179 [crypttab]='/etc/crypttab'
180 [pacman]='/etc/pacman.conf'
181 [console]='/etc/vconsole.conf'
182 [mkinitcpio]='/etc/mkinitcpio.conf'
183 [hostname]='/etc/hostname /etc/hosts'
184 [bootloader]="/boot/loader/entries/$DIST.conf" # ** based on bootloader
185 [locale]='/etc/locale.conf /etc/default/locale'
186 [keyboard]='/etc/X11/xorg.conf.d/00-keyboard.conf /etc/default/keyboard'
189 # mkfs command and flags for filesystem formatting {
194 [ntfs]='mkfs.ntfs -q'
195 [ext2]='mkfs.ext2 -q'
196 [ext3]='mkfs.ext3 -q'
197 [ext4]='mkfs.ext4 -q'
198 [vfat]='mkfs.vfat -F32'
199 [nilfs2]='mkfs.nilfs2 -q'
200 [reiserfs]='mkfs.reiserfs -q'
203 # mount options for each filesystem {
209 [jfs]='discard errors=continue errors=panic nointegrity'
210 [reiserfs]='acl nolog notail replayonly user_xattr off'
211 [ext4]='discard dealloc nofail noacl relatime noatime nobarrier nodelalloc'
212 [xfs]='discard filestreams ikeep largeio noalign nobarrier norecovery noquota wsync'
213 [nilfs2]='discard nobarrier errors=continue errors=panic order=relaxed order=strict norecovery'
214 [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'
217 # packages installed for each login option {
218 declare -A LOGIN_PKGS=(
223 [lightdm]='lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings accountsservice'
226 # extras installed for user selected packages {
227 # if a package requires additional packages that aren't already dependencies
228 # they can be added here eg. [package]="extra"
232 [mupdf]='mupdf-tools'
233 [qt5ct]='qt5-styleplugins'
234 [rxvt-unicode]='urxvt-pearls'
235 [vlc]='qt5ct qt5-styleplugins'
236 [zathura]='zathura-pdf-poppler'
237 [noto-fonts]='noto-fonts-emoji'
238 [cairo-dock]='cairo-dock-plug-ins'
239 [qutebrowser]='qt5ct qt5-styleplugins'
240 [qbittorrent]='qt5ct qt5-styleplugins'
241 [transmission-qt]='qt5ct qt5-styleplugins'
242 [bluez]='bluez-libs bluez-utils bluez-tools bluez-plugins bluez-hid2hci'
243 [kdenlive]='kdebase-meta dvdauthor frei0r-plugins breeze breeze-gtk qt5ct qt5-styleplugins'
248 # dialog text variables
251 # Basics (somewhat in order)
252 _welcome="\nThis will help you get $DIST installed and setup on your system.\n\nIf you are unsure about a section the default option will be listed or\nthe first selected item will be the default.\n\n\nMenu Navigation:\n\n - Select items with the arrow keys or the option number.\n - Use [Space] to toggle check boxes and [Enter] to accept.\n - Switch between fields 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"
253 _keymap="\nPick which keymap to use for the system from the list below\n\nThis is used once a graphical environment is running (Xorg).\n\nSystem default: us"
254 _vconsole="\nSelect the console keymap, the console is the tty shell you reach before starting a graphical environment (Xorg).\n\nIts keymap is seperate from the one used by the graphical environments, though many do use the same such as 'us' English.\n\nSystem default: us"
255 _device="\nSelect a device to use from the list below.\n\nDevices (/dev) are the available drives on the system. /sda, /sdb, /sdc ..."
256 _resize="\nSelect a new filesystem size in MB, a new partition will be created from the free space but will be left unformatted.\nThe lowest size is just enough to fit the currently in use space on the partition while the default is set to split the free space evenly.\n\nUse Tab or the arrow keys move the cursor between the buttons and the value, when the cursor is on the value, you can edit it by:\n\n - left/right cursor movement to select a digit to modify\n - +/- characters to increment/decrement the digit by one\n - 0 through 9 to set the digit to the given value\n\nSome keys are also recognized in all cursor positions:\n\n - Home/End set the value to its maximum or minimum\n - Pageup/Pagedown increment the value so that the slider moves by one column."
257 _mount="\nUse [Space] to toggle mount options from below, press [Enter] when done to confirm selection.\n\nNot selecting any and confirming will run an automatic mount."
258 _warn="\nIMPORTANT:\n\nChoose carefully when editing, formatting, and mounting partitions or your DATA MAY BE LOST.\n\nTo mount a partition without formatting it, select 'skip' when prompted to choose a filesystem during the mounting stage.\nThis can only be used for partitions that already contain a filesystem and cannot be the root (/) partition, it needs to be formatted before install.\n"
259 _part="\nFull device auto partitioning is available for beginners otherwise cfdisk is recommended.\n\n - All systems will require a root partition (8G or greater).\n - UEFI (and BIOS using LUKS without LVM) require a separate boot partition (100-512M)."
260 _uefi="\nSelect the EFI boot partition (/boot), required for UEFI boot.\n\nIt's usually the first partition on the device, 100-512M, and will be formatted as vfat/fat32 if not already."
261 _bios="\nDo you want to use a separate boot partition? (optional)\n\nIt's usually the first partition on the device, 100-512M, and will be formatted as ext3/4 if not already."
262 _biosluks="\nSelect the boot partition (/boot), required for LUKS.\n\nIt's usually the first partition on the device, 100-512M, and will be formatted as ext3/4 if not already."
263 _format="is already formatted correctly.\n\nFor a clean install, previously existing partitions should be reformatted, however this removes ALL data (bootloaders) on the partition so choose carefully.\n\nDo you want to reformat the partition?\n"
264 _swapsize="\nEnter the size of the swapfile in megabytes (M) or gigabytes (G).\n\neg. 100M will create a 100 megabyte swapfile, while 10G will create a 10 gigabyte swapfile.\n\nFor ease of use and as an example it is filled in to match the size of your system memory (RAM).\n\nMust be greater than 1, contain only whole numbers, and end with either M or G."
265 _expart="\nYou can now choose any additional partitions you want mounted, you'll be asked for a mountpoint after.\n\nSelect 'done' to finish the mounting step and begin unpacking the base system in the background."
266 _exmnt="\nWhere do you want the partition mounted?\n\nEnsure the name begins with a slash (/).\nExamples include: /usr, /home, /var, etc."
267 _user="\nEnter a name and password for the new user account.\n\nThe name must not use capital letters, contain any periods (.), end with a hyphen (-), or include any colons (:)\n\nNOTE: Use [Up], [Down], or [Tab] to switch between fields, and [Enter] to accept."
268 _hostname="\nEnter a hostname for the new system.\n\nA hostname is used to identify systems on the network.\n\nIt's restricted to alphanumeric characters (a-z, A-Z, 0-9).\nIt can contain hyphens (-) BUT NOT at the beggining or end."
269 _locale="\nLocale determines the system language and currency formats.\n\nThe format for locale names is languagecode_COUNTRYCODE\n\neg. en_US is: english United States\n en_GB is: english Great Britain"
270 _timez="\nThe time zone is used to set the system clock.\n\nSelect your country or continent from the list below"
271 _timesubz="\nSelect the nearest city to you or one with the same time zone.\n\nTIP: Pressing the first letter of the city name repeatedly will navigate between entries beggining with that letter."
272 _sessions="\nUse [Space] to toggle available sessions, use [Enter] to accept the selection and continue.\n\nA basic package set will be installed for compatibility and functionality."
273 _login="\nSelect which of your session choices to use for the initial login.\n\nYou can be change this later by editing your ~/.xinitrc"
274 _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"
275 _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."
276 _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."
279 _luksnew="Basic LUKS Encryption"
280 _luksadv="Advanced LUKS Encryption"
281 _luksopen="Open Existing LUKS Partition"
282 _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."
283 _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."
284 _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)."
287 _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."
288 _lvmnew="Create Volume Group and Volume(s)"
289 _lvmdel="Delete an Existing Volume Group"
290 _lvmdelall="Delete ALL Volume Group(s) and Volume(s)"
291 _lvmvgname="\nEnter a name for the volume group (VG) being created from the partition(s) selected."
292 _lvmlvname="\nEnter a name for the logical volume (LV) being created.\n\nThis is similar to setting a label for a partition."
293 _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."
294 _lvmdelask="\nConfirm deletion of volume group(s) and logical volume(s).\n\nDeleting a volume group, will delete all logical volumes within it.\n"
297 _errexpart="\nCannot mount partition due to a problem with the mountpoint.\n\nEnsure it begins with a slash (/) followed by atleast one character.\n"
298 _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"
299 _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"
300 _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"
301 _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"
302 _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"
303 _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"
309 ###############################################################################
311 # main is the entry point which calls functions including outside of its block
312 # once those functions finished they always are returned here with the
313 # exception of install_main(), it exits upon completion
317 (( SEL < 12 )) && (( SEL++ ))
319 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Prepare " --default-item $SEL --cancel-label 'Exit' --menu "$_prep" 0 0 0 \
320 1 "Device tree (optional)" \
321 2 "Partitioning (optional)" \
322 3 "LUKS setup (optional)" \
323 4 "LVM setup (optional)" \
324 5 "Mount partitions" \
325 6 "System bootloader" \
326 7 "User and password" \
327 8 "System configuration" \
328 9 "Select WM/DE (optional)" \
329 10 "Select Packages (optional)" \
330 11 "View configuration (optional)" \
331 12 "Start the installation" 2>"$ANS"
334 [[ -z $WARN && $SEL =~ (2|5) ]] && { msg "Data Warning" "$_warn"; WARN=true; }
337 2) part_menu || (( SEL-- )) ;;
338 3) luks_menu || (( SEL-- )) ;;
339 4) lvm_menu || (( SEL-- )) ;;
340 5) mount_menu || (( SEL-- )) ;;
341 6) prechecks 0 && { select_boot || (( SEL-- )); } ;;
342 7) prechecks 1 && { select_mkuser || (( SEL-- )); } ;;
343 8) prechecks 2 && { select_config || (( SEL-- )); } ;;
344 9) prechecks 3 && { select_sessions || (( SEL-- )); } ;;
345 10) prechecks 3 && { select_packages || (( SEL-- )); } ;;
346 11) prechecks 3 && select_show ;;
347 12) prechecks 3 && install_main ;;
348 *) yesno "Exit" "\nUnmount partitions (if any) and exit the installer?\n" && die 0
354 if [[ $SYS == 'BIOS' ]]; then
355 dlg BOOTLDR menu "BIOS Bootloader" "\nSelect which bootloader to use." \
356 "grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
357 "syslinux" "A collection of boot loaders for booting drives, CDs, or over the network" || return 1
359 dlg BOOTLDR menu "UEFI Bootloader" "\nSelect which bootloader to use." \
360 "systemd-boot" "A simple UEFI boot manager which executes configured EFI images" \
361 "grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
362 "refind-efi" "A UEFI boot manager that aims to be platform neutral and simplify multi-boot" \
363 "efistub" "Boot the kernel image directly (no chainloading support)" \
364 "syslinux" "A collection of boot loaders for booting drives, CDs, or over the network (no chainloading support)" || return 1
371 local pkgs="${USER_PKGS// / } ${PACKAGES// / }"
372 [[ $BOOT_PART ]] && local mnt="/$BOOTDIR"
373 [[ $INSTALL_WMS == *dwm* ]] && pkgs="dwm st dmenu $pkgs"
374 pkgs="${pkgs// / }" pkgs="${pkgs# }"
375 msg "Show Configuration" "
376 ---------- PARTITION CONFIGURATION ------------
378 Root: ${ROOT_PART:-none}
379 Boot: ${BOOT_PART:-${BOOT_DEV:-none}}
381 Swap: ${SWAP_PART:-none}
382 Size: ${SWAP_SIZE:-none}
383 Extra: ${EXMNTS:-${EXMNT:-none}}
384 Hooks: ${HOOKS:-none}
390 ------------ SYSTEM CONFIGURATION -------------
392 Locale: ${MYLOCALE:-none}
393 Keymap: ${KEYMAP:-none}
394 Hostname: ${MYHOST:-none}
395 Timezone: ${ZONE:-none}/${SUBZ:-none}
398 ------------ USER CONFIGURATION ---------------
400 Username: ${NEWUSER:-none}
401 Login Shell: ${MYSHELL:-none}
402 Login Session: ${LOGIN_WM:-none}
403 Autologin: ${AUTOLOGIN:-none}
404 Login Type: ${LOGIN_TYPE:-none}
407 ----------- PACKAGE CONFIGURATION -------------
409 Kernel: ${KERNEL:-none}
410 Bootloader: ${BOOTLDR:-none}
411 Packages: ${pkgs:-none}
417 [[ $INSTALL_WMS ]] || return 0
419 AUTOLOGIN='' # no autologin unless using xinit
421 dlg LOGIN_TYPE menu "Login Management" "\nSelect what kind of login management to use." \
422 "xinit" "Console login without a display manager" \
423 "ly" "TUI display manager with a ncurses-like interface" \
424 "lightdm" "Lightweight display manager with a gtk greeter" \
425 "gdm" "Gnome display manager" \
426 "sddm" "Simple desktop display manager" || return 1
429 ly) EDIT_FILES[login]="/etc/ly/config.ini" ;;
430 gdm|sddm) EDIT_FILES[login]="" ;;
431 lightdm) EDIT_FILES[login]="/etc/lightdm/lightdm.conf /etc/lightdm/lightdm-gtk-greeter.conf" ;;
432 xinit) EDIT_FILES[login]="/home/$NEWUSER/.xinitrc /home/$NEWUSER/.xprofile"
433 if (( $(wc -w <<< "$INSTALL_WMS") > 1 )); then
434 dlg LOGIN_WM menu "Login Management" "$_login" $LOGIN_CHOICES || return 1
435 LOGIN_WM="${WM_SESSIONS[$LOGIN_WM]}"
437 [[ -z $LOGIN_WM ]] && LOGIN_WM="${WM_SESSIONS[${INSTALL_WMS%% *}]}"
438 yesno "Autologin" "$(sed "s|USER|$NEWUSER|g; s|RC|$LOGINRC|g" <<< "$_autologin")" && AUTOLOGIN=true || AUTOLOGIN=''
448 until [[ $CONFIG_DONE ]]; do
450 0) dlg MYSHELL menu "Shell" "\nChoose which shell to use." \
451 zsh 'A very advanced and programmable command interpreter (shell) for UNIX' \
452 bash 'The GNU Bourne Again shell, standard in many GNU/Linux distributions' \
453 mksh 'The MirBSD Korn Shell - an enhanced version of the public domain ksh' || return 1
455 1) dlg MYHOST input "Hostname" "$_hostname" "${DIST,,}" limit || { i=0; continue; } ;;
456 2) dlg MYLOCALE menu "Locale" "$_locale" $LOCALES || { i=1; continue; } ;;
458 until [[ $ZONE && $SUBZ ]]; do
459 dlg ZONE menu "Timezone" "$_timez" America - Australia - Asia - Atlantic - Africa - Europe - Indian - Pacific - Arctic - Antarctica - || break
460 dlg SUBZ menu "Timezone" "$_timesubz" $(awk '/'"$ZONE"'\// {gsub(/'"$ZONE"'\//, ""); print $3 " - "}' /usr/share/zoneinfo/zone.tab | sort) || continue
462 [[ $ZONE && $SUBZ ]] || { i=2; continue; } ;;
463 4) dlg KERNEL menu "Kernel" "\nChoose which kernel to use." \
464 linux 'Vanilla linux kernel and modules, with a few patches applied' \
465 linux-lts 'Long-term support (LTS) linux kernel and modules' \
466 linux-zen 'A effort of kernel hackers to provide the best kernel for everyday systems' \
467 linux-hardened 'A security-focused linux kernel with hardening patches to mitigate exploits' || { i=3; continue; }
471 (( i++ )) # progress through to the next choice
474 case $MYSHELL in bash) LOGINRC='.bash_profile' ;; zsh) LOGINRC='.zprofile' ;; mksh) LOGINRC='.profile' ;; esac
482 local v='' u='' p='' p2='' rp='' rp2=''
484 until [[ $NEWUSER ]]; do
487 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " User " --mixedform "$_user" 0 0 0 \
488 "Username:" 1 1 "$u" 1 11 "$COLUMNS" 0 0 \
489 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
490 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 \
491 "--- Root password, if left empty the user password will be used ---" 6 1 '' 6 68 "$COLUMNS" 0 2 \
492 "Password:" 8 1 '' 8 11 "$COLUMNS" 0 1 \
493 "Password2:" 9 1 '' 9 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
495 while read -r line; do
496 case $i in 0) u="$line" ;; 1) p="$line" ;; 2) p2="$line" ;; 4) rp="$line" ;; 5) rp2="$line" ;; esac
500 # root passwords empty, so use the user passwords
501 [[ -z $rp && -z $rp2 ]] && { rp="$p"; rp2="$p2"; }
503 # make sure a username was entered and that the passwords match
504 if [[ ${#u} -eq 0 || $u =~ \ |\' || $u =~ [^a-z0-9] ]]; then
505 msg "Invalid Username" "\nIncorrect user name.\n\nPlease try again.\n"; u=''
506 elif [[ -z $p ]]; then
507 msg "Empty Password" "\nThe user password cannot be left empty.\n\nPlease try again.\n"
508 elif [[ "$p" != "$p2" ]]; then
509 msg "Password Mismatch" "\nThe user passwords do not match.\n\nPlease try again.\n"
510 elif [[ "$rp" != "$rp2" ]]; then
511 msg "Password Mismatch" "\nThe root passwords do not match.\n\nPlease try again.\n"
523 dlg KEYMAP menu "Keyboard Layout" "$_keymap" \
524 us English cm English gb English au English gh English \
525 za English ng English ca French 'cd' French gn French \
526 tg French fr French de German at German ch German \
527 es Spanish latam Spanish br Portuguese pt Portuguese ma Arabic \
528 sy Arabic ara Arabic ua Ukrainian cz Czech ru Russian \
529 sk Slovak nl Dutch it Italian hu Hungarian cn Chinese \
530 tw Taiwanese vn Vietnamese kr Korean jp Japanese th Thai \
531 la Lao pl Polish se Swedish is Icelandic 'fi' Finnish \
532 dk Danish be Belgian in Indian al Albanian am Armenian \
533 bd Bangla ba Bosnian 'bg' Bulgarian dz Berber mm Burmese \
534 hr Croatian gr Greek il Hebrew ir Persian iq Iraqi \
535 af Afghani fo Faroese ge Georgian ee Estonian kg Kyrgyz \
536 kz Kazakh lt Lithuanian mt Maltese mn Mongolian ro Romanian \
537 no Norwegian rs Serbian si Slovenian tj Tajik lk Sinhala \
538 tr Turkish uz Uzbek ie Irish pk Urdu 'mv' Dhivehi \
539 np Nepali et Amharic sn Wolof ml Bambara tz Swahili \
540 ke Swahili bw Tswana ph Filipino my Malay tm Turkmen \
541 id Indonesian bt Dzongkha lv Latvian md Moldavian mao Maori \
542 by Belarusian az Azerbaijani mk Macedonian kh Khmer epo Esperanto \
543 me Montenegrin || return 1
545 if [[ $CMAPS == *"$KEYMAP"* ]]; then
548 dlg CMAP menu "Console Keymap" "$_vconsole" $CMAPS || return 1
551 if [[ $DISPLAY && $TERM != 'linux' ]]; then
552 setxkbmap "$KEYMAP" >/dev/null 2>&1
554 loadkeys "$CMAP" >/dev/null 2>&1
563 dlg INSTALL_WMS check "Sessions" "$_sessions\n" \
564 openbox "A lightweight, powerful, and highly configurable stacking wm" "$(ofn openbox "${INSTALL_WMS[*]}")" \
565 i3-gaps "A fork of i3wm with more features including gaps" "$(ofn i3-gaps "${INSTALL_WMS[*]}")" \
566 dwm "A dynamic WM for X that manages windows in tiled, floating, or monocle layouts" "$(ofn dwm "${INSTALL_WMS[*]}")" \
567 bspwm "A tiling wm that represents windows as the leaves of a binary tree" "$(ofn bspwm "${INSTALL_WMS[*]}")" \
568 xfce4 "A lightweight and modular desktop environment based on gtk+2/3" "$(ofn xfce4 "${INSTALL_WMS[*]}")" \
569 awesome "A customized Awesome WM session created by @elanapan" "$(ofn awesome "${INSTALL_WMS[*]}")" \
570 fluxbox "A lightweight and highly-configurable window manager" "$(ofn fluxbox "${INSTALL_WMS[*]}")" \
571 plasma "A kde software project currently comprising a full desktop environment" "$(ofn plasma "${INSTALL_WMS[*]}")" \
572 gnome "A desktop environment that aims to be simple and easy to use" "$(ofn gnome "${INSTALL_WMS[*]}")" \
573 cinnamon "A desktop environment combining traditional desktop with modern effects" "$(ofn cinnamon "${INSTALL_WMS[*]}")"
575 [[ $INSTALL_WMS ]] || return 0
577 WM_PKGS="${INSTALL_WMS/dwm/}" # remove dwm from package list
578 WM_PKGS="${WM_PKGS// / }" # remove double spaces
579 WM_PKGS="${WM_PKGS# }" # remove leading space
581 # add archlabs base when choosing any session
582 [[ $WM_PKGS ]] && WM_PKGS+=" $AL_BASE_PKGS"
584 for i in $INSTALL_WMS; do
585 LOGIN_CHOICES+="$i - "
586 [[ ${WM_EXT[$i]} && $WM_PKGS != *"${WM_EXT[$i]}"* ]] && WM_PKGS+=" ${WM_EXT[$i]}"
589 select_login || return 1
591 while IFS=' ' read -r pkg; do
592 [[ $PACKAGES != *"$pkg"* ]] && PACKAGES+=" $pkg"
600 dlg USER_PKGS check " Packages " "$_packages" \
601 abiword "A Fully-featured word processor" "$(ofn abiword "${USER_PKGS[*]}")" \
602 alacritty "A cross-platform, GPU-accelerated terminal emulator" "$(ofn alacritty "${USER_PKGS[*]}")" \
603 atom "An open-source text editor developed by GitHub" "$(ofn atom "${USER_PKGS[*]}")" \
604 audacious "A free and advanced audio player based on GTK+" "$(ofn audacious "${USER_PKGS[*]}")" \
605 audacity "A program that lets you manipulate digital audio waveforms" "$(ofn audacity "${USER_PKGS[*]}")" \
606 blueman "GUI bluetooth device manager" "$(ofn blueman "${USER_PKGS[*]}")" \
607 bluez "Simple CLI based bluetooth support" "$(ofn bluez "${USER_PKGS[*]}")" \
608 cairo-dock "Light eye-candy fully themable animated dock" "$(ofn cairo-dock "${USER_PKGS[*]}")" \
609 calligra "A set of applications for productivity" "$(ofn calligra "${USER_PKGS[*]}")" \
610 chromium "An open-source web browser based on the Blink rendering engine" "$(ofn chromium "${USER_PKGS[*]}")" \
611 clementine "A modern music player and library organizer" "$(ofn clementine "${USER_PKGS[*]}")" \
612 cmus "A small, fast and powerful console music player" "$(ofn cmus "${USER_PKGS[*]}")" \
613 deadbeef "A GTK+ audio player for GNU/Linux" "$(ofn deadbeef "${USER_PKGS[*]}")" \
614 deluge "A BitTorrent client written in python" "$(ofn deluge "${USER_PKGS[*]}")" \
615 docky "Full fledged dock for opening applications and managing windows" "$(ofn docky "${USER_PKGS[*]}")" \
616 emacs "An extensible, customizable, self-documenting real-time display editor" "$(ofn emacs "${USER_PKGS[*]}")" \
617 epiphany "A GNOME web browser based on the WebKit rendering engine" "$(ofn epiphany "${USER_PKGS[*]}")" \
618 evince "A document viewer" "$(ofn evince "${USER_PKGS[*]}")" \
619 evolution "Manage your email, contacts and schedule" "$(ofn evolution "${USER_PKGS[*]}")" \
620 file-roller "Create and modify archives" "$(ofn file-roller "${USER_PKGS[*]}")" \
621 firefox "A popular open-source web browser from Mozilla" "$(ofn firefox "${USER_PKGS[*]}")" \
622 gcolor2 "A simple GTK+2 color selector" "$(ofn gcolor2 "${USER_PKGS[*]}")" \
623 geany "A fast and lightweight IDE" "$(ofn geany "${USER_PKGS[*]}")" \
624 geary "A lightweight email client for the GNOME desktop" "$(ofn geary "${USER_PKGS[*]}")" \
625 gimp "GNU Image Manipulation Program" "$(ofn gimp "${USER_PKGS[*]}")" \
626 gnome-calculator "GNOME Scientific calculator" "$(ofn gnome-calculator "${USER_PKGS[*]}")" \
627 gnome-disk-utility "Disk Management Utility" "$(ofn gnome-disk-utility "${USER_PKGS[*]}")" \
628 gnome-system-monitor "View current processes and monitor system state" "$(ofn gnome-system-monitor "${USER_PKGS[*]}")" \
629 gparted "A GUI frontend for creating and manipulating partition tables" "$(ofn gparted "${USER_PKGS[*]}")" \
630 gpick "Advanced color picker using GTK+ toolkit" "$(ofn gpick "${USER_PKGS[*]}")" \
631 gpicview "Lightweight image viewer" "$(ofn gpicview "${USER_PKGS[*]}")" \
632 guvcview "Capture video from camera devices" "$(ofn guvcview "${USER_PKGS[*]}")" \
633 hexchat "A popular and easy to use graphical IRC client" "$(ofn hexchat "${USER_PKGS[*]}")" \
634 inkscape "Professional vector graphics editor" "$(ofn inkscape "${USER_PKGS[*]}")" \
635 irssi "Modular text mode IRC client" "$(ofn irssi "${USER_PKGS[*]}")" \
636 kdenlive "A popular non-linear video editor for Linux" "$(ofn kdenlive "${USER_PKGS[*]}")" \
637 krita "Edit and paint images" "$(ofn krita "${USER_PKGS[*]}")" \
638 libreoffice-fresh "Full featured office suite" "$(ofn libreoffice-fresh "${USER_PKGS[*]}")" \
639 lollypop "A new music playing application" "$(ofn lollypop "${USER_PKGS[*]}")" \
640 mousepad "A simple text editor" "$(ofn mousepad "${USER_PKGS[*]}")" \
641 mpd "A flexible, powerful, server-side application for playing music" "$(ofn mpd "${USER_PKGS[*]}")" \
642 mpv "A media player based on mplayer" "$(ofn mpv "${USER_PKGS[*]}")" \
643 mupdf "Lightweight PDF and XPS viewer" "$(ofn mupdf "${USER_PKGS[*]}")" \
644 mutt "Small but very powerful text-based mail client" "$(ofn mutt "${USER_PKGS[*]}")" \
645 nautilus "The default file manager for Gnome" "$(ofn nautilus "${USER_PKGS[*]}")" \
646 ncmpcpp "A mpd client and almost exact clone of ncmpc with some new features" "$(ofn ncmpcpp "${USER_PKGS[*]}")" \
647 neovim "A fork of Vim aiming to improve user experience, plugins, and GUIs." "$(ofn neovim "${USER_PKGS[*]}")" \
648 nicotine+ "A graphical client for Soulseek" "$(ofn nicotine+ "${USER_PKGS[*]}")" \
649 noto-fonts "Google Noto fonts" "$(ofn noto-fonts "${USER_PKGS[*]}")" \
650 noto-fonts-cjk "Google Noto CJK fonts (Chinese, Japanese, Korean)" "$(ofn noto-fonts-cjk "${USER_PKGS[*]}")" \
651 obs-studio "Free opensource streaming/recording software" "$(ofn obs-studio "${USER_PKGS[*]}")" \
652 openshot "An open-source, non-linear video editor for Linux" "$(ofn openshot "${USER_PKGS[*]}")" \
653 opera "A Fast and secure, free of charge web browser from Opera Software" "$(ofn opera "${USER_PKGS[*]}")" \
654 pcmanfm "A fast and lightweight file manager based in Lxde" "$(ofn pcmanfm "${USER_PKGS[*]}")" \
655 pidgin "Multi-protocol instant messaging client" "$(ofn pidgin "${USER_PKGS[*]}")" \
656 plank "An elegant, simple, and clean dock" "$(ofn plank "${USER_PKGS[*]}")" \
657 qbittorrent "An advanced BitTorrent client" "$(ofn qbittorrent "${USER_PKGS[*]}")" \
658 qpdfview "A tabbed PDF viewer" "$(ofn qpdfview "${USER_PKGS[*]}")" \
659 qt5ct "GUI for managing Qt based application themes, icons, and fonts" "$(ofn qt5ct "${USER_PKGS[*]}")" \
660 qutebrowser "A keyboard-focused vim-like web browser based on Python and PyQt5" "$(ofn qutebrowser "${USER_PKGS[*]}")" \
661 rhythmbox "A Music playback and management application" "$(ofn rhythmbox "${USER_PKGS[*]}")" \
662 rxvt-unicode "A unicode enabled rxvt-clone terminal emulator" "$(ofn rxvt-unicode "${USER_PKGS[*]}")" \
663 sakura "A terminal emulator based on GTK and VTE" "$(ofn sakura "${USER_PKGS[*]}")" \
664 simple-scan "Simple scanning utility" "$(ofn simple-scan "${USER_PKGS[*]}")" \
665 simplescreenrecorder "A feature-rich screen recorder" "$(ofn simplescreenrecorder "${USER_PKGS[*]}")" \
666 steam "A popular game distribution platform by Valve" "$(ofn steam "${USER_PKGS[*]}")" \
667 surf "A simple web browser based on WebKit2/GTK+" "$(ofn surf "${USER_PKGS[*]}")" \
668 terminator "Terminal emulator that supports tabs and grids" "$(ofn terminator "${USER_PKGS[*]}")" \
669 termite "A minimal VTE-based terminal emulator" "$(ofn termite "${USER_PKGS[*]}")" \
670 thunar "A modern file manager for the Xfce Desktop Environment" "$(ofn thunar "${USER_PKGS[*]}")" \
671 thunderbird "Standalone mail and news reader from mozilla" "$(ofn thunderbird "${USER_PKGS[*]}")" \
672 tilda "A GTK based drop down terminal for Linux and Unix" "$(ofn tilda "${USER_PKGS[*]}")" \
673 tilix "A tiling terminal emulator for Linux using GTK+ 3" "$(ofn tilix "${USER_PKGS[*]}")" \
674 transmission-cli "Free BitTorrent client CLI" "$(ofn transmission-cli "${USER_PKGS[*]}")" \
675 transmission-gtk "GTK+ Front end for transmission" "$(ofn transmission-gtk "${USER_PKGS[*]}")" \
676 transmission-qt "Qt Front end for transmission" "$(ofn transmission-qt "${USER_PKGS[*]}")" \
677 ttf-anonymous-pro "A family fixed-width fonts designed with code in mind" "$(ofn ttf-anonymous-pro "${USER_PKGS[*]}")" \
678 ttf-fira-code "Monospaced font with programming ligatures" "$(ofn ttf-fira-code "${USER_PKGS[*]}")" \
679 ttf-font-awesome "Iconic font designed for Bootstrap" "$(ofn ttf-font-awesome "${USER_PKGS[*]}")" \
680 ttf-hack "A hand groomed typeface based on Bitstream Vera Mono" "$(ofn ttf-hack "${USER_PKGS[*]}")" \
681 vlc "A free and open source cross-platform multimedia player" "$(ofn vlc "${USER_PKGS[*]}")" \
682 weechat "Fast, light and extensible IRC client" "$(ofn weechat "${USER_PKGS[*]}")" \
683 xapps "Common library for X-Apps project" "$(ofn xapps "${USER_PKGS[*]}")" \
684 xarchiver "A GTK+ frontend to various command line archivers" "$(ofn xarchiver "${USER_PKGS[*]}")" \
685 xed "A small and lightweight text editor. X-Apps Project." "$(ofn xed "${USER_PKGS[*]}")" \
686 xfce-terminal "A terminal emulator based in the Xfce Desktop Environment" "$(ofn xfce-terminal "${USER_PKGS[*]}")" \
687 xreader "Document viewer for files like PDF and Postscript. X-Apps Project." "$(ofn xed "${USER_PKGS[*]}")" \
688 xterm "The standard terminal emulator for the X window system" "$(ofn xterm "${USER_PKGS[*]}")" \
689 zathura "Minimalistic document viewer" "$(ofn zathura "${USER_PKGS[*]}")"
691 if [[ $USER_PKGS ]]; then # add any needed PKG_EXT to the list
692 for i in $USER_PKGS; do
693 [[ ${PKG_EXT[$i]} && $USER_PKGS != *"${PKG_EXT[$i]}"* ]] && USER_PKGS+=" ${PKG_EXT[$i]}"
700 ###############################################################################
702 # non-essential partitioning helpers called by the user when using the optional
703 # partition menu and selecting a device to edit
707 no_bg_install || return 0
708 local device choice devhash
709 devhash="$(lsblk -f | base64)"
711 part_device || return 1
716 dlg choice menu "Edit Partitions" "$_part" \
717 "auto" "Whole device automatic partitioning" \
718 "shrink" "Shrink an existing ext2/3/4 or ntfs partition to make room for a new partition" \
719 "cfdisk" "Curses based variant of fdisk" \
720 "parted" "GNU partition editor" \
721 "fdisk" "Dialog-driven creation and manipulation of partitions" \
722 "done" "Return to the main menu"
724 if [[ -z $choice || $choice == 'done' ]]; then
726 elif [[ $choice == 'shrink' ]]; then
727 part_shrink "$device"
728 elif [[ $choice == 'auto' ]]; then
729 local root_size txt table boot_fs
730 root_size=$(lsblk -lno SIZE "$device" | awk 'NR == 1 {
733 print ($1 * 1000 - 512) / 1000 "G"
739 txt="\nWARNING:\n\nALL data on $device will be destroyed and the following partitions will be created\n\n- "
740 if [[ $SYS == 'BIOS' ]]; then
741 table="msdos" boot_fs="ext4"
742 txt+="An $boot_fs boot partition with the boot flag enabled (512M)\n- "
744 table="gpt" boot_fs="fat32"
745 txt+="A $boot_fs efi boot partition (512M)\n- "
747 txt+="An ext4 partition using all remaining space ($root_size)\n\nDo you want to continue?\n"
748 yesno "Auto Partition" "$txt" && msg "Info" "\nGathering device info.\n" 1 && part_auto "$device" "$table" "$boot_fs" "$root_size"
755 if [[ $devhash != "$(lsblk -f | base64)" ]]; then
756 msg "Probing Partitions" "\nInforming kernel of partition changes using partprobe\n" 0
757 partprobe >/dev/null 2>&1
758 [[ $choice == 'auto' ]] && return
766 if [[ $IGNORE_DEV ]]; then
767 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk "!/$IGNORE_DEV/"' && /disk|part|lvm|crypt|NAME/')"
769 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk '/disk|part|lvm|crypt|NAME/')"
771 msg "Device Tree" "\n\n$txt\n\n"
776 local device="$1" table="$2" boot_fs="$3" size="$4" dev_info=""
777 dev_info="$(parted -s "$device" print)"
779 msg "Auto Partition" "\nRemoving partitions on $device and setting table to $table\n" 1
782 while read -r PART; do
783 parted -s "$device" rm "$PART" >/dev/null 2>&1
784 done <<< "$(awk '/^ [1-9][0-9]?/ {print $1}' <<< "$dev_info" | sort -r)"
786 [[ $(awk '/Table:/ {print $3}' <<< "$dev_info") != "$table" ]] && parted -s "$device" mklabel "$table" >/dev/null 2>&1
788 msg "Auto Partition" "\nCreating a 512M $boot_fs boot partition.\n" 1
789 if [[ $SYS == "BIOS" ]]; then
790 parted -s "$device" mkpart primary "$boot_fs" 1MiB 513MiB >/dev/null 2>&1
792 parted -s "$device" mkpart ESP "$boot_fs" 1MiB 513MiB >/dev/null 2>&1
797 AUTO_BOOT_PART=$(lsblk -lno NAME,TYPE "$device" | awk 'NR==2 {print "/dev/" $1}')
799 if [[ $SYS == "BIOS" ]]; then
800 mkfs.ext4 -q "$AUTO_BOOT_PART" >/dev/null 2>&1
802 mkfs.vfat -F32 "$AUTO_BOOT_PART" >/dev/null 2>&1
805 msg "Auto Partition" "\nCreating a $size ext4 root partition.\n" 0
806 parted -s "$device" mkpart primary ext4 513MiB 100% >/dev/null 2>&1
808 AUTO_ROOT_PART="$(lsblk -lno NAME,TYPE "$device" | awk 'NR==3 {print "/dev/" $1}')"
809 mkfs.ext4 -q "$AUTO_ROOT_PART" >/dev/null 2>&1
811 FORMATTED+="$AUTO_BOOT_PART $AUTO_ROOT_PART "
812 msg "Auto Partition" "\nProcess complete.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$device")\n"
819 local device="$1" fs=""
821 part_find "${device##*/}[^ ]" || return 1
822 (( COUNT == 1 )) && part="$(awk '{print $1}' <<< "${PARTS[@]}" )"
824 if (( COUNT == 1 )) || dlg part menu "Resize" "\nWhich partition on $device do you want to resize?" $PARTS; then
825 fs=$(lsblk -lno FSTYPE "$part")
828 msg "Resize" "\nGathering device size info.\n" 0
830 end=$(parted -s "$device" unit KiB print | awk '/^\s*'"$num"'/ {print $3}') # part size in KiB
831 devsize=$(parted -s "$device" unit KiB print | awk '/Disk '"${device//\//\\/}"':/ {print $3}') # whole device size in KiB
832 mount "$part" $MNT >/dev/null 2>&1; sleep 0.5
833 min=$(df --output=used --block-size=MiB "$part" | awk 'NR == 2 {print int($1) + 256}')
834 max=$(df --output=avail --block-size=MiB "$part" | awk 'NR == 2 {print int($1)}')
837 if dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Resize: $part " --rangebox "$_resize" 17 "$COLUMNS" "$min" "$max" $((max / 2)) 2>$ANS; then
839 size=$((size * 1024))
846 if ntfsresize -fc "$part"; then
847 ntfsresize -ff --size $(( (size * 1024) / 1000 ))k "$part" 2>$ERR # k=10^3 bytes
848 errshow "ntfsresize -f -s $(( (size * 1024) / 1000 ))k $part" || return 1
850 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"
855 e2fsck -f "$part"; sleep 0.5
856 resize2fs -f "$part" ${size}K 2>$ERR # K=2^10 bytes
857 errshow "resize2fs -f $part ${size}K" || return 1
861 parted "$device" resizepart "$num" ${size}KiB || return 1
864 if [[ $devsize == "$end" ]]; then
865 parted -s "$device" mkpart primary ext4 ${size}KiB 100% 2>$ERR
866 errshow "parted -s $device mkpart primary ext4 ${size}KiB 100%" || return 1
868 parted -s "$device" mkpart primary ext4 ${size}KiB ${end}KiB 2>$ERR
869 errshow "parted -s $device mkpart primary ext4 ${size}KiB ${end}KiB" || return 1
871 msg "Resize Complete" "\n$part has been successfully resized to $((size / 1024))M.\n" 1
873 "") msg "No Filesystem" "\nFor unformatted partitions, cfdisk can be used in the partition menu.\n" ;;
874 *) msg "Invalid Filesystem: $fs" "\nResizing only supports ext and ntfs.\n" ;;
879 ###############################################################################
880 # partition management functions
881 # these are helpers for use by other functions to do essential setup/teardown
885 local regexp="$1" err=''
887 # string of partitions as /TYPE/PART SIZE
888 if [[ $IGNORE_DEV ]]; then
889 PARTS="$(lsblk -lno TYPE,NAME,SIZE |
890 awk "/$regexp/"' && !'"/$IGNORE_DEV/"' {
891 sub(/^part/, "/dev/")
892 sub(/^lvm|^crypt/, "/dev/mapper/")
896 PARTS="$(lsblk -lno TYPE,NAME,SIZE |
898 sub(/^part/, "/dev/")
899 sub(/^lvm|^crypt/, "/dev/mapper/")
904 # number of partitions total
906 while read -r line; do
910 # ensure we have enough partitions for the system and action type
912 'part|lvm|crypt') [[ $COUNT -lt 1 || ($SYS == 'UEFI' && $COUNT -lt 2) ]] && err="$_errpart" ;;
913 'part|crypt') (( COUNT < 1 )) && err="$_lvmerr" ;;
914 'part|lvm') (( COUNT < 2 )) && err="$_lukserr" ;;
917 # if there aren't enough partitions show the relevant error message
918 [[ $err ]] && { msg "Not Enough Partitions" "$err" 2; return 1; }
925 if [[ $1 == "$MNT/swapfile" && $SWAP_SIZE ]]; then
926 fallocate -l $SWAP_SIZE "$1" 2>$ERR
927 errshow "fallocate -l $SWAP_SIZE $1"
928 chmod 600 "$1" 2>$ERR
929 errshow "chmod 600 $1"
931 mkswap "$1" >/dev/null 2>$ERR
933 swapon "$1" >/dev/null 2>$ERR
940 local part="$1" mountp="${MNT}$2" fs=""
941 fs="$(lsblk -lno FSTYPE "$part")"
944 if [[ $fs && ${FS_OPTS[$fs]} && $part != "$BOOT_PART" ]] && select_mntopts "$fs"; then
945 mount -o "$MNT_OPTS" "$part" "$mountp" >/dev/null 2>&1
947 mount "$part" "$mountp" >/dev/null 2>&1
950 part_mountconf "$part" "$mountp" || return 1
958 local part="$1" fs="$2" delay="$3"
960 msg "Format" "\nFormatting $part as $fs\n" 0
961 ${FS_CMDS[$fs]} "$part" >/dev/null 2>$ERR
962 errshow "${FS_CMDS[$fs]} $part" || return 1
969 if [[ $DEV_COUNT -eq 1 && $SYS_DEVS ]]; then
970 DEVICE="$(awk '{print $1}' <<< "$SYS_DEVS")"
971 elif (( DEV_COUNT > 1 )); then
973 dlg DEVICE menu "Boot Device" "\nSelect the device to use for bootloader install." $SYS_DEVS
975 dlg DEVICE menu "Select Device" "$_device" $SYS_DEVS
977 [[ $DEVICE ]] || return 1
978 elif [[ $DEV_COUNT -lt 1 && ! $1 ]]; then
979 msg "Device Error" "\nNo available devices.\n\nExiting..\n" 2
983 [[ $1 ]] && BOOT_DEV="$DEVICE"
990 BOOT_DEV="${BOOT_PART%[1-9]}"
991 BOOT_PART_NUM="${BOOT_PART: -1}"
992 [[ $BOOT_PART = /dev/nvme* ]] && BOOT_DEV="${BOOT_PART%p[1-9]}"
993 if [[ $SYS == 'UEFI' ]]; then
994 parted -s $BOOT_DEV set $BOOT_PART_NUM esp on >/dev/null 2>&1
996 parted -s $BOOT_DEV set $BOOT_PART_NUM boot on >/dev/null 2>&1
1003 local part="$1" devs=""
1004 devs="$(lsblk -lno NAME,FSTYPE,TYPE)"
1006 # Identify if $part is LUKS+LVM, LVM+LUKS, LVM alone, or LUKS alone
1007 if lsblk -lno TYPE "$part" | grep -q 'crypt'; then
1009 LUKS_NAME="${part#/dev/mapper/}"
1010 for dev in $(awk '/lvm/ && /crypto_LUKS/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
1011 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1012 LUKS_DEV="$LUKS_DEV cryptdevice=$dev:$LUKS_NAME"
1013 LVM='logical volume'
1017 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
1018 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1019 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
1020 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
1024 elif lsblk -lno TYPE "$part" | grep -q 'lvm'; then
1025 LVM='logical volume'
1026 VNAME="${part#/dev/mapper/}"
1027 for dev in $(awk '/crypt/ && /lvm2_member/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
1028 if lsblk -lno NAME "$dev" | grep -q "$VNAME"; then
1029 LUKS_NAME="${dev/\/dev\/mapper\//}"
1033 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
1034 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1035 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
1036 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
1047 if (( COUNT > 0 )); then
1048 PARTS="$(sed "/${pt//\//\\/}/d" <<< "$PARTS")"
1056 if grep -qw "$1" /proc/mounts; then
1057 msg "Mount Success" "\nPartition $1 mounted at $2\n" 1
1061 msg "Mount Fail" "\nPartition $1 failed to mount at $2\n" 2
1066 ###############################################################################
1068 # mount_menu is the entry point which calls all other functions
1069 # once finished it returns to the main menu: main()
1073 msg "Info" "\nGathering device info.\n" 0
1074 no_bg_install || return 0
1077 part_find 'part|lvm|crypt' || { SEL=2; return 1; }
1079 [[ $LUKS && $LUKS_PART ]] && part_countdec $LUKS_PART
1080 [[ $LVM && $LVM_PARTS ]] && part_countdec $LVM_PARTS
1082 select_root_partition || return 1
1084 if [[ $SYS == 'UEFI' ]]; then
1085 select_efi_partition || { BOOT_PART=''; return 1; }
1086 elif (( COUNT > 0 )); then
1087 select_boot_partition || { BOOT_PART=''; return 1; }
1090 if [[ $BOOT_PART ]]; then
1091 part_mount "$BOOT_PART" "/$BOOTDIR" && SEP_BOOT=true || return 1
1095 select_swap || return 1
1096 select_extra_partitions || return 1
1104 dlg SWAP_PART menu "Swap Setup" "\nSelect whether to use a swapfile, swap partition, or none." \
1105 "none" "Don't allocate any swap space" \
1106 "swapfile" "Allocate $SYS_MEM at /swapfile" \
1109 if [[ -z $SWAP_PART || $SWAP_PART == "none" ]]; then
1112 elif [[ $SWAP_PART == "swapfile" ]]; then
1114 until [[ ${SWAP_SIZE:0:1} =~ [1-9] && ${SWAP_SIZE: -1} =~ (M|G) ]]; do
1115 (( 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
1116 dlg SWAP_SIZE input "Swap Setup" "$_swapsize" "$SYS_MEM" || { SWAP_PART=''; SWAP_SIZE=''; return 1; }
1119 part_swap "$MNT/$SWAP_PART"
1120 SWAP_PART="/$SWAP_PART"
1121 elif [[ $PARTS == *"$SWAP_PART"* ]]; then
1122 part_swap $SWAP_PART
1123 part_countdec $SWAP_PART
1124 SWAP_SIZE="$(lsblk -lno SIZE $SWAP_PART)"
1134 local fs="$1" opts=''
1135 local title="${fs^} Mount Options"
1137 for i in ${FS_OPTS[$fs]}; do
1141 until [[ $MNT_OPTS ]]; do
1142 dlg MNT_OPTS check "$title" "$_mount" $opts
1143 [[ $MNT_OPTS ]] || return 1
1144 MNT_OPTS="${MNT_OPTS// /,}"
1145 yesno "$title" "\nConfirm the following options: $MNT_OPTS\n" || MNT_OPTS=''
1154 until [[ $EXMNT ]]; do
1155 dlg EXMNT input "Extra Mount $part" "$_exmnt" "/" || return 1
1156 if [[ ${EXMNT:0:1} != "/" || ${#EXMNT} -le 1 || $EXMNT =~ \ |\' || $EXMNTS == *"$EXMNT"* ]]; then
1157 msg "Mountpoint Error" "$_errexpart"
1166 local part="$1" fs='' cur=''
1167 local txt="\nSelect which filesystem to use for: $part\n\nDefault: ext4"
1168 cur="$(lsblk -lno FSTYPE "$part" 2>/dev/null)"
1171 if [[ $cur && ($part != "$ROOT_PART" || $FORMATTED == *"$part"*) ]]; then
1172 dlg fs menu "Filesystem" "$txt\nCurrent: $cur" skip - ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1174 dlg fs menu "Filesystem" "$txt" ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1176 [[ $fs == 'skip' ]] && return 0
1177 yesno "Filesystem" "\nFormat $part as $fs?\n" || fs=''
1179 part_format "$part" "$fs"
1182 select_efi_partition()
1184 if [[ $AUTO_BOOT_PART ]]; then
1185 msg "EFI Boot Partition" "\nUsing partition created during automatic format.\n" 2
1186 BOOT_PART="$AUTO_BOOT_PART"; return 0 # were done here
1188 local pts size dev isize bsize ptcount=0
1190 # walk partition list and skip ones that are too small/big for boot
1191 while read -r dev size; do
1192 size_t="${size: -1:1}" # size type eg. K, M, G, T
1193 isize=${size:0:-1} # remove trailing size type character
1194 isize=${isize%.*} # remove any decimal (round down)
1195 [[ $size_t =~ [KT] || ($size_t == 'G' && $isize -gt 2) || ($size_t == 'M' && $isize -lt 100) ]] || { pts+="$dev $size "; (( ptcount++ )); }
1198 if (( ptcount == 1 )); then
1199 msg "EFI Boot Partition" "\nOnly one partition available that meets size requirements.\n" 1
1200 BOOT_PART="$(awk 'NF > 0 {print $1}' <<< "$pts")"
1202 dlg BOOT_PART menu "EFI Partition" "$_uefi" $pts
1206 [[ $BOOT_PART ]] || return 1
1208 if grep -q 'fat' <<< "$(fsck -N "$BOOT_PART")"; then
1209 local txt="\nIMPORTANT:\n\nThe EFI partition $BOOT_PART $_format"
1210 if yesno "Format EFI Partition" "$txt" "Format $BOOT_PART" "Skip Formatting" 1; then
1211 part_format "$BOOT_PART" "vfat" 2
1214 part_format "$BOOT_PART" "vfat" 2
1220 select_boot_partition()
1222 if [[ $AUTO_BOOT_PART && ! $LVM ]]; then
1223 msg "BIOS Boot Partition" "\nUsing partition created during automatic format.\n" 2
1224 BOOT_PART="$AUTO_BOOT_PART"; return 0 # were done here
1226 local pts size dev isize bsize ptcount=0
1228 # walk partition list and skip ones that are too small/big for boot
1229 while read -r dev size; do
1230 size_t="${size: -1:1}" # size type eg. K, M, G, T
1231 isize=${size:0:-1} # remove trailing size type character
1232 isize=${isize%.*} # remove any decimal (round down)
1233 [[ $size_t =~ [KT] || ($size_t == 'G' && $isize -gt 2) || ($size_t == 'M' && $isize -lt 100) ]] || { pts+="$dev $size "; (( ptcount++ )); }
1236 if [[ $LUKS && ! $LVM ]]; then
1237 dlg BOOT_PART menu "Boot Partition" "$_biosluks" $pts
1238 [[ $BOOT_PART ]] || return 1
1240 dlg BOOT_PART menu "Boot Partition" "$_bios" "skip" "don't use a separate boot" $pts
1241 [[ -z $BOOT_PART || $BOOT_PART == "skip" ]] && { BOOT_PART=''; return 0; }
1245 if grep -q 'ext[34]' <<< "$(fsck -N "$BOOT_PART")"; then
1246 local txt="\nIMPORTANT:\n\nThe boot partition $BOOT_PART $_format"
1247 if yesno "Format Boot Partition" "$txt" "Format $BOOT_PART" "Skip Formatting" 1; then
1248 part_format "$BOOT_PART" "ext4" 2
1251 part_format "$BOOT_PART" "ext4" 2
1256 select_root_partition()
1258 if [[ $AUTO_ROOT_PART && -z $LVM && -z $LUKS ]]; then
1259 ROOT_PART="$AUTO_ROOT_PART"
1260 msg "Select Root Partition (/)" "\nUsing partition created during automatic format.\n" 2
1261 part_mount "$ROOT_PART" || { ROOT_PART=''; return 1; }
1262 return 0 # we're done here
1264 local pts size dev isize bsize ptcount=0
1266 # walk partition list and skip ones that are too small for / (root)
1267 while read -r dev size; do
1268 size_t="${size: -1:1}" # size type eg. K, M, G, T
1269 isize=${size:0:-1} # remove trailing size type character
1270 isize=${isize%.*} # remove any decimal (round down)
1271 [[ $size_t =~ [MK] || ($size_t == 'G' && $isize -lt 4) ]] || { pts+="$dev $size "; (( ptcount++ )); }
1274 if (( ptcount == 1 )); then # only one available device
1275 msg "Select Root Partition (/)" "\nOnly one partition available that meets size requirements.\n" 2
1276 ROOT_PART="$(awk 'NF > 0 {print $1}' <<< "$pts")"
1278 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
1281 [[ $ROOT_PART ]] || return 1
1283 select_filesystem "$ROOT_PART" || { ROOT_PART=''; return 1; }
1284 part_mount "$ROOT_PART" || { ROOT_PART=''; return 1; }
1289 select_extra_partitions()
1293 # walk partition list and skip ones that are too small to be usable
1294 while read -r dev size; do
1295 [[ ${size: -1:1} =~ [KM] ]] && part_countdec "$dev"
1298 while (( COUNT > 0 )); do
1300 dlg part menu 'Mount Extra' "$_expart" 'done' 'finish mounting step' $PARTS || break
1301 if [[ $part == 'done' ]]; then
1303 elif select_filesystem "$part" && select_mountpoint && part_mount "$part" "$EXMNT"; then
1304 EXMNTS+="$part: $EXMNT "
1305 [[ $EXMNT == '/usr' && $HOOKS != *usr* ]] && HOOKS="usr $HOOKS"
1313 ###############################################################################
1315 # main is the entry point which calls all other install functions, once
1316 # complete it shows a dialog to edit files on the new system before reboot
1321 genfstab -U $MNT >$MNT/etc/fstab 2>$ERR
1322 errshow 1 "genfstab -U $MNT >$MNT/etc/fstab"
1323 [[ -f $MNT/swapfile ]] && sed -i "s~${MNT}~~" $MNT/etc/fstab
1327 chrun "hwclock --systohc --utc" || chrun "hwclock --systohc --utc --directisa"
1330 chrun "chown -Rf $NEWUSER:users /home/$NEWUSER"
1333 dlg choice menu "Finalization" "$_edit" \
1334 finished "exit the installer and reboot" \
1335 keyboard "${EDIT_FILES[keyboard]}" \
1336 console "${EDIT_FILES[console]}" \
1337 locale "${EDIT_FILES[locale]}" \
1338 hostname "${EDIT_FILES[hostname]}" \
1339 sudoers "${EDIT_FILES[sudoers]}" \
1340 mkinitcpio "${EDIT_FILES[mkinitcpio]}" \
1341 fstab "${EDIT_FILES[fstab]}" \
1342 crypttab "${EDIT_FILES[crypttab]}" \
1343 bootloader "${EDIT_FILES[bootloader]}" \
1344 pacman "${EDIT_FILES[pacman]}" \
1345 login "${EDIT_FILES[login]}"
1347 if [[ -z $choice || $choice == 'finished' ]]; then
1348 [[ $DEBUG == true && -r $DBG ]] && $EDITOR $DBG
1352 for f in ${EDIT_FILES[$choice]}; do
1353 [[ -e ${MNT}$f ]] && exists+=" ${MNT}$f"
1355 if [[ $exists ]]; then
1358 msg "File Missing" "\nThe file(s) selected do not exist:\n\n${EDIT_FILES[$choice]}\n"
1368 while kill -0 "$RSYNC_PID" 2>/dev/null || kill -0 "$MIRROR_PID" 2>/dev/null; do
1370 printf "\nOne or more background install processes are still running...\n"
1374 unset RSYNC_PID MIRROR_PID
1376 rm -rf $MNT/etc/mkinitcpio-archiso.conf
1377 find $MNT/usr/lib/initcpio -name 'archiso*' -type f -delete
1378 sed -i 's/#\(Storage=\)volatile/\1auto/' $MNT/etc/systemd/journald.conf
1379 find $MNT/boot -name '*-ucode.img' -delete
1381 [[ $DIST != "ArchLabs" ]] || sed -i "s/ArchLabs/$DIST/g" $MNT/etc/{lsb-release,os-release}
1384 find $MNT/etc/X11/xorg.conf.d/ -name '*.conf' -delete
1385 elif lspci | grep ' VGA ' | grep -q 'Intel'; then
1386 echo "Creating Intel VGA Tear Free config /etc/X11/xorg.conf.d/20-intel.conf"
1387 cat > $MNT/etc/X11/xorg.conf.d/20-intel.conf <<- EOF
1389 Identifier "Intel Graphics"
1391 Option "TearFree" "true"
1396 [[ -e /run/archiso/sfs/airootfs && $KERNEL == 'linux' ]] && cp -vf $RUN/x86_64/vmlinuz $MNT/boot/vmlinuz-linux
1398 cp -fv /etc/resolv.conf $MNT/etc/
1399 [[ -e /etc/NetworkManager/system-connections ]] && cp -rvf /etc/NetworkManager/system-connections $MNT/etc/NetworkManager/
1401 echo "LANG=$MYLOCALE" > $MNT/etc/locale.conf
1402 cp -fv $MNT/etc/locale.conf $MNT/etc/default/locale
1403 sed -i "s/#en_US.UTF-8/en_US.UTF-8/g; s/#${MYLOCALE}/${MYLOCALE}/g" $MNT/etc/locale.gen
1405 chrun "ln -svf /usr/share/zoneinfo/$ZONE/$SUBZ /etc/localtime"
1407 cat > $MNT/etc/X11/xorg.conf.d/00-keyboard.conf <<- EOF
1408 # Use localectl(1) to instruct systemd-localed to update it.
1409 Section "InputClass"
1410 Identifier "system-keyboard"
1411 MatchIsKeyboard "on"
1412 Option "XkbLayout" "$KEYMAP"
1416 cat > $MNT/etc/default/keyboard <<- EOF
1417 # KEYBOARD CONFIGURATION FILE
1418 # Consult the keyboard(5) manual page.
1425 printf "KEYMAP=%s\nFONT=%s\n" "$CMAP" "$FONT" > $MNT/etc/vconsole.conf
1426 echo "$MYHOST" > $MNT/etc/hostname
1427 cat > $MNT/etc/hosts <<- EOF
1430 ::1 localhost ip6-localhost ip6-loopback
1431 ff02::1 ip6-allnodes
1432 ff02::2 ip6-allrouters
1438 echo "Installing $BOOTLDR"
1440 if [[ $ROOT_PART == /dev/mapper* ]]; then
1441 ROOT_PART_ID="$ROOT_PART"
1443 local uuid_type="UUID"
1444 [[ $BOOTLDR =~ (systemd-boot|refind-efi|efistub) ]] && uuid_type="PARTUUID"
1445 ROOT_PART_ID="$uuid_type=$(blkid -s $uuid_type -o value $ROOT_PART)"
1448 if [[ $SYS == 'UEFI' ]]; then
1449 # remove our old install and generic BOOT/ dir
1450 find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname "$DIST" -type d -delete
1451 find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname 'BOOT' -type d -delete
1455 chrun "${BCMDS[$BOOTLDR]}" 2>$ERR
1456 errshow 1 "${BCMDS[$BOOTLDR]}"
1458 if [[ -d $MNT/hostrun ]]; then
1459 # cleanup the bind mounts we made earlier for the grub-probe module
1460 umount_dir $MNT/hostrun/{udev,lvm}
1461 rm -rf $MNT/hostrun >/dev/null 2>&1
1464 if [[ $SYS == 'UEFI' ]]; then
1465 # some UEFI firmware requires a generic esp/BOOT/BOOTX64.EFI
1466 mkdir -pv $MNT/$BOOTDIR/EFI/BOOT
1468 grub) cp -fv $MNT/$BOOTDIR/EFI/$DIST/grubx64.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI ;;
1469 syslinux) cp -rf $MNT/$BOOTDIR/EFI/syslinux/* $MNT/$BOOTDIR/EFI/BOOT/ && cp -f $MNT/$BOOTDIR/EFI/syslinux/syslinux.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI ;;
1470 refind-efi) sed -i '/#extra_kernel_version_strings/ c extra_kernel_version_strings linux-hardened,linux-zen,linux-lts,linux' $MNT/$BOOTDIR/EFI/refind/refind.conf
1471 cp -fv $MNT/$BOOTDIR/EFI/refind/refind_x64.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI ;;
1480 rm -f $MNT/root/.zshrc # remove welcome message from root zshrc
1482 chrun "chpasswd <<< 'root:$ROOT_PASS'" 2>$ERR
1483 errshow 1 "set root password"
1484 if [[ $MYSHELL != 'zsh' ]]; then # root uses zsh by default
1485 chrun "usermod -s /bin/$MYSHELL root" 2>$ERR
1486 errshow 1 "usermod -s /bin/$MYSHELL root"
1487 # copy the default mkshrc to /root if it was selected
1488 [[ $MYSHELL == 'mksh' ]] && cp -fv $MNT/etc/skel/.mkshrc $MNT/root/.mkshrc
1491 echo "Creating new user $NEWUSER and setting password"
1492 local groups='audio,floppy,log,network,rfkill,scanner,storage,optical,power,wheel'
1494 chrun "useradd -m -u 1000 -g users -G $groups -s /bin/$MYSHELL $NEWUSER" 2>$ERR
1495 errshow 1 "useradd -m -u 1000 -g users -G $groups -s /bin/$MYSHELL $NEWUSER"
1496 chrun "chpasswd <<< '$NEWUSER:$USER_PASS'" 2>$ERR
1497 errshow 1 "set $NEWUSER password"
1499 if [[ $INSTALL_WMS == *dwm* ]];then
1500 mkdir -pv "$mnt/home/$newuser/suckless"
1501 for i in dwm dmenu st; do
1502 if chrun "git clone https://git.suckless.org/$i /home/$newuser/suckless/$i"; then
1503 chrun "cd /home/$newuser/suckless/$i; make prefix=/usr install; make clean; rm config.h"
1505 printf "failed to clone %s repo\n" "$i"
1510 [[ $WM_PKGS == *xfce* ]] && echo 'volumeicon &' >> $MNT/home/$NEWUSER/.xprofile
1512 # remove some commands from ~/.xprofile when using KDE or Gnome as the login session
1513 if [[ $LOGIN_WM =~ (startkde|gnome-session) || ($LOGIN_TYPE =~ (lightdm|ly) && $WM_PKGS =~ (plasma|gnome)) ]]; then
1514 sed -i '/super/d' $MNT/home/$NEWUSER/.xprofile $MNT/root/.xprofile
1515 sed -i '/nitrogen/d' $MNT/home/$NEWUSER/.xprofile $MNT/root/.xprofile
1516 sed -i '/compton/d' $MNT/home/$NEWUSER/.xprofile $MNT/root/.xprofile
1519 # create user home directories (Music, Documents, Downloads, etc..)
1520 chrun 'xdg-user-dirs-update'
1527 local serv="$MNT/etc/systemd/system/getty@tty1.service.d"
1528 echo "Setting up $LOGIN_TYPE"
1530 ly|sddm|gdm|lightdm)
1531 rm -rf "$serv" "$MNT/home/$NEWUSER/.xinitrc"
1532 chrun "systemctl enable $LOGIN_TYPE.service" 2>$ERR
1533 errshow 1 "systemctl enable $LOGIN_TYPE.service"
1534 if [[ $LOGIN_TYPE == 'lightdm' ]]; then
1535 cat > $MNT/etc/lightdm/lightdm-gtk-greeter.conf <<- EOF
1537 default-user-image=/usr/share/icons/ArchLabs-Dark/64x64/places/distributor-logo-archlabs.png
1538 background=/usr/share/backgrounds/archlabs/archlabs.jpg
1539 theme-name=Adwaita-dark
1540 icon-theme-name=Adwaita
1541 font-name=DejaVu Sans Mono 11
1542 position=30%,end 50%,end
1547 if [[ $INSTALL_WMS ]]; then
1548 sed -i "/exec/ c exec ${LOGIN_WM}" "$MNT/home/$NEWUSER/.xinitrc"
1549 elif [[ -e $MNT/home/$NEWUSER/.xinitrc ]]; then
1550 sed -i '/exec/d' "$MNT/home/$NEWUSER/.xinitrc"
1553 if [[ $AUTOLOGIN ]]; then
1554 sed -i "s/root/${NEWUSER}/g" $serv/autologin.conf
1555 cat > "$MNT/home/$NEWUSER/$LOGINRC" <<- EOF
1556 # automatically run startx when logging in on tty1
1557 [ -z \$DISPLAY ] && [ \$XDG_VTNR -eq 1 ] && exec startx
1568 local rmpkg="archlabs-installer "
1569 local inpkg="$BASE_PKGS ${LOGIN_PKGS[$LOGIN_TYPE]} $PACKAGES $USER_PKGS "
1571 case $MYSHELL in zsh) inpkg+="zsh-completions " ;; mksh) inpkg+="mksh " rmpkg+="zsh " ;; bash) inpkg+="bash-completion " rmpkg+="zsh " ;; esac
1573 # using a different kernel, remove the stock one
1574 [[ $KERNEL != 'linux' ]] && inpkg+="$KERNEL " rmpkg+="linux "
1576 # don't install extras on dwm only installs
1577 if [[ $INSTALL_WMS != 'dwm' ]]; then
1578 # gnome, plasma, and cinnamon have their own superkey bind and ksuperkey conflicts
1579 [[ $INSTALL_WMS =~ ^(plasma|gnome|cinnamon)$ ]] || inpkg+="archlabs-ksuperkey "
1580 # window manager only packages
1581 [[ $INSTALL_WMS =~ (openbox|bspwm|i3-gaps|fluxbox) ]] && inpkg+="$WM_BASE_PKGS "
1583 inpkg+="arandr nitrogen polkit-gnome xclip xdotool compton gnome-keyring dunst feh "
1586 # update first to avoid issues
1587 chrun "pacman -Syyu --noconfirm"
1589 # remove the packages we don't want on the installed system
1590 [[ $rmpkg ]] && chrun "pacman -Rnsc $rmpkg --noconfirm"
1592 # reinstalling iputils fixes the network issue for non-root users
1593 chrun "pacman -S iputils $UCODE --noconfirm"
1595 # install the packages chosen throughout the install
1596 chrun "pacman -S $inpkg --needed --noconfirm" 2>$ERR
1597 errshow 1 "pacman -S $inpkg --needed --noconfirm"
1599 # bootloader packages
1600 if [[ $BOOTLDR == 'grub' ]]; then
1601 [[ $SYS == 'UEFI' ]] && local efib="efibootmgr"
1602 chrun "pacman -S os-prober grub $efib --needed --noconfirm" 2>$ERR
1603 errshow 1 "pacman -S os-prober grub $efib --needed --noconfirm"
1604 elif [[ $BOOTLDR == 'refind-efi' ]]; then
1605 chrun "pacman -S refind-efi efibootmgr --needed --noconfirm" 2>$ERR
1606 errshow 1 "pacman -S refind-efi efibootmgr --needed --noconfirm"
1607 elif [[ $SYS == 'UEFI' ]]; then
1608 chrun "pacman -S efibootmgr --needed --noconfirm" 2>$ERR
1609 errshow 1 "pacman -S efibootmgr --needed --noconfirm"
1612 # allow members of the wheel group to run commands as root
1613 sed -i "s/# %wheel ALL=(ALL) ALL/%wheel ALL=(ALL) ALL/g" $MNT/etc/sudoers
1618 install_mkinitcpio()
1621 [[ $LUKS ]] && add="encrypt"
1622 [[ $LVM ]] && { [[ $add ]] && add+=" lvm2" || add+="lvm2"; }
1623 sed -i "s/block filesystems/block ${add} filesystems ${HOOKS}/g" $MNT/etc/mkinitcpio.conf
1624 chrun "mkinitcpio -p $KERNEL" 2>$ERR
1625 errshow 1 "mkinitcpio -p $KERNEL"
1628 install_mirrorlist()
1630 if hash reflector >/dev/null 2>&1; then
1631 reflector --verbose --score 80 -l 40 -f 5 --sort rate --save "$1"
1632 elif hash rankmirrors >/dev/null 2>&1; then
1633 echo "Sorting mirrorlist"
1634 local key="access_key=5f29642060ab983b31fdf4c2935d8c56"
1635 ip_add="$(curl -fsSL "http://api.ipstack.com/check&?$key&fields=ip" | python -c "import sys, json; print(json.load(sys.stdin)['ip'])")"
1636 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'])")"
1637 if [[ "$country" ]]; then
1638 if [[ $country =~ (CA|US) ]]; then
1639 # use both CA and US mirrors for CA or US countries
1640 mirror="https://www.archlinux.org/mirrorlist/?country=US&country=CA&use_mirror_status=on"
1641 elif [[ $country =~ (AU|NZ) ]]; then
1642 # use both AU and NZ mirrors for AU or NZ countries
1643 mirror="https://www.archlinux.org/mirrorlist/?country=AU&country=NZ&use_mirror_status=on"
1645 mirror="https://www.archlinux.org/mirrorlist/?country=${country}&use_mirror_status=on"
1647 else # no country code so just grab all mirrors, will be a very slow sort but we don't have other options
1648 mirror="https://www.archlinux.org/mirrorlist/?country=all&use_mirror_status=on"
1650 curl -fsSL "$mirror" | sed -e 's/^#Server/Server/' -e '/^#/d' | rankmirrors -n 6 - >"$1"
1656 install_background()
1658 msg "Background Install" "\nInstall will now begin in the background\n" 1
1659 rsync -a /run/archiso/sfs/airootfs/ $MNT/ &
1661 ( install_mirrorlist "$MNT/etc/pacman.d/mirrorlist" ) &
1663 # end the background processes before exiting
1664 trap "kill $RSYNC_PID $MIRROR_PID 2>/dev/null" EXIT
1667 ###############################################################################
1669 # prerun_* set up the configs needed before actually running the commands
1670 # setup_* are run after selecting a bootloader and build the command used later
1671 # they can also be used for further user input as these run before control is taken away
1675 EDIT_FILES[bootloader]="/etc/default/grub"
1677 if [[ $SYS == 'BIOS' ]]; then
1678 [[ $BOOT_DEV ]] || { part_device 1 || return 1; }
1679 BCMDS[grub]="grub-install --recheck --force --target=i386-pc $BOOT_DEV"
1681 BCMDS[grub]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1682 grub-install --recheck --force --target=x86_64-efi --efi-directory=/$BOOTDIR --bootloader-id=$DIST"
1683 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1686 BCMDS[grub]="mkdir -p /run/udev /run/lvm &&
1687 mount --bind /hostrun/udev /run/udev &&
1688 mount --bind /hostrun/lvm /run/lvm &&
1690 grub-mkconfig -o /boot/grub/grub.cfg &&
1691 sleep 1 && umount /run/udev /run/lvm"
1698 sed -i "s/GRUB_DISTRIBUTOR=.*/GRUB_DISTRIBUTOR=\"${DIST}\"/g; s/GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT=\"\"/g" $MNT/etc/default/grub
1700 if [[ $LUKS_DEV ]]; then
1701 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
1702 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"
1705 if [[ $SYS == 'BIOS' && $LVM && -z $SEP_BOOT ]]; then
1706 sed -i "s/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g" $MNT/etc/default/grub 2>$ERR
1707 errshow 1 "sed -i 's/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g' $MNT/etc/default/grub"
1710 # setup for os-prober module
1711 mkdir -p /run/{lvm,udev} $MNT/hostrun/{lvm,udev}
1712 mount --bind /run/lvm $MNT/hostrun/lvm
1713 mount --bind /run/udev $MNT/hostrun/udev
1720 EDIT_FILES[bootloader]=""
1725 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1726 efibootmgr -v -d $BOOT_DEV -p $BOOT_PART_NUM -c -L '${DIST} Linux' -l /vmlinuz-${KERNEL} \
1727 -u 'root=$ROOT_PART_ID rw $([[ $UCODE ]] && printf 'initrd=\%s.img ' "$UCODE")initrd=\initramfs-${KERNEL}.img'"
1732 if [[ $SYS == 'BIOS' ]]; then
1733 EDIT_FILES[bootloader]="/boot/syslinux/syslinux.cfg"
1735 EDIT_FILES[bootloader]="/boot/EFI/syslinux/syslinux.cfg"
1736 BCMDS[syslinux]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1737 efibootmgr -v -c -d $BOOT_DEV -p $BOOT_PART_NUM -l /EFI/syslinux/syslinux.efi -L $DIST"
1743 local c="$MNT/boot/syslinux" s="/usr/lib/syslinux/bios" d=".."
1744 [[ $SYS == 'UEFI' ]] && { c="$MNT/boot/EFI/syslinux"; s="/usr/lib/syslinux/efi64"; d=''; }
1747 cp -rfv "$s/"* "$c/"
1748 cat > "$c/syslinux.cfg" <<- EOF
1751 MENU TITLE $DIST Boot Menu
1756 MENU LABEL $DIST Linux
1757 LINUX $d/vmlinuz-$KERNEL
1758 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1759 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL.img
1761 LABEL ${DIST}fallback
1762 MENU LABEL $DIST Linux Fallback
1763 LINUX $d/vmlinuz-$KERNEL
1764 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1765 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL-fallback.img
1772 EDIT_FILES[bootloader]="/boot/refind_linux.conf"
1773 BCMDS[refind-efi]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1; refind-install"
1778 cat > $MNT/boot/refind_linux.conf <<- EOF
1779 "$DIST Linux" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] &&
1780 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1781 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL.img"
1782 "$DIST Linux Fallback" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] &&
1783 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1784 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL-fallback.img"
1786 mkdir -p $MNT/etc/pacman.d/hooks
1787 cat > $MNT/etc/pacman.d/hooks/refind.hook <<- EOF
1794 Description = Updating rEFInd on ESP
1795 When = PostTransaction
1796 Exec = /usr/bin/refind-install
1800 setup_systemd-boot()
1802 EDIT_FILES[bootloader]="/boot/loader/entries/$DIST.conf"
1803 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1; bootctl --path=/boot install"
1806 prerun_systemd-boot()
1808 mkdir -p $MNT/boot/loader/entries
1809 cat > $MNT/boot/loader/loader.conf <<- EOF
1814 cat > $MNT/boot/loader/entries/$DIST.conf <<- EOF
1816 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1817 initrd /initramfs-$KERNEL.img
1818 options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1820 cat > $MNT/boot/loader/entries/$DIST-fallback.conf <<- EOF
1821 title $DIST Linux Fallback
1822 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1823 initrd /initramfs-$KERNEL-fallback.img
1824 options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1826 mkdir -p $MNT/etc/pacman.d/hooks
1827 cat > $MNT/etc/pacman.d/hooks/systemd-boot.hook <<- EOF
1834 Description = Updating systemd-boot
1835 When = PostTransaction
1836 Exec = /usr/bin/bootctl update
1838 systemd-machine-id-setup --root="$MNT"
1842 ###############################################################################
1847 msg "Info" "\nGathering device info.\n" 0
1848 no_bg_install || return 1
1852 dlg choice menu "Logical Volume Management" "$_lvmmenu" \
1853 "$_lvmnew" "vgcreate -f, lvcreate -L -n" \
1854 "$_lvmdel" "vgremove -f" \
1855 "$_lvmdelall" "lvrmeove, vgremove, pvremove -f" \
1856 "Back" "Return to the main menu"
1858 "$_lvmnew") lvm_create && break ;;
1859 "$_lvmdel") lvm_delgroup && yesno "$_lvmdel" "$_lvmdelask" && vgremove -f "$DEL_VG" >/dev/null 2>&1 ;;
1860 "$_lvmdelall") lvm_del_all ;;
1871 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
1872 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
1873 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
1875 if [[ $VGROUP && $v && $pv ]]; then
1876 msg "LVM Setup" "\nActivating existing logical volume management.\n" 0
1877 modprobe dm-mod >/dev/null 2>$ERR
1878 errshow 'modprobe dm-mod'
1879 vgscan >/dev/null 2>&1
1880 vgchange -ay >/dev/null 2>&1
1886 VGROUP='' LVM_PARTS='' VGROUP_MB=0
1888 lvm_mkgroup || return 1
1889 local txt="\nThe last (or only) logical volume will automatically use all remaining space in the volume group."
1890 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 -
1891 [[ $VOL_COUNT ]] || return 1
1892 lvm_extra_lvs || return 1
1893 lvm_volume_name "$_lvmlvname\nNOTE: This LV will use up all remaining space in the volume group (${VGROUP_MB}MB)" || return 1
1894 msg "$_lvmnew (LV:$VOL_COUNT)" "\nCreating volume $VNAME from remaining space in $VGROUP\n" 0
1895 lvcreate -l +100%FREE "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
1896 errshow "lvcreate -l +100%FREE $VGROUP -n $VNAME" || return 1
1897 LVM='logical volume'; sleep 0.5
1898 txt="\nDone, volume: $VGROUP-$VNAME (${VOLUME_SIZE:-${VGROUP_MB}MB}) has been created.\n"
1899 msg "$_lvmnew (LV:$VOL_COUNT)" "$txt\n$(lsblk -o NAME,MODEL,TYPE,FSTYPE,SIZE $LVM_PARTS)\n"
1905 local txt="${VGROUP}: ${SIZE}$SIZE_UNIT (${VGROUP_MB}MB remaining).$_lvmlvsize"
1909 dlg VOLUME_SIZE input "$_lvmnew (LV:$VOL_COUNT)" "$txt" ''
1910 if [[ -z $VOLUME_SIZE ]]; then
1912 break # allow bailing with escape or an empty choice
1913 elif (( ${VOLUME_SIZE:0:1} == 0 )); then
1914 ERR_SIZE=1 # size values can't begin with '0'
1916 # walk the string and make sure all but the last char are digits
1917 local lv=$((${#VOLUME_SIZE} - 1))
1918 for (( i=0; i<lv; i++ )); do
1919 [[ ${VOLUME_SIZE:$i:1} =~ [0-9] ]] || { ERR_SIZE=1; break; }
1921 if (( ERR_SIZE != 1 )); then
1922 case ${VOLUME_SIZE:$lv:1} in
1923 [mMgG]) local s=${VOLUME_SIZE:0:$lv} m=$((s * 1000))
1924 case ${VOLUME_SIZE:$lv:1} in
1925 [Gg]) (( m >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - m)) ;;
1926 [Mm]) (( ${VOLUME_SIZE:0:$lv} >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - s)) ;;
1933 if (( ERR_SIZE )); then
1934 msg "Invalid Logical Volume Size" "$_lvmerrlvsize"
1947 until [[ $named ]]; do
1948 lvm_partitions || return 1
1949 lvm_group_name || return 1
1950 yesno "$_lvmnew" "\nCreate volume group: $VGROUP\n\nusing these partition(s): $LVM_PARTS\n" && named=true
1953 msg "$_lvmnew" "\nCreating volume group: $VGROUP\n" 0
1954 vgcreate -f "$VGROUP" $LVM_PARTS >/dev/null 2>$ERR
1955 errshow "vgcreate -f $VGROUP $LVM_PARTS" || return 1
1957 SIZE=$(vgdisplay "$VGROUP" | awk '/VG Size/ { gsub(/[^0-9.]/, ""); print int($0) }')
1958 SIZE_UNIT="$(vgdisplay "$VGROUP" | awk '/VG Size/ { print substr($NF, 0, 1) }')"
1960 if [[ $SIZE_UNIT == 'G' ]]; then
1961 VGROUP_MB=$((SIZE * 1000))
1966 msg "$_lvmnew" "\nVolume group $VGROUP (${SIZE}$SIZE_UNIT) successfully created\n"
1972 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
1973 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
1974 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
1976 if [[ $VGROUP || $v || $pv ]]; then
1977 if yesno "$_lvmdelall" "$_lvmdelask"; then
1978 for i in $v; do lvremove -f "/dev/mapper/$i" >/dev/null 2>&1; done
1979 for i in $VGROUP; do vgremove -f "$i" >/dev/null 2>&1; done
1980 for i in $pv; do pvremove -f "$i" >/dev/null 2>&1; done
1984 msg "Delete LVM" "\nNo LVMs to remove...\n" 2
1994 for i in $(lvs --noheadings | awk '{print $2}' | uniq); do
1995 VOL_GROUP_LIST+="$i $(vgdisplay "$i" | awk '/VG Size/ {print $3$4}') "
1998 [[ $VOL_GROUP_LIST ]] || { msg "No Groups" "\nNo volume groups found."; return 1; }
2000 dlg DEL_VG menu "Logical Volume Management" "\nSelect volume group to delete.\n\nAll logical volumes within will also be deleted." $VOL_GROUP_LIST
2006 while (( VOL_COUNT > 1 )); do
2007 lvm_volume_name "$_lvmlvname" && lvm_lv_size || return 1
2008 msg "$_lvmnew (LV:$VOL_COUNT)" "\nCreating a $VOLUME_SIZE volume $VNAME in $VGROUP\n" 0
2009 lvcreate -L "$VOLUME_SIZE" "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
2010 errshow "lvcreate -L $VOLUME_SIZE $VGROUP -n $VNAME" || return 1
2011 msg "$_lvmnew (LV:$VOL_COUNT)" "\nDone, logical volume (LV) $VNAME ($VOLUME_SIZE) has been created.\n"
2019 part_find 'part|crypt' || return 1
2020 PARTS="$(awk 'NF > 0 {print $0 " off"}' <<< "$PARTS")"
2021 dlg LVM_PARTS check "$_lvmnew" "\nSelect the partition(s) to use for the physical volume (PV)." $PARTS
2028 until [[ $VGROUP ]]; do
2029 dlg VGROUP input "$_lvmnew" "$_lvmvgname" "lvgroup"
2030 if [[ -z $VGROUP ]]; then
2032 elif [[ ${VGROUP:0:1} == "/" || $VGROUP =~ \ |\' ]] || vgdisplay | grep -q "$VGROUP"; then
2033 msg "LVM Name Error" "$_lvmerrvgname"
2043 local txt="$1" default="mainvolume"
2044 (( VOL_COUNT > 1 )) && default="extvolume$VOL_COUNT"
2045 until [[ $VNAME ]]; do
2046 dlg VNAME input "$_lvmnew (LV:$VOL_COUNT)" "\n$txt" "$default"
2047 if [[ -z $VNAME ]]; then
2049 elif [[ ${VNAME:0:1} == "/" || $VNAME =~ \ |\' ]] || lsblk | grep -q "$VNAME"; then
2050 msg "LVM Name Error" "$_lvmerlvname"
2057 ###############################################################################
2063 no_bg_install || return 1
2064 dlg choice menu "LUKS Encryption" "$_luksmenu" \
2065 "$_luksnew" "cryptsetup -q luksFormat" \
2066 "$_luksopen" "cryptsetup open --type luks" \
2067 "$_luksadv" "cryptsetup -q -s -c luksFormat" \
2068 "Back" "Return to the main menu"
2071 "$_luksnew") luks_basic || return 1 ;;
2072 "$_luksopen") luks_open || return 1 ;;
2073 "$_luksadv") luks_advanced || return 1 ;;
2081 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
2083 part_find 'part|crypt|lvm' || return 1
2085 if (( COUNT == 1 )); then
2086 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2088 dlg LUKS_PART menu "$_luksopen" "\nSelect which partition to open." $PARTS
2091 [[ $LUKS_PART ]] || return 1
2093 luks_pass "$_luksopen" || return 1
2094 msg "$_luksopen" "\nOpening encrypted partition: $LUKS_NAME\n\nUsing device/volume: $LUKS_PART\n" 0
2095 cryptsetup open --type luks "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2096 errshow "cryptsetup open --type luks $LUKS_PART $LUKS_NAME" || return 1
2097 LUKS='encrypted'; luks_show
2104 local t="$1" n='' p='' p2=''
2106 until [[ $LUKS_PASS ]]; do
2109 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " $t " --mixedform "$_luksomenu" 0 0 0 \
2110 "Name:" 1 1 "${LUKS_NAME:-cryptroot}" 1 7 "$COLUMNS" 0 0 \
2111 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
2112 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
2114 while read -r line; do
2123 if [[ -z $n ]]; then
2124 msg "Name Empty" "\nEncrypted device name cannot be empty.\n\nPlease try again.\n" 2
2125 elif [[ -z $p || "$p" != "$p2" ]]; then
2127 msg "Password Mismatch" "\nThe passwords entered do not match.\n\nPlease try again.\n" 2
2129 LUKS_NAME="$n" LUKS_PASS="$p"
2139 msg "$_luksnew" "\nEncrypted partition ready for mounting.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$LUKS_PART")\n\n"
2144 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
2146 part_find 'part|lvm' || return 1
2148 if [[ $AUTO_ROOT_PART ]]; then
2149 LUKS_PART="$AUTO_ROOT_PART"
2150 elif (( COUNT == 1 )); then
2151 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2153 dlg LUKS_PART menu "$_luksnew" "\nSelect the partition you want to encrypt." $PARTS
2156 [[ $LUKS_PART ]] || return 1
2157 luks_pass "$_luksnew"
2162 luks_setup || return 1
2163 msg "$_luksnew" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2164 cryptsetup -q luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2165 errshow "cryptsetup -q luksFormat $LUKS_PART" || return 1
2166 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2167 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2168 LUKS='encrypted'; luks_show
2176 dlg cipher input "LUKS Encryption" "$_lukskey" "-s 512 -c aes-xts-plain64"
2177 [[ $cipher ]] || return 1
2178 msg "$_luksadv" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2179 cryptsetup -q $cipher luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2180 errshow "cryptsetup -q $cipher luksFormat $LUKS_PART" || return 1
2181 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2182 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2189 ###############################################################################
2191 # some help avoid repetition and improve usability of some commands
2192 # others are initial setup functions used before reaching the main loop
2196 [[ "$2" == *"$1"* ]] && printf "on" || printf "off"
2201 # cleanup and exit the installer cleanly with exit code $1
2202 local e="$1" # when e is 127 unmount /run/archiso/bootmnt and reboot
2206 if [[ -d $MNT ]]; then
2208 if (( e == 127 )); then
2209 umount_dir /run/archiso/bootmnt && sleep 0.5 && reboot -f
2217 local var="$1" # assign output from dialog to var
2218 local dlg_t="$2" # dialog type (menu, check, input)
2219 local title="$3" # dialog title
2220 local body="$4" # dialog message
2221 local n=0 # number of items to display for menu and check dialogs
2223 shift 4 # shift off args assigned above
2225 # adjust n when passed a large list
2226 local l=$((LINES - 20))
2227 (( ($# / 2) > l )) && n=$l
2231 menu) dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --menu "$body" 0 0 $n "$@" 2>"$ANS" || return 1 ;;
2232 check) dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --checklist "$body" 0 0 $n "$@" 2>"$ANS" || return 1 ;;
2235 local def="$1" # assign default value for input
2237 if [[ $1 == 'limit' ]]; then
2238 dialog --backtitle "$DIST Installer - $SYS - v$VER" --max-input 63 --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2240 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2244 # if answer file isn't empty read from it into $var
2245 [[ -s "$ANS" ]] && printf -v "$var" "%s" "$(< "$ANS")"
2250 # displays a message dialog
2251 # when more than 2 args the message will disappear after sleep time ($3)
2257 dialog --backtitle "$DIST Installer - $SYS - v$VER" --sleep "$1" --title " $title " --infobox "$body\n" 0 0
2259 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --msgbox "$body\n" 0 0
2267 if ! select_keymap; then
2270 elif ! net_connect; then
2271 msg "Not Connected" "\nRunning live requires an active internet connection.\n\nExiting..\n" 2
2275 pacman -Syyu --noconfirm || die 1
2276 pacman -S $AL_BASE_PKGS $WM_BASE_PKGS xorg-xinit xorg-server --needed --noconfirm || die 1
2280 pacman -S git --needed --noconfirm || die 1
2281 mkdir -pv /root/suckless
2282 for i in dwm dmenu st; do
2283 git clone https://git.suckless.org/$i /root/suckless/$i && cd /root/suckless/$i && make PREFIX=/usr install
2286 i3-gaps|oepnbox|fluxbox|bspwm|xfce4|gnome|plasma|cinnamon|awesome)
2287 pacman -S "$ses" ${WM_EXT[$ses]} xterm --needed --noconfirm || die 1
2289 *) echo "error: invalid session for -l, --live, see -h, --help"; die 1 ;;
2292 pacman -Scc --noconfirm
2293 rm -rf /var/cache/pacman/pkg/*
2294 cp -rfT /etc/skel /root || die 1
2295 sed -i "/exec/ c exec ${WM_SESSIONS[$ses]}" /root/.xinitrc
2296 printf "\n%s has been set as the login session in /root/.xinitrc, to start the session simply run\n\n\tstartx\n\n" "${WM_SESSIONS[$ses]}"
2304 usage: $1 [-hdl] [session]
2307 -h, --help print this message and exit
2308 -l, --live install and setup a live session
2309 -d, --debug enable debugging and log output to $DBG
2312 i3-gaps - A fork of i3wm with more features including gaps
2313 openbox - A lightweight, powerful, and highly configurable stacking wm
2314 dwm - A dynamic WM for X that manages windows in tiled, floating, or monocle layouts
2315 awesome - A customized Awesome WM session created by @elanapan
2316 bspwm - A tiling wm that represents windows as the leaves of a binary tree
2317 fluxbox - A lightweight and highly-configurable window manager
2318 gnome - A desktop environment that aims to be simple and easy to use
2319 cinnamon - A desktop environment combining traditional desktop with modern effects
2320 plasma - A kde software project currently comprising a full desktop environment
2321 xfce4 - A lightweight and modular desktop environment based on gtk+2/3
2329 local title="$1" body="$2" yes='Yes' no='No'
2330 (( $# >= 3 )) && yes="$3"
2331 (( $# >= 4 )) && no="$4"
2333 if (( $# == 5 )); then
2334 dialog --backtitle "$DIST Installer - $SYS - v$VER" --defaultno --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2336 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2342 arch-chroot "$MNT" bash -c "$1"
2347 export PS4='| ${BASH_SOURCE} LINE:${LINENO} FUNC:${FUNCNAME[0]:+ ${FUNCNAME[0]}()} |> '
2357 "\e]P0191919" # #191919
2358 "\e]P1D15355" # #D15355
2359 "\e]P2609960" # #609960
2360 "\e]P3FFCC66" # #FFCC66
2361 "\e]P4255A9B" # #255A9B
2362 "\e]P5AF86C8" # #AF86C8
2363 "\e]P62EC8D3" # #2EC8D3
2364 "\e]P7949494" # #949494
2365 "\e]P8191919" # #191919
2366 "\e]P9D15355" # #D15355
2367 "\e]PA609960" # #609960
2368 "\e]PBFF9157" # #FF9157
2369 "\e]PC4E88CF" # #4E88CF
2370 "\e]PDAF86C8" # #AF86C8
2371 "\e]PE2ec8d3" # #2ec8d3
2372 "\e]PFE1E1E1" # #E1E1E1
2375 [[ $TERM == 'linux' ]] && printf "%b" "${colors[@]}" && clear
2380 [ $? -eq 0 ] && return 0
2382 local fatal=0 err=""
2383 err="$(sed 's/[^[:print:]]//g; s/\[[0-9\;:]*\?m//g; s/==> //g; s/] ERROR:/]\nERROR:/g' "$ERR")"
2385 (( $1 == 1 )) && { fatal=1; shift; }
2388 local txt+="\nThe command exited abnormally:\n\n$1\n\nWith the following message:\n\n$err\n\n"
2390 local txt+="\nThe command exited abnormally:\n\n$1\n\nWith no error message:\n\n"
2393 if (( fatal )); then
2394 msg "Install Error" "${txt}Errors at this stage are fatal and the install cannot continue.\n"
2395 [[ -r $DBG && $TERM == 'linux' ]] && less "$DBG"
2399 msg "Install Error" "${txt}Errors at this stage are non-fatal and can be either fixed or ignored depending on the error.\n"
2407 if (( $1 >= 0 )) && ! grep -qw "$MNT" /proc/mounts; then
2408 msg "Not Mounted" "\nPartition(s) must be mounted first.\n" 2
2410 elif [[ $1 -ge 1 && -z $BOOTLDR ]]; then
2411 msg "No Bootloader" "\nBootloader must be selected first.\n" 2
2413 elif [[ $1 -ge 2 && (-z $NEWUSER || -z $USER_PASS) ]]; then
2414 msg "No User" "\nA user must be created first.\n" 2
2416 elif [[ $1 -ge 3 && -z $CONFIG_DONE ]]; then
2417 msg "Not Configured" "\nSystem configuration must be done first.\n" 2
2420 (( i )) # return code
2425 mount | grep -q 'swap' && swapoff -a
2427 if [[ -d $dir ]] && mount | grep -q "on $dir "; then
2428 if ! umount "$dir" 2>/dev/null; then
2430 umount -f "$dir" 2>/dev/null || umount -l "$dir"
2438 msg "Network Connect" "\nVerifying network connection\n" 0
2439 curl -sIN --connect-timeout 5 'https://www.archlinux.org/' | sed '1q' | grep -q '200'
2444 if chk_connect; then
2446 elif hash nmtui >/dev/null 2>&1; then
2448 if [[ $TERM == 'linux' ]]; then
2449 printf "%b" "\e]P1191919" "\e]P4191919"
2451 printf "%b" "\e]P1D15355" "\e]P4255a9b"
2456 elif hash wifi-menu >dev/null 2>&1; then
2466 [[ $RSYNC_PID || $MIRROR_PID ]] || return 0
2467 msg "Install Running" "\nA background install process is currently running.\n" 2
2473 IGNORE_DEV="$(lsblk -lno NAME,MOUNTPOINT | awk '/\/run\/archiso\/bootmnt/ {sub(/[1-9]/, ""); print $1}')"
2475 if [[ $IGNORE_DEV ]]; then
2476 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ && !'"/$IGNORE_DEV/"' {print "/dev/" $1 " " $2}')"
2478 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ {print "/dev/" $1 " " $2}')"
2481 if [[ -z $SYS_DEVS ]]; then
2482 msg "Device Error" "\nNo available devices...\n\nExiting..\n" 2
2487 while read -r line; do
2489 done <<< "$SYS_DEVS"
2496 # amd-ucode is not needed it's provided by linux-firmware
2497 # elif grep -q 'AuthenticAMD' /proc/cpuinfo; then
2499 elif grep -q 'GenuineIntel' /proc/cpuinfo; then
2503 modprobe -q efivarfs >/dev/null 2>&1
2505 _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."
2506 if [[ -d /sys/firmware/efi/efivars ]]; then
2508 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars
2509 _prep+="\n - An EFI boot partition mounted."
2513 _prep+="\n\nOnce finished mounting, a portion of the install can be done in the background while you continue configuring the system:\n"
2514 _prep+="\n - Choose the system bootloader.\n - Create a user and password."
2515 _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."
2518 ###############################################################################
2521 # enable some nicer colours in the linux console
2524 if (( UID != 0 )); then
2525 msg "Not Root" "\nThis installer must be run as root or using sudo.\n\nExiting..\n" 2
2527 elif ! grep -qwm 1 'lm' /proc/cpuinfo; then
2528 msg "Not x86_64 Architecture" "\nThis installer only supports x86_64 architectures.\n\nExiting..\n" 2
2531 case "$1" in -d|--debug) debug ;; -h|--help) usage "$0" ;; -l|--live) shift; live "$@" ;; esac
2534 # trap ^C to perform cleanup
2535 trap 'printf "\n^C\n" && die 1' INT
2540 msg "Welcome to the $DIST Installer" "$_welcome"
2542 if ! select_keymap; then
2544 elif ! net_connect; then
2545 msg "Not Connected" "\nThis installer requires an active internet connection.\n\nExiting..\n" 2
2552 # vim:fdm=marker:fmr={,}