Hacker News new | past | comments | ask | show | jobs | submit login
Zero to Nix, an unofficial, opinionated, gentle introduction to Nix (zero-to-nix.com)
383 points by biggestlou on Jan 23, 2023 | hide | past | favorite | 225 comments



I would love to see a discussion from somebody who really likes Nix on why it isn't ready for prime time yet/just play devil's advocate aloud on why it isn't the greatest thing since sliced bread.

I feel like I must not be doing anything "serious" enough to need package reproducibility at that high level. I'm aware of things like git checkout/tags, package-lock.json, Cargo.lock, Docker image tags.

What is a real world use case where Nix isn't overkill? I've read toolchains but... nvm (node version manager), rustup. I still Rust on a machine once and I never think about it again.

It feels like the Kubernetes of package management/build if you will complexity wise. "Do we really need this or is it just what everybody else is doing?"


> I would love to see a discussion from somebody who really likes Nix on why it isn't ready for prime time yet/just play devil's advocate aloud on why it isn't the greatest thing since sliced bread.

Top reasons in my mind:

1. Error messages. Even with my >1 year of experience using NixOS full-time, I've encountered errors that I simply _cannot_ fix. This is getting better (recent nix releases let you introspect problems more easily).

2. Documentation gaps. Much of the nix docs are actually pretty good now! But sometimes you run into "missing links" that make it really hard.

> What is a real world use case where Nix isn't overkill? I've read toolchains but... nvm (node version manager), rustup. I still Rust on a machine once and I never think about it again.

For me, nix is unbelievably powerful to construct system images for various virtual machine formats. I'm using the nixos-generators[1] project to construct 8 or 9 image formats from one NixOS configuration. Packer and similar tools are the non-nix analog, but nixos-generators requires essentially adding a singular line to support something like Proxmox as opposed to much more work in some other tool.

I'm also using nix to build all our team's software - which varies from Vue.js to Rust to Django - and fold _all_ those development dependencies into a singular nix `devShell`. This means you can clone our repository, use `nix develop .`, and all engineers use the identical verisons of all software, dependencies, and libraries across several toolchains. It's incredibly convenient. (Imagine that you're a .js developer who needs to make a quick edit to a Rust backend route but doesn't sling Rust all day - you don't need to know how to setup rust at all, the `devShell` provides it).

[1]: https://github.com/nix-community/nixos-generators


I'm curious, what the is the bend of nix for your dev env vs using a docker container with everything pre-installed


It's a good question, and a very mature/well-engineered Docker dev environment probably gets you near-parity with an equivalent nix setup. That said, my reasons are:

- Although not _all_ of our projects need nix builds in the end, at least a few do, and acquiring their devshells is essentially zero-effort (you just ask nix for the devshell for the package instead of the package output itself)

- As some other commenters have noted, dealing with large container contexts can get hairy/slow. A devshell just tweaks a few environment variables, which is less of a tangle when working on the various projects (I use direnv, so my emacs session hooks into `flake.nix` and finds everything in-path automatically)

- While you could get a bit-for-bit identical dev environments by pushing a built container image to a registry that all devs pull from, I think most people would write a `Dockerfile` once and let folks build it locally before hopping in, which leaves a small (but extant) possibility that some environments may be subtly different (shifting container tags, ad-hoc apt-get commands, etc). A flake.nix coupled with a flake.lock means all devshells are lock-step identical.


I don't know much about Nix, but I'm planning on reading more about it.

Since you mentioned packer/proxmox/nixos-generators - am I understanding correctly that nix could be used instead of packer to generate a vm image/template for proxmox(or whatever hypervisor)? Is it limited to NixOS or could it create a centos image as an example?

I've used a combination of packer+ansible/chef/salt to create images, but it's always felt a little clunky.


> [...] am I understanding correctly that nix could be used instead of packer to generate a vm image/template for proxmox(or whatever hypervisor)?

That's correct, although as you mention later, it's limited to NixOS. It's an unfortunate constraint given how tremendously powerful it is, but the limitation makes sense. nixos-generators is literally a nix function that accepts a NixOS configuration and operates on the nix value in order to construct the VM image, so it wouldn't work quite the same without nix at the core.

Because nix "knows" about the total definition of the system, nixos-generators can do wonderful things like construct an AMI image or VMWare image without talking to any hypervisor APIs or cloud APIs at all - it knows how to construct the system from the "ground up" and you just end up with a big disk image file after the appropriate `nix build ...` command, no AWS keys or running Proxmox API required.

It's a tradeoff, to be sure. But if the use case fits - which for us, it does quite well - you can be outrageously productive. Adding an entirely new image format takes as long as typing a new line in `flake.nix`, and I leverage a common NixOS module between all the image types to invoke a quick and easy local qemu VM when I'd like to experiment locally.

It's become hard to imagine what managing a "normal" system would be like with the features I get by baking it all into a NixOS configuration.


I love Nix, all of my machines run NixOS, but I think it's 5-10 years out from widespread adoption. Currently the biggest issues have to do with severely lacking documentation, lack of developer tooling (missing things like LSP), very slow iteration cycles, confusing or impossible to understand errors, and even naming (Nix refers to the language, package manager, cli, community, etc).

That said, right now it's still the best tool I've ever used. Nix is great at a few things: reproducible development environments, reproducible builds, and reproducible systems. I introduced Nix at my last job to do most of these things and it helped onboarding dramatically: Nix-based development environments with automatic activation, Nix-based Docker image builds which reuse the work done for the dev environment, and Nix-Darwin configuration to configure systems with one command. It's incredibly powerful and you're able to use as much or as little as you like. So the amount of "overkill" is variable.

Of course, the problem here is that knowledge of Nix itself is necessary to build and maintain these things. Due to the reasons outlined previously, it is quite an investment. I believe it is worth it given the stability, flexibility, and efficiency Nix can provide.


> I think it's 5-10 years out from widespread adoption

To quote Andy Warhol, "They always say that time changes things, but you actually have to change them yourself."

I don't mean you personally! I mean that it's not clear how time is going to fix Nix's documentation.

My guess is that at some point a big company will either clone or copy NixOS and enforce some discipline on the documentation. At that point it'll take over the world.


> I mean that it's not clear how time is going to fix Nix's documentation.

This is my estimate based on the work that has happened over the last two years. There is steady movement in the right direction and the community is organized alongside the NixOS Foundation members to make things happen. Just not at a break-neck pace. Places like Determinate Systems, Tweag, etc are the largest forces currently, but there are plenty of others that are trying to move things along. Over time, that steady movement will land Nix in a place where its pains have been largely dealt with. I don't think we're there yet and, at this pace, won't be for a while.


I have huge respect for those people and I hope you're right.


How would you compare Nix to Guix?

https://guix.gnu.org/en/about/


New to both. In spite of significant interest and weeks of work, I can't even get Guix installed on bare metal on my Mac nor on my older Acer laptop (a converted chromebook) nor on a raspberry pi. New to Nix and have it running with hardly a hitch on all or these.

Reached out to Guix IRC and mailing list with no response (though one helpful HN commenter got back to me -- thank you, and I still need to respond!).

Nix community on the other hand has been extremely helpful on their discourse and has been remarkably welcoming to PRs and contributions in spite of me being a noob.

Will take another look at Guix in a year, it certainly seems to get many things "more right" IMO, but I can't validate that opinion if I can't get it installed.


> I can't even get Guix installed on bare metal on my Mac

macOS is not a supported platform on Guix, right? Is there new/ongoing work to support that?


Correct.

> Is there new/ongoing work to support that?

Not a chance -- very focused on free, from what I gather I don't think they even allow discussion of non-free software.


Ah so have you been trying to trailblaze to port Guix to macOS a bit, then?


No, not smart enough to "port" exactly, was just trying to get the aarch64 binary to run (no luck), and eventually got it working in a VM: https://n8henrie.com/2022/10/guix-system-guixsd-vm-on-an-m1-...


This will not work.

There's no port of the GNU C Library for macOS, and there's no free toolchain that would let us build binaries for macOS.

Possible routes are:

- virtualization (use a GNU system on top of macOS) - arbitrarily cut the graph and graft macOS-built binaries on top of a huge binary blob specific to macOS

Neither of these seem appealing.


Which of these approaches is used by GNU coreutils, GNU sed, GNU grep, etc., on macOS? I love having them whenever I have to use macOS.


> (Nix refers to the language, package manager, cli, community, etc)

Thats wrong. It refers to exactly two things: the language and the cli that implements that and is a package manager at the same time.


So you're saying that it is not a language, package manager, cli and community, but it is a language, a package manager and a cli (and I guess we can assume that talking about the "Nix community" makes sense).

How was the parent wrong again?


There is the nix language and the nix program which is a package manager and cli at the same time. There might also be the running joke in German that nix literally means nothing but there is no etc. nix does not generally refer to anything else.


Sandro is right that the language is called Nix and the CLI is called Nix. Though, part of the trouble is that Nix handles multiple things (eg. Dev environments) and is often referred to separately as the Nix Package Manager. Realistically, people do talk about "Nix" as one of many of these things which confuses a lot of people. Even the name NixOS is confusing for those unfamiliar with Nix.


