Little bites of nix, with mise (seeking design feedback)

I keep running across problems that nix would solve at work. But I don’t think I’ll be able to make the case that we should nixify everything. There are still things here and there that I’m struggling to nixify, and I can’t lead that charge until I’ve figured them all out. So I’m seeking ergonomic ways to include nix just for the stuff I’m confident about.

I saw support nix environments · Issue #1302 · jdx/mise · GitHub it gave me an idea: If nix were just yet another supported backend for mise it would give my co-workers a fallback:

If Matt’s nix stuff fails, we can just switch to the homebrew backend, which is what we’re having people do manually anyway. Nix or not, it’s still worth capturing our dependency versions somewhere.

So I’m interested in helping make that happen. I commented in that issue with my idea for what the nix side of such a handoff would look like. Can I get someone to take a peek at what I wrote there?

I have no idea if my perspective is such that other nix users would go:

yeah that’s alright

Or if it would be:

that was a dumb way to do it

If it’s the latter, I’d like to hear about it up front rather than investing in a dumb approach and hearing about it later on.

1 Like

This sounds like a great idea to give more people a way to try Nix that feels safe in their context.

Your proposal is alright given what we have. It’s worth noting though that @roberth was recently making a bit of progress on an idea that has been floating around for a while, namely cleanly separating environments produced by derivations and derivation build execution environments: `devShellTools`: add environment functions by roberth · Pull Request #324789 · NixOS/nixpkgs · GitHub

For a tool like mise it may not even be necessary to use mkShell – just provide the buildEnv output and let the consumer take it from there.

I agree with @FRidh that mkShell was a mistake, and would add that nix-shell should not exist.

1 Like

Thanks for taking a look. I’ll take a look at the devShellTools PR you linked, looks interesting.

Can I trouble you with a few follow-on questions?

  1. Re: the use of buildEnv as a hand-off to misemkShell provides more than buildEnv (i.e. it has shell hooks). So we potentially lose something by using buildEnv. I’m thinking that in most cases this is not a problem because whatever might have been handled by those hooks can instead be handled in one of two ways:
  • by configuring mise to do whatever the shell hook did
  • by using something like wrapProgram to repackage the tool to have the needed env

Does anything come to mind where this wouldn’t work? I’d feel pretty silly if I blindly disallowed large swaths of nixpkgs because I overlooked a use case here.

  1. Flake outputs support packages (for use with nix build) and apps (for use with nix run). packages seems to have more examples floating around, but a package can be anything right? You could be building something that doesn’t even execute, like a pdf. Would apps be a more appropriate place, since these are assumed to be runnable? I’d hate to put mise in a position where it now has to make a shaky assumption how to run an arbitrary package when maybe nix can provide more guidance.

  2. I’m aware flakes are not universally loved (my attachment to them just has to do with the timing of my arrival in this community). It feels like whatever I come up with re: referencing a flake will probably have something analogous which works on an arbitrary nix file (e.g. mise.nix). Do you think that’s the case, or should I worry about the non-flake case up front?

Thanks again!

Yes, you just need to output something that contains an executable that will be run by the consumer. That executable may as well be “run $SHELL with all the environment variables from this attribute set”.

Arbitrary packages will be arbitrary packages. You can hope that upstream authors will put executables into /bin and that Nixpkgs may expose a meta.mainProgram.

Nix proper doesn’t have a notion of anything more sophisticated than file system trees. The constraints imposed by all that comes with flakes are quite opinionated, and that’s intended. But one reason none of that is stable is that – from what I observe – it’s by far not universally agreed-upon by maintainers of the ecosystem.

Ideally we’d finally come up with a Nixpkgs convention to derive composable environments from packages, the last effort around that stalled: Nixpkgs CLI Working Group Member Search Help appreciated!

From experience, it’s much easier to work up from pure Nix expressions and wrap that in flakes when needed than doing everything monolithically first and then refactoring the other way around. The example you’ve posted primarily uses Nixpkgs facilities, and only needs flake references to pull in remote sources.

This can be separated into the business logic that produces file system trees (Nixpkgs package recipes, or whatever really) and any mechanism to provide file sources for these recipes. mise could even have its own?

Also, enabling backwards compatibility is really not as easy as you’d think. Forward compatibility on the other hand is not just trivial but actually beneficial for code organisation and conducive to different ways of consuming the code.

In any case, I’d personally advise against baking flakes into everything by default. It’s a usage paradigm for Nix that is pretty much oriented towards end-users of closed systems rather than developer-users of library components, and it seems to me that you’re trying to facilitate the second use case here.

1 Like