3 # This program is free software, provided under the GNU GPL
4 # Written by Nathaniel Maia for use in Archlabs
5 # Some ideas and code reworked from other resources
6 # AIF, Cnichi, Calamares, Arch Wiki.. Credit where credit is due
8 VER="2.0.57" # installer version
9 DIST="ArchLabs" # linux distributor
10 MNT="/mnt" # install mountpoint
11 ANS="/tmp/ans" # dialog answer file
13 # ------------------------------------------------------ #
14 # When manually mounting your partitions, you need
15 # to set these values to avoid using the mount menu.
16 # ------------------------------------------------------ #
18 # root partition, eg. /dev/sda2
21 # boot partition, required on UEFI eg. /dev/sda1
24 # boot device, used for some bootloaders eg. /dev/sda
27 # bootloader to use, can be:
28 # UEFI: grub, syslinux, efistub, systemd-boot, refind-efi
29 # BIOS: grub, syslinux
32 # directory to mount the boot partition (if any) for most bootloaders
33 # this will need to be 'boot' however a popular one for grub is 'boot/efi'
36 # ------------------------------------------------------ #
38 # bulk default values {
40 # these values will be selected during the install, it is not recommended
41 # to edit them here unless you know what you're doing.
43 UCODE='' # cpu microcode (if any), can be: amd-ucode, intel-ucode
44 KERNEL='' # linux kernel, can be: linux, linux-lts, linux-zen, or linux-hardened
45 MYSHELL='' # full path for the shell, eg. /usr/bin/zsh
47 SWAP_PART='' # swap partition or file path
48 SWAP_SIZE='' # swap size, only used when creating a swapfile
50 EXMNT='' # holder for additional partitions while mounting
51 EXMNTS='' # when an extra partition is mounted append it's info
53 FONT="ter-i16n" # font used for the linux console
54 HOOKS="shutdown" # list of additional HOOKS to add in /etc/mkinitcpio.conf
56 LOGIN_TYPE='' # login manager can be: lightdm, xinit, ly
57 LOGIN_WM='' # default login session to be placed in ~/.xinitrc
58 LOGINRC='' # login shell rc file, eg. .zprofile, .bash_profile, .profile
60 INSTALL_WMS='' # space separated list of chosen wm/de
62 WM_PKGS='' # list of packages added during wm/de choice (not user edited)
63 PACKAGES='' # list of all packages to install including WM_PKGS (not user edited)
64 USER_PKGS='' # packages selected by the user during install
66 NEWUSER='' # username for the new user
67 USER_PASS='' # new user's password
68 ROOT_PASS='' # root password
70 LUKS='' # empty when not using encryption
71 LUKS_DEV='' # boot parameter string for LUKS
72 LUKS_PART='' # partition used for encryption
73 LUKS_PASS='' # encryption password
74 LUKS_UUID='' # encrypted partition UUID
75 LUKS_NAME='' # name used for encryption
77 LVM='' # empty when not using lvm
78 LVM_PARTS='' # partitions used for volume group
79 VGROUP_MB=0 # available space in volume group
81 WARN='' # issued mounting/partitioning warning
82 SEP_BOOT='' # separate boot partition for BIOS
83 AUTOLOGIN='' # enable autologin for xinit
84 CONFIG_DONE='' # basic configuration is finished
85 BROADCOM_WL='' # fixes for broadcom cards eg. BCM4352
87 FORMATTED='' # partitions we formatted and should allow skipping
88 AUTO_ROOT_PART='' # root value from auto partition
89 AUTO_BOOT_PART='' # boot value from auto partition
91 # iso base, pacstrap when running the installer from a stock arch iso
92 ISO_BASE="b43-firmware b43-fwcutter broadcom-wl clonezilla dhclient dhcpcd ethtool wpa_supplicant "
93 ISO_BASE+="exfat-utils f2fs-tools gptfdisk vim hdparm ipw2100-fw ipw2200-fw nfs-utils nilfs-utils ntfs-3g "
94 ISO_BASE+="pacman-contrib parted rsync sdparm smartmontools wget wireless_tools wpa_actiond xl2tpd dialog parted "
95 ISO_BASE+="alsa-firmware alsa-lib alsa-plugins pulseaudio pulseaudio-alsa networkmanager w3m htop wireless-regdb "
96 ISO_BASE+="lm_sensors lsb-release p7zip pamixer reflector unrar ranger terminus-font ttf-dejavu archlabs-keyring"
99 AL_BASE_PKGS="archlabs-skel-base archlabs-fonts archlabs-themes archlabs-dARK archlabs-icons archlabs-wallpapers archlabs-scripts"
101 # baseline (usually installed in the background)
102 BASE_PKGS="base-devel xorg xorg-drivers sudo git gvfs gtk3 gtk-engines gtk-engine-murrine pavucontrol tumbler "
103 BASE_PKGS+="playerctl ffmpeg gstreamer libmad libmatroska gst-libav gst-plugins-base gst-plugins-good scrot"
105 # extras for window managers
106 WM_BASE_PKGS="arandr archlabs-networkmanager-dmenu xdg-user-dirs nitrogen polkit-gnome volumeicon xclip exo "
107 WM_BASE_PKGS+="xdotool compton wmctrl gnome-keyring dunst feh gsimplecal xfce4-power-manager xfce4-settings laptop-detect"
110 SEL=0 # currently selected menu item
111 ERR="/tmp/errlog" # error log used internally
112 DBG="/tmp/debuglog" # debug log when passed -d
113 RUN="/run/archiso/bootmnt/arch/boot" # path for live /boot
114 VM="$(dmesg | grep -i "hypervisor")" # is the system a vm
117 export DIALOGOPTS="--cr-wrap"
121 # giant ugly variable container :P {
124 SYS_MEM="$(awk '/MemTotal/ {print int($2 / 1024) "M"}' /proc/meminfo)"
126 # locales from /etc/locale.gen
127 LOCALES="$(awk '/\.UTF-8/ {gsub(/# .*|#/, ""); if ($1) {print $1 " - "}}' /etc/locale.gen)"
129 # console keyboard mappings
130 CMAPS="$(find /usr/share/kbd/keymaps -name '*.map.gz' | awk '{gsub(/\.map\.gz|.*\//, ""); print $1 " - "}' | sort)"
133 [[ $LINES ]] || LINES=$(tput lines)
134 [[ $COLUMNS ]] || COLUMNS=$(tput cols)
140 # commands used to install each bootloader, however most get modified during runtime {
142 [refind-efi]='refind-install' # minor modification
143 [grub]='grub-install --recheck --force' # heavily modified
144 [syslinux]='syslinux-install_update -i -a -m' # modified on UEFI
145 [efistub]='efibootmgr -v -d /dev/sda -p 1 -c -l' # heavily modified
146 [systemd-boot]='bootctl --path=/boot install' # not modified
149 # executable name for each wm/de used in ~/.xinitrc {
150 declare -A WM_SESSIONS=(
157 [gnome]='gnome-session'
158 [fluxbox]='startfluxbox'
159 [openbox]='openbox-session'
160 [cinnamon]='cinnamon-session'
163 # packages installed for each wm/de, most are depends of the skel packages {
167 [plasma]='kdebase-meta' # base plasma application set
168 [awesome]='archlabs-skel-awesome' # see deps of archlabs-skel-awesome
169 [bspwm]='archlabs-skel-bspwm' # see deps of archlabs-skel-bspwm
170 [fluxbox]='archlabs-skel-fluxbox' # see deps of archlabs-skel-fluxbox
171 [i3-gaps]='archlabs-skel-i3-gaps' # see deps of archlabs-skel-i3-gaps
172 [openbox]='archlabs-skel-openbox' # see deps of archlabs-skel-openbox
173 [xfce4]='archlabs-skel-xfce4 xfce4-goodies' # see deps of archlabs-skel-xfce4
176 # files offered for editing after install is complete {
177 declare -A EDIT_FILES=(
178 [login]='' # login is populated once we know the username and shell
180 [sudoers]='/etc/sudoers'
181 [crypttab]='/etc/crypttab'
182 [pacman]='/etc/pacman.conf'
183 [console]='/etc/vconsole.conf'
184 [mkinitcpio]='/etc/mkinitcpio.conf'
185 [hostname]='/etc/hostname /etc/hosts'
186 [bootloader]="/boot/loader/entries/$DIST.conf"
187 [locale]='/etc/locale.conf /etc/default/locale'
188 [keyboard]='/etc/X11/xorg.conf.d/00-keyboard.conf /etc/default/keyboard'
191 # mkfs command and flags for filesystem formatting {
196 [ntfs]='mkfs.ntfs -q'
197 [ext2]='mkfs.ext2 -q'
198 [ext3]='mkfs.ext3 -q'
199 [ext4]='mkfs.ext4 -q'
200 [vfat]='mkfs.vfat -F32'
201 [nilfs2]='mkfs.nilfs2 -q'
202 [reiserfs]='mkfs.reiserfs -q'
205 # mount options for each filesystem {
211 [jfs]='discard errors=continue errors=panic nointegrity'
212 [reiserfs]='acl nolog notail replayonly user_xattr off'
213 [ext4]='discard dealloc nofail noacl relatime noatime nobarrier nodelalloc'
214 [xfs]='discard filestreams ikeep largeio noalign nobarrier norecovery noquota wsync'
215 [nilfs2]='discard nobarrier errors=continue errors=panic order=relaxed order=strict norecovery'
216 [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'
219 # packages installed for each login option {
220 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 [vlc]='qt5ct qt5-styleplugins'
235 [zathura]='zathura-pdf-poppler'
236 [noto-fonts]='noto-fonts-emoji'
237 [cairo-dock]='cairo-dock-plug-ins'
238 [qutebrowser]='qt5ct qt5-styleplugins'
239 [qbittorrent]='qt5ct qt5-styleplugins'
240 [transmission-qt]='qt5ct qt5-styleplugins'
241 [kdenlive]='kdebase-meta dvdauthor frei0r-plugins breeze breeze-gtk qt5ct qt5-styleplugins'
246 # dialog text variables
249 # Basics (somewhat in order)
250 _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"
251 _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"
252 _device="\nSelect a device to use from the list below.\n\nDevices (/dev) are the available drives on the system. /sda, /sdb, /sdc ..."
253 _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."
254 _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."
255 _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"
256 _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)."
257 _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."
258 _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."
259 _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."
260 _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"
261 _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."
262 _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."
263 _exmnt="\nWhere do you want the partition mounted?\n\nEnsure the name begins with a slash (/).\nExamples include: /usr, /home, /var, etc."
264 _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."
265 _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."
266 _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"
267 _timez="\nThe time zone is used to set the system clock.\n\nSelect your country or continent from the list below"
268 _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."
269 _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."
270 _login="\nSelect which of your session choices to use for the initial login.\n\nYou can be change this later by editing your ~/.xinitrc"
271 _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"
272 _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."
273 _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."
276 _luksnew="Basic LUKS Encryption"
277 _luksadv="Advanced LUKS Encryption"
278 _luksopen="Open Existing LUKS Partition"
279 _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."
280 _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."
281 _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)."
284 _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."
285 _lvmnew="Create Volume Group and Volume(s)"
286 _lvmdel="Delete an Existing Volume Group"
287 _lvmdelall="Delete ALL Volume Group(s) and Volume(s)"
288 _lvmvgname="\nEnter a name for the volume group (VG) being created from the partition(s) selected."
289 _lvmlvname="\nEnter a name for the logical volume (LV) being created.\n\nThis is similar to setting a label for a partition."
290 _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."
291 _lvmdelask="\nConfirm deletion of volume group(s) and logical volume(s).\n\nDeleting a volume group, will delete all logical volumes within it.\n"
294 _errexpart="\nCannot mount partition due to a problem with the mountpoint.\n\nEnsure it begins with a slash (/) followed by atleast one character.\n"
295 _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"
296 _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"
297 _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"
298 _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"
299 _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"
300 _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"
306 ###############################################################################
308 # main is the entry point which calls functions including outside of its block
309 # once those functions finished they always are returned here with the
310 # exception of install_main(), it exits upon completion
314 (( SEL < 12 )) && (( SEL++ ))
316 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Prepare " --default-item $SEL --cancel-label 'Exit' --menu "$_prep" 0 0 0 \
317 1 "Device tree (optional)" \
318 2 "Partitioning (optional)" \
319 3 "LUKS setup (optional)" \
320 4 "LVM setup (optional)" \
321 5 "Mount partitions" \
322 6 "System bootloader" \
323 7 "User and password" \
324 8 "System configuration" \
325 9 "Select WM/DE (optional)" \
326 10 "Select Packages (optional)" \
327 11 "View configuration (optional)" \
328 12 "Start the installation" 2>"$ANS"
331 [[ -z $WARN && $SEL =~ (2|5) ]] && { msg "Data Warning" "$_warn"; WARN=true; }
334 2) part_menu || (( SEL-- )) ;;
335 3) luks_menu || (( SEL-- )) ;;
336 4) lvm_menu || (( SEL-- )) ;;
337 5) mount_menu || (( SEL-- )) ;;
338 6) prechecks 0 && { select_boot || (( SEL-- )); } ;;
339 7) prechecks 1 && { select_mkuser || (( SEL-- )); } ;;
340 8) prechecks 2 && { select_config || (( SEL-- )); } ;;
341 9) prechecks 3 && { select_sessions || (( SEL-- )); } ;;
342 10) prechecks 3 && { select_packages || (( SEL-- )); } ;;
343 11) prechecks 3 && select_show ;;
344 12) prechecks 3 && install_main ;;
345 *) yesno "Exit" "\nUnmount partitions (if any) and exit the installer?\n" && die 0
351 if [[ $SYS == 'BIOS' ]]; then
352 dlg BOOTLDR menu "BIOS Bootloader" "\nSelect which bootloader to use." \
353 "grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
354 "syslinux" "A collection of boot loaders for booting drives, CDs, or over the network" || return 1
356 dlg BOOTLDR menu "UEFI Bootloader" "\nSelect which bootloader to use." \
357 "systemd-boot" "A simple UEFI boot manager which executes configured EFI images" \
358 "grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
359 "refind-efi" "A UEFI boot manager that aims to be platform neutral and simplify multi-boot" \
360 "efistub" "Boot the kernel image directly (no chainloading support)" \
361 "syslinux" "A collection of boot loaders for booting drives, CDs, or over the network (no chainloading support)" || return 1
369 local cmd="${BCMDS[$BOOTLDR]}"
370 local pkgs="${USER_PKGS// / } ${PACKAGES// / }"
371 local exmnt="${EXMNT:-none}"
372 [[ $BOOT_PART ]] && mnt="/$BOOTDIR"
373 [[ $INSTALL_WMS == *dwm* ]] && pkgs="dwm st dmenu $pkgs"
375 msg "Show Configuration" "
377 ---------- PARTITION CONFIGURATION ------------
379 Root: ${ROOT_PART:-none}
380 Boot: ${BOOT_PART:-${BOOT_DEV:-none}}
381 Swap: ${SWAP_PART:-none}
382 Size: ${SWAP_SIZE:-none}
383 Extra: ${EXMNTS:-$exmnt}
384 Hooks: ${HOOKS:-none}
389 ---------- BOOTLOADER CONFIGURATION -----------
391 Bootloader: ${BOOTLDR:-none}
392 Mountpoint: ${mnt:-none}
393 Command: ${cmd:-none}
396 ------------ SYSTEM CONFIGURATION -------------
398 Locale: ${MYLOCALE:-none}
399 Keymap: ${KEYMAP:-none}
400 Hostname: ${MYHOST:-none}
401 Timezone: ${ZONE:-none}/${SUBZ:-none}
404 ------------ USER CONFIGURATION --------------
406 User: ${NEWUSER:-none}
407 Shell: ${MYSHELL:-none}
408 Session: ${LOGIN_WM:-none}
409 Autologin: ${AUTOLOGIN:-none}
410 DM or xinit: ${LOGIN_TYPE:-none}
413 ------------ PACKAGES AND MIRRORS -------------
415 Kernel: ${KERNEL:-none}
416 Sessions: ${INSTALL_WMS:-none}
417 Packages: ${USER_PKGS// / } ${PACKAGES// / }
423 [[ $INSTALL_WMS ]] || return 0
425 if [[ -z $LOGIN_TYPE ]]; then
426 dlg LOGIN_TYPE menu "Login Management" "\nSelect what kind of login management to use." \
427 "xinit" "Console login without a display manager" \
428 "ly" "TUI display manager with a ncurses-like interface"
429 "lightdm" "Lightweight display manager with a gtk greeter" || return 1
432 if [[ $LOGIN_TYPE == 'xinit' ]]; then
433 EDIT_FILES[login]="/home/$NEWUSER/.xinitrc /home/$NEWUSER/.xprofile"
434 # define what wm/de to use for xinit
435 if (( $(wc -w <<< "$INSTALL_WMS") > 1 )); then
436 dlg LOGIN_WM menu "Login Management" "$_login" $LOGIN_CHOICES || return 1
437 LOGIN_WM="${WM_SESSIONS[$LOGIN_WM]}"
439 [[ -z $LOGIN_WM ]] && LOGIN_WM="${WM_SESSIONS[${INSTALL_WMS%% *}]}"
441 yesno "Autologin" "$(sed "s|USER|$NEWUSER|g; s|RC|$LOGINRC|g" <<< "$_autologin")" && AUTOLOGIN=true || AUTOLOGIN=''
443 AUTOLOGIN='' # no autologin for DMs
444 if [[ $LOGIN_TYPE == 'lightdm' ]]; then
445 EDIT_FILES[login]="/etc/lightdm/lightdm.conf /etc/lightdm/lightdm-gtk-greeter.conf"
446 elif [[ $LOGIN_TYPE == 'ly' ]]; then
447 EDIT_FILES[login]="/etc/ly/config.ini"
457 until [[ $CONFIG_DONE ]]; do
459 0) dlg MYSHELL menu "Shell" "\nChoose which shell to use." \
460 /usr/bin/zsh 'A very advanced and programmable command interpreter (shell) for UNIX' \
461 /bin/bash 'The GNU Bourne Again shell, standard in many GNU/Linux distributions' \
462 /usr/bin/mksh 'The MirBSD Korn Shell - an enhanced version of the public domain ksh' || return 1
464 1) dlg MYHOST input "Hostname" "$_hostname" "${DIST,,}" limit || { i=0; continue; } ;;
465 2) dlg MYLOCALE menu "Locale" "$_locale" $LOCALES || { i=1; continue; } ;;
467 until [[ $ZONE && $SUBZ ]]; do
468 dlg ZONE menu "Timezone" "$_timez" America - Australia - Asia - Atlantic - Africa - Europe - Indian - Pacific - Arctic - Antarctica - || break
469 dlg SUBZ menu "Timezone" "$_timesubz" $(awk '/'"$ZONE"'\// {gsub(/'"$ZONE"'\//, ""); print $3 " - "}' /usr/share/zoneinfo/zone.tab | sort) || continue
471 [[ $ZONE && $SUBZ ]] || { i=2; continue; } ;;
472 4) dlg KERNEL menu "Kernel" "\nChoose which kernel to use." \
473 linux 'Vanilla linux kernel and modules, with a few patches applied' \
474 linux-lts 'Long-term support (LTS) linux kernel and modules' \
475 linux-zen 'A effort of kernel hackers to provide the best kernel for everyday systems' \
476 linux-hardened 'A security-focused linux kernel with hardening patches to mitigate exploits' || { i=3; continue; }
480 (( i++ )) # progress through to the next choice
483 case $MYSHELL in *bash) LOGINRC='.bash_profile' ;; *zsh) LOGINRC='.zprofile' ;; *mksh) LOGINRC='.profile' ;; esac
491 local v='' u='' p='' p2='' rp='' rp2=''
493 until [[ $NEWUSER ]]; do
496 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " User " --mixedform "$_user" 0 0 0 \
497 "Username:" 1 1 "$u" 1 11 "$COLUMNS" 0 0 \
498 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
499 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 \
500 "--- Root password, if left empty the user password will be used ---" 6 1 '' 6 68 "$COLUMNS" 0 2 \
501 "Password:" 8 1 '' 8 11 "$COLUMNS" 0 1 \
502 "Password2:" 9 1 '' 9 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
504 while read -r line; do
505 case $i in 0) u="$line" ;; 1) p="$line" ;; 2) p2="$line" ;; 3) rp="$line" ;; 4) rp2="$line" ;; esac
509 # root passwords empty, so use the user passwords
510 [[ -z $rp && -z $rp2 ]] && { rp="$p"; rp2="$p2"; }
512 # make sure a username was entered and that the passwords match
513 if [[ ${#u} -eq 0 || $u =~ \ |\' || $u =~ [^a-z0-9] ]]; then
514 msg "Invalid Username" "\nIncorrect user name.\n\nPlease try again.\n"; u=''
515 elif [[ -z $p ]]; then
516 msg "Empty Password" "\nThe user password cannot be left empty.\n\nPlease try again.\n"
517 elif [[ "$p" != "$p2" ]]; then
518 msg "Password Mismatch" "\nThe user passwords do not match.\n\nPlease try again.\n"
519 elif [[ "$rp" != "$rp2" ]]; then
520 msg "Password Mismatch" "\nThe root passwords do not match.\n\nPlease try again.\n"
532 dlg KEYMAP menu "Keyboard Layout" "$_keymap" \
533 us English cm English gb English au English gh English \
534 za English ng English ca French 'cd' French gn French \
535 tg French fr French de German at German ch German \
536 es Spanish latam Spanish br Portuguese pt Portuguese ma Arabic \
537 sy Arabic ara Arabic ua Ukrainian cz Czech ru Russian \
538 sk Slovak nl Dutch it Italian hu Hungarian cn Chinese \
539 tw Taiwanese vn Vietnamese kr Korean jp Japanese th Thai \
540 la Lao pl Polish se Swedish is Icelandic 'fi' Finnish \
541 dk Danish be Belgian in Indian al Albanian am Armenian \
542 bd Bangla ba Bosnian 'bg' Bulgarian dz Berber mm Burmese \
543 hr Croatian gr Greek il Hebrew ir Persian iq Iraqi \
544 af Afghani fo Faroese ge Georgian ee Estonian kg Kyrgyz \
545 kz Kazakh lt Lithuanian mt Maltese mn Mongolian ro Romanian \
546 no Norwegian rs Serbian si Slovenian tj Tajik lk Sinhala \
547 tr Turkish uz Uzbek ie Irish pk Urdu 'mv' Dhivehi \
548 np Nepali et Amharic sn Wolof ml Bambara tz Swahili \
549 ke Swahili bw Tswana ph Filipino my Malay tm Turkmen \
550 id Indonesian bt Dzongkha lv Latvian md Moldavian mao Maori \
551 by Belarusian az Azerbaijani mk Macedonian kh Khmer epo Esperanto \
552 me Montenegrin || return 1
554 if [[ $CMAPS == *"$KEYMAP"* ]]; then
557 dlg CMAP menu "Console Keymap" "$_vconsole" $CMAPS || return 1
560 if [[ $DISPLAY && $TERM != 'linux' ]]; then
561 setxkbmap "$KEYMAP" >/dev/null 2>&1
563 loadkeys "$CMAP" >/dev/null 2>&1
573 dlg INSTALL_WMS check "Sessions" "$_sessions\n" \
574 i3-gaps "A fork of i3wm with more features including gaps" "$(ofn i3-gaps "${INSTALL_WMS[*]}")" \
575 openbox "A lightweight, powerful, and highly configurable stacking wm" "$(ofn openbox "${INSTALL_WMS[*]}")" \
576 awesome "A customized Awesome WM session created by @elanapan" "$(ofn awesome "${INSTALL_WMS[*]}")" \
577 dwm "A dynamic WM for X that manages windows in tiled, floating, or monocle layouts" "$(ofn dwm "${INSTALL_WMS[*]}")" \
578 bspwm "A tiling wm that represents windows as the leaves of a binary tree" "$(ofn bspwm "${INSTALL_WMS[*]}")" \
579 fluxbox "A lightweight and highly-configurable window manager" "$(ofn fluxbox "${INSTALL_WMS[*]}")" \
580 gnome "A desktop environment that aims to be simple and easy to use" "$(ofn gnome "${INSTALL_WMS[*]}")" \
581 cinnamon "A desktop environment combining traditional desktop with modern effects" "$(ofn cinnamon "${INSTALL_WMS[*]}")" \
582 plasma "A kde software project currently comprising a full desktop environment" "$(ofn plasma "${INSTALL_WMS[*]}")" \
583 xfce4 "A lightweight and modular desktop environment based on gtk+2/3" "$(ofn xfce4 "${INSTALL_WMS[*]}")"
585 [[ $INSTALL_WMS ]] || return 0
587 WM_PKGS="${INSTALL_WMS/dwm/}" # remove dwm from package list
588 WM_PKGS="${WM_PKGS// / }" # remove double spaces
589 WM_PKGS="${WM_PKGS# }" # remove leading space
591 # add archlabs base when choosing any session
592 [[ $WM_PKGS ]] && WM_PKGS+=" $AL_BASE_PKGS"
594 for i in $INSTALL_WMS; do
595 LOGIN_CHOICES+="$i - "
596 [[ ${WM_EXT[$i]} && $WM_PKGS != *"${WM_EXT[$i]}"* ]] && WM_PKGS+=" ${WM_EXT[$i]}"
599 select_login || return 1
601 while IFS=' ' read -r pkg; do
602 [[ $PACKAGES != *"$pkg"* ]] && PACKAGES+=" $pkg"
610 dlg USER_PKGS check " Packages " "$_packages" \
611 abiword "A Fully-featured word processor" "$(ofn abiword "${USER_PKGS[*]}")" \
612 alacritty "A cross-platform, GPU-accelerated terminal emulator" "$(ofn alacritty "${USER_PKGS[*]}")" \
613 atom "An open-source text editor developed by GitHub" "$(ofn atom "${USER_PKGS[*]}")" \
614 audacious "A free and advanced audio player based on GTK+" "$(ofn audacious "${USER_PKGS[*]}")" \
615 audacity "A program that lets you manipulate digital audio waveforms" "$(ofn audacity "${USER_PKGS[*]}")" \
616 cairo-dock "Light eye-candy fully themable animated dock" "$(ofn cairo-dock "${USER_PKGS[*]}")" \
617 calligra "A set of applications for productivity" "$(ofn calligra "${USER_PKGS[*]}")" \
618 chromium "An open-source web browser based on the Blink rendering engine" "$(ofn chromium "${USER_PKGS[*]}")" \
619 clementine "A modern music player and library organizer" "$(ofn clementine "${USER_PKGS[*]}")" \
620 cmus "A small, fast and powerful console music player" "$(ofn cmus "${USER_PKGS[*]}")" \
621 deadbeef "A GTK+ audio player for GNU/Linux" "$(ofn deadbeef "${USER_PKGS[*]}")" \
622 deluge "A BitTorrent client written in python" "$(ofn deluge "${USER_PKGS[*]}")" \
623 docky "Full fledged dock for opening applications and managing windows" "$(ofn docky "${USER_PKGS[*]}")" \
624 emacs "An extensible, customizable, self-documenting real-time display editor" "$(ofn emacs "${USER_PKGS[*]}")" \
625 epiphany "A GNOME web browser based on the WebKit rendering engine" "$(ofn epiphany "${USER_PKGS[*]}")" \
626 evince "A document viewer" "$(ofn evince "${USER_PKGS[*]}")" \
627 evolution "Manage your email, contacts and schedule" "$(ofn evolution "${USER_PKGS[*]}")" \
628 file-roller "Create and modify archives" "$(ofn file-roller "${USER_PKGS[*]}")" \
629 firefox "A popular open-source web browser from Mozilla" "$(ofn firefox "${USER_PKGS[*]}")" \
630 gcolor2 "A simple GTK+2 color selector" "$(ofn gcolor2 "${USER_PKGS[*]}")" \
631 geany "A fast and lightweight IDE" "$(ofn geany "${USER_PKGS[*]}")" \
632 geary "A lightweight email client for the GNOME desktop" "$(ofn geary "${USER_PKGS[*]}")" \
633 gimp "GNU Image Manipulation Program" "$(ofn gimp "${USER_PKGS[*]}")" \
634 gnome-disk-utility "Disk Management Utility" "$(ofn gnome-disk-utility "${USER_PKGS[*]}")" \
635 gnome-system-monitor "View current processes and monitor system state" "$(ofn gnome-system-monitor "${USER_PKGS[*]}")" \
636 gparted "A GUI frontend for creating and manipulating partition tables" "$(ofn gparted "${USER_PKGS[*]}")" \
637 gpick "Advanced color picker using GTK+ toolkit" "$(ofn gpick "${USER_PKGS[*]}")" \
638 gpicview "Lightweight image viewer" "$(ofn gpicview "${USER_PKGS[*]}")" \
639 guvcview "Capture video from camera devices" "$(ofn guvcview "${USER_PKGS[*]}")" \
640 hexchat "A popular and easy to use graphical IRC client" "$(ofn hexchat "${USER_PKGS[*]}")" \
641 inkscape "Professional vector graphics editor" "$(ofn inkscape "${USER_PKGS[*]}")" \
642 irssi "Modular text mode IRC client" "$(ofn irssi "${USER_PKGS[*]}")" \
643 kdenlive "A popular non-linear video editor for Linux" "$(ofn kdenlive "${USER_PKGS[*]}")" \
644 krita "Edit and paint images" "$(ofn krita "${USER_PKGS[*]}")" \
645 libreoffice-fresh "Full featured office suite" "$(ofn libreoffice-fresh "${USER_PKGS[*]}")" \
646 lollypop "A new music playing application" "$(ofn lollypop "${USER_PKGS[*]}")" \
647 mousepad "A simple text editor" "$(ofn mousepad "${USER_PKGS[*]}")" \
648 mpd "A flexible, powerful, server-side application for playing music" "$(ofn mpd "${USER_PKGS[*]}")" \
649 mpv "A media player based on mplayer" "$(ofn mpv "${USER_PKGS[*]}")" \
650 mupdf "Lightweight PDF and XPS viewer" "$(ofn mupdf "${USER_PKGS[*]}")" \
651 mutt "Small but very powerful text-based mail client" "$(ofn mutt "${USER_PKGS[*]}")" \
652 nautilus "The default file manager for Gnome" "$(ofn nautilus "${USER_PKGS[*]}")" \
653 ncmpcpp "A mpd client and almost exact clone of ncmpc with some new features" "$(ofn ncmpcpp "${USER_PKGS[*]}")" \
654 neovim "A fork of Vim aiming to improve user experience, plugins, and GUIs." "$(ofn neovim "${USER_PKGS[*]}")" \
655 nicotine+ "A graphical client for Soulseek" "$(ofn nicotine+ "${USER_PKGS[*]}")" \
656 noto-fonts "Google Noto fonts" "$(ofn noto-fonts "${USER_PKGS[*]}")" \
657 noto-fonts-cjk "Google Noto CJK fonts (Chinese, Japanese, Korean)" "$(ofn noto-fonts-cjk "${USER_PKGS[*]}")" \
658 obs-studio "Free opensource streaming/recording software" "$(ofn obs-studio "${USER_PKGS[*]}")" \
659 openshot "An open-source, non-linear video editor for Linux" "$(ofn openshot "${USER_PKGS[*]}")" \
660 opera "A Fast and secure, free of charge web browser from Opera Software" "$(ofn opera "${USER_PKGS[*]}")" \
661 pcmanfm "A fast and lightweight file manager based in Lxde" "$(ofn pcmanfm "${USER_PKGS[*]}")" \
662 pidgin "Multi-protocol instant messaging client" "$(ofn pidgin "${USER_PKGS[*]}")" \
663 plank "An elegant, simple, and clean dock" "$(ofn plank "${USER_PKGS[*]}")" \
664 qbittorrent "An advanced BitTorrent client" "$(ofn qbittorrent "${USER_PKGS[*]}")" \
665 qpdfview "A tabbed PDF viewer" "$(ofn qpdfview "${USER_PKGS[*]}")" \
666 qt5ct "GUI for managing Qt based application themes, icons, and fonts" "$(ofn qt5ct "${USER_PKGS[*]}")" \
667 qutebrowser "A keyboard-focused vim-like web browser based on Python and PyQt5" "$(ofn qutebrowser "${USER_PKGS[*]}")" \
668 rhythmbox "A Music playback and management application" "$(ofn rhythmbox "${USER_PKGS[*]}")" \
669 rxvt-unicode "A unicode enabled rxvt-clone terminal emulator" "$(ofn rxvt-unicode "${USER_PKGS[*]}")" \
670 sakura "A terminal emulator based on GTK and VTE" "$(ofn sakura "${USER_PKGS[*]}")" \
671 simplescreenrecorder "A feature-rich screen recorder" "$(ofn simplescreenrecorder "${USER_PKGS[*]}")" \
672 steam "A popular game distribution platform by Valve" "$(ofn steam "${USER_PKGS[*]}")" \
673 surf "A simple web browser based on WebKit2/GTK+" "$(ofn surf "${USER_PKGS[*]}")" \
674 terminator "Terminal emulator that supports tabs and grids" "$(ofn terminator "${USER_PKGS[*]}")" \
675 termite "A minimal VTE-based terminal emulator" "$(ofn termite "${USER_PKGS[*]}")" \
676 thunar "A modern file manager for the Xfce Desktop Environment" "$(ofn thunar "${USER_PKGS[*]}")" \
677 thunderbird "Standalone mail and news reader from mozilla" "$(ofn thunderbird "${USER_PKGS[*]}")" \
678 tilda "A GTK based drop down terminal for Linux and Unix" "$(ofn tilda "${USER_PKGS[*]}")" \
679 tilix "A tiling terminal emulator for Linux using GTK+ 3" "$(ofn tilix "${USER_PKGS[*]}")" \
680 transmission-cli "Free BitTorrent client CLI" "$(ofn transmission-cli "${USER_PKGS[*]}")" \
681 transmission-gtk "Free BitTorrent client GTK+ GUI" "$(ofn transmission-gtk "${USER_PKGS[*]}")" \
682 transmission-qt "Free BitTorrent client Qt GUI" "$(ofn transmission-qt "${USER_PKGS[*]}")" \
683 ttf-anonymous-pro "A family fixed-width fonts designed with code in mind" "$(ofn ttf-anonymous-pro "${USER_PKGS[*]}")" \
684 ttf-fira-code "Monospaced font with programming ligatures" "$(ofn ttf-fira-code "${USER_PKGS[*]}")" \
685 ttf-font-awesome "Iconic font designed for Bootstrap" "$(ofn ttf-font-awesome "${USER_PKGS[*]}")" \
686 ttf-hack "A hand groomed typeface based on Bitstream Vera Mono" "$(ofn ttf-hack "${USER_PKGS[*]}")" \
687 vlc "A free and open source cross-platform multimedia player" "$(ofn vlc "${USER_PKGS[*]}")" \
688 weechat "Fast, light and extensible IRC client" "$(ofn weechat "${USER_PKGS[*]}")" \
689 xarchiver "A GTK+ frontend to various command line archivers" "$(ofn xarchiver "${USER_PKGS[*]}")" \
690 xfce-terminal "A terminal emulator based in the Xfce Desktop Environment" "$(ofn xfce-terminal "${USER_PKGS[*]}")" \
691 xterm "The standard terminal emulator for the X window system" "$(ofn xterm "${USER_PKGS[*]}")" \
692 zathura "Minimalistic document viewer" "$(ofn zathura "${USER_PKGS[*]}")"
694 if [[ $USER_PKGS ]]; then
695 for i in $USER_PKGS; do
696 [[ ${PKG_EXT[$i]} && $USER_PKGS != *"${PKG_EXT[$i]}"* ]] && USER_PKGS+=" ${PKG_EXT[$i]}"
703 ###############################################################################
705 # non-essential partitioning helpers called by the user when using the optional
706 # partition menu and selecting a device to edit
710 is_bg_install || return 0
711 local device choice devhash
712 devhash="$(lsblk -f | base64)"
714 part_device || return 1
719 if [[ $DISPLAY && $TERM != 'linux' ]] && hash gparted >/dev/null 2>&1; then
720 dlg choice menu "Edit Partitions" "$_part" \
721 "auto" "Whole device automatic partitioning" \
722 "shrink" "Shrink an existing ext2/3/4 or ntfs partition to make room for a new partition" \
723 "gparted" "GUI front end to parted" \
724 "cfdisk" "Curses based variant of fdisk" \
725 "parted" "GNU partition editor" \
726 "fdisk" "Dialog-driven creation and manipulation of partitions" \
727 "done" "Return to the main menu" || return 0
729 dlg choice menu "Edit Partitions" "$_part" \
730 "auto" "Whole device automatic partitioning" \
731 "shrink" "Shrink an existing ext2/3/4 or ntfs partition to make room for a new partition" \
732 "cfdisk" "Curses based variant of fdisk" \
733 "parted" "GNU partition editor" \
734 "fdisk" "Dialog-driven creation and manipulation of partitions" \
735 "done" "Return to the main menu" || return 0
738 if [[ $choice == 'done' ]]; then
740 elif [[ $choice == 'shrink' ]]; then
741 part_shrink "$device"
742 elif [[ $choice == 'auto' ]]; then
743 local root_size txt table boot_fs
744 root_size=$(lsblk -lno SIZE "$device" | awk 'NR == 1 {
747 print ($1 * 1000 - 512) / 1000 "G"
753 txt="\nWARNING:\n\nALL data on $device will be destroyed and the following partitions will be created\n\n- "
754 if [[ $SYS == 'BIOS' ]]; then
755 table="msdos" boot_fs="ext4"
756 txt+="An $boot_fs boot partition with the boot flag enabled (512M)\n- "
758 table="gpt" boot_fs="fat32"
759 txt+="A $boot_fs efi boot partition (512M)\n- "
761 txt+="An ext4 partition using all remaining space ($root_size)\n\nDo you want to continue?\n"
762 yesno "Auto Partition" "$txt" && part_auto "$device" "$table" "$boot_fs" "$root_size"
768 if [[ $devhash != "$(lsblk -f | base64)" ]]; then
769 msg "Probing Partitions" "\nInforming the kernel of partition changes using partprobe.\n" 0
770 partprobe >/dev/null 2>&1
778 if [[ $IGNORE_DEV ]]; then
779 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk "!/$IGNORE_DEV/"' && /disk|part|lvm|crypt|NAME/')"
781 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk '/disk|part|lvm|crypt|NAME/')"
783 msg "Device Tree" "\n\n$txt\n\n"
788 if [[ $1 == "$MNT/swapfile" && $SWAP_SIZE ]]; then
789 fallocate -l $SWAP_SIZE "$1" 2>$ERR
790 errshow "fallocate -l $SWAP_SIZE $1"
791 chmod 600 "$1" 2>$ERR
792 errshow "chmod 600 $1"
794 mkswap "$1" >/dev/null 2>$ERR
796 swapon "$1" >/dev/null 2>$ERR
803 local device="$1" table="$2" boot_fs="$3" size="$4" dev_info=""
804 dev_info="$(parted -s "$device" print)"
806 msg "Auto Partition" "\nRemoving partitions on $device and setting table to $table\n" 1
809 while read -r PART; do
810 parted -s "$device" rm "$PART" >/dev/null 2>&1
811 done <<< "$(awk '/^ [1-9][0-9]?/ {print $1}' <<< "$dev_info" | sort -r)"
813 [[ $(awk '/Table:/ {print $3}' <<< "$dev_info") != "$table" ]] && parted -s "$device" mklabel "$table" >/dev/null 2>&1
815 msg "Auto Partition" "\nCreating a 512M $boot_fs boot partition.\n" 1
816 if [[ $SYS == "BIOS" ]]; then
817 parted -s "$device" mkpart primary "$boot_fs" 1MiB 513MiB >/dev/null 2>&1
819 parted -s "$device" mkpart ESP "$boot_fs" 1MiB 513MiB >/dev/null 2>&1
824 AUTO_BOOT_PART=$(lsblk -lno NAME,TYPE "$device" | awk 'NR==2 {print "/dev/" $1}')
826 if [[ $SYS == "BIOS" ]]; then
827 mkfs.ext4 -q "$AUTO_BOOT_PART" >/dev/null 2>&1
829 mkfs.vfat -F32 "$AUTO_BOOT_PART" >/dev/null 2>&1
832 msg "Auto Partition" "\nCreating a $size ext4 root partition.\n" 0
833 parted -s "$device" mkpart primary ext4 513MiB 100% >/dev/null 2>&1
835 AUTO_ROOT_PART="$(lsblk -lno NAME,TYPE "$device" | awk 'NR==3 {print "/dev/" $1}')"
836 mkfs.ext4 -q "$AUTO_ROOT_PART" >/dev/null 2>&1
838 FORMATTED+="$AUTO_BOOT_PART $AUTO_ROOT_PART "
839 msg "Auto Partition" "\nProcess complete.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$device")\n"
846 local device="$1" fs=""
848 part_find "${device##*/}[^ ]" || return 1
849 (( COUNT == 1 )) && part="$(awk '{print $1}' <<< "${PARTS[@]}" )"
851 if (( COUNT == 1 )) || dlg part menu "Resize" "\nWhich partition on $device do you want to resize?" $PARTS; then
852 fs=$(lsblk -lno FSTYPE "$part")
855 msg "Resize" "\nGathering device size info.\n" 0
857 end=$(parted -s "$device" unit KiB print | awk '/^\s*'"$num"'/ {print $3}') # part size in KiB
858 devsize=$(parted -s "$device" unit KiB print | awk '/Disk '"${device//\//\\/}"':/ {print $3}') # whole device size in KiB
859 mount "$part" $MNT >/dev/null 2>&1; sleep 0.5
860 min=$(df --output=used --block-size=MiB "$part" | awk 'NR == 2 {print int($1) + 256}')
861 max=$(df --output=avail --block-size=MiB "$part" | awk 'NR == 2 {print int($1)}')
864 if dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Resize: $part " --rangebox "$_resize" 17 "$COLUMNS" "$min" "$max" $((max / 2)) 2>$ANS; then
866 size=$((size * 1024))
873 if ntfsresize -fc "$part"; then
874 ntfsresize -ff --size $(( (size * 1024) / 1000 ))k "$part" 2>$ERR # k=10^3 bytes
875 errshow "ntfsresize -f -s $(( (size * 1024) / 1000 ))k $part" || return 1
877 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"
882 e2fsck -f "$part"; sleep 0.5
883 resize2fs -f "$part" ${size}K 2>$ERR # K=2^10 bytes
884 errshow "resize2fs -f $part ${size}K" || return 1
888 parted "$device" resizepart "$num" ${size}KiB || return 1
891 if [[ $devsize == "$end" ]]; then
892 parted -s "$device" mkpart primary ext4 ${size}KiB 100% 2>$ERR
893 errshow "parted -s $device mkpart primary ext4 ${size}KiB 100%" || return 1
895 parted -s "$device" mkpart primary ext4 ${size}KiB ${end}KiB 2>$ERR
896 errshow "parted -s $device mkpart primary ext4 ${size}KiB ${end}KiB" || return 1
898 msg "Resize Complete" "\n$part has been successfully resized to $((size / 1024))M.\n" 1
900 "") msg "No Filesystem" "\nFor unformatted partitions, cfdisk can be used in the partition menu.\n" ;;
901 *) msg "Invalid Filesystem: $fs" "\nResizing only supports ext and ntfs.\n" ;;
906 ###############################################################################
907 # partition management functions
908 # these are helpers for use by other functions to do essential setup/teardown
912 local regexp="$1" err=''
914 # string of partitions as /TYPE/PART SIZE
915 if [[ $IGNORE_DEV ]]; then
916 PARTS="$(lsblk -lno TYPE,NAME,SIZE |
917 awk "/$regexp/"' && !'"/$IGNORE_DEV/"' {
918 sub(/^part/, "/dev/")
919 sub(/^lvm|^crypt/, "/dev/mapper/")
923 PARTS="$(lsblk -lno TYPE,NAME,SIZE |
925 sub(/^part/, "/dev/")
926 sub(/^lvm|^crypt/, "/dev/mapper/")
931 # number of partitions total
933 while read -r line; do
937 # ensure we have enough partitions for the system and action type
939 'part|lvm|crypt') [[ $COUNT -lt 1 || ($SYS == 'UEFI' && $COUNT -lt 2) ]] && err="$_errpart" ;;
940 'part|crypt') (( COUNT < 1 )) && err="$_lvmerr" ;;
941 'part|lvm') (( COUNT < 2 )) && err="$_lukserr" ;;
944 # if there aren't enough partitions show the relevant error message
945 [[ $err ]] && { msg "Not Enough Partitions" "$err" 2; return 1; }
952 local part="$1" mountp="${MNT}$2" fs=""
953 fs="$(lsblk -lno FSTYPE "$part")"
956 if [[ $fs && ${FS_OPTS[$fs]} && $part != "$BOOT_PART" ]] && select_mntopts "$fs"; then
957 mount -o "$MNT_OPTS" "$part" "$mountp" >/dev/null 2>&1
959 mount "$part" "$mountp" >/dev/null 2>&1
962 part_mountconf "$part" "$mountp" || return 1
970 local part="$1" fs="$2" delay="$3"
972 msg "Format" "\nFormatting $part as $fs\n" 0
973 ${FS_CMDS[$fs]} "$part" >/dev/null 2>$ERR
974 errshow "${FS_CMDS[$fs]} $part" || return 1
981 if [[ $DEV_COUNT -eq 1 && $SYS_DEVS ]]; then
982 DEVICE="$(awk '{print $1}' <<< "$SYS_DEVS")"
983 elif (( DEV_COUNT > 1 )); then
985 dlg DEVICE menu "Boot Device" "\nSelect the device to use for bootloader install." $SYS_DEVS
987 dlg DEVICE menu "Select Device" "$_device" $SYS_DEVS
989 [[ $DEVICE ]] || return 1
990 elif [[ $DEV_COUNT -lt 1 && ! $1 ]]; then
991 msg "Device Error" "\nNo available devices.\n\nExiting..\n" 2
995 [[ $1 ]] && BOOT_DEV="$DEVICE"
1002 BOOT_DEV="${BOOT_PART%[1-9]}"
1003 BOOT_PART_NUM="${BOOT_PART: -1}"
1004 [[ $BOOT_PART = /dev/nvme* ]] && BOOT_DEV="${BOOT_PART%p[1-9]}"
1005 if [[ $SYS == 'UEFI' ]]; then
1006 parted -s $BOOT_DEV set $BOOT_PART_NUM esp on >/dev/null 2>&1
1008 parted -s $BOOT_DEV set $BOOT_PART_NUM boot on >/dev/null 2>&1
1015 local part="$1" devs=""
1016 devs="$(lsblk -lno NAME,FSTYPE,TYPE)"
1018 # Identify if $part is LUKS+LVM, LVM+LUKS, LVM alone, or LUKS alone
1019 if lsblk -lno TYPE "$part" | grep -q 'crypt'; then
1021 LUKS_NAME="${part#/dev/mapper/}"
1023 for dev in $(awk '/lvm/ && /crypto_LUKS/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
1024 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1025 LUKS_DEV="$LUKS_DEV cryptdevice=$dev:$LUKS_NAME"
1026 LVM='logical volume'
1031 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
1032 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1033 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
1034 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
1039 elif lsblk -lno TYPE "$part" | grep -q 'lvm'; then
1040 LVM='logical volume'
1041 VNAME="${part#/dev/mapper/}"
1043 for dev in $(awk '/crypt/ && /lvm2_member/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
1044 if lsblk -lno NAME "$dev" | grep -q "$VNAME"; then
1045 LUKS_NAME="${dev/\/dev\/mapper\//}"
1050 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
1051 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1052 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
1053 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
1064 if (( COUNT > 0 )); then
1065 PARTS="$(sed "/${pt//\//\\/}/d" <<< "$PARTS")"
1073 if grep -qw "$1" /proc/mounts; then
1074 msg "Mount Success" "\nPartition $1 mounted at $2\n" 1
1078 msg "Mount Fail" "\nPartition $1 failed to mount at $2\n" 2
1083 ###############################################################################
1085 # mount_menu is the entry point which calls all other functions
1086 # once finished it returns to the main menu: main()
1090 msg "Info" "\nGathering device info.\n" 0
1091 is_bg_install || return 0
1094 part_find 'part|lvm|crypt' || { SEL=2; return 1; }
1096 [[ $LUKS && $LUKS_PART ]] && part_countdec $LUKS_PART
1097 [[ $LVM && $LVM_PARTS ]] && part_countdec $LVM_PARTS
1099 select_root_partition || return 1
1101 if [[ $SYS == 'UEFI' ]]; then
1102 select_efi_partition || { BOOT_PART=''; return 1; }
1103 elif (( COUNT > 0 )); then
1104 select_boot_partition || { BOOT_PART=''; return 1; }
1107 if [[ $BOOT_PART ]]; then
1108 part_mount "$BOOT_PART" "/$BOOTDIR" && SEP_BOOT=true || return 1
1112 select_swap || return 1
1113 select_extra_partitions || return 1
1121 dlg SWAP_PART menu "Swap Setup" "\nSelect whether to use a swapfile, swap partition, or none." \
1122 "none" "Don't allocate any swap space" \
1123 "swapfile" "Allocate $SYS_MEM at /swapfile" \
1126 if [[ -z $SWAP_PART || $SWAP_PART == "none" ]]; then
1129 elif [[ $SWAP_PART == "swapfile" ]]; then
1131 until [[ ${SWAP_SIZE:0:1} =~ [1-9] && ${SWAP_SIZE: -1} =~ (M|G) ]]; do
1132 (( 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
1133 dlg SWAP_SIZE input "Swap Setup" "$_swapsize" "$SYS_MEM" || { SWAP_PART=''; SWAP_SIZE=''; return 1; }
1136 part_swap "$MNT/$SWAP_PART"
1137 SWAP_PART="/$SWAP_PART"
1138 elif [[ $PARTS == *"$SWAP_PART"* ]]; then
1139 part_swap $SWAP_PART
1140 part_countdec $SWAP_PART
1141 SWAP_SIZE="$(lsblk -lno SIZE $SWAP_PART)"
1151 local fs="$1" opts=''
1152 local title="${fs^} Mount Options"
1154 for i in ${FS_OPTS[$fs]}; do
1158 until [[ $MNT_OPTS ]]; do
1159 dlg MNT_OPTS check "$title" "$_mount" $opts
1160 [[ $MNT_OPTS ]] || return 1
1161 MNT_OPTS="${MNT_OPTS// /,}"
1162 yesno "$title" "\nConfirm the following options: $MNT_OPTS\n" || MNT_OPTS=''
1171 until [[ $EXMNT ]]; do
1172 dlg EXMNT input "Extra Mount $part" "$_exmnt" "/" || return 1
1173 if [[ ${EXMNT:0:1} != "/" || ${#EXMNT} -le 1 || $EXMNT =~ \ |\' || $EXMNTS == *"$EXMNT"* ]]; then
1174 msg "Mountpoint Error" "$_errexpart"
1183 local part="$1" fs='' cur=''
1184 local txt="\nSelect which filesystem to use for: $part\n\nDefault: ext4"
1185 cur="$(lsblk -lno FSTYPE "$part" 2>/dev/null)"
1188 if [[ $cur && ($part != "$ROOT_PART" || $FORMATTED == *"$part"*) ]]; then
1189 dlg fs menu "Filesystem" "$txt\nCurrent: $cur" skip - ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1191 dlg fs menu "Filesystem" "$txt" ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1193 [[ $fs == 'skip' ]] && return 0
1194 yesno "Filesystem" "\nFormat $part as $fs?\n" || fs=''
1196 part_format "$part" "$fs"
1199 select_efi_partition()
1201 if [[ $AUTO_BOOT_PART ]]; then
1202 msg "EFI Boot Partition" "\nUsing partition created during automatic format.\n" 2
1203 BOOT_PART="$AUTO_BOOT_PART"; return 0 # were done here
1205 local pts size dev isize bsize ptcount=0
1207 # walk partition list and skip ones that are too small/big for boot
1208 while read -r dev size; do
1209 size_t="${size: -1:1}" # size type eg. K, M, G, T
1210 isize=${size:0:-1} # remove trailing size type character
1211 isize=${isize%.*} # remove any decimal (round down)
1212 [[ $size_t =~ [KT] || ($size_t == 'G' && $isize -gt 2) || ($size_t == 'M' && $isize -lt 100) ]] || { pts+="$dev $size "; (( ptcount++ )); }
1215 if (( ptcount == 1 )); then
1216 msg "EFI Boot Partition" "\nOnly one partition available that meets size requirements.\n" 1
1217 BOOT_PART="$(awk 'NF > 0 {print $1}' <<< "$pts")"
1219 dlg BOOT_PART menu "EFI Partition" "$_uefi" $pts
1223 [[ $BOOT_PART ]] || return 1
1225 if grep -q 'fat' <<< "$(fsck -N "$BOOT_PART")"; then
1226 local txt="\nIMPORTANT:\n\nThe EFI partition $BOOT_PART $_format"
1227 if yesno "Format EFI Partition" "$txt" "Format $BOOT_PART" "Skip Formatting" 1; then
1228 part_format "$BOOT_PART" "vfat" 2
1231 part_format "$BOOT_PART" "vfat" 2
1237 select_boot_partition()
1239 if [[ $AUTO_BOOT_PART && ! $LVM ]]; then
1240 msg "BIOS Boot Partition" "\nUsing partition created during automatic format.\n" 2
1241 BOOT_PART="$AUTO_BOOT_PART"; return 0 # were done here
1243 local pts size dev isize bsize ptcount=0
1245 # walk partition list and skip ones that are too small/big for boot
1246 while read -r dev size; do
1247 size_t="${size: -1:1}" # size type eg. K, M, G, T
1248 isize=${size:0:-1} # remove trailing size type character
1249 isize=${isize%.*} # remove any decimal (round down)
1250 [[ $size_t =~ [KT] || ($size_t == 'G' && $isize -gt 2) || ($size_t == 'M' && $isize -lt 100) ]] || { pts+="$dev $size "; (( ptcount++ )); }
1253 if [[ $LUKS && ! $LVM ]]; then
1254 dlg BOOT_PART menu "Boot Partition" "$_biosluks" $pts
1255 [[ $BOOT_PART ]] || return 1
1257 dlg BOOT_PART menu "Boot Partition" "$_bios" "skip" "don't use a separate boot" $pts
1258 [[ -z $BOOT_PART || $BOOT_PART == "skip" ]] && { BOOT_PART=''; return 0; }
1262 if grep -q 'ext[34]' <<< "$(fsck -N "$BOOT_PART")"; then
1263 local txt="\nIMPORTANT:\n\nThe boot partition $BOOT_PART $_format"
1264 if yesno "Format Boot Partition" "$txt" "Format $BOOT_PART" "Skip Formatting" 1; then
1265 part_format "$BOOT_PART" "ext4" 2
1268 part_format "$BOOT_PART" "ext4" 2
1273 select_root_partition()
1275 if [[ $AUTO_ROOT_PART && -z $LVM && -z $LUKS ]]; then
1276 ROOT_PART="$AUTO_ROOT_PART"
1277 msg "Select Root Partition (/)" "\nUsing partition created during automatic format.\n" 2
1278 part_mount "$ROOT_PART" || { ROOT_PART=''; return 1; }
1279 return 0 # we're done here
1281 local pts size dev isize bsize ptcount=0
1283 # walk partition list and skip ones that are too small for / (root)
1284 while read -r dev size; do
1285 size_t="${size: -1:1}" # size type eg. K, M, G, T
1286 isize=${size:0:-1} # remove trailing size type character
1287 isize=${isize%.*} # remove any decimal (round down)
1288 [[ $size_t =~ [MK] || ($size_t == 'G' && $isize -lt 4) ]] || { pts+="$dev $size "; (( ptcount++ )); }
1291 if (( ptcount == 1 )); then # only one available device
1292 msg "Select Root Partition (/)" "\nOnly one partition available that meets size requirements.\n" 2
1293 ROOT_PART="$(awk 'NR==1 {print $1}' <<< "$pts")"
1295 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
1298 [[ $ROOT_PART ]] || return 1
1300 select_filesystem "$ROOT_PART" || { ROOT_PART=''; return 1; }
1301 part_mount "$ROOT_PART" || { ROOT_PART=''; return 1; }
1306 select_extra_partitions()
1310 # walk partition list and skip ones that are too small to be usable
1311 while read -r dev size; do
1312 [[ ${size: -1:1} =~ [KM] ]] && part_countdec "$dev"
1315 while (( COUNT > 0 )); do
1317 dlg part menu 'Mount Extra' "$_expart" 'done' 'finish mounting step' $PARTS || break
1318 if [[ $part == 'done' ]]; then
1320 elif select_filesystem "$part" && select_mountpoint && part_mount "$part" "$EXMNT"; then
1321 EXMNTS+="$part: $EXMNT "
1322 [[ $EXMNT == '/usr' && $HOOKS != *usr* ]] && HOOKS="usr $HOOKS"
1330 ###############################################################################
1332 # main is the entry point which calls all other install functions, once
1333 # complete it shows a dialog to edit files on the new system before reboot
1340 genfstab -U $MNT >$MNT/etc/fstab 2>$ERR
1341 errshow 1 "genfstab -U $MNT >$MNT/etc/fstab"
1342 [[ -f $MNT/swapfile ]] && sed -i "s~${MNT}~~" $MNT/etc/fstab
1346 chrun "hwclock --systohc --utc" || chrun "hwclock --systohc --utc --directisa"
1349 chrun "chown -Rf $NEWUSER:users /home/$NEWUSER"
1353 dlg choice menu "Finalization" "$_edit" \
1354 finished "exit the installer and reboot" \
1355 keyboard "${EDIT_FILES[keyboard]}" \
1356 console "${EDIT_FILES[console]}" \
1357 locale "${EDIT_FILES[locale]}" \
1358 hostname "${EDIT_FILES[hostname]}" \
1359 sudoers "${EDIT_FILES[sudoers]}" \
1360 mkinitcpio "${EDIT_FILES[mkinitcpio]}" \
1361 fstab "${EDIT_FILES[fstab]}" \
1362 crypttab "${EDIT_FILES[crypttab]}" \
1363 bootloader "${EDIT_FILES[bootloader]}" \
1364 pacman "${EDIT_FILES[pacman]}" \
1365 login "${EDIT_FILES[login]}"
1367 if [[ -z $choice || $choice == 'finished' ]]; then
1368 [[ $DEBUG == true && -r $DBG ]] && vim $DBG
1372 for f in ${EDIT_FILES[$choice]}; do
1373 [[ -e ${MNT}$f ]] && exists+=" ${MNT}$f"
1375 if [[ $exists ]]; then
1378 msg "File Missing" "\nThe file(s) selected do not exist:\n\n${EDIT_FILES[$choice]}\n"
1386 if [[ $RSYNC_PID || $MIRROR_PID ]]; then
1387 local oldmsg="" msg=""
1388 printf "\nOne or more background install processes are still running, grabbing their output...\n"
1389 while kill -0 "$RSYNC_PID" 2>/dev/null || kill -0 "$MIRROR_PID" 2>/dev/null; do
1390 msg="$(tail -n 1 /tmp/bg_out)"
1391 if [[ "$msg" != "$oldmsg" ]]; then
1392 printf "\n%s" "$msg"
1400 unset RSYNC_PID MIRROR_PID
1402 rsync -ahv /run/archiso/sfs/airootfs/ $MNT/ 2>$ERR
1403 errshow 1 "rsync -ahv /run/archiso/sfs/airootfs/ $MNT/"
1404 install_mirrorlist "$MNT/etc/pacman.d/mirrorlist"
1405 chrun "pacman -Syyu --noconfirm && pacman -S $BASE_PKGS --needed --noconfirm"
1408 rm -rf $MNT/etc/mkinitcpio-archiso.conf
1409 find $MNT/usr/lib/initcpio -name 'archiso*' -type f -delete
1410 sed -i 's/volatile/auto/g' $MNT/etc/systemd/journald.conf
1411 find $MNT/boot -name '*-ucode.img' -delete
1414 find $MNT/etc/X11/xorg.conf.d/ -name '*.conf' -delete
1415 elif lspci | grep ' VGA ' | grep -q 'Intel'; then
1416 cat > $MNT/etc/X11/xorg.conf.d/20-intel.conf <<- EOF
1418 Identifier "Intel Graphics"
1420 Option "TearFree" "true"
1425 [[ -e /run/archiso/sfs/airootfs && $KERNEL == 'linux' ]] && cp -vf $RUN/x86_64/vmlinuz $MNT/boot/vmlinuz-linux
1427 cp -fv /etc/resolv.conf $MNT/etc/
1428 [[ -e /etc/NetworkManager/system-connections ]] && cp -rvf /etc/NetworkManager/system-connections $MNT/etc/NetworkManager/
1430 echo "LANG=$MYLOCALE" > $MNT/etc/locale.conf
1431 cp -f $MNT/etc/locale.conf $MNT/etc/default/locale
1432 sed -i "s/#en_US.UTF-8/en_US.UTF-8/g; s/#${MYLOCALE}/${MYLOCALE}/g" $MNT/etc/locale.gen
1434 chrun "ln -svf /usr/share/zoneinfo/$ZONE/$SUBZ /etc/localtime"
1436 if [[ $BROADCOM_WL ]]; then
1437 echo 'blacklist bcma' >> $MNT/etc/modprobe.d/blacklist.conf
1438 rm -f $MNT/etc/modprobe/
1441 cat > $MNT/etc/X11/xorg.conf.d/00-keyboard.conf <<- EOF
1442 # Use localectl(1) to instruct systemd-localed to update it.
1443 Section "InputClass"
1444 Identifier "system-keyboard"
1445 MatchIsKeyboard "on"
1446 Option "XkbLayout" "$KEYMAP"
1450 cat > $MNT/etc/default/keyboard <<- EOF
1451 # KEYBOARD CONFIGURATION FILE
1452 # Consult the keyboard(5) manual page.
1459 printf "KEYMAP=%s\nFONT=%s\n" "$CMAP" "$FONT" > $MNT/etc/vconsole.conf
1460 echo "$MYHOST" > $MNT/etc/hostname
1461 cat > $MNT/etc/hosts <<- EOF
1464 ::1 localhost ip6-localhost ip6-loopback
1465 ff02::1 ip6-allnodes
1466 ff02::2 ip6-allrouters
1472 echo "Installing $BOOTLDR"
1474 if [[ $ROOT_PART == /dev/mapper* ]]; then
1475 ROOT_PART_ID="$ROOT_PART"
1477 local uuid_type="UUID"
1478 [[ $BOOTLDR =~ (systemd-boot|refind-efi|efistub) ]] && uuid_type="PARTUUID"
1479 ROOT_PART_ID="$uuid_type=$(blkid -s $uuid_type -o value $ROOT_PART)"
1482 if [[ $SYS == 'UEFI' ]]; then
1483 # remove our old install and generic BOOT/ dir
1484 find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname "$DIST" -type d -delete
1485 find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname 'BOOT' -type d -delete
1489 chrun "${BCMDS[$BOOTLDR]}" 2>$ERR
1490 errshow 1 "${BCMDS[$BOOTLDR]}"
1492 if [[ -d $MNT/hostrun ]]; then
1493 # cleanup the bind mounts we made earlier for the grub-probe module
1494 umount_dir $MNT/hostrun/{udev,lvm}
1495 rm -rf $MNT/hostrun >/dev/null 2>&1
1498 if [[ $SYS == 'UEFI' ]]; then
1499 # some UEFI firmware requires a generic esp/BOOT/BOOTX64.EFI
1500 mkdir -pv $MNT/$BOOTDIR/EFI/BOOT
1501 if [[ $BOOTLDR == 'grub' ]]; then
1502 cp -fv $MNT/$BOOTDIR/EFI/$DIST/grubx64.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI
1503 elif [[ $BOOTLDR == 'syslinux' ]]; then
1504 cp -rf $MNT/$BOOTDIR/EFI/syslinux/* $MNT/$BOOTDIR/EFI/BOOT/
1505 cp -f $MNT/$BOOTDIR/EFI/syslinux/syslinux.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI
1506 elif [[ $BOOTLDR == 'refind-efi' ]]; then
1507 sed -i '/#extra_kernel_version_strings/ c extra_kernel_version_strings linux-hardened,linux-zen,linux-lts,linux' $MNT/$BOOTDIR/EFI/refind/refind.conf
1508 cp -fv $MNT/$BOOTDIR/EFI/refind/refind_x64.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI
1517 echo "Creating new user $NEWUSER and setting password"
1518 rm -f $MNT/root/.zshrc # remove welcome message from root zshrc
1520 chrun "chpasswd <<< 'root:$ROOT_PASS'" 2>$ERR
1521 errshow 1 "set root password"
1522 if [[ $MYSHELL != "/usr/bin/zsh" ]]; then # root uses zsh by default, change it if something else was chosen
1523 chrun "usermod -s $MYSHELL root" 2>$ERR
1524 errshow 1 "usermod -s $MYSHELL root"
1525 # copy the default mkshrc to /root if mksh was picked
1526 [[ $MYSHELL == '/usr/bin/mksh' ]] && cp -fv $MNT/etc/skel/.mkshrc $MNT/root/.mkshrc
1529 local groups='audio,floppy,log,network,rfkill,scanner,storage,optical,power,wheel'
1531 chrun "useradd -m -u 1000 -g users -G $groups -s $MYSHELL $NEWUSER" 2>$ERR
1532 errshow 1 "useradd -m -u 1000 -g users -G $groups -s $MYSHELL $NEWUSER"
1533 chrun "chpasswd <<< '$NEWUSER:$USER_PASS'" 2>$ERR
1534 errshow 1 "set $NEWUSER password"
1536 # if neovim was picked copy vim configs to ~/.config/nvim
1537 if [[ $USER_PKGS == *neovim* ]]; then
1538 mkdir -p $MNT/home/$NEWUSER/.config/nvim
1539 cp -fv $MNT/home/$NEWUSER/.vimrc $MNT/home/$NEWUSER/.config/nvim/init.vim
1540 cp -rfv $MNT/home/$NEWUSER/.vim/colors $MNT/home/$NEWUSER/.config/nvim/colors
1543 [[ $INSTALL_WMS == *dwm* ]] && install_suckless
1545 [[ $WM_PKGS == *xfce* ]] && echo 'volumeicon &' >> $MNT/home/$NEWUSER/.xprofile
1547 # remove some commands from ~/.xprofile when using KDE or Gnome as the login session
1548 if [[ $LOGIN_WM =~ (startkde|gnome-session) || ($LOGIN_TYPE =~ (lightdm|ly) && $WM_PKGS =~ (plasma|gnome)) ]]; then
1549 sed -i '/super/d' $MNT/home/$NEWUSER/.xprofile $MNT/root/.xprofile
1550 sed -i '/nitrogen/d' $MNT/home/$NEWUSER/.xprofile $MNT/root/.xprofile
1551 sed -i '/compton/d' $MNT/home/$NEWUSER/.xprofile $MNT/root/.xprofile
1560 if [[ $INSTALL_WMS ]]; then
1561 if [[ -e $MNT/home/$NEWUSER/.xinitrc ]] && grep -q 'exec' "$MNT/home/$NEWUSER/.xinitrc"; then
1562 sed -i "/exec/ c exec ${LOGIN_WM}" "$MNT/home/$NEWUSER/.xinitrc"
1563 elif [[ $INSTALL_WMS ]]; then
1564 printf "exec %s\n" "$LOGIN_WM" >> "$MNT/home/$NEWUSER/.xinitrc"
1566 printf "exec %s\n" "$LOGIN_WM" >> "$MNT/home/$NEWUSER/.xinitrc"
1568 elif [[ -e $MNT/home/$NEWUSER/.xinitrc ]]; then
1569 # no sessions available so remove the exec from ~/.xinitrc and return
1570 sed -i '/exec/d' "$MNT/home/$NEWUSER/.xinitrc"
1574 [[ ${EDIT_FILES[login]} == *"$LOGINRC"* ]] || EDIT_FILES[login]+=" /home/$NEWUSER/$LOGINRC"
1576 if [[ $AUTOLOGIN ]]; then
1577 sed -i "s/root/${NEWUSER}/g" $SERVICE/autologin.conf
1578 cat > "$MNT/home/$NEWUSER/$LOGINRC" <<- EOF
1580 # sourced by ${MYSHELL##*/} when used as a login shell
1582 # automatically run startx when logging in on tty1
1583 [ -z \$DISPLAY ] && [ \$XDG_VTNR -eq 1 ] && exec startx
1592 rm -rf "$SERVICE" "$MNT/home/$NEWUSER"/.{xinitrc,profile,zprofile,bash_profile}
1593 chrun 'systemctl enable ly.service' 2>$ERR
1594 errshow 1 "systemctl enable ly.service"
1599 echo "Setting up $LOGIN_TYPE"
1600 SERVICE="$MNT/etc/systemd/system/getty@tty1.service.d"
1601 install_${LOGIN_TYPE:-xinit}
1606 rm -rf "$SERVICE" "$MNT/home/$NEWUSER"/.{xinitrc,profile,zprofile,bash_profile}
1607 chrun 'systemctl enable lightdm.service' 2>$ERR
1608 errshow 1 "systemctl enable lightdm.service"
1609 cat > $MNT/etc/lightdm/lightdm-gtk-greeter.conf <<- EOF
1610 # LightDM GTK+ Configuration
1613 default-user-image=/usr/share/icons/ArchLabs-Dark/64x64/places/distributor-logo-archlabs.png
1614 background=/usr/share/backgrounds/archlabs/archlabs.jpg
1615 theme-name=Adwaita-dark
1616 icon-theme-name=Adwaita
1617 font-name=DejaVu Sans Mono 11
1618 position=30%,end 50%,end
1625 local inpkg="$BASE_PKGS ${LOGIN_PKGS[$LOGIN_TYPE]} $PACKAGES $USER_PKGS "
1627 if pacman -Qsq 'archlabs-installer' >/dev/null 2>&1; then
1628 rmpkg+="archlabs-installer "
1629 elif [[ -e "$MNT/usr/bin/archlabs-installer" ]]; then
1630 rm -f "$MNT/usr/bin/archlabs-installer"
1633 # add extra packages chosen throughout the install
1634 if [[ $MYSHELL == '/usr/bin/zsh' ]]; then
1635 inpkg+="zsh-completions "
1638 [[ $MYSHELL == '/usr/bin/mksh' ]] && inpkg+="mksh "
1640 if [[ $KERNEL != 'linux' ]]; then
1645 # gnome, plasma, and cinnamon have their own superkey bind and ksuperkey conflicts
1646 [[ $INSTALL_WMS =~ ^(plasma|gnome|cinnamon)$ ]] || inpkg+="archlabs-ksuperkey "
1648 # window manager only packages
1649 [[ $INSTALL_WMS =~ (openbox|bspwm|i3-gaps|dwm|fluxbox) ]] && inpkg+="$WM_BASE_PKGS "
1651 # ensure a terminal gets installed if one wasn't chosen or a DE that installs one
1652 [[ $inpkg =~ (term|urxvt|tilix|alacritty|sakura|tilda|plasma|cinnamon) || $INSTALL_WMS == *dwm* ]] || inpkg+="xterm "
1654 # update first to avoid issues
1655 chrun "pacman -Syyu --noconfirm"
1657 # remove the packages we don't want on the installed system
1658 [[ $rmpkg ]] && chrun "pacman -Rns $rmpkg --noconfirm"
1660 # reinstalling iputils fixes the network issue for non-root users
1661 chrun "pacman -S iputils $UCODE --noconfirm"
1663 # install the packages chosen throughout the install
1664 chrun "pacman -S $inpkg --needed --noconfirm" 2>$ERR
1665 errshow 1 "pacman -S $inpkg --needed --noconfirm"
1667 # bootloader packages
1668 if [[ $BOOTLDR == 'grub' ]]; then
1669 [[ $SYS == 'UEFI' ]] && local efib="efibootmgr"
1670 chrun "pacman -S os-prober grub $efib --needed --noconfirm" 2>$ERR
1671 errshow 1 "pacman -S os-prober grub $efib --needed --noconfirm"
1672 elif [[ $BOOTLDR == 'refind-efi' ]]; then
1673 chrun "pacman -S refind-efi efibootmgr --needed --noconfirm" 2>$ERR
1674 errshow 1 "pacman -S refind-efi efibootmgr --needed --noconfirm"
1675 elif [[ $SYS == 'UEFI' ]]; then
1676 chrun "pacman -S efibootmgr --needed --noconfirm" 2>$ERR
1677 errshow 1 "pacman -S efibootmgr --needed --noconfirm"
1680 # allow members of the wheel group to run commands as root
1681 sed -i "s/# %wheel ALL=(ALL) ALL/%wheel ALL=(ALL) ALL/g" $MNT/etc/sudoers
1688 mkdir -pv "$MNT/home/$NEWUSER/suckless"
1690 for i in dwm dmenu st; do
1691 if chrun "git clone https://git.suckless.org/$i /home/$NEWUSER/suckless/$i"; then
1692 chrun "cd /home/$NEWUSER/suckless/$i; make PREFIX=/usr install; make clean; rm config.h"
1694 printf "failed to clone %s repo\n" "$i"
1698 if [[ -x $MNT/usr/bin/dwm ]]; then
1699 printf "To configure dwm edit %s\n" "/home/$NEWUSER/suckless/dwm/config.h"
1700 printf "You can then recompile it with 'sudo make clean install'\n"
1705 install_mkinitcpio()
1709 # luks keyfile creation
1710 # currently not used due to not prompting for passphrase on startup
1711 # [[ $LUKS_UUID && $LUKS_PASS && $SYS == 'UEFI' && $BOOTLDR == 'grub' ]] && luks_keyfile
1713 [[ $LUKS ]] && add="encrypt"
1714 [[ $LVM ]] && { [[ $add ]] && add+=" lvm2" || add+="lvm2"; }
1715 sed -i "s/block filesystems/block ${add} filesystems ${HOOKS}/g" $MNT/etc/mkinitcpio.conf
1716 chrun "mkinitcpio -p $KERNEL" 2>$ERR
1717 errshow 1 "mkinitcpio -p $KERNEL"
1720 install_mirrorlist()
1722 local mfile="$1" # output mirrorlist file
1724 if hash reflector >/dev/null 2>&1; then
1725 reflector --verbose --score 80 -l 40 -f 5 --sort rate --save "$mfile"
1726 elif hash rankmirrors >/dev/null 2>&1; then
1727 echo "Sorting mirrorlist"
1728 local key="access_key=5f29642060ab983b31fdf4c2935d8c56"
1729 ip_add="$(curl -fsSL "http://api.ipstack.com/check&?$key&fields=ip" | python -c "import sys, json; print(json.load(sys.stdin)['ip'])")"
1730 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'])")"
1731 if [[ "$country" ]]; then
1732 if [[ $country =~ (CA|US) ]]; then
1733 # use both CA and US mirrors for CA or US countries
1734 mirror="https://www.archlinux.org/mirrorlist/?country=US&country=CA&use_mirror_status=on"
1735 elif [[ $country =~ (AU|NZ) ]]; then
1736 # use both AU and NZ mirrors for AU or NZ countries
1737 mirror="https://www.archlinux.org/mirrorlist/?country=AU&country=NZ&use_mirror_status=on"
1739 mirror="https://www.archlinux.org/mirrorlist/?country=${country}&use_mirror_status=on"
1741 else # no country code so just grab all mirrors, will be a very slow sort but we don't have other options
1742 mirror="https://www.archlinux.org/mirrorlist/?country=all&use_mirror_status=on"
1744 curl -fsSL "$mirror" | sed -e 's/^#Server/Server/' -e '/^#/d' | rankmirrors -n 6 - >"$mfile"
1750 install_background()
1752 yesno "Background Install" "\nBegin install in the background?\n" || return 0
1754 rsync -a /run/archiso/sfs/airootfs/ $MNT/ &
1757 mkdir -p $MNT/var/lib/pacman # can help with pacman errors
1758 ( install_mirrorlist "$MNT/etc/pacman.d/mirrorlist" >/dev/null 2>&1 && sleep 1 && chrun "pacman -Syyu $BASE_PKGS --needed --noconfirm" >> /tmp/bg_out 2>&1 ) &
1761 # end the background processes before exiting
1762 trap "kill $RSYNC_PID $MIRROR_PID 2>/dev/null" EXIT
1765 ###############################################################################
1767 # prerun_* set up the configs needed before actually running the commands
1768 # setup_* are run after selecting a bootloader and build the command used later
1769 # they can also be used for further user input as these run before control is taken away
1773 EDIT_FILES[bootloader]="/etc/default/grub"
1775 if [[ $SYS == 'BIOS' ]]; then
1776 [[ $BOOT_DEV ]] || { part_device 1 || return 1; }
1777 BCMDS[grub]="grub-install --recheck --force --target=i386-pc $BOOT_DEV"
1779 # since we're not using the keyfile this is dead code
1780 # if [[ $ROOT_PART == */dev/mapper/* && -z $LVM && -z $LUKS_PASS ]]; then
1781 # luks_pass "$_luksopen" 1 || return 1
1783 BCMDS[grub]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1784 grub-install --recheck --force --target=x86_64-efi --efi-directory=/$BOOTDIR --bootloader-id=$DIST"
1785 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1788 BCMDS[grub]="mkdir -p /run/udev /run/lvm &&
1789 mount --bind /hostrun/udev /run/udev &&
1790 mount --bind /hostrun/lvm /run/lvm &&
1792 grub-mkconfig -o /boot/grub/grub.cfg &&
1793 sleep 1 && umount /run/udev /run/lvm"
1800 sed -i "s/GRUB_DISTRIBUTOR=.*/GRUB_DISTRIBUTOR=\"${DIST}\"/g; s/GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT=\"\"/g" $MNT/etc/default/grub
1802 if [[ $LUKS_DEV ]]; then
1803 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
1804 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"
1807 if [[ $SYS == 'BIOS' && $LVM && -z $SEP_BOOT ]]; then
1808 sed -i "s/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g" $MNT/etc/default/grub 2>$ERR
1809 errshow 1 "sed -i 's/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g' $MNT/etc/default/grub"
1812 # setup for os-prober module
1813 mkdir -p /run/{lvm,udev} $MNT/hostrun/{lvm,udev}
1814 mount --bind /run/lvm $MNT/hostrun/lvm
1815 mount --bind /run/udev $MNT/hostrun/udev
1822 EDIT_FILES[bootloader]=""
1827 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1828 efibootmgr -v -d $BOOT_DEV -p $BOOT_PART_NUM -c -L '${DIST} Linux' -l /vmlinuz-${KERNEL} \
1829 -u 'root=$ROOT_PART_ID rw $([[ $UCODE ]] && printf 'initrd=\%s.img ' "$UCODE")initrd=\initramfs-${KERNEL}.img'"
1834 if [[ $SYS == 'BIOS' ]]; then
1835 EDIT_FILES[bootloader]="/boot/syslinux/syslinux.cfg"
1837 EDIT_FILES[bootloader]="/boot/EFI/syslinux/syslinux.cfg"
1838 BCMDS[syslinux]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1839 efibootmgr -v -c -d $BOOT_DEV -p $BOOT_PART_NUM -l /EFI/syslinux/syslinux.efi -L $DIST"
1845 local c="$MNT/boot/syslinux" s="/usr/lib/syslinux/bios" d=".."
1846 [[ $SYS == 'UEFI' ]] && { c="$MNT/boot/EFI/syslinux"; s="/usr/lib/syslinux/efi64/"; d=''; }
1848 mkdir -pv "$c" && cp -rfv $s/* "$c/" && cp -f "$RUN/syslinux/splash.png" "$c/"
1849 cat > "$c/syslinux.cfg" <<- EOF
1851 MENU TITLE $DIST Boot Menu
1852 MENU BACKGROUND splash.png
1856 # see: https://www.syslinux.org/wiki/index.php/Comboot/menu.c32
1865 MENU HELPMSGENDROW 29
1866 MENU COLOR border 30;44 #40ffffff #a0000000 std
1867 MENU COLOR title 1;36;44 #9033ccff #a0000000 std
1868 MENU COLOR sel 7;37;40 #e0ffffff #20ffffff all
1869 MENU COLOR unsel 37;44 #50ffffff #a0000000 std
1870 MENU COLOR help 37;40 #c0ffffff #a0000000 std
1871 MENU COLOR timeout_msg 37;40 #80ffffff #00000000 std
1872 MENU COLOR timeout 1;37;40 #c0ffffff #00000000 std
1873 MENU COLOR msg07 37;40 #90ffffff #a0000000 std
1874 MENU COLOR tabmsg 31;40 #30ffffff #00000000 std
1877 MENU LABEL $DIST Linux
1878 LINUX $d/vmlinuz-$KERNEL
1879 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1880 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL.img
1882 LABEL ${DIST}fallback
1883 MENU LABEL $DIST Linux Fallback
1884 LINUX $d/vmlinuz-$KERNEL
1885 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1886 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL-fallback.img
1893 EDIT_FILES[bootloader]="/boot/refind_linux.conf"
1894 BCMDS[refind-efi]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1900 cat > $MNT/boot/refind_linux.conf <<- EOF
1901 "$DIST Linux" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] &&
1902 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1903 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL.img"
1904 "$DIST Linux Fallback" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] &&
1905 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1906 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL-fallback.img"
1908 mkdir -p $MNT/etc/pacman.d/hooks
1909 cat > $MNT/etc/pacman.d/hooks/refind.hook <<- EOF
1916 Description = Updating rEFInd on ESP
1917 When = PostTransaction
1918 Exec = /usr/bin/refind-install
1922 setup_systemd-boot()
1924 EDIT_FILES[bootloader]="/boot/loader/entries/$DIST.conf"
1925 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1926 bootctl --path=/boot install"
1929 prerun_systemd-boot()
1931 mkdir -p $MNT/boot/loader/entries
1932 cat > $MNT/boot/loader/loader.conf <<- EOF
1937 cat > $MNT/boot/loader/entries/$DIST.conf <<- EOF
1939 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1940 initrd /initramfs-$KERNEL.img
1941 options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1943 cat > $MNT/boot/loader/entries/$DIST-fallback.conf <<- EOF
1944 title $DIST Linux Fallback
1945 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1946 initrd /initramfs-$KERNEL-fallback.img
1947 options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1949 mkdir -p $MNT/etc/pacman.d/hooks
1950 cat > $MNT/etc/pacman.d/hooks/systemd-boot.hook <<- EOF
1957 Description = Updating systemd-boot
1958 When = PostTransaction
1959 Exec = /usr/bin/bootctl update
1961 systemd-machine-id-setup --root="$MNT"
1965 ###############################################################################
1970 is_bg_install || return 1
1973 dlg choice menu "Logical Volume Management" "$_lvmmenu" \
1974 "$_lvmnew" "vgcreate -f, lvcreate -L -n" \
1975 "$_lvmdel" "vgremove -f" \
1976 "$_lvmdelall" "lvrmeove, vgremove, pvremove -f" \
1977 "back" "return to the main menu"
1980 "$_lvmnew") lvm_create || return 1 ;;
1981 "$_lvmdel") lvm_delgroup && yesno "$_lvmdel" "$_lvmdelask" && vgremove -f "$DEL_VG" >/dev/null 2>&1 ;;
1982 "$_lvmdelall") lvm_del_all ;;
1991 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
1992 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
1993 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
1995 if [[ $VGROUP && $v && $pv ]]; then
1996 msg "Logical Volume Management" "\nActivating existing logical volume management (LVM).\n\n" 1
1997 modprobe dm-mod >/dev/null 2>$ERR
1998 errshow 'modprobe dm-mod'
1999 vgscan >/dev/null 2>&1
2000 vgchange -ay >/dev/null 2>&1
2006 VGROUP='' LVM_PARTS='' VGROUP_MB=0
2008 lvm_mkgroup || return 1
2009 local txt="\nThe last (or only) logical volume will automatically use all remaining space in the volume group."
2010 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
2011 [[ $VOL_COUNT ]] || return 1
2012 lvm_extra_lvs || return 1
2013 lvm_volume_name "$_lvmlvname\nNOTE: This LV will use up all remaining space in the volume group (${VGROUP_MB}MB)" || return 1
2014 lvcreate -l +100%FREE "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
2015 errshow "lvcreate -l +100%FREE $VGROUP -n $VNAME" || return 1
2016 LVM='logical volume'; sleep 0.5
2017 txt="\nDone, volume: $VGROUP-$VNAME (${VOLUME_SIZE:-${VGROUP_MB}MB}) has been created.\n"
2018 msg "$_lvmnew (LV:$VOL_COUNT)" "$txt\n$(lsblk -o NAME,MODEL,TYPE,FSTYPE,SIZE $LVM_PARTS)\n"
2024 local txt="${VGROUP}: ${SIZE}$SIZE_UNIT (${VGROUP_MB}MB remaining).$_lvmlvsize"
2028 dlg VOLUME_SIZE input "$_lvmnew (LV:$VOL_COUNT)" "$txt" ''
2029 if [[ -z $VOLUME_SIZE ]]; then
2031 break # allow bailing with escape or an empty choice
2032 elif (( ${VOLUME_SIZE:0:1} == 0 )); then
2033 ERR_SIZE=1 # size values can't begin with '0'
2035 # walk the string and make sure all but the last char are digits
2036 local lv=$((${#VOLUME_SIZE} - 1))
2037 for (( i=0; i<lv; i++ )); do
2038 [[ ${VOLUME_SIZE:$i:1} =~ [0-9] ]] || { ERR_SIZE=1; break; }
2040 if (( ERR_SIZE != 1 )); then
2041 case ${VOLUME_SIZE:$lv:1} in
2042 [mMgG]) local s=${VOLUME_SIZE:0:$lv} m=$((s * 1000))
2043 case ${VOLUME_SIZE:$lv:1} in
2044 [Gg]) (( m >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - m)) ;;
2045 [Mm]) (( ${VOLUME_SIZE:0:$lv} >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - s)) ;;
2052 if (( ERR_SIZE )); then
2053 msg "Invalid Logical Volume Size" "$_lvmerrlvsize"
2065 local txt="\nConfirm creation of volume group: $VGROUP\n\nwith the following partition(s):"
2067 until [[ $named ]]; do
2068 lvm_partitions || return 1
2069 lvm_group_name || return 1
2070 yesno "$_lvmnew" "$txt $LVM_PARTS\n" && named=true
2073 vgcreate -f "$VGROUP" $LVM_PARTS >/dev/null 2>$ERR
2074 errshow "vgcreate -f $VGROUP $LVM_PARTS" || return 1
2076 SIZE=$(vgdisplay "$VGROUP" | awk '/VG Size/ { gsub(/[^0-9.]/, ""); print int($0) }')
2077 SIZE_UNIT="$(vgdisplay "$VGROUP" | awk '/VG Size/ { print substr($NF, 0, 1) }')"
2079 if [[ $SIZE_UNIT == 'G' ]]; then
2080 VGROUP_MB=$((SIZE * 1000))
2085 msg "$_lvmnew" "\nVolume group: $VGROUP ($SIZE $SIZE_UNIT) has been created\n"
2092 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
2093 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
2094 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
2096 if [[ $VGROUP || $v || $pv ]]; then
2097 if yesno "$_lvmdelall" "$_lvmdelask"; then
2098 for i in $v; do lvremove -f "/dev/mapper/$i" >/dev/null 2>&1; done
2099 for i in $VGROUP; do vgremove -f "$i" >/dev/null 2>&1; done
2100 for i in $pv; do pvremove -f "$i" >/dev/null 2>&1; done
2104 msg "Delete LVM" "\nNo LVMs to remove...\n" 2
2114 for i in $(lvs --noheadings | awk '{print $2}' | uniq); do
2115 VOL_GROUP_LIST+="$i $(vgdisplay "$i" | awk '/VG Size/ {print $3$4}') "
2117 [[ $VOL_GROUP_LIST ]] || { msg "No Groups" "\nNo volume groups found."; return 1; }
2119 dlg DEL_VG menu "Logical Volume Management" "\nSelect volume group to delete.\n\nAll logical volumes within will also be deleted." $VOL_GROUP_LIST
2125 while (( VOL_COUNT > 1 )); do
2126 lvm_volume_name "$_lvmlvname" && get_lv_size || return 1
2127 lvcreate -L "$VOLUME_SIZE" "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
2128 errshow "lvcreate -L $VOLUME_SIZE $VGROUP -n $VNAME" || return 1
2129 msg "$_lvmnew (LV:$VOL_COUNT)" "\nDone, logical volume (LV) $VNAME ($VOLUME_SIZE) has been created.\n"
2137 part_find 'part|crypt' || return 1
2138 PARTS="$(awk 'NF > 0 {print $0 " off"}' <<< "$PARTS")"
2139 dlg LVM_PARTS check "$_lvmnew" "\nSelect the partition(s) to use for the physical volume (PV)." $PARTS
2146 until [[ $VGROUP ]]; do
2147 dlg VGROUP input "$_lvmnew" "$_lvmvgname" "mygroup"
2148 if [[ -z $VGROUP ]]; then
2150 elif [[ ${VGROUP:0:1} == "/" || $VGROUP =~ \ |\' ]] || lsblk | grep -q "$VGROUP"; then
2151 msg "LVM Name Error" "$_lvmerrvgname"
2161 local txt="$1" default="mainvolume"
2162 (( VOL_COUNT > 1 )) && default="extravolume$VOL_COUNT"
2163 until [[ $VNAME ]]; do
2164 dlg VNAME input "$_lvmnew (LV:$VOL_COUNT)" "\n$txt" "$default"
2165 if [[ -z $VNAME ]]; then
2167 elif [[ ${VNAME:0:1} == "/" || $VNAME =~ \ |\' ]] || lsblk | grep -q "$VNAME"; then
2168 msg "LVM Name Error" "$_lvmerlvname"
2175 ###############################################################################
2181 is_bg_install || return 1
2182 dlg choice menu "LUKS Encryption" "$_luksmenu" \
2183 "$_luksnew" "cryptsetup -q luksFormat" \
2184 "$_luksopen" "cryptsetup open --type luks" \
2185 "$_luksadv" "cryptsetup -q -s -c luksFormat" \
2186 "back" "Return to the main menu"
2189 "$_luksnew") luks_basic || return 1 ;;
2190 "$_luksopen") luks_open || return 1 ;;
2191 "$_luksadv") luks_advanced || return 1 ;;
2199 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
2201 part_find 'part|crypt|lvm' || return 1
2203 if (( COUNT == 1 )); then
2204 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2206 dlg LUKS_PART menu "$_luksopen" "\nSelect which partition to open." $PARTS
2209 [[ $LUKS_PART ]] || return 1
2211 luks_pass "$_luksopen" || return 1
2212 msg "$_luksopen" "\nOpening encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2213 cryptsetup open --type luks "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2214 errshow "cryptsetup open --type luks $LUKS_PART $LUKS_NAME" || return 1
2215 LUKS='encrypted'; luks_show
2222 local t="$1" op="$2" v='' p='' p2=''
2224 until [[ $LUKS_PASS ]]; do
2228 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " $t " \
2229 --mixedform "\nEnter the password to decrypt $ROOT_PART\n\nThis is needed to create a keyfile." 0 0 0 \
2230 "Password:" 1 1 '' 1 11 "$COLUMNS" 0 1 \
2231 "Password2:" 2 1 '' 2 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
2234 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " $t " --mixedform "$_luksomenu" 0 0 0 \
2235 "Name:" 1 1 "${LUKS_NAME:-cryptroot}" 1 7 "$COLUMNS" 0 0 \
2236 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
2237 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
2241 while read -r line; do
2257 if [[ -z $op && -z $n ]]; then
2258 msg "Name Empty" "\nEncrypted device name cannot be empty.\n\nPlease try again.\n" 2
2259 elif [[ -z $p || "$p" != "$p2" ]]; then
2260 [[ $op ]] || LUKS_NAME="$n"
2261 msg "Password Mismatch" "\nThe passwords entered do not match.\n\nPlease try again.\n" 2
2263 [[ $op ]] || LUKS_NAME="$n"
2274 msg "$_luksnew" "\nEncrypted partition opened and ready for mounting.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$LUKS_PART")\n\n"
2279 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
2281 part_find 'part|lvm' || return 1
2283 if [[ $AUTO_ROOT_PART ]]; then
2284 LUKS_PART="$AUTO_ROOT_PART"
2285 elif (( COUNT == 1 )); then
2286 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2288 dlg LUKS_PART menu "$_luksnew" "\nSelect the partition you want to encrypt." $PARTS
2291 [[ $LUKS_PART ]] || return 1
2292 luks_pass "$_luksnew"
2297 luks_setup || return 1
2298 msg "$_luksnew" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2299 cryptsetup -q luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2300 errshow "cryptsetup -q luksFormat $LUKS_PART" || return 1
2301 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2302 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2303 LUKS='encrypted'; luks_show
2309 if [[ ! -e $MNT/crypto_keyfile.bin ]]; then
2310 # printf "Creating LUKS keyfile /crypto_keyfile.bin\n"
2312 n="$(lsblk -lno NAME,UUID,TYPE | awk "/$LUKS_UUID/"' && /part|crypt|lvm/ {print $1}')"
2313 local mkkey="dd bs=512 count=8 if=/dev/urandom of=/crypto_keyfile.bin"
2314 mkkey="$mkkey && chmod 000 /crypto_keyfile.bin"
2315 mkkey="$mkkey && cryptsetup luksAddKey /dev/$n /crypto_keyfile.bin <<< '$LUKS_PASS'"
2317 sed -i 's/FILES=()/FILES=(\/crypto_keyfile.bin)/g' $MNT/etc/mkinitcpio.conf 2>$ERR
2327 dlg cipher input "LUKS Encryption" "$_lukskey" "-s 512 -c aes-xts-plain64"
2328 [[ $cipher ]] || return 1
2329 msg "$_luksadv" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2330 cryptsetup -q $cipher luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2331 errshow "cryptsetup -q $cipher luksFormat $LUKS_PART" || return 1
2332 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2333 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2340 ###############################################################################
2342 # some help avoid repetition and improve usability of some commands
2343 # others are initial setup functions used before reaching the main loop
2347 # does $2 contain $1
2348 [[ "$2" == *"$1"* ]] && printf "on" || printf "off"
2353 # cleanup and exit the installer cleanly with exit code $1
2354 # when ecode is 127 unmount /run/archiso/bootmnt and reboot
2359 if [[ -d $MNT ]] && command cd /; then
2361 if (( ecode == 127 )); then
2362 umount_dir /run/archiso/bootmnt
2373 local var="$1" # assign output from dialog to var
2374 local dlg_t="$2" # dialog type (menu, check, input)
2375 local title="$3" # dialog title
2376 local body="$4" # dialog message
2377 local n=0 # number of items to display
2379 shift 4 # shift off args assigned above
2381 # when passed a large amount of arguments (menu list) adjust menu height
2382 (( ($# / 2) > SHL )) && n=$SHL
2386 menu) dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --menu "$body" 0 0 $n "$@" 2>"$ANS" || return 1 ;;
2387 check) dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --checklist "$body" 0 0 $n "$@" 2>"$ANS" || return 1 ;;
2390 local def="$1" # assign default value for input
2392 if [[ $1 == 'limit' ]]; then
2393 dialog --backtitle "$DIST Installer - $SYS - v$VER" --max-input 63 --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2395 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2399 # if answer file isn't empty read from it into $var
2400 [[ -s "$ANS" ]] && printf -v "$var" "%s" "$(< "$ANS")"
2405 # displays a message dialog
2406 # when more than 2 args the message will disappear after sleep time ($3)
2412 dialog --backtitle "$DIST Installer - $SYS - v$VER" --sleep "$1" --title " $title " --infobox "$body\n" 0 0
2414 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --msgbox "$body\n" 0 0
2420 local title="$1" body="$2" yes='Yes' no='No'
2421 (( $# >= 3 )) && yes="$3"
2422 (( $# >= 4 )) && no="$4"
2424 if (( $# == 5 )); then
2425 dialog --backtitle "$DIST Installer - $SYS - v$VER" --defaultno --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2427 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2433 arch-chroot "$MNT" bash -c "$1"
2438 export PS4='| ${BASH_SOURCE} LINE:${LINENO} FUNC:${FUNCNAME[0]:+ ${FUNCNAME[0]}()} |> '
2447 printf "\n^C caught, cleaning up...\n"
2454 "\e]P0191919" # #191919
2455 "\e]P1D15355" # #D15355
2456 "\e]P2609960" # #609960
2457 "\e]P3FFCC66" # #FFCC66
2458 "\e]P4255A9B" # #255A9B
2459 "\e]P5AF86C8" # #AF86C8
2460 "\e]P62EC8D3" # #2EC8D3
2461 "\e]P7949494" # #949494
2462 "\e]P8191919" # #191919
2463 "\e]P9D15355" # #D15355
2464 "\e]PA609960" # #609960
2465 "\e]PBFF9157" # #FF9157
2466 "\e]PC4E88CF" # #4E88CF
2467 "\e]PDAF86C8" # #AF86C8
2468 "\e]PE2ec8d3" # #2ec8d3
2469 "\e]PFE1E1E1" # #E1E1E1
2472 [[ $TERM == 'linux' ]] && printf "%b" "${colors[@]}" && clear
2477 [ $? -eq 0 ] && return 0
2479 local fatal=0 err=""
2480 err="$(sed 's/[^[:print:]]//g; s/\[[0-9\;:]*\?m//g; s/==> //g; s/] ERROR:/]\nERROR:/g' "$ERR")"
2482 (( $1 == 1 )) && { fatal=1; shift; }
2484 local txt="\nThe command exited abnormally:\n\n$1\n\n"
2487 txt+="With the following message:\n\n$err\n\n"
2489 txt+="With no error message:\n\n"
2492 if (( fatal )); then
2493 txt+="Errors at this stage are fatal and the install cannot continue.\n"
2495 txt+="Errors at this stage are non-fatal and can be either fixed or ignored depending on the error.\n"
2497 msg "Install Error" "$txt"
2499 if (( fatal )); then
2500 [[ -r $DBG && $TERM == 'linux' ]] && less "$DBG"
2509 msg "Broadcom Wireless Setup" "\nDetected chipset is Broadcom BCM4352\n\nDisabling bcma/b43 modules and loading wl module.\n" 1
2510 { rmmod wl; rmmod bcma; rmmod b43; rmmod ssb; modprobe wl; depmod -a; } >/dev/null 2>&1
2518 if (( $1 >= 0 )) && ! grep -qw "$MNT" /proc/mounts; then
2519 msg "Not Mounted" "\nPartition(s) must be mounted first.\n" 2
2521 elif [[ $1 -ge 1 && -z $BOOTLDR ]]; then
2522 msg "No Bootloader" "\nBootloader must be selected first.\n" 2
2524 elif [[ $1 -ge 2 && (-z $NEWUSER || -z $USER_PASS) ]]; then
2525 msg "No User" "\nA user must be created first.\n" 2
2527 elif [[ $1 -ge 3 && -z $CONFIG_DONE ]]; then
2528 msg "Not Configured" "\nSystem configuration must be done first.\n" 2
2531 (( i )) # return code
2536 mount | grep -q 'swap' && swapoff -a
2538 [[ -d $dir && "$(mount | grep "on $dir ")" ]] || continue
2539 umount "$dir" 2>/dev/null || { sleep 0.5; umount -f "$dir" 2>/dev/null || umount -l "$dir"; }
2545 msg "Network Connect" "\nVerifying network connection\n" 1
2546 curl -sIN --connect-timeout 5 'https://www.archlinux.org/' | sed '1q' | grep -q '200'
2551 if chk_connect; then
2554 if hash nmtui >/dev/null 2>&1; then
2556 if [[ $TERM == 'linux' ]]; then
2557 printf "%b" "\e]P1191919" "\e]P4191919"
2559 printf "%b" "\e]P1D15355" "\e]P4255a9b"
2572 [[ $RSYNC_PID || $MIRROR_PID ]] || return 0
2573 msg "Install Running" "\nA background install process is currently running.\n" 2
2579 IGNORE_DEV="$(lsblk -lno NAME,MOUNTPOINT | awk '/\/run\/archiso\/bootmnt/ {sub(/[1-9]/, ""); print $1}')"
2581 if [[ $IGNORE_DEV ]]; then
2582 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ && !'"/$IGNORE_DEV/"' {print "/dev/" $1 " " $2}')"
2584 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ {print "/dev/" $1 " " $2}')"
2587 if [[ -z $SYS_DEVS ]]; then
2588 msg "Device Error" "\nNo available devices...\n\nExiting..\n" 2
2593 while read -r line; do
2595 done <<< "$SYS_DEVS"
2602 elif grep -q 'AuthenticAMD' /proc/cpuinfo; then
2604 elif grep -q 'GenuineIntel' /proc/cpuinfo; then
2608 modprobe -q efivarfs >/dev/null 2>&1
2610 _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."
2611 if [[ -d /sys/firmware/efi/efivars ]]; then
2613 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars
2614 _prep+="\n - An EFI boot partition mounted."
2618 _prep+="\n\nOnce finished mounting, a portion of the install can be done in the background while you continue configuring the system:\n"
2619 _prep+="\n - Choose the system bootloader.\n - Create a user and password."
2620 _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."
2623 ###############################################################################
2626 # enable some nicer colours in the linux console
2629 if (( UID != 0 )); then
2630 msg "Not Root" "\nThis installer must be run as root or using sudo.\n\nExiting..\n" 2
2632 elif ! grep -qwm 1 'lm' /proc/cpuinfo; then
2633 msg "Not x86_64 Architecture" "\nThis installer only supports x86_64 architectures.\n\nExiting..\n" 2
2635 elif [[ $1 =~ (-d|--debug) ]]; then
2639 # trap ^C to perform cleanup
2645 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"
2647 select_keymap || { clear; die 0; }
2649 # try to fix problematic broadcom wireless chipset before network check
2650 lspci -vnn -d 14e4: | grep -q 'BCM4352' && load_bcm
2652 net_connect || { msg "Not Connected" "\nThis installer requires an active internet connection.\n\nExiting..\n" 2; die 1; }
2658 # vim:fdm=marker:fmr={,}