#!/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 # Our local repository should have most of our packages: cat >> /etc/pacman.conf </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 \ blueman \ bluez \ bluez-tools \ bluez-utils \ bolt \ brltty \ broadcom-wl \ btop \ btrfs-progs \ chromium \ chrony \ clonezilla \ cloud-init \ cryptsetup \ darkhttpd \ ddrescue \ dhcpcd \ diffutils \ dmidecode \ dmraid \ dnsmasq \ dosfstools \ e2fsprogs \ edk2-shell \ efibootmgr \ entr \ espeakup \ ethtool \ 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 \ limine \ 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 \ network-manager-applet \ networkmanager \ nfs-utils \ nilfs-utils \ nload \ nm-connection-editor \ nmap \ noto-fonts-emoji \ ntfs-3g \ nvme-cli \ obs-studio \ open-iscsi \ open-vm-tools \ openbsd-netcat \ opencl-mesa \ openconnect \ openpgp-card-tools \ openssh \ openvpn \ partclone \ parted \ partimage \ pass \ pass-otp \ pavucontrol \ pcsclite \ pipewire \ pipewire-pulse \ ppp \ pptpclient \ 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 \ zstd \ yay \ brave-bin \ 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/udev/rules.d/99-hidraw.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 & Vulkan Drivers do_chroot pacman -S --needed \ intel-compute-runtime intel-media-driver libva-utils vulkan-intel vulkan-mesa-layers ;; *) 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 ln -sf \ /usr/lib/systemd/system/chronyd.service \ "${_install_path}"/etc/systemd/system/multi-user.target.wants/chronyd.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 is automatically setup, it seems, so this can be skipped # here for now, but if for some reason it isn not now you know what command to # run # snapper -c root create-config / limine-update limine-snapper-sync ' > "${_install_path}"/home/"${_username}"/setup.sh echo "${_green}Install complete!" echo "" echo "${_green}Make sure you run the 'setup.sh' script after first boot." echo "" echo "${_green}Rebooting!" sleep 15 reboot