Before that I used giant Docker image with all sorts of build tools installed/built, plus persistent VMs which had to be maintained manually, and Nix made it so much easier. Nixpkgs provides a good foundation - it has almost all software you may need and all the utilities to modify it or add new software. Need to patch or switch to custom version some obscure dependency of a compiler building another compiler building a library you use? Override a derivation, and all the dependent stuff will be rebuilt automatically. For building software Nix can be seen as a kind of super-Docker - Nix store allows for more granular caching than just layers, so incremental improvements can be done much faster. Essentially Nix turns files and packages into values in a programming language, so instead of hacky bash scripts trying to imperatively maintain a file dump, you just compose immutable packages by writing expressions.
That said, Nix is really hard to understand at first, comparable to Haskell/monad tutorials. I remember I made a few unsuccessful attempts at it over a ~6 month period, every time becoming more desperate, and then it finally clicked after careful reading of Nix pills [2] for a few consecutive days. To me, the most interesting thing to discover was that while Nix/nixpkgs do necessarily use some "hard" concepts like fixed point, it is in fact quite "old-school" and mostly about Unix, executables, linking, string templating, contains a lot of bash scripts, etc, so it's not really another Haskell. In fact, traditional building of C/C++ software with autotools is supported in Nixpkgs better than building modern stuff like Rust or Go, due to reliance of the latter on own package managers.