#!/bin/bash set -e # Stop on Errors scriptdir="$(dirname "$(readlink -f "$0")")" function show_help() { echo "$0 -d -h [options]" echo " A Semi-Automatic Archlinux Install Script" echo " -d Device to Install to" echo " -k Kernel Name to Install (default: linux-zen)" echo " -n Network Management: n NetworkMangager, m NetworkManager + ModemManager, s systemd-networkd (default: none)" echo " -l Locale to use (default: de_DE)" echo " -m Console Keymap to use (default: de)" echo " -t Timezone to use (default: Europe/Berlin)" echo " -h Set the Target Hostname" echo " -s Only use hddsize for the system partition" echo " -b Set System Type to BIOS (default: UEFI)" echo " -c Disable Encryption (default: enabled)" } function exit_error() { echo "$1" show_help exit 1 } function install_network() { local option=$1 case $option in 1) echo "Installing NetworkManager" pacstrap /mnt networkmanager systemctl enable --root=/mnt NetworkManager ;; 2) echo "Installing NetworkManager an ModemManager" pacstrap /mnt networkmanager modemmanager systemctl enable --root=/mnt NetworkManager ModemManager ;; 3) echo "Installing systemd-networkd" systemctl enable --root=/mnt systemd-networkd ;; *) echo "No Network Management selected, not installing any" ;; esac } ## Defaults kernel="linux-zen" locale="de_DE" keymap="de" timezone="Europe/Berlin" systype="x86_64-efi" network=0 encryption=1 hddsize="100%" ## Get CLI Options while getopts 'k:d:n:m:l:h:s:t:bc?' flag; do case "${flag}" in k) kernel="${OPTARG}" ;; n) case "${OPTARG}" in n) network=1 ;; m) network=2 ;; s) network=3 ;; *) exit_error "Unknown Network Type Selected, Aborting" ;; esac ;; d) device="${OPTARG}" ;; l) locale="${OPTARG}" ;; m) keymap="${OPTARG}" ;; t) timezone="${OPTARG}" ;; b) systype="i386-pc" ;; c) encryption=0 ;; h) hostname="${OPTARG}" ;; s) hddsize="${OPTARG}" ;; ?) show_help ;; *) show_help ;; esac done if [[ -z "$device" ]]; then exit_error "No Installation Device Selected, Aborting" fi if [[ -z "$hostname" ]]; then exit_error "No Hostname given, Aborting" fi ## Confirm installation read -r -p "This will delete the current partition table on $device. Do you agree [y/N]? " response response=${response,,} if [[ "$response" =~ ^(yes|y)$ ]]; then wipefs -af "$device" &>/dev/null sgdisk -Zo "$device" &>/dev/null else exit_error "Installation Aborted by User" fi ## Select Microcode if [[ "$(systemd-detect-virt)" == "none" ]]; then if [[ "$(grep vendor_id /proc/cpuinfo)" == *"AuthenticAMD"* ]]; then microcode=amd-ucode else microcode=intel-ucode fi firmware=linux-firmware fi echo "Paritioning Disk ${device}" if [[ "${systype}" == "x86_64-efi" ]]; then parted -s "$device" \ mklabel gpt \ mkpart ESP fat32 1MiB 513MiB \ set 1 esp on \ mkpart arch 514MiB ${hddsize} part_esp="/dev/disk/by-partlabel/ESP" part_root="/dev/disk/by-partlabel/arch" extrapkgs="efibootmgr" partprobe "${device}" sleep 2 mkfs.fat -F32 -n EFI "${part_esp}" else parted -s "$device" \ mklabel gpt \ mkpart grub 1MiB 2MiB \ set 1 bios_grub on \ mkpart arch 2MiB 100% partprobe "${device}" sleep 2 part_root="/dev/disk/by-partlabel/arch" fi if [ $encryption -eq 1 ]; then echo "Creating Encrypted Root Partition" read -s -r -p "Please Enter the Encryption Passhprase: " lukspw echo "" read -s -r -p "Please Verify the Encryption Passhprase: " lukspw2 echo "" [ "$lukspw" != "$lukspw2" ] && echo "Passphrases don't match!" && exit 1 echo -n "$lukspw" | cryptsetup luksFormat --type luks1 --cipher aes-xts-plain64 --hash sha512 --key-size 512 "${part_root}" - echo -n "$lukspw" | cryptsetup open --key-file - "${part_root}" "cryptroot" unset lukspw lukspw2 root_dev="/dev/mapper/cryptroot" else root_dev="${part_root}" fi echo "Creating BTRFS Filesystem" mkfs.btrfs -f -L archlinux "${root_dev}" echo "Creating BRTFS Subvolumes" mount "${root_dev}" /mnt for sv in "@" "@home" "@data" "@snapshots" "@log" "@pkg" "@machines" "@portables"; do btrfs su cr "/mnt/${sv}" done btrfs_opts="ssd,noatime,compress=zstd,autodefrag,discard=async" umount /mnt echo "Mounting System Subvolumes" mount -o ${btrfs_opts},subvol=@ "${root_dev}" /mnt mkdir -p /mnt/{home,data,.snapshots,var/log,var/cache/pacman/pkg,var/lib/machines,var/lib/portables} mount -o ${btrfs_opts},subvol=@home "${root_dev}" /mnt/home mount -o ${btrfs_opts},subvol=@data "${root_dev}" /mnt/data mount -o ${btrfs_opts},subvol=@snapshots "${root_dev}" /mnt/.snapshots mount -o ${btrfs_opts},subvol=@log "${root_dev}" /mnt/var/log mount -o ${btrfs_opts},subvol=@pkg "${root_dev}" /mnt/var/cache/pacman/pkg mount -o ${btrfs_opts},subvol=@machines "${root_dev}" /mnt/var/lib/machines mount -o ${btrfs_opts},subvol=@portables "${root_dev}" /mnt/var/lib/portables chattr +C /mnt/var/log /mnt/var/cache/pacman/pkg if [[ "${systype}" == "x86_64-efi" ]]; then mkdir -p /mnt/boot/efi mount "${part_esp}" /mnt/boot/efi fi echo "Installing Base System Packages" pacstrap /mnt base $kernel $microcode $firmware $extrapkgs btrfs-progs grub grub-btrfs snapper vim git tmux htop iftop iotop tcpdump mtr rsync wget which zip lsof strace openssh inetutils bc man-pages sudo bash-completion echo "Creating Basic Config Files" genfstab -U /mnt | sed -e 's/suvolid=[0-9]*,//g' >> /mnt/etc/fstab echo "${hostname}" >> /mnt/etc/hostname cat > /mnt/etc/hosts < /mnt/etc/locale.gen echo "LANG=$locale.UTF-8" > /mnt/etc/locale.conf echo "KEYMAP=$keymap" > /mnt/etc/vconsole.conf if [ -d "${scriptdir}/etc" ]; then cp -r "${scriptdir}/etc/"* /mnt/etc/ fi sed -i 's/#COMPRESSION="zstd"/COMPRESSION="zstd"/g' /mnt/etc/mkinitcpio.conf if [ $encryption -eq 1 ]; then sed -i 's/HOOKS=.*/HOOKS=(base udev autodetect keyboard keymap modconf block encrypt filesystems fsck)/g' /mnt/etc/mkinitcpio.conf UUID=$(blkid ${part_root} | cut -f2 -d'"') sed -i 's/#GRUB_ENABLE_CRYPTODISK=y/GRUB_ENABLE_CRYPTODISK=y/g' /mnt/etc/default/grub sed -i "s#GRUB_CMDLINE_LINUX_DEFAULT=.*#GRUB_CMDLINE_LINUX_DEFAULT=\"loglevel=3 quiet cryptdevice=UUID=$UUID:cryptroot:allow-discards root=${root_dev}\"#g" /mnt/etc/default/grub else sed -i 's/HOOKS=.*/HOOKS=(base udev autodetect keyboard keymap modconf block filesystems fsck)/g' /mnt/etc/mkinitcpio.conf fi arch-chroot /mnt /bin/bash -e <> /etc/pacman.conf echo 'SigLevel = Required DatabaseOptional TrustedOnly' >> /etc/pacman.conf echo 'Server = http://www.seiichiro0185.org/repo/\$arch' >> /etc/pacman.conf echo "Setting up Snapper" umount /.snapshots rm -r /.snapshots snapper --no-dbus -c root create-config / btrfs subvolume delete /.snapshots &>/dev/null mkdir /.snapshots mount -a chmod 750 /.snapshots echo "Installing Grub" if [ "${systype}" == "x86_64-efi" ]; then grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=GRUB &>/dev/null else grub-install --target=i386-pc ${device} fi grub-mkconfig -o /boot/grub/grub.cfg EOF echo "Please set a Password for root" arch-chroot /mnt /bin/passwd install_network ${network} echo "Enabling Services" systemctl enable sshd grub-btrfs.path --root /mnt echo -e "\n\nInstallation finished, you may further customize it in /mnt or reboot now"