From 3d65438b2801823dca3d633c7176f0e3f2d741bf Mon Sep 17 00:00:00 2001 From: Blake Romero Date: Fri, 20 Sep 2024 11:34:57 +0100 Subject: Move config into separate file & rename install script --- install.sh | 414 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 414 insertions(+) create mode 100644 install.sh (limited to 'install.sh') diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..4eadbdf --- /dev/null +++ b/install.sh @@ -0,0 +1,414 @@ +#!/bin/bash +# ====================================================== +# Artix Linux Installation +# See the README for details +# ====================================================== + +# FIXME: fix encryption setup +# TODO: add BIOS support +# TODO: add pacman repository options (https://wiki.artixlinux.org/Main/Repositories) + +source config + +# Ensure nothing mounted +swapoff -a &> /dev/null +cryptsetup close Artix &> /dev/null +umount -R /mnt &> /dev/null + +# Init shell environment +set -e + +# Checks +if [[ ! -d /sys/firmware/efi/efivars ]]; then + echo "Only UEFI systems are currently supported" + exit +fi +if [[ "${drive}" == "/dev/DRIVE" ]]; then + echo "You forgot to set the DRIVE option!" + exit +fi + +echo "Checking for internet connection..." +ping -c 3 artixlinux.org &> /dev/null \ + || { echo "No internet connection found"; exit; } + +# Sync clock +dinitctl start ntpd + +# Read password +echo "Enter a password for ${user} (also used for encryption if enabled)" +while true; do + read -sr -p "Password: " password + printf "\n" + read -sr -p "Confirm password: " password2 + printf "\n" + [[ "${password}" == "${password2}" ]] && break + echo "Incorrect password!"; + read -rp "Press ENTER to try again..."; +done + +# Get system RAM size +pacman --needed --noconfirm -Sy bc +ram_kB=$(awk 'FNR==1 {print $2}' /proc/meminfo) +ram_gb=$(bc <<< "${ram_kB} / 1000^2") + +# Check there is at least 1GB RAM for swap +if [[ "${ram_gb}" -lt 1 ]]; then + echo "Not enough ram for SWAP" + exit +fi + +# Calculate SWAP size +if [[ "${swap_size}" == auto ]]; then + swap_size="$(bc <<< "sqrt(${ram_gb}) * 4")G" +fi + +# Get boot size if using an already created partition +# (note: only used for prompt confirmation) +if [[ $duel_boot == true ]]; then + boot_bytes=$(blockdev --getsize64 "${boot}") + boot_size="$(bc <<< "${boot_bytes} / 1000000000")G" +fi + +# Request confirmation +drive_bytes=$(blockdev --getsize64 "${drive}") +drive_size="$(bc <<< "${drive_bytes} / 1000000000")G" + +# Get a list of options +[[ $encrypt == true ]] && options+="encrypt " +[[ $arch_support == true ]] && options+="arch_support " +[[ $enable_aur == true ]] && options+="enable_aur " +[[ $autologin == true ]] && options+="autologin " +[[ $duel_boot == true ]] && options+="duel_boot " + +echo " +================ CONFIRM INSTALLATION ================ +Drive: ${drive} (size: ${drive_size}) +BOOT Partition: ${boot}, Size: ${boot_size} +ROOT Partition: ${root}, Size: MAX +SWAP Size: ${swap_size} +------------------------------------------------------" +if [[ $options != "" ]]; then + echo "Options: ${options} +------------------------------------------------------" +fi +echo "CAUTION: ALL data from ${drive} will be erased !!! +------------------------------------------------------" +if [[ $duel_boot == true ]]; then + echo "Note: GRUB will be installed into ${boot}." +fi + +echo "Are you sure you want install?" +unset input +read -rp "Type YES (in uppercase letters) to begin installation: " input +[[ "${input}" != "YES" ]] && exit + +# Wipe file-system +wipefs -a "${drive}" + +# Create partitions +if [[ $duel_boot == true ]]; then + # create root partition + printf ',+,L\n' \ + | sfdisk -qf -X gpt ${drive} +else + # create UEFI boot & root partition + printf ',%s,U,*\n,+,L\n' "${boot_size}" \ + | sfdisk -qf -X gpt ${drive} +fi + +# Encryption setup +if [[ $encrypt == true ]]; then + # Create encrypted drive + echo "${password}" | cryptsetup --type luks2 \ + --label LUKS \ + --cipher aes-xts-plain64 \ + --hash sha512 \ + --use-random \ + luksFormat "${root}" + + # Open encrypted drive + echo "${password}" | cryptsetup luksOpen ${root} Artix + + # Change root to mapper + root="/dev/mapper/Artix" +fi + +# Make BOOT filesystem +if [[ $duel_boot == false ]]; then + mkfs.fat -n BOOT -F 32 "${boot}" +fi + +# Make BTRFS ROOT filesystem +mkfs.btrfs -qfL ROOT "${root}" + +# Mount btrfs ROOT drive +mount "${root}" /mnt + +# Create BTRFS subvolumes +btrfs -q subvolume create /mnt/@ +btrfs -q subvolume create /mnt/@home +btrfs -q subvolume create /mnt/@tmp +btrfs -q subvolume create /mnt/@var +btrfs -q subvolume create /mnt/@snapshots +btrfs -q subvolume create /mnt/@swap + +# Mount BTRFS subvolumes +umount /mnt +options="noatime,compress=zstd" +mount -o "${options},subvol=@" "${root}" /mnt +mkdir /mnt/{boot,home,tmp,var,.snapshots,.swap} +mount -o "${options},subvol=@home" "${root}" /mnt/home +mount -o "${options},subvol=@tmp" "${root}" /mnt/tmp +mount -o "${options},subvol=@var" "${root}" /mnt/var +mount -o "${options},subvol=@snapshots" "${root}" /mnt/.snapshots \ + && chmod 750 /mnt/.snapshots +mount -o "nodatacow,subvol=@swap" "${root}" /mnt/.swap + +# Create swap file +# btrfs filesystem mkswapfile \ +# --size "$swap_size" \ +# --uuid clear \ +# /mnt/.swap/swapfile +# btrfs property set /mnt/.swap compression none +# swapon /mnt/.swap/swapfile + +# SWAP FILE +swapfile=/mnt/.swap/swapfile +# create an empty file +truncate -s 0 $swapfile +# set to copy-on-write +chattr +Cm $swapfile +# preallocate file size to swap size +fallocate -l "$swap_size" $swapfile +# restrict access to swap file +chmod 0600 $swapfile +# initialise the swap file (note: LABEL is required for bootloader) +mkswap -L SWAP $swapfile +# ensure compression is disabled +btrfs property set /mnt/.swap compression none +swapon $swapfile + +# Mount boot partition. +mount "${boot}" /mnt/boot + +# Sync packages +pacman -Syy + +# Install base packages +basestrap /mnt \ + base base-devel booster artools-base\ + dinit seatd-dinit \ + turnstile-dinit pambase + +# Install Linux & utilities +basestrap /mnt \ + linux linux-firmware \ + grub efibootmgr os-prober \ + btrfs-progs \ + git vim man-{db,pages} + +# Get CPU type for microcode +ucode=amd-ucode +if [[ $(grep "vendor_id" /proc/cpuinfo) == *Intel* ]]; then + ucode=intel-ucode +fi +basestrap /mnt "${ucode}" --overwrite "/mnt/boot/${ucode}.img" + +# Install crypt service +if [[ "${encrypt}" == true ]]; then + basestrap /mnt cryptsetup-dinit +fi + +basestrap /mnt --needed \ + {iwd,dhcpcd,openntpd,cronie,openssh,ufw,dbus,seatd}-dinit + +# Enable services +services="dbus ufw iwd dhcpcd ntpd cronie turnstiled seatd" +# NOTE: do not quote 'services' variable or space is ignored +for service in ${services}; do + artix-chroot /mnt bash -c \ + "ln -s /etc/dinit.d/$service /etc/dinit.d/boot.d/" +done + +# Generate file-system table +fstabgen -L /mnt >> /mnt/etc/fstab + +# Set swappiness levels +[ -d /mnt/etc/sysctl.d/ ] || mkdir -p /mnt/etc/sysctl.d/ +echo vm.swappiness=10 > /mnt/etc/sysctl.d/99-swappiness.conf + +# SETUP SYSTEM +# Set locale +echo "${locale}.UTF-8 UTF-8 +${locale} ISO-8859-1" >> /mnt/etc/locale.gen +echo "LANG=${locale}.UTF-8 +export LC_COLLATE=C" > /mnt/etc/locale.conf +artix-chroot /mnt bash -c "locale-gen" + +# Set timezone +artix-chroot /mnt bash -c \ + "ln -sf /usr/share/zoneinfo/${timezone} /etc/localtime" +artix-chroot /mnt bash -c "hwclock -w" + +# Set default text editor +echo "export EDITOR=vim" >> /mnt/etc/profile + +# Set hostname +echo "${hostname}" > /mnt/etc/hostname + +# Set root password +artix-chroot /mnt bash -c "echo root:artix | chpasswd" + +# Add new user +artix-chroot /mnt bash -c "useradd -mG ${user_groups} ${user}" +artix-chroot /mnt bash -c "echo \"${user}:${password}\" | chpasswd" + +# Set user privileges +echo " +Cmnd_Alias STAT = /usr/bin/ufw status +Cmnd_Alias PACMAN = /usr/bin/checkupdates +Cmnd_Alias REBOOT = /bin/halt,/bin/reboot +Defaults pwfeedback +%wheel ALL=(ALL) ALL +${user} ALL=(ALL) NOPASSWD: PACMAN,REBOOT,STAT +" >> /mnt/etc/sudoers + +# Add user to autologin (note: password must match decryption password) +if [[ "${autologin}" == true ]]; then + cp /mnt/etc/dinit.d/config/agetty-default.conf \ + /mnt/etc/dinit.d/config/agetty-tty1.conf + sed "s/GETTY_ARGS=.*/GETTY_ARGS=\"--noclear --autologin ${user}\"/" \ + -i /mnt/etc/dinit.d/config/agetty-tty1.conf +fi + +# Setup user dinit log directory +mkdir /mnt/var/log/dinit/user +chgrp log /mnt/var/log/dinit/user +chmod g+rw /mnt/var/log/dinit/user + +# Add PACMAN download style +pac_options=ILoveCandy +sed "s/# Misc options/# Misc options\n${pac_options}/g" \ + -i /mnt/etc/pacman.conf + +# Enable firewall +sed "s/ENABLED=no/ENABLED=yes/" -i /mnt/etc/ufw/ufw.conf + +# Enable turnstile rundir +sed "s/manage_rundir = no/manage_rundir = yes/" -i /mnt/etc/turnstile/turnstiled.conf + +# Set MAKEFLAGS to match CPU threads for faster compiling +cp /etc/makepkg.conf /etc/makepkg.conf.bak +sed "s/#MAKEFLAGS=\".*\"/MAKEFLAGS=\"-j$(nproc)\"/" \ + -i /mnt/etc/makepkg.conf + +# Configure booster +echo "compress: zstd -9 -T0 +modules: btrfs" > /mnt/etc/booster.yaml +artix-chroot /mnt bash -c "/usr/lib/booster/regenerate_images" +# Add to GRUB +echo " +# Add Booster as custom initrd +GRUB_EARLY_INITRD_LINUX_CUSTOM=booster-linux.img +" >> /mnt/etc/default/grub + +# SETUP BOOT LOADER +# -------------------------------------------------------------------- +# Add swap device +devices="resume=LABEL=SWAP" + +# BTRFS swap files requires an offset for hibernation to work +# https://man.archlinux.org/man/btrfs.5#HIBERNATION +offset=$(btrfs inspect-internal map-swapfile -r /mnt/.swap/swapfile) +devices+=" resume_offset=$offset" + +# Add crypt device if enabled +if [[ "${encrypt}" == true ]]; then + crypt_uuid=$(lsblk -f | grep "$(basename $root)" | awk '{print $4}') + devices+=" rd.luks.name=${crypt_uuid}=Artix" +fi + +# Set command options +grub_cmds="quiet loglevel=3 net.iframes=0 splash" + +# Replace default grub commands +sed "s/^GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT=\"$grub_cmds $devices\"/" \ + -i /mnt/etc/default/grub + +# Enable os-prober to detect other operating systems +if [[ $duel_boot == true ]]; then + echo "GRUB_DISABLE_OS_PROBER=false" >> /mnt/etc/default/grub +fi + +# Install grub bootloader +grub_options="--target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB" +artix-chroot /mnt bash -c "grub-install ${grub_options}" +artix-chroot /mnt bash -c "grub-mkconfig -o /boot/grub/grub.cfg" + +# Enable Arch repositories (extra, community & multilib) +# https://wiki.artixlinux.org/Main/Repositories +if [[ "${arch_support}" == true ]]; then + echo "Enabling Arch repositories..." + + # Package requirements + pacman --needed --noconfirm -Sy vim git \ + || { echo "Error installing packages"; exit; } + + # Download latest Arch mirrorlist + url="https://github.com/archlinux/svntogit-packages\ +/raw/packages/pacman-mirrorlist/trunk/mirrorlist" + curl -L "${url}" -o /mnt/etc/pacman.d/mirrorlist-arch \ + || { echo "Error downloading Arch mirrorlist"; exit; } + + # Set a region defined in 'mirrorlist-arch' + region="United Kingdom" + + # Ensure region exists + grep -qw "${region}" /mnt/etc/pacman.d/mirrorlist-arch \ + || { echo "Arch server location '${region}' not found."; exit; } + + # Uncomment local servers in Arch mirrorlist + vim -s <(printf "/%s\nvip:s/^#//g\n:wq\n" "${region}") \ + /mnt/etc/pacman.d/mirrorlist-arch &>/dev/null + + # Add Arch mirrorlist & servers to pacman + echo " +# Arch +[extra] +Include = /etc/pacman.d/mirrorlist-arch + +[multilib] +Include = /etc/pacman.d/mirrorlist-arch +" >> /mnt/etc/pacman.conf + + # Download Arch Linux support + artix-chroot /mnt bash -c \ + "pacman --noconfirm -Syy artix-archlinux-support" \ + || { echo "Error installing artix-archlinux-support"; exit; } + + # Update keys + artix-chroot /mnt bash -c "pacman-key --populate archlinux" + + echo "Arch support installation complete!" +fi + +# Install AUR helper +if [[ "${enable_aur}" == true ]]; then + artix-chroot /mnt bash -c "pacman --noconfirm -Syy trizen" \ + || { echo "Error installing trizen AUR helper"; exit; } + echo "AUR helper installation complete!" +fi + +# FINISH +swapoff -a +umount -R /mnt +[[ "${encrypt}" == true ]] && cryptsetup close Artix +set +x + +echo " +====================================================================== + Installation Finished +====================================================================== +" +echo "You can now reboot and log into system" -- cgit