diff --git a/install.sh b/install.sh index 9558e1b..6489743 100644 --- a/install.sh +++ b/install.sh @@ -25,29 +25,30 @@ unpriv(){ } install_mode_selector() { - output "Is this a desktop or server installation?" - output "1) Desktop" - output "2) Server" - read -r -p "Select the installation type: " choice + output 'Is this a desktop or server installation?' + output '1) Desktop' + output '2) Server' + output 'Insert the number of your selection:' + read -r choice case $choice in 1 ) install_mode=desktop ;; 2 ) install_mode=server ;; - * ) output "You did not enter a valid selection." + * ) output 'You did not enter a valid selection.' install_mode_selector esac } # Selecting the kernel flavor to install. kernel_selector () { - output "List of kernels:" - output "1) Stable — Vanilla Linux kernel and modules, with a few patches applied." - output "2) Hardened — A security-focused Linux kernel." - output "3) Longterm — Long-term support (LTS) Linux kernel and modules." - output "4) Zen Kernel — Optimized for desktop usage." - read -r -p "Insert the number of the corresponding kernel:" choice - output "$choice will be installed" + output 'List of kernels:' + output '1) Stable — Vanilla Linux kernel and modules, with a few patches applied.' + output '2) Hardened — A security-focused Linux kernel.' + output '3) Longterm — Long-term support (LTS) Linux kernel and modules.' + output '4) Zen Kernel — Optimized for desktop usage.' + output 'Insert the number of your selection:' + read -r choice case $choice in 1 ) kernel=linux ;; @@ -57,67 +58,76 @@ kernel_selector () { ;; 4 ) kernel=linux-zen ;; - * ) output "You did not enter a valid selection." + * ) output 'You did not enter a valid selection.' kernel_selector esac } luks_password_prompt () { - output "Enter your encryption password (the password will not be shown on the screen):" + output 'Enter your encryption password (the password will not be shown on the screen):' read -r -s luks_password if [ -z "${luks_password}" ]; then - output "You need to enter a password." + output 'You need to enter a password.' luks_password_prompt fi - output "Confirm your encryption password (the password will not be shown on the screen):" + output 'Confirm your encryption password (the password will not be shown on the screen):' read -r -s luks_password2 if [ "${luks_password}" != "${luks_password2}" ]; then - output "Passwords don't match, please try again." + output 'Passwords do not match, please try again.' luks_password_prompt fi } disk_prompt (){ - output "Please select the number of the corresponding disk (e.g. 1):" + output 'Please select the number of the corresponding disk (e.g. 1):' select entry in $(lsblk -dpnoNAME|grep -P "/dev/sd|nvme|vd"); do disk="${entry}" - output "Arch Linux will be installed on the following disk: ${disk}" + output 'Arch Linux will be installed on the following disk: ${disk}' break done } username_prompt (){ - output "Enter your username:" + output 'Enter your username:' read -r username - if [ "${username}" = '' ]; then - output "You need to enter a password." + if [ -z "${username}" ]; then + output 'You need to enter a username.' username_prompt fi } user_password_prompt () { - output "Enter your user password (the password will not be shown on the screen):" + output 'Enter your user password (the password will not be shown on the screen):' read -r -s user_password if [ -z "${user_password}" ]; then - output "You need to enter a password." + output 'You need to enter a password.' user_password_prompt fi - output "Confirm your user password (the password will not be shown on the screen):" + output 'Confirm your user password (the password will not be shown on the screen):' read -r -s user_password2 if [ "${user_password}" != "${user_password2}" ]; then - output "Passwords don't match, please try again." + output 'Passwords do not match, please try again.' user_password_prompt fi } +hostname_prompt (){ + output 'Enter your username:' + read -r hostname + + if [ -z "${hostname}" ]; then + output 'You need to enter a hostname.' + hostname_prompt + fi +} + # Set hardcoded variables (temporary, these will be replaced by future prompts) -hostname=localhost locale=en_US kblayout=us @@ -131,6 +141,7 @@ luks_password_prompt disk_prompt username_prompt user_password_prompt +hostname_prompt # Check if this is a VM virtualization=$(systemd-detect-virt) @@ -155,30 +166,30 @@ parted -s "${disk}" \ set 1 esp on \ mkpart CRYPTROOT 513MiB 100% \ -ESP="/dev/disk/by-partlabel/ESP" -cryptroot="/dev/disk/by-partlabel/cryptroot" +ESP='/dev/disk/by-partlabel/ESP' +cryptroot='/dev/disk/by-partlabel/cryptroot' ## Informing the Kernel of the changes. -output "Informing the Kernel about the disk changes." +output 'Informing the Kernel about the disk changes.' partprobe "${disk}" ## Formatting the ESP as FAT32. -output "Formatting the EFI Partition as FAT32." +output 'Formatting the EFI Partition as FAT32.' mkfs.fat -F 32 -s 2 "${ESP}" &>/dev/null ## Creating a LUKS Container for the root partition. -output "Creating LUKS Container for the root partition." +output 'Creating LUKS Container for the root partition.' echo -n "${luks_password}" | cryptsetup luksFormat --type luks1 ${cryptroot} -d - &>/dev/null echo -n "${luks_password}" | cryptsetup open ${cryptroot} cryptroot -d - -BTRFS="/dev/mapper/cryptroot" +BTRFS='/dev/mapper/cryptroot' ## Formatting the LUKS Container as BTRFS. -output "Formatting the LUKS container as BTRFS." +output 'Formatting the LUKS container as BTRFS.' mkfs.btrfs "${BTRFS}" &>/dev/null mount "${BTRFS}" /mnt ## Creating BTRFS subvolumes. -output "Creating BTRFS subvolumes." +output 'Creating BTRFS subvolumes.' btrfs su cr /mnt/@ &>/dev/null btrfs su cr /mnt/@/.snapshots &>/dev/null @@ -234,7 +245,7 @@ chmod 600 /mnt/@/.snapshots/1/info.xml ## Mounting the newly created subvolumes. umount /mnt -echo "Mounting the newly created subvolumes." +output 'Mounting the newly created subvolumes.' mount -o ssd,noatime,space_cache,compress=zstd:3 "${BTRFS}" /mnt mkdir -p /mnt/{boot,root,home,.snapshots,srv,tmp,/var/log,/var/crash,/var/cache,/var/tmp,/var/spool,/var/lib/libvirt/images,/var/lib/machines,/var/lib/gdm,/var/lib/AccountsService,/cryptkey} mount -o ssd,noatime,compress=zstd,nodev,nosuid,noexec,subvol=@/boot "${BTRFS}" /mnt/boot @@ -262,7 +273,7 @@ mount -o ssd,noatime,compress=zstd,nodatacow,nodev,nosuid,noexec,subvol=@/cryptk mkdir -p /mnt/boot/efi mount -o nodev,nosuid,noexec "${ESP}" /mnt/boot/efi -## Checking the microcode to install. +## Check the microcode to install. if [ "${virtualization}" = 'none' ]; then CPU=$(grep vendor_id /proc/cpuinfo) if [[ "${CPU}" == *"AuthenticAMD"* ]]; then @@ -272,42 +283,48 @@ if [ "${virtualization}" = 'none' ]; then fi fi -## Pacstrap (setting up a base sytem onto the new root). -## As I said above, I am considering replacing gnome-software with pamac-flatpak-gnome as PackageKit seems very buggy on Arch Linux right now. -echo "Installing the base system (it may take a while)." -pacstrap /mnt base ${kernel} ${microcode} linux-firmware grub grub-btrfs snapper snap-pac efibootmgr sudo networkmanager apparmor firewalld zram-generator reflector chrony sbctl openssh fwupd +## Pacstrap +output 'Installing the base system (it may take a while).' +if [ "${install_mode}" = 'desktop' ]; then + pacstrap /mnt base ${kernel} ${microcode} apparmor chrony firewalld grub grub-btrfs linux-firmware nano networkmanager reflector snapper snap-pac sudo gdm gnome-control-center gnome-console nautilus pipewire-pulse pipewire-alsa pipewire-jack flatpak zram-generator +elif [ "${install_mode}" = 'server' ]; then + pacstrap /mnt base ${kernel} ${microcode} apparmor chrony firewalld grub grub-btrfs linux-firmware nano networkmanager reflector snapper snap-pac sudo zram-generator openssh +fi -# Generating /etc/fstab. -echo "Generating a new fstab." +if [ "${virtualization}" = 'none' ]; then + pacstrap /mnt sbctl fwupd +fi + +## Generate /etc/fstab. +output 'Generating a new fstab.' genfstab -U /mnt >> /mnt/etc/fstab sed -i 's#,subvolid=258,subvol=/@/.snapshots/1/snapshot,subvol=@/.snapshots/1/snapshot##g' /mnt/etc/fstab -# Setting hostname. -read -r -p "Please enter the hostname: " hostname +output 'Setting up hostname, locale and keyboard layout' + +## Set hostname. echo "$hostname" > /mnt/etc/hostname -# Setting hosts file. -echo "Setting hosts file." -cat > /mnt/etc/hosts < /mnt/etc/hosts -# Setting up locales. +## Setup locales. echo "$locale.UTF-8 UTF-8" > /mnt/etc/locale.gen echo "LANG=$locale.UTF-8" > /mnt/etc/locale.conf -# Setting up keyboard layout. +## Setup keyboard layout. read -r -p "Please insert the keyboard layout you use: " kblayout echo "KEYMAP=$kblayout" > /mnt/etc/vconsole.conf -# Configuring /etc/mkinitcpio.conf -echo "Configuring /etc/mkinitcpio for ZSTD compression and LUKS hook." +## Configure /etc/mkinitcpio.conf +output 'Configuring /etc/mkinitcpio for ZSTD compression and LUKS hook.' sed -i 's,#COMPRESSION="zstd",COMPRESSION="zstd",g' /mnt/etc/mkinitcpio.conf -sed -i 's,HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block filesystems fsck),HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block encrypt filesystems fsck),g' /mnt/etc/mkinitcpio.conf +sed -i 's,HOOKS=.*,HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block encrypt filesystems fsck),g' /mnt/etc/mkinitcpio.conf -# Enabling LUKS in GRUB and setting the UUID of the LUKS container. +## Enable LUKS in GRUB and setting the UUID of the LUKS container. UUID=$(blkid $cryptroot | cut -f2 -d'"') sed -i 's/#\(GRUB_ENABLE_CRYPTODISK=y\)/\1/' /mnt/etc/default/grub echo "" >> /mnt/etc/default/grub @@ -315,70 +332,37 @@ echo -e "# Booting with BTRFS subvolume\nGRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETE sed -i 's#rootflags=subvol=${rootsubvol}##g' /mnt/etc/grub.d/10_linux sed -i 's#rootflags=subvol=${rootsubvol}##g' /mnt/etc/grub.d/20_linux_xen -# Enabling CPU Mitigations -curl https://raw.githubusercontent.com/Kicksecure/security-misc/master/etc/default/grub.d/40_cpu_mitigations.cfg -o /mnt/etc/grub.d/40_cpu_mitigations.cfg +## Kernel hardening +sed -i 's/quiet/cryptdevice=UUID=$UUID:cryptroot root=$BTRFS mitigations=auto,nosmt spectre_v2=on spectre_bhi=on spec_store_bypass_disable=on tsx=off kvm.nx_huge_pages=force nosmt=force l1d_flush=on spec_rstack_overflow=safe-ret gather_data_sampling=force reg_file_data_sampling=on random.trust_bootloader=off random.trust_cpu=off intel_iommu=on amd_iommu=force_isolation efi=disable_early_pci_dma iommu=force iommu.passthrough=0 iommu.strict=1 slab_nomerge init_on_alloc=1 init_on_free=1 pti=on vsyscall=none ia32_emulation=0 page_alloc.shuffle=1 randomize_kstack_offset=on debugfs=off lockdown=confidentiality module.sig_enforce=1/g' /etc/default/grub +sudo update-grub -# Distrusting the CPU -curl https://raw.githubusercontent.com/Kicksecure/security-misc/master/etc/default/grub.d/40_distrust_cpu.cfg -o /mnt/etc/grub.d/40_distrust_cpu.cfg - -# Enabling IOMMU -curl https://raw.githubusercontent.com/Kicksecure/security-misc/master/etc/default/grub.d/40_enable_iommu.cfg -o /mnt/etc/grub.d/40_enable_iommu.cfg - -# Enabling NTS -curl https://raw.githubusercontent.com/GrapheneOS/infrastructure/main/chrony.conf -o /mnt/etc/chrony.conf - -# Setting GRUB configuration file permissions -chmod 755 /mnt/etc/grub.d/* - -# Adding keyfile to the initramfs to avoid double password. +## Add keyfile to the initramfs to avoid double password. dd bs=512 count=4 if=/dev/random of=/mnt/cryptkey/.root.key iflag=fullblock &>/dev/null chmod 000 /mnt/cryptkey/.root.key &>/dev/null cryptsetup -v luksAddKey /dev/disk/by-partlabel/cryptroot /mnt/cryptkey/.root.key -sed -i "s#quiet#cryptdevice=UUID=$UUID:cryptroot root=$BTRFS lsm=landlock,lockdown,yama,apparmor,bpf cryptkey=rootfs:/cryptkey/.root.key#g" /mnt/etc/default/grub +sed -i "s#debugfs=off#debugfs=off cryptkey=rootfs:/cryptkey/.root.key#g" /mnt/etc/default/grub sed -i 's#FILES=()#FILES=(/cryptkey/.root.key)#g' /mnt/etc/mkinitcpio.conf -# Configure AppArmor Parser caching -sed -i 's/#write-cache/write-cache/g' /mnt/etc/apparmor/parser.conf -sed -i 's,#Include /etc/apparmor.d/,Include /etc/apparmor.d/,g' /mnt/etc/apparmor/parser.conf - -# Blacklisting kernel modules -curl https://raw.githubusercontent.com/Kicksecure/security-misc/master/etc/modprobe.d/30_security-misc.conf -o /mnt/etc/modprobe.d/30_security-misc.conf -chmod 600 /mnt/etc/modprobe.d/* - -# Security kernel settings. -curl https://raw.githubusercontent.com/Kicksecure/security-misc/master/usr/lib/sysctl.d/990-security-misc.conf -o /mnt/etc/sysctl.d/990-security-misc.conf +## Continue kernel hardening +unpriv curl https://raw.githubusercontent.com/Kicksecure/security-misc/master/etc/modprobe.d/30_security-misc.conf | tee /mnt/etc/modprobe.d/30_security-misc.conf +unpriv curl https://raw.githubusercontent.com/Kicksecure/security-misc/master/usr/lib/sysctl.d/990-security-misc.conf | tee /mnt/etc/sysctl.d/990-security-misc.conf sed -i 's/kernel.yama.ptrace_scope=2/kernel.yama.ptrace_scope=3/g' /mnt/etc/sysctl.d/990-security-misc.conf -curl https://raw.githubusercontent.com/Kicksecure/security-misc/master/etc/sysctl.d/30_silent-kernel-printk.conf -o /mnt/etc/sysctl.d/30_silent-kernel-printk.conf -curl https://raw.githubusercontent.com/Kicksecure/security-misc/master/etc/sysctl.d/30_security-misc_kexec-disable.conf -o /mnt/etc/sysctl.d/30_security-misc_kexec-disable.conf -chmod 600 /mnt/etc/sysctl.d/* +unpriv curl https://raw.githubusercontent.com/Kicksecure/security-misc/master/etc/sysctl.d/30_silent-kernel-printk.conf | tee /mnt/etc/sysctl.d/30_silent-kernel-printk.conf +unpriv curl https://raw.githubusercontent.com/Kicksecure/security-misc/master/etc/sysctl.d/30_security-misc_kexec-disable.conf | tee /mnt/etc/sysctl.d/30_security-misc_kexec-disable.conf -# Remove nullok from system-auth +## Setup NTS +unpriv curl https://raw.githubusercontent.com/GrapheneOS/infrastructure/main/chrony.conf | tee /mnt/etc/chrony.conf + +## Remove nullok from system-auth sed -i 's/nullok//g' /mnt/etc/pam.d/system-auth -# Disable coredump -echo "* hard core 0" >> /mnt/etc/security/limits.conf +## Disable coredump +unpriv curl https://raw.githubusercontent.com/TommyTran732/Linux-Setup-Scripts/main/etc/security/limits.d/30-disable-coredump.conf | tee /mnt/etc/security/limits.d/30-disable-coredump.conf -# Disable su for non-wheel users -bash -c 'cat > /mnt/etc/pam.d/su' <<-'EOF' -#%PAM-1.0 -auth sufficient pam_rootok.so -# Uncomment the following line to implicitly trust users in the "wheel" group. -#auth sufficient pam_wheel.so trust use_uid -# Uncomment the following line to require a user to be in the "wheel" group. -auth required pam_wheel.so use_uid -auth required pam_unix.so -account required pam_unix.so -session required pam_unix.so -EOF +## ZRAM configuration +unpriv curl https://raw.githubusercontent.com/TommyTran732/Linux-Setup-Scripts/main/etc/systemd/zram-generator.conf | tee /mnt/etc/systemd/zram-generator.conf -# ZRAM configuration -bash -c 'cat > /mnt/etc/systemd/zram-generator.conf' <<-'EOF' -[zram0] -zram-fraction = 1 -max-zram-size = 8192 -EOF - -# Configuring the system. +## Configuring the system. arch-chroot /mnt /bin/bash -e </dev/null -# Giving wheel user sudo access. +## Give wheel user sudo access. sed -i 's/# \(%wheel ALL=(ALL\(:ALL\|\)) ALL\)/\1/g' /mnt/etc/sudoers -# Change audit logging group -echo "log_group = audit" >> /mnt/etc/audit/auditd.conf +## Enabling openssh server +if [ "${install_mode}" = 'server' ]; then + systemctl enable sshd --root=/mnt &>/dev/null +fi -# Enabling audit service. -systemctl enable auditd --root=/mnt &>/dev/null - -# Enabling openssh server -systemctl enable sshd --root=/mnt &>/dev/null - -# Enabling auto-trimming service. -systemctl enable fstrim.timer --root=/mnt &>/dev/null - -# Enabling NetworkManager. -systemctl enable NetworkManager --root=/mnt &>/dev/null - -# Enabling AppArmor. -echo "Enabling AppArmor." +## Enable services systemctl enable apparmor --root=/mnt &>/dev/null - -# Enabling Firewalld. -echo "Enabling Firewalld." -systemctl enable firewalld --root=/mnt &>/dev/null - -# Enabling Reflector timer. -echo "Enabling Reflector." -systemctl enable reflector.timer --root=/mnt &>/dev/null - -# Enabling systemd-oomd. -echo "Enabling systemd-oomd." -systemctl enable systemd-oomd --root=/mnt &>/dev/null - -# Disabling systemd-timesyncd -systemctl disable systemd-timesyncd --root=/mnt &>/dev/null - -# Enabling chronyd systemctl enable chronyd --root=/mnt &>/dev/null - -# Enabling Snapper automatic snapshots. -echo "Enabling Snapper and automatic snapshots entries." +systemctl enable firewalld --root=/mnt &>/dev/null +systemctl enable fstrim.timer --root=/mnt &>/dev/null +systemctl enable grub-btrfs.path --root=/mnt &>/dev/null +systemctl enable NetworkManager --root=/mnt &>/dev/null +systemctl enable reflector.timer --root=/mnt &>/dev/null systemctl enable snapper-timeline.timer --root=/mnt &>/dev/null systemctl enable snapper-cleanup.timer --root=/mnt &>/dev/null -systemctl enable grub-btrfs.path --root=/mnt &>/dev/null +systemctl enable systemd-oomd --root=/mnt &>/dev/null +systemctl disable systemd-timesyncd --root=/mnt &>/dev/null -# Setting umask to 077. -sed -i 's/022/077/g' /mnt/etc/profile -echo "" >> /mnt/etc/bash.bashrc -echo "umask 077" >> /mnt/etc/bash.bashrc +## Set umask to 077. +sudo sed -i 's/^UMASK.*/UMASK 077/g' /mnt/etc/login.defs +sudo sed -i 's/^HOME_MODE/#HOME_MODE/g' /mnt/etc/login.defs +sudo sed -i 's/^USERGROUPS_ENAB.*/USERGROUPS_ENAB no/g' /mnt/etc/login.defs +sudo sed -i 's/umask 022/umask 077/g' /mnt/etc/bash.bashrc -# Finishing up +# Finish up echo "Done, you may now wish to reboot (further changes can be done by chrooting into /mnt)." exit \ No newline at end of file