From cd49f479ddff1c463b8bee8fd58683a7fdc3b5be Mon Sep 17 00:00:00 2001 From: randogoth Date: Sun, 1 Feb 2026 20:43:53 +0200 Subject: [PATCH] Simplify installer script to non-interactive flow --- docs/install-help.txt | 13 ++- scripts/install-btrfs.sh | 217 ++++----------------------------------- 2 files changed, 27 insertions(+), 203 deletions(-) mode change 100755 => 100644 scripts/install-btrfs.sh diff --git a/docs/install-help.txt b/docs/install-help.txt index c3f4fc8..dfe9c4f 100644 --- a/docs/install-help.txt +++ b/docs/install-help.txt @@ -1,17 +1,16 @@ NixOS installer (flake + Lix) ============================= -1) Build is prewired with Lix; the installer ISO includes the repo. -2) Run the guided Btrfs installer: +1) Build is prewired with Lix; the installer ISO includes the repo at /etc/nixos. +2) Run the non-interactive Btrfs installer (set envs as needed): - sudo ./scripts/install-btrfs.sh + sudo DISK=/dev/vda HOSTNAME=nixos /etc/nixos/scripts/install-btrfs.sh - - Interactive by default (choose disk, LUKS, swap). - - Non-interactive example: - sudo NON_INTERACTIVE=1 USE_LUKS=1 LUKS_PASSPHRASE='secret' SWAP_GB=4 DISK=/dev/sda HOSTNAME=myhost ./scripts/install-btrfs.sh + Defaults: DISK=/dev/vda, HOSTNAME=nixos + The script wipes the disk, creates Btrfs subvolumes (root, home, nix), copies the flake, generates hardware config, and installs with the chosen host name. 3) After install finishes, reboot into the new system. Notes -- Filesystem is always Btrfs with subvolumes: root, home, nix (and swapfile if enabled). +- Filesystem is Btrfs with subvolumes: root, home, nix. - The flake lives under /etc/nixos on the target; edit hosts/.nix to customize. diff --git a/scripts/install-btrfs.sh b/scripts/install-btrfs.sh old mode 100755 new mode 100644 index f5c8cb1..9adf547 --- a/scripts/install-btrfs.sh +++ b/scripts/install-btrfs.sh @@ -1,220 +1,48 @@ #!/usr/bin/env bash set -euo pipefail -# Automated Btrfs install using the flake in this repo. -# Defaults remain environment-driven for headless use. -# Interactive prompts are shown unless --non-interactive is set. +# Non-interactive Btrfs installer using the flake in this repo. +# Defaults: DISK=/dev/vda HOSTNAME=nixos -NON_INTERACTIVE=0 -if [[ "${1:-}" == "--non-interactive" ]]; then - NON_INTERACTIVE=1 - shift -fi - -DISK=${DISK:-/dev/vda} # full-disk target -ROOT_PART=${ROOT_PART:-} # optional existing root partition -BOOT_PART=${BOOT_PART:-} # optional existing boot (FAT) partition -HOSTNAME=${HOSTNAME:-nanuqsaurus} -USE_LUKS=${USE_LUKS:-0} # 1 to encrypt root -SWAP_GB=${SWAP_GB:-0} # swap size in GB, 0 disables +DISK=${DISK:-/dev/vda} +HOSTNAME=${HOSTNAME:-nixos} SCRIPT_DIR=$(cd -- "$(dirname "${BASH_SOURCE[0]}")" && pwd) REPO_ROOT=$(cd -- "${SCRIPT_DIR}/.." && pwd) -has_cmd() { command -v "$1" >/dev/null 2>&1; } +echo "[1/7] Partitioning ${DISK}" +printf "label: gpt\n,550M,U\n,,L\n" | sfdisk "${DISK}" -prompt_select() { - local title="$1" prompt="$2" choices=("${@:3}") - if (( NON_INTERACTIVE )); then - echo "${choices[0]}" - return - fi - if has_cmd dialog; then - dialog --no-cancel --menu "$prompt" 15 60 6 "${choices[@]}" 2> /tmp/choice - cat /tmp/choice - elif has_cmd whiptail; then - whiptail --notags --menu "$prompt" 15 60 6 "${choices[@]}" 2> /tmp/choice || true - cat /tmp/choice - else - echo "$prompt" - select c in "${choices[@]}"; do echo "$c"; break; done - fi -} +echo "[2/7] Formatting" +mkfs.fat -F 32 "${DISK}1" +mkfs.btrfs -f "${DISK}2" -prompt_yes_no() { - local prompt="$1" default="${2:-n}" - if (( NON_INTERACTIVE )); then - [[ "$default" =~ ^[Yy]$ ]] && echo "yes" || echo "no" - return - fi - if has_cmd dialog; then - if dialog --yesno "$prompt" 8 60; then echo "yes"; else echo "no"; fi - elif has_cmd whiptail; then - if whiptail --yesno "$prompt" 8 60; then echo "yes"; else echo "no"; fi - else - read -rp "$prompt [y/N]: " ans - [[ "${ans:-$default}" =~ ^[Yy]$ ]] && echo "yes" || echo "no" - fi -} - -prompt_input() { - local prompt="$1" default="$2" - if (( NON_INTERACTIVE )); then - echo "$default" - return - fi - if has_cmd dialog; then - dialog --inputbox "$prompt" 8 60 "$default" 2>/tmp/input && cat /tmp/input || echo "$default" - elif has_cmd whiptail; then - whiptail --inputbox "$prompt" 8 60 "$default" 2>/tmp/input && cat /tmp/input || echo "$default" - else - read -rp "$prompt [$default]: " ans - echo "${ans:-$default}" - fi -} - -ls_disks() { - lsblk -dpno NAME,SIZE,TYPE | awk '$3=="disk"{print $1" "$2}' -} - -if (( ! NON_INTERACTIVE )); then - mapfile -t disks < <(ls_disks) - if ((${#disks[@]})); then - disk_choices=() - for d in "${disks[@]}"; do - disk_choices+=("$d" "") - done - DISK=$(prompt_select "disk" "Select target disk (will be wiped)" "${disk_choices[@]}") - DISK=${DISK%% *} # strip size suffix from selection - fi - - target_mode=$(prompt_select "mode" "Partitioning mode" \ - "full-disk" "Use entire disk (wipes!)" \ - "existing" "Use existing partitions") - - if [[ "$target_mode" == "existing" ]]; then - ROOT_PART=$(prompt_input "Root partition (will be formatted btrfs)" "${ROOT_PART:-/dev/vda2}") - BOOT_PART=$(prompt_input "Boot EFI partition (FAT32)" "${BOOT_PART:-/dev/vda1}") - fi - - USE_LUKS=$(prompt_yes_no "Encrypt root with LUKS?" "n") - [[ "$USE_LUKS" == "yes" ]] && USE_LUKS=1 || USE_LUKS=0 - - SWAP_GB=$(prompt_input "Swap size in GB (0 = none)" "${SWAP_GB}") -fi - -echo "[0/8] Summary:" -echo " Disk: ${DISK}" -if [[ -n "$ROOT_PART" ]]; then - echo " Root partition: $ROOT_PART" - echo " Boot partition: $BOOT_PART" -else - echo " Mode: full disk wipe" -fi -echo " LUKS: $([ "$USE_LUKS" -eq 1 ] && echo enabled || echo disabled)" -echo " Swap: ${SWAP_GB}G" -echo " Hostname: ${HOSTNAME}" - -if (( NON_INTERACTIVE )); then - echo "Proceeding in non-interactive mode." -else - if [[ "$(prompt_yes_no "Proceed with these settings? This will destroy data." "n")" != "yes" ]]; then - echo "Aborted." - exit 1 - fi -fi - -part_boot="" -part_root="" -mapper_root="" - -echo "[1/8] Partitioning/selection" -if [[ -z "$ROOT_PART" ]]; then - if [[ ! -b "$DISK" ]]; then - echo "Error: target disk ${DISK} not found. Available disks:" - ls_disks - exit 1 - fi - printf "label: gpt\n,550M,U,boot\n,,L,cryptroot\n" | sfdisk "${DISK}" - part_boot="${DISK}1" - part_root="${DISK}2" -else - part_boot="${BOOT_PART}" - part_root="${ROOT_PART}" -fi - -echo "[2/8] Formatting boot" -mkfs.fat -F 32 "${part_boot}" - -echo "[3/8] Preparing root" -if [[ "$USE_LUKS" -eq 1 ]]; then - pass=${LUKS_PASSPHRASE:-} - if [[ -z "$pass" && $NON_INTERACTIVE -eq 0 ]]; then - pass=$(prompt_input "LUKS passphrase" "") - fi - if [[ -z "$pass" ]]; then - echo "LUKS passphrase required for encrypted install" - exit 1 - fi - printf "%s" "$pass" | cryptsetup luksFormat "${part_root}" - - printf "%s" "$pass" | cryptsetup open "${part_root}" cryptroot - - mapper_root="/dev/mapper/cryptroot" -else - mapper_root="${part_root}" -fi - -mkfs.btrfs -f "${mapper_root}" - -echo "[4/8] Creating Btrfs subvolumes" +echo "[3/7] Creating Btrfs subvolumes" mkdir -p /mnt -mount "${mapper_root}" /mnt +mount "${DISK}2" /mnt btrfs subvolume create /mnt/root btrfs subvolume create /mnt/home btrfs subvolume create /mnt/nix umount /mnt -echo "[5/8] Mounting subvolumes" -mount -o compress=zstd,subvol=root "${mapper_root}" /mnt +echo "[4/7] Mounting subvolumes" +mount -o compress=zstd,subvol=root "${DISK}2" /mnt mkdir -p /mnt/{home,nix,boot} -mount -o compress=zstd,subvol=home "${mapper_root}" /mnt/home -mount -o compress=zstd,subvol=nix "${mapper_root}" /mnt/nix -mount "${part_boot}" /mnt/boot +mount -o compress=zstd,subvol=home "${DISK}2" /mnt/home +mount -o compress=zstd,subvol=nix "${DISK}2" /mnt/nix +mount "${DISK}1" /mnt/boot -if [[ "${SWAP_GB}" -gt 0 ]]; then - echo "[5b/8] Creating swapfile (${SWAP_GB}G)" - mkdir -p /mnt/swap - chattr +C /mnt/swap || true - fallocate -l "${SWAP_GB}G" /mnt/swap/swapfile - chmod 600 /mnt/swap/swapfile - mkswap /mnt/swap/swapfile - swapon /mnt/swap/swapfile -fi - -echo "[6/8] Copying flake to /etc/nixos" +echo "[5/7] Copying flake to /etc/nixos" +mkdir -p /mnt/etc/nixos if command -v rsync >/dev/null 2>&1; then rsync -a --exclude '.git' --exclude 'result' --exclude 'node_modules' "${REPO_ROOT}/" /mnt/etc/nixos/ else (cd "${REPO_ROOT}" && tar -cf - --exclude=.git --exclude=result --exclude=node_modules .) | (cd /mnt/etc/nixos && tar -xf -) fi -echo "[7/8] Generating hardware config" -hardware_file="/mnt/etc/nixos/hosts/${HOSTNAME}-hardware.nix" +echo "[6/7] Generating hardware config" mkdir -p /mnt/etc/nixos/hosts -nixos-generate-config --root /mnt --show-hardware-config > "${hardware_file}" - -if [[ "$USE_LUKS" -eq 1 || "${SWAP_GB}" -gt 0 ]]; then - tmpfile=$(mktemp) - # drop trailing closing brace - sed '$d' "${hardware_file}" > "${tmpfile}" - if [[ "$USE_LUKS" -eq 1 ]]; then - echo " boot.initrd.luks.devices.cryptroot.device = \"${part_root}\";" >> "${tmpfile}" - fi - if [[ "${SWAP_GB}" -gt 0 ]]; then - echo " swapDevices = [ { device = \"/swap/swapfile\"; } ];" >> "${tmpfile}" - fi - echo "}" >> "${tmpfile}" - mv "${tmpfile}" "${hardware_file}" -fi +nixos-generate-config --root /mnt --show-hardware-config > "/mnt/etc/nixos/hosts/${HOSTNAME}-hardware.nix" host_file="/mnt/etc/nixos/hosts/${HOSTNAME}.nix" if [ ! -e "${host_file}" ]; then @@ -226,9 +54,6 @@ if [ ! -e "${host_file}" ]; then inputs.lix-module.nixosModules.lixFromNixpkgs ../modules/system/base.nix ../modules/users/admin.nix - # Uncomment to enable Secure Boot after install: - # inputs.lanzaboote.nixosModules.lanzaboote - # ../modules/system/secure-boot.nix ./${HOSTNAME}-hardware.nix ]; @@ -237,7 +62,7 @@ if [ ! -e "${host_file}" ]; then EOF fi -echo "[8/8] Installing ${HOSTNAME} via flake" +echo "[7/7] Installing ${HOSTNAME} via flake" nixos-install --root /mnt --flake "/mnt/etc/nixos#${HOSTNAME}" echo "Install complete. You can reboot now."