Copy nix closure to a machine without nix installed

Suppose I build a package with nix and a customized store (say /opt/bla). Can I copy everything in /opt/bla to some other machine’s /opt/bla, and be able to run my program? The target machine has no nix installed.

I think there’s some glibc complication, but I’m not understaing it properly.

You can:

nix copy nixpkgs#hello --to /tmp/tmpstore
podman run -it --rm -v /tmp/tmpstore:/nix/store alpine:latest

# in container
ls /nix/store
/nix/store/1apy255z15pclskgkzsbzldgdn87zbyr-hello-2.12.2/bin/hello

I guess there’s no glibc complication, after all?

Can I do the following:

Configure nix to use local store (which gives up official cache, sadly):

store = local?store=/opt/bla/store&state=/opt/bla/state&log=/opt/bla/log

Then build hello from scratch. Finally:

nix copy nixpkgs#hello --to /tmp/tmpstore

and copy /tmp/tmpstore to /opt/bla in a remote host. Ideally, a user from the remote host can run hello from nixpkgs, regardless of his/her own glibc versions, etc.

Would what I proposed above work?

Building a package with a custom store, in the sense you mean, is hard. You need to compile nix differently to do it. Of course the cache will be useless, and you’ll need to compile the entire closure of your package. It is possible, however.

Nix options that use an alternate store, still build things to run out of /nix/store, they just bind that to a different location on the host OS. You’d need that directory to be accessible under /nix/store in order to run anything from it.

It’s very seldom worthwhile to actually use another store path in the truest sense.

@yipengsun Unless you have a specific reason for having an actual nix store on the target machine, you should have a look at GitHub - NixOS/bundlers: Aggregated bundlers [maintainer=@tomberek, @Artturin]

It’s a HPC environment which the admin refuses (unsurprisingly) to allow us install nix, and the userspace namespace is disabled for paranoid reasons.

I’ve been playing around with a statically linked nix, and set its store to use /opt/bla. So far it is building things.

I’m just wondering if I can somehow expose my /opt/bla so that the workers managed by slurm can pick the programs compiled by me and run them properly, without nix installed.

If all the store’s files are in the place their build processes expected them to be, it really doesn’t matter if nix is installed. Files are files.

The programs don’t know about nix, just certain file paths.

1 Like

That certainly makes sense, and was my initial impression as well. But then I asked the question to Gemini Pro, and it insisted that:

[the kernel] doesn’t know that the file at that path is supposed to be the system’s dynamic linker.

Which made my rather uneasy.

In truth, I should’ve read the ELF’s spec and check about the libc situation myself, but I don’t have a lot of free time RN.

The kernel doesn’t register the system’s linker in the first place. Its filesystem path is listed in the metadata of a dynamic executable. Nix-built executables will list linkers inside the store. That’s certainly not a sensible argument.

2 Likes

Ignore the AI slop. As long as you’ve got all dependencies in the store you should be fine. Just remember that store paths to your binaries change with updates, so you might want to create some wrappers during your build or some helpers to add the relevant store paths to your PATH environment variable.

2 Likes