feat(nixos): add phantom-ship host and streamline server installer

- New host config: phantom-ship.nix (SSH, auto-rebuild, nix-ld, Ethernet)
- Hardware stub: phantom-ship-hardware.nix (replaced by install script)
- Add phantom-ship to flake.nix with home-manager
- Install script now auto-provisions post-install:
  - Clones dotfiles to /etc/dotfiles
  - Installs SSH public key (SSH_PUBKEY_FILE env var)
  - Generates hardware config
  - Supports INSTALLER_HOSTNAME and INSTALLER_DISK env vars
- Fix bootstrap-install.sh default branch to main
- Update CLAUDE.md and server-installer-usb.md
This commit is contained in:
DannyDannyDanny 2026-03-31 11:37:15 +02:00
parent 2c9cf1e8b4
commit d4dbd73a8c
7 changed files with 314 additions and 183 deletions

View file

@ -6,8 +6,9 @@
# macOS (from ~/dotfiles/nixos)
darwin-rebuild switch --flake .
# NixOS server (SSH from mac, or on server)
# NixOS servers (SSH from mac, or on server)
sudo nixos-rebuild switch --flake .#sunken-ship
sudo nixos-rebuild switch --flake .#phantom-ship
# WSL
sudo nixos-rebuild switch --flake ~/dotfiles/nixos#wsl
@ -29,9 +30,10 @@ cd ~/dotfiles/nixos && nix build .#installer-iso
- **Inputs:** nixpkgs-unstable, nix-darwin, home-manager, nixos-wsl, disko, zen-browser
- **Host configs** in `nixos/hosts/`:
- `daniel-macbook-air.nix` — hostname `Daniel-Macbook-Air` (aarch64-darwin, nix-darwin)
- `sunken-ship.nix` — NixOS home server (x86_64-linux)
- `sunken-ship.nix` — NixOS home server (x86_64-linux, WiFi + AirPlay)
- `phantom-ship.nix` — NixOS home server (x86_64-linux, Ethernet)
- `wsl.nix` — WSL (x86_64-linux)
- `server-install.nix` — disko-install target (LUKS + WiFi)
- `server-install.nix` — disko-install target (LUKS)
- **Home Manager:** integrated on macOS, WSL, and sunken-ship; user config in `nixos/home/danny/home.nix`
- **Shared modules:** `nixos/fish.nix` (fish + bash), `nixos/ollama.nix`
- **Darwin config name:** `Daniel-Macbook-Air` (must match in rebuild commands)
@ -46,8 +48,16 @@ cd ~/dotfiles/nixos && nix build .#installer-iso
- SSH: `ssh -i ~/.ssh/id_ed25519_sunken_ship danny@sunken-ship`
- Remote rebuild: `ssh ... 'cd /etc/dotfiles/nixos && sudo nixos-rebuild switch --flake .#sunken-ship'`
- Auto-rebuild timer: `dotfiles-rebuild` — only active after flake config switch. Check with `systemctl is-active dotfiles-rebuild.timer`.
- Server has WiFi; stays reachable when ethernet is unplugged.
- Auto-rebuild timer: `dotfiles-rebuild` — every 15 min. Check with `systemctl is-active dotfiles-rebuild.timer`.
- WiFi connected; stays reachable when ethernet is unplugged.
- Services: UxPlay (AirPlay receiver on Scarlett Solo)
## Server (phantom-ship)
- SSH: `ssh danny@phantom-ship`
- Remote rebuild: `ssh ... 'cd /etc/dotfiles/nixos && sudo nixos-rebuild switch --flake .#phantom-ship'`
- Auto-rebuild timer: same pattern as sunken-ship.
- Ethernet only (no WiFi).
## Ollama

View file

