I have tried to get warm with Nix a few times, but it never quite clicked for me.
My use case is the following: I’m a computer science master’s students and I want to do reproducible projects. For me, this means:
a) When we publish something and its code, the readers should be able to run this without having to figure out the necessary software and dependencies themselves. Ideally, they would need to install one “installation framework” (Nix?), and then run a single command, and this command would install all the necessary software and libraries (at exactly the same versions that we used while creating the code) into the project directory, so that the readers can easily verify the results and play with the code. There would be no complications occurring on what software and libraries they have installed globally on their computer. We can assume that they are using a Unix-based operating system.
b) My team members who I collaborate with on the code together should be able to use exactly the same software on their devices. If a) works, this should also work. Moreover, they should also be able to easily install software into the project themselves, which we share via Git.
So, my first question is: Is Nix really suited to this? My understanding is that while the focus of Nix is to have reproducible operating system states, Nix does aim at use cases like mine, is this correct? Or is Nix less suitable for this task than, for example, Docker?
I will briefly describe my workflow with tools like NPM, and then my question will be: (How) can I imitate this workflow with Nix?
When working with NPM, the following commands are crucial for me:
npm init: This creates a file with boilerplate. As a consequence, I never need to create or modify files myself, I can do everything conveniently on the command line.
npm install mypackage: This command figures out the latest version of the package and adds an entry with the exact version to a lock file within the project directory. It also figures out the versions of all the indirect dependencies and adds them to this file. There is some way of differentiating between direct and indirect dependencies. The lock file can be shared via version control and is the basis for collaboration with the same software.
npm install: This checks the lock file in the project directory, and installs the software; either to a subdirectory within the project directory that is excluded from version control, or to a global location. Where it is actually installed does not matter to me as a user.
npx mypackageis an easy way of running the package (if it is executable). In the Python package managers, I would have the choice between starting a shell with a virtual environment (
poetry shell), or using a command such as
poetry run mypackage.
npm-check-updateschecks whether there are (potentially breaking) updates to my packages, and lets me choose whether I want to change to them. This command is less important than the other ones for me.
Is there a way to transfer this workflow to Nix?
When I tried Nix, I found a relatively convenient way to install packages at the level of an operating system user (with
nix-shell, as far as I remember) – but the only way to do things at the level of a project was to create Nix files by hand, which I struggled with and which it would be very hard to convince team members to learn.
Looking forward to your ideas!