set positional-arguments host := `hostname` key_services := "github gradescope" # Default: list available recipes. default: @just --list # Rebuild the system and switch immediately rebuild: sudo nixos-rebuild switch --flake .#{{host}} # Update flake.lock update: nix flake update # Clean up old generations and optimize store gc: sudo nix-collect-garbage --delete-older-than 14d sudo nix-store --optimise sudo nixos-rebuild boot --flake .#{{host}} # Generate Ed25519 SSH keys for each configured service gen-keys: #!/usr/bin/env bash set -euo pipefail mkdir -p ~/.ssh chmod 700 ~/.ssh for service in {{key_services}}; do file="$HOME/.ssh/id_$service" if [ -f "$file" ]; then echo "skipping: $file already exists" continue fi echo "generating: $file" ssh-keygen -t ed25519 -f "$file" -N "" -C "$service@$(hostname -s)" done # Build a bootable NixOS installer USB (writes ISO + optional extras partition). # Pass arguments through to scripts/make-usb.sh, e.g.: # just make-usb --iso ~/Downloads/nixos.iso # Re-executes itself under sudo if not already root. Quoting is preserved # via `set positional-arguments` + "$@". make-usb *args: #!/usr/bin/env bash set -euo pipefail if [[ ! -x scripts/make-usb.sh ]]; then chmod +x scripts/make-usb.sh fi if (( EUID == 0 )); then exec ./scripts/make-usb.sh "$@" else exec sudo --preserve-env=PATH ./scripts/make-usb.sh "$@" fi # Register a new host: scaffold hosts// and add a flake.nix entry. # Example: just register-host blackbear register-host name: @python3 scripts/register-host.py --repo-root . "{{name}}" # Capture the current machine's hardware config into hosts//hardware.nix. # Run this on the *new* machine. Two contexts work: # 1. Already-installed NixOS: just runs nixos-generate-config against /. # 2. Booted from installer with target mounted at /mnt: detected # automatically and --root /mnt is used. # Example: just capture-hardware blackbear capture-hardware name: #!/usr/bin/env bash set -euo pipefail name="{{name}}" target="hosts/$name/hardware.nix" if [[ ! -d "hosts/$name" ]]; then echo "[-] hosts/$name does not exist. Run \`just register-host $name\` first." >&2 exit 1 fi if ! command -v nixos-generate-config >/dev/null 2>&1; then echo "[-] nixos-generate-config not found." >&2 echo " Run this command on a NixOS machine (or inside the installer)." >&2 exit 1 fi # Detect whether we're in the installer with a target mounted at /mnt. extra_args=() if mountpoint -q /mnt 2>/dev/null && [[ -d /mnt/etc ]]; then echo "[+] Detected mounted target at /mnt — using --root /mnt" extra_args+=(--root /mnt) elif mountpoint -q /mnt 2>/dev/null; then echo "[!] /mnt is mounted but doesn't look like a NixOS target (no /mnt/etc)." echo " Continuing as if on a running system. Pass --no-filesystems by editing" echo " hardware.nix afterwards if disks aren't permanent." fi # Confirm before overwriting a non-placeholder hardware.nix. if [[ -f "$target" ]] && ! grep -q 'PLACEHOLDER hardware.nix' "$target"; then echo "[!] $target already exists and doesn't look like a placeholder." >&2 read -r -p "Overwrite? (yes/[no]) " confirm [[ "$confirm" == "yes" ]] || { echo "aborted."; exit 1; } fi echo "[+] Generating hardware config..." # The redirect runs in the user's shell BEFORE sudo, so the file is # owned by you, not root. sudo is needed because nixos-generate-config # reads /proc, /sys, and may probe mounted filesystems. sudo nixos-generate-config --show-hardware-config "${extra_args[@]}" > "$target" echo "[+] Wrote $target" if command -v git >/dev/null && git -C . rev-parse >/dev/null 2>&1; then echo "[+] git diff:" git --no-pager diff -- "$target" || true fi # Show which hosts are currently registered in flake.nix (parses the file directly). hosts: #!/usr/bin/env python3 import re, sys src = open('flake.nix').read() m = re.search(r'nixosConfigurations\s*=\s*\{', src) if not m: sys.exit(0) # Brace-match to find the closing }. depth, i, close = 0, m.end() - 1, None while i < len(src): c = src[i] if c == '{': depth += 1 elif c == '}': depth -= 1 if depth == 0: close = i break i += 1 block = src[m.end():close] if close else '' for name in re.findall(r'^[ \t]*([A-Za-z_][\w-]*)\s*=\s*nixpkgs\.lib\.nixosSystem', block, re.M): print(name)