OOKNET                             [ /  search the index  ]  
──────────────────────────────────────────────────────────────────────────────────────
══════════════════════════════════════════════════════════════════════════════════════
OOKNET   [ /  search  ]  
────────────────────────────────────────────────
════════════════════════════════════════════════
 
 
main @ 314 LINES
 
[ HISTORY ]  [ UP ]
 

{
  osConfig,
  config,
  lib,
  pkgs,
  ...
}: let
  inherit (lib) mkIf;
  inherit (builtins) attrValues;
  cfg = osConfig.ooknet.console.tools.ooknet-infra;
in {
  config = mkIf cfg.enable {
    home.packages = [
      (pkgs.writeShellApplication {
        name = "ooknet-provision";
        runtimeInputs = attrValues {
          inherit
            (pkgs)
            gum
            jq
            coreutils
            nixos-anywhere
            ;
          # I could add 1password here but it is included in all workstation confi
gurations by default
        };
        # wrapper around nixos-anywhere with 1password integration for fetching ho
stkeys for
        # secret decryption.
        # this script is not intended for general use, but specifically tailored t
o my needs.
        text = ''
          #TODO:
          # - add options for install-key/target user
          # - add log file output
          # - write this in go
          set -euo pipefail

          hostname=""
          targetIP=""
          targetUser="root"
          localHostConfigDir=""
          installKey=${config.home.homeDirectory}/.ssh/install-key
          additionalFlags=""
          verbose=""
          temp=$(mktemp -d)

          cleanup() {
            find "$temp" -type f -exec shred -uzn 3 {} \;
            rm -rf "$temp"
          }

          helpCmd() {
            cat <<USAGE

          Usage: ooknet-provision [target hostname] [target ip]

          Options:

          * -v, --verbose
            Enable verbose output
          * -o, --extra-options
            Pass additional options to nixos-anywhere
          * -h, --help
            Print help
          * -d, --host-config-dir
            Specify the location of the target hosts confuration location where ha
rdware.nix will be written.
            Defaults to "<FLAKE>/hosts/<hostname>"
          USAGE
          }

          log() {
            local type="$1"
            local message="$2"

            if [ "$type" = "verbose" ]; then
              if [ -n "$verbose" ]; then
                gum log --structured --level debug "$message"
              fi
              return
            fi
            if [ "$type" = "abort" ]; then
              gum log --structured --level error "$message"
              exit 1
            else
              gum log --structured --level "$type" "$message"
            fi
          }

          arguments() {
            while [[ $# -gt 0 ]]; do
              case "$1" in
              -h | --help)
                helpCmd
                exit 0
                ;;
              -v | --verbose)
                verbose="y"
                shift
                ;;
              -o | --extra-options)
                if [[ -z "$2" || "$2" == -* ]]; then
                  log abort "Missing value for -o, --extra-options"
                fi
                additionalFlags="$2"
                shift 2
                ;;
              -d | --host-config-dir)
                if [[ -z "$2" || "$2" == -* ]]; then
                  log abort "Missing value for -d, --host-config-dir"
                fi
                localHostConfigDir="$2"
                shift 2
                ;;
              -*)
                log abort "Unknown option: $1"
                ;;
              *)
                if [ -z "$hostname" ]; then
                  hostname="$1"
                elif [ -z "$targetIP" ]; then
                  targetIP="$1"
                else
                  log abort "Too many positional arguments: $1. Expected [hostname
] [targetIP]"
                fi
                shift
                ;;
              esac
            done
            if [ -z "$hostname" ]; then
              log abort "Target hostname is required. Use: provision <hostname> <t
argetIP> [options]"
            fi

            if [ -z "$targetIP" ]; then
              log abort "Target IP address is required. Use: provision <hostname> 
<targetIP> [options]"
            fi

            if [ -z "$localHostConfigDir" ]; then
              if [ -n "$FLAKE" ]; then
                localHostConfigDir="$FLAKE/hosts/$hostname"
                log verbose "Defaulting local host config directory to: $localHost
ConfigDir"
              else
                log verbose "FLAKE variable not set; cannot form default for local
HostConfigDir."
              fi
            else
              log verbose "Using specified local config directory $localHostConfig
Dir"
            fi
          }

          preChecks() {
            # we need to authenticate early
            log info "Authenicating with 1Password"
            if ! op account get >/dev/null; then
              log abort "Failed to authenicate with 1Password..."
            fi

            log info "Running pre-installation checks..."

            # have you set $FLAKE
            log verbose "Checking FLAKE variable is set..."
            if [ -z "$FLAKE" ]; then
              log abort "FLAKE variable unset, please set the FLAKE variable to th
e root location of the ooknet flake"
            else
              log verbose "FLAKE location found..."
            fi

            # is there a valid nixosConfigurations.$hostname flake output
            log verbose "Checking for nixosConfiguration.$hostname"
            if ! nix flake show "$FLAKE" \
              --json \
              --no-update-lock-file \
              --quiet \
              --all-systems |
              jq -e --arg hn "$hostname" '.nixosConfigurations[$hn]'; then
              log abort "nixosConfigurations.$hostname not found..."
            else
              log verbose "nixosConfigurations.$hostname found..."
            fi

            # ensure $hostname has valid configuration directory
            # we could make this more robust
            log verbose "Checking for $hostname configuration file"
            if [ ! -d "$localHostConfigDir" ]; then
              log abort "Host confguration directory: '$localHostConfigDir' (for h
ardware.nix) does not exist..."
            else
              log verbose "Host configuration directory: '$localHostConfigDir' fou
