How to push the derivations from a shell.nix to cachix?

I use a shell.nix file for project development. This file contains custom derivations that I would like to push to cachix to avoid rebuilding them if these are deleted by the garbage collector.

Unfortunately, nix-build shell.nix | cachix push smaret does not work:

% nix-build shell.nix  | cachix push smaret
these derivations will be built:
  /nix/store/mclpppsyq5fjka6bmp1046n09zv97808-nix-shell.drv
building '/nix/store/mclpppsyq5fjka6bmp1046n09zv97808-nix-shell.drv'...
nobuildPhase

This derivation is not meant to be built, aborting

One workaround is to copy the shell.nix file to default.nix and to replace the pkg.mkShell function with pkg.buildEnv function. But that’s a bit combersome.

Is there another way to do this?

Just want to point out that one alternative might be to use Lorri, which automatically creates GC roots so you won’t have to worry about it.

The other option is to use nix-shell --indirect --add-root wherever/is/fine[1].

For getting a handle on the derivation for pushing to cachix, you could get it like this: nix-instantiate shell.nix

[1]: This really is not documented well:
You can find it by following some manpages in this order: nix-shell → nix-instantiate → nix-store, which says:

--add-root path
    Causes the result of a realisation (--realise and --force-realise) to be
    registered as a root of the garbage collector. The root is stored in path,
    which must be inside a directory that is scanned for roots by the garbage
    collector (i.e., typically in a subdirectory of /nix/var/nix/gcroots/) unless
    the --indirect flag is used.

    If there are multiple results, then multiple symlinks will be created by
    sequentially numbering symlinks beyond the first one (e.g., foo, foo-2, foo-3,
    and so on).

--indirect
    In conjunction with --add-root, this option allows roots to be stored outside
    of the GC roots directory. This is useful for commands such as nix-build that
    place a symlink to the build result in the current directory; such a build
    result should not be garbage-collected unless the symlink is removed.

    The --indirect flag causes a uniquely named symlink to path to be stored in
    /nix/var/nix/gcroots/auto/. For instance,

        $ nix-store --add-root /home/eelco/bla/result --indirect -r ...

        $ ls -l /nix/var/nix/gcroots/auto
        lrwxrwxrwx    1 ... 2005-03-13 21:10 dn54lcypm8f8... -> /home/eelco/bla/result

        $ ls -l /home/eelco/bla/result
        lrwxrwxrwx    1 ... 2005-03-13 21:10 /home/eelco/bla/result -> /nix/store/1r11343n6qd4...-f-spot-0.0.10

    Thus, when /home/eelco/bla/result is removed, the GC root in the auto directory
    becomes a dangling symlink and will be ignored by the collector.

        Warning
        Note that it is not possible to move or rename indirect GC roots, since the
        symlink in the auto directory will still point to the old location.
2 Likes

Thanks, this is what I was looking for,

See How does one use cachix to share nix-shell environments? · Issue #52 · cachix/cachix · GitHub