3 ms·
Is anyone using Nix to standardize local development tool versions? In our company — as in most companies, I suppose — apps rely on a specific toolchain, such
by atombender 5y ago
Is anyone using Nix to standardize local development tool versions?
In our company — as in most companies, I suppose — apps rely on a specific toolchain, such as the Go compiler, Protobuf, linters, PostgreSQL, and so on.
Coordinating these is difficult. We have to maintain documents saying "install Go 1.17" and so on. Some people are on different architectures, though we are all on either macOS or Linux.
The other challenge is coordinating these versions with what's used to build and test. A developer might accidentally develop using different versions than what we build and run with.
Our solution for a subset of these tools is to use Docker. We have helper scripts to let you run some standard versions of some tools. But there is a lot of friction inherent to using Docker, especially on a Mac.
My idea would be to use Nix to specify the complete environment, and that thjs could also be leveraged to run exactly the same environment in automated builds and tests.
That would require running Nix locally as well as inside our Docker builds and CI runs (CircleCI, mostly). How difficult is this?
My concern is that it could be difficult to mix Nix with the parent OS if you don't adopt NixOS wholesale, which I think would be going too far. For example, imagine we want Go and the Protobuf compiler in our toolchain. If we used official Nix packages for these, they probably declare dependencies on things like libc and other libraries that Nix also provides. But we'd like to continue using our Debian Docker images. Maybe instead of using the NixOS packages, we could write our own package tree from scratch for just the limited subset of tools we need?
- ris 5y agoSee `dockerTools` for using Nix to build very minimal docker images.
- SAI_Peregrinus 5y agoMy employer does this. They (the team that maintains this) use Nix & direnv, so local developers get nix-based tool versions when they `cd` into the company repo directories, and whatever their native machine provides elsewhere. They support NixOS, Ubuntu LTS, Pop!OS, and Mac OS for this setup. Anything else and you're on your own, but I use Debian with it and just occasionally submit patches.
- atombender 5y agoThat sounds great. How has the experience been? Is maintaining it a lot of work?
- SAI_Peregrinus 5y agoI don't maintain it in general. Not much work on my end, about the only thing that's failed is if someone whitelists the supported platforms somewhere. It works quite well.
- fesc 5y agoAt work we switched from a big list in our wiki + some shell scripts + brew to a smaller list in our wiki + nix-darwin and I really like the result. Everything which isn't in nixpkgs I prefer to install manually (such as IDEs, VirtualBox, Docker, ...) because the built-in installer/updater is more robust than brew and most of the time brew just invokes the native installer anyways. If something is in nixpkgs though you can be pretty certain that it will work at your colleagues machine just like it does on yours which is great.
- atombender 5y agoThat sounds promising. So let's say the developer has a Mac and wants to have Go and Node on their machine; how do you specify these versions in a central way so that all team members have the same versions of tools? Also, we want to make sure that any Docker image we build uses the same packages. Do we have to migrate our images to be built on NixOS, or can we continue to use Debian base images and simply insert Nix into them? I'd also be interested in learning how much actual Nix packaging is needed. If the packages we need are all in Nix already (like, again, Go and Node and so on), we shouldn't need to actually write any Nix code, I think?
- KingMachiavelli 5y agoFor simple devshell environments, you probably don't need to write much Nix at all. You can use a tool like numtide/devshell [1] to create a flake from a template which lets you define packages and commands you want to expose via a TOML config file. [1] https://github.com/numtide/devshell/blob/master/docs/getting_started.md#Flakes https://github.com/numtide/devshell/blob/master/docs/getting... The reason to use the Flake based version is that then it will automatically create a flake.lock file which should be added to version control so every user will use the same nixpkgs version. While you can build normal Dockerfiles using some Nix tools it would be the same as building the image from Docker directly. If you want the same package-pinning guarantees in Docker images, then you need to build a NixOS based image which will let you add Nix packages. The pkgs.dockerTools.buildLayeredImage and it's counterpart function pkgs.dockerTools.streamLayeredImage, are interesting in that they will build a layered docker image so that packages can be shared between containers which makes rebuilding images much faster. [2] At some point you will probably want to manage the project's Go and Node dependencies themselves from Nix and that involve writing Nix. Essentially the process is to use a tool that convert's the go.mod and node/yarn lock file into a .nix file [3,4]. This can be a bit more involved as some dependencies especially nodejs ones will want to download additional resources at build time which breaks the Nix model. The best way to use Nix is gradually; just start with a simple devshell. There are some oddities when using Nix on Mac so it's best to get those figured out before trying to do too much. [2] https://nixos.org/manual/nixpkgs/stable/#ssec-pkgs-dockerTools-streamLayeredImage https://nixos.org/manual/nixpkgs/stable/#ssec-pkgs-dockerToo... [3] https://nixos.wiki/wiki/Go https://nixos.wiki/wiki/Go [4] https://nixos.wiki/wiki/Node.js https://nixos.wiki/wiki/Node.js