nd..."
            fi

            # does the configuration evaluate
            log verbose "Evaluting configuration"
            if ! nix eval --raw "$FLAKE"#nixosConfigurations."$hostname".config.sy
stem.build.toplevel; then
              log abort "nixosConfigurations.$hostname.config.system.build.topleve
l failed to evaluate"
            else
              log verbose "nixosConfigurations.$hostname.config.system.build.tople
vel successfully evaluated..."
            fi

            # for jq arg (there is a better way to do this...)
            local target_title="$hostname-hostkey"

            # have you setup a hostkey in 1Password
            log verbose "Checking if hostkey '$target_title' is available in 1Pass
word"
            if ! op item list --vault ooknet --tags hostkey --format=json |
              jq -e --arg title_to_find "$target_title" 'any(.[]; .title == $title
_to_find)'; then
              log abort "Hostkey '$target_title' not found in vault 'ooknet' with 
tag 'hostkey'. Ensure $hostname hostkey has been defined in 1Password"
            else
              log verbose "Hostkey found..."
            fi

            log verbose "Checking for install key"

            if [ ! -f "$installKey" ]; then
              log abort "Install key not found at $installKey"
            else
              log verbose "Install key found..."
            fi

            local ssh_output
            if ! ssh_output=$(ssh \
              -F /dev/null \
              -l "$targetUser" \
              -i "$installKey" \
              -o BatchMode=yes \
              -o StrictHostKeyChecking=no \
              -o ConnectTimeout=30 \
              "$targetIP" \
              true 2>&1); then
              log error "$ssh_output"
              log abort "$0 SSH connection to $targetUser@$targetIP cannot be esta