It is ready for prime time if you are an advanced linux user already. It is the greatest thing since sliced bread if you where using Arch or Gentoo before.

Do you have more than two machines you want to keep in sync? Do you don't want to track custom patches for software? Do you want to make upgrades painless? Do you want to be forced to at least have documentation as code? Do you need to manage a multi user environment and want to know what is configured?

With NixOS you don't need to think about re-installs. They are painless and an order of magnitude easier to do. You know you will get the same configuration back.

Kubernetes is complicated and a good choice for a big team with lots of containers, but rather pointless for a single machine. NixOS already works great for a single machine and scales well for more machines but not as well as k8s. If you are building 100 different machines on hydra, you start to run into scaling problems pretty fast.

So what are actual bad points: - you must work with the nix, not against it. If you want to continue your current workflow and don't change anything, nix will be a big obstacle for you. - you need to invest some time and start climb the steeper learning curve. - documentation could and should be better, especially general guides that enable and teach you how to solve your problems yourself - smaller and bigger rough edges in places that are usually very different to classical distros


> ... why it isn't ready for prime time yet ...

I think for a professional / team setting, its learning curve is sufficiently steep enough that it'd be risky to adopt with only one or two team members familiar with Nix.

Writing Nix code for your own packages varies in difficulty from 'trivial' to 'demands you know a lot about Nix, the compiler, Linux, and your software package'.

> What is a real world use case where Nix isn't overkill? ...

I'd rephrase this as "nix is 2nd best at everything".

So, yeah.. to setup tools you could use asdf; provision a system you could use ansible; to build an image you could use packer; etc. -- But, if you've already paid the (steep) learning curve for nix, it's going to be a better choice when doing anything that involves packages.

I'd put emphasis on "declarative" more than I'd emphasise "reproducible", though.

> It feels like the Kubernetes of package management/build if you will complexity wise.

This is an apt comparison.

However, there Kubernetes alternatives are often simpler with 80% of the power.

With Nix, there's nothing that's simpler that handles as many use cases.


This is a 100% fair point and I do agree that people can be overzealous with pushing Nix. For many projects, Nix is indeed overkill, and it's worth pointing out that some tools, like pnpm, have taken important cues from Nix. In many cases good enough really _is_ good enough and saying "just install npm using Homebrew or whatever you prefer" is totally fine. But when good enough isn't good enough and teammates and would-be contributors burn an hour installing dependencies just to push a small fix, that's where Nix can really shine. Another sweet spot is larger orgs where knowing that you can run `nix develop` in any repo and get everything you need is a legit superpower.


Personally, I think because its feature-set is currently very much "scattered".

Nix is in the transition to use 'flakes': a new concept that gives a bit more structure and allows easier reuse of Nix packages, NixOS modules and more. In addition it includes a standardized 'lock' file. Lock files are quite useful (or even essential) for reproducibility.

However, it is in experimental phase for more than 4 years now. It is behind a configuration flag, so it isn't obvious how to use it. A division in community, projects and documentation happens this way.

Because it is still considered an experimental feature, flakes and its surrounding CLI tools aren't mentioned in the official docs.

Even though it is experimental, flakes is considered an essential part of Nix by a large portion of the community.

This makes those people look for and create their own solutions:

This results in multiple documentation sites:

