I wanted to point something out that the series doesn't do a good job of highlighting:
You can use Nix alongside your existing package manager.
They won't conflict. You can set up dev environments with Nix without drinking the kool-aid. I still have Homebrew installed, and I still occasionally reach for it in the rare cases where Nix is missing some package I want to try. But I am sad every time I do: I never really realized how unbelievably slow Homebrew is until I tried Nix.
So if you're Nix-curious, you can try it out without committing to anything upfront. I didn't make the switch until part 19:
Nix is weird and hard to learn, but it's a lot like git in that respect. Yes, the UI is terrible. You have to learn the difference between `reset --hard` and `reset --mixed` and it's weird and unintuitive but you eventually get over it.
And people are using it despite how unintuitive it is, because of how valuable it is to them. No one is arguing that `nix-env -qaP package` is a reasonable command to ask a fellow human being to type, but people are willing to type it anyway because the benefits are worth it. As a fun example, a few weeks ago I wrote up a little hack that I would not have even attempted before spending the time to learn Nix:
> So even if something bothers you about the software you use every day – even if you find a bug in tmux, or wish that you had some additional jq function or whatever – you probably aren’t going to do anything about it. It’s not worth it; it’s too hard.
> I am obviously projecting here: that is the way that I thought before I started using Nix. I never would have tried to change this Emacs behavior back then.
> But now?
> Now I can get a working build environment for any package I want, just by running nix-shell. I can write a patch, and I can ask Nix to automatically apply that patch to the latest version of the package. I don’t have to worry about maintaining my own fork or manually updating it – I can keep using all the same commands to list and upgrade and uninstall packages, regardless of what I’ve done to them.
I think this is what all the old greybeards have always been getting at when they talk about software freedom, this blurring of the line between user and contributor that is possible with F/OSS. I know for a fact that there are some HN posters who do use apt-get and related tools this way (that Debian developer who taught his kids to use Xmonad, for example). But I do think it's something Nix is especially good at, as a flexible, source-based package manager.
It's really nice to be able to treat your customized builds in a first-class way with a mature system for managing software.
Btw, if your main use case for this is customizing F/OSS, there's a SaaS offering you can use for free to recover binary caching without even having to set up a build server. Pretty cool if you have multiple computers! https://www.cachix.org/
`apt-get source` and `apt-get build-dep` is a wonderful thing! It's a shame there isn't more around that (like how to navigate the code to a large software package once you have it, eg Firefox).
I remember how awesome it was to switch from Homebrew to Nix, noticeably the speed. But there is something off about Nix:
+ Installation process, especially on Mac: nix, and then home-manager. And I don't even mention flake. Right now I'm settled with a helpful script from https://nix.dev/, but I don't say I'm fully confident.
+ How to add an external package which is not in nixpkgs. I have to learn Nix and dig Nix docs and ask too many questions to figure this process. In the end it is awesome but I could feel the barrier for beginner.
+ Documentation. It's easy to get started with some popular packages but it's a pain to customize your own. I always find myself banging my head to dig the information I need.
So in conclusion, Nix is awesome to use if you invest time to learn the Nix expression language. Otherwise you have to stuck with the default packages provided by nixpkgs.
I love nix as a concept. I have a couple concerns in practice.
* I don't want to learn nix, nor do I want to learn apt, brew, pip, npm, crates etc. beyond a handful basic commands: install, remove, list all, list package (version & deps), update (at version). A one page cheatsheet would be fantastic.
* There is a ton of QA work sunk in standard package manager workflows. Is there a way to leverage this work? You allude it is possible, hopefully there is a one page cheatsheet explaining how.
Regarding obscure command syntax, I use bash aliases to give names to the most common 7 git commands (which constitute 99% of my daily usage) and never have to remember any git command flags.
The thing is, I don't think the one page cheat sheet is very useful.
npm is a great example of why: pretend that all you have is `npm install -g`. That's sort of how a traditional package manager, like Homebrew, works. But that's not typically how you use Nix, just like you don't typically globally install npm packages. Instead, you write package.json files -- which isn't very hard, because you already know JSON.
But in order to write the Nix equivalent, you have to learn the Nix expression language. You can just copy a template shell.nix file and modify it slightly (as you might for a package.json file), but it's likely that that will be frustrating, because... well, because you still have to learn about garbage collection, and channels, and lots of other incidental things that don't map as cleanly to traditional package managers.
There are cheat sheets, though. I linked my Homebrew <-> Nix translation guide above, and the NixOS wiki has one for apt-get:
But this requires so many asterisks as to be not extremely useful. For example, that page lists `nix-env -u` as an equivalent of `apt-get upgrade`, but it's not. `nix-env -u` is hopelessly broken and will not do what you want. There actually isn't a "right" way to upgrade packages if you're using nix-env. It's just not a thing that Nix can do.
Which sounds crazy at first glance, but remember: nix-env is like `npm -g`. Even though that's a first class concept in most package managers, it's sort of bolted onto the side of Nix, and accepting "the Nix way" of doing things is important to have a pleasant relationship with the tool.
Right, npm (and other language-specific package managers) do dependency resolution in a first-class way and Nix doesn't. Nix resolves dependencies in the way that's typical of source-based package managers: when you name a package as a dependency, what you're depending on is whatever version of that package simultaneously inhabits the monorepo of build recipes as your package.
Language-specific package managers like NPM or Cargo or Composer are not designed for a universe in which packages inhabit a monorepo where compatibility is ensured simply by coordination of changes in that repo. They're built on top of a different kind of infrastructure.
They also face different challenges since their focus is much narrower, i.e., libraries in a single language with a single build system, rather than whole applications whose build system can freely change in a fairly open-ended way from version to version.
It would be pretty cool for Nix to have some version constraint solving built in, and for Nixpkgs to host more versions of many packages. There's precedent for that in a way that wouldn't require radical change to Nix and Nixpkgs in other source-based package managers like NetBSD Pkgsrc and Gentoo Portage. It would also be cool to provide some built-in machinery for pulling package recipes out of old versions of Nixpkgs (or searching a global registry of some other kind for them). Whether the latter happens will probably depend on the future of the flakes implementation, and extending it backwards will take manual work. There's already sort of a proof of concept, though, in the implementation of one tool for generating Python packages for use with Nix (mach-nix).
I forgot to mention that an in-depth resource like the OA is invaluable complement to terse cheatsheets for the 1% of the cases when the common commands are not sufficient. Thank you :)
I've bounced off Nix a couple of times and figured that the problem is that it was too different. A lot of Linux distros (especially post-systemd) have a fair number of similarities and it's pretty easy to translate knowledge between them. NixOS _probably_ works very similarly, but it's also got this additional declarative configuration layer on top, which is the point of using NixOS, and it's got its own special way of doing things.
You can't translate Linux knowledge to a NixOS config directly, you need NixOS' documentation to understand the "NixOS Way" of doing things, and the NixOS way of doing things does not translate into other distros. And the documentation is difficult to understand and at times seemingly arbitrary.
You have to commit to learning NixOS and understand that you are only learning NixOS, it won't help you use anything else. Other Linux distros help you learn Linux in general and inform your understanding of Linux system construction, but NixOS is its own thing. Plenty of people learn NixOS anyway, and more power to them, but it's definitely pushed me away.
> "and understand that you are only learning NixOS, it won't help you use anything else"
So — for one thing — in my personal case, it helped me at one time when I was experimenting with kernel build flags. With the caveat that finding how to change them was (surprise surprise) typically non-trivial in Nix in the first place... so it may be a feeble counterpoint... but still, after I found how to do it, NixOS made rebuilding new OS with different kernel flags absolute breeze, with basically 0 worry if I bork something (I mean, except maybe going to deep hardware params hacking such that would risk fraying some electronics) — I'd always automatically be just one GRUB entry away from a previous working configuration. (Though also useful to have `git commit`ed the previous /etc/configuration.nix from before I made some risky change, so that I could easily go tweaking again from there.)
I've had a similar experience with systemd itself. While you could go and read through the systemd docs to understand all of its nooks and crannies, you can actually learn the important bits by reading through the source for NixOS's modules (which are linked directly from https://search.nixos.org/options). You start to see patterns of which options they set in the units, and pretty quickly build up the knowledge you need to write your own. This is also aided by the fact that the repository is one giant git repo hosted on GitHub that you can search, clone, tweak, atomically deploy from a local branch. It buys you so much flexibility when experimenting.
This is something that is coming to traditional Linux as well though, with zfs snapshots. I've had it for a long time on FreeBSD. I just snapshot before I do something big.
I see the benefit of declarative configuration as an admin at work where we need to set up many systems the same way. For home desktop use I don't really see the point, I don't think it's a tech that fits perfectly in every scenario. Like most technologies there's usecases where its benefits shine and the drawbacks are irrelevant, and others where it's the opposite.
For example I often come across software that isn't packaged for my OS and I like to just compile them and try them out without having to do the whole packaging routine.
As to "home use", personally I'm successfully keeping my dotfiles & $HOME/bin/ scripts managed with Nix + home-manager. Becomes useful when changing jobs, and also makes it easier to share new config tricks between work & home machine. Regardless if Linux or Mac.
edit: in particular, going just Nix (not NixOS) on work machine(s) allows me to fall back to apt-get/brew quickly when a particular tool is not (yet) on Nixpkgs.
> For home desktop use I don't really see the point
Lucky that you don't need to run NixOS as your OS to get a lot of the advantages from it then. I use debian for my boring desktop applications but have Nix available to me for when I need any e.g. development tools.
This is what I used to think, but after twenty years of running Linux, and at least twice that many reinstalls, I very much appreciate an OS that doesn't eventually bitrot underneath me.
"Just install this one package to get CUDA working"... no. If I do that, then in two months when I want to do something else I'll find my OS is no longer capable of being used that way. And in four, when I want this specific version of CUDA working again, I don't remember how. The instructions probably wouldn't work anymore anyway.
NixOS allows me to put in down in terms of code, and the code practically never stops working. It's also immortal -- I've never needed to reinstall it. If I did, it'd be painless, but that's only ever happened in case of hardware failure.
> I thought it was always going to remain poorly integrated into the Linux ecosystem.
Interestingly, NixOS excels at ZFS integration.
Because NixOS builds everything from source with transparent binary caching, always upgrades your system as an integral while, and performs upgrades atomically, you'll probably not even notice that ZFS isn't in the mainline kernel as you use it. NixOS will never upgrade your kernel to one that's incompatible with whatever version of ZFS is in the repos, and it'll never leave you in a partially upgraded state where your new kernel is installed, but your new ZFS modules are not— even if you pull the power during an upgrade.
To my knowledge, the integration with the kernel is still not very good. As someone else mentioned in a reply, there are large swathes of the Solaris kernel with duplicate functionality included in the Linux kernel solely to support ZFS, because native integration is too difficult in face of the licensing and maintenance issues.
It remains a kludge rather than something that can really be thought of as an integrated Linux solution. Even if it works okay in some situations.
Is the Solaris Porting Layer really due to a licensing issue or just a ZFS portability issue? FreeBSD's ZFS implementation reportedly has a similar portability shim.¹ The new OpenZFS implementations for Windows and macOS each have their own Solaris Porting Layer, too.
If what you want is just snapshotting and you want something that's in the mainline kernel, I guess there's BTRFS. Bcachefs seems to be coming along nicely, but who knows when it'll really be ready.
I can ignore the licensing for my personal stuff (and some work might be able to, too) but from a technical perspective I find the SPL translation layer and fs caching overhead much greater pill to swallow. It’s basically bolting on Solaris as a 2nd memory system just for zfs. I really hope this hack is recognized for what it is sooner rather then later…
> This is something that is coming to traditional Linux as well though, with zfs snapshots. I've had it for a long time on FreeBSD. I just snapshot before I do something big.
This has been available on traditional Linux for quite some time with btrfs snapshots.
> You have to commit to learning NixOS and understand that you are only learning NixOS, it won't help you use anything else.
This is kind of true on a surface level, but NixOS experience can be super helpful for setting up other distros because it turns Nixpkgs into a repository of high quality examples and demos that are always up to date.
Once you learn some basics of reading Nix code and how the NixOS module system works, the Nixpkgs repo itself becomes an excellent cross-distro resource on how to configure Linux software, much like the Arch and Gentoo wikis. I often consult Nixpkgs on how to do things in Linux for the purposes of configuring another distro or helping another user to do so! :)
The NixOS way of doing things (a layer on top of plain config files) is inevitable once configuration management is taken seriously: one needs to be able to merge configuration values from multiple source files; for example, a generic role plus some more machine-specific role, working together to produce one systemd unit or file in /etc. The modules in nixpkgs effectively make it possible to combine configuration values to produce most of the config files that Linux applications want.
If one weren't using NixOS to do it, it would be done with your own templates and configuration management, and probably without the huge advantage of being able to rebuild a whole immutable system without leftovers from prior configurations.
Doing programmatic configuration with a traditional distribution isn't difficult. I've got a python script that starts with a tree of config files and a top level file that says what files to consider per-machine. Each config file is run through Jinja2. Some templating even pulls data from a LibreOffice spreadsheet [0]. By default the script only pushes files that haven't been remote, so if you do deviate and edit a config file on a machine you can diff it to merge those changes back into the centralized config before overwriting.
Having said that, I'm moving towards NixOS for reasons detailed in another comment.
[0] It's ugly but it works. I'd love to find a lightweight curses-based data structure editor.
Where is the evidence for this? Where is the evidence that you can and should mix config management all of the way down the OS stack? How many containerization concepts do we need? Docker, lxc, VMs, and now NixOS? If it were a legitimate abstraction layer, then wouldn't it have caused fewer problems in implementation? And wouldn't it have seemed more intuitive to Unix experts? Yes... Reinventing the wheel again. I'm open to nicer restructuring of the Linux fileystem, but this is really re-inventing the wheel trying to polish over ugly parts that are ugly for a reason. Keep useful abstractions separate!
One problem that NixOS solves is to be able to use different tools on the same host in different versions easily(1) and in a reproducible way(2). Docker containers can be used to solve 1), but they are in some sense overkill and quite a few uses cases. If you are a developer who only wants do use different compilers then Docker containers are not really ideal, because they also enforce process isolation. Also there is the popular believe that Docker containers also solve 2) that is not really completely true. Yes you can run a Docker image in a reproducible way on different machines, but cannot necessarily reproduce the Docker image, at least not with the standard Docker tools. You can use Nix to create Docker images in a reproducible way.
> If it were a legitimate abstraction layer, then wouldn't it have caused fewer problems in implementation? And wouldn't it have seemed more intuitive to Unix experts? Yes... Reinventing the wheel again.
The basic concept of Nix is (a) use the `--prefix` argument of ./configure scripts to keep things apart, and (b) use the `PATH` end var to choose what we want to run.
In comparison, containers are much more recent, require more invasive changes (i.e. support from the kernel), etc.
Personally, I like using containers to run binaries. Putting a whole Linux/Busybox installation inside one seems to defeat the point though...
This is why I feel efforts like Fedora Silverblue might end up becoming mainstream in the years to come rather than esoteric projects like NixOS.
I personally dislike both projects though, when it comes personal desktops. Silverblue is heavily influenced by Flatpak and I don't expect RPMs for GUI applications to survive in Fedora. NixOS needs you to learn Nix which is a pretty steep learning curve and like you said, that knowledge probably won't translate anywhere else. You're probably better off investing your time learning things like shell/python scripting, Ansible, and Docker/podman.
Flatpak and the likes are similar enough to Apple's "bundle" concept where you put all the versions, dedicated libraries and frameworks inside the bundle for your 'thing' that you want to distribute. It has been proven to work well (or well enough). I suppose the additional technology behind overlays/bindmounts etc. is different since a Darwin bundle is practically just a directory with some predetermined layout but the experience is the same.
Once it doesn't depend on (yet again) a daemon, registry, and other system-level components but is understood by the shell (or DE) instead, you get a user experience that something like Nix cannot deliver (or at least, not without cutting down on the whole "learn this language to then learn those features to then get work down" thing).
The bundle concept applies more to AppImages than to Flatpak. Flatpak downloads common runtime libraries and packages and uses them to run all GUI packages in a sandboxed environment using bubblewrap. OStree is also involved.
I dislike Flatpak because it encourages package maintainer obsolescence. I heard a guy from OpenSUSE saying in a MicroOS presentation that why create, manage, and use RPMs when we can just use Flatpak. I also don't want to touch Flatpak anymore because people from GNOME are involved in it.
I have to admit that Flatpak's runtime deduplication is impressively good, despite preferring the Nix approach.
It's a shame to hear that kind of talk coming from the openSUSE world when Zypper did so much to raise the bar for high-level Linux distro package management tools. :(
openSUSE does an awesome job getting a hell of a lot of mileage out of RPM, from the vendor-based repo management to BTRFS snapshots to the huge and powerful (cross-distro!) automated build service.
> It's a shame to hear that kind of talk coming from the openSUSE world when Zypper did so much to raise the bar for high-level Linux distro package management tools. :(
Yeah, I don't think it'll last in the foreseeable future judging by how these distros are jumping on the Flatpak/Snap bandwagon. For these distros, package management might as well be dead.
I expect a few distros, such as Alpine Linux and Arch Linux, to remain relatively free from the influence of Flatpak and that's what I'll continue to use on my personal machines.
right now NixOS is for a small subset of geeks(who are ok with using custom functional language for pretty much all configuration) but it's entirely possible to make a GUI based like a SUSE configurator based on nix, and with mature enough nix ecosystem it will work flawlessly an be powerful and simple to use for the end user
For the end user it doesn't matter if a GUI is using some nix-thing in the background. It could just was well run dpkg/rpm behind the scenes and as long as the result is the same it really doesn't matter.
This is also why Nix and NixOS painted itself in a corner; the presented value is only relevant if you are hacking away at it. When you have a smooth GUI experience it really no longer matters what the technical goodness underneath is.
I think the point is that Nix makes it a lot easier (in some ways) to build a more reliable system GUI, rather than other package managers because of declarativity being a first-class feature.
Users shouldn’t have to care what their GUI uses underneath, but it could be the difference between building your own pseudo-declarative layer (which you now have to maintain in perpetuity and handle all the small edge cases), or getting something that is already declarative as the backend and simply generating a config file from the GUI (https://github.com/nix-gui/nix-gui).
EDIT: Also composition. Users could, if they wanted to, augment the GUI generated configuration using the built-in Nix features for composition with config files, which is a lot easier than trying to do the same with traditional system managers.
I doubt a user wants or cares about any of that. User story:
As a User I want to select an application to run so that I can use the application.
This applies to practically everything, if you want to play a game, you don't want to dick around with installers, managers, layers, configurations etc. Just point and click, that's all it should need.
My main point was in the first paragraph. Users care about reliability and I was justifying why I think Nix has the potential to be a more reliable base for a GUI than other options.
I also do think certain users will care about e.g. extensibility/composabilty, as soon as they have to do anything outside of the officially blessed path. Having the ability to compose things nicely is pretty useful. It’s the difference between having to recreate the entire GUI configuration manually and just being able to dip into the config for the (likely small) non-standard part of the system.
While I agree with that, operating systems like macOS and Windows have shown that ease of use still beats other features when a user simply wants to 'do' something.
As good (or as bad) as the technical underpinnings can be, as long as the user gets what they want most of the time they are fine with it.
Nix is one big advantage of course and that is that is isn't a commercial endeavour beholden to markets and income. So it doesn't really matter what general users might want or think (at least not at this stage). We also still have the same problem that is always present and that is content availability. If a user wants to install a Netflix client but none is available, it doesn't matter how good the tools are. Even the best UX can't help when the desired content isn't available.
Nix isn't a package manager, it's a system for making ad-hoc, repeatable computing environments.
The "package manager" paradigm doesn't fit Nix that well, which is why it's a painful experience when you come to it from the angle that it's another Linux distro.
(IMO it makes more sense to think of Nix as "declarative Docker that doesn't need Linux namespaces".)
Thisss! I'm very disappointed that most people seriously misunderstand what Nix is.
Some calls it just another package manager and others dare to call it another Docker... while i'm screaming in horror internally.
Nix is pretty unlike the package managers of most popular distros, but it's not so dissimilar to other source-based package managers, like Gentoo's Portage. The basic idea that you have a giant monorepo of build recipes and a tool that automatically builds packages from source according to it is the same.
It's absolutely true that you're missing out if all you do is use `nix profile install` like you might use `apt-get install`, though.
The projects do rely heavily on Nix for infrastructure stuff, and I have to explain it to unprepared developers often.
The best angle is to explain it as "like Python venvs, except works for any combination of programming languages". That sets for correct expectation for feature set and complexity.
P.S. The single biggest huge blocker is lack of support for nix-shell in VSCode and JetBrains IDEs. Every other complaint is a minor trifle in comparison.
> The single biggest huge blocker is lack of support for nix-shell in VSCode and JetBrains IDEs. Every other complaint is a minor trifle in comparison.
> No, not really. [...] [E]xplaining it as "like Python venvs, except works for any combination of programming languages" [...] sets for correct expectation for feature set and complexity.
That's definitely a good description of the development environment use case, for people who know what Python venvs are for. It's also accurate, as far as Nix is about Nix profiles. Nix profiles are like Python venvs.
But all or close to all of the packages in Nixpkgs work just fine even if you have no profile at all set up for them— they behave correctly even if you invoke them directly from their paths in /nix/store. If you look at the install target as `/nix/store` rather than `/nix/var/nix/profiles/...`, then `nix-build` is just a source-based package manager in the ordinary sense which:
• installs each package to a unique, content-addressed-ish prefix
• uses the Nix language and Bash like Homebrew uses Ruby, Portage uses Ebuilds + Bash, MacPorts uses Tcl, etc.
• happens to have a really good build caching story
And your tools that build Nix profiles (`nix-env`, `nix profile`, `nix-darwin` and `nixos-rebuild`) aren't doing package management in the sense of building or installing anything, but instead just build convenient facades (out of symlinks) for accessing all of those packages installed to /nix/store in a more convenient way. The venv-like properties of those facades (symlink forests) just emerge from the one-prefix-per-package strategy of the underlying package manager. (In the case of profile managers that manage services, they also run some activation scripts.)
All of that is not to say that what I outlined above would be a better strategy for describing Nix to developers who just want to take advantage of environments that their DevOps team has prepared for them. I think you've settled on a really good explanation, for the reason that you outline.
If you're the Nix guy at work, you probably already understand what I wrote in this post, and have good reasons for preferring to present Nix to the developers that you support in the way you do. What I want to point out is more for the benefit of others, especially people who've done packaging or sysadmin work with other distros but maybe don't get how Nix works, maybe because they're turned off by all the FP jargon.
The lesson is this: there is an old-fashioned, familiar sort of package manager underneath the tools Nix users interact with. The essence of how that package manager is different from what came before can be boiled down to a single sentence: each variation of every package gets installed to a unique prefix. Once you have that, you can do wonderful things like build in snapshot-free rollbacks; allow unprivileged, per-user installation of packages; or generate venv-like per-project environments; and all of the other cool things Nix enables. Nix's complexity and power both follow from that one tweak, from what it took to get there on the one hand (the concept of derivations and various properties of the Nix language) and what it buys you once you have it (polyglot, venv-like setups and lots of other goodies).
The knowledge is one thing, because you can always learn how to do things the "Nix way" (either by reading the incomplete documentation or tinkering for hours until the thing works).
But the real problem is that software does not understand nix either.
For example loads of scripts expect /bin/bash to exist, but on NixOS it is missing. Want to run a random python script from github? Well that's a bummer, because there is no nix version of a random library this script uses. Also no-machine server and Chrome Remote Desktop don't work, and these are the two remote desktop solutions which work on spotty 4G.
And I had to ditch NixOS, because my employer forced me to use a proprietary VPN, and I there is no way it would run on NixOS.
For python, you're best off using a virtualenv anyways. For proprietary binaries, you can almost always get them to run using steam-run. But the nicer way is a wrapper script to set up LD_LIBRARY_PATH, or custom derivation to patch their ld lib paths.
Yeah it requires some elbow grease sometimes, but what distribution doesn't? Maybe Fedora/Ubuntu? I think the pain really is all that prior Linux knowledge is non-transferable and you have to learn how to fix things in the Nix way.
> wrapper script to set up LD_LIBRARY_PATH, or custom derivation to patch their ld lib paths.
There is your problem, I don't want to spend time writing wrapper scripts, or researching how to craft my buildFHS for every little piece of software I will run once for an oddly specific purpose.
Running the proprietary VPN on Arch Linux was as simple as running debtap, and then installing the package via pacman, even though the package shipped by the vendor was made for Ubuntu. It even figured out the dependencies automatically.
It could probably be automated more. It's just that most NixOS users have low interest in automation .deb -> Nix conversion since it's not something you actually run into often as a NixOS user.
you should not create such an imperative simlink
almost anything can be packages with nix in a minute or two, so any code you found out the internet would be easy to run and it will take not much more time than to simply check it's build config for malicious code, which you should do anyway
Maybe if you use buildUserFHS and --impure a lot. But NodeJS applications that try to download binaries at install time or python packages with conflicting package versions definitely take more than a minute or two. Just look at the history of Anki in Nixpkgs, or the derivations for JetBrains products or Cypress or any of the other packages that took consistent effort by multiple contributors to even get them working in the first place.
I think it's important to manage expectations about Nix and that includes being realistic about what's easy and simple what isn't.
Yeah, I am aware what I did above would make a lot of nixos purists shudder. But from a pragmatic pov it saves me a lot of time. It's mostly to deal with repos at clients that are filled with scripts hardcoded to /bin/bash.
I really tried making a derrivation for for the nomachine server, but it consists of a wrapper script in bash which for some reason is very long and complicated, this script calls a binary which required some libraries which were missing in the NixOS repo, and everyting assumed the program was installed in /opt/something. Then I tried steam-run, but the program just segfaulted on me when I tried. This is where I reckoned investing more time was not worth it.
On Arch I just do `yay -S nomachine` and call it a day.
But I really believe that someday the NixOS community will catch up, but currently it is not for me, since sometimes I want to get stuff done and not tinker with my system.
I played Dota2 in NixOS for years, so i am not sure why steam wouldn't work for you(it uses FHS too). You can always ask for help in discourse/matrix channel.
> since sometimes I want to get stuff done and not tinker with my system.
Plenty of people do get their work done on NixOS, so good luck with that attitude.
> You have to commit to learning NixOS and understand that you are only learning NixOS, it won't help you use anything else.
As a NixOS user, I did learn a lot about what is part of Linux distributions and what is part of the kernel, and how they interact. Compared to my previous Ubuntu knowledge, of course. If I would have ran Arch, I would have learned similar things.
I bounced off NixOS a few times as well. In addition to what you've said, I also didn't find it compelling because I already had a way of doing programmatic configuration and functional system management under Debian using my own scripts. So I didn't particularly see what converting everything over to NixOS configs would get me.
What made NixOS stick is running up against some problems where Debian itself was ill-suited and seeing Nix's power. For example, building an image for a Raspberry Pi can be done with a handful of config lines. Changing between a cross compile and an emulated compile is also a handful of lines. This kind of power feels akin to the general lisp / functional curse where certain things become so easy they aren't even well documented because once you understand the system it's second nature.
Another benefit - I've modified kernel source and I've written my own modules, but they always fell by the wayside due to the maintenance burden of a compiling a custom kernel package. With Debian, I would end up reading kernel source plenty of times to figure out what was going on, but it was effectively read only. Whereas with NixOS, adding kernel overlays is straightforward. Using what is essentially a source distribution plays to the larger philosophy of Free software.
Same here. I still flock to the page every now and then and think about to give it yet another shot. But my main usecase is to develop software. I work with java, rust, ruby, JS and different other languages that needs custom treatment when doing things the nix way. Like writing a custom nix shell env file which deals with npm dependencies and the like to have all the glory deterministic package updates etc. I guess I will try it again at one point.
This is a pretty good take. Although I'd further emphasise: knowledge of Linux is "necessary but not sufficient" for using NixOS. NixOS requires additional knowledge, rather than a different set of knowledge.
I think for many developers with Linux experience, probably getting a reasonable NixOS desktop setup is straightforward.
There are some compelling benefits to Nix/NixOS, but these also require getting past a steep cliff in the difficulty curve.
>I think for many developers with Linux experience, probably getting a reasonable NixOS desktop setup is straightforward.
I took this as an excuse to try NixOS myself and an opportunity to provide anecdata.
Previous Linux experience: Lots, including about 7 years of Gentoo use, some Arch and the usual distro hopping before that. Mostly on laptops (not counting VMs). Lately it's mostly been the BSDs so I'm a little lost.
It took me about 45 minutes from searching for their site to have a working XFCE install using their minimal install ISO with VirtualBox. Certainly a different experience, but with their install guide and searching "nixos xfce" you'll get it done.
Promptly rebooted and went for an encrypted ZFS root - less straightforward but after a few PEBKAC snags I got it up in an hour or two.
My immediate impression is that this is great but not being allowed to just
# which zsh >> /etc/shells
rubbed me the wrong way. Definitely something I'll consider using in the future, seems like a good fit for i.e. a VPS you might want to move easily.
Naturally I haven't learned the config language fully, but it seems easy enough if the docs aren't terrible.
> My immediate impression is that this is great but not being allowed to just `# which zsh >> /etc/shells` rubbed me the wrong way.
Yep. That kind of thing will come up; on NixOS, root's interactive whim doesn't own /etc— `nixos-rebuild` owns /etc. But of course, both root and nixos-rebuild are you, so that's not so bad. :)
For those curious (I assume the parent poster already figured it out) the NixOS way of enabling ZSH as a login shell is the following one liner:
programs.zsh.enable = true;
which will both ensure that it is installed and on the PATH, and add it to /etc/shells for you.
As a rule of thumb, it's generally a good idea to check the NixOS options to see if there's a module defined for configuring a program before just adding it to your `environment.systemPackages`. Here's NixOS' zsh configuration options, for example: https://search.nixos.org/options?channel=21.05&from=0&size=5...
(`programs.zsh.{shell,prompt,loginShell,interactiveShell}Init` are your escape hatches; you can put whatever custom zsh scripting you want in there)
> This is a pretty good take. Although I'd further emphasise: knowledge of Linux is "necessary but not sufficient" for using NixOS. NixOS requires additional knowledge, rather than a different set of knowledge.
You can use NixOS to learn more about Linux quite well. You can't really ruin everything by mucking around at the low-level. Just rollback to previous generation. I've definitely learned a lot due to NixOS allowed me to hack with impunity.
Recently started using NixOS, and nix.dev has been very useful thanks!
Some more NixOS-specific stuff would be really nice, if it’s in scope. I think a lot of the power of NixOS comes from the composition aspect, but I haven’t managed to figure out how mkOverride, mkIf, mkDefault and everything else actually work (rather than at a superficial level). I’m not sure if something as simple as adding an item to an option list from 2 separate bits of config is possible for example.
Along the same line, another thing I’ve found hard to discover is patterns used in the standard library. For example, I recently learned about makeBinPath from some random Nix file, and I’d really like some way of discovering quality of life stuff like that without needing to randomly come across it in some Nix code.
I would like to see it mentioned how to use Nix as a system package manager in MacOS. This guide was exactly what I needed: https://wickedchicken.github.io/post/macos-nix-setup/ and the official documentation made no mention of nix-darwin.
It was frustrating reading all the official intro documentation on Nix and it only talking about nix-env (not declarative AFAIK) or how to use Nix for per-project dependencies.
A couple of things come to mind that I'm struggling with now:
1. how to install outside of NixOS, mostly to use home-manager, in a flake-y way using the new `nix profile` thing that supercedes nix-env. The few folks I've spoken to seem to prefer to use NixOS as a shell, then to manage their dotfiles with home-manager, and trying to figure out how to manage this global state in profiles with flakes (e.g. I've heard ~/.config/nixpkgs/flake.nix is the location, but hits on a web search for this file name are almost non-existent).
2. how does one _develop_ with flakes. I get confused about how to use the repl to add something into my config (thankfully there's :lf now!). Some simple walkthrough that goes from packaging a simple application and troubleshooting in the repl, using shell to check the build stages, etc, would be extremely useful. Once one gets over this hurdle, Nix becomes an extremely attractive tool to bundle existing code and manageg packages, and new users start to see the power of it.
I hope you take the time to read the whole series, Domen! It's like a perfect test case to drive the kind of docs you've put so much effort into— an extremely detailed experience report
Thanks to nix.dev, I can run some commands and get a feel for what nix is in a single night rather than wading through the documentation. Apart from how to use nix, I see the need for resources on what problems it solves and how it solves it.
Are there any resources on taking a production example of issues we face on a daily basis and solve it with Nix and explain in a way without someone has to actually learn all of Nix in the first place ?
Thinking of practical production problems. We are using docker at work and it is great for deployment. But for dev setup it was painful.
Let me give you an example, I need three services running to be able to make changes to a package. The 3 services comes from the registry, so no docker files locally. As for docker-compose.yml it just starts the 3 services and builds the docker file for the package.
Now for the dev environment the way we are solving it is by creating a docker-compose.override.yml style. This works great isn't it ? The problem is we still need to support python2( I know, please don't judge). So we ended up with 2 dev environments one for each python version. So at the end I have two docker files for each version of python. 4 docker-compose files, one for dev and one for deployment. ( There are projects which reduced the docker-compose.yml files by adding the python-2 and 3 in the same file as different services but yes it blew up the file )
We might be overdoing this and completely wrong in the way we approached. I am open for feedback.
At part 3 now, and it's great. I feel like I might finally learn what all the arcane stuff in the manuals actually mean. Most of the Nix documentation is like reading ASCII EBNF or research papers. This, on the other hand, has just the right amount of snark:
>> A store path Q is reachable from another store path P if Q is in the closure of the references relation.
>
> Good definition. Intuitive term.
I wasn't sure if this is supposed to be snarky, given the author said he has a background in functional programming and thus probably has a good understanding how closures are defined. The statement works both ways I suppose.
It's "closure" in the mathematical sense, not in the functionnal programming sense. It would have been clearer with the full term: "transitive closure" instead of just "closure".
> It's "closure" in the mathematical sense, not in the functionnal programming sense.
The latter being of course an instance of the former :) Your lambda uses a reference to a local variable `x`, so go follow it and transitively capture all its references, repeat until you've closed over all such transitions.
let a = // whatever
let b x = a + x;
let f x = x + b x; // closes over b and transitively over a
One of the things I've hated about being a part-time systems administrator is the fear of the unknown. All the little changes to config files, the different installed programs, everything required to get the system working is scattered around the disk. It creates fear around making changes, because who knows which little configuration change was required to get everything working? I understand that better organizations try to combat this with rigorous processes and documentation, with great effort.
I recently evaluated NixOS for a new server deployment. Being able to describe the entire state of the system in a single file is magical - it is so clearly The Right Way to do things. I am not a Functional Programmer but using the Nix language as just a config file is fairly straightforward. I left convinced that a simple functional language is the best way to make more complex config files, way better than Jinja2 templated YAML. (Though, functionistas, come down out of the ivory tower and make a language that looks C-family. Yeah, "it's just syntax" so why not make it easy for the proles like me to learn.)
However, I ended up giving up on NixOS for two reasons.
First, while learning the basics of Nix was easy I wasn't confident about the more complex things. Packages were missing features and I was going to have to start investing in reading and writing lots of Nix code. I couldn't continue ignoring the many intricacies of the Nix system if I wanted to be confident that I could quickly fix an issue at 2AM on a Saturday. As others have noted, there is a lack of good intermediate-level documentation apart from this great "How to Learn Nix" blog. My whole interest in Nix was being able to completely document the system so that future me or someone else could quickly understand how the system is configured. That doesn't work if you can't count on that person knowing Nix very well. Even if I invested in learning Nix it would feel like professional malpractice to dump some heavily customized Nix system on the next guy to come along.
Second, there's no LTS. That's fine if it's a dev machine, or if you have a professional full-time ops team watching package changelogs and testing upgrades. My machines need to survive with bare-minimum supervision.
I learned Nix a couple days ago because I needed a build system for my project that could handle many different tools: Java+Gradle, Thrift, Rust, Python, CUDA, etc.
It's been kind of a pain: Docker is easier to get started with. But the payoff seems higher because it does handle all these tools in a sensible way: For development I can switch between subprojects written in many different languages and get the exact Python, Java, etc. and all necessary libraries are in scope.
I've gotten it working on Linux, and I expect a little more work porting to Mac OS for teammates(mostly for things like switching from CUDA to CPU based on system), but using it should be similar to Linux. Mac doesn't support cgroups or Linux containers so sandboxing is weaker than Linux, so it's better to develop Nix projects on Linux and add other platforms afterward.
I would recommend it for polyglot or Python projects. But for single-language projects with a sensible dependency manager(Rust Cargo), there's not as much benefit.
Nix is really nice for polyglot development environments on macOS, because the fact that Docker requires full machine virtualization makes it very heavyweight. Nix gets to be a lot faster and simpler. (And you can use it to generate Docker images and full fat VMs if you still want that option.)
I thought so at first too, but then I realized, no matter what distribution comes up in the future, learning a new distribution from the ground up is going to be hard no matter what. I dove head first into Nix and after a understanding the language, the OS and package manager was actually not that hard to understand. Now in after hand, I don't regret any of the the time I spent learning it.
I recently installed GUIX and just out of the gate I like the syntax much more than I ever did with Nix. The Nix syntax is just to random and hard to just guess what is going on if you're not sure what you're looking at. At least GUIX is more traditional looking Scheme type code.
I don't have time to play with it, but really hope that one day someone will write something that effectively "compiles to nix". As far as I can tell, that could be done using the Spack's python descriptions.
Dhall is a generic config language with some programming capabilities (but not turing complete) that can compile to json, yaml, and other formats, like in this instance nix.
It's not just the syntax (for me anyway). I just don't care about the how the derivation composes in practice, how it does overrides, how it integrates with flakes, how it applies the best-practices-of-the-day. I see the derivation as pure function as a cool theoretical exercise - but not something I want to actually write.
I want to actually declaratively say: here's an autotools package with some parameters I defined, give me the fancy overridable pure nix equivalent.
It sounds like https://github.com/jonringer/nix-template might be helpful to you. You can generate a nix expression to build an autotools package, and you can even pull the package info straight from a public repo. In the case of nix, most C-type things fall under stdenv, so that is the template you would want to use.
I barely write any C, but I've gotten very good at building C/C++ applications over the past couple of weeks by fixing broken derivations ahead of a release.
Is Dhall worth it? I see there are Go bindings for it, but I am not sure. Is it really worth it? What is the use-case for it where TOML would not suffice?
I keep thinking about using it, but I've never used it, so I wouldn't actually know..
But, the use case is to reduce redundancy in the config file. Maybe when you have lots of configs, each with slightly different fields but the rest otherwise the same. Toml isn't really suitable for programmatically generating config like that.
As a Nix user who has recently taken some time with Guix, I envy the Guix CLI but not the language. The Guix DSL seems totally fine, but imo the Nix language is very well suited to its problem domain.
For simple configuration, you can just leave 95% of the Nix language's power on the table and it feels really simple, like it's JSON or something.
You can work your way to to all the real features at your own pace.
I've been looking into Nix a lot lately (but have yet to take the leap - I'll probably start with devshell)
But a couple of projects have come up lately that piqued my interest wrt syntax and alteratives (Since I am not sure about Scheme anymore than Nix (as a langauge) :-)
Most of Nix's complexity is intrinsic and not incidental. It's just that it makes it explicit instead of implicit like every other OS & package manager (many of which don't actually solve a lot of important problems and instead rely on the user to keep things consistent and working.)
Yes, this is definitely a complex problem to solve. Imaging we are talking about providing a pipEnv style abstraction for all the programming languages, tools and operating systems.
I’m waiting for other distros to steal ideas from nix. Guix might be a good candidate but I didn’t manage to get quickly started with it looking the docs (although they looked useful if you wanted to sit down for a couple of hours).
I've tried to learn nix and tried to read various documentation. The problem was that there was always a piece of information missing. That was until I've found the nix pills which are a pretty good and structured introduction on people interested in building packages with nix.
I'm still in the learning process, but one thing I've had a hard time is finding out what functions are available. e.g. there's stdenv.mkDerivation for a generic target, and as your docs mention pythonXY.withPackages for a python virtualenv [1]. But what if I wanted, e.g. Ruby? How do I find out what's available? What options they take?
This is less packaging related (more nix lang related) but here is my go to resource for functions: https://teu5us.github.io/nix-lib.html. teu5us extracted the builtin/lib function docs and put them on one place saving you from having it split up into multiple manuals.
One issue with nix is the content has been written down it’s very inaccessible. It is split up between blog posts, discourse, nixpkgs code comments, the wiki, Reddit, etc. When working on something in nix I’ll frequently have 10+ sources of information. The google-fu needed is strong.
My biggest recommendation is to dive into the nixpkgs repo and other public dotfiles as most likely what you are doing has been done.
Would love to see some documentation on dealing with SSL decryption for those who are in MITM corporate environments.
I've struggled with this as I recently got a new Mac for work and I tried to set it up from scratch with Nix but I couldn't even get it to connect to the nixpkgs channel. I tried every solution I could find online for pulling the CAs and specifying the NIX_SSL_CERT_FILE, but it borked even after I left the office and connected through another network (and wiping and reinstalling Nix didn't seem to fix it, but I probably didn't do that correctly either...).
Eventually I gave up and went back to homebrew and setup scripts.
You need to make sure the `https_proxy` environment variable is set correctly as well. There used to be some coverage of this in the manual, but it looks like maybe it's gone now.
Nice guide! One thing I noticed missing is how to use nix flakes (e.g. in place of niv). That is my next thing to understand, and I want to convert my NixOS / shell.nix files to use them.
From the start this looks very promising from more than one angle, including as an ux review done by an actual user:
> If someone who contributes to Nix ever actually sees these blog posts, I hope that they take them for what they are: a weird kind of user acceptance test. Not demands or complaints, just the story of one person’s experience.
I've been looking for a simple package management solution that doesn't interfere with my OS and simply puts all packages in /some_location/package/version, and that allows me to install packages on remote machines together with the other packages they depend on.
I thought Nix could be this; unfortunately it looks like it's an overengineered thing that requires that everything you do follows the Nix philosophy.
> I've been looking for a simple package management solution that doesn't interfere with my OS and simply puts all packages in /some_location/package/version, and that allows me to install packages on remote machines together with the other packages they depend on.
Almost anything that achieves this will necessarily be as "overengineered" as Nix. What you're asking as it turns out is not a simple problem at all, and a "simple" approach to it will end up rather fragile.
Not really.
Coming up with syntax to describe dependencies and code that computes the indirect dependencies of a package and rsyncs all packages (which are all exclusive directories) to a given remote host took a few hours.
I still don't understand why you need chroot and all other horrors. Just use RPATH to ensure you link to the right version of the dependencies, no magic or pseudo-containers needed.
The rpath trick you mention is how Nix actually works, but the difficulty is in convincing build routines to obey it. I'd estimate less than a quarter of the packages in nixpkgs have "well-behaved" build routines where it's just a matter of telling the build system where to look for things. Ensuring that you're using all the correct corresponding versions of libraries, headers and auxiliary files for all dependencies requires some build environment trickery, unless you want to maintain extensive patches for half of your packages.
It also means we can allow most build systems to "auto-discover" their dependencies rather than extensively coach them with explicit locations of everything (i.e. tens of configure --with-foo=... flags)
That was my original use case for Nix! Computer lab admins wouldn't install something I wanted, so I went about seeing how to install it myself.
Linuxbrew had to compile everything from source, but Nix in a proot environment worked perfectly.
If you're not going to be writing packages yourself, whatever package manager you use, you don't really have to worry too much about The Nix Way for the use case you describe
Does anyone else not use any of the ad hoc package management with Nix? I exclusively use a declarative `config.nix`, with `sudo nixos-rebuild switch` every time I want to install a package.
I extensively use nix-shell if that falls under ad-hoc package management. Together with lorri[0], I can place a `shell.nix` in my project repository and when cd'ing into the folder, I will be dropped in a shell with all project specific dependencies available to me.
This is what I do. If I need an ad hoc environment, I use `nix shell`, or I set up a flake for the project and have `direnv` activate it when I `cd` into the project directory or open the folder in VS Code.
> Okay! Wow. The script is 1338 lines long. That’s a lotta shell – I will not reproduce it here. But also: come on, Nix maintainers. Trim one line. You’re so close.
Made me laugh! :D
This material is gold by the way - I am learning NixOS and HomeManager myself, and a lot of questions I also have are addressed here. Thanks a lot!
NixOS claims to be "reproducible", "declarative" and "reliable".
Yet there is no way of "declaring" which version of given package you want to install, which might be seen as hard requirement for some build to be "reproducible". You might need to stick to some old (but tested) version when building "reliable" system.
> Yet there is no way of "declaring" which version of given package you want to install
But there is? First, by pinning nixpkgs you pin to whatever set of versions was within nixpkgs at the time. Then, if you want to change the version of a package, you can use overlays to poke at what source version is being used to build a package (or what flags it's being built with, etc). There's also nothing preventing your from mixing derivations from multiple nixpkgs pins within a single nixpkgs/nixos fixpoint for your system.
Stuff that in your shell.nix or /etc/nixos/configuration.nix or just nix-build it straight from a small .nix file.
Overlays are very hit and miss for this. It's important for non-nix people to understand that with an overlay you typically only change the version of the source of the program. Essentially think of it like downloading an older git commit. But quite often the Nix build instructions won't work with arbitrary commits. A file that's being patched in the current Nixpkgs checkout might not exist in the version of the source you check out. Then you start playing whack a mole where you override more and more of the derivation.
Using an older Nixpkgs checkout might have a higher rate of success but if Nixpkgs never included the version you need in the first place that also doesn't work.
So the mechanisms you describe are in my experience very good in theory but often lacking in practice.
Using an older Nixpkgs checkout might have a higher rate of success but if Nixpkgs never included the version you need in the first place that also doesn't work.
Yeah, but also keep in mind that uses the older version, plus older versions of all its transitive dependencies (from the same nixpkgs checkout). So, you could end up with multiple versions of glibc and other commonly-used libraries, but worse -- many known security vulnerabilities as well.
Another practical annoyance is that overriding attributes often does not work across a derivation. E.g. overriding the version attribute does not override the same version in the src attribute (which is used to download the sources) [1]. So, you may have to override the attribute in several places.
> Using an older Nixpkgs checkout might have a higher rate of success but if Nixpkgs never included the version you need in the first place that also doesn't work.
Then you could get the package from a fork of nixpkgs where it is present.
Indeed, when you depend on a package from a Nix channel, you implicitly depend always on the latest definition of that package in that channel.
When the version matters, Nix has separate packages for separate versions. There are separate Nix packages for Python 2.7, 3.7, 3.8, 3.9 or 3.10, and there's OpenJDK 8, 11 and 17, etc.
You probably don't want to depend on an overly specific version anyway. If a security fix for one of your dependencies is released, you want it. Furthermore, CI ensures that everything within a channel is maximally consistent.
You can use nix-shell to create complete runtime environments with pinned software versions. Not sure re nix flakes (it's been a while since I last used Nix) however I found nix-shell pretty good for exactly this type of stuff.
Ok so I have 0 experience with Nix however, I been eyeballing it for some time now. I like the setup of this post, but I run my personal infra completely from code (docker compose, traefic). I now run this on Ubuntu and I’ve been wondering for some time why my infra can be declarative but my OS can’t. And then I started eyeballing NixOS…
I think from my perspective it wil make more sense i.e. the first thing that OP runs into is:
“ nix-env -i git, right? Wrong. I mean, you could do that. But you actually want to say nix-env -iA nixpkgs.git. Why? Don’t worry about it.”
My Nix-noob but declarative mindset would assume the "A" is to add the install somewhere to a file needed to recreate the server at some point. Am I wrong? No idea… Actually, I already find it strand that you can call the package manager like that, shouldn't there be a declaration of the packages I want somewhere, should I not add the package that list (maybe a Yaml, like my docker-compose.yaml?) then ask Nix to make the installation consistent with the declaration?
> Actually, I already find it strand that you can call the package manager like that, shouldn't there be a declaration of the packages I want somewhere, should I not add the package that list (maybe a Yaml, like my docker-compose.yaml?) then ask Nix to make the installation consistent with the declaration?
Yes, I completely avoid 'nix-env' for that reason. It maintains a bunch of symlinks behind-the-scenes, but the 'nix-env' command itself is imperative.
If you use NixOS, the config option 'env.systemPackages' specifies which programs to install. This can be declared in the /etc/nixos/configuration.nix file. There are similar approaches when using Nix on non-NixOS systems (e.g. using the 'buildEnv' function from Nixpkgs to combine multiple programs into a single derivation/package, and install that)
The "-A" shortflag indicates that the argument given is an "attribute path".
Roughly: without the "-A", the command searches for packages named "git" and installs that. With the "-A", it will install the "git" package from nixpkgs.
Ah, guessed wrong, well I should have known, on a declarative system there should not be a way to add packages without declaring them anyway :) (I'm glad I'm wrong)
NixOS is declarative in a comprehensive way OOTB, so that there's no other way to do it
Nix the standalone package manager offers some imperative ways of doing things, plus you can declare a package that depends on all your needs. Then there are a couple of optional declarative systems that you can use with standalone Nix which add extra functionality, like configuring services in a NixOS-like way or managing your dotfiles
The name is actually referencing nix in latin, which means snow. That’s also why the logo. But even better is “nix flakes”, which just takes the name to a completely different level.
Part 41 is basically what made me realize Nix wasn't ready to use yet. In addition to a number of smaller things.
Overall, I'm still on the fence about having to rewrite all the configuration files and documentation in Nix, but having a unified setup is enticing. Maybe there's a way documentation can we prevesred and translated automatically, but it seems difficult to me.
Excellent blog series! Very good reading for people who've been using Nix for a long time, because it gives you a clear sense of things you've likely forgotten by now
That made me laugh because I understand the feeling.
Homebrew is very, very good at the things Nix is worst at.
But Nix is also excellent at the things Homebrew is worst at.
The new CLI that comes (disabled by default because it's still 'experimental') with the most recent major Nix release (2.4) goes a long way toward learning from the UX of tools like Homebrew. Hopefully changes like that will help more people get to the good parts before the UX warts turn them off.
I wanted to point something out that the series doesn't do a good job of highlighting:
You can use Nix alongside your existing package manager.
They won't conflict. You can set up dev environments with Nix without drinking the kool-aid. I still have Homebrew installed, and I still occasionally reach for it in the rare cases where Nix is missing some package I want to try. But I am sad every time I do: I never really realized how unbelievably slow Homebrew is until I tried Nix.
So if you're Nix-curious, you can try it out without committing to anything upfront. I didn't make the switch until part 19:
https://ianthehenry.com/posts/how-to-learn-nix/switching-fro...
Nix is weird and hard to learn, but it's a lot like git in that respect. Yes, the UI is terrible. You have to learn the difference between `reset --hard` and `reset --mixed` and it's weird and unintuitive but you eventually get over it.
And people are using it despite how unintuitive it is, because of how valuable it is to them. No one is arguing that `nix-env -qaP package` is a reasonable command to ask a fellow human being to type, but people are willing to type it anyway because the benefits are worth it. As a fun example, a few weeks ago I wrote up a little hack that I would not have even attempted before spending the time to learn Nix:
https://ianthehenry.com/posts/janet-game/how-to-patch-emacs/