blished at this time..."
            else
              log info "SSH connection successful..."
            fi
            log info "All checks passed"
          }

          getHostKey() {
            log info "Retrieving Host keys from 1Password vault..."
            install -d -m755 "$temp/etc/ssh"
            if ! op read \
              --out-file "$temp/etc/ssh/ssh_host_ed25519_key" \
              --file-mode 0600 \
              "op://ooknet/$hostname-hostkey/private key"; then
              log abort "Failed to retrieve private host key"
            fi
            if ! op read \
              --out-file "$temp/etc/ssh/ssh_host_ed25519_key.pub" \
              --file-mode 0644 \
              "op://ooknet/$hostname-hostkey/public key"; then
              log abort "Failed to retrieve public host key"
            fi
          }

          deploySystem() {
            log info "Running nixos-anywhere..."

            if [ -z "$localHostConfigDir" ]; then
              log abort "localHostConfigDir is not set. This is a script bug or wa
s not defaulted correctly"
            fi

            local hardware_config_path="$localHostConfigDir/hardware.nix"
            nixos_anywhere_cmd=(
              "nixos-anywhere"
              "--generate-hardware-config" "nixos-generate-config" "$hardware_conf
ig_path"
              "--extra-files" "$temp"
              "--flake" "$FLAKE#$hostname"
              "--target-host" "$targetUser@$targetIP"
              "-i" "$installKey"
            )
            log verbose "Base command: nixos-anywhere with standard options"

            if [ -n "$additionalFlags" ]; then
              log verbose "Adding additional flags: $additionalFlags"

              declare -a extra_args
              read -r -a extra_args <<<"$additionalFlags"

              for arg in "''${extra_args[@]}"; do
                nixos_anywhere_cmd+=("$arg")
              done

              log verbose "Command array now has ''${#nixos_anywhere_cmd[@]} eleme
nts. Full command: ''${nixos_anywhere_cmd[*]}"
            fi

            if [ -n "$verbose" ]; then
              log verbose "Executing: ''${nixos_anywhere_cmd[*]}"
            fi

            "''${nixos_anywhere_cmd[@]}"

            local exit_code=$?
            if [ $exit_code -eq 0 ]; then
              log info "nixos-anywhere completed successfully"
            else
              log error "nixos-anywhere failed with exit code $exit_code"
            fi
          }

          main() {
            arguments "$@"
            preChecks
            getHostKey
            deploySystem
            log info "Installation completed!"
          }

          if [ "$#" -lt 2 ]; then
            helpCmd
          fi

          trap cleanup EXIT
          main "$@"

        '';
      })
    ];
  };
}

{
  osConfig,
  config,
  lib,
  pkgs,
  ...
}: let
  inherit (lib) mkIf;
  inherit (builtins) attrValues;
  cfg = osConfig.ooknet.console.tools.ooknet
