Using Nix on macOS
checkoway.net
checkoway.net
Honestly, doing that may be easier and a better option than using Nix packages in MacOS.
Respectfully, I disagree. I’ve been using Nix on a couple of my Macs, including on an M1, and I’ve cutdown my dependence on homebrew almost to the point of its absence; I rely more on Nix packages, than on Homebrew packages.
Having said that, I still wouldn’t recommend anyone using Nix; steep learning curve, and too many rough edges.
I'd like to think there are roughly two camps of people:
Those who hear about Nix's declarative nature, with its reproducible/'pure' nature, and generational installation, all of which allow for some pretty neat UX. To this group, Nix sounds technically interesting.
The other group, those who want a tool that just works, that's simple to use, and already get their job done with other package managers. -- I think for this group, Nix is going to be a bad tool to recommend, even if they keep hearing about how neat Nix is.
Rather. Nix is wonderful 95% of the time. But the 5% of the time you run into some problem, it's much more difficult to get unstuck compared to other tools. (Other knowledge is necessary but not sufficient, the community is small so maybe harder to find a StackOverflow post, the documentation is fragmented, etc.).
I am not sure what is the story of having NixOS as a server, but would not suggest to have it as a main OS. There a sometime cases when there are simply no package you want to install, or you install it but some functionality doesn't work. Yes, maybe one can fix/patch, but I simply fall back to apt-get in such cases, and don't spend my time on that. Usually I have problems like this with GUI application, ie: installed pdf editor, which can open pdf, but can highliting functionality doesn't work and the crashes.
This was what I thought when I was learning nix. Once I used NixOS, I realised it's not quite that difficult. -- The two big differences: 1. Roughly, you only really need to care about the NixOS config about as frequently as you'd change system files in /etc/ in other Linux distributions. 2. Some programs (e.g. minikube) will download a binary automatically, and this doesn't work well with NixOS.
I've seen tools like distrobox https://github.com/89luca89/distrobox recommended as backups on NixOS, as well as the usual Docker / VMs.
I secretly suspect some of the reason NixOS is popular is it's less trouble than nix on non-NixOS. Whereas, nix on macOS, I've sometimes mixed compilers/libraries, which leads to difficult to discern problems.
I _really_ like being able to drop into a shell with a few additional packages installed. But nix does have a learning curve and some rough edges. I found it tricky to use things like libraries outside of nix's build process. And there is a bit of an impedance mismatch when trying to use languages that have their own package management.
So I've got nix for a bunch of software, a couple of libraries in homebrew, and native package management for various languages (cargo, ghcup, lake, idris).
I also reluctantly installed agda via homebrew because I can't get it to build. (Haskell mostly works on M1).
Because client IP is coarse geolocation, this unique tracking ID allows Google to see your travel history.
Sadly, it's not quite there for my needs, but it's getting better. Flakes are more fleshed out, the CLI is improving in it's user experience. I still don't feel like I understand the language works and build my flakes off of copying/pasting the one that works.
What are the advantages of that?
I use UTM (a nice wrapper around qemu), but the rest is just standard nix config, of which, nearly all of it I reuse from the configuration for the rest of my machines.
Here's my config: https://git.sr.ht/~averagechris/dotfiles
Here's a branch that I has some aarch64 specific things in it that I'm using for my guest vm config (I will merge it into the main branch when I get an hour or two so this link might die at some point) https://git.sr.ht/~averagechris/dotfiles/tree/aarch64-work-v...
Here's the link to my display manager config https://git.sr.ht/~averagechris/dotfiles/tree/aarch64-work-v...
services.xserver.videoDrivers = [ "qxl" ];
services.spice-vdagentd.enable = true; services.xserver.videoDrivers = [ "qxl" ];
Then you're only left with the spice line. I think qxl requires other configuration.NixOS is pretty great too, but there's no need to run a VM to use it. NixOS generally solves OS problems. Adding a VM just adds complexity.
* you are correct to be terrified
* you are correct to think “this is a demented amount of busywork; who in their right mind would do this to themselves?”
* you should know that this is a highly atypical setup that does a staggering number of things by hand for no discernible reason
* normal people just install https://github.com/LnL7/nix-darwin on top of standard nix and enjoy about the same lack of janitorial work as macports/homebrew users, relative to whatever the hell this guy is doing
* please don't be scared off nix by this article
most nix-darwin users i know have a darwin-configuration.nix that's nearly identical to the one the installer plops down for you, with the exception of more items under `environment.systemPackages`, and using nix-darwin solely as a declarative alternative to nix-env is totally viable
other than a few built-in service configurations and plist defaults, darwin-configuration.nix typically grows much as configuration.nix does on nixos. define or modify a couple packages here and there, shove them into `pkgs` by setting `nixpkgs.overlays`, etc etc. the ux is intentionally very similar to that of nixos
what this means is you can look at a lot of people's nixos config repos and get some idea of what you can do just as well with nix-darwin
i can, however, offer you my anecdote:
nix-darwin has let me completely forget that brew and macports exist, and even let me get away without installing xcode at all -- it's perfectly competent at “getting a suite of dev tools onto a macbook”, but what really sold me on it was just how straightforward adding a new package is:
mypkgs $ bc <<<$(cat *.nix | wc -l)/$(ls | wc -l)
32
that's an average of 32 lines to go from “obscure thing that literally nobody packages” to “bona fide part of my system”, and that includes meta blocks with homepage/description/etc, because i periodically try and get some of this stuff merged into mainline nixpkgsthe language itself is a little quirky and the evaluation model of the module system is somewhat fraught with fixed-point knot-tying fuckery, but between the process of packaging being so nice and brew/macports pissing me off, i found it easy to drink enough koolaid to get to grips with those aspects
i've been using nix-darwin and for almost exactly one year, and replaced all my linux installs with nixos, and i have not looked back whatsoever
For folks unfamiliar with Nix, this is a fairly atypical and complicated setup. It's honestly pretty smooth sailing normally.
Managing that declaratively is slightly more challenging. That’s when you need to understand the Nix language and use something like home-manager or the file approach in the blog post. But at this point, Nix is competing against something like Ansible/Puppet and not a standard package manager.
Anyway I don't think there's anything really wrong with it. There are also other options for people who are hesitant to try flakes or home-manager if they don't like this one for some reason, though. The most common one is a named package based on buildEnv in your packageOverrides or in an overlay. (There's an example of this on the unofficial NixOS wiki, in the FAQ.) And of course home-manager is usable without flakes.
(Aside: I can't imagine figuring out how to use nix just from the official documentation. Those documents are a total mismatch from what the audience needs, focusing way too much on how to write your own custom modules, and not nearly enough on actually consuming them or decent patterns for it)
[0]: people are allowed to do what they want. But the path chosen by this author is not the easy path
I agree— I really like NixOS-like module systems and how they merge together different bits of config to bring the benefits of Nix to configuration management. Being able to configure the whole OS or a big chunk of it via Nix, including running services, managing users, pre-configuring various programs, and more, from a unified interface in a simple language like Nix is awesome.
Declarative package management is great but the broader configuration/service management stuff is even better.
> Aside: I can't imagine figuring out how to use nix just from the official documentation.
That's part of what makes Ian Henry's blog series on the topic compelling! Nobody really learns it that way, and so he's putting the docs to an unusual and much-needed test. Definitely check it out :)
Another thing that I'm realizing is awesome about Nix as I'm getting my feet wet with CUE (also an interesting configuration language) is that in a way, the power of Nix makes it easier to learn than it otherwise might be.
So much of what we actually do with Nix leverages functions and libraries that are written in Nixlang, stored in the same monorepo as all of our build recipes. This means that once you get more familiar with Nix-the-language from using it in your own configs, exploring the implementations of the tools you use in building your packages and environment becomes easier and more natural. And Nixpkgs is then an awesome one-stop-shop for countless examples, and even kind of a quick reference for how a bazillion different pieces of software can be configured.
Maybe it's an acquired taste, idk. But I feel like the language is great at being simple when it can and surprisingly flexible when it needs to be. And Nixpkgs becomes a great resource for users, once they learn some of that relatively simple language.
Does anyone know if this update was a fluke?
The only things that broke for me after the update were the xcode command-line tools, which break for everyone[1].
[1](https://stackoverflow.com/questions/32893412/command-line-to...)
They bothered writing a system capable of dropping the conflicted file in Relocated Items for us to optionally use--but they appear to be only using it for /etc/bashrc, and not /etc/zshrc. So, people who use zsh by choice or default get dumped on a bit :/
Some background in https://github.com/NixOS/nix/issues/3616
On a Linux system, login shells are only invoked when you actually create a new session which doesn't come from an existing session belonging to the same user. In other words, you get the when
- you switch to a 'real' TTY and log in manually
- you log in via your GUI session manager (GDM, SDDM, etc.)
- you log in remotely, e.g., via SSH
But not when you open a new terminal emulator window. You can't just run `login` as your normal user inside a terminal emulator and get a new session either. You can check this with `finger` or `loginctl list-sessions`.On macOS, those things do get you new sessions which are shown by `finger`. I wonder whether the difference reveals a macOS quirk or a Linux quirk.
Anyone got a Linux distro configured differently that they can explain, or a *BSD they care to try and compare on? Is there any reason (security, 'correctness') to prefer one way over the other?
- don't use nix-env ever
- enable and use the new nix command (nix3)
- enable and use flakes
- use home-manager
- if on macOS, use nix-darwin
- with flakes, freely use nixpkgs unstable (stable is still useful, but flakes provide their own stability through pinned versions).
For some examples: you can manage your homebrew packages, set keyboard preferences, trackpad settings, updates, finder defaults, etc through the nix config.
https://daiderd.com/nix-darwin/manual/index.html#sec-options
Or if you don’t want to install the package permanently and just want it for a one-off job, `nix-shell -p mysql` starts a shell with mysql on your path, which will disappear as soon as you exit the shell.
"Oh, Ubuntu is too complicated"
"It's easy. 1. Don't use dpkg, ever. 2. Use the apt command. 3. Avoid Snaps. 4. Well, forget about locking dependencies, this isn't Nix. 5. No Home Manager equivalent exists, so I don't know, use Ansible? 6. If on macOS, you're out of luck. 7. Make sure to download the latest release."
"And you do this to install MySQL?"
Linux virtualization almost became a mandatory feature of a modern OS because of it.
I wish there was something that would run on any POSIX, but that’s probably not enough ground to cover complete reproduction.
My hope is that eventually, you can just run `cargo build --reproducible` or `meson build --reproducible` or `make --reproducible`, and if your architecture is the same, the dependencies will be the same and the output will run exactly the same. Even going as far as to install an older cargo or meson or CMake if that's what's needed for backwards compatibility. And if you want to be safe, you can create a sandbox or "jail" and libraries will know how to deal with it instead of just crashing when they try to access something outside.
There is a lockfile, even if it's not respected by default. Doesn't help with build.rs being able to do whatever it wants but it's better than default
You need something like Bazel for that really.
I think you were/are into something. I though about it but never managed to build it.
But I’ve never really touched Mac OS. Does Mac OS natively support this style of development?
Do you know of anyone that’s blogging about it?
Nice, that's a first step. I'll try to play with the idea
Docker also conflates too many concepts; layer generation, image distribution based on layers, registries and tags (mutable! wtf?), cgroups, PID namespaces, network namespaces, storage namespaces, etc. I'm sure it was a godsend for a certain type of workflow (one that depends heavily on the OS base; shelling out to utilities, using programming languages with poor dependency management systems, etc.) but for the average modern codebase, it seems like a detriment to me. I see people doing full builds of their app every time they want to test a change (often downloading 100s of packages from the Internet), simply because that's how Docker does things, and that honestly isn't right. They're throwing their time away for no good reason.
I’m not denying that it’s complicated, but doing declarative package management is not the only way to dip your toes into Nix. You can use it pretty much as a conventional package manager with none of the upsides of declarative package management (but none of the complexity either).
On the surface level for people migrating from existing package managers, nix-env is approximately as complicated as something like pacman. You just need the command for installing, removing and updating (well, the 2 commands for updating, but that’s the only extra complexity).
https://nixos.org/manual/nix/stable/package-management/basic...
Also, there is no “right way”. What I suggested was the way to get parity with standard package managers. There are many different ways to use it, because it is a very flexible tool. There’s no reason to learn every single one to get started with it.
This worked for me. I think MacOS installation was a bit hands on due to Mac weirdness (when I did it ~2 years ago), but I think it is better now.
Everything about first contact with Nix is off putting. I really wish it weren’t so :/
Again, I am convinced Nix is a superior way to write software, and I would love nothing more than to have a working installation in a few minutes.
If you already have a Nix based development environment, it's much less work and more reliable than patching something worse up with homebrew.
> here, paste this into your terminal for the easiest way to get up and running with Nix in a fashion that's representative of community common practices
I think it's a good blog post which, carefully read, teaches lots of useful things about Nix in a pretty concise way.
It's totally fair to point out that this doesn't represent a path of least resistance to enjoying the benefits of Nix. But I don't love the way your short comment kinda frames the blog post's job as doing something for Nix, either, you know?
I don't like the idea of this guy or anyone else feeling punished or chastised when their Nix-related blog posts become visible because those posts don't function as good marketing for Nix. Having a post about your Nix journey blow up should yield encouraging responses from fellow Nix users, right?
If the audience was Nix users, then it would be different.
It's kinda like if you bought a fancy new camera and demonstrated your process but all your photos were out of focus, framed badly and lit poorly because you're into that for some reason. Would fellow fancy new camera enthusiasts cheer? Would folks who don't know about your fancy new camera think it's a good camera?
> Files inside node_modules are cloned or hard linked from a single content-addressable storage
Also (IIRC, it's been a long while) it's lockfile contains enough information to translate it directly to a Nix derivation[1].
[0]: https://pnpm.io/ [1]: https://github.com/nix-community/pnpm2nix
(I misread their comment the same way as you did the first time :)
It's really no different from Vim in this respect. Most people will bounce off due to the learning curve, but once you get past it, the benefits are too great to go back to a more crude system. In fact it was easier to learn and setup than Vim for me.
Such as?
With every change I make, the system only gets more stable, predictable, and reliable, which is the exact opposite of every Linux distribution I've ever user before, which had to be wiped and reinstalled every couple years, after which I'd have endless struggle sessions getting everything set up. I'll never go back.
(Not a bad thing, just be aware that Nix is for when you need DIY development environment infrastructure and don't have the budget to keep a team of seven k8s specialists for the job.)
The main problem I have is when I try to install a package that fails to install, usually it has to compile. Like today I tried watchexec on my M1, doesn't work. Luckily I can just download a binary watchexec build to get around it but it would be nice to know how to get it working. Worked with homebrew. (but homebrew has it's own problems)
The other thing is that I like the idea of using nix-shell for projects, but I hoped they would be more isolated than they appear to be. It's possible for example to have files in a user directory which will be accessible to all projects and package versions I'm using. It hasn't become a problem yet in my testing so far though.
Reading other comments I decided I will also play with running things in a VM with NixOS. Maybe I'll end up with a mix of local Nix for some basic stuff and then a development VM.
I'm coming from homebrew + asdf, but so far Nix appears to be working fine for me. I think asdf has a lot of custom config to try and isolate version-specific shared files/modules etc. I can replicate it by setting some environment variables myself in nix shell file though. I've got my basic home manager setup (still need to migrate some manually managed files to nix config) and every project I work on is now running with their own shell.nix file. No huge problems yet, aside from the mentioned watchexec failing.
Not yet sure if I'll keep it in my regular workflow, it's been an interesting experience and I would be happy to not need homebrew anymore. (Might just try ports too). I'm also curious to see how fast new versions of software will be added/supported, so I'll have to at least keep this running until that happens.
While source builds aren't completely avoidable, you can alleviate much of the pain with a combination of declarative package management and dependency locking. It's what long term Nix users most likely end up using:
* nix-darwin for managing system-wide configuration
* Home Manager for managing user-level configuration
* Nix Flakes for locking dependencies
Once you have a working config, the same config would run anywhere, anytime. You can then use GitHub Actions to automatically update dependencies and check if they all build before merging. Also as a last resort, you can always revert to a previous config if something goes wrong.
Using steam-run, nix-autobahn or using buildFHSUserEnv yourself.
Using flakes and using it for project dependencies though is amazing and quite easy to use imo.
We decided to use it at my job for a new project and it's been pretty amazing https://link.medium.com/DwIGVmRZ6rb
Then again, I don't like much about macs except the touchpad and macOS annoys me.
So this advice might not hold as true if you actually like OSX. Maybe checkout:
https://github.com/LnL7/nix-darwin
I'd also advice using flakes to simplify a lot of this.
Not trying to convince you to try again since you seem done, but want any prospective nix users to know which approach you found painful.
And if you don't mind, a list of the most painful things that should be improved.