- Official manual (https://nixos.org/manual/nixos/stable/) - https://nix.dev/ - https://nixos.wiki/ - Blog posts - Now https://zero-to-nix.com/

Multiple wrapping tools for development environments:

- `nix-shell` (non-flake style) - `nix develop` (flake style) - https://devenv.sh/ - https://www.jetpack.io/devbox/ - https://floxdev.com/

It makes sense that these are created. I'm still hoping Nix flakes will become the default and UX can be iterated upon. But it doesn't make the future of Nix all bright and beautiful atm.


> It is behind a configuration flag, so it isn't obvious how to use it.

It is: the error message tells you exactly how to activate it.

> A division in community, projects and documentation happens this way.

No, not really. flakes are not fundamentally different, they just replace channels, a very small component, with something new and more powerful. You can convert any NixOS config in minutes if you just import the configuration.nix, add --impure and add a nixpkgs input.

> its surrounding CLI tools aren't mentioned in the official docs.

There is an entire section in the nix manual about them https://nixos.org/manual/nix/stable/command-ref/experimental...

> This makes those people look for and create their own solutions:

Also not entirely true. Before flakes there where several projects like niv which are now more and more in maintenance mode and got replaced by flakes. There was a need for a feature like flakes in the community for a long time and it it slowly forming shape.

> This results in multiple documentation sites:

Yes, like for any other big ecosystem. There will grow community maintained wiki's, opinionated websites, guides and resources. Is that necessarily a bad thing? We can't prevent people from creating them and not everything fits into the official guide especially if it is opinionated.

> Multiple wrapping tools for development environments:

Same thing. nix-shell is pretty basic and does not have every bell and whistle and people in the community build on top of that, create wrappers and new tools and try to build the bells and whistles. Similar things for example happened in the debian community with for example aptitude and synaptics.

> I'm still hoping Nix flakes will become the default

It will and the tools you listed above won't go away. Flakes do not attempt to replace them and what they try to achieve but to support them.


I think you get that in most posts advocating for nix: its hard to spinup on as a concept/system.

At least for me personally, I've always tried to add that disclaimer, and very few nix-accolades recommend nix _wholesale, no questions asked_ to a random viewer. Almost everyone I know who is all-in on nix recommends nix with caveats, and only after doing some vetting of who you are recommending it to.

That said, even though it is hard... the pain is worth it in the end. Once you get over the hump, its a refreshing ecosystem to rely on overall. One of the main reasons I say that is because it is uniquely positioned to hit both the throwaway script and the production system. You can use it to do all of the following:

  - Install things to the system temporarily
  - Write scripts that are copy-pasteable between machines
  - Setup monorepos with multiple languages targeted
  - Run "bare metal" docker-like systems directly on the host
  - Build bare-minimum docker containers
  - Configure your host OS in a reproducible way
  - Build prod servers in a reproducible way
  - Safely upgrade/rollback a computer
  - Share computer configuration in a simple data-driven manner


Some things are much harder in practice than in theory. I recently had to work with a JavaScript project that doesn’t get a lot of maintenance love. It requires a JavaScript version that is no longer part of Nixpkgs. Now try figuring out how to build just that version and also make Yarn use that version. It’s not incredibly hard but the documentation is not obvious to find.

Then go on a very very long walk while your Darwin machine is now compiling node.

Contrast that with something like Volta which just works and takes minutes to setup.

Or take anything in Node with a postInstall script that tries to download binaries.

Even Haskell that ostensibly has good support in Nix has a lot of flaws unless you use some of the third party Haskell tooling such as Haskell.nix

Quite a few Haskell packages are marked as broken and there’s only a single version of every Haskell package in the Nixpkgs Haskell packages. Meaning you will quickly run into lots of errors because of version bound problems.

Then there’s matters such a what if you install a formatter and a linter through Nix as is often suggested in those super neat tutorials on how to quickly set up a dev environment. But now you’re using a version of these tools that’s decoupled from the rest of the project.

The list goes on and on.


You have similar but yet different problems on other distros, too.

For example if you want to use a very old node version then you either find a prerecompilation for your distro or also compile it yourself. The precompilation might be linked against an older glibc version or compiling does not work with your distros because your icu version is incompatible and then you are in the same rabbit hole.

volta "just works" because it was specifically designed to achieve one defined purpose run on a few platforms and is well tested on those. nix is general and cannot achieve everything. Somewhere maintainers need to cut a line otherwise things get completely out of hand.

Network is restricted in the sandbox because otherwise reproducibility would be severely reduced and we could not guarantee that the outputs match what we expect them to be. Also downloaded binaries would usually need patching anyway.

Also you are not supposed to take everything from nixpkgs. Like on any other distro if you are developing something the ecosystems own tools are the most well equipped and have all the versions. The versions in nixpkgs are the versions we need for other packages and NixOS, not every possible version you could need to develop a project with specific requirements necessarily.

PS: volta did not just work on my NixOS machine because it assumes that relative to glibc there will be a lib directory where it can place things.


> Then go on a very very long walk while your Darwin machine is now compiling node.

Yes, if you fall off the happy-path of cached public hydra builds you can easily go from "a few seconds" to "lol maybe today?". Cross-compilation especially is likely to burn you bad in this regard.


> I would love to see a discussion from somebody who really likes Nix on why it isn't ready for prime time yet

I have several friends who use Nix and generally recommend it.

I do believe I think enough like them to like Nix for the same reasons (declarative, reproducible).

I've asked them to play devil's advocate, and I generally get the downsides, but...

There is one downside that I feel they can't tell me, but they end up telling me indirectly:

Nix is very complicated and takes a long time to learn. It's the Haskell of package managers.

I love Haskell, so it's not even unreasonable that I'll like Nix. But I won't like the learning curve. I spent a decade becoming productive in Haskell, and a year becoming productive in Rust. Will I like for my operating system to have crutches for months as I reconstruct my neural pathways to perform basic navigation?

This is why I think a tutorial like this is great: A gentle introduction, and a lot of courage to spend time, is all you need.

> It feels like the Kubernetes of package management/build if you will complexity wise.

In terms of learning curve, it might not be as bad as Kubernetes.

Kubernetes has a lot of complexity because of its distributed model.

But in terms of learning a new operating system with its own paradigms, it may seem similarly impairing to learn. (You'll lose the same abilities to run things until you figure out what's going on.)

> "Do we really need this or is it just what everybody else is doing?"

We definitely need reproducible builds.

Nix is the best solution to offer this.


My biggest gripe is they invented their own expression language that could have easily been more familiar. Instead it adds to the learning curve.


I don’t mind that they invented a language, but my impression is that it could be a better language. Less dynamic, better error messages.


It's the composability that is the killer feature. Reproducibility is just a prerequisite to that.

It's kind of like Haskell. Composable programs is the sell. Purity is a means towards that.


> would love to see a discussion from somebody who really likes Nix on why it isn't ready for prime time yet

The daemon needs to be run as root root in a standard multi-user install which rules out HPC-like envs where Nix would actually shine. There are workarounds but none of them official.

Tooling and documentation are on the same level as for a random esoteric programming language. I love Nix but have been hesitant so far to push it at work despite immense productivity gains.

Similarly to HPC, Nix looks like a perfect match for CI/CD pipelines on the surface. In reality the only easy way to get it done is to use additional non-foss software [1].

[1]: https://discourse.nixos.org/t/recommendations-for-introducin...


> The daemon needs to be run as root root in a standard multi-user install which rules out HPC-like envs where Nix would actually shine.

That's an important issue! For those who haven't seen the recent work on it, check it out below.

Théophane Huffschmitt is working on it here: https://github.com/NixOS/nix/pull/5380

and here: https://github.com/NixOS/nix/pull/5226

tracking issue: https://github.com/NixOS/nix/issues/5208

NixCon 2022 talk: https://youtu.be/Gw3LtgbKouc


> There are workarounds but none of them official.

But does it need to be official? Wouldn't that at the same time bloat nix even more? Isn't it enough if core people of the community for example build https://github.com/nix-community/nix-user-chroot ?

> In reality the only easy way to get it done is to use additional non-foss software

That is not true at all. You can use a nix docker image, a 5 line nix file and 2 commands to do a very basic CI pipeline almost anywhere.


> But does it need to be official?

When looking at the up-front time investment and long-term effects, it’s (counterintuitively) crucial that it be official.

If you’re lucky unofficial things eventually end up being official and work fine, but much more often unofficial things die on the vine. If you’re really unlucky the whole branch rots and the system you built on that branch ends up isolated on the ground.

Apologies for stretching the metaphor, it’s been a long day.


> You can use a nix docker image, a 5 line nix file and 2 commands to do a very basic CI pipeline almost anywhere.

Yes, if you don't cache the build results or manage that cache very crudely. Sorry, I wasn't precise enough.


> What is a real world use case where Nix isn't overkill?

When you need to tie together code in two or more different languages. For example if you need to call an Node executable in your rust program. In that case neither npm nor rustup is enough since you need something to tie the two together. Nix is excellent for that in my experience.


Fragmented documentation. Flakes are still "experimental" and their interface subject to change, but they're also widely acknowledged to be the better way to use Nix. There aren't that many Flakes-first docs, and many existing documents describe things that don't really work with Flakes, so the already incomplete & fragmented docs are even more incomplete & fragmented than it seems at first!

AFAICT, there's no way to use the Flakes-based tools (`nix develop` and such) in the shebang of a script, so you have to stick to legacy Nix when making a shell script or Makefile or Python script that uses Nix to set up the environment. That means no lockfile, which is annoying.

Troubleshooting errors can be a horrible exercise in frustration.

Making derivations for particularly complicated build processes can be a massive pain in the ass.


> AFAICT, there's no way to use the Flakes-based tools (`nix develop` and such) in the shebang of a script

For now there's nix-runner: https://github.com/clhodapp/nix-runner


Nice, but that appears to need the (non-portable) `-S` option to `env`. POSIX only requires a single argument string to pass to the utility invoked (though the documentation has it as [argument...] the OPERANDS section uses the singular "a string" form)[1]. Further arguments may be ignored (it's implementation dependent). With `nix-shell` your shebang can be `#! /usr/bin/env nix-shell` and subsequent arguments can be on the following lines, and `nix-shell` itself knows to parse that. Busybox's `env` doesn't support `-S`, and Busybox is the standard shell environment in Alpine (for a common use).

[1] https://pubs.opengroup.org/onlinepubs/9699919799/utilities/e...


UX feedback: for an opinionated guide targeted at newbies, I think the 'concepts' page should be much more of a guided introduction. I click on it and have a big basket of things in _alphabetical order_. I think it should be a top-to-bottom ordering of how a user should read them if encountering for the first time. Maybe have a separate glossary page if thats what you are going for with the alphabetical order.


Thanks for this. Our goal is to keep people on the "rails" of the quick start, with the Concepts as a way to fill out knowledge people are curious about. I wonder if we should downplay the concept docs in service of that? Or put more CTA's to go take the quickstart?


If thats the intent, then it seems the Quick Start is what I'd adjust to be more linear then : )

Again, it looks like a basket of equally-weighted links that a user is free to click into at leisure. It seems more like a directory of useful links rather than a "highly opinionated" guide to get me from zero to proficient.

Compared to something like the sveltekit docs [1] (randomly pulled because I was viewing it today) its much easier to understand the flow of topics, and I think a user can assume they should read them in the presented order unless they understand a given topic already.

[1] - https://kit.svelte.dev/docs/introduction


Actually I just realized I was confused because of the homepage styling. On the homepage it has the "quick start" pill in an active state, which I thought meant I was already _on_ the quick start page. It turns out you click that to actually view page 1 of the quick start. But on that page the "linear list of topics" is only shown when clicking the quick start in the header nav. I would add that to the sidebar by default.


Yeah “Quick Start” is really a misleading title for this “section” as it is really the meat of the site itself.


If that’s the intention the naming of the quick start misleads me. I typically skip the example at the beginning of documentation and go straight into the meat of it. In this case it sounds like I inadvertently skipped the main content.


I like the idea of having a flow through, at least, some of the concepts in the order they should be introduced.


Two years ago I didn't know a thing about nix, NixOS or functional programming. I wanted to manage multiple machines with a sort of config file. Shouldn't be that hard, right? Removal of packages should be done automatically without explicitly removing the package. So brew and ansible failed already with those, to me at the time, pretty basic requirements. Building deb meta packages was inconvenient and they broke every single time when I didn't update a machine for some weeks. Managing requires, replaces, conflicts was cumbersome and often put me into hard problems. Then I learned about nix. First it seemed rather complex. Why does it need to do everything different? Strongly believing that it won't solve my problems and it isn't worth the rather steep learning curve. I tried two weeks to find alternatives but there where none and slowly nix seemed to be the only available solution to my problem which first didn't seem to be that complicated...

Here I am now. With LOTs of struggle and sweat. Never gave up debugging the most strange errors and very often fixing them in the end. Starting as a total beginner and very slowly becoming a very big fan, advocate and contributor to NixOS. Not regretting the journey. Being happy to have remove all Debian frickel kisten from my life. :)

PS: If you run NixOS 22.05 or older: Some parts of the code for your machine is from me. How awesome is that? Couldn't have imagined that two years ago.


Thanks for your work for Nix Sandro.


I'm trying Nix this weekend, and I'm surprised that many part of the core nixpkgs library are mostly undocumented. For example, searching with `"stdenv.isLinux" site:nixos.org -site:discourse.nixos.org -site:releases.nixos.org` returns a single result in total, which only contain the one usage of the function but no other list of available stdenv.is* functions.


Maybe `isLinux` is not the best example, as it's pretty much a self-documented boolean. But when I'm in the general situation you describe, I tend to just search github.com/NixOS/nixpkgs in order to figure out usage, if it's not documented elsewhere already.

Here is an example for isLinux specifically: https://github.com/NixOS/nixpkgs/search?q=isLinux

Reading through how the stdenv stuff is working might help as well, the generic lists a bunch of "is" booleans: https://github.com/NixOS/nixpkgs/blob/7e325cb89453651dbe9a17...

In general I agree, things are vastly under-documented, and that makes it kind of hard, and only solution I've found is digging deeper into sources. Which had the happy side-effect of me understanding NixOS better as well.


If you don't mind, a shameless plug:

https://drakerossman.com/blog/nixos-for-apt-yum-users-a-gift...

I am doing a similar series of NixOS-related stuff, currently got only a single article out, yet quite "meaty".

You may want to check it out for a more streamlined approach in learning nix/NixOS which also compares it to familiar concepts from other Linux distributions. Will be releasing way more complete articles in the nearest future, hopefully within the next 2-3 weeks.


My own shameless plug: nix by example https://mimoo.github.io/nixbyexample/


I really like the foreword, as it captures the best reason to use NixOS on a personal device: it makes your computer yours again. And that feels really good. It can make computers fun again when they've gotten dreary.


As a Mac-using Python shop, we had serious file-sync performance issues when mounting our codebase inside a container via docker-compose. Nix completely freed us from them and allowed us to develop with Python natively speedily and without all the serious faff & headaches that usually comes with getting reproducible builds on everyone machines.

If you'd like to know more, I spoke at DjangoCon Europe late last year [1] on our setup; it's still paying serious dividends for us!

Happy to answer more.

[1] https://www.youtube.com/watch?v=Mx3yiE_CJOY


This is great! Also directly answers some questions commenters have given elsewhere on this submission, e.g., 'why not Docker?'.


Yes! And it’s actually not either/or for us, we still use Docker Compose to run our services (Redis, PostgreSQL, etc) that don’t require file syncing with the host. It’s good at that.


I am a huge fan of all the work Determinate Systems is doing to make Nix easier to use for everyone.


Thank you =)! I'm really happy to hear that the work we're doing is landing with you.


