-
-
Notifications
You must be signed in to change notification settings - Fork 14.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
nixos-rebuild: Allow remote building when using flakes #119540
Conversation
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/building-a-flake-based-nixos-system-remotely/11309/5 |
cc5e29e
to
c4a1855
Compare
c4a1855
to
9241a4d
Compare
if [ -a "$drv" ]; then | ||
NIX_SSHOPTS=$SSHOPTS nix "${flakeFlags[@]}" copy --derivation --to "ssh://$buildHost" "$drv" | ||
# The 'nix-command flakes' part in "${flakeFlags[@]}" is seen as two separate args over SSH | ||
buildHostCmd nix --experimental-features "'nix-command flakes'" build "${buildArgs[@]}" --out-link "${tmpDir}/result" "$drv" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This now requires that the remote host has nix.package = pkgs.nixUnstable
, due to the --experimental-features
flag. I think we should mention that somewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❯ ../nix/nixos-rebuild.sh switch --target-host monitor --flake ~/code/foo#monitor --use-remote-sudo
warning: Git tree '/home/asymmetric/code/foo' is dirty
building the system configuration...
warning: Git tree '/home/asymmetric/code/foo' is dirty
error: unrecognised flag '--experimental-features'
Try 'nix --help' for more information.
error: getting status of '/tmp/nixos-rebuild.u96Og6/result': No such file or directory
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that's true? As I understand it, nixos-rebuild
uses it's own nix
by default. I guess it could be documented for when --no-build-nix
, --build-host
and flakes are combined, but that seems like a rare use-case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, posted before I saw your later comments. I wonder if the --use-remote-sudo
flag is responsible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is already code that builds the latest Nix before attempting to rebuild to exactly avoid that situation, however, currently that is limited to the local machine.
nixpkgs/pkgs/os-specific/linux/nixos-rebuild/nixos-rebuild.sh
Lines 356 to 392 in 37f8212
if [[ -n $buildNix && -z $flake ]]; then | |
echo "building Nix..." >&2 | |
nixDrv= | |
if ! nixDrv="$(nix-instantiate '<nixpkgs/nixos>' --add-root $tmpDir/nix.drv --indirect -A config.nix.package.out "${extraBuildFlags[@]}")"; then | |
if ! nixDrv="$(nix-instantiate '<nixpkgs>' --add-root $tmpDir/nix.drv --indirect -A nix "${extraBuildFlags[@]}")"; then | |
if ! nixStorePath="$(nix-instantiate --eval '<nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix>' -A $(nixSystem) | sed -e 's/^"//' -e 's/"$//')"; then | |
nixStorePath="$(prebuiltNix "$(uname -m)")" | |
fi | |
if ! nix-store -r $nixStorePath --add-root $tmpDir/nix --indirect \ | |
--option extra-binary-caches https://cache.nixos.org/; then | |
echo "warning: don't know how to get latest Nix" >&2 | |
fi | |
# Older version of nix-store -r don't support --add-root. | |
[ -e $tmpDir/nix ] || ln -sf $nixStorePath $tmpDir/nix | |
if [ -n "$buildHost" ]; then | |
remoteNixStorePath="$(prebuiltNix "$(buildHostCmd uname -m)")" | |
remoteNix="$remoteNixStorePath/bin" | |
if ! buildHostCmd nix-store -r $remoteNixStorePath \ | |
--option extra-binary-caches https://cache.nixos.org/ >/dev/null; then | |
remoteNix= | |
echo "warning: don't know how to get latest Nix" >&2 | |
fi | |
fi | |
fi | |
fi | |
if [ -a "$nixDrv" ]; then | |
nix-store -r "$nixDrv"'!'"out" --add-root $tmpDir/nix --indirect >/dev/null | |
if [ -n "$buildHost" ]; then | |
nix-copy-closure --to "$buildHost" "$nixDrv" | |
# The nix build produces multiple outputs, we add them all to the remote path | |
for p in $(buildHostCmd nix-store -r "$(readlink "$nixDrv")" "${buildArgs[@]}"); do | |
remoteNix="$remoteNix${remoteNix:+:}$p/bin" | |
done | |
fi | |
fi | |
PATH="$tmpDir/nix/bin:$PATH" | |
fi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, same thing:
❯ ../nix/nixos-rebuild.sh switch --target-host monitor --flake ~/code/foo#monitor
warning: Git tree '/home/asymmetric/code/foo' is dirty
building the system configuration...
warning: Git tree '/home/asymmetric/code/foo' is dirty
error: unrecognised flag '--experimental-features'
Try 'nix --help' for more information.
error: getting status of '/tmp/nixos-rebuild.Aa5unK/result': No such file or directory
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation for the --build-host
option says that it is also built remotely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, the nix build only happens if flakes aren't used. That's annoying.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed it to use old-style nix commands on the build host. It seemed like the most frictionless change to me.
9241a4d
to
456aa2d
Compare
@chvp I think it would be a bit easier to review if you didn't force-push, so we could look at the diff in each commit ❤️ |
@edolstra @worldofpeace @obadz @volth @domenkozar @Mic92 |
Just wanted to mention that I've been using this to build my systems remotely since I created this PR without any issues. |
This PR doesn't change behavior if host is not defined and a few people reported success with it, so let's merge it. |
Prior to NixOS#119540, the toplevel output was built locally then pushed to the remote host when using the command: nixos-rebuild --flake <flake> --target-host remote.host However, buildHost would default to targetHost when only --target-host was supplied. This caused the .drv closure to always be transferred unless --build-host=localhost is supplied. This change restores the previous build local default behavior. TargetHost can still build the outputs, if explicitly mentioned: nixos-rebuild --flake <flake> \ --target-host remote.host \ --build-host remote.host
This wasn't correct because of the following lines:
A previous The consequences was that 2000-4400 store paths would need be transferred instead of the previous 100-400 realised paths. |
Motivation for this change
Remotely building hosts when using flakes should be possible. See also #119448, https://discourse.nixos.org/t/building-a-flake-based-nixos-system-remotely/11309/4, and https://nixos.wiki/wiki/Flakes#Using_nix_flakes_with_NixOS
Things done
I rebuilt my system with this PR, and then used nixos-rebuild to build a host on itself, build a host on another remote host and build the local host on a remote host.
sandbox
innix.conf
on non-NixOS linux)nix-shell -p nixpkgs-review --run "nixpkgs-review wip"
./result/bin/
)nix path-info -S
before and after)