Copy nix store to another machine?

Here’s the scenario:
I have 2 nixos machines, one laptop and one desktop. The desktop machine has limited or no internet access - enough to check emails but not enough to download 3GB for nixos-rebuild switch --upgrade.

I keep the laptop up to date, and can build the whole desktop from my laptop:

nix-build desktop.nix
nix-copy-closure --to desktop result/

Everything works fine in this scenario, until you want to nixos-rebuild on the desktop.
If I execute nixos-rebuild --switch from the desktop, it’s nix channel is super oudated and it can’t even parse the configuration.nix. If i run sudo nixos-rebuild switch --upgrade from the desktop, it parses configuration.nix but wants to download 3GB of stuff that the laptop likely already has.

Am I missing something obvious?

Sounds like you are using channels and the stable Nix interface, which means that unless your channels on both machines match up to the exact same commit, that building the closure on the laptop and copying the closure won’t accomplish much, since a different commit of nixpkgs means the hash of everything will be different.

A simple workaround for this would be to use the in built remote functions of nixos-rebuild, namely the --build-host and --target-host options. That way, the script will actually handle building and installing the desktop directly from the laptop. All that’s required is an ssh connection from one to the other, which it sounds like you already have.

1 Like

Looking at your answer, I think my question was probably not super clear.
Both computers are on nix unstable FWIW.

You can run nix build, nix-copy-closure, and run result/bin/switch-to-configuration switch on the desktop (–target-host) with my setup.

The only problem is that you always need to be building it’s configuration from the laptop.
What I want is the ability to copy all the relevant nix store contents from the laptop to desktop, so that nix-build desktop.nix works the same on laptop and desktop.

Well if you are using nix-build then you probably aren’t using flakes? What is really relevant is whether you are relying on nix-channel to set your system revision, or if you are using a “flake.nix” to pin your system declaratively.

In the latter case, it’d be simple enough to build the system output as follows from the flake root: nix build .#nixosConfigurations.\<someConfig\>.config.system.build.toplevel and then nix copy result ssh://your-desktop-url.

If you are using channels then my previous answer still holds, the script just does what you are wanting to do, but automatically. If you insist on doing in manually though then you’ll need to build the system with something similar to this:
nix-build -I nixos-config=./configuration.nix '<nixpkgs/nixos>' -A system and then copy the result over to the desktop system. Unless the channel revisions match though, you’ll have to call the activation script manually, which irrc, doesn’t update the bootloader entry properly. So I still highly suggest you just use nixos-rebuild in that case.