I am glad someone is doing this. There's lots of things in nix I want to try and use but the tooling and docs are just a bridge too far for me, if someone's going to give the initial ux a do over then I'm down for that!


Thanks, Jorge! I think the nix3 interface and the Flakes solve a lot of UX problems. Maybe we could do a bit of a user study, to see where you get hung up?


What's the `nix3 interface`? I use NixOS with Flakes, but frankly it's quite obtuse lol. I don't even know how to specifically update my `nix`. I updated to the latest release the other week and my `nix` CLI is on `2.11`. Are you referencing a 3.0 version of the `nix` CLI? If is there a summary somewhere on what is different between 2.xx and 3.0?

Though i still have no clue how to update to 3.0 if i wanted to. Searching for `nix` is incredibly obtuse given the language is Nix and the OS is Nix. (I know i know, Nix, NixOS, Nixpkgs, but you know what i mean)


It refers to the new CLI, i.e. the "nix" command. The old CLI is the nix-* commands (nix-env, nix-store, etc.). The new CLI and flakes are still marked experimental, but the plan is to stabilize them and call that "3.0". So it won't be very different from the current 2.12 - you just won't need to enable some experimental features anymore to get the new CLI/flakes.


Do you have an idea when the stabilization might come?

I've been using flakes for well over a year and there doesn't seem to be much discernible progress.


Because of politics (see RFC 49, 134, 136), I don't see this actually happening that soon.

There is agreement in principle to carve out a store only Nix so the no-flakes crowd can build their own UI on it which is held by them as a pre-requisite to any stabilisation of flakes, along with some bad blood of it being announced by blog post. But it's slow because the project maintainer and chief flakes advocate doesn't want to adjust the project just so an alternative frontend specifically to avoid their view of an easier Nix should go ahead.

People are still working somewhat constructively towards this in 134, but because their goals feel fundamentally opposed, it seems likely to go on a while.


The Nix team, including the Nix author and chief developer of flakes (upstream in this thread, so be kind all), is also working right now on enabling the nix3 UI for non-flakes setups as well: https://discourse.nixos.org/t/2023-01-16-nix-team-meeting-mi...

Consensus is hard but I'm glad to see people coming together on this. Really looking forward to seeing the new Nix command and flakes move forward (independently)


Funny i don't want a UI, i just want better type systems so some random field is easily known. I know it's difficult, but strictly from a user experience - that's all i want lol.


I'm really optimistic about Nickel, which is a new DSL based on Nix (in terms of inspiration) and designed for Nixpkgs-like use, but informed by the designs of other DSLs in the same space (e.g., Starlark, CUE, JSonnet).

One of the things it adds over Nix's design is types (it grew out of early efforts to add gradual typing to Nix). It has a gradual typing system with 'contracts' for dealing with untyped code.

I have spent some time doing exercises and examples in it, first in Nix code and then translating it to Nickel. It feels very Nix-y, in the best way, and I think in the end it will be very nice to use.

Definitely check it out if you have thoughts about Nixlang and how it could be better! Development is very active and the maintainers seem quite appreciative of testing and feedback.

https://github.com/tweag/nickel


I've been patiently waiting the nickel<->nixpkgs integration. Several hurdles they have to solve first though, iirc, but yea Nickel looks great.

Really that's almost all of my issues with Nix[(pkgs|os)]. Nickel hopefully solves that quite well.. we just need it to work with Nix first, which is a big hurdle on its own.


> I don't even know how to specifically update my `nix`

I just clean reinstalled when I went from v2 to v3. Thats the great thing about nix... the rebuilt system is still the same after I installed : )

Note that in nix v3, updating nix is a simple `sudo nix upgrade-nix`, which is really nice.


Is that with flakes though? That's my thing, i'm using flakes, and it's difficult to know what is with flakes or without.

Updating my root `nixpkgs` did seem to update my `nix` CLI, but that felt a bit heavy handed. I had a difficult time finding out how to override just the Nix CLI version.


Flakes and 'nix command' are actually 2 separate, experimental features. I think the new nix command has some dependence on flakes, but I'm not sure what. I use flakes though, so you should be good as well. I think it would only potentially be an issue for non-flakes?

I really, really, really wish they would rip the band-aid off and just have everything assume flakes with an easy opt-out. Let all the newcomers reap the benefits of a massively simplified model.


Don't those still give you a terrible error message if you use them in a default config?


They do, and using the installer we recommend enables Flakes and the Nix command out of the box: https://zero-to-nix.com/start/install#up.

We think flakes and the new interface are the future, and we're working to bring it home.


> Zero to Nix is opinionated because it advocates learning and using flakes and treating channels as deprecated.

I think I need a “Channels to Flakes”. I have an existing system configuration that seems to work fine without flakes. What am I missing out on?


In your specific case - a _channel_ versus a flake _input_ - consider how you're tracking your system configuration. If you have an /etc/nixos/configuration.nix, then your system can be reconstituted _only_ if you have that configuration.nix in addition to the revision that your channel is currently on. Compare this with a system defined in a flake's `nixosConfiguration`, which accepts its version of nixpkgs from the flake's input, so you can rebuild/recreate the system from the flake entirely without needing to piece together other bits of state like the current channel revision/nixpkgs checkout.


Is this more deterministic than pointing Nixpkgs at a specific commit/tarball in the configuration? I have often done this to make reproducible builds in other Nix settings and it has worked well.


It is: using Flakes you're thrusted into a more pure evaluation mode by default, and it creates a (standard) artifact of the revision you're on: the flake.lock.

You can get almost all the benefits Flakes brings without Flakes using alternatives like niv.


> It is: using Flakes you're thrusted into a more pure evaluation mode by default, and it creates a (standard) artifact of the revision you're on: the flake.lock.

Can you name a specific example of the kind of nondeterminism/nonreproducibility I risk by simply pinning Nixpkgs itself (or to be more principled, using Niv)?


Certain environment variables at the time "nix-build" is executed can affect the nix configuration. Nix flakes default to ignoring those environment variables.

Flakes are also the way forward for pinning nixpkgs; it autogenerates a list of revisions used to pin, and allows easy updating. Flakes and niv, to a large degree, are about solving the same problem.


