#!/bin/sh set -e _red="$(printf "\033[1;31m")" _yellow="$(printf "\033[1;33m")" _green="$(printf "\033[1;32m")" _clear="$(printf "\033[0m")" _disk="${INSTALLATION_DISK:-}" _cryptname="${CRYPTDEVICE_NAME:-root}" _install_path="${INSTALL_PATH:-/mnt}" _mnt="${_install_path}" _tz="${TZ:-America/New_York}" _hostname="${INSTALL_HOSTNAME:-arch}" PACSTRAP="${PACSTRAP:-yes}" DISK_SETUP="${DISK_SETUP:-yes}" CONFIGURE="${CONFIGURE:-yes}" LOGIND="${LOGIND:-yes}" GRAPHICS="${GRAPHICS:-yes}" ping -c 3 8.8.4.4 >/dev/null 2>&1 || exec sh -c "echo No internet access. Please try again after connecting to the internet." if [ "$(id -u)" -ne 0 ] ; then echo "Run this script as root, i.e. with sudo" exit 1 fi # temporary Workaround for slow mirrors reflector | grep rit.edu > /etc/pacman.d/mirrorlist echo "############################################################" echo "INSTALL PROCESS" echo "############################################################" echo echo "We're going to keep this short and to the point" echo "First the overview, here's the process:" echo echo " * Select the disk to install to. Ideally, remove all disks you don't want touched" echo " * Set the encryption passphrase. ${_red}THERE IS NO RECOVERY IF YOU LOSE IT${_clear}" echo " * Reboot into your new system" echo echo echo "No alternative parition layouts are supported, no dual booting to the same drive." echo "If you want these things, feel free to install Arch by hand, you're on your own" echo echo if [ "$DISK_SETUP" = yes ]; then _disk= echo "Select a disk from the list:" if [ "$(lsblk -N | wc -l)" -gt 1 ] ; then echo "NVME:" lsblk -N | sed -re "s/^(nvme[^ ]*)/$_green\1$_clear/g" else printf '%s' "$_yellow" echo "Warning: No NVME drives found on this system." printf '%s' "$_clear" fi if [ "$(lsblk -S | wc -l)" -gt 1 ] ; then echo "SCSI:" lsblk -S | sed -re "s/^(sd[^ ]*)/$_green\1$_clear/g" fi if [ "$(lsblk -v | wc -l)" -gt 1 ] ; then echo "Virtio:" lsblk -v | sed -re "s/^(vio[^ ]*)/$_green\1$_clear/g" fi if [ "$(lsblk -S | wc -l)" -lt 2 ] && [ "$(lsblk -N | wc -l)" -lt 2 ] && [ "$(lsblk -v | wc -l)" -lt 2 ]; then printf '%s' "$_red" echo No suitable drives for installation found, exiting printf '%s' "$_clear" exit 1 fi while true ; do printf "Which disk to use for installation (green): " read -r _disk printf "%s" "Selected disk ${_yellow}$_disk${_clear} Are you sure you want to ${_red}delete everything${_clear}? (type \"YES\" in caps): $_clear" read -r resp case $resp in YES) break;; *) continue ;; esac done if [ -b "$_disk" ] ; then true elif [ -b "/dev/$_disk" ] ; then _disk="/dev/$_disk" else echo Neither "$_disk" or /dev/"$_disk" appear to be valid block devices, exiting exit 1 fi _part1="${_disk}1" _part2="${_disk}2" if echo "$_disk" | grep "nvme" ; then _part1="${_disk}p1" _part2="${_disk}p2" fi set -x wipefs -a "$_disk" sgdisk --zap-all "$_disk" sgdisk --hybrid "$_disk" sgdisk \ --new=1::+2G --typecode=1:ef00 \ --largest-new=2 --typecode=2:8e00 \ "$_disk" partprobe >/dev/null 2>&1 || echo "" mkfs.vfat -F 32 "$_part1" set +x echo "You will now enter your passphrase for ${_red}disk encryption${_clear}: " cryptsetup luksFormat "$_part2" _part2_uuid="$(blkid -o json "$_part2" | jq -r .uuid | tr -d '\n')" if [ -z "$_part2_uuid" ] ; then echo "${_red}Unable to find UUID for partition 3, bailing${_clear}" exit 1 fi echo "We're now going to unlock that disk with the same passhrase: " cryptsetup luksOpen "$_part2" "$_cryptname" set -x mkfs.btrfs /dev/mapper/"$_cryptname" mount /dev/mapper/"$_cryptname" "$_mnt" cd "$_mnt" btrfs sub create @ btrfs sub create @home btrfs sub create @log btrfs sub create @pkg cd - umount /dev/mapper/"$_cryptname" mount -o subvol=@,compress=zstd /dev/mapper/"$_cryptname" "$_mnt" mkdir -p "$_mnt"/home mount -o subvol=@home,compress=zstd /dev/mapper/"$_cryptname" "$_mnt"/home mkdir -p "$_mnt"/var/log mount -o subvol=@log,compress=zstd /dev/mapper/"$_cryptname" "$_mnt"/var/log mkdir -p "$_mnt"/var/cache/pacman/pkg mount -o subvol=@pkg /dev/mapper/"$_cryptname" "$_mnt"/var/cache/pacman/pkg mkdir -p "$_mnt"/boot mount "$_part1" "$_mnt"/boot set +x fi # DISK_SETUP do_edit() { printf "%s" "Edit \"$1\" ? : " read -r resp case $resp in Y|y) arch-chroot "${_install_path}" nvim "$1" ;; *) ;; esac } do_chroot() { if [ "$1" = "-u" ] ; then _u="$2"; shift; shift arch-chroot -u "$_u" "$_install_path" "$@" else arch-chroot "$_install_path" "$@" fi } set -x pacman-key --init pacman-key --populate set +x # TODO: all the same packages as the ISO if [ $PACSTRAP = yes ] ; then set -x pacstrap -K "$_install_path" \ alsa-utils \ amd-ucode \ arch-install-scripts \ archinstall \ archlinux-keyring \ b43-fwcutter \ base \ base-devel \ bcachefs-tools \ bind \ bluez \ bluez-tools \ bluez-utils \ blueman \ bolt \ brltty \ broadcom-wl \ btop \ btrfs-progs \ chromium \ clonezilla \ cloud-init \ cryptsetup \ darkhttpd \ ddrescue \ dhcpcd \ diffutils \ dmidecode \ dmraid \ dnsmasq \ dosfstools \ e2fsprogs \ edk2-shell \ efibootmgr \ espeakup \ ethtool \ exfat-utils \ exfatprogs \ f2fs-tools \ fastfetch \ fatresize \ foot-terminfo \ fsarchiver \ git \ git-lfs \ gpart \ gpm \ gptfdisk \ grml-zsh-config \ grub \ hdparm \ hyperv \ intel-ucode \ iperf3 \ irssi \ iw \ iwd \ jfsutils \ jq \ kitty-terminfo \ ldns \ less \ lftp \ libfido2 \ libusb-compat \ linux \ linux-atm \ linux-firmware \ linux-firmware-marvell \ livecd-sounds \ lsscsi \ lvm2 \ lynx \ man-db \ man-pages \ mc \ mdadm \ memtest86+ \ memtest86+-efi \ mkinitcpio \ mkinitcpio-archiso \ mkinitcpio-nfs-utils \ mmc-utils \ modemmanager \ mtools \ nano \ nbd \ ncdu \ ndisc6 \ neovim \ net-tools \ networkmanager \ network-manager-applet \ nfs-utils \ nilfs-utils \ nload \ nm-connection-editor \ nmap \ noto-fonts-emoji \ ntfs-3g \ nvme-cli \ open-iscsi \ open-vm-tools \ openbsd-netcat \ openconnect \ openpgp-card-tools \ openssh \ openvpn \ partclone \ parted \ partimage \ pass \ pass-otp \ pavucontrol \ pcsclite \ ppp \ pptpclient \ pulseaudio \ pv \ pwgen \ qemu-guest-agent \ refind \ reflector \ ripgrep \ rsync \ rxvt-unicode-terminfo \ screen \ scrot \ sddm \ sdparm \ seahorse \ sequoia-sq \ sg3_utils \ shellcheck \ smartmontools \ sof-firmware \ squashfs-tools \ sudo \ syslinux \ systemd-resolvconf \ tcpdump \ terminus-font \ testdisk \ tmux \ tpm2-tools \ tpm2-tss \ ttf-3270-nerd \ udftools \ usb_modeswitch \ usbmuxd \ usbutils \ vim \ virtualbox-guest-utils-nox \ vlc \ vpnc \ whois \ wireguard-tools \ wireless-regdb \ wireless_tools \ wpa_supplicant \ wvdial \ xclip \ xdg-utils \ xdotool \ xfce4 \ xfce4-goodies \ xfsprogs \ xl2tpd \ xorg-apps \ xorg-server \ xorg-xkill \ zsh \ opencl-mesa \ limine \ zstd set +x fi if [ "$CONFIGURE" = yes ] ; then set -x genfstab -U "$_install_path" > "${_install_path}/etc/fstab" # do_edit /etc/fstab # do_edit /etc/locale.gen sed -i -e '/^en_US.UTF-8 UTF-8$/d' "${_install_path}/etc/locale.gen" echo "en_US.UTF-8 UTF-8" >> "${_install_path}/etc/locale.gen" do_chroot locale-gen do_chroot ln -sf "/usr/share/zoneinfo/$_tz" /etc/localtime sed -i \ -e 's/^HOOKS=.*$/HOOKS=(base udev autodetect microcode modconf kms keyboard block keymap encrypt lvm2 consolefont filesystems fsck)/g' \ "${_install_path}/etc/mkinitcpio.conf" # do_edit /etc/mkinitcpio.conf do_chroot mkinitcpio -p linux # sed -i \ # -e 's/^GRUB_CMDLINE_LINUX_DEFAULT=.*$/GRUB_CMDLINE_LINUX_DEFAULT=""/' \ # "${_install_path}"/etc/default/grub # # sed -i \ # -e 's@^GRUB_CMDLINE_LINUX=.*$@GRUB_CMDLINE_LINUX="cryptdevice=UUID='"$_part2_uuid"':'"$_cryptname"'"@g' \ # "${_install_path}"/etc/default/grub # do_edit /etc/default/grub # Make this bootable directly as removable media # do_chroot grub-install --target=x86_64-efi --removable --efi-directory=/boot/efi # But also add an entry to the uEFI, and set it as default # do_chroot grub-install --target=x86_64-efi --efi-directory=/boot/efi # do_chroot grub-mkconfig -o /boot/grub/grub.cfg do_chroot mkdir -p /boot/EFI/BOOT do_chroot mkdir -p /boot/EFI/limine do_chroot cp /usr/share/limine/BOOTX64.EFI /boot/EFI/BOOT/BOOTX64.EFI do_chroot cp /usr/share/limine/BOOTX64.EFI /boot/EFI/limine/limine.efi efibootmgr --create --disk "$_disk" --part 1 --label "Arch Linux Limine Bootloader" \ --loader "\EFI\limine\limine.efi" \ --unicode # This one is just for first boot... cat > "$_install_path"/boot/limine.conf < "${_install_path}"/etc/hostname if [ "$LOGIND" = "yes" ] ; then fn="${_install_path}/etc/systemd/logind.conf" bak="$fn.$(date +%s)" cp "$fn" "$bak" sed -i -E -e 's/^.*KillUserProcesses=.*$/KillUserProcesses=yes/g' "$fn" sed -i -E -e 's/^.*HandleLidSwitch=.*$/HandleLidSwitch=ignore/g' "$fn" if diff -q "$fn" "$bak" >/dev/null ; then rm "$bak" fi fi cat > "${_install_path}"/etc/udev/rules.d/99-removable.rules < "${_install_path}"/etc/modprobe.d/v4l2loopback.conf < "${_install_path}"/etc/modules-load.d/v4l2loopback.conf </dev/null 2>&1 || makepkg -si cd - yay -S brave-bin snapper limine-snapper-sync limine-mkinitcpio-hook snap-pac # snapper -c root create-config / sudo systemctl enable limine-snapper-sync.service ' > "${_install_path}"/home/"${_username}"/setup.sh do_chroot chown "$_username" /home/"${_username}"/setup.sh do_chroot chmod +x /home/"${_username}"/setup.sh do_chroot pacman -Syy if [ "$GRAPHICS" = yes ] ; then case $(lspci | grep VGA) in *NVIDIA*) echo "Note older GPUs need 'nvidia' and/or 'nvidia-lts' instead of nvidia-open" do_chroot pacman -S --needed nvidia-open nvidia-open-lts nvidia-utils opencl-nvidia ;; *AMD*) # OpenCL Drivers echo "Note ROCM isn't supported by all AMD GPUs" do_chroot pacman -S --needed rocm-opencl-runtime ;; *Intel*) # OpenCL Drivers do_chroot pacman -S --needed intel-compute-runtime ;; *) echo "No GPU detected" esac fi mkdir -p "$_install_path"/etc/sddm.conf.d echo "[Autologin] User=${_username} Session=xfce" > "$_install_path"/etc/sddm.conf.d/autologin.conf echo 'Defaults!/usr/bin/visudo env_keep += "SUDO_EDITOR EDITOR VISUAL" Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/bin" root ALL=(ALL:ALL) ALL %wheel ALL=(ALL:ALL) NOPASSWD: ALL # %wheel ALL=(ALL:ALL) ALL @includedir /etc/sudoers.d' > "${_install_path}"/etc/sudoers ln -sf \ /usr/lib/systemd/system/sddm.service \ "${_install_path}"/etc/systemd/system/display-manager.service ln -sf \ /usr/lib/systemd/system/NetworkManager.service \ "${_install_path}"/etc/systemd/system/multi-user.target.wants/NetworkManager.service mkdir -p "${_install_path}"/etc/systemd/system/network-online.target.wants ln -sf \ /usr/lib/systemd/system/NetworkManager-wait-online.service \ "${_install_path}"/etc/systemd/system/network-online.target.wants/NetworkManager-wait-online.service ln -sf \ /usr/lib/systemd/system/bluetooth.service \ "${_install_path}"/etc/systemd/system/dbus-org.bluez.service mkdir -p "${_install_path}"/etc/systemd/system/bluetooth.target.wants ln -sf \ /usr/lib/systemd/system/bluetooth.service \ "${_install_path}"/etc/systemd/system/bluetooth.target.wants/bluetooth.service do_chroot -u "$_username" /bin/sh -c "export HOME=/home/'$_username'; /home/'$_username'/setup.sh" fi # CONFIGURE do_chroot cp /boot/limine.conf.old /boot/limine.conf echo '#!/bin/sh set -ex if [ "$(id -u)" -ne 0 ] ; then echo "Run this script as root, i.e. with sudo" exit 1 fi cp /boot/limine.conf /boot/limine.conf.install snapper -c root create-config / limine-update limine-snapper-sync ' > "${_install_path}"/home/"${_username}"/setup.sh echo "${_green}Install complete! Rebooting!" sleep 10 reboot