-infra;
in {
  config = mkIf cfg.enable {
    home.packages = [
      (pkgs.writeShellApplication {
        name = "ooknet-provision";
        runtimeInputs = attrValues {
          inherit
            (pkgs)
            gum
            jq
            coreutils
            nixos-anywhere
            ;
          # I could add 1password here but i
t is included in all workstation configurati
ons by default
        };
        # wrapper around nixos-anywhere with
 1password integration for fetching hostkeys
 for
        # secret decryption.
        # this script is not intended for ge
neral use, but specifically tailored to my n
eeds.
        text = ''
          #TODO:
          # - add options for install-key/ta
rget user
          # - add log file output
          # - write this in go
          set -euo pipefail

          hostname=""
          targetIP=""
          targetUser="root"
          localHostConfigDir=""
          installKey=${config.home.homeDirec
tory}/.ssh/install-key
          additionalFlags=""
          verbose=""
          temp=$(mktemp -d)

          cleanup() {
            find "$temp" -type f -exec shred
 -uzn 3 {} \;
            rm -rf "$temp"
          }

          helpCmd() {
            cat <<USAGE

          Usage: ooknet-provision [target ho
stname] [target ip]

          Options:

          * -v, --verbose
            Enable verbose output
          * -o, --extra-options
            Pass additional options to nixos
-anywhere
          * -h, --help
            Print help
          * -d, --host-config-dir
            Specify the location of the targ
et hosts confuration location where hardware
.nix will be written.
            Defaults to "<FLAKE>/hosts/<host
name>"
          USAGE
          }

          log() {
            local type="$1"
            local message="$2"

            if [ "$type" = "verbose" ]; then
              if [ -n "$verbose" ]; then
                gum log --structured --level
 debug "$message"
              fi
              return
            fi
            if [ "$type" = "abort" ]; then
              gum log --structured --level e
rror "$message"
              exit 1
            else
              gum log --structured --level "
$type" "$message"
            fi
          }

          arguments() {
            while [[ $# -gt 0 ]]; do
              case "$1" in
              -h | --help)
                helpCmd
                exit 0
                ;;
              -v | --verbose)
                verbose="y"
                shift
                ;;
              -o | --extra-options)
                if [[ -z "$2" || "$2" == -* 
]]; then
                  log abort "Missing value f
or -o, --extra-options"
                fi
                additionalFlags="$2"
                shift 2
                ;;
              -d | --host-config-dir)
                if [[ -z "$2" || "$2" == -* 
]]; then
                  log abort "Missing value f
or -d, --host-config-dir"
                fi
                localHostConfigDir="$2"
                shift 2
                ;;
              -*)
                log abort "Unknown option: $
1"
                ;;
              *)
                if [ -z "$hostname" ]; then
                  hostname="$1"
                elif [ -z "$targetIP" ]; the
n
                  targetIP="$1"
                else
                  log abort "Too many positi
onal arguments: $1. Expected [hostname] [tar
getIP]"
                fi
                shift
                ;;
              esac
            done
            if [ -z "$hostname" ]; then
              log abort "Target hostname is 
required. Use: provision <hostname> <targetI
P> [options]"
            fi

            if [ -z "$targetIP" ]; then
              log abort "Target IP address i
s required. Use: provision <hostname> <targe
tIP> [options]"
            fi

            if [ -z "$localHostConfigDir" ];
 then
              if [ -n "$FLAKE" ]; then
                localHostConfigDir="$FLAKE/h
osts/$hostname"
                log verbose "Defaulting loca
l host config directory to: $localHostConfig
Dir"
              else
                log verbose "FLAKE variable 
not set; cannot form default for localHostCo
nfigDir."
              fi
            else
              log verbose "Using specified l
ocal config directory $localHostConfigDir"
            fi
          }

          preChecks() {
            # we need to authenticate early
            log info "Authenicating with 1Pa
ssword"
            if ! op account get >/dev/null; 
then
              log abort "Failed to authenica
te with 1Password..."
            fi

            log info "Running pre-installati
on checks..."

            # have you set $FLAKE
            log verbose "Checking FLAKE vari
able is set..."
            if [ -z "$FLAKE" ]; then
              log abort "FLAKE variable unse
t, please set the FLAKE variable to the root
 location of the ooknet flake"
            else
              log verbose "FLAKE location fo
und..."
            fi

            # is there a valid nixosConfigur
ations.$hostname flake output
            log verbose "Checking for nixosC
onfiguration.$hostname"
            if ! nix flake show "$FLAKE" \
              --json \
              --no-update-lock-file \
              --quiet \
              --all-systems |
              jq -e --arg hn "$hostname" '.n
ixosConfigurations[$hn]'; then
              log abort "nixosConfigurations
.$hostname not found..."
            else
              log verbose "nixosConfiguratio
ns.$hostname found..."
            fi

            # ensure $hostname has valid con
figuration directory
            # we could make this more robust
            log verbose "Checking for $hostn
ame configuration file"
            if [ ! -d "$localHostConfigDir" 
]; then
              log abort "Host confguration d
irectory: '$localHostConfigDir' (for hardwar
e.nix) does not exist..."
            else
              log verbose "Host configuratio
n directory: '$localHostConfigDir' found..."
            fi

            # does the configuration evaluat
e
            log verbose "Evaluting configura
tion"
            if ! nix eval --raw "$FLAKE"#nix
osConfigurations."$hostname".config.system.b
uild.toplevel; then
              log abort "nixosConfigurations
.$hostname.config.system.build.toplevel fail
ed to evaluate"
            else
              log verbose "nixosConfiguratio
ns.$hostname.config.system.build.toplevel su
ccessfully evaluated..."
            fi

            # for jq arg (there is a better 
way to do this...)
            local target_title="$hostname-ho
stkey"

            # have you setup a hostkey in 1P
assword
            log verbose "Checking if hostkey
 '$target_title' is available in 1Password"
            if ! op item list --vault ooknet
 --tags hostkey --format=json |
              jq -e --arg title_to_find "$ta
rget_title" 'any(.[]; .title == $title_to_fi
nd)'; then
              log abort "Hostkey '$target_ti