Yes, because it also makes your Nixpkgs config explicit (doesn't read ~/.config/nixpkgs/config.nix unless you source it in-repo) and doesn't rely on env vars (e.g., NIX_PATH) which are not given explicitly in the flake.

But pinning Nixpkgs alone does get you much of the way there (and for many use cases— those where the only referent on it is 'nixpkgs' or 'nixos'— does make NIX_PATH redundant anyway).


> But pinning Nixpkgs alone does get you much of the way there (and for many use cases— those where the only referent on it is 'nixpkgs' or 'nixos'— does make NIX_PATH redundant anyway).

What is missing compared to using flakes? The only `NIX_PATH` components I normally use is `nixpkgs` which hooks into the whole channel system (which is bad), but by settings my `pkgs` variable to a specific commit/tarball, I can ignore `NIX_PATH` entirely, right?


Traditionally you might also use NIX_PATH for secondary sources of packages and modules, like the Emacs overlay, NUR, or the Nix-Darwin repo.

But yeah if you pin all of your package sources and set your Nixpkgs config locally, you get all the benefits aside from the Nix evaluator's 'pure' mode, which gets some evaluation speedups due to caching.


A `flake.nix` file provides a consistent entrypoint to your codebase, which is nice when using Nix generally. For NixOS specifically, you can point `nixos-rebuild` to a flake & have it switch config.

I also find nix flakes have a nicer UX to use. To use a channel, I have to run `nix-channel --add`. But, with flakes, I only have to declare it as an input.


https://github.com/Misterio77/nix-starter-configs is probably the closest to that right now.


Just my two cents: Nix doesn’t guarantee “reproducible”, just “repeatable”. (I think it’s helpful to keep these technical concepts distinct, and to introduce the right terminology when teaching, since it makes elaboration easier in the future.)


Can you elaborate? From what I understand, Nix packages are mostly reproducible as they are running great lengths for that, to the point where every time in Nix land is the exact same.


"reproducible" means you get the same result, bit-for-bit, when running a build in different circumstances.

It's trivial to write non-reproducible Nix derivations by placing timestamps, randomly generated data, or similar into the build output, directly or indirectly. Nix is a powerful tool for working towards reproducibility, since it can specify the software side of a build environment more exhaustively than most other package managers out there, and has a language (derivations) that enables repeating builds easily as well as comparing them, but does not guarantee reproducibility on its own.

A lot of the reproducibility of nixpkgs is attributable to reproducible build efforts elsewhere, including conventions like SOURCE_DATE_EPOCH. Nix itself does not in fact "freeze the clock" for builds, but many tools that use timestamps as part of a build will respect SOURCE_DATE_EPOCH instead of using the system clock. Many of these valuable developments in this direction are coordinated in the cross-distro https://reproducible-builds.org group.


Not bit-for-bit reproducible. Package builds can be nondeterministic, binaries can have embedded timestamps (e.g, build time), and so on.

They should be semantically equivalent, but it's not fully guaranteed.


You're not wrong overall, but your example is. In the build environment, the current time is set to the epoch which removes that variability.

An upcoming feature of nix is content addressed builds which use the output hashes to determine the store path. This should make it much more transparent which builds are reproducible and which are not.


> In the build environment, the current time is set to the epoch which removes that variability.

The amount of time per build can vary. Embedded timestamps will all be in January 1970, but even a single second difference means the binaries are no longer bit for bit identical -- and that assumes the embedded timestamp isn't microseconds.


I think you're assuming that the timestamp only starts at the epoch and still advances in real time, which is not necessarily true.


If it didn't advance, that would cause trouble for some build systems. So yes, I'm assuming it does.


hash of build output is not used in hash of derivation and in derivation tree. hence it is not reproducible.


Accurate, but there is only so much to be done on that front when the consumed packages do not strive for reproducibility. As Nix or similar tools bring the lack of bit-for-bit reproducibility to the forefront, I hope build systems start adopting processes that will correct this behavior.


I mean, its impossible to guarantee full reproducibility under all possible conditions, but Nix does take steps towards promoting it. eg setting all times to UNIX epoch, enforcing purity (so specifying dependencies explicitly instead of fetching them from $PATH, etc).


With flakes it is reproducible in a self-contained way.


would you mind elaborating on the difference?


These two words have the same meaning


Repeating a non-deterministic process can give you a different result, which makes the results non-reproducible.

Nix does provide a higher degree of functional reproducibility (builds will have the same behavior, if not identical bits) than other systems do, though, because of the way it locks down exact dependency versions and build flags, though. In that sense, Nix is 'more reproducible' than competing tools even when both are invoking non-deterministic compilers at the last step.


repeatable - do the exact same thing every time

reproducable - get the exact same results every time

not the same thing


I wish guides like these contained screenshots.

Do people use Nix for desktop OSes? As a VM they SSH into? A collection of config scripts that they don't directly issue commands to?

I certainly can't tell from a quick glance of this guide


All of the above.

NixOS is actually fairly well suited to a full desktop OS. They package-up basically everything you would expect. You can even pull in Steam its proton environment without much hassle.

It is also perfectly workable as simple server OS running on bare metal or a VM.

One can use it on other OSes as a way to create fully deterministic environments for developing. (Like the python virtualenv concept, but for any language, pulling any arbitary tools you might need). Almost like a docker container, but without isolating the filesystem.

Using just nix tool not as part of NixOS, can be an underwhelming experience, as the default does not quite give the fully declarative environment setup you might want. For example, under the default you can imperatively request packages to be added to the nix store. But if you chose to use the "correct" versions of commands, you can get the intended result. Alternatively, using it in conjunction with tools like direnv (which enables you to configure your shell to ask nix for a specific environment when you cd into it, or alternatively when you run a specific command within it). This environment can have exactly the set of tools you need for developing the project that lives in this folder, even if the rest of your OS has a different and incompatible version of the compilers installed, or whatever.


Nix is pretty usable for both desktops and headless servers. Personally, I even use it on macOS without much trouble.

My system looks like any other install of Ventura, but all of my configuration, ranging from the terminal and VS Code to macOS-specific system preferences and Safari, is done declaratively in Nix [1]. The overwhelming majority of my installed software also comes from Nix packages, with some exceptions for stuff that is not packaged yet (e.g., I have Podman Desktop, the macOS ZFS port, Lulu, yubikey-manager-qt installed through Homebrew -- fortunately nix-darwin [2] also just lets me have an set of brews/casks in my config).

It was been a bit of a nightmare at first since the error messages are kind of horrific, and there can be a lack of good examples/docs on flakes. But I think the weekend worth of time I invested was worth it since I no longer need to rely on hacky shellscripts or remember to manually configure anything.

[1]: <https://github.com/nix-community/home-manager>

[2]: <https://github.com/LnL7/nix-darwin>


Interesting, so you are running both home-manager and nix-darwin? When I got into the game, it seemed like they were a bit of a one-or-the-other. I use home-manager but keep homebrew around for some cask management and its mostly "out of band" right now, so I'd be interested to move that "in band" if possible.


Holy crap! I had no idea that Nix-Darwin will even install, configure, and wrap Homebrew for you now. That's awesome. Love the inclusive, impure approach.

The Homebrew module for Nix-Darwin also looks awesome, like extremely feature-complete.


Zero to Nix introduces Nix, not NixOS the operating system. So, there's not really a need for screen shots as Zero to Nix it teaching how best to install and use Nix on any Linux or macOS. For that, code snippets are convenient I think.


From the questions in the parent post I wonder if it would be good to have a clear definition of what Nix is, what NixOS is, how they're different, and when to use each? Could just be a short paragraph, but if the site is for people just starting out it might be helpful...


I can tell you that I do all three. My daily driver is a laptop running NixOS with a highly customised desktop environment. I also have a small VPS that running NixOS that I communicate with via SSH. Finally, as work, we use a nix flake to simplify our build system. Most days of the year, that is handled entirely by the CI script and I don't have to think about it.


Yes, all of the above - and much more.


Screenshots of what exactly? Installing packages? Running nixos-rebuild switch? I guess screenshots of a bunch of text.


Yes! Assuming that is what "using Nix" looks like for an expected use case, that would be informative for someone who does not know what using Nix looks like.


You will like nixos.org then :)

https://nixos.org/

Lots of examples if you scroll down!


Oh this is completely and exactly what I was thinking of, thank you! :)


You can use 'Nix' itself for writing NixOS packages, creating Docker images, etc. For NixOS, it's perfectly valid as a desktop OS (I use it on my daily driver laptop) as well as on a server.


People use Nix on desktop a ton, but the GUI tools in the ecosystem are still largely marginal and incomplete. The screenshots here would just be images of text, which is probably why there aren't any.


Been using it as my desktop for about 5 years and have never looked back.


Is Nix good at dealing with cuda dependencies? I am always frustrated trying to deploy cuda-based environments onto machines with different sorts of GPUs.


I've setup pytorch with CUDA on nix and it was quite straightforward, but never tried anything more exotic.


Off topic, but I wonder if the authors of zero-to-nix.com are aware that their project name actually reads quite funny for German speakers (as "Nix" in German also means Zero)


Indeed, "zero to nix" was our jokey "working name." We never actually came up with a better name, so here we are :).


The original author is Dutch.

In Dutch, "niks" (same pronunciation as Nix), actually means "nothing".

His nickname is niksnut, which means "good-for-nothing".


> His nickname is niksnut, which means "good-for-nothing".

In german that would be Nichtsnutz. Would the english word deadbeat mean the same?


Yep!


The pun also works in english, so I imagine they are.


I read of Nix now and then. Seems its more than a fad. Why should I invest time? What makes it stand out?


> Why should I invest time?

It's not for everyone.

Specifically, because Nix's 'costs' are upfront (for likely future benefit), nix isn't well suited to just-get-it-done pragmatic attitudes. -- e.g. if you'd prefer to just launch VMs from the web console, over using a tool like Terraform, then Nix isn't going to be for you.

Nix isn't too difficult to use. I'd say it's 95% wonderful, 5% huge pain to deal with. (Writing new nix code can be very hard).

As to why it's worth learning:

> What makes it stand out?

Nix provides very expressive control over packages of software.

e.g. With nix, it's easy to have multiple versions of the same software running on the same system. Whereas, with package managers, if you upgrade, you aren't able to easily also keep the old version around.

Some of the use cases Nix allows are pretty neat:

- You can declare a set of development tools to be made available. So, when you load up the project, you don't have to copy-paste "apt-get install...". This is especially useful for side projects you might not touch all the time.

- There's a "nix run" command, which can act a bit like "docker, without containers": it will download the package, and run it on the host.

- NixOS makes use of Nix so that the system configuration is all declared starting from a single file. Rolling back changes to system configuration is easy, in case you accidentally misconfigure the system. -- This can be used to build container images or VM images.

- Nix can be used to declare what packages you want installed for your user, and declare the configurations for these files. This allows ensuring you have a familiar setup quickly on a new computer.

All sorts of programming involves dealing with packages.

To clarify a bit on the details: nix declares packages in a pure way, using all of its inputs (source code, compiler, library dependencies; which are themselves declared with nix), and builds these in an isolated/non-global directories. Packages are 'installed' by symlinking to where the package is placed.


> nix isn't well suited to just-get-it-done pragmatic attitudes

