Stage 4f cleanup. The flake moved from ~/dotfiles/nixos/ to ~/dotfiles/
in 88c5139; docs and install scripts hadn't been refreshed. Point all
rebuild / flake references at the new root:
- AGENTS.md, README.md, server-quickstart.md, docs/server-installer-usb.md,
docs/sunken-ship-wifi.md, nixos/readme.md — rebuild command paths.
- scripts/nixos-server-install.sh — auto-detect now looks for flake.nix
at repo root (was nixos/flake.nix).
- scripts/post-install-provision.sh — first-rebuild hint path.
`nixos/hosts/<host>-hardware.nix` and friends stay where they are —
host-specific NixOS modules still live under nixos/; only the flake
entry-points + sops/ + vars/ + lib/ + modules/ + flake-modules/ moved.
nixos/readme.md rewritten to reflect the split (flake at root, per-host
modules under nixos/).
201 lines
7 KiB
Bash
201 lines
7 KiB
Bash
#!/bin/bash
|
|
# Install NixOS with disko (LUKS + root) on a live system.
|
|
# Prompts for hostname and target disk, then provisions the installed system
|
|
# (clones dotfiles, installs SSH key, generates hardware config).
|
|
#
|
|
# Usage (from repo root, e.g. /tmp/dotfiles):
|
|
# sudo ./scripts/nixos-server-install.sh
|
|
#
|
|
# Environment variables (all optional):
|
|
# INSTALLER_HOSTNAME — skip hostname prompt
|
|
# INSTALLER_DISK — skip disk prompt (validated as block device)
|
|
# SSH_PUBKEY_FILE — path to .pub file; installed to danny's authorized_keys
|
|
# FLAKE_REF — override flake reference (default: auto-detect from repo)
|
|
# INSTALLER_SYSTEM_CONFIG_FILE — JSON file merged into --system-config
|
|
set -euo pipefail
|
|
|
|
FLAKE_REF="${FLAKE_REF:-}"
|
|
if [[ -z "$FLAKE_REF" ]]; then
|
|
if [[ -f "$(dirname "$0")/../flake.nix" ]]; then
|
|
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
FLAKE_REF="path:${REPO_ROOT}"
|
|
else
|
|
echo "FLAKE_REF not set and not running from dotfiles repo. Example:"
|
|
echo " export FLAKE_REF=github:USER/REPO # or path:/path/to/dotfiles"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
if [[ "$EUID" -ne 0 ]]; then
|
|
echo "Run as root (e.g. sudo $0)"
|
|
exit 1
|
|
fi
|
|
|
|
# --- Hostname ---
|
|
hostname="${INSTALLER_HOSTNAME:-}"
|
|
if [[ -z "$hostname" ]]; then
|
|
read -r -p "Hostname (e.g. phantom-ship): " hostname
|
|
fi
|
|
if [[ -z "$hostname" ]]; then
|
|
echo "Hostname cannot be empty."
|
|
exit 1
|
|
fi
|
|
|
|
# --- Target disk ---
|
|
disk="${INSTALLER_DISK:-}"
|
|
if [[ -z "$disk" ]]; then
|
|
read -r -p "Target disk [default: /dev/sda]: " disk
|
|
disk="${disk:-/dev/sda}"
|
|
fi
|
|
if [[ ! -b "$disk" ]]; then
|
|
echo "Not a block device: $disk"
|
|
exit 1
|
|
fi
|
|
|
|
# --- System config (hostname + optional extras) ---
|
|
if [[ -n "${INSTALLER_SYSTEM_CONFIG_FILE:-}" ]] && [[ -f "$INSTALLER_SYSTEM_CONFIG_FILE" ]]; then
|
|
if command -v jq &>/dev/null; then
|
|
SYSTEM_CONFIG=$(jq --arg h "$hostname" '.networking.hostName = $h' "$INSTALLER_SYSTEM_CONFIG_FILE")
|
|
else
|
|
SYSTEM_CONFIG=$(cat "$INSTALLER_SYSTEM_CONFIG_FILE")
|
|
echo "Warning: jq not found, using file as-is (hostname may not match)."
|
|
fi
|
|
else
|
|
SYSTEM_CONFIG='{"networking":{"hostName":"'"$hostname"'"}}'
|
|
fi
|
|
|
|
# --- Optional: danny password ---
|
|
danny_pass=""
|
|
read -r -p "Set a password for user danny? [y/N] " set_pass
|
|
if [[ "${set_pass,,}" == "y" || "${set_pass,,}" == "yes" ]]; then
|
|
read -s -r -p "Password for danny: " danny_pass
|
|
echo
|
|
read -s -r -p "Confirm password: " danny_pass2
|
|
echo
|
|
if [[ "$danny_pass" != "$danny_pass2" ]]; then
|
|
echo "Passwords do not match. Aborted."
|
|
exit 1
|
|
fi
|
|
if [[ -z "$danny_pass" ]]; then
|
|
echo "Password cannot be empty. Aborted."
|
|
exit 1
|
|
fi
|
|
HASH=$(echo -n "$danny_pass" | openssl passwd -6 -stdin 2>/dev/null) || HASH=$(mkpasswd -6 -m sha-512 "$danny_pass" 2>/dev/null) || true
|
|
if [[ -n "${HASH:-}" ]]; then
|
|
if command -v jq &>/dev/null; then
|
|
SYSTEM_CONFIG=$(echo "$SYSTEM_CONFIG" | jq --arg h "$HASH" '. + {"users":{"users":{"danny":{"hashedPassword":$h}}}}')
|
|
else
|
|
NEW_CONFIG=$(echo "$SYSTEM_CONFIG" | nix run nixpkgs#jq -- --arg h "$HASH" '. + {"users":{"users":{"danny":{"hashedPassword":$h}}}}' 2>/dev/null)
|
|
[[ -n "$NEW_CONFIG" ]] && SYSTEM_CONFIG="$NEW_CONFIG" || echo "Could not merge password. Set after boot: passwd danny"
|
|
fi
|
|
echo "Password will be set for danny."
|
|
else
|
|
echo "Could not hash password (need openssl or mkpasswd). Set after boot: passwd danny"
|
|
fi
|
|
fi
|
|
|
|
# --- Confirm and install ---
|
|
echo ""
|
|
echo "=== Install Summary ==="
|
|
echo "Flake: ${FLAKE_REF}#server-install"
|
|
echo "Disk: $disk"
|
|
echo "Hostname: $hostname"
|
|
echo "SSH pubkey: ${SSH_PUBKEY_FILE:-none}"
|
|
echo "System config: $SYSTEM_CONFIG"
|
|
read -r -p "Proceed? [y/N] " confirm
|
|
if [[ "${confirm,,}" != "y" && "${confirm,,}" != "yes" ]]; then
|
|
echo "Aborted."
|
|
exit 0
|
|
fi
|
|
|
|
nix run --extra-experimental-features "nix-command flakes" \
|
|
github:nix-community/disko/latest#disko-install -- \
|
|
--flake "${FLAKE_REF}#server-install" \
|
|
--disk main "$disk" \
|
|
--system-config "$SYSTEM_CONFIG"
|
|
|
|
echo ""
|
|
echo "=== Post-install provisioning ==="
|
|
echo "Re-opening LUKS to provision the installed system..."
|
|
read -s -r -p "LUKS passphrase: " luks_pass
|
|
echo
|
|
|
|
LUKS_DEV="/dev/disk/by-partlabel/disk-main-luks"
|
|
ESP_DEV="/dev/disk/by-partlabel/disk-main-ESP"
|
|
if [[ ! -b "$LUKS_DEV" ]]; then
|
|
LUKS_DEV="${disk}2"
|
|
ESP_DEV="${disk}1"
|
|
fi
|
|
|
|
if [[ ! -b "$LUKS_DEV" ]]; then
|
|
echo "Could not find LUKS partition. Complete these steps manually after boot:"
|
|
echo " 1. Clone dotfiles: sudo git clone ... /etc/dotfiles"
|
|
echo " 2. Add SSH key: mkdir -p ~/.ssh && cat /tmp/key.pub >> ~/.ssh/authorized_keys"
|
|
echo " 3. Generate hardware config: nixos-generate-config --show-hardware-config > /etc/dotfiles/nixos/hosts/${hostname}-hardware.nix"
|
|
exit 0
|
|
fi
|
|
|
|
if [[ -e /dev/mapper/crypted ]]; then
|
|
echo " [ok] LUKS device already open (left open by disko-install)"
|
|
unset luks_pass
|
|
elif ! echo -n "$luks_pass" | cryptsetup open "$LUKS_DEV" crypted --key-file -; then
|
|
echo "Wrong LUKS passphrase. Complete provisioning manually after boot."
|
|
unset luks_pass
|
|
exit 0
|
|
else
|
|
unset luks_pass
|
|
fi
|
|
|
|
mount /dev/mapper/crypted /mnt
|
|
[[ -b "$ESP_DEV" ]] && mount "$ESP_DEV" /mnt/boot
|
|
mount --bind /dev /mnt/dev
|
|
mount --bind /proc /mnt/proc
|
|
mount --bind /sys /mnt/sys
|
|
|
|
# 1. Set danny password (belt-and-suspenders; Nix merge can fail)
|
|
if [[ -n "$danny_pass" ]]; then
|
|
echo "danny:${danny_pass}" | chroot /mnt chpasswd
|
|
echo " [ok] danny password set"
|
|
fi
|
|
unset danny_pass
|
|
|
|
# 2. Clone dotfiles
|
|
if [[ ! -d /mnt/etc/dotfiles ]]; then
|
|
chroot /mnt nix run --extra-experimental-features "nix-command flakes" nixpkgs#git -- \
|
|
clone https://github.com/DannyDannyDanny/dotfiles.git /etc/dotfiles
|
|
echo " [ok] dotfiles cloned to /etc/dotfiles"
|
|
else
|
|
echo " [skip] /etc/dotfiles already exists"
|
|
fi
|
|
|
|
# 3. Install SSH public key
|
|
if [[ -n "${SSH_PUBKEY_FILE:-}" ]] && [[ -f "$SSH_PUBKEY_FILE" ]]; then
|
|
mkdir -p /mnt/home/danny/.ssh
|
|
cat "$SSH_PUBKEY_FILE" >> /mnt/home/danny/.ssh/authorized_keys
|
|
chmod 700 /mnt/home/danny/.ssh
|
|
chmod 600 /mnt/home/danny/.ssh/authorized_keys
|
|
chroot /mnt chown -R danny:users /home/danny/.ssh
|
|
echo " [ok] SSH public key installed"
|
|
elif [[ -n "${SSH_PUBKEY_FILE:-}" ]]; then
|
|
echo " [warn] SSH_PUBKEY_FILE set but file not found: $SSH_PUBKEY_FILE"
|
|
fi
|
|
|
|
# 4. Generate hardware config
|
|
HW_CONFIG="/mnt/etc/dotfiles/nixos/hosts/${hostname}-hardware.nix"
|
|
if nixos-generate-config --show-hardware-config --root /mnt > "$HW_CONFIG" 2>/dev/null; then
|
|
echo " [ok] hardware config saved to hosts/${hostname}-hardware.nix"
|
|
echo " NOTE: Commit this file to the repo after first boot."
|
|
else
|
|
echo " [warn] nixos-generate-config failed; run manually after boot:"
|
|
echo " nixos-generate-config --show-hardware-config > /etc/dotfiles/nixos/hosts/${hostname}-hardware.nix"
|
|
fi
|
|
|
|
umount -R /mnt
|
|
cryptsetup close crypted
|
|
|
|
echo ""
|
|
echo "=== Done! ==="
|
|
echo "Remove the USB and reboot. After unlocking LUKS:"
|
|
echo " 1. SSH in: ssh danny@${hostname}"
|
|
echo " 2. First rebuild: cd /etc/dotfiles && sudo nixos-rebuild switch --flake .#${hostname}"
|
|
echo " 3. Commit ${hostname}-hardware.nix back to the repo"
|