easy dev environments with nix and direnv

Posted on May 24, 2025
I recently delved back into the nixos ecosystem, now that it’s more mature - I’ve found a new
at least, new to me (it’s been around a while, alright…)
way to do dev environments for the many different projects, running on many different ecosystems that I have on the go at any given time. Enter the great combination of nix and direnv.

Myself and many others have long extolled the virtues of reproducible builds and nix in general - I won’t do that here (tl:dr - nix is amazing). In short, nix allows for deterministic builds - and pertinent to our current situation, development environments. It means that your team no longer has to say “it works with my setup” - or ask “what gcc version are you on?”.

Note that a big advantage of using nix like this is it doesn’t matter what distro you’re on - and your local dev environment can come for the ride! What’s not to love? Now to the fun bit.

First, install nix and direnv, and make sure to enable flakes. Then find a victim project you wish to make determinate.

Now create a flake.nix file in your project’s root directory - note that this can be a bit different depending on your dev environment, but it generally looks something like
{
  inputs.nixpkgs.url = "nixpkgs/nixos-unstable";

  outputs = inputs:
    let
      supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
      forEachSupportedSystem = f: inputs.nixpkgs.lib.genAttrs supportedSystems (system: f {
        pkgs = import inputs.nixpkgs { inherit system; };
      });
    in
    {
      devShells = forEachSupportedSystem ({ pkgs }: {
        default = pkgs.mkShell {
          packages = with pkgs; [<your packages here>];
        };
      });
    };
}

You can find packages for common programs here.

You can test that this is working by running nix develop. You should get a basic shell with the commands you need. But why stop here? Let’s make it a bit easier to switch between our projects (and keep our preferred shells!).

Now for the final bit - create a .envrc file with the contents use flake, and run direnv allow, which tells direnv not to ignore the file you just created
it does this for security reasons
.

Now when you cd into your project folder, you should see the flake environment activate by default. However, you might notice that it’s a bit slow - you can install nix-direnv, which aims to fix this by caching the nix-shell environment.

Now you’re all set to have easily shareable, reproducible dev environments!