Depends on what exactly you're trying to do. I discovered nix years ago when I was trying to install a newer version of Java than was available in the Ubuntu repos, and the "nix-env" method (just using nix as a package manager without the declarative config) was the only thing that just worked with no hassle.


My first encounter with Nix was using it that way to get my favorite tools on the university computer lab without convincing the admins to install them for me.

Today, some Steam Deck users are using Nix to supplement their console's desktop experience with familiar tools without the overhead of Flatpak or the risk of modifying the base system (in which case modifications are nuked on SteamOS updates anyhow).

Determinate Systems did some work to enable and document that, and one YouTuber recently posted an intro/walkthrough of their docs as well.

Video: https://m.youtube.com/watch?v=ttOs5iWgNzk

Secondary documentation (YouTuber's blog): https://christitus.com/steamdeck-as-a-desktop/

Primary documentation by Determinate Systems: https://determinate.systems/posts/nix-on-the-steam-deck

(Some of the work relevant here was done by folks outside of Determinate Systems as well. The installer workgroup is not exclusively DSers.)

Sometimes it just fits a use case so much better than alternatives that it's an obvious choice.


How does Nix compare to Environment Modules: https://modules.sourceforge.net/ Am I correct in understanding they are similar, except Nix has the "pure" package building?


Modules imperatively modify the current (shell) environment (PATH and other variables) but you've to install anything required by modulefiles yourself. Nix handles package management and also allows you to declaratively create an environment to which you enter. For example `module load gcc` will bring gcc to your environment but it must already be installed by the administrator. On the other hand on Nix, you can either do something similar with `nix-shell -p gcc` which will give you an environment with gcc that if it isn't available on store will download it, but you can also create a `shell.nix` where you specify anything you need explicitly (have those packages available, download those dependencies not available as packages, make those config files, etc). Overall Modules has only a part of the functionality offered by Nix.

*Although `nix-shell` in newer unified `nix` command has been broken to few subcommands. Can find more info at https://blog.ysndr.de/posts/guides/2021-12-01-nix-shells/ if interested.


This is not Nix, but in showing the Environment Modules support for Guix the blog post also shows how functional package management (as implemented in Nix and Guix) differ:

https://hpc.guix.info/blog/2022/05/back-to-the-future-module...


Helpful article and cool feature! Thanks for sharing


I'm not familiar with Environment Modules. I see they're popular in HPC?

One difference: On Nix's homepage (https://nixos.org), the first word which stands out is "reproducible". -- If I search the read the docs for "reproducible", the word shows up once. https://modules.readthedocs.io/en/latest/index.html

Not sure if there's anything recent, but links from this may be useful: https://github.com/freuk/awesome-nix-hpc


Closing in on 20 years of existence doesn't really qualify for fad

I'm just starting a serious learning journey with Nix after flirting with the idea for a few years. Mostly because I find myself endlessly working on tooling to support the projects I work on that Nix already does extremely well.

The feature I am most sold on is the ability to invoke clean complex development environments, that bring themselves to existence automatically as I traverse directories. If you work in code or in DevOps, Nix is totally worth a look.


It may not be a fad, but there's a lot of rose-colored hype that masks a world of tedium. New prospective users should be prepared for a lot of uphill grind with respect to configuring packages or defining their own packages. Every time I try to do seemingly simple tasks in Nix, I end up spending hours on the Nix discord channel trying to work out a solution with seasoned users (who invariably struggle to work out a reasonable solution). Often times I end up having to try to figure out how to package some obscure C dependency deep in the dependency tree with its own bespoke build system and so on. Nixpkgs is also pretty poorly organized (or at least I can almost never find the package I need) and this is pretty critical because something as simple as answering "what type does this function take?" requires a ton of searching around Nixpkgs (largely due to the lack of type annotations or even informal documentation). The CLI tool surface is also not particularly intuitive, and there are different tools for different problems and no consensus about which tools to use (or at least the official docs often disagree with popular opinions in the community). You have to be aware of whether you're just using the Nix package manager or whether you're using NixOS because it will affect the way you write your configuration and often snippets on the Internet implicitly assume one or the other such that you will spend a lot of time trying to fix snippets or find the right snippet for your use case. MacOS is still a second-class citizen in the Nix world and a fair amount of stuff doesn't work properly (although I can't think of specific examples off hand). The Nix expression language seems unnecessarily unfamiliar to mainstream programming languages--I don't object to the functional nature, but I still spend quite a lot of time consciously thinking about syntax even though I've been using Nix on and off for ~7 years now (compared with e.g. typescript which I've barely touched and yet is trivial to read). Normally I don't complain about syntax, but you can do very little in the Nix world without reading and writing a bunch of nixlang and even if the other problems were resolved this alone would make it difficult to sell in most organizations since every developer would have to figure out how to work with it (package management is high-touch).

I'm a big believer in Nix's high-level approach to declarative systems, but the whole UX of Nix is so poor that foregoing declarative systems altogether is quite a lot less painful than using Nix in my experience. I'm rooting for it, but it really feels like Nix needs a product manager or something (no disrespect to the maintainers; these are difficult problems and I'm sure I wouldn't do a very good job). New users should beware.


> MacOS is still a second-class citizen in the Nix world and a fair amount of stuff doesn't work properly

In my experience:

With fewer nix users on macOS, it's more likely you'll run into software which isn't in the binary cache, & so will compile from source. (brew also does this).

With fewer nix users on macOS, it's may take longer for packages broken on macOS to be fixed.

It's a bit more of a hurdle to use .app programs out-of-the-box compared to brew, due to the symlinking.


> With fewer nix users on macOS, it's more likely you'll run into software which isn't in the binary cache, & so will compile from source.

This isn't necessarily true, unless the package happened to fail to build on Hydra, or it just hasn't been built yet. (Every package is built for every platform that has builders in Hydra, it's not a matter of maintenance unless it just doesn't build.)

Does brew do this differently? I thought they also automatically compile every package.


.app programs which require Xcode to build weren't in the binary caches altogether, last I checked. Stuff with proprietary software in its build toolchain doesn't get built on Hydra.

I just use brew for .apps (and only for .apps) when I'm on macOS.


Yep, I use Brew with a Brewfile to handle most casks. A select few I've manually created derivations for. This seems to be the path of much less resistance.


> MacOS is still a second-class citizen in the Nix world and a fair amount of stuff doesn't work properly

and that will stay this way if Apple continues to make major and breaking changes with every update and changing MacOS more and more away from a BSD system and locking it further down.


I feel like Nix is worth it for me at this point, but I've definitely been through some of the pain described. This is a tough critique to hear for anyone who loves the project but I agree with the core of it (except the syntax issue).

Worth reading for Nix people and prospective Nix users alike, imo.


Yeah, I don't want to rain on a parade; I think about it as opportunity for people who care about the project to rally around. I know plenty of people care about the user experience, but the current efforts seem kind of superficial and limited. It kind of feels like efforts are geared toward making Nix slightly better for its current user-base: individual, super-technical users who are really excited about package management and functional purity. Sadly, this misses out on Nix as a package manager for larger organizations (packaging their own software as well as configuring their hosts) as well as individual users who want the benefits of declarative systems but who don't want to learn a ton about package management, functional programming, Nix minutia, etc.

IMHO, it seems like there should be a UX working group that starts with broad scenarios and personas and develops a vision of what tooling should look like and works from there, rather than haphazard, incremental improvements on the current state of Nix tooling/workflows/etc. It could be interesting to look at how the Rust project makes big ambitious changes (they seem to do a really good job from my vantage point). Again, this is my view from afar as someone who has never run a big open source project and knows relatively little about package management (though thanks to Nix, much more than I ever wanted to know!).


NixOS has been my daily driver for just over a year and my impression is that it’s still all a big experiment. A promising one, but far from a polished product so try to avoid that framing.

The Nix community is doing exciting work but in the long run I wouldn’t be surprised to see another project take its place in the mainstream once the ideas have matured. The current space has much of the same chaos as projects like Oh My Zsh or Spacemacs and needs to be treated more like an active hobby.

All that considered, the core paradigm is a breath of fresh air and I can’t imagine going back to a mutable system.


If you are building a complex system with a large number of cascading dependencies then nix can literally save your sanity, however you have to get over the initial steep learning curve.

If your work tends to be more isolated and self contained on stable unchanging mainline or mainstream versions of any dependencies you have. Then it’s not worth your time and you won’t appreciate or understand it’s value.


For me, i use it on my Desktop because i love things being stable for my work environment. I don't want an upgrade over the weekend to cause problems come Monday morning.

I've had my system get "borked" on updates in the past, and Nix lets me revert very very easily. Also upgrading libraries for one App can easily be isolated from breaking other applications and etc.

It's got tons of flaws (to me), but the core idea to me is a foundation for a super stable system. I both love Nix and hate it. It's so good that myself, a large critic of the OS, still uses it.


For me, the "borking" issue is largely resolved by running Btrfs. Just make a snapshot shortly before updating, and then I can revert to it if needed.


My problem is i don't know what gets borked immediately after updating unless it's catastrophic. Ie i've gone a fair bit of time before i realized some specific functionality of some program no longer works due to some unrelated change in an underlying dependency that i was unaware of. Oof.

Granted Btrfs sounds great though, i've not used that. It would certainly help.


Yeah that's true. That's where the "largely" part of my comment does some work.

I just take occasional snapshots before I do things that I'm concerned may be catastrophic. But it definitely won't catch everything. It helps that I run Arch, and I update packages once a day, which only leaves me with under 40 (small) packages usually. So a quick cursory glance at which ones are updating usually tells me what to be cautious of. Display driver update, kernel update, etc.

If I'm not sure what went wrong, but I at least have a working snapshot, then I can get done what I need to get done, and then go back to troubleshooting. Rather than just having a broken system regardless.


I used to employ ZFS for this, but if it took me a while to notice something was broken, or I updated multiple times, it was annoying to figure out which snapshot was the issue, and which changes actually caused the problem. On NixOS, I just have to select a different generation in systemd-boot, and since my configuration is stored in a Git repo, they're all tagged with the data and commit hash they were built at, so it's very quick to a) find a working generation to just use for now, and b) actually find where the issue is and solve it.


