I don’t know if it’s just because I hopped on the bandwagon in the past few months, but it really is starting to feel like Nix is gaining momentum.
You can use it on Mac, WSL, Ubuntu multiuser, Docker, in an nspawn container, or through NixOS on a drive. You can build a livecd iso or a Raspberry Pi image from the same flake that you use for everything else.
I work in embedded with Yocto every day, and I can’t help but think that Nix is going to eat their lunch in the next decade.
There’s really never been anything (usable) that’s like Nix. I think it’s inevitable that it takes over everything.
We recently adopted it at my company for managing local dev machines, project environments, and CI. It definitely has some warts, often the best documentation is “read the source code”, but man is it an awesome tool. I’ve switched all of my machines / servers over to it and I’ll never look back.
Now I’m looking at my iPad and iPhone and wishing I could manage them through Nix too.
I’d put it at a comparable difficulty to learn / powerful tool as git. Which given that they’re both based on hash trees makes sense.
Though the documentation may be lacking, or difficult for beginners, I'd like to point out that I've found the community to be extremely helpful, patient and welcoming when asking questions and for help on Matrix.
First, direnv (along with nix-direnv) is really the glue that makes all of this work seamlessly.
It depends on what the dotfiles are for and how they're used.
Here's an example of a problematic one: AWS configs. You can theoretically override the default location of these files with environment variables, but a lot of tooling doesn't respect this and will break as a result.
I often deal with a large number of AWS accounts, so my solution is to have one main way for populating AWS config files that lives outside of projects, and then, because I have a rubric for account/role assignment naming, I can select the correct account/role for each project, and I can even have projects that switch them based on specific code/deployments.
Can you say what specifically? Many language-specific package managers match your description and are completely handled by Nix, but maybe you're talking about something else?
I was afraid of Nix before I adopted it based on what I've read. Now that I've taken the leap, there is no going back. Other operating systems are crude dinosaurs in comparison. Once you get past the learning curve and the initial setup (which can be steep), your system will be far more stable and easy to maintain than anything out there. Declarative OS builds are the future, whether it's Nix or something else.
Okay, sorry to hijack, but I keep trying it, and keep getting stuck. Most recently, how do I install a Rust binary from Github? They have a releases page, or I can just do a cargo build. Either way, I would just drop the resulting binary in /usr/bin and it's done. With Nix... I'm totally stumped. Do I have to package it myself somehow?
If you just want to take a precompiled binary and install it, you just have to write a derivation wrapper around the binary which will declare the expected hash and take care of e.g. unzipping and moving to $out/bin.
Once I discovered `lib.fakeSha256`, I just put that in the derivation, try to build it and then use the error message to find the correct hash to put into it. Probably not the fastest way to do it, but it's easier for me to remember.
> Either way, I would just drop the resulting binary in /usr/bin and it's done. With Nix... I'm totally stumped.
If you don't care about Nixpkgs conventions ("build phases", etc.) then you can use `runCommand` to run arbitrary bash code. It's a function which takes three arguments: a name for the output, a key/value mapping for the environment variables (plus a few some special names), and a string of bash code (usually written between ''two single quotes'').
with import <nixpkgs> {};
runCommand
"my-favourite-program" # A name for the output
{
# A key/value mapping of env vars
myVar = "myValue";
# The 'buildInputs' name is special: for each element 'x', the directory '${x}/bin'
# will be appended to the PATH env var
buildInputs = [ jq gcc ];
}
''
# This is a multi-line string containing arbitrary bash code.
# The output path will be provided via the env var $out so we
# just need to create a file or folder with that path
mkdir -p "$out/bin"
echo "$myVar" > "$out/bin/my-executable"
chmod +x "$out/bin/my-executable"
''
One complication is that (by default) the script will be run in a sandbox, with no network access. We should fetch anything it depends on up-front, using e.g. fetchurl, fetchGit, etc. Here's a more realistic example:
I actually hate Nix.. and i agree, i'm never going back. I use it on my desktop (Linux), my Macbooks, and i want it on my Windows machine (not that it's going to happen hah).
The thing that Nix, for me, currently fails at is introspection. Every function is a black box and i have no clue what's in it. I have to go dig up files on github to see what it even accepts. It's as if everything is obtuse.
A "simple" LSP/Type system would do wonders for understanding what the function is, what it does, and the inputs/outputs.
.. also i have some difficulty understanding functional "mutation" patterns like how overloads are implemented. But i hope that'll make sense eventually.
NOTE: i also think Flakes are absolutely necessary for Nix. Nix is way less valuable to me without Flakes.
Agreed on Flakes. It both makes the entire thing much more pure in terms of its guarantees about reproducibility/portability as well as being a lot easier to understand for me as a non-expert consumer.
As a learner myself over the past year, I also strongly prefer the flake workflow— the tooling design makes more sense, there's no implicit magic about where your inputs are coming from, and everything is pure by default. Not to mention the absolute delight that is the `--override-input` flag— being able to layer your project into multiple flakes and then trivially rebuild it with just one part overridden from a modified local source, so great.
But yeah, it's super frustrating that it's all still hidden behind experimental flags and the official documentation continues to suggest non-flake workflows, though. It's ready for primetime— commit to it please!
I would read a bit and look at the nix-pills [1] even though I could never understand them when I was learning. Then, what I always recommend is this playlist by Burke Libbey on youtube [2]. There are a couple fundamental things that you can internalize which will make everything much more approachable:
1. Nix the language is basically a JSON object. Almost everything is about generating and composing subtrees to build a _really_ big JSON object.
2. `<foo>` means from channel `foo`. This is less relevant now with flakes but that was always extremely confusing syntax to me and when I "got it" it made things way easier.
I'm about a year into Nix and consider myself a moderate in some areas but something of an expert (by necessity) in others. I think the ideal pattern is to attack it bottom-up and top-down at the same time.
Bottom up, you want to learn the fundamentals of how the Nix language works, and how the basic primitives it offers can be used to build up package definitions, a package manager, and ultimately an entire OS. For this, the Nix Pills are invaluable: https://nixos.org/guides/nix-pills/
Top down, you need goals for some specific things you want to accomplish in the system. For me, this was automated packaging for hundreds of source repos internal to my company, but that's a bit of a crazy case— for a normal person, I'd expect this could be something like "I want to run a webserver with some static assets" or "I want to define and launch a container declaratively", or maybe "I want a reproducible environment to do Python development in, where the reproducibility isn't just tagged versions in a requirements/pyproject file, but also includes the full underlay of everything I'm depending on from the base system.
Whatever the goal is here, you're inevitably going to find your way to override-related tasks, like "okay, I want to upgrade this package" or "I want to add patches to this package" or "I want to change the settings on one of my dependencies", and that's where the extraordinary power of Nix really starts to sink in, when you realise how much can be accomplished with so little, and you try to imagine what accomplishing that under a conventional apt- or dnf-type system would look like.
I love nix, but you're a lot more optimistic and forgiving of its cons than I am :D
To be clear, I've not used NixOS and it might be a more reasonable experience. Nix package manager though is the most useful tool I have integrated into my dev-life and also the one I am most hesitant to recommend to anyone else. The UX of the whole thing still has a long way to go and the initial installation experience on Mac has been all over the place quality-wise in recent years. Now that flakes are officially a thing (even though they are still unofficial!!!) it again will take a while to stabilize.
My hope is that once that flake transition stabilizes we will have a much more reasonable baseline of UX to begin recommending to others without nearly as many caveats.
> and the initial installation experience on Mac has been all over the place quality-wise in recent years.
In minor defense of this, Apple making the root read-only threw a pretty big wrench in things. There are a lot of little reasons (some understandable and some exasperating) it took so long to adjust, but all of them were exacerbated by the amount of new logistical complexity required (and the amount of experimentation necessary to figure it out).
Most of the issues come from the lack of enthusiasm for moving the Nix store somewhere else than /nix. Even with read-only root, macOS has some designated locations where you can write. E.g. Homebrew uses /opt/homebrew, which is fine because /opt is writable.
I understand the reasoning of avoiding this on Intel Macs, since there there are years of cached derivations which would become useless without hacks. However, Apple Silicon Macs are a clean slate and the transition would've been a good occasion to move the store to /opt/nix.
(I did suggest this in some places, but there didn't seem to be much interest in switching over, unless I missed something.)
By the way, this isn't only an issue with macOS. Nix also doesn't work on Fedora Silverblue because it uses read-only root and the Nix store path violates FHS.
Yup, this. I think a big part of this is that Eelco is really only interested in NixOS. Nix is a large community and there are plenty of people that do care about other platforms, so these things do tend to get sorted out. Still, the core devs will choose to avoid short-term, medium-painful transitions for NixOS even at the expense of killing all the other platforms.
It's not that easy to change the default store dir.
https://cache.nixos.org/nix-cache-info has it hard-coded to /nix/store. If you want another one you'll need a whole new cache. But Hydra only works with one cache, so now you're deploying a second Hydra build farm.
One of the cool features of Nix is that you can evaluate some nix code on macOS even if the target build host is Linux. And then ship the .drv over to the build host. But that only works if both hosts share the same store dir.
So now you're looking at moving the whole community to use /opt/nix. And thinking of how to upgrade the existing users to it.
And fix all of the tooling we built that assumes /nix/store as the store dir.
So far nobody had the courage to tackle this huge task.
I guess this is a valid way to frame the problem (and I personally agreed with moving it), but I'd also quibble a bit...
- IIRC, ~stakeholders weren't keen on relocating it just on macOS because it would require a separate set of build/cache infrastructure (and it sounded like the macOS+Nix community would be on the hook for supporting it).
- There did actually seem to be a fair amount of support for moving it globally (and Eelco, while skeptical, didn't sound like he was going to stand in the way), but the coordination work sounded significant to me.
- Also, I think the circular arguments around relocating /nix played their own role in the inaction/bystanding that let the problem fester (as did, to be fair, fear/uncertainty about whether Apple would later ~secure whatever new location was chosen).
For sure, that part is understandable and the current install is pretty simple since FDE avoids previous steps. But for a while it was _really_ difficult to find the needed info (had to read through Github issues and find specific comments embedded in extremely long threads)
Yes--it was bleak. Getting tired of watching people run into sharp corners in the process of that was part of why I got involved with trying to fix it up, myself.
There were some dumb (but common in informally-organized OSS...) reasons it malingered. Most of them are still problems (though a few have improved or are slowly moving towards it). A lot of the fixes entail investments in improving leverage of time spent on the installer. Better automated testing, more organizational structure/memory/accountability, etc.
But those issues wouldn't have been enough headwind to drag the situation out like it did if there was always one obvious straightforward politically-acceptable solution from day-1 that just needed to get implemented.
To all the folks using Nix at scale: How are you doing it? Are you still using Kubernetes and friends, custom images, etc? How are you deploying apps or making changes to your Nix instances across a fleet of servers?
qq: Any good tutorials to get up to speed with NixOS with 64-bit Raspberry Pi Zero 2 please?
I have a plan to thinker with some off-grid IoT this year, good moment to try something new, like Nix, than continue with Ansible which unfortunately gets out of hand with very long lasting installations - no implicit cleanup of removed resources and lack of build reproducibility (apt-get update issue really).
I know that there’s a very active matrix channel for Nix on ARM that is mostly dedicated to pinephone/smartphone projects, so I imagine there’s some android tooling there but I don’t think it’s “android” in the AOSP sense.
You can use it on Mac, WSL, Ubuntu multiuser, Docker, in an nspawn container, or through NixOS on a drive. You can build a livecd iso or a Raspberry Pi image from the same flake that you use for everything else.
I work in embedded with Yocto every day, and I can’t help but think that Nix is going to eat their lunch in the next decade.
There’s really never been anything (usable) that’s like Nix. I think it’s inevitable that it takes over everything.