Using nix-env --from-expression


I’ve created a derivation which is a Python application with optional plugins. The derivation is either usable as-is (ie. foobar) or with the withPlugins function (ie. foobar.withPlugins [ bar baz ]) so the user can control which plugins they want.

I managed to use my derivation in configuration.nix (using foobar = import <foobar> {}; foobar.foobar.withPlugins [ foobar.baz ]) but I’d like to give instructions to people on how to install it with nix-env. Here’s what I tried doing (I’ve already added foobar as a channel, which exposes a set with foobar, foo and bar which are the derivations):

nix-env -i -f '<foobar>' -E 'foobar: foobar.foobar.withPlugins [ ]'

However this gives me error: value is a function while a set was expected, at (string):1:9. My understanding from the manpage is that the foobar argument would receive the set from <foobar>, which contains the elements foobar, foo and bar.

I managed to get it to work that way, but I was hoping I could get a shorter syntax:

nix-env -i -E 'f: let foobar = import <foobar> {}; in (foobar.foobar.withPlugins [ ])'

If you need more info here’s the default.nix file from the channel:

You probably mean this part:

The error message is indeed confusing, because it refers to the specified file, not the expression. Your default.nix returns a function. I couldn’t find in the manual where it says the file should evaluate to a set, but that’s what it has to do.

If you don’t want to change your default.nix, you can shorten your expression to

nix-env -i -E 'with import <foobar> {}; foobar.withPlugins [ foo ]'

Thanks! Changing default.nix did the trick. I think it would be nice to have this somewhere in the manual, I found the “channels” part was lacking a part “creating your channel”, which could give this information.

By the way, I used home-manager as an inspiration, and their default.nix is a function. Not sure why?

Channels are getting deprecated for good reason. Not sure what’s the official one, but so far they mostly confused the hell out of me. I expected stuff to follow what was specified in my configuration files, but then something in the environment changed and everything suddenly rebuilds. When I want automatic updates, I specify a git branch to follow, at least that’s immediately visible.

Anyway, having functions for your derivation allows users to compose your package into their environment, in that case by basing it on whatever version of nixpkgs currently in use. Thats why every package definition in nixpkgs is a function which takes dependencies as arguments - to make them explicitly configurable.