Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Script

This is a small script which is serving as installer for this project. It basically:

  • Sets up an environment to install the system from
  • Asks for basic information such as the disk to be used or the username
  • Sets up the partition layout via disko and mounting the partitions to /mnt
  • Provides a basic, quite generic dr460nixed template and customizes it based on previous choices
  • Executes the installation
#!/usr/bin/env bash
set -eo pipefail

# Check for root rights
if [ "$EUID" -ne 0 ]; then
  echo "I can only run as root!"
  exit 3
fi

# Prepare our environment
prepare() {
  # Clone dr460nixed repo if it is not present, otherwise use current dir
  if [ ! "$(test -f flake.nix)" ]; then
    test -d /tmp/dr460nixed && sudo rm -rf /tmp/dr460nixed
    WORK_DIR=/tmp/dr460nixed
    git clone https://github.com/dr460nf1r3/dr460nixed.git "$WORK_DIR"
    cd "$WORK_DIR"
  else
    WORK_DIR=$(pwd)
  fi

  # Ensure needed "experimental" features are always enabled
  export NIX_CONFIG="experimental-features = nix-command flakes"
}

# Confirmation prompt
confirm_choices() {
  # Continue if the user confirms our choice
  read -rp "Are you sure you want to continue? $1 [y/n] " _ANSWER

  while [ -z "${KILLIT+x}" ]; do
    case "${_ANSWER}" in
    y | yes | Y | YES)
      KILLIT=1
      ;;
    n | no | N | NO)
      exit 1
      ;;
    *)
      read -rp "Invalid input. Only yes or no is valid: " _ANSWER
      ;;
    esac
  done
}

# Create a runner for disko, directly from git
disko_runner() {
  nix run github:nix-community/disko -- --mode disko "$1" --arg disks "[ \"$2\" ]"
}

# Create partitions using disko and mount them to /mnt
disko() {
  echo "The following partition layouts are available:
1) BTRFS with subvolumes
2) BTRFS on LUKS with subvolumes
3) Simple EFI
4) ZFS (recommended)
5) ZFS encrypted"

  read -rp "Enter the number of the partition layout you want to use: " _LAYOUT

  # https://stackoverflow.com/questions/3601515/how-to-check-if-a-variable-is-set-in-bash
  while [ -z "${DISKO_MODULE+x}" ]; do
    case "${_LAYOUT}" in
    1)
      DISKO_MODULE=btrfs-subvolumes
      ;;
    2)
      DISKO_MODULE=luks-btrfs-subvolumes
      ;;
    3)
      DISKO_MODULE=simple-efi
      ;;
    4)
      DISKO_MODULE=zfs-encrypted
      ;;
    5)
      DISKO_MODULE=zfs
      ;;
    *)
      read -rp "Invalid input. Enter the number of the partition layout you want to use: " _LAYOUT
      ;;
    esac
  done

  while [ -z "${_VALID_DISK+x}" ]; do
    read -rp 'Specify the disk you want to use, eg. "nvme0n1": ' DISK
    # Disk identifiers should at least be 3 characters long and be present in our system
    # this does not prevent all possible errors (eg. nvme0 would be valid) but good enough for now
    if [ ${#DISK} -gt 2 ] && lsblk | grep "$DISK"; then
      _VALID_DISK=1
    else
      echo "The disk you entered is invalid! Try again."
    fi
  done

  # Ask whether the hard drive should really be wiped
  echo "The disk you chose to format is $DISK."
  confirm_choices "This will start the wiping process!"

  # Create partitions and set up /mnt
  disko_runner ./nixos/modules/disko/"$DISKO_MODULE".nix /dev/"$DISK"
}

# Create initial configuration
create_config() {
  NIX_ROOT=/mnt/etc/nixos
  read -rp "Enter the hostname you want to use: " HOSTNAME
  read -rp "Enter your desired username: " USER
  [ -d /sys/firmware/efi ] && SYSTEM_TYPE=systemd-boot || SYSTEM_TYPE=grub

  # Create config without filesystems as disko provides those already
  # also apply our dr460nixed template
  nixos-generate-config --no-filesystems --root /mnt
  pushd "$NIX_ROOT" || exit 2
  nix flake init --template "$WORK_DIR"#dr460nixed

  mv ./hardware-configuration.nix ./nixos/example-host
  rm ./configuration.nix # we are using flakes, no need for that anymore
  mv ./nixos/example-host ./nixos/"$HOSTNAME"
  mv ./nixos/"$HOSTNAME"/example-host.nix ./nixos/"$HOSTNAME"/"$HOSTNAME".nix

  sed -i s/example-boot/"$SYSTEM_TYPE"/g ./nixos/"$HOSTNAME"/"$HOSTNAME".nix
  sed -i s/example-disk/"$DISK"/g .{/nixos/flake-module.nix,nixos/"$HOSTNAME"/"$HOSTNAME".nix}
  sed -i s/example-hostname/"$HOSTNAME"/g {./nixos/flake-module.nix,nixos/"$HOSTNAME"/"$HOSTNAME".nix}
  sed -i s/example-layout/"$DISKO_MODULE"/g ./nixos/flake-module.nix
  sed -i s/example-user/"$USER"/g ./nixos/modules/users.nix

  echo "Configuration successfully created.
You made the following choices:
hostname: $HOSTNAME
user: $USER"
  confirm_choices "This starts the installation process."

  popd || exit 2
}

# Install basic dr460nixed system
install_system() {
  nixos-install --flake "$NIX_ROOT#$HOSTNAME" --verbose
}

# Notices
finish() {
  echo "The installation finished successfully. You may now reboot into your new system."
  confirm_choices "This will remove the temporary directory an reboot the system."
  umount -Rf /mnt
  rm -rf "$WORK_DIR"
}

# Actually execute our functions
prepare
disko
create_config
install_system
finish