Skip to content

Commit 0a26df3

Browse files
authored
fix: rewrite nixos-setup as flat minimal install/rescue script
1 parent 505eb55 commit 0a26df3

1 file changed

Lines changed: 58 additions & 138 deletions

File tree

nixos-setup.sh

Lines changed: 58 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -3,187 +3,107 @@
33
set -euxo pipefail
44
shopt -s inherit_errexit 2>/dev/null || true
55

6-
readonly SCRIPT_NAME="$(basename "$0")"
7-
readonly REQUIRED_CMDS=(parted mkfs.vfat mkfs.btrfs btrfs nixos-generate-config nixos-install nixos-enter)
8-
9-
DISK=""
10-
MODE=""
6+
DISK="$1"
7+
MODE="$2"
118
BOOT_PART=""
129
ROOT_PART=""
10+
MOUNTED=0
1311

1412
cleanup() {
15-
local code=$?
13+
[[ $MOUNTED -eq 1 ]] || return 0
1614
swapoff /mnt/var/swapfile 2>/dev/null || true
1715
umount -R /mnt 2>/dev/null || true
18-
[[ $code -ne 0 ]] && echo "Script exited with code $code. Verify mounts manually if needed." >&2
1916
}
2017
trap cleanup EXIT
2118

22-
usage() {
23-
echo "Usage: $SCRIPT_NAME <BLOCK_DEVICE> <install|rescue>"
24-
echo " BLOCK_DEVICE Target disk (e.g., /dev/nvme0n1, /dev/sda)"
25-
echo " MODE 'install' for fresh setup, 'rescue' to chroot"
26-
exit 1
27-
}
28-
29-
check_dependencies() {
30-
for cmd in "${REQUIRED_CMDS[@]}"; do
31-
command -v "$cmd" &>/dev/null || { echo "Missing required command: $cmd" >&2; exit 1; }
32-
done
33-
}
34-
35-
check_root() {
36-
[[ $EUID -ne 0 ]] && { echo "This script must be run as root." >&2; exit 1; }
37-
}
38-
39-
set_partition_names() {
40-
local disk="$1"
41-
if [[ "$disk" =~ (nvme|mmcblk)[0-9] ]]; then
42-
BOOT_PART="${disk}p1"
43-
ROOT_PART="${disk}p2"
44-
else
45-
BOOT_PART="${disk}1"
46-
ROOT_PART="${disk}2"
47-
fi
48-
}
19+
[[ $EUID -ne 0 ]] && { echo "must be root" >&2; exit 1; }
20+
[[ $# -ne 2 ]] && { echo "usage: $0 <disk> <install|rescue>" >&2; exit 1; }
21+
[[ ! -b "$DISK" ]] && { echo "not a block device: $DISK" >&2; exit 1; }
22+
[[ "$MODE" != "install" && "$MODE" != "rescue" ]] && { echo "mode must be install or rescue" >&2; exit 1; }
4923

50-
parse_args() {
51-
[[ $# -lt 2 ]] && usage
52-
DISK="$1"
53-
MODE="$2"
24+
if [[ "$DISK" =~ (nvme|mmcblk)[0-9] ]]; then
25+
BOOT_PART="${DISK}p1"
26+
ROOT_PART="${DISK}p2"
27+
else
28+
BOOT_PART="${DISK}1"
29+
ROOT_PART="${DISK}2"
30+
fi
5431

55-
[[ ! -b "$DISK" ]] && { echo "'$DISK' is not a valid block device." >&2; exit 1; }
32+
# safety checks
33+
root_disk=$(lsblk -ndo PKNAME "$(findmnt -n -o SOURCE /)" 2>/dev/null || true)
34+
[[ "/dev/$root_disk" == "$DISK" ]] && { echo "refusing to operate on booted disk" >&2; exit 1; }
35+
lsblk -n -o MOUNTPOINTS "$DISK" | grep -qE '\S' && { echo "disk has active mounts" >&2; exit 1; }
5636

57-
if [[ "$DISK" =~ nvme[0-9]+n[0-9]+p[0-9]+$ ]] || \
58-
[[ "$DISK" =~ mmcblk[0-9]+p[0-9]+$ ]] || \
59-
[[ "$DISK" =~ [a-z][0-9]+$ && ! "$DISK" =~ nvme && ! "$DISK" =~ mmcblk ]]; then
60-
echo "Specify the base disk (e.g., /dev/nvme0n1, /dev/sda), not a partition." >&2
61-
exit 1
62-
fi
37+
if [[ "$MODE" == "rescue" ]]; then
38+
[[ ! -b "$BOOT_PART" || ! -b "$ROOT_PART" ]] && { echo "rescue requires existing partitions" >&2; exit 1; }
39+
fi
6340

64-
[[ "$MODE" != "install" && "$MODE" != "rescue" ]] && { echo "Mode must be 'install' or 'rescue'." >&2; exit 1; }
41+
read -r -p "wipe $DISK and $MODE? type yes: " confirm
42+
[[ "$confirm" != "yes" ]] && exit 0
6543

66-
set_partition_names "$DISK"
44+
mount_subvolumes() {
45+
mount -o subvol=@ "$ROOT_PART" /mnt
46+
MOUNTED=1
47+
mkdir -p /mnt/{home,nix,var,boot}
48+
mount -o subvol=@home "$ROOT_PART" /mnt/home
49+
mount -o subvol=@nix "$ROOT_PART" /mnt/nix
50+
mount -o subvol=@var "$ROOT_PART" /mnt/var
51+
mount "$BOOT_PART" /mnt/boot
6752
}
6853

69-
validate() {
70-
local root_src root_disk
71-
root_src=$(findmnt -n -o SOURCE / 2>/dev/null || echo "")
72-
if [[ -n "$root_src" ]]; then
73-
root_disk=$(lsblk -ndo PKNAME "$root_src" 2>/dev/null || echo "")
74-
[[ "/dev/$root_disk" == "$DISK" ]] && { echo "Refusing to operate on the currently booted disk: $DISK" >&2; exit 1; }
75-
fi
76-
77-
if lsblk -n -o MOUNTPOINTS "$DISK" | grep -qE '\S'; then
78-
echo "Disk '$DISK' or its partitions are mounted. Unmount them first." >&2
79-
exit 1
80-
fi
81-
82-
if [[ "$MODE" == "rescue" ]]; then
83-
[[ ! -b "$BOOT_PART" || ! -b "$ROOT_PART" ]] && { echo "Rescue mode requires existing partitions: $BOOT_PART and $ROOT_PART" >&2; exit 1; }
84-
else
85-
lsblk -n "$DISK" | grep -q "part" && echo "WARNING: '$DISK' contains partitions. ALL DATA WILL BE DESTROYED." >&2
86-
fi
87-
88-
local prompt
89-
if [[ "$MODE" == "install" ]]; then
90-
prompt="This will WIPE '$DISK' and install NixOS. Type 'yes' to continue: "
91-
else
92-
prompt="Proceed with '$MODE' on '$DISK'? Type 'yes' to continue: "
93-
fi
94-
95-
read -r -p "$prompt" confirm
96-
[[ "$confirm" != "yes" ]] && { echo "Aborted."; exit 0; }
97-
}
54+
if [[ "$MODE" == "install" ]]; then
55+
for cmd in parted mkfs.vfat mkfs.btrfs btrfs nixos-generate-config nixos-install; do
56+
command -v "$cmd" &>/dev/null || { echo "missing: $cmd" >&2; exit 1; }
57+
done
9858

99-
partition_and_format() {
100-
echo "Partitioning $DISK..."
10159
parted "$DISK" --script -- \
10260
mklabel gpt \
10361
mkpart ESP fat32 1MiB 513MiB \
10462
set 1 esp on \
105-
mkpart primary 513MiB 100% || { echo "Partitioning failed." >&2; exit 1; }
63+
mkpart primary 513MiB 100%
10664

107-
partprobe "$DISK" 2>/dev/null || udevadm settle
65+
partprobe "$DISK" 2>/dev/null || true
66+
udevadm settle
10867

109-
echo "Formatting partitions..."
110-
mkfs.vfat -F32 -n "NIX-BOOT" "$BOOT_PART" || { echo "Boot format failed." >&2; exit 1; }
111-
mkfs.btrfs -f -L "nix-root" "$ROOT_PART" || { echo "Root format failed." >&2; exit 1; }
112-
}
68+
mkfs.vfat -F32 -n "NIX-BOOT" "$BOOT_PART"
69+
mkfs.btrfs -f -L "nix-root" "$ROOT_PART"
11370

114-
create_subvolumes() {
115-
echo "Creating Btrfs subvolumes..."
11671
mount "$ROOT_PART" /mnt
11772
btrfs subvolume create /mnt/@
11873
btrfs subvolume create /mnt/@home
11974
btrfs subvolume create /mnt/@nix
12075
btrfs subvolume create /mnt/@var
12176
umount /mnt
122-
}
12377

124-
mount_subvolumes() {
125-
echo "Mounting filesystems..."
126-
mount -o subvol=@ "$ROOT_PART" /mnt
127-
mkdir -p /mnt/{home,nix,var,boot}
128-
mount -o subvol=@home "$ROOT_PART" /mnt/home
129-
mount -o subvol=@nix "$ROOT_PART" /mnt/nix
130-
mount -o subvol=@var "$ROOT_PART" /mnt/var
131-
mount "$BOOT_PART" /mnt/boot
132-
}
78+
mount_subvolumes
13379

134-
setup_swap() {
135-
echo "Creating swapfile..."
13680
if btrfs filesystem mkswapfile --size 7G /mnt/var/swapfile 2>/dev/null; then
13781
:
13882
else
139-
echo "btrfs mkswapfile unavailable, falling back to manual method." >&2
14083
truncate -s 0 /mnt/var/swapfile
14184
chattr +C /mnt/var/swapfile 2>/dev/null || true
142-
fallocate -l 7G /mnt/var/swapfile || dd if=/dev/zero of=/mnt/var/swapfile bs=1M count=7168 status=progress
143-
mkswap /mnt/var/swapfile || { echo "mkswap failed." >&2; exit 1; }
85+
dd if=/dev/zero of=/mnt/var/swapfile bs=1M count=7168 status=progress
86+
mkswap /mnt/var/swapfile
14487
fi
14588
chmod 600 /mnt/var/swapfile
146-
swapon /mnt/var/swapfile || echo "Swap activation failed, continuing without swap." >&2
147-
}
89+
swapon /mnt/var/swapfile || true
14890

149-
run_install() {
150-
partition_and_format
151-
create_subvolumes
152-
mount_subvolumes
153-
setup_swap
91+
nixos-generate-config --root /mnt
15492

155-
echo "Generating NixOS configuration..."
156-
nixos-generate-config --root /mnt || { echo "Config generation failed." >&2; exit 1; }
157-
158-
echo "Installing NixOS..."
15993
if [[ -f flake.nix ]]; then
160-
local flake_host
161-
flake_host=$(grep -oP '(?<=hostName = ").*(?=")' /mnt/etc/nixos/configuration.nix 2>/dev/null | head -1 || echo "")
162-
[[ -z "$flake_host" ]] && { echo "Could not detect hostname, defaulting flake target to 'nixos'." >&2; flake_host="nixos"; }
163-
nixos-install --flake ".#${flake_host}" --no-root-passwd || { echo "Flake installation failed." >&2; exit 1; }
94+
flake_host=$(grep -oP '(?<=hostName = ").*(?=")' /mnt/etc/nixos/hardware-configuration.nix 2>/dev/null | head -1 || echo "nixos")
95+
[[ -z "$flake_host" ]] && flake_host="nixos"
96+
nixos-install --flake ".#${flake_host}" --no-root-passwd
16497
else
165-
nixos-install --no-root-passwd || { echo "Installation failed." >&2; exit 1; }
98+
nixos-install --no-root-passwd
16699
fi
167-
echo "Installation complete. Reboot when ready."
168-
}
169100

170-
run_rescue() {
171-
mount_subvolumes
172-
[[ -f /mnt/var/swapfile ]] && { swapon /mnt/var/swapfile 2>/dev/null || echo "Swapfile found but failed to activate." >&2; }
173-
echo "Launching nixos-enter. Type 'exit' to return to host."
174-
nixos-enter || { echo "nixos-enter failed." >&2; exit 1; }
175-
}
176-
177-
main() {
178-
check_root
179-
check_dependencies
180-
parse_args "$@"
181-
validate
182-
183-
case "$MODE" in
184-
install) run_install ;;
185-
rescue) run_rescue ;;
186-
esac
187-
}
101+
else
102+
for cmd in btrfs nixos-enter; do
103+
command -v "$cmd" &>/dev/null || { echo "missing: $cmd" >&2; exit 1; }
104+
done
188105

189-
main "$@"
106+
mount_subvolumes
107+
swapon /mnt/var/swapfile 2>/dev/null || true
108+
nixos-enter
109+
fi

0 commit comments

Comments
 (0)