Zero to Nix, an unofficial, opinionated, gentle introduction to Nix
zero-to-nix.com
zero-to-nix.com
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?"
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).
- 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.
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.
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.
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.
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.
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.
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.
macOS is not a supported platform on Guix, right? Is there new/ongoing work to support that?
> 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.
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.
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.
How was the parent wrong again?
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
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.
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: 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.
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 mannerThen 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.
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.
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 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.
It's kind of like Haskell. Composable programs is the sell. Purity is a means towards that.
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...
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
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.
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.
Yes, if you don't cache the build results or manage that cache very crudely. Sorry, I wasn't precise enough.
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.
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.
For now there's nix-runner: https://github.com/clhodapp/nix-runner
[1] https://pubs.opengroup.org/onlinepubs/9699919799/utilities/e...
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.
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.
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.
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.
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.
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)
I've been using flakes for well over a year and there doesn't seem to be much discernible progress.
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.
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)
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.
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 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.
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.
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.
We think flakes and the new interface are the future, and we're working to bring it home.
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?
You can get almost all the benefits Flakes brings without Flakes using alternatives like niv.
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)?
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.
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?
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.
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.
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.
They should be semantically equivalent, but it's not fully guaranteed.
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.
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.
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.
reproducable - get the exact same results every time
not the same thing
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
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.
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.
The Homebrew module for Nix-Darwin also looks awesome, like extremely feature-complete.
Lots of examples if you scroll down!
In Dutch, "niks" (same pronunciation as Nix), actually means "nothing".
His nickname is niksnut, which means "good-for-nothing".
In german that would be Nichtsnutz. Would the english word deadbeat mean the same?
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.
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.
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.
*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.
https://hpc.guix.info/blog/2022/05/back-to-the-future-module...
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
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.
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.
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.
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.
I just use brew for .apps (and only for .apps) when I'm on macOS.
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.
Worth reading for Nix people and prospective Nix users alike, imo.
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!).
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 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.
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.
Granted Btrfs sounds great though, i've not used that. It would certainly help.
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.
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/
Potentially it can save you time in the future. Moving to another hardware is a breath.
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.
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 said "a lot more to it" as well...
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.
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.
I sure am! What is Nix?
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.
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.
Would also be awesome to see something like this for NixOS.
- 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.)
"Declarative, reproducible development environments"
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
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?
why on earth would you make # any kind of a special character in commands. who thought of that
> echo "Hello Nix" | nix run nixpkgs#ponysay
also works.
$ echo a#b
a#bZero 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...
> 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.
'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.)
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.
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.
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`
/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.
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).