1
0
mirror of https://github.com/tommytran732/Arch-Setup-Script synced 2024-11-22 17:41:33 -05:00

Compare commits

..

11 Commits

Author SHA1 Message Date
15a17738b3
Update README.md
Signed-off-by: Tommy <contact@tommytran.io>
2024-05-31 21:30:58 -07:00
b298669bfe
Add comment on disabling subvol pinning
Signed-off-by: Tommy <contact@tommytran.io>
2024-05-31 20:13:48 -07:00
5d8c96396e
Enable gdm
Signed-off-by: Tommy <contact@tommytran.io>
2024-05-31 20:07:06 -07:00
85399bc680
Install sbctl by default
Signed-off-by: Tommy <contact@tommytran.io>
2024-05-31 20:06:43 -07:00
0d1cb58727
Remove unnecessary output hiding
Signed-off-by: Tommy <contact@tommytran.io>
2024-05-31 16:31:00 -07:00
7de2799cfb
Rearrange command
Signed-off-by: Tommy <contact@tommytran.io>
2024-05-31 16:13:21 -07:00
16331d8f2f
Use rd.luks.key
Signed-off-by: Tommy <contact@tommytran.io>
2024-05-31 16:12:27 -07:00
87595278e0
Fix grub-btrfs
Signed-off-by: Tommy <contact@tommytran.io>
2024-05-31 16:06:24 -07:00
8412ddcb5b
Add efibootmgr
Signed-off-by: Tommy <contact@tommytran.io>
2024-05-31 15:07:59 -07:00
19942b80fd
Add KVM guest agents
Signed-off-by: Tommy <contact@tommytran.io>
2024-05-31 14:35:50 -07:00
78220c311d
Update kernel hardening
Signed-off-by: Tommy <contact@tommytran.io>
2024-05-31 13:59:44 -07:00
2 changed files with 51 additions and 71 deletions

View File

