Improve installer VM compatibility
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
This commit is contained in:
co-authored by
arena-agent
parent
f39f59fb81
commit
5188cca9aa
@@ -12,6 +12,11 @@ Options:
|
||||
--deploy-key "ssh-ed25519 AAAA..." SSH pubkey for remote access after install
|
||||
--headscale-server URL Headscale login server for post-install Tailnet
|
||||
--headscale-key KEY Headscale pre-auth key for the installed OS
|
||||
|
||||
VM notes:
|
||||
Desktop test installs still need a 256 GB OS disk (thin-provisioned is OK).
|
||||
Node/server installs need a separate 2 TB data disk. UEFI is preferred; UEFI
|
||||
VMs avoid NVRAM boot-entry writes, and legacy BIOS VMs use GRUB.
|
||||
USAGE
|
||||
}
|
||||
|
||||
@@ -25,6 +30,8 @@ DEPLOY_KEY=""
|
||||
HEADSCALE_SERVER=""
|
||||
HEADSCALE_KEY=""
|
||||
DATA_DISK_HAS_TIMECHAIN=false
|
||||
BOOT_MODE=""
|
||||
VIRTUALIZATION=""
|
||||
|
||||
FLAKE="/etc/sovran/flake"
|
||||
LOG="/tmp/sovran-headless-install.log"
|
||||
@@ -69,6 +76,22 @@ case "$ROLE" in
|
||||
*) die "--role must be one of: server, desktop, node" ;;
|
||||
esac
|
||||
|
||||
# ── Detect firmware / VM environment ─────────────────────────────────────────
|
||||
if [[ -d /sys/firmware/efi ]]; then
|
||||
BOOT_MODE="uefi"
|
||||
else
|
||||
BOOT_MODE="bios"
|
||||
fi
|
||||
|
||||
if command -v systemd-detect-virt >/dev/null 2>&1; then
|
||||
if VIRT_RESULT=$(systemd-detect-virt --vm 2>/dev/null); then
|
||||
[[ "$VIRT_RESULT" != "none" ]] && VIRTUALIZATION="$VIRT_RESULT"
|
||||
fi
|
||||
fi
|
||||
|
||||
log "Boot mode: ${BOOT_MODE} ($([[ "$BOOT_MODE" == uefi ]] && echo systemd-boot || echo GRUB))"
|
||||
[[ -n "$VIRTUALIZATION" ]] && log "Virtual machine detected: ${VIRTUALIZATION}"
|
||||
|
||||
# ── Validate disk existence and size ─────────────────────────────────────────
|
||||
log "=== Validating disks ==="
|
||||
|
||||
@@ -96,13 +119,26 @@ fi
|
||||
# ── Helper: partition suffix ──────────────────────────────────────────────────
|
||||
part_suffix() {
|
||||
local dev="$1" n="$2"
|
||||
if [[ "$dev" == *nvme* ]]; then
|
||||
local base
|
||||
base=$(basename "$dev")
|
||||
if [[ "$base" == nvme* || "$base" == mmcblk* || "$base" == loop* || "$base" == md* || "$base" =~ [0-9]$ ]]; then
|
||||
echo "${dev}p${n}"
|
||||
else
|
||||
echo "${dev}${n}"
|
||||
fi
|
||||
}
|
||||
|
||||
nix_string() {
|
||||
local value="$1"
|
||||
value="${value//\\/\\\\}"
|
||||
value="${value//\"/\\\"}"
|
||||
value="${value//$'\n'/\\n}"
|
||||
value="${value//$'\r'/\\r}"
|
||||
value="${value//$'\t'/\\t}"
|
||||
value="${value//\$\{/\\\$\{}"
|
||||
printf '"%s"' "$value"
|
||||
}
|
||||
|
||||
# ── Detect existing Bitcoin timechain data on data disk ───────────────────────
|
||||
if [[ -n "$DATA_DISK" ]]; then
|
||||
DATA_P1=$(part_suffix "$DATA_DISK" 1)
|
||||
@@ -142,12 +178,19 @@ partprobe "$DISK"
|
||||
sleep 2
|
||||
|
||||
# ── Step 2: Partition OS disk ─────────────────────────────────────────────────
|
||||
log "=== Partitioning OS disk ==="
|
||||
|
||||
sgdisk \
|
||||
-n "1:1M:+512M" -t "1:EF00" -c "1:ESP" \
|
||||
-n "2:0:0" -t "2:8300" -c "2:root" \
|
||||
"$DISK"
|
||||
if [[ "$BOOT_MODE" == "uefi" ]]; then
|
||||
log "=== Partitioning OS disk (UEFI) ==="
|
||||
sgdisk \
|
||||
-n "1:1M:+512M" -t "1:EF00" -c "1:ESP" \
|
||||
-n "2:0:0" -t "2:8300" -c "2:root" \
|
||||
"$DISK"
|
||||
else
|
||||
log "=== Partitioning OS disk (Legacy BIOS) ==="
|
||||
sgdisk \
|
||||
-n "1:1M:+1M" -t "1:EF02" -c "1:BIOS-boot" \
|
||||
-n "2:0:0" -t "2:8300" -c "2:root" \
|
||||
"$DISK"
|
||||
fi
|
||||
|
||||
partprobe "$DISK"
|
||||
sleep 2
|
||||
@@ -168,7 +211,11 @@ log "=== Formatting partitions ==="
|
||||
BOOT_P1=$(part_suffix "$DISK" 1)
|
||||
BOOT_P2=$(part_suffix "$DISK" 2)
|
||||
|
||||
mkfs.vfat -F 32 "$BOOT_P1"
|
||||
if [[ "$BOOT_MODE" == "uefi" ]]; then
|
||||
mkfs.vfat -F 32 "$BOOT_P1"
|
||||
else
|
||||
log "Skipping ESP format for Legacy BIOS install"
|
||||
fi
|
||||
mkfs.ext4 -F -L sovran_systemsos "$BOOT_P2"
|
||||
|
||||
if [[ -n "$DATA_DISK" && "$DATA_DISK_HAS_TIMECHAIN" != true ]]; then
|
||||
@@ -180,8 +227,12 @@ fi
|
||||
log "=== Mounting filesystems ==="
|
||||
|
||||
mount "$BOOT_P2" /mnt
|
||||
mkdir -p /mnt/boot/efi
|
||||
mount -o umask=0077,defaults "$BOOT_P1" /mnt/boot/efi
|
||||
if [[ "$BOOT_MODE" == "uefi" ]]; then
|
||||
mkdir -p /mnt/boot/efi
|
||||
mount -o umask=0077,defaults "$BOOT_P1" /mnt/boot/efi
|
||||
else
|
||||
log "Legacy BIOS install: /boot/efi mount not required"
|
||||
fi
|
||||
|
||||
if [[ -n "$DATA_DISK" ]]; then
|
||||
DATA_P1=$(part_suffix "$DATA_DISK" 1)
|
||||
@@ -219,16 +270,41 @@ case "$ROLE" in
|
||||
IS_SERVER=false; IS_DESKTOP=false; IS_NODE=true ;;
|
||||
esac
|
||||
|
||||
cat > /mnt/etc/nixos/role-state.nix <<EOF
|
||||
{
|
||||
cat <<EOF
|
||||
# THIS FILE IS AUTO-GENERATED BY THE INSTALLER. DO NOT EDIT.
|
||||
{ config, lib, ... }:
|
||||
{
|
||||
sovran_systemsOS.roles.server_plus_desktop = lib.mkDefault ${IS_SERVER};
|
||||
sovran_systemsOS.roles.desktop = lib.mkDefault ${IS_DESKTOP};
|
||||
sovran_systemsOS.roles.node = lib.mkDefault ${IS_NODE};
|
||||
}
|
||||
EOF
|
||||
|
||||
if [[ "$BOOT_MODE" == "bios" ]]; then
|
||||
GRUB_DEVICE=$(nix_string "$DISK")
|
||||
cat <<EOF
|
||||
|
||||
# The installer ISO was booted in Legacy BIOS mode, so install GRUB to the
|
||||
# target disk instead of using the default UEFI systemd-boot configuration.
|
||||
boot.loader.systemd-boot.enable = lib.mkForce false;
|
||||
boot.loader.efi.canTouchEfiVariables = lib.mkForce false;
|
||||
boot.loader.grub.enable = lib.mkForce true;
|
||||
boot.loader.grub.device = lib.mkForce ${GRUB_DEVICE};
|
||||
fileSystems."/boot/efi".enable = lib.mkForce false;
|
||||
EOF
|
||||
elif [[ -n "$VIRTUALIZATION" ]]; then
|
||||
cat <<EOF
|
||||
|
||||
# VM UEFI firmware can reject or forget NVRAM boot-entry writes. Keep the
|
||||
# normal UEFI systemd-boot layout, but use the fallback removable path instead
|
||||
# of depending on EFI variable updates.
|
||||
boot.loader.efi.canTouchEfiVariables = lib.mkForce false;
|
||||
EOF
|
||||
fi
|
||||
|
||||
echo "}"
|
||||
} > /mnt/etc/nixos/role-state.nix
|
||||
|
||||
# ── Step 10: Write custom.nix with deploy config ──────────────────────────────
|
||||
log "=== Writing custom.nix ==="
|
||||
|
||||
|
||||
Reference in New Issue
Block a user