diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 8d87139..49c0aa0 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -53,11 +53,26 @@ Use `just` for all operations: ```bash just switch # Rebuild current host just switch desktop # Rebuild specific host -just update nixpkgs # Update single input +just test # Apply changes temporarily (nixos-rebuild test) +just boot # Apply changes on next boot +just update # Update flake.lock just diff # Preview changes before switching -nix fmt # Format with alejandra, deadnix, statix +just fmt # Format all files +just gc # Collect garbage (delete older than 7d) +just check # Validate configuration +just repl # Open nix repl with flake loaded +just factor # Generate nixos-facter hardware config +just secret-edit # Edit an encrypted secret ``` +### Safety Boundaries + +**CRITICAL**: As an AI agent, you are **FORBIDDEN** from executing commands that permanently modify the system state or perform remote deployments. +- **DO NOT** run `just switch` or `just boot`. +- **DO NOT** run `just switch `. +- Use `just test` or `just build-system` if you need to verify that a configuration builds successfully. +- **ALWAYS** run `just fmt` after modifying files and before finishing your task to ensure consistent code style. + ## Secret Management Secrets use agenix + agenix-rekey with YubiKey master identity: diff --git a/README.md b/README.md index 4785ced..d224135 100644 --- a/README.md +++ b/README.md @@ -9,33 +9,64 @@ All common tasks are managed via `just`. Run `just` to see available commands. ### System Operations ```bash -# Rebuild and switch to new configuration (current host) +# Rebuild and switch to new configuration just switch -# Rebuild a specific host +# Rebuild and switch a specific host just switch desktop -# Update flake inputs -just update +# Try out configuration without making it permanent (reverts on reboot) +just test -# Update a specific input -just update nixpkgs +# Apply on next boot +just boot # Build without switching just build-system -# Compare changes before switching +# Update flake inputs +just update + +# Compare current system with configuration just diff + +# Format configuration files +just fmt + +# Validate configuration (flake check) +just check + +# Maintenance: Collect garbage and delete old generations +just gc ``` ### Remote Deployment ```bash -# Deploy to a remote host +# Deploy to a remote host (via nixos-rebuild --target-host) just switch hostname user@remote -# Fresh install on a new machine +# Fresh install on a new machine (via nixos-anywhere) just deploy-remote hostname user@remote + +# Generate hardware configuration for a remote host +just factor hostname user@remote +``` + +### Tools & Debugging + +```bash +# Open nix repl with flake loaded +just repl + +# List system generations/history +just history + +# Visualize dependency tree +just tree + +# Build an install ISO for a specific host +just iso hostname ``` ### Bootstrap ISO @@ -79,9 +110,9 @@ just bootstrap-flash /dev/sdX just factor user@remote ``` -5. Rekey secrets: +5. Deploy or Build: ```bash - just secret-rekey + just test ``` > [!TIP] diff --git a/justfile b/justfile index 9dc4a9a..e14da56 100644 --- a/justfile +++ b/justfile @@ -6,6 +6,7 @@ nixcmd := "nix --experimental-features 'nix-command flakes'" just --list [doc("Build a flake output")] +[group('tools')] build target *ARGS="": @{{ nixcmd }} run {{ ARGS }} nixpkgs#nix-output-monitor -- build {{ justfile_directory() }}#{{ target }} @@ -19,6 +20,10 @@ build-system hostname=`hostname -s` *ARGS="": factor hostname=`hostname -s` target='': #!/usr/bin/env -S bash -e target="{{ target }}" + if [ ! -d "hosts/{{ hostname }}" ]; then + echo "Error: Host '{{ hostname }}' does not exist in ./hosts/" + exit 1 + fi if [ -z "$target" ]; then sudo {{ nixcmd }} run nixpkgs#nixos-facter -- -o hosts/{{ hostname }}/facter.json else @@ -31,19 +36,29 @@ factor hostname=`hostname -s` target='': [doc('Wrapper for nixos-rebuild switch')] [group("deploy")] -switch hostname=`hostname -s` target='': +switch hostname=`hostname -s` target='' *ARGS="": #!/usr/bin/env -S bash -e target="{{ target }}" if [ -z "$target" ]; then - sudo {{ nixcmd }} run nixpkgs#nixos-rebuild -- switch --show-trace --flake .#{{ hostname }} + sudo {{ nixcmd }} run nixpkgs#nixos-rebuild -- switch --show-trace --flake .#{{ hostname }} {{ ARGS }} else {{ nixcmd }} run nixpkgs#nixos-rebuild -- switch \ --flake .#{{ hostname }} \ --use-substitutes \ --target-host {{ target }} \ - --sudo + --sudo {{ ARGS }} fi +[doc('Wrapper for nixos-rebuild boot')] +[group("deploy")] +boot hostname=`hostname -s` *ARGS="": + sudo {{ nixcmd }} run nixpkgs#nixos-rebuild -- boot --show-trace --flake .#{{ hostname }} {{ ARGS }} + +[doc('Wrapper for nixos-rebuild test')] +[group("deploy")] +test hostname=`hostname -s` *ARGS="": + sudo {{ nixcmd }} run nixpkgs#nixos-rebuild -- test --show-trace --flake .#{{ hostname }} {{ ARGS }} + [doc('Use nixos-anywhere to deploy to a remote host')] [group('deploy')] deploy-remote hostname target: @@ -75,7 +90,7 @@ disko-install hostname disk: sudo {{ nixcmd }} run 'github:nix-community/disko/latest#disko-install' -- --flake .#{{ hostname }} --disk main {{ disk }} [doc('Build an install ISO for a host')] -[group('deploy')] +[group('tools')] iso hostname: {{ nixcmd }} build .#nixosConfigurations.{{ hostname }}.config.formats.install-iso @@ -133,8 +148,14 @@ secret-rekey: {{ nixcmd }} run .#agenix-rekey.x86_64-linux.rekey [doc("Sets up configuration + SSH keys for a new host")] +[group('maintenance')] new-host hostname username: #!/usr/bin/env -S bash -e + if [ -d "hosts/{{ hostname }}" ]; then + echo "Error: Host '{{ hostname }}' already exists." + exit 1 + fi + temp=$(mktemp -d) trap "rm -rf $temp" EXIT @@ -157,17 +178,37 @@ new-host hostname username: echo "Encrypting SSH key" just age -e "$temp/id_ed25519" -o "secrets/hosts/{{ hostname }}/id_ed25519.age" + echo "Secret rekeying..." + just secret-rekey + echo "Remember to update ./hosts/default.nix eg:" # Bold with no newline cat <