@ -2,72 +2,34 @@
[![ShellCheck](https://github.com/TommyTran732/Arch-Setup-Script/actions/workflows/shellcheck.yml/badge.svg)](https://github.com/TommyTran732/Arch-Setup-Script/actions/workflows/shellcheck.yml) [![ShellCheck](https://github.com/TommyTran732/Arch-Setup-Script/actions/workflows/shellcheck.yml/badge.svg)](https://github.com/TommyTran732/Arch-Setup-Script/actions/workflows/shellcheck.yml)
This is my fork of [easy-arch](https://github.com/classy-giraffe/easy-arch), a **script** made in order to boostrap a basic **Arch Linux** environment with **snapshots** and **encryption** by using a fully automated process (UEFI only). This is my installer for Arch Linux. It sets up a BTRFS system with encrypted `/boot` and full snapper support (both snapshotting and rollback work!). It also includes various system hardening configurations.
This fork comes with various security improvements and fully working rollbacks with snapper. I do submit some of the changes here back to upstream as well. The script was originally based off [easy-arch](https://github.com/classy-giraffe/easy-arch). However, it diverges substantially from the original project does not follow its development.
Visit my Matrix group: https://matrix.to/#/#tommytran732:matrix.org Visit my Matrix group: https://invite.arcticfoxes.net/#/#tommy:arcticfoxes.net
### How does it work? ### How to use it?
1. Download an Arch Linux ISO from [here](https://archlinux.org/download/) 1. Download an Arch Linux ISO from [here](https://archlinux.org/download/)
2. Flash the ISO onto an [USB Flash Drive](https://wiki.archlinux.org/index.php/USB_flash_installation_medium). 2. Flash the ISO onto an [USB Flash Drive](https://wiki.archlinux.org/index.php/USB_flash_installation_medium).
3. Boot the live environment. 3. Boot the live environment.
4. Connect to the internet. 4. Connect to the internet.
5. `git clone https://github.com/tommytran732/Arch-Setup-Script/` 5. `git clone https://github.com/tommytran732/Arch-Setup-Script/`
6. `cd Arch-Setup-Script` 6. `cd Arch-Setup-Script`
7. `./install.sh` 7. `chmod u+x ./install.sh`
8. `./install.sh`
### Secure Boot
The Secure Boot script can be run after you have rebooted into the system to automate the process of generating your own keys and setting up Secure Boot described at https://wiki.archlinux.org/title/Unified_Extensible_Firmware_Interface/Secure_Boot. Please make sure that your firmware is in Setup mode and the TPM is disabled.
Currently, there is an problem where GRUB requires tpm.mod to be included for signature verification, but if tpm.mod is included and the TPM is enabled it will also attempt to do Measured Boot, breaking the Arch Linux snapshots menu created by grub-btrfs. I have yet to find a solution for this issue.
### Changes to the original project
1. Encrypted /boot with LUKS1
2. SUSE - like partition layout and fully working snapper snapshots & rollback
3. Minimally setup GNOME with pipewire
4. AppArmor and Firewalld enabled by default
5. Defaulting umask to 077
6. Randomize Mac Address and disable Connectivity Check for privacy
7. Added some kernel/grub settings from https://github.com/Whonix/security-misc/tree/master/etc/default
8. Added Secure Boot script
### Snapper behavior ### Snapper behavior
The partition layout I use rallows us to replicate the behavior found in openSUSE 🦎 The partition layout I use allows us to replicate the behavior found in openSUSE 🦎
1. Snapper rollback <number> works! You will no longer need to manually rollback from a live USB like you would with the @ and @home layout suggested in the Arch Wiki. 1. Snapper rollback <number> works! You will no longer need to manually rollback from a live USB like you would with the @ and @home layout suggested in the Arch Wiki.
2. You can boot into a readonly snapshot! GDM and other services will start normally so you can get in and verify that everything works before rolling back. 2. You can boot into a readonly snapshot! GDM and other services will start normally so you can get in and verify that everything works before rolling back.
3. Automatic snapshots on pacman install/update/remove operations 3. Automatic snapshots on pacman install/update/remove operations
4. Directories such as /boot, /boot/efi, /var/log, /var/crash, /var/tmp, /var/spool, /var/lib/libvirt/images are excluded from the snapshots as they either should be persistent or are just temporary files. /cryptkey is excluded as we do not want the encryption key to be included in the snapshots, which could be sent to another device as a backup. 4. Directories such as /boot, /boot/efi, /var/log, /var/crash, /var/tmp, /var/spool, /var/lib/libvirt/images are excluded from the snapshots as they either should be persistent or are just temporary files. /cryptkey is excluded as we do not want the encryption key to be included in the snapshots, which could be sent to another device as a backup.
5. GRUB will boot into the default BTRFS snapshot set by snapper. Like on SUSE, your running system will always be a read-write snapshot in @/.snapshots/X/snapshot. 5. GRUB will boot into the default BTRFS snapshot set by snapper. Like on openSUSE, your running system will always be a read-write snapshot in @/.snapshots/X/snapshot.
### Partitions layout ### Security considerations
| Partition/Subvolume | Label | Mountpoint | Notes | Since this is an encrypted /boot setup, GRUB will prompt you for your encryption password and decrypt the drive so that it can access the kernel and initramfs. I am unaware of any way to make it use a TPM + PIN setup.
|---------------------|------------------------------|--------------------------|-----------------------------|
| 1 | ESP | /boot/efi | Unencrypted FAT32 |
| 2 | @/.snapshots/X/snapshot | / | Encrypted BTRFS |
| 3 | @/boot | /boot/ | Encrypted BTRFS (nodatacow) |
| 4 | @/root | /root | Encrypted BTRFS |
| 5 | @/home | /home | Encrypted BTRFS |
| 6 | @/.snapshots | /.snapshots | Encrypted BTRFS |
| 7 | @/srv | /srv | Encrypted BTRFS (nodatacow) |
| 8 | @/var_log | /var/log | Encrypted BTRFS (nodatacow) |
| 9 | @/var_log/journal | /var/log/journal | Encrypted BTRFS (nodatacow) |
| 10 | @/var_crash | /var/crash | Encrypted BTRFS (nodatacow) |
| 11 | @/var_cache | /var/cache | Encrypted BTRFS (nodatacow) |
| 12 | @/var_tmp | /var/tmp | Encrypted BTRFS (nodatacow) |
| 13 | @/var_spool | /var/spool | Encrypted BTRFS (nodatacow) |
| 14 | @/var_lib_libvirt_images | /var/lib/libvirt/images | Encrypted BTRFS (nodatacow) |
| 15 | @/var_lib_machines | /var/lib/machines | Encrypted BTRFS (nodatacow) |
| 16 | @/var_lib_gdm | /var/lib/gdm | Encrypted BTRFS (nodatacow) |
| 17 | @/var_lib_AccountsService | /var/lib/AccountsService | Encrypted BTRFS (nodatacow) |
| 18 | @/cryptkey | /cryptkey | Encrypted BTRFS (nodatacow) |
### LUKS1 and Encrypted /boot (Mumbo Jumbo stuff) The implication of this is that an attacker can change your secure boot state with a programmer, replace your grubx64.efi and it will not be detected until its too late.
This is the same setup that is used on openSUSE. One problem with the way Secure Boot currently works is that the initramfs and a variety of things in /boot are not validated by GRUB whatsoever, even if Secure Boot is active. Thus, they are vulnerable to tampering. My approach as of now is to encrypt the entire /boot partition and have the only that is unencrypted - the grubx64.efi stub - validated by the firmware.
Ideally, I could use GRUB's GPG verification for the initramfs and its configuration files and what not, but then I need to create hooks to sign them everytime they get updated (when a new initramfs gets generated, when grub-btrfs.path gets triggered, when grub gets updated and its config files change, etc). It is quite a tedious task and I have yet to implement or test this out. This type of attack can theoratically be solved by splitting /boot out to a seperate partition and encrypt the root filesystem separately. The key protector for the root filesystem can then be sealed to a TPM with PCR 0+1+2+3+5+7+14. It is a bit more complicated to set up so my installer does not support this (yet!).
As for why LUKS1 is used, GRUB 2.06 does not work nicely with LUKS2 yet. grub-install will not make GRUB auto detect the LUKS2 partition, and GRUB itself does not support Argon2id (cryptsetup default) as of now anyways. It makes little sense to use GRUB with LUKS2 in its current state, thus I am using LUKS1 to avoid the headache.
You may also see an a keyfile being created by the script and stored at /cryptkey. This is to avoid getting 2 encryption password prompts (one for GRUB to decrypt the disk so that it can get to the kernel, the initramfs and configuration files and one for the kernel itself to start up the rest of the boot process). As the key resides on an encrypted partition (and so does the initramfs that stores a copy of it), security risks should be minimal. The only time an attacker would have access to it is when they have root, at which point you have a much, much more serious problem. The procedure I am using is describe at https://en.opensuse.org/SDB:Encrypted_root_file_system.

View File

@ -285,16 +285,22 @@ fi
## Pacstrap ## Pacstrap
output 'Installing the base system (it may take a while).' output 'Installing the base system (it may take a while).'
if [ "${install_mode}" = 'desktop' ]; then if [ "${install_mode}" = 'desktop' ]; then
pacstrap /mnt base "${kernel}" "${microcode}" apparmor chrony firewalld grub grub-btrfs linux-firmware nano networkmanager reflector snapper sudo zram-generator nautilus gdm gnome-console gnome-control-center pipewire-alsa pipewire-pulse pipewire-jack pacstrap /mnt base "${kernel}" "${microcode}" apparmor chrony efibootmgr firewalld grub grub-btrfs inotify-tools linux-firmware nano networkmanager reflector sbctl snapper sudo zram-generator nautilus gdm gnome-console gnome-control-center pipewire-alsa pipewire-pulse pipewire-jack
elif [ "${install_mode}" = 'server' ]; then elif [ "${install_mode}" = 'server' ]; then
pacstrap /mnt base "${kernel}" "${microcode}" apparmor chrony firewalld grub grub-btrfs linux-firmware nano networkmanager reflector snapper sudo zram-generator openssh pacstrap /mnt base "${kernel}" "${microcode}" apparmor chrony efibootmgr firewalld grub grub-btrfs inotify-tools linux-firmware nano networkmanager reflector sbctl snapper sudo zram-generator openssh
fi fi
if [ "${virtualization}" = 'none' ]; then if [ "${virtualization}" = 'none' ]; then
pacstrap /mnt sbctl fwupd pacstrap /mnt fwupd
echo 'UriSchemes=file;https' | sudo tee -a /mnt/etc/fwupd/fwupd.conf echo 'UriSchemes=file;https' | sudo tee -a /mnt/etc/fwupd/fwupd.conf
elif [ "${virtualization}" = 'kvm' ]; then
pacstrap /mnt qemu-guest-agent
if [ "${install_mode}" = 'desktop' ]; then
pacstrap /mnt spice-vdagent
fi
fi fi
## Install snap-pac list otherwise we will have problems
pacstrap /mnt snap-pac pacstrap /mnt snap-pac
## Generate /etc/fstab. ## Generate /etc/fstab.
@ -330,6 +336,9 @@ sed -i 's/#GRUB_ENABLE_CRYPTODISK=.*/GRUB_ENABLE_CRYPTODISK=y/g' /mnt/etc/defaul
echo '' >> /mnt/etc/default/grub echo '' >> /mnt/etc/default/grub
echo '# Booting with BTRFS subvolume echo '# Booting with BTRFS subvolume
GRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION=true' >> /mnt/etc/default/grub GRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION=true' >> /mnt/etc/default/grub
## Disable root subvol pinning.
## This is **extremely** important, as snapper expects to be able to set the default btrfs subvol.
# shellcheck disable=SC2016 # shellcheck disable=SC2016
sed -i 's/rootflags=subvol=${rootsubvol}//g' /mnt/etc/grub.d/10_linux sed -i 's/rootflags=subvol=${rootsubvol}//g' /mnt/etc/grub.d/10_linux
# shellcheck disable=SC2016 # shellcheck disable=SC2016
@ -343,11 +352,16 @@ sed -i "s#quiet#rd.luks.name=${UUID}=cryptroot root=${BTRFS} mitigations=auto,no
dd bs=512 count=4 if=/dev/random of=/mnt/cryptkey/.root.key iflag=fullblock &>/dev/null 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 chmod 000 /mnt/cryptkey/.root.key &>/dev/null
echo -n "${luks_password}" | cryptsetup luksAddKey /dev/disk/by-partlabel/cryptroot /mnt/cryptkey/.root.key -d - echo -n "${luks_password}" | cryptsetup luksAddKey /dev/disk/by-partlabel/cryptroot /mnt/cryptkey/.root.key -d -
sed -i "s#module.sig_enforce=1#module.sig_enforce=1 cryptkey=rootfs:/cryptkey/.root.key#g" /mnt/etc/default/grub
sed -i 's#FILES=()#FILES=(/cryptkey/.root.key)#g' /mnt/etc/mkinitcpio.conf sed -i 's#FILES=()#FILES=(/cryptkey/.root.key)#g' /mnt/etc/mkinitcpio.conf
sed -i "s#module.sig_enforce=1#module.sig_enforce=1 rd.luks.key=/cryptkey/.root.key#g" /mnt/etc/default/grub
## Continue kernel hardening ## 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/etc/modprobe.d/30_security-misc.conf | tee /mnt/etc/modprobe.d/30_security-misc.conf
sudo sed -i 's/#[[:space:]]*install msr/install msr/g' /mnt/etc/modprobe.d/30_security-misc.conf
if [ "${install_mode}" != 'server' ]; then
sudo sed -i 's/#[[:space:]]*install bluetooth/install bluetooth/g' /mnt/etc/modprobe.d/30_security-misc.conf
sudo sed -i 's/#[[:space:]]*install btusb/install btusb/g' /mnt/etc/modprobe.d/30_security-misc.conf
fi
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 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[[:space:]]*=.*/kernel.yama.ptrace_scope=3/g' /mnt/etc/sysctl.d/990-security-misc.conf sed -i 's/kernel\.yama\.ptrace_scope[[:space:]]*=.*/kernel.yama.ptrace_scope=3/g' /mnt/etc/sysctl.d/990-security-misc.conf
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_silent-kernel-printk.conf | tee /mnt/etc/sysctl.d/30_silent-kernel-printk.conf
@ -387,20 +401,23 @@ arch-chroot /mnt /bin/bash -e <<EOF
# Generating locales.my keys aren't even on # Generating locales.my keys aren't even on
echo "Generating locales." echo "Generating locales."
locale-gen &>/dev/null locale-gen
# Create SecureBoot keys. This isn't strictly necessary, but certain things like linux-hardened preset expects it and mkinitcpio will fail without it, sooo...
sbctl create-keys
# Generating a new initramfs. # Generating a new initramfs.
echo "Creating a new initramfs." echo "Creating a new initramfs."
chmod 600 /boot/initramfs-linux* &>/dev/null chmod 600 /boot/initramfs-linux*
mkinitcpio -P &>/dev/null mkinitcpio -P
# Installing GRUB. # Installing GRUB.
echo "Installing GRUB on /boot." echo "Installing GRUB on /boot."
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=GRUB --modules="normal test efi_gop efi_uga search echo linux all_video gfxmenu gfxterm_background gfxterm_menu gfxterm loadenv configfile gzio part_gpt cryptodisk luks gcry_rijndael gcry_sha256 btrfs" --disable-shim-lock &>/dev/null grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=GRUB --modules="normal test efi_gop efi_uga search echo linux all_video gfxmenu gfxterm_background gfxterm_menu gfxterm loadenv configfile gzio part_gpt cryptodisk luks gcry_rijndael gcry_sha256 btrfs" --disable-shim-lock
# Creating grub config file. # Creating grub config file.
echo "Creating GRUB config file." echo "Creating GRUB config file."
grub-mkconfig -o /boot/grub/grub.cfg &>/dev/null grub-mkconfig -o /boot/grub/grub.cfg
# Adding user with sudo privilege # Adding user with sudo privilege
if [ -n "$username" ]; then if [ -n "$username" ]; then
@ -427,21 +444,22 @@ sed -i 's/# \(%wheel ALL=(ALL\(:ALL\|\)) ALL\)/\1/g' /mnt/etc/sudoers
## Enabling openssh server ## Enabling openssh server
if [ "${install_mode}" = 'server' ]; then if [ "${install_mode}" = 'server' ]; then
systemctl enable sshd --root=/mnt &>/dev/null systemctl enable sshd --root=/mnt
fi fi
## Enable services ## Enable services
systemctl enable apparmor --root=/mnt &>/dev/null systemctl enable apparmor --root=/mnt
systemctl enable chronyd --root=/mnt &>/dev/null systemctl enable chronyd --root=/mnt
systemctl enable firewalld --root=/mnt &>/dev/null systemctl enable firewalld --root=/mnt
systemctl enable fstrim.timer --root=/mnt &>/dev/null systemctl enable fstrim.timer --root=/mnt
systemctl enable grub-btrfs.path --root=/mnt &>/dev/null systemctl enable gdm.service --root=/mnt
systemctl enable NetworkManager --root=/mnt &>/dev/null systemctl enable grub-btrfsd.service --root=/mnt
systemctl enable reflector.timer --root=/mnt &>/dev/null systemctl enable NetworkManager --root=/mnt
systemctl enable snapper-timeline.timer --root=/mnt &>/dev/null systemctl enable reflector.timer --root=/mnt
systemctl enable snapper-cleanup.timer --root=/mnt &>/dev/null systemctl enable snapper-timeline.timer --root=/mnt
systemctl enable systemd-oomd --root=/mnt &>/dev/null systemctl enable snapper-cleanup.timer --root=/mnt
systemctl disable systemd-timesyncd --root=/mnt &>/dev/null systemctl enable systemd-oomd --root=/mnt
systemctl disable systemd-timesyncd --root=/mnt
## Set umask to 077. ## Set umask to 077.
sudo sed -i 's/^UMASK.*/UMASK 077/g' /mnt/etc/login.defs sudo sed -i 's/^UMASK.*/UMASK 077/g' /mnt/etc/login.defs