Skip to content

Instantly share code, notes, and snippets.

@paulvictor
Forked from mx00s/install.sh
Last active July 26, 2022 05:20
Show Gist options
  • Save paulvictor/86191d6b2d031ce26bac1870dc4bfb91 to your computer and use it in GitHub Desktop.
Save paulvictor/86191d6b2d031ce26bac1870dc4bfb91 to your computer and use it in GitHub Desktop.
NixOS install script based on @grahamc's "Erase Your Darlings" blog post
#!/usr/bin/env bash
#
# NixOS install script synthesized from:
#
# - Erase Your Darlings (https://grahamc.com/blog/erase-your-darlings)
# - ZFS Datasets for NixOS (https://grahamc.com/blog/nixos-on-zfs)
# - NixOS Manual (https://nixos.org/nixos/manual/)
#
# It expects the name of the block device (e.g. 'sda') to partition
# and install NixOS on and an authorized public ssh key to log in as
# 'root' remotely. The script must also be executed as root.
#
# Example: `sudo ./install.sh sde "ssh-rsa AAAAB..."`
#
set -euo pipefail
################################################################################
export COLOR_RESET="\033[0m"
export RED_BG="\033[41m"
export BLUE_BG="\033[44m"
function err {
echo -e "${RED_BG}$1${COLOR_RESET}"
}
function info {
echo -e "${BLUE_BG}$1${COLOR_RESET}"
}
################################################################################
export DISK=$1
if ! [[ -v DISK ]]; then
err "Missing argument. Expected block device name, e.g. 'sda'"
exit 1
fi
export DISK_PATH="/dev/${DISK}"
if ! [[ -b "$DISK_PATH" ]]; then
err "Invalid argument: '${DISK_PATH}' is not a block special file"
exit 1
fi
if [[ "$EUID" > 0 ]]; then
err "Must run as root"
exit 1
fi
export ZFS_POOL="master"
# ephemeral datasets
export ZFS_LOCAL="${ZFS_POOL}/local"
export ZFS_DS_ROOT="${ZFS_LOCAL}/root"
export ZFS_DS_NIX="${ZFS_LOCAL}/nix"
export ZFS_DS_TMP="${ZFS_LOCAL}/tmp"
export ZFS_DS_GNU="${ZFS_LOCAL}/gnu"
# persistent datasets
export ZFS_SAFE="${ZFS_POOL}/safe"
export ZFS_DS_HOME="${ZFS_SAFE}/home"
export ZFS_DS_PERSIST="${ZFS_SAFE}/persist"
export ZFS_DS_TOMB="${ZFS_SAFE}/tomb"
export ZFS_BLANK_SNAPSHOT="${ZFS_DS_ROOT}@blank"
################################################################################
info "Running the UEFI (GPT) partitioning and formatting directions from the NixOS manual ..."
parted "$DISK_PATH" -- mklabel gpt
parted "$DISK_PATH" -- mkpart primary 512MiB 100%
parted "$DISK_PATH" -- mkpart ESP fat32 1MiB 512MiB
parted "$DISK_PATH" -- set 2 boot on
export DISK_PART_ROOT="${DISK_PATH}p1" # The p is specifically for nvme's, adjust accordingly
export DISK_PART_BOOT="${DISK_PATH}p2"
info "Formatting boot partition ..."
mkfs.fat -F 32 -n BOOT "$DISK_PART_BOOT"
info "Creating '$ZFS_POOL' ZFS pool for '$DISK_PART_ROOT' ..."
zpool create -f "$ZFS_POOL" -o ashift=13 "$DISK_PART_ROOT"
zpool set autotrim=on "$ZFS_POOL"
info "Enabling compression for '$ZFS_POOL' ZFS pool ..."
zfs set compression=on "$ZFS_POOL"
info "Creating '$ZFS_DS_ROOT' ZFS dataset ..."
zfs create -p -o mountpoint=legacy "$ZFS_DS_ROOT"
info "Configuring extended attributes setting for '$ZFS_DS_ROOT' ZFS dataset ..."
zfs set xattr=sa "$ZFS_DS_ROOT"
info "Configuring access control list setting for '$ZFS_DS_ROOT' ZFS dataset ..."
zfs set acltype=posixacl "$ZFS_DS_ROOT"
info "Creating '$ZFS_BLANK_SNAPSHOT' ZFS snapshot ..."
zfs snapshot "$ZFS_BLANK_SNAPSHOT"
info "Mounting '$ZFS_DS_ROOT' to /mnt ..."
mount -t zfs "$ZFS_DS_ROOT" /mnt
info "Mounting '$DISK_PART_BOOT' to /mnt/boot ..."
mkdir /mnt/boot
mount -t vfat "$DISK_PART_BOOT" /mnt/boot
info "Creating '$ZFS_DS_NIX' ZFS dataset ..."
zfs create -p -o mountpoint=legacy "$ZFS_DS_NIX"
info "Disabling access time setting for '$ZFS_DS_NIX' ZFS dataset ..."
zfs set atime=off "$ZFS_DS_NIX"
info "Mounting '$ZFS_DS_NIX' to /mnt/nix ..."
mkdir /mnt/nix
mount -t zfs "$ZFS_DS_NIX" /mnt/nix
################################################################################
info "Creating '$ZFS_DS_TMP' ZFS dataset ..."
zfs create -p -o mountpoint=legacy -o setuid=off -o devices=off -o sync=disabled "$ZFS_DS_TMP"
info "Mounting '$ZFS_DS_TMP' to /mnt/tmp ..."
mkdir /mnt/tmp
mount -t zfs "$ZFS_DS_TMP" /mnt/tmp
################################################################################
info "Creating '$ZFS_DS_GNU' ZFS dataset ..."
zfs create -p -o mountpoint=legacy "$ZFS_DS_GNU"
info "Disabling access time setting for '$ZFS_DS_GNU' ZFS dataset ..."
zfs set atime=off "$ZFS_DS_GNU"
info "Mounting '$ZFS_DS_GNU' to /mnt/gnu ..."
mkdir /mnt/gnu
mount -t zfs "$ZFS_DS_GNU" /mnt/gnu
################################################################################
info "Creating '$ZFS_SAFE' ZFS dataset ..."
zfs create -p -o mountpoint=none -o encryption=on -o keyformat=passphrase "$ZFS_SAFE"
info "Creating '$ZFS_DS_HOME' ZFS dataset ..."
zfs create -p -o mountpoint=legacy "$ZFS_DS_HOME"
info "Mounting '$ZFS_DS_HOME' to /mnt/home ..."
mkdir /mnt/home
mount -t zfs "$ZFS_DS_HOME" /mnt/home
info "Creating '$ZFS_DS_PERSIST' ZFS dataset ..."
zfs create -p -o mountpoint=legacy "$ZFS_DS_PERSIST"
info "Mounting '$ZFS_DS_PERSIST' to /mnt/persist ..."
mkdir /mnt/persist
mount -t zfs "$ZFS_DS_PERSIST" /mnt/persist
info "Creating '$ZFS_DS_TOMB' ZFS dataset ..."
zfs create -p -o mountpoint=legacy "$ZFS_DS_TOMB"
info "Mounting '$ZFS_DS_TOMB' to /mnt/tomb ..."
mkdir /mnt/tomb
mount -t zfs "$ZFS_DS_TOMB" /mnt/tomb
info "Permit ZFS auto-snapshots on ${ZFS_SAFE}/* datasets ..."
zfs set com.sun:auto-snapshot=true "$ZFS_DS_HOME"
zfs set com.sun:auto-snapshot=true "$ZFS_DS_PERSIST"
zfs set com.sun:auto-snapshot=true "$ZFS_DS_TOMB"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment