diff --git a/configs/nixos/AGENTS.md b/configs/nixos/AGENTS.md index 064dc22..c127e3a 100644 --- a/configs/nixos/AGENTS.md +++ b/configs/nixos/AGENTS.md @@ -50,7 +50,10 @@ directories already exist inside the read-only source. For aggregate Copyparty volumes such as `/srv` with nested `/srv/inbox`, keep the guest bind mount writable and enforce read-only behavior through Copyparty access plus service `ReadWritePaths`. -- `deploy-to` builds from the source checkout and activates a copied closure on the target. +- `deploy-to` builds from the source checkout and activates an imported closure on the target. Do not rely on a target-local monorepo checkout for remote deployment. +- On Pikachu, `nix copy --to ssh://pikachu` accepted a small `nix store add-file` probe, + but rejected locally built system paths that lacked trusted signatures. + Use a sudo `nix-store --import` path for unsigned deploy closures. - Do not hand-author `hardware-configuration.nix` for a host that has not been generated on that machine. Generate it on the target system or live ISO, then stage it before evaluating the flake. diff --git a/configs/nixos/modules/shell/fish/default.nix b/configs/nixos/modules/shell/fish/default.nix index 42de91d..7808133 100644 --- a/configs/nixos/modules/shell/fish/default.nix +++ b/configs/nixos/modules/shell/fish/default.nix @@ -99,7 +99,7 @@ in }; deploy-to = { - description = "Build the current checkout locally, copy it to a host, and activate it"; + description = "Build the current checkout locally, import it on a host, and activate it"; body = builtins.readFile ./functions/deploy-to.fish; }; diff --git a/configs/nixos/modules/shell/fish/functions/deploy-to.fish b/configs/nixos/modules/shell/fish/functions/deploy-to.fish index 09503d7..4e3c043 100644 --- a/configs/nixos/modules/shell/fish/functions/deploy-to.fish +++ b/configs/nixos/modules/shell/fish/functions/deploy-to.fish @@ -34,10 +34,40 @@ if test (count $system_path) -ne 1 return 1 end -echo "deploy-to: copying $system_path to $host" >&2 -nix copy --to ssh://$host $system_path +set nar_file (mktemp --suffix=.nar) +or return $status +set remote_nar "/tmp/deploy-to-$host-"(date +%s)"-$fish_pid.nar" + +set closure_paths (nix-store -qR $system_path) or begin - echo "deploy-to: copy failed for $host" >&2 + set query_status $status + rm -f $nar_file + echo "deploy-to: closure query failed for $host" >&2 + return $query_status +end + +echo "deploy-to: exporting closure for $system_path" >&2 +nix-store --export $closure_paths >$nar_file +or begin + set export_status $status + rm -f $nar_file + echo "deploy-to: closure export failed for $host" >&2 + return $export_status +end + +echo "deploy-to: copying closure archive to $host:$remote_nar" >&2 +scp $nar_file $host:$remote_nar +set scp_status $status +rm -f $nar_file +if test $scp_status -ne 0 + echo "deploy-to: closure archive copy failed for $host" >&2 + return $scp_status +end + +echo "deploy-to: importing closure on $host" >&2 +ssh -t $host "sudo sh -c 'nix-store --import < $remote_nar' && rm -f $remote_nar" +or begin + echo "deploy-to: closure import failed for $host" >&2 return $status end