tle' not found in vault 'ooknet' with tag 'h
ostkey'. Ensure $hostname hostkey has been d
efined in 1Password"
            else
              log verbose "Hostkey found..."
            fi

            log verbose "Checking for instal
l key"

            if [ ! -f "$installKey" ]; then
              log abort "Install key not fou
nd at $installKey"
            else
              log verbose "Install key found
..."
            fi

            local ssh_output
            if ! ssh_output=$(ssh \
              -F /dev/null \
              -l "$targetUser" \
              -i "$installKey" \
              -o BatchMode=yes \
              -o StrictHostKeyChecking=no \
              -o ConnectTimeout=30 \
              "$targetIP" \
              true 2>&1); then
              log error "$ssh_output"
              log abort "$0 SSH connection t
o $targetUser@$targetIP cannot be establishe
d at this time..."
            else
              log info "SSH connection succe
ssful..."
            fi
            log info "All checks passed"
          }

          getHostKey() {
            log info "Retrieving Host keys f
rom 1Password vault..."
            install -d -m755 "$temp/etc/ssh"
            if ! op read \
              --out-file "$temp/etc/ssh/ssh_
host_ed25519_key" \
              --file-mode 0600 \
              "op://ooknet/$hostname-hostkey
/private key"; then
              log abort "Failed to retrieve 
private host key"
            fi
            if ! op read \
              --out-file "$temp/etc/ssh/ssh_
host_ed25519_key.pub" \
              --file-mode 0644 \
              "op://ooknet/$hostname-hostkey
/public key"; then
              log abort "Failed to retrieve 
public host key"
            fi
          }

          deploySystem() {
            log info "Running nixos-anywhere
..."

            if [ -z "$localHostConfigDir" ];
 then
              log abort "localHostConfigDir 
is not set. This is a script bug or was not 
defaulted correctly"
            fi

            local hardware_config_path="$loc
alHostConfigDir/hardware.nix"
            nixos_anywhere_cmd=(
              "nixos-anywhere"
              "--generate-hardware-config" "
nixos-generate-config" "$hardware_config_pat
h"
              "--extra-files" "$temp"
              "--flake" "$FLAKE#$hostname"
              "--target-host" "$targetUser@$
targetIP"
              "-i" "$installKey"
            )
            log verbose "Base command: nixos
-anywhere with standard options"

            if [ -n "$additionalFlags" ]; th
en
              log verbose "Adding additional
 flags: $additionalFlags"

              declare -a extra_args
              read -r -a extra_args <<<"$add
itionalFlags"

              for arg in "''${extra_args[@]}
"; do
                nixos_anywhere_cmd+=("$arg")
              done

              log verbose "Command array now
 has ''${#nixos_anywhere_cmd[@]} elements. F
ull command: ''${nixos_anywhere_cmd[*]}"
            fi

            if [ -n "$verbose" ]; then
              log verbose "Executing: ''${ni
xos_anywhere_cmd[*]}"
            fi

            "''${nixos_anywhere_cmd[@]}"

            local exit_code=$?
            if [ $exit_code -eq 0 ]; then
              log info "nixos-anywhere compl
eted successfully"
            else
              log error "nixos-anywhere fail
ed with exit code $exit_code"
            fi
          }

          main() {
            arguments "$@"
            preChecks
            getHostKey
            deploySystem
            log info "Installation completed
!"
          }

          if [ "$#" -lt 2 ]; then
            helpCmd
          fi

          trap cleanup EXIT
          main "$@"

        '';
      })
    ];
  };
}
 
──────────────────────────────────────────────────────────────────────────────────────
OOKNET
────────────────────────────────────────────────
OOKNET