diff --git a/install.bash b/install.bash index 42030f9..1cf3b79 100644 --- a/install.bash +++ b/install.bash @@ -1,79 +1,191 @@ #!/usr/env/bin bash -set -euox pipefail -export DISK="/dev/vda" -export DISK_EXT="${DISK}" - # The size is large because I'd like to be able to hibernate my laptop in its entirety. I have 64 GB of ram. -export SWAP_SIZE="32" -export SWAP_OFFSET="$(( SWAP_SIZE + 1 ))" +install() { + set -euo pipefail + local disk="${1}" + local encrypt_disk="${2}" + local swap_size="${3}" -export LABEL_CRYPT_LUKS="NixOS-Crypt" -export LABEL_SWAP="NixOS-Swap" -export LABEL_BTRFS="NixOS-Primary" -export LABEL_BOOT="NixOS-Boot" + local boot_partition="${disk}1" + local swap_partition="${disk}2" + local primary_partition="${disk}3" + # The size is large because I'd like to be able to hibernate my laptop in its entirety. I have 64 GB of ram. -swapoff -a || true -umount /mnt/**/* || true -umount /mnt/* || true -umount /mnt || true -cryptsetup close enc || true -dd if=/dev/zero of="${DISK}" bs=512 count=1024 || true + if [[ -z "${swap_size}" ]]; then + swap_size="$(grep MemTotal /proc/meminfo | awk '{print int(sqrt($2 / 1024 / 1024) * 2)}')" + fi + local swap_offset="$((swap_size + 1))" -### Partition The Disk -parted "${DISK}" -- mklabel gpt -# Boot partition -parted -a optimal "${DISK}" -- mkpart ESP fat32 1MiB 1GiB -parted "${DISK}" -- set 1 boot on -mkfs.vfat "${DISK_EXT}1" -fatlabel "${DISK_EXT}1" "${LABEL_BOOT}" -# Swap Partition -parted -a optimal "${DISK}" -- mkpart "${LABEL_SWAP}" linux-swap 1Gib "${SWAP_OFFSET}GB" -mkswap -L "${LABEL_SWAP}" "${DISK_EXT}2" -swapon "${DISK_EXT}2" -# Nix Partition, where the OS will reside with our data -parted -a optimal "${DISK}" -- mkpart "${LABEL_BTRFS}" "${SWAP_OFFSET}GiB" 100% + local label_crypt_luks="NixOS-Crypt" + local label_swap="NixOS-Swap" + local label_primary="NixOS-Primary" + local label_boot="NixOS-Boot" -### Encrypt -cryptsetup --verify-passphrase -v luksFormat "${DISK_EXT}3" -cryptsetup config "${DISK_EXT}3" --label "${LABEL_CRYPT_LUKS}" -# Have to decrypt it so we can actually get other things setup -export CRYPT_OPEN_NAME="enc" -export CRYPT_PATH="/dev/mapper/${CRYPT_OPEN_NAME}" -cryptsetup open "${DISK_EXT}3" "${CRYPT_OPEN_NAME}" + swapoff -a >/dev/null 2>&1 || true + umount /mnt/**/* >/dev/null 2>&1 || true + umount /mnt/* >/dev/null 2>&1 || true + umount /mnt >/dev/null 2>&1 || true + cryptsetup close >/dev/null 2>&1 enc || true + dd if=/dev/zero of="${disk}" bs=512 count=1024 || true -### BTRFS Setup -# Go ahead and make the unerypted BTRFS -mkfs.btrfs -L "${LABEL_BTRFS}" "${CRYPT_PATH}" + ### Partition The Disk + parted "${disk}" -- mklabel gpt + # Boot partition + parted -a optimal "${disk}" -- mkpart ESP fat32 1MiB 1GiB + parted "${disk}" -- set 1 boot on + mkfs.vfat "${boot_partition}" + fatlabel "${boot_partition}" "${label_boot}" + # Swap Partition + parted -a optimal "${disk}" -- mkpart "${label_swap}" linux-swap 1Gib "${swap_offset}GB" + mkswap -L "${label_swap}" "${swap_partition}" + swapon "${swap_partition}" + # Nix Partition, where the OS will reside with our data + parted -a optimal "${disk}" -- mkpart "${label_primary}" "${swap_offset}GiB" 100% -# Mount it -mount -t btrfs "${CRYPT_PATH}" /mnt + ### Encrypt + if [[ "${encrypt_disk}" == "yes" ]]; then + cryptsetup --verify-passphrase -v luksFormat "${primary_partition}" + cryptsetup config "${primary_partition}" --label "${label_crypt_luks}" + # Have to decrypt it so we can actually get other things setup + local crypt_open_name="enc" + cryptsetup open "${primary_partition}" "${crypt_open_name}" + primary_partition="/dev/mapper/${crypt_open_name}" + fi -# Create our subvolumes -btrfs subvolume create "/mnt/@nix" -umount /mnt + ### BTRFS Setup + # Go ahead and make the unerypted BTRFS + mkfs.btrfs -f -L "${label_primary}" "${primary_partition}" -### Final Mountings -# Mount tmpfs to mnt -mount -t tmpfs -o mode=755 none /mnt + # Mount it + mount -t btrfs "${primary_partition}" /mnt -# Create our directories -mkdir /mnt/{"boot","nix"} -# Mount our boot partition -mount -t vfat -o defaults,noatime "${DISK_EXT}1" /mnt/boot + # Create our subvolumes + btrfs subvolume create "/mnt/@nix" + umount /mnt -# Mount our btrfs subvolumes individually with some btrfs options -# NOTE: On high performance NVME SSDs with a beefy CPU it may be worth considering ZLO compression instead of ZSTD. In -# many cases ZLO is more performant, especially when writing, than ZSTD while having a somewhat worse comrpession ratio. -# WARN: ZLO *may* be a good solution, it can be VERY slow on incompressible data. Something to keep in mind. -mount -t btrfs -o noatime,compress=zstd,subvol=@nix "${CRYPT_PATH}" /mnt/nix + ### Final Mountings + # Mount tmpfs to mnt + mount -t tmpfs -o mode=755 none /mnt -mkdir -p /mnt/nix/persist -### Install NixOS -# Gotta make sure current working tree isn't dirty for the flake -git config --global user.email "m@m.com"; git config --global user.name "name"; git add .; git commit -m "Shit" >/dev/null 2>&1; \ -# Clone the flake into place -git clone . /mnt/nix/persist/etc/nixos && cd /mnt/nix/persist/etc/nixos -# Finally, actually install NixOS -nixos-install --flake "git+file:.#orion" + # Create our directories + mkdir /mnt/{"boot","nix"} + # Mount our boot partition + mount -t vfat -o defaults,noatime "${boot_partition}" /mnt/boot + # Mount our btrfs subvolumes individually with some btrfs options + # NOTE: On high performance NVME SSDs with a beefy CPU it may be worth considering ZLO compression instead of ZSTD. In + # many cases ZLO is more performant, especially when writing, than ZSTD while having a somewhat worse comrpession ratio. + # WARN: ZLO *may* be a good solution, it can be VERY slow on incompressible data. Something to keep in mind. + mount -t btrfs -o noatime,compress=zstd,subvol=@nix "${primary_partition}" /mnt/nix + + mkdir -p /mnt/nix/persist + # Finally, actually install NixOS + nixos-install --flake "git+file:.#orion" +} + +usage() { + cat <<-__EOF__ + Usage: $(basename "${0}") -d "/dev/DISK_HERE" -s 32 -e + -h | -? | --help + Shows this menu. + Example: + $(basename "${0}") -h + + -d | --disk [REQUIRED] + Path to a disk to install NixOS to. + Default: none + Example: + $(basename "${0}") -d /dev/vda + + -e | --encrypt [OPTIONAL] + Enable disk encryption during install. Note, this will prompt you for the encryption password. + Default: disabled + Example: + $(basename "${0}") -e + + -s | --swap [OPTIONAL] + The size of the swap partition in gigabytes. + Default: sqrt(Current system ram in GB) * 2 + Example: + $(basename "${0}") -s 32 + __EOF__ +} + +running_as_root() { + (( EUID == 0 )) +} + +main() { + if ! running_as_root; then + printf "This script MUST be ran as root, exiting!\n" + exit 1 + fi + + local disk="" + local encrypt_disk="no" + local swap_size="" + + while :; do + case ${1} in + -h | -\? | --help) + usage # Display a usage synopsis. + exit + ;; + --) # End of all options. + break + ;; + -d | --disk) + shift + disk="${1}" + if [[ ! -b "${disk}" ]]; then + printf "Unable to read disk '%s', check that it exists, is a block device, and that you have write and read permissions for it!" "${disk}" + exit 1 + fi + printf "Setting installation disk to '%s'\n" "${disk}" + ;; + -e | --encrypt) + encrypt_disk="yes" + printf "Enabled disk encryption\n" + ;; + -s | --swap) + shift + if [[ "${1}" =~ ^[0-9]+$ ]]; then + swap_size="${1}" + if ((swap_size <= 0)); then + printf "Invalid value passed for swap! Expected a non-zero positive number, got: %s\n" "${swap_size}" + exit 1 + fi + printf "Set swap size to '%s'\n" "${swap_size}" + else + printf "Invalid value passed for swap! Expected a number got: %s\n" "${1}" + exit 1 + fi + ;; + -?*) + printf 'Unknown option: %s\n' "$1" >&2 + usage + exit 1 + ;; + *) # Default case: No more options, so break out of the loop. + break ;; + esac + shift + done + + set -euo pipefail + if [[ -z "${disk}" ]]; then + printf "Value for 'disk' (-d) was not provided! See '--help' for usage!\n" + exit 1 + fi + read -r -s -n 1 -p "Press any key to begin NixOS installation to '${disk}'!" + printf "Installing in " + for i in {3..1}; do + printf "%s.." "${i}" + sleep 1 + done + printf "\n" + install "${disk}" "${encrypt_disk}" "${swap_size}" +} + +main "${@}"