@ -1,79 +1,100 @@
# Server installer USB (NixOS + LUKS + WiFi)
# Server installer USB (NixOS + LUKS)
Bootable USB that installs NixOS on a new server with disk encryption (LUKS) and optional WiFi from first boot. Only required input is the hostname (and LUKS passphrase when disko creates the volume). Existing hosts are not modified.
Bootable USB that installs NixOS on a new server with disk encryption (LUKS). The install script handles partitioning, encryption, dotfiles cloning, SSH key setup, and hardware config generation. Only required inputs: hostname, LUKS passphrase, and target disk.
## Quick path: boot USB → WiFi → SSH in → run bootstrap
## Quick path (Ethernet server like phantom-ship)
1. Boot the target machine from the NixOS installer USB.
2. On the live system, connect to WiFi (or plug in Ethernet). Check internet (e.g. `ping -c 2 8.8.8.8`).
3. On the **live** system, start SSH and set a password for the `nixos` user so you can log in from your Mac:
### Prep (on sunken-ship or any Linux box)
1. Download the [NixOS minimal ISO](https://nixos.org/download.html#nixos-iso) on sunken-ship.
2. Plug in USB and write the ISO:
```bash
# Find your USB device (e.g. /dev/sdc)
lsblk
sudo dd if=nixos-minimal-*.iso of=/dev/sdX status=progress bs=4M
sync
```
### Install (on the new server)
3. Boot the new machine from USB, plug in Ethernet, verify connectivity (`ping 8.8.8.8`).
4. Start SSH on the live system so you can paste commands from your Mac:
```bash
sudo systemctl start sshd
sudo passwd nixos
hostname -I
hostname -I # note the IP
```
Note the IP from `hostname -I`.
4. From your **Mac**: `ssh nixos@<IP>` (use the password you set). Now you can paste the bootstrap command instead of typing on the machine.
5. In that SSH session, run the bootstrap (installs NixOS with LUKS; prompts for hostname, disk, **danny password**, LUKS passphrase, then once more LUKS to set the password on disk):
5. From your **Mac**, scp your SSH public key and SSH in:
```bash
curl -sL https://raw.githubusercontent.com/DannyDannyDanny/dotfiles/server-installer-usb/scripts/bootstrap-install.sh | sudo bash
scp ~/.ssh/id_ed25519_phantom_ship.pub nixos@<IP>:/tmp/key.pub
ssh nixos@<IP>
```
6. When it finishes, reboot and remove the USB. Unlock LUKS at boot, then log in as **danny** with the password you set during the install.
6. Run the bootstrap (one command):
```bash
curl -sL https://raw.githubusercontent.com/DannyDannyDanny/dotfiles/main/scripts/bootstrap-install.sh | \
INSTALLER_HOSTNAME=phantom-ship SSH_PUBKEY_FILE=/tmp/key.pub sudo -E bash
```
This will prompt for: target disk, optional danny password, confirmation, and LUKS passphrase (twice: once for disko, once for post-install provisioning).
## Option A: Official NixOS ISO (works from macOS)
The script automatically:
- Partitions and encrypts the disk (LUKS + ext4)
- Installs NixOS with the hostname
- Clones dotfiles to `/etc/dotfiles`
- Installs your SSH public key
- Generates `phantom-ship-hardware.nix`
You **cannot** build the custom installer ISO on macOS (it is x86_64-linux only and `--system` is restricted). Use the official NixOS minimal ISO instead:
7. Reboot, remove USB, unlock LUKS.
1. Download the [minimal ISO](https://nixos.org/download.html#nixos-iso) (e.g. `nixos-minimal-*-x86_64-linux.iso`).
2. Write it to your USB (on macOS: `diskutil unmountDisk diskN`, then `sudo dd if=path/to/nixos-minimal-*.iso of=/dev/rdiskN bs=4m`).
3. Boot the server from the USB. Attach Ethernet or use the **graphical** ISO if you need WiFi on the live system.
4. On the live system, clone this repo and run the install script (see [Install on the server](#install-on-the-server) below). The script runs `disko-install` and does LUKS + hostname; no custom ISO needed.
### After first boot
8. SSH in: `ssh danny@phantom-ship`
9. First rebuild to switch from generic `server-install` to `phantom-ship` config:
```bash
cd /etc/dotfiles/nixos && sudo nixos-rebuild switch --flake .#phantom-ship
```
10. Commit the generated `phantom-ship-hardware.nix` back to the repo.
## Environment variables
All optional; skip interactive prompts or add automation:
| Variable | Description |
|----------|-------------|
| `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` (e.g. WiFi config) |
## Option A: Official NixOS ISO (recommended)
Cannot build the custom ISO on macOS (x86_64-linux only). Use the official NixOS minimal ISO:
1. Download from [nixos.org](https://nixos.org/download.html#nixos-iso).
2. Write to USB from sunken-ship or any Linux box.
3. Boot, connect Ethernet, run bootstrap.
## Option B: Custom ISO (build on Linux only)
The custom ISO adds WiFi kernel modules and optional live WiFi; it must be built on **x86_64-linux** (or with a Nix remote builder configured for that system). Building on macOS will fail.
Adds WiFi kernel modules for servers that need WiFi on the live system.
### Build from sunken-ship (one command from your Mac)
When the server is on the same network, run from the dotfiles repo:
### Build from sunken-ship
```bash
./scripts/build-installer-iso-on-server.sh
```
This pushes the branch, SSHs to sunken-ship, clones the repo there, runs `nix build .#installer-iso`, and copies the ISO back to the current directory. Optional: `./scripts/build-installer-iso-on-server.sh sunken-ship /path/to/output`.
### Build directly on a Linux machine
From a Linux box (or on sunken-ship after SSH in):
### Build directly on Linux
```bash
cd ~/dotfiles/nixos
nix build .#installer-iso
cd ~/dotfiles/nixos && nix build .#installer-iso
# Write to USB:
sudo dd if=result/iso/nixos-minimal-*.iso of=/dev/sdX status=progress bs=4M
```
The image is at `result/iso/nixos-minimal-*.iso`. Write it to a USB stick (replace `sdX` with your device, e.g. `sda`):
## Live-system WiFi (optional, custom ISO only)
```bash
# Linux
sudo dd if=result/iso/nixos-minimal-*.iso of=/dev/sdX status=progress
sync
```
On macOS, use the disk number (e.g. `4` for `disk4`):
```bash
sudo dd if=result/iso/nixos-minimal-*.iso of=/dev/rdisk4 bs=4m
diskutil eject disk4
```
Or adapt [scripts/make-ubuntu-usb.sh](../scripts/make-ubuntu-usb.sh) for the NixOS ISO path.
## Live-system WiFi (optional)
So the live system can reach the network (and fetch the flake) without Ethernet, add WiFi to the ISO at **build time**. Do not put SSID/PSK in the repo.
1. Create **`nixos/installer-wifi.nix`** (gitignored) with your network:
Create `nixos/installer-wifi.nix` (gitignored):
```nix
{
@ -82,77 +103,18 @@ So the live system can reach the network (and fetch the flake) without Ethernet,
}
```
2. Add it to the flake for the installer ISO only. In `nixos/flake.nix`, change the `installer-iso` modules to:
Add to flake's installer-iso modules, rebuild ISO on Linux.
```nix
installer-iso = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [ ./installer-iso.nix ./installer-wifi.nix ]; # add installer-wifi.nix
};
```
## Installed-system WiFi (optional)
3. Ensure `nixos/installer-wifi.nix` is in `.gitignore`, then rebuild the ISO.
If you skip this, use Ethernet on the live system or the graphical NixOS installer to join WiFi, then run the install script.
## Install on the server
1. Boot the server from the USB.
2. If you did not bake WiFi into the ISO, attach Ethernet or (on graphical installer) join WiFi so the machine has network.
3. Run **one** of the following (shortest first).
**Shortest — fetch and run (no clone step):**
Exact URL (watch for typos: **.com** not .con, **usb** not ush, **DannyDannyDanny** with three capital Ds):
Pass a JSON file with wireless config:
```bash
curl -sL https://raw.githubusercontent.com/DannyDannyDanny/dotfiles/server-installer-usb/scripts/bootstrap-install.sh | sudo bash
sudo INSTALLER_SYSTEM_CONFIG_FILE=/path/to/wifi.json INSTALLER_HOSTNAME=my-server ./scripts/nixos-server-install.sh
```
If you see `bash: 404: command not found`, the URL was wrong or the branch doesnt exist. Check the URL, or verify first: `curl -sL "THE_URL_ABOVE" | head -1` should show `#!/bin/bash`, not HTML.
To type less, create a [git.io](https://git.io) short link once (paste the raw URL above), then on the machine run: `curl -sL https://git.io/YOUR_CODE | sudo bash`.
**Alternative — clone then run** (if you prefer not to pipe curl to bash):
```bash
nix run --extra-experimental-features "nix-command flakes" nixpkgs#git -- clone https://github.com/USER/REPO.git /tmp/dotfiles && cd /tmp/dotfiles && git checkout server-installer-usb && sudo ./scripts/nixos-server-install.sh
```
If you see `command not found` when running the script, use `sudo bash ./scripts/nixos-server-install.sh` instead of `sudo ./scripts/...`.
4. When prompted: enter **hostname** (e.g. `phantom-ship`), then **target disk** (default `/dev/sda`), then **y** to proceed. When disko creates the LUKS volume, enter your encryption passphrase.
5. When the script finishes, remove the USB and reboot. The new NixOS system will have LUKS root and the hostname you chose.
## WiFi on the installed system (optional)
To have WiFi configured from first boot (no manual step after reboot):
1. Create a JSON file **outside the repo** with the config to merge (hostname is set by the script from the prompt):
```json
{
"networking": {
"wireless": {
"networks": {
"YourSSID": { "psk": "your-password" }
}
}
}
}
```
2. Copy that file onto the live system (e.g. put it on the USB or scp it). If the script is run with `jq` available and `INSTALLER_SYSTEM_CONFIG_FILE` set to that file, the script will merge it and set the hostname:
```bash
sudo INSTALLER_SYSTEM_CONFIG_FILE=/path/to/wifi-config.json ./scripts/nixos-server-install.sh
```
If you omit this, the installed system still has `networking.wireless.enable = true`. Add credentials after first boot (e.g. [imperative wpa_supplicant config](sunken-ship-wifi.md)).
## Manual install (without the script)
You can run disko-install yourself:
```bash
sudo nix run github:nix-community/disko/latest#disko-install -- \
--flake 'path:/tmp/dotfiles/nixos#server-install' \
@ -160,21 +122,13 @@ sudo nix run github:nix-community/disko/latest#disko-install -- \
--system-config '{"networking":{"hostName":"my-server"}}'
```
Adjust the flake path and `--system-config` (e.g. add WiFi) as needed.
## After install
- Add your SSH key: from your machine `scp ~/.ssh/id_ed25519_servers.pub danny@NEW-SERVER:/tmp/`, then on the server `mkdir -p ~/.ssh; cat /tmp/*.pub >> ~/.ssh/authorized_keys`.
- To switch this machine to another host config in the same flake (e.g. a full server profile), clone the repo on the new system and run `sudo nixos-rebuild switch --flake /path/to/nixos#other-host`.
## Summary
| Step | Action |
|------|--------|
| **From macOS** | Use Option A: download official NixOS minimal ISO, write to USB, boot server, clone repo, run install script. |
| **From Linux** | Option B: `nix build .#installer-iso` in `nixos/`, then write `result/iso/*.iso` to USB. |
| Optional live WiFi | (Custom ISO only) Add `installer-wifi.nix` (gitignored), include in flake, rebuild on Linux. |
| Boot | Boot server from USB |
| Install | On live system: `curl -sL https://raw.githubusercontent.com/.../server-installer-usb/scripts/bootstrap-install.sh | sudo bash` (or clone then `sudo ./scripts/nixos-server-install.sh`) |
| Optional installed WiFi | Set `INSTALLER_SYSTEM_CONFIG_FILE` to a JSON file with wireless config |
| Reboot | Remove USB, reboot; set root password if needed, add SSH keys |
| **Prep** | Download NixOS minimal ISO on sunken-ship, write to USB |
| **Boot** | Boot new server from USB, plug Ethernet |
| **Install** | `curl ... \| INSTALLER_HOSTNAME=phantom-ship SSH_PUBKEY_FILE=/tmp/key.pub sudo -E bash` |
| **Reboot** | Remove USB, unlock LUKS |
| **First rebuild** | `sudo nixos-rebuild switch --flake /etc/dotfiles/nixos#phantom-ship` |
| **Commit** | Push generated `phantom-ship-hardware.nix` to repo |

View file

@ -72,6 +72,26 @@
];
};
phantom-ship = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
./hosts/phantom-ship.nix
# Home Manager on NixOS
home-manager.nixosModules.home-manager
({ lib, ... }: {
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.backupFileExtension = "backup";
home-manager.users.danny = { ... }: {
home.username = "danny";
home.homeDirectory = lib.mkForce "/home/danny";
home.stateVersion = "25.11";
};
})
];
};
# For disko-install: LUKS + WiFi; hostname/WiFi via --system-config.
server-install = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";

View file

@ -0,0 +1,17 @@
# STUB — replace with output of: nixos-generate-config --show-hardware-config
# The install script saves the real config here automatically.
# Filesystems are managed by disko during install; only boot/initrd config here.
{ config, lib, pkgs, modulesPath, ... }:
{
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usb_storage" "sd_mod" ];
boot.kernelModules = [ "kvm-intel" ];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View file

@ -0,0 +1,65 @@
# NixOS server: bare config with SSH, auto-rebuild, Ethernet.
# Services (OpenClaw, etc.) to be added later.
{ config, lib, pkgs, ... }:
let
dotfilesDir = "/etc/dotfiles";
flakeRef = "${dotfilesDir}/nixos#phantom-ship";
in
{
imports = [ ./phantom-ship-hardware.nix ];
networking.hostName = "phantom-ship";
networking.useDHCP = lib.mkDefault true; # Ethernet; no wireless
time.timeZone = "Europe/Copenhagen";
nix.settings.experimental-features = [ "nix-command" "flakes" ];
programs.nix-ld.enable = true; # run dynamically linked binaries (e.g. Claude Code remote CLI)
system.stateVersion = "24.11";
users.users.danny = {
isNormalUser = true;
extraGroups = [ "wheel" ];
};
# Key-only auth; no password or keyboard-interactive.
services.openssh = {
enable = true;
settings = {
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
};
};
# Passwordless sudo for wheel.
security.sudo.wheelNeedsPassword = false;
environment.systemPackages = with pkgs; [
git # clone/bootstrap and dotfiles-rebuild timer
];
# Pull dotfiles and rebuild if the repo has new commits.
systemd.services.dotfiles-rebuild = {
description = "Pull dotfiles and run nixos-rebuild if repo changed";
path = with pkgs; [ git nix ];
environment.GIT_CONFIG_COUNT = "1";
environment.GIT_CONFIG_KEY_0 = "safe.directory";
environment.GIT_CONFIG_VALUE_0 = dotfilesDir;
script = ''
set -euo pipefail
cd ${dotfilesDir}
git fetch origin
if [ "$(git rev-parse HEAD)" = "$(git rev-parse origin/main)" ]; then
exit 0
fi
git pull origin main
exec nixos-rebuild switch --flake ${flakeRef}
'';
serviceConfig.Type = "oneshot";
};
systemd.timers.dotfiles-rebuild = {
wantedBy = [ "timers.target" ];
timerConfig.OnCalendar = "*-*-* *:00/15:00"; # every 15 minutes
timerConfig.RandomizedDelaySec = "2min";
};
}

View file

@ -1,13 +1,13 @@
#!/bin/bash
# Fetch with curl and run to install NixOS (clone + run nixos-server-install.sh).
# On the live system, run only:
# curl -sL https://raw.githubusercontent.com/DannyDannyDanny/dotfiles/server-installer-usb/scripts/bootstrap-install.sh | sudo bash
# curl -sL https://raw.githubusercontent.com/DannyDannyDanny/dotfiles/main/scripts/bootstrap-install.sh | sudo bash
#
# Optional: REPO_URL=... BRANCH=... (default repo and server-installer-usb)
set -euo pipefail
REPO_URL="${REPO_URL:-https://github.com/DannyDannyDanny/dotfiles.git}"
BRANCH="${BRANCH:-server-installer-usb}"
BRANCH="${BRANCH:-main}"
DEST="/tmp/dotfiles"
INSTALL_SCRIPT="$DEST/scripts/nixos-server-install.sh"

View file

@ -1,16 +1,17 @@
#!/bin/bash
# Run on a NixOS minimal live system (or installer ISO) to install NixOS with
# disko (LUKS + root). Prompts for hostname and target disk; optionally use
# INSTALLER_SYSTEM_CONFIG_FILE for WiFi etc.
# 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
# If you see "command not found", use: sudo bash ./scripts/nixos-server-install.sh
#
# Optional: FLAKE_REF=github:User/dotfiles or path:/path/to/dotfiles/nixos
#
# Optional: INSTALLER_SYSTEM_CONFIG_FILE=/path/to/json with full --system-config
# (e.g. hostName + networking.wireless.networks). If unset, only hostname is passed.
# 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:-}"
@ -30,21 +31,29 @@ if [[ "$EUID" -ne 0 ]]; then
exit 1
fi
read -r -p "Hostname (e.g. my-server): " hostname
# --- 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
read -r -p "Target disk [default: /dev/sda]: " disk
disk="${disk:-/dev/sda}"
# --- 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
# Use provided JSON; ensure hostname is set
if command -v jq &>/dev/null; then
SYSTEM_CONFIG=$(jq --arg h "$hostname" '.networking.hostName = $h' "$INSTALLER_SYSTEM_CONFIG_FILE")
else
@ -55,8 +64,9 @@ else
SYSTEM_CONFIG='{"networking":{"hostName":"'"$hostname"'"}}'
fi
# Prompt for password for danny so you can log in at console after reboot (no rescue needed)
read -r -p "Set a password for user danny (console/SSH login)? [y/N] " set_pass
# --- 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
@ -70,23 +80,27 @@ if [[ "${set_pass,,}" == "y" || "${set_pass,,}" == "yes" ]]; 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)
if [[ -z "$HASH" ]]; then
echo "Could not hash password (need openssl or mkpasswd). Skipping password."
else
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 (jq not found). Set after boot: passwd danny"
[[ -n "$NEW_CONFIG" ]] && SYSTEM_CONFIG="$NEW_CONFIG" || echo "Could not merge password. Set after boot: passwd danny"
fi
[[ -n "$SYSTEM_CONFIG" ]] && echo "Password will be set for danny."
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
@ -100,33 +114,84 @@ nix run --extra-experimental-features "nix-command flakes" \
--disk main "$disk" \
--system-config "$SYSTEM_CONFIG"
# Set danny password directly on disk (Nix merge can fail); re-open LUKS and chroot
if [[ -n "${danny_pass:-}" ]]; then
echo "Setting password for danny on installed system (re-enter LUKS passphrase once)..."
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
if ! echo -n "$luks_pass" | cryptsetup open "$LUKS_DEV" crypted --key-file -; then
echo "Wrong LUKS passphrase; set danny password after boot: passwd danny"
else
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
echo "danny:${danny_pass}" | chroot /mnt chpasswd
umount -R /mnt
cryptsetup close crypted
echo "Password for danny set. Reboot and log in."
fi
unset luks_pass
else
echo "Could not find LUKS partition; set password after boot: passwd danny"
fi
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 ! 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
fi
unset luks_pass
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/nixos && sudo nixos-rebuild switch --flake .#${hostname}"
echo " 3. Commit ${hostname}-hardware.nix back to the repo"