https://github.com/nix-community/nh?tab=readme-ov-file # Overview *Sherpa* is an all-in-one Nix flake configuration tool written in Go. It attempts to unify the following tools used in the Nix community into one common interface: - [Agenix](https://github.com/ryantm/agenix) / [Ragenix](https://github.com/yaxitech/ragenix) - [Disko](https://github.com/nix-community/disko) - [NixOS Anywhere](https://github.com/nix-community/nixos-anywhere) - [NixOS Generators](https://github.com/nix-community/nixos-generators) - [nixos-install](https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/ni/nixos-install/nixos-install.sh) Sherpa ships the following utilities: - Sherpa CLI - Sherpa Web UI - Sherpa Live Image ISO ## Use Cases - Use Sherpa on the NixOS Installer ISO Live Image to install NixOS on a local machine - Use Sherpa on the NixOS Installer ISO Live Image to install NixOS on a remote machine - Use Sherpa on a macOS machine to remotely install NixOS on another machine using SSH - Use Sherpa on any Linux distribution to remotely install NixOS on another machine using SSH ## CLI Examples ```bash # initialize a flake: $ sherpa init . # create a machine $ sherpa hosts create framework-16 # deploy a machine $ sherpa hosts deploy framework-16 # remove a machine (removes directory and updates secrets.nix) $ sherpa hosts remove framework-16 # generate outputs from a host # an ISO of the target system, as-is $ sherpa hosts generate --type=live-iso framework-16 # an ISO that would install the target system as-is with a GUI installer $ sherpa hosts generate --type=install-iso framework-16 # an ISO that would blast away the existing OS without any user interaction $ sherpa hosts generate --type=blast-iso framework-16 # create and encrypt secrets (also updates secrets.nix) $ sherpa secrets create --type=machine-id ./hosts/framework-16/secrets/machine-id $ sherpa secrets create --type=id_ed25519 ./hosts/framework-16/secrets/ssh_host_ed25519_key $ sherpa secrets create --type=password ./hosts/framework-16/secrets/user-jacobranson-password $ sherpa secrets create --type=plaintext ./hosts/framework-16/secrets/luks-password $ sherpa secrets create --type=plaintext --editor ./hosts/framework-16/secrets/other # view existing secrets $ sherpa secrets show ./hosts/framework-16/secrets/other # edit existing secrets $ sherpa secrets edit ./hosts/framework-16/secrets/other # remove existing secrets (removes file and updates secrets.nix) $ sherpa secrets remove ./hosts/framework-16/secrets/other # rekey existing secrets $ sherpa secrets rekey ``` ## CLI Deep Dive ```bash # initialize a flake: $ sherpa init . # User information: # - Full Name # - Email # Repo information: # - Repo name # - Confirm create repo? # Features # - Which version of Nix do you want? # - CppNix # - Determinate Nix # - Lix # create a machine $ sherpa hosts create framework-16 # target: # - local machine # - remote machine # - virtual machine # system information: # - hardware-configuration.nix # - machine-id # - ssh_host_ed25519_key # - ssh_host_ed25519_key.pub # select primary disk: # - nvme0n1 # - sda # - etc. # select disk features: # - full disk encryption? # - password # - confirm password # - auto login to default user? # - secure boot? # - impermanence? # - persistent partition name # select disk filesystem: # - ext4 # - btrfs # - zfs # - tmpfs # configure the host: # - hostname # - layout # - locale # - timezone # - desktop environment: # - GDM & GNOME # - SDDM & Plasma # - None # configure the user: # - Full Name (try to pull from git) # - Email (try to pull from git) # - Username (try to pull from machine) # - Password # - Confirm Password # - Generate user SSH key pair (try pull from curr machine, if local target) # - SSH Authorized Keys (recommend current machine keys if target is remote) # configure administrator: # - enable the root account? # - root password same as user password? # - Root password # - Confirm root password # - Root SSH Authorized Keys same as user? # - Root SSH Authorized Keys # write `secrets.nix`. # write, encrypt, git add, git commit secrets # - id_ed25519 # - id_ed25519.pub # - ssh_host_ed25519_key # - ssh_host_ed25519_key.pub # - machine-id # - luks-password # - user-password # deploy a machine $ sherpa hosts deploy framework-16 # target: # - local machine # - remote machine # - virtual machine # # if local machine && not live ISO: # you must be booted into a NixOS Live ISO to use local deploy # # if remote machine && no SSH access: # you must have SSH access to the corresponding machine # # if virtual machine # this feature is not yet implemented! # # if local machine && live ISO: # copy network connections from the live image to the target machine? # # copy this flake to the target machine? # - directory to copy to # create and encrypt secrets $ sherpa secrets create --type=machine-id ./hosts/framework-16/secrets/machine-id # Created ./hosts/framework-16/secrets/machine-id $ sherpa secrets create --type=id_ed25519 ./hosts/framework-16/secrets/ssh_host_ed25519_key # Created ./hosts/framework-16/secrets/ssh_host_ed25519_key # Created ./hosts/framework-16/secrets/ssh_host_ed25519_key.pub $ sherpa secrets create --type=password ./hosts/framework-16/secrets/user-jacobranson-password # Password: *** # Confirm Password: *** # # Created ./hosts/framework-16/secrets/user-jacobranson-password $ sherpa secrets create --type=plaintext ./hosts/framework-16/secrets/luks-password # Secret: *** # # Created ./hosts/framework-16/secrets/luks-password $ sherpa secrets create --type=plaintext --editor ./hosts/framework-16/secrets/other # Open $EDITOR # # Created ./hosts/framework-16/secrets/other ``` ## Pseudocode ```ts var luksKey string var user string var machineId string var privateHostKey string var publicHostKey string var privateUserKey string var publicUserKey string var disk string if "fde" in features { write("/tmp/luks.key", "root", "root", "700", luksKey) } destroyDisk(disk) formatDisk(disk) mountDisk(disk) mkdir("/persist", "root", "root", "755") mkdir("/persist/etc", "root", "root", "755") write("/persist/etc/machine-id", "root", "root", "444", machineId) mkdir("/persist/etc/ssh", "root", "root", "755") write("/persist/etc/ssh/ssh_host_ed25519_key", "root", "root", "600", privateHostKey) write("/persist/etc/ssh/ssh_host_ed25519_key.pub", "root", "root", "644", publicHostKey) if scenario == "local" { mkdir("/persist/etc/NetworkManager", "root", "root", "755") mkdir("/persist/etc/NetworkManager/system-connections", "root", "root", "700") cp("/etc/NetworkManager/system-connections", "/persist/etc/NetworkManager/system-connections") } mkdir("/persist/home", "root", "root", "755") mkdir("/persist/home/$user", user, "users", "700") mkdir("/persist/home/$user/.ssh", user, user, "700") write("/persist/home/$user/.ssh/id_ed25519", user, user, "600", privateUserKey) write("/persist/home/$user/.ssh/id_ed25519.pub", user, user, "644", publicUserKey) mkdir("/persist/home/$user/.config", user, user, "700") mkdir("/persist/home/$user/.config/nixcfg", user, user, "700") cp(".", "/persist/home/$user/.config/nixcfg") install() ```