I think the nix community is doing an increasingly-better job at addressing several outstanding issues, and although the OP link resolves one of them - the getting-started experience - the "why" that you highlight here is still a hard one to answer without getting into the technical weeds. I ran an informal Twitter poll a few months ago and this question (the "why" instead of "how") was the most-requested kind of content.

One potential answer to this is, "imagine building and running software with lockfiles for _literally everything_". I'm not just talking about _versions_ of dependencies or shared libraries - which nix does - but also things like:

- Locking the current point in time (nix resets the build sandbox to the unix epoch)

- Locking out network conditions (all build dependencies need to be fetched and therefore expressed as part of the instructions and not left to "at some point during the build")

- Locking out access to any system state (again, builds occur in a sandbox populated only with what you indicate within the build instructions)

That's what's behind the marketing for reproducability and repeatability. If you lift those principles into new and interesting applications, the various other uses for nix fall out of it:

- NixOS takes the principle of those nix builds and applies to it building not just packages, but the system entirely, like the files it places in /etc or the running kernel.

- Projects like devenv[1] or flake devShells in general re-use the portability of a fully-defined nix package to ship hard-to-break executables into share-able devshells so your peers can work with the bit-for-bit same version of Terraform or python (without worrying about what version of /lib/libssl.so they may have)

- Since nix "owns" the _entirety_ of the inputs and outputs to a piece of built software, shaping it into different artifacts becomes trivial. For example, as long as you're able to build a rust project with nix, nix easily lets you kick out a minimal OCI container (without needing to write a `Dockerfile`), or produce a tiny qemu clone of your system (or any system) by feeding your NixOS configuration into a function that produces images instead of configuring your running system.

Hopefully that's helpful, sorry if it isn't - but nix is sort of alien software, and nix people are still learning how to best share its potential with others!

edit: list formatting

[1]: https://devenv.sh/


I found NixOS to be usable (though it has limits in comparison to other distributions), reliable and reproducible(!). You can add and remove packages without polluting the system.

Potentially it can save you time in the future. Moving to another hardware is a breath.


- Nix is a purely functional language with lazy evaluation. - One of its types is a derivation which is basically an immutable result of some script / application / other build system ran in sandbox with exactly specified environment. - Calling derive with same inputs generates same derivation. - It's lazy... only when something tries to access derivation's files or other properties its build script is run.

You can use derivations as (/ to represent) - packages - generated configuration files / settings - containers - whole OS images ... e.g. I'm building raspi SD card images using Nix.


Nix is for people who have entirely given up on the idea of system libraries. There is no system. Unless someone else has already done the work every single random bit of .c code, or whatever, you try to compile or run will require you to explicitly set the system libraries available/required to run it in a set of config files. It's like building a custom OS container for every single program you run.

For some people this is good because future shock has made relying on system libaries to run things very troublesome. So troublesome it compares to the above.


I recommend to sit back and wait until the hype has subsided. Later, when the starting problems subsided and documentation has improved, it might be worth a try. Provided that ever happens.


It's basically checking in your OS to git. It never gets crufty and almost never breaks. There's a lot more to it but those are the core ideas and I'm typing on my phone.


NO. He asked about Nix NOT NixOS... do not conflate them together. Nix an extremely generic tool for much much much more than what you have said.


Is Nix used for anything besides configuring a computer?

I said "a lot more to it" as well...


Yes, its used to guarantee reproducible scripts (so, e.g., you can use `jq` and not require someone have jq installed and not require running through docker) and dev environments as well (which is really great for both version locking as well as polyglot projects).


I use nix shell for development and reference uninstalled packages from scripts as well. I think we both understand what Nix is capable of. I still don't find any issue with my initial comment that Nix at its core is for maintaining a reproducible system from config files in git. My point wasn't to be pedantically perfect but rather to communicate a core use case in laymen's terms for the uninitiated.


The same Zero to NixOS would be highly appreciate.


We've been tossing the idea back and forth inside to try and find the right way to approach it. I totally agree.


What are your thoughts on the section about NixOS?


Zero to Nix and its NixOS section is elegant and simple.

It has already been said many times but NixOS suffer from a poor and a fragmented documentation.

The Official Nixos Manual is a very good start to install Nixos. But that's it.

It does not explain all the logic behind NixOS for already experienced user. Because yes, Nixos is absolulety not for beginners !

Nixos is a kind of blackbox where once you've luckily found the site https://search.nixos.org/options it comes with all the options you were looking for.

You need a sysadmin background to understrand theses options like (ie: services.nginx.virtualHosts.<name>.locations.<name>.extraConfig). A reverse dictionary of how we used to do things with traditionnal distro and how to do with Nixos should be a very good start !

At least, the extrem big fucking issue is the complete mess between Nixos/Nix/Flake/Home Manager. Theirs documentation and definition are often "recursive dependant" in a way you are completely lost.

If i compare to AUR (ArchLinux User Repository), the learning curve to create a custom package is quite easy. For Nix, it requires an amount of concentration, reads and skills to do the same. This discourage users.


I like the idea of a NixOS section.


How fast is nix on delivering security patches? I am looking for arguments to use it in an enterprise setting given the declarative nature but unless there is somebody who will sell you a support contract and Guarantee security updates it seems like a hard sell


It is actually slower than Ubuntu which can be see with the recent git update BUT if you know you need this patch or update it enables you to achieve that with overlays pretty easy and fast and if you know what you are doing you can reduce the rebuild amounts to near zero. You also need to remember that behind NixOS there is not a big corp like canonical but mostly a community with way to much time. If you ever tried to build an Ubuntu package with a custom patch you will know how painful it is and unmaintainable. Not with nix. Easy maintenance included with automatic, atomic rebuilds and applying the patch to the next software version if the source code didn't change.


I have tried several times to dig into nix and make it stick. Each time I get a little further along, but I always get to the same stuck point: things that I am trying to combine are unclear to me how they should fit together, and/or there are just massive amounts of code for what should be a simple thing.

Nix flakes has indeed made it all quite a bit easier. But, sadly, in the interim, there are lots of things in an in-between state.


As someone who uses nix daily for work and home, I've found that there is always a nice concise way to accomplish what I want, but finding that solution is extremely difficult. It seems like the best (and sometimes only) documentation is the code itself, so until you get comfortable with the language you are missing a majority of the documentation. It's a catch-22, you have to know nix to learn nix. It really shouldn't have to be that way.


> Welcome! It's great to see that you're interested in Nix.

I sure am! What is Nix?


About NixOS, there's something really basic that I cannot seem to grasp. I had already installed many linux distro's with time, after the years I was really found on KDE and ZFS.

I've stumbled upon this tutorial with great interests and yet I can't start to see what is the expected install workflow. Are you expected to write your nix config file booting on the live medium, how could you easily transfer this config file to your install medium.

As much as I understand that targeting the right ZFS dataset and so should not be included in box and I was still happy to find some mention of it in the official doc. I don't understand this mix of an all seeing doc, spanning across many technologies and configurations set and yet what I could call the context is rather absent.


Are you referring to impermanence or the erase-your-darlings config?

This tutorial is for Nix itself, not the operating system based on it, which is why it doesn't include install instructions for NixOS.

For a normal NixOS setup with ZFS, traditionally you just partition manually, then mount the datasets how you want for NixOS under /mnt, and the nixos-generate-config command generates a hardware-configuration.nix file which automatically includes all of those mounts for your to-be-installed NixOS system.

You tweak configuration.nix on the target media under /mnt/etc/nixos/configuration.nix, and then run nixos-install and reboot into the new system.


Just made an account to say that I think this is great - a well structured, well explained, and most importantly guided introduction to Nix is exactly what's needed to get into it.

Would also be awesome to see something like this for NixOS.


What problem does this solve?


Some problems Nix solves, as concisely as possible:

  - dependency conflicts
  - build reproducibility
  - configuration management
    - configuration drift
  - package management on restricted systems (i.e., installing stuff when you're not root)
  - shared library duplication
  - inconsistent state/broken system after a botched upgrade
This makes it nice for setting up development environments, building containers, and deploying servers.

(A lot of people also enjoy using it for their dotfiles, since it works on macOS as well as across all Linuxes. I personally love it on desktops and development workstations as well.)


It's right there in the heading!

"Declarative, reproducible development environments"


I've been dipping my toes into the Nix ecosystem recently, having a dev environment per project with direnv is neat but how does this work with IDEs like VSCode or IntelliJ IDEA? For example, if I define a specific JDK in my project with Nix, will IntelliJ be able to pick this up? Does anyone have any good resources on how to set this up?

BTW, for others who just want to try it out without having to install anything on your system, there are docker containers you can use as a sandbox: docker run -it nixos/nix bash


For vscode, I like the `arrterian.nix-env-selector` extension.

Can IntelliJ be configured to simply use whatever JDK belongs to the `javac` in PATH? If so, it should suffice to simply start it in a `nix-shell`. If not, maybe setting `JAVA_HOME` in your `.envrc` could help?


VSCode and IntelliJ also both have direnv plugins for importing env vars from direnv after the fact. You can use that alongside direnv's Nix integration to load those variables without relaunching your editor/IDE!


omg how did I not know about these?!?


I've just been starting my Emacs from the direnv to ensure it has the right dev tools. This works, but can be annoying. It'd be nice to have a better solution.


Does emacs-envrc work with nix-direnv?


> echo "Hello Nix" | nix run "nixpkgs#ponysay"

why on earth would you make # any kind of a special character in commands. who thought of that


In most shells, "#" is not special unless it's preceded by whitespace. So

> echo "Hello Nix" | nix run nixpkgs#ponysay

also works.


  $ echo a#b
  a#b


Are you complaining because it's not on some latin keyboards, or for some other reason? A lot of other characters are already taken either by shell or by the nix expression language.


If I could push this to my kindle as an epub with an index. It would be great if these document frameworks would support it. At least a PDF.


Quite duly noted! I'd love to provide other formats and will investigate this very soon. I can't guarantee that I'll come up with a solution given how vast and variegated the space is, but it's worth trying.


I used to do that with my e-readers via Pocket


What does opinionated mean is this case? I read through a bit and didn't see any strong opinions.


# What's opinionated about Zero to Nix

Zero to Nix is opinionated because it advocates learning and using flakes and treating channels as deprecated. Zero to Nix also deviates from official recommendations in that it recommends installing Nix using Nix Installer rather than the official Nix installation script.

https://zero-to-nix.com/about#whats-opinionated-about-zero-t...


To me using the word opinionated is a deterrent. Any time I hear the word opinionated used it usually means the opinion(s) expressed are overly strong, stubborn, and/or negative. I was expecting the guide to call out issues with the official documentation in a way that could upset the people working on the official docs. But this is just an alternative method. Hardly opinionated.


The term has gained a specialized meaning in computing over the last decade or so.

> Opinionated software means that there is basically one right way to do things […] Non-opinionated software leaves lots of flexibility to the user https://stackoverflow.com/q/802050

Providing only a single answer for how to do things is helpful for beginners who haven’t yet formed a basis upon which to make informed decisions.


Historically, the Nix ecosystem has arguably suffered a bit due to competing conventions throughout. Often, there have been many competing tools in the same space, and few standard, blessed conventions/interfaces.

'Opinionated' here means that the authors are trying to spare newbies from the 'paralysis by analysis' problem by making some (defensible) choices about what conventions to use on the reader's behalf up front.

These docs are going to 'lead' the official docs in the sense of coming out first because making things official will involve standardizing some of the interfaces used here and solidifying more consensus around them. (There is lots of organizational and technical work happening around that right now. You can follow along by looking for the minutes of various community team meetings on NixOS Discourse and following links from there, if you're curious.)


As a nix user I agree. Nix needs to make flakes stable ASAP. It creates a lot of confusion for new users and friction for getting started. "Do I use the thing that's deprecated but stable or the thing that's unstable but is the future of nix?"


The most obvious example is that using the installer in the quick start enables the flakes and nix-command features automatically, even though they are still considered experimental by upstream.


I'm glad this guide is focused on flakes. If you're starting out with Nix, forget about home-manager, nix-env, and the pre-flake configuration model.


But what if I manage my home-manager configuration with flakes.


My very personal recommendation: You don't, at least on a single user machine. Instead you use one of the many dotfile managers out there and for anything package related NixOS. home-manager makes the feedback loop for editing configs managed through it very long, which slowed me personally down a lot. One place where I would recommend home-manager is, if you are not using NixOS and only manage your packages through it.


a lot of software support including configuration files, so what I do is that my configuration has a permanent configuration and a temporary configuration through including a "local" file. This even helps as a workaround to managing secrets for some stubborn stuff to which you need to put some api key or password on a text file (shitty software exist). Otherwise, I haven't seen much problem with managing home with home-manager. I also can load the same config with the nixos and darwin modules.


Usually you’re on a single-user system anyway though. You should be able to manage all that with your global configuration.nix. You’ll also get the benefit of rollbacks.


Home Manager is nice if you're on non-NixOS, where you don't have a configuration.nix. :)


I use configuration on macos as well, so I'm not sure what you mean?


Yeah, Home Manager is more redundant if you're using Nix-Darwin for a configuration.nix. Non-NixOS Linux doesn't have an equivalent module system to Nix-Darwin, though, so if you want a module system for declarative config there it's Home Manager.


So Nix does not support system level declarative config on Linux except for NixOS? Oh wow, that sucks.


Yeah. It's an unfortunate gap.

There is some work in NixOS-WSL on a special Systemd shim which allows that NixOS instance to work with the WSL-provided Systemd that Microsoft recently added with their 'native' systemd support. I wonder if that can be extended to port NixOS to systems where it doesn't control the whole stack.

Ideally we'll eventually see existing module systems unified with that of NixOS via some kind of process management abstraction framework, and you'll be able to do NixOS-like things in more places with a shared codebase.

Edited to add: there's nothing as simple as NixOS or Nix-Darwin, but you can use Disnix to deploy configured services via Nix on non-NixOS. Not something I'd go for on desktop, but it's there.


I see. Yeah that's a shame.


You can rollback with plain home-manager: https://github.com/nix-community/home-manager/blob/master/do...


Nix and NixOS have had a similar sort of effect on me as Gentoo and FreeBSD have in the past. They have helped to expand my consciousness in the realm of systems administration and have helped me achieve new heights with my low latency audio configuration. For this reason, Nix and NixOS have become indispensable to my workflow.

NixOS introduces a new form of declarative configuration, fusing Gentoo's highly configurable nature with BSD's unified configuration file approach. For me, it's absolutely perfect until my own laziness bites me in the butt. If you want to do a gentle dive into Nix, resist the temptation to go full "NixOS" and learn the Nix build/environment system first. It will make things a lot easier for you in the long run.


I'd also suggest that, once you _do_ feel comfortable enough to step foot into NixOS territory, that you start off by version-controlling your configuration. It doesn't necessarily have to be public, but I've found it very helpful in the past when I've had to debug various issues due to misconfiguration by me.


Do you symlink your config repo to /etc/nixos or something else? So far, I've just been rsyncing my config repo folder after I modify it.


I don't; my config lives in ~/flake, and I run `nixos-rebuild ... --flake ~/flake` whenever I update it.


You don't have to specify the nixosConfiguration name (e.g ~/flake#my-configuration)? Do you just name it "default" or something for that to work? I've never tried that.


Exactly as Macha said, if you name the attribute `nixosConfiguration.<hostname>`, `nixos-rebuild` will look for that attribute implicitly; you can still specify another configuration if you're e.g. in a VM or a live image.


You name it the same as your current system's hostname.


Oh, I had no idea. I was actually already doing that. Guess I was just being extra verbose on the command line.


You can actually put your NixOS config anywhere. Assuming you're not using flakes, `nixos-rebuild` finds the config through NIX_PATH:

grahamc@scruffy:~/ > echo $NIX_PATH

nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos:nixos-config=/etc/nixos/configuration.nix:/nix/var/nix/profiles/per-user/root/channels

you can change the `nixos-config` value to point to somewhere else, or call it like this:`nixos-rebuild -I nixos-config=./configuration.nix`


I use an update script that overrides that location to $(pwd), and also uses nvd to print a package diff for the update. Among a few other niceties. With flakes, that's a regular nixos-rebuild flag; otherwise it's an envvar.

/etc/nixos is just the default, there's a number of ways to set your own path. One of the simplest might be to put "import /home/wherever" as the sole contents of configuration.nix.


That sounds like a nice little workflow; I might have to incorporate something like that with `nvd`...

Though, it should be said that `import /home/wherever` might not work if you switch to / use flakes, as that is likely outside of the flake's git repo (and thus impure).


Yeah, I symlink `/etc/nixos/configuration.nix` to my git repo. (I do keep a `hardware-configuration.nix` which isn't version controlled. I probably should add version-control at some point but for now it is simple enough to copy around and maybe make some minor tweaks).


You can also use `git init --separate-git-dir=~/something /etc/nixos` to keep the git data in your user directory while the config remains in the default location. I like this solution because it keeps the stuff I want to do as root (configuring the system) separate from what I want to do as regular user (tracking changes of the configuration).




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: