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()
```