escaping dependency hell with nix
the problem
every developer has been there. you clone a repo, run the build, and get a wall of errors because your version of python is wrong, or a native library is missing, or the tool expects glibc 2.31 but you have 2.35.
dependency hell is not a nix problem. it's the default state of software development without nix.
what nix actually is
nix is three things: a package manager, a build system, and a language. the key insight is reproducibility by construction.
every package in nix is identified by a cryptographic hash of all its inputs — source code, compiler version, build flags, dependencies. if two builds have the same hash, they produce identical output. bit-for-bit.
{
description = "my rust project";
inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
outputs = { self, nixpkgs }: {
devShells.default = nixpkgs.legacyPackages.x86_64-linux.mkShell {
packages = with nixpkgs.legacyPackages.x86_64-linux; [
rustc cargo clippy rust-analyzer
];
};
};
}
the nix store
everything nix installs goes into /nix/store. each package lives in its own directory named by its hash:
/nix/store/abc123-rustc-1.75.0/bin/rustc
/nix/store/def456-rustc-1.76.0/bin/rustc
two versions of the same tool coexist without conflict. no symlink gymnastics. no virtualenvs. no pyenv, rbenv, nvm, or any other version manager.
nix flakes
flakes are nix's answer to lockfiles. flake.lock pins every input to an exact commit hash. share the flake, get identical environments across every machine.
the learning curve
i won't lie: nix is hard to learn. the language is lazy and functional in ways that surprise you. error messages are cryptic. the documentation is scattered.
but after six months, i deleted homebrew, asdf, and docker from my machines. my development environments boot in seconds and work identically on my laptop and my CI server.