#!/usr/bin/env zsh set -e # fail on undeclared variable set -u set -o pipefail readonly cmdname=$(basename $0) readonly machines_repo_entry_point=$MACHINES_PATH/flake.nix # This script cannot run without the nixos configuration entry point if [[ ! -f "$machines_repo_entry_point" ]] then print -P "%B%F{red}Error: Machines repo %F{orange}default.nix%F{red} not found%b%f" >&2 exit 2 fi source $DOTFILES_PATH/bin/lib/util.zsh usage() { print "Usage: $cmdname [--via via_hostname] [--substitute-on-destination|-s] <hostname> [switch|boot|reboot|test|dry-activate|build|iso]" >&2 } positional=() via_hostname="" substitute_on_destination="" keep_going="" show_trace="" while [[ $# -gt 0 ]] do case "$1" in --help|-h) usage exit 0 ;; --via) via_hostname="$2" shift ;; --substitute-on-destination|-s) substitute_on_destination="--substitute-on-destination" ;; --keep-going) keep_going="--keep-going" ;; --show-trace) show_trace="--show-trace" ;; *) positional+=("$1") ;; esac shift done if [[ ${#positional[@]} -ne 1 && ${#positional[@]} -ne 2 ]] then print "Invalid number of arguments." >&2 usage exit 2 fi readonly hostname="${positional[1]}" if [[ ${#positional[@]} -ge 2 ]] then readonly original_operation="${positional[2]}" else # default operation readonly original_operation=switch fi if [[ -z "$via_hostname" ]] then via_hostname="$hostname" fi operation=$original_operation set_profile="" reboot="" readonly common_nix_flags=(--log-format bar-with-logs $keep_going) if [[ "$operation" = "switch" || "$operation" = "boot" ]] then set_profile=1 elif [[ "$operation" = "reboot" ]] then operation="boot" set_profile=1 reboot=1 elif [[ "$operation" = "test" || "$operation" = "dry-activate" || "$operation" = "build" || "$operation" = "iso" ]] then # pass else print_error "Invalid operation: $operation" usage exit 2 fi if [[ "$(hostname)" = "$hostname" ]] then readonly is_target_host=1 else readonly is_target_host="" fi # Update nar-hash of dotfiles repository nix flake lock --update-input dotfiles "path:$MACHINES_PATH" if [[ "$operation" = "iso" ]] then print_info "Building iso image" readonly nixos_iso_path=$(nix build $common_nix_flags --no-link --json "path:$MACHINES_PATH#isos.$hostname" | jq --raw-output ".[0].outputs.out") print_info "Iso generated" print $nixos_iso_path exit 0 fi print_info "Evaluating target system configuration" readonly system_installable="path:$MACHINES_PATH#nixosConfigurations.$hostname.config.system.build.toplevel" readonly nixos_config_path=$(nix path-info $common_nix_flags $show_trace --json "$system_installable" | jq --raw-output ".[0].path") print >&2 "$nixos_config_path" if [[ -z "$nixos_config_path" ]] then print_error "No path was generated" exit 3 fi print_info "Deploying target system configuration" if [[ "$is_target_host" || "$operation" = "build" ]] then # local deploy print_info "Building target system configuration" nix build $common_nix_flags --no-link "$system_installable" if [[ "$operation" = "build" ]] then print_info "Build completed" print $nixos_config_path exit 0 fi if [[ -n "$set_profile" ]] then sudo nix-env --profile /nix/var/nix/profiles/system --set $nixos_config_path fi sudo $nixos_config_path/bin/switch-to-configuration $operation sync if [[ -n "$reboot" ]] then sudo systemctl reboot fi else # remote deploy nix copy $common_nix_flags $substitute_on_destination --to "ssh://root@$via_hostname" "$system_installable" # The manual way to activate a system derivation if [[ -n "$set_profile" ]] then ssh root@$via_hostname "nix-env --profile /nix/var/nix/profiles/system --set $nixos_config_path" fi ssh root@$via_hostname "$nixos_config_path/bin/switch-to-configuration $operation && sync" # This should work instead, but has some bugs at the moment #nixos-rebuild "$operation" --flake "path:$MACHINES_PATH#$hostname" --target-host "root@$via_hostname" if [[ -n "$reboot" ]] then ssh root@$via_hostname "systemctl reboot" fi fi print_info "Update completed"