Building third party flakes takes forever since every flake uses its own version of nixpkgs. If you don't pin your third party flake urls they might also change under your nose as you run the same command again a day later.
Flakes are coupled to git. You need to remember to stage changes whenever you do Ctrl+S in your editor before rebuilding. I've wasted more time than I'd like to admit wondering why what I'm building doesn't include my latest change.
Flakes copy the entire directory into the nix store. This is terrible for mono-repos - and especially if it contains any large files. There is an issue about making the copying of the entire directory into /nix/store lazy - though this doesn't really address the problem. It just treats some common symptoms.
This kind of copying would likely be a lot more acceptable if it was specified explicitly in flake.nix, rather than implicitly. Then you could also use your own filters for ignoring files, rather than relying on the coupling to git and its staging area.
This is good constructive criticism and I'd like to second every part of it.
You're probably already aware, but for the benefit of newcomers in this thread, here's a link to the massive PR trying to work out more efficient copying of local flakes to the Nix store:
>You need to remember to stage changes whenever you do Ctrl+S in your editor before rebuilding
This is decidely not quite true. You must have the file visible to Git. Flakes still just uses the files, as long as they're tracked by git. As long as you have no new files that aren't in the index, staging unstaged changes will not change eval.
That said, yes, when you add a new file to a flakes repo, you start to develop a habit of always adding it to the stage/index for eval.
but you should ONLY ever see this as a very very obvious "file not found", it is not a subtle problem as this post implies.
> Building third party flakes takes forever since every flake uses its own version of nixpkgs.
The “official” (as in, community consensus) solution seems to be to bring your own nixpkgs, and manually override the nixpkgs of every dependency (and their transitive dendencies) and verify your build still works. Which just doesn’t seem right to me.
Flakes are great for building an ecosystem of composable, reproducable software. The more they succeed at that, the bigger the problem becomes. Surely it’s not too late to figure out a principled solution before stabilizing flakes?
I think the current solution is not too far from an ideal scenario: package the most commonly used dependencies/programs in nixpks (roughly what would be available with other package managers’ default channel/repository), and use flakes as an out-of-tree solution for proprietary/freemium/hard-to-package/very specialist software, similarly to what you might use Docker for.
That way you get the benefit of a minimal-sized system with no size overhead for the most part, yet out-of-tree git repos get reproducible at any commit, and it is even easier than adding a new repo to apt, etc.
With content-addressable hashing, the problem may largely solve itself, reusing unchanged dependencies between older flakes.
The traditional way is to reduce the surface area of the core package as much as possible, such that it sees less changes/releases overall.
The way I would do it with nix is: because everything gets hashed, just check that the built output with a new nix-pkg version matches the hash with the old version and fail out/fetch the older version as a second step. The rest is just finding ways to cache that build fail information so that you can share the result across users transparently.
There is work on content-based hashing, but that is not only related to flakes. So that problem may get solved, and is likely the correct path forward.
This depends, Hyprland has their own flake, and rather than overriding nixpkgs they recommend adding their cachix binary cache. You get binaries for Hyprland from Cachix and for it's dependencies from cache.nixos.org.
Works well for me. Though when doing configuration changes I usually pass --no-substitutes (or smth) to not query all my subs for derivations that'll never be in a remote cache.
> Building third party flakes takes forever since every flake uses its own version of nixpkgs.
That's not quite right. It may use a predefined version of nixpkgs and there may be a reason the version is hardcoded to something. But if that's not what you want, you can use something like `nix run ... --override-input nixpkgs nixpkgs` and it will run with your current system nixpkgs version instead.
> Flakes are coupled to git. You need to remember to stage changes whenever you do Ctrl+S in your editor before rebuilding. I've wasted more time than I'd like to admit wondering why what I'm building doesn't include my latest change.
There's an upside to this: I've been in situations where I've lost the definition of a previous configuration because I didn't check the state of it at that point into source control. By "forcing" the user (me) to at least add the current state to source control (if not commit it), it makes it more likely for me to have the configuration/definition for the state saved at the same time as the state itself.
If you don't lose the whole repo, you can probably pull those versions of of the git reflog even if you do lose them. One of the blessings of having `git add`ed something.
FYI, if you want Flakes to not be tied to Git, I'd recommend using `nix [...] path://$PWD` or something along those lines. This will bypass the VCS detection for you.
Given that the Git thing is meant to stop you from shooting yourself in the foot, I think maybe it's time to conclude it wasn't really that great of an idea. However, I still see why it works that way.
This makes the third issue of the parent comment much worse, unfortunately since there will be a new /nix/store hash when even things in .gitignore or things like lock files or editor backup files are touched. I've cleaned up hundreds of gigs after a long evening of hacking
I used to be annoyed by how Flakes are coupled to Git, but I've realized that dealing with that is way less pain than dealing with builds that accidentally depend on non-version-controlled files. Missing an unstaged file is annoying, but it gives you an explicit error message and it's easy to fix; accidentally depending on a wrong file can skate by silently (perhaps leading to extra rebuilds but nothing more) until you try to reproduce the build somewhere else, and then it's at least a small headache to debug and fix.
Yes, you are right - I misremembered this detail. My problem at the the time was I didn't want to commit my flake.nix to the repository in one of my previous work places (for political reasons). So I had to unstage and restage it every time I created a new commit.
Even better, you can `git add -N` and just record the intent to include the file in a later commit, without staging its current contents. Nix seems happy with that.
> Flakes copy the entire directory into the nix store. This is terrible for mono-repos - and especially if it contains any large files. There is an issue about making the copying of the entire directory into /nix/store lazy - though this doesn't really address the problem. It just treats some common symptoms.
Could you not just do a sparse checkout for monorepos?
My use case here is not using pkgs.fetchgit etc - but rather when developing a package locally and rebuilding it.
Let's say I'm working on a huge monorepo locally, with GBs of code and data in it, most of which I want to ignore in my nix build. Let's say the files I actually care about are also not in a single subfolder. Then I can't just move the flake.nix to that subfolder either.
Oh yeah in that case it'd be a problem. There might be a way around that but that case definitely isn't ideal. albeit you could probably sparse-checkout your repo to avoid that if you don't need all of it.
definitely not ideal and I agree that until lazy file mapping, content addressed derivations, and file deduplication get implemented that the UX will be rough in some cases.
> Building third party flakes takes forever since every flake uses its own version of nixpkgs. If you don't pin your third party flake urls they might also change under your nose as you run the same command again a day later.
then what's the point of using nix and flakes if flakes destroy the very point of nix, reproducibility?
Ive always loved the idea of nix, but feel like I've read numerous, if not horror, at least uncomfortable stories about the actual real-world experience after the initial "setup yak shaving" is done - which is often exciting for "us", it's the new project problem solving part before it falls into the boring "work" part.
If I have an arch system now, how useful is it to use Nix or Homemanager on a non-nixos linux system? I dont really want to dump a working system and duel booting always has whatever you need on the other system.
Do you get anything when not using NixOS to manage everything? What good is it if half my system is installed by pacman, half by asdf-per-project and the rest by nix? Has anyone gone down this route? What is the actual lived experience of half-assing it?
It can get you two major things. Docker-like reproducibility for any development project in a much more convenient way. And the ability to try lots of software without installing it.
For me, the last one is a gamechanger, as I am no longer worried about littering my system with tons of dependencies. Say I want to convert an eBook I downloaded. I can quickly use Calibre for a one-off thing, with nix run nixpkgs#calibre.
I'm new to nix/nixos but gradually building up my environment.
it's like having your whole OS in git. it's amazing. want to try out some nightly build? no problem.
on most computers (personal, home computers) the various lib dirs get scary after a while. repoquery can help, but is kind of a hassle. if some executable `foo` depends on some specific behavior in some version of some library, it's fine. that weird library can stay in place, I can try out nightly's of foo, can always rollback to the system that used to work, and can flip to the new foo when it's ready.
I think it's a good practice to wipe and re provision from time to time to make sure provisioning and backups actually work, but like, you can screw around with _crazy_ things and not really have to worry about having to rebuild the whole thing. (well, I haven't yet) I still will, because that's how I am. but I can do it when I feel like it, not when I fucked up. it's so easy to un fuck a nix system.
I guess the big caveat is, this is a hobby. I haven't used nix for work. Back in the day, I did support docker in production when the kernel patches were coming pretty quickly. Finding the right balance of patch level, and libc version, that would support docker, and the other stuff that needed to run was a pretty complicated dance, and missing a step would be, not great. Knowing what I know now, even as a hobbyist, I probably could have made my life a lot easier back then.
Exactly, I have been a huge distro hopper to the point that having the same install for a month was already at the high end (though I did keep my home partition).
Now I have 2 years old NixOS installs on personal machines and they do not get bloated with packages that the package manager can no longer handle, and is basically always at a state as if it were freshly installed. It just “feels right”. To me, that makes the occasional edge cases worthwhile to suffer through (some binary package, mostly) - especially that in most cases something like steam-run is enough to make it work. When it isn’t, systemd-nspawn can boot you into any systemd distro you would want.
I get Docker-actual reproducibility with Fedora Silverblue and toolboxes. Enter one of my Arch/Fedora containers, install Calibre without affecting the host. Even better than Nix because I can test custom distributions, rather than each environment simply being another NixOS.
In fact, I've departed from vanilla Silverblue, as now my base image is an actual, bona-fide Docker container as well.
I feel like the immutable Linux OS is the pragmatic approach, whereas NixOS is the pure, ideal way that requires a lot of changes to tools and workflow to work. Maybe even in this case, worse is better.
Yeah, Silverblue is pretty great. But Nix and Silverblue both require changes to your workflow. I like Nix more, but I don’t think one is objectively better.
I also really like flakes. I know they are still experimental today - though hopefully that'll improve with this RFC - but they make it trivial to have an out of tree package. For example I just recently created a flake for a vendor OpenOCD fork [0] - and now I can reference that in my home-manager config or from some other project.
This is already solved by Docker. I know Docker has a bunch of issues and Nix is clearly a more elegant design, but in practice Docker works fine (at least for my use case).
It's really not. Docker is a tool for binary distribution. Docker images are those binaries. Dockerfiles used to create Docker images don't have any mechanism to ensure reproducibility whatsoever. Unlike Nix, you can't take a Dockerfile and expect builds to succeed.
Furthermore, Docker images are monoliths that's isolated from the system. Instead of system administrators choosing the isolation boundaries that best fits their requirements, the image packagers put walls around each and every image. As a result, Docker containers are inflexible compared to traditional Unix applications. Piecing together multiple Docker containers is a clunky experience.
In contrast, Nix is an integrated build/configuration/deployment system. Entire systems down to the package level can be reproduced from Nix expressions.
It also gives system administrators power over the whole process. Administrators have control over things like how each components are pieced together, and where isolation boundaries are placed. They can even make tweaks to the package build steps.
Docker can't substitute Nix. It's not a matter of elegance. Their features and capabilities are wildly different.
I don’t know the value of half-assing it, but committing your full ass is amazing. Don’t abandon a working system, but the next time you wait a whole three weeks to pacman -syu and your GPG keys are out of date and everything goes to hell… give it a shot.
Honestly, it’s Home Manager that really adds the maximum value, and getting all the way there takes a full weekend, but what were you gonna do anyway?
> Honestly, it’s Home Manager that really adds the maximum value
I feel like Nix does have such killer features, but they are different for everyone.
For me it was:
- system management (nixos + nix-darwin. I wish there was something like nix-darwin for non-nixos linux distros, binding daemon systemd units and desktop files into the "hosting" distro)
- on-the-spot running without globally installing for one shot tasks (nix-shell -p iotop --run iotop)
- "just works" project environment (default.nix+shell.nix or flakes)
These are the ones that made me tip over and decide to go from tiptoeing to full tilt
Yeah, nix-darwin is incredible. Use cases you mentioned are great; for me, I love being able to use my NixOS machine and MacBook to seamlessly carry around the same dev environment.
Another benefit is that "traditional" package managers may litter your system with configuration files and post-install scripts (for the software you are installing and all of its dependencies), some of which can persist even after uninstalling the packages.
One less thing to manage and think about, including cleaning up after myself. It may pull dependencies that I don't care about or want exposed e.g that would be picked up by some other thing as with traditional package managers (e.g a configure script would pick installed stuff). apt-get autoremove --purge or pacman -Rsc become a distant memory.
It's fire and forget and I can just focus on what I'm set to do.
Once I'm done with the one shot task, it disappears and could be garbage collected for all I care.
Some tools I did promote to being part of my user env but crossing that bar is a very deliberate thing, some are promoted to systemwide (root) and the bar for that is even higher.
I use home-manager on Ubuntu on my work machine. You have to pay the full learning curve of Nix. Once you do, it works just fine. I think there comes a natural pressure to use Nix for as much as possible and slowly cut down one's dependency on the "base" system when you go this route. Maybe that's just because I want to see my investment in Nix pay off.
I would say that the biggest benefit you get is the hugeness and currentness of nixpkgs and the fact that it becomes a lot less important what software you have "installed".
It's fine, just be sure you know where your tools are coming from (use the which command a lot when unsure). Nix might have more up to date or bleeding edge software, although since you're on arch in my experience nix can lag even arch by a little bit.
Fully reproducible environments with home manager and nixos are neat but IMHO you can just use ansible to do the same thing on debian, arch, etc. if those systems have the packages you need.
When you inevitably find software that isn't in nix (or are packaging your own software), be prepared to take a quantum leap in complexity as you now need to fully understand the nix language and its concepts like derivations. This isn't necessarily hard but it is not documented well at all, and there are factions in nix at odds with each other (flakes vs. nix-env) which make learning it even more confusing.
> When you inevitably find software that isn't in nix (or are packaging your own software), be prepared to take a quantum leap in complexity as you now need to fully understand the nix language and its concepts like derivations. This isn't necessarily hard but it is not documented well at all, and there are factions in nix at odds with each other (flakes vs. nix-env) which make learning it even more confusing.
Exactly this was why I am so hesitant to switch to nix. I tried to dig into the details of nix, language, derivation and whatnot, but documentations and community discussions are, in my experience pretty segregated that left me confused, and I eventually went back to arch.
In 90% of the cases it is as easy as modifying the earlier version’s version and hash. I think learning nix from outside-in is perhaps easier - grep for something you are looking for, and as if it were a language and you are a small kid, imitate that.
Though I will give you that there is enough complexity in specifying which nixpkgs/flake gets built, where is it places, etc as is, especially with the `nix-\w+` vs `nix \w+` variants being slightly different, to the point that I always have to look it up in the man page/in my history whether I need -A and the like.
fwiw nixpkgs has significantly more packages than arch (including the aur), and those packages are also significantly more up to date. No other repo comes close to nixpkgs in this regard. This has been the case for quite some years now.
Repology already attempts to account for that, and Nixpkgs normal policy is one version per package unless there are specific reasons for it to be otherwise. Nixpkgs doesn't duplicate packages just to have alternative build options or whatever like the AUR does.
Sorry to be blunt but I've seen nearly exact comments as yours and they come off as someone who hasn't really used Nix and doesn't understand the value proposition and the problems it solves.
I've used Ansible for years, then moved to Nix and have been on it for a year and a half. Yes the configuration language is more complex than Ansible's but it's also way more consistent and predictable. The bit of complexity comes with a lot of additional benefit. Ansible half-asses it, only giving you idempotency if you stay within certain boundaries in how you write configs. And a leaky system is a system that will break. Making it even worse is that you are building on top of a moving target with a distribution underneath that will break your Ansible scripts regularly as the system changes. Ansible is a huge mess and not suitable for the job IMHO.
With NixOS, the entire system is controlled by config, so there is only one source of truth for the state of the system, unlike Ansible. This is a fundamental flaw. Ansible is a hack on top of pre-existing setups.
With Nix, my system only gets more stable with time. It's the opposite of anything I've ever used, where systems get crufty and have to be reinstalled every couple years. Since the state of the system is fully determined by your config, you can always get to an exact state without a bunch of extra shit missing or added.
And the language isn't really that hard for anyone who's done a bit of programming. It's certainly easier than most general purpose languages, as it's static data 90% of the time with a bit of logic thrown in when needed.
> It's fine, just be sure you know where your tools are coming from (use the which command a lot when unsure). Nix might have more up to date or bleeding edge software, although since you're on arch in my experience nix can lag even arch by a little bit.
That'll depend if you're on stable or not. If you're on stable and you need something from unstable that's also possible without any real risk of breakage on NixOS.
Also, once you've learned the ins and outs of Nix (which TBH I didn't find as hard as others, there's tons of examples) it's usually pretty simple to update software yourself--relatively risk-free. For example, I've been keeping Minecraft on the cutting edge for my kid by occasionally updating a URL and hash. A lot of the modules provide a 'package' option to make that easier.
Yep, a lot of the time it’s as simple as overriding the src and version of a given package -though if the package has patches to build on Nix it can be more work.
> When you inevitably find software that isn't in nix (or are packaging your own software), be prepared to take a quantum leap in complexity
I think this is where most of the "i went back" posts I read came from. That and hitting issues with programs that expect to be able to write to some XDG dirs.
> Do you get anything when not using NixOS to manage everything?
Sure, I think the biggest benefit is being able to get a temporary environment for a project. You can have all of your dependencies pinned, even for languages that don't have package managers, and for mixed-language projects. You can get easily get a shell that contains the exact compiler versions, libraries, etc. from a single config file, and it's isolated from the rest of the system. I guess it's kind of like having a lighter-weight container.
It's no lighter than a process running in docker, on a Linux machine at least. With docker you have a whole root filesystem packaged up and a process inside it is executed on your system with certain kernel namespacing to set its root filesystem, users, network access, limits on memory and CPU usage, etc.
With nix instead of a tarball being the root filesystem it's a bunch of symlinks to stuff in the nix store directory--the process you run is exactly the same as whatever you're running in docker.
One crucial difference is that nix does nothing for network isolation, you have to do all that on your own (if you need it).
My thoughts exactly. Container-based development environments has a Cygwin-like clunkiness to it. But even clunkier because of the default lack of access to the host system, and the additional burden of having to manage multiple containers.
Just to be clear, Cygwin is a great project. But it's not something I'd actively choose over a native Linux system if I had the choice of operating systems.
You don't have to use them, docker has flags to disable things like network isolation. If you want to go deeper systemd-nspawn doesn't isolate anything (network, pid, user, etc.). And if you are some anti-systemd zealot the plain old chroot command does what you want too (and has done so for decades).
Except none of those solutions are package managers, are they? The thing that's nice about nix is that you can just specify which packages you want by name, and easily get them in your path.
It’s a lot lighter in terms of disk space. Yes, drives are cheap, but even so, bringing in a different version of debian-slim for every executable gets bloaty. I routinely reclaim 10s (sometimes 100s) of gigs with a podman system reset.
No a process running in docker or on your host is going to use the same amount of RAM. There is no RAM dedicated to a running container on Linux--it's just a process that's flagged with some metadata to tell the kernel that it should be isolated in certain ways, like with a unique root filesystem.
Loading in the whole container though does increase the necessary RAM — with nix, two versions of the same executable can link to the same hash, but it is unlikely to be the case with Docker.
Your kernel is fine at managing the container root filesystem and paging in and out parts as necessary. It's not just loading gigabytes of root fs into memory and calling it good.
I am forced to run both, work needs Intune which needs Ubuntu (I'd use NixOS everywhere if I could). Here is my config, but be warned it'll probably confuse a newcomer: http://codeberg.org/jcdickinson/nix
My config/flake is cleaved in two: one for NixOS (which isn't used for Ubuntu) and one for "Generic Linux" (which is used everywhere). I used to have nix-darwin in there too, but Intune on Ubuntu has allowed me to retire the work Mac.
The second-half is where the real value lies (my NixOS config is actually really minimal, just enough to get into sway). I use home-manager to manage all my dotfiles. I switched work laptops recently and nix+home-manager brought up the environment in less time than it took to install Ubuntu - and that's a full desktop replica (Gnome plugins, hotkeys, installed apps, nvim config, and everything).
The next big benefit is direnv integration. Direnv itself is bloody fantastic, but add nix to the mix and you have a whole new level of magic. If there is an in-tree flake I can just echo `use flake` to establish a dev environment with all dependencies, at the right version, through the mere act of cd'ing into that dir. If there's no in-tree flake (as is the case with my work repos), I can use one of my dev-shells with e.g. `use flake $HOME/Nix#cmg-js` (assuming I've cloned my config to ~/Nix).
There's no real reason for me to use NixOS on my own machine, but I do love the boot speed and the ability to roll back. I'm pretty fearless when changing my OS config. The nature of Nix means very little beyond what you explicitly demand is installed, and it keeps snapshots of your previous configs. It's not mandatory at all, though. Home-manager is where it shines.
> Do you get anything when not using NixOS to manage everything? [...] Has anyone gone down this route?
Yeah, for sure! I don't use Nix this way very much on Linux because I mostly just use NixOS. But I use Nix this way on macOS at work every day, because that's the Unix desktop that's available to engineers there.
By not going full NixOS, the tradeoff is that you suffer some minor integration issues, and in return you get some more escape hatches. This is a pretty good option for some people imo.
Declarative system config on non-NixOS is a bit more work, because you either have to write your own sort of metapackages with buildEnv¹ or use a third-party module system like Home Manager, System Manager (that one's in very early stages, so pronably skip it if you're a newbie), or Nix-Darwin. The latter are really nice, but you might have to think about how they plug into things like your OS's bashrc file sometimes, and sometimes their install procedures are kinda wonky.
The other main integration quirk to watch out for on non-NixOS is 3D graphics acceleration. Check out nixGL and you'll be covered for that.
Using Nix for nifty per-project development environments, though, is pretty smooth and basically identical whether you're on NixOS or not. If that's an interesting use case for you, Nix on non-NixOS is worth checking out.
Nix as a package manager for CLI tools that don't depend on the base system, or trying out software without permanently installing it, is also kinda nice on other distros. It's especially nice for running newer software on top of stale distros, but it can also take you in the other direction, which might sometimes be useful on Arch.
I think the head first approach of just committing to daily driving NixOS can be good for some people, and it certainly was for me. But learning your way around the Nix language and developer tools by focusing on developer environments and oddball packages on a foreign OS can definitely make for an easier, lower stakes learning process.
> What good is it if half my system is installed by pacman, half by asdf-per-project and the rest by nix?
If you're not using Nix for any per-project stuff, you're definitely missing some value, as that's likely among the first low-hanging fruit you'll encounter on your Nix journey.
That said, stacking Nix with other package managers and only using it where it makes most sense is totally viable. On macOS, I use it in combination with light use of pkgsrc and Homebrew. You can definitely do the same kind of thing on Linux.
I'm running home-manager on arch and it's fantastic. I'm only using it for cli/tui programs, as I've had trouble getting gui software to correctly create desktop entries which show up in my menus. You can use it alongside pacman just fine.
In the worst case scenario, you can just manually create files in your home directory if needed, so putting them under .local/share something should get you desktop entries (though depending on the desktop/window manager you may need a restart).
It depends on what you're hoping to get out of it. I mostly-whole-ass it, but I still use the mac app store and homebrew for a few things. Most projects are Nix by this point.
It's hard to tell from how you say it; if you aren't using it for any projects and would just be using it for a slice of your system/user packages, I suspect you'll end up not really seeing what the fuss is about. If you will try to use it with some projects, I'd start there and see how it goes.
(It should be fairly low stakes. If it doesn't stick, you won't disrupt yourself that much. If it does stick, you'll have a better sense of what you want to hand over to it and why.)
How do you personally use Nix on a project, any tips? Do you use flakes? What are first steps/basic scaffolding? I am eager to get into Nix but not ready to go full on (I'm also on Mac but some devs may be on Linux)
Is it possible with complex projects like based on Electron? Is it reasonable to use Nix in Docker (eg. I am on Mac but want to build it like it's on CI)?
> How do you use Nix on a project, any tips? What are first steps/basic scaffolding? I am eager to get into Nix but not ready to go full on (I'm also on Mac but some devs may be on Linux)
Not sure I can boil it down to tips, but: more or less any time I need to do something regularly that involves third-party code, I'll be using Nix to manage it. Specifics depends on the project. There are templates around (and templating is built into flakes via `nix flake init`), but I haven't used those much myself.
Maybe a sense of general patterns helps?
Most of my projects have at least a shell.nix (devShell expression in flake.nix) for setting up an environment to work on the project. I.e., add appropriate deps to path, define some utility shell functions, start up database servers and so on.
Sometimes that's all. For example, my blog just has a shell.nix for providing dependencies like hugo, gist, make, jq, etc., defining some helper functions for scaffolding new posts and such, and then I use Makefile targets for creating a dev build, production build, and publishing.
If it's something others might use, I'll generally have a default.nix/flake expression for building the package. Then I can use that for testing it, for integrating it in other projects or my own systems or whatever.
I'll often have one or more expressions for ~testing it. (If I have more than one, the first might be a straight test, and the 2nd might be a performance suite comparing it against similar tools, for example.)
If I'm researching several potential alternatives, I may build a Nix expression that builds all of them, pulls them all into scope, and then invokes them all to compare whatever I care about. Then I can readily repeat the same check locally, or go run it a bunch in CI.
If it's something I have CI set up for, I may bother to have a ~normal build that runs against pinned dependency versions whenever I make code changes, and then also set up a ~canary build that regularly re-runs my project's main/master against the latest nixpkgs so that I get some notice if something I depend on happens to be broken.
> Is it possible with complex projects like based on Electron?
I'm not familiar with the Electron packaging, sorry. I know it's doable because we've got a number of electron packages, but I don't have perspective on how easy it is and whether it's working on Linux and macOS or just the former.
> Is it reasonable to use Nix in Docker (eg. I am on Mac but want to build it like it's on CI)?
Sure. There's an official Nix container image, and some of our gitlab CI jobs use it. IIRC it's a little tricky to install Nix in a container imperatively, but I think the state of that has improved since the last time I needed to fiddle with our setup.
> If I have an arch system now, how useful is it to use Nix or Homemanager on a non-nixos linux system? I dont really want to dump a working system and duel booting always has whatever you need on the other system.
100%, I recommend people to start with home-manager before NixOS as it's easier to escape the Nix when you're out of depth than if you're on NixOS. It'll manage your user systemd units and everything else within your user, it's great.
My biggest problem with flakes is that it is too much added complexity for tiny incremental gains (as per my limited understanding, happy to be corrected). Not only do most users gain very, very little from it, it also deters users from using nix for two reasons:
1) There is more to learn now.
2) Split ecosystem.
I'm looking to be educated, I've made contributions to nixpkgs (two "mid-sized" changes) but for some reason I couldn't bring myself to learn flakes ... Although that could have been because they were in limbo.
I have to say though, nix is increasingly becoming a nerd thing philosophizing over minute issues rather than "getting shit done" to benefit the maximum number of users ... :-(
> Not only do most users gain very, very little from it
How do you come to that conclusion?
Those who switch to using flakes are enthusiastic about the improved UX.
> flakes is that it is too much added complexity for tiny incremental gains
A 'flake' is more/less a set of inputs and a set of outputs. I'd say it's less complicated than a package.json file in an NPM project.
The benefits are hard to get otherwise.
With flakes, `flake.nix` provides a standard entrypoint to a Nix codebase. Without flakes, you might see a `default.nix`, but would have to read the `default.nix` to know how it's supposed to be called.
With flakes, the exact version of Nixpkgs used is locked. Without flakes, I'm not aware of an easy way to do this with channels; and there are a variety of ways (read: no standard way) to do this in Nix code.
- flake-specific state is fully captured and locked
- this locking applies for all platforms the flake targets
- extreme ability to be composed
The first two solve the same issue as Gemfile.lock, its the PLATFORMS section, and the platform annotations on each of its gem line, which allows `bundle lock` to lock not just for the platform it's being run on but all platforms that are targeted.
It also canonicalizes the way to declare targets to build, whereas previously it was kind of TIMTOWTDI (e.g default.nix evaluation is the default target and calling nix-build sans arguments builds that to `result`, and if you want more you write alternative nix files, the whole organisation of that is on you)
These are very useful for project-oriented nix stuff.
For system (nixos, nix-darwin)/environment/profile/home management I still prefer classic channels, which gives me a single, consistent nixpkgs source, kind of like BSD's base which is handled as a whole (except here it applies to the whole of packages). I am still able to locally override this or that by selectively pulling another nixpkgs (or other source) and use that to pick a specific package version (either forward or backward) but otherwise I stick to the single consistent one.
It feels to me that using flakes for the whole system would be like using npm and having a whole recursive tree of `node_modules`. I certainly don't want to have a thousand different openssl around!
> A 'flake' is more/less a set of inputs and a set of outputs. I'd say it's less complicated than a package.json file in an NPM project.
It's conceptually comparably complicated, but the actual practical experience of writing flakes is much more complicated. This is not the fault of flakes specifically, but rather due to the complexity of nixpkgs. Although on second thoughts the fact that there are a bunch of libraries like flake-utils and flake-parts out there does seem to point at a verbosity UX issue.
I think we all have our own aha moments with things like this. I thought like you until I really dug in and set up Home Manager as well. My moment, and maybe this means nothing to you, was when I realized I could reference any package in a config file without even “installing” it. So it’s no longer that I have config files in Git somewhere, and then also a list of all the packages I need to install somewhere else; the config files themselves pull in the packages they need by virtue of referencing them. There are a million other things, but that’s when I was like, “Okay, I’m actually gonna do this.”
Yes, in Nix code it is possible to refer to arbitrary Nix codebases from Nix code.
I'd point to the home-manager installation instructions for an example of Nix flakes having a nicer UX. Running flake-enabled codebases is just much nicer than non-flake codebases.
The former involves running `nix-channel --add <...> home-manager && nix-channel --update` in order for `<home-manager>` to mean anything. With the latter, it's simply `nix run home-manager/release-23.05 -- init --switch`. (Albeit, `home-manager` is already registered as an alias for `github:nix-community/home-manager`).
One key detail is that `nix-channel --add` modifies the 'system state', whereas running flakes essentially does not.
-- Regarding "you can pull in arbitrary Nix code by reference". With flakes, you have a standard entry point where you know the interface it has. Whereas, having a 'default.nix' is a convention, and there's no way to know how a `default.nix` is to be used without reading its source.
I'm familiar with home manager (or as I like to call it, a hammer looking for a nail, that solves no problem). I don't think home manager has any relationship with flakes. Also, nix solves actual real problems, home manager doesn't. There are better dotfile managers. In fact, vim understands the syntaxes of a lot of dotfiles, with home manager, you even lose that.
> In fact, vim understands the syntaxes of a lot of dotfiles, with home manager, you even lose that.
Nix is perfectly capable of referencing external text files (e.g. `./my-config-file.ini`), which you can write with vim or whatever if you like.
It's trivial to put such files in place with Home Manager (or NixOS config) if you want, e.g.
home.file.foo.source = ./my-config-file.ini;
Home Manager is certainly overkill if that's all you're using it for; but many more things become possible thanks to its use of Nix. For example, you can run some find/replace on the file contents (say, to splice in some Nix store paths, or the results of some calculation); you can fetch arbitrary files from arbitrary locations (e.g. some other git repo); you can choose between alternative contents based on arbitrary criteria (say, CPU type, or hostname); etc.
There are Nix LSP servers now that handle embedded config files. But beyond that, you can always just leave the config in its original format and import it into the Nix config, and not lose your syntax highlighting.
Speaking of vim, I've got neovim configured completely with home manager. It references plugins as first-class nix packages, and also any external dependencies like language servers, node packages, parsing tools etc are also managed by Nix. You can reference the deps in the vim config and it will automatically download and point to them in the nix store without even installing them.
It's amazing. Everytime I upgrade and building my system, my nvim setup gets upgraded automatically too. No need for a package manager or manual updates.
Which you can presumably only do on a 1 user system right? (I’m just trying to understand, I thought home manager makes more sense on a multi user system, and has some options for more fine grained configuration?
Home Manager is less useful if you're using NixOS. I've found it handy on non-NixOS systems, e.g. my phone; although I'm planning to switch that to NixOS at some point too ;)
Can you tell me which one of the nix lsp servers supports the embedded configuration in multiline strings? I think neither rnix-lsp, nil or nixd support this, but maybe I am missing something.
I moved from Chezmoi to Home Manager. Chezmoi is easily the best dotfile manager I had used at the time, and Home Manager is on a totally different level.
> vim understands the syntaxes of a lot of dotfiles, with home manager, you even lose that.
I wonder what we can do about this, or what is the best way to annotate long strings in Nix code that are actually source snippets. Something like how code snippets are handled in Org files would be awesome.
As a counter-anecdote, as someone who used to be a newcomer to Nix, it took until I encountered flakes before I went "aha, this is how it was always meant to be".
Do you have much development experience? I've been wondering lately whether the helpfulness or difficulty associated with flakes depends on familiarity with Nixlang and readiness to approach Nix code as code.
That fits with my hypothesis, which is that programmers tend to find that the way Nix flakes lay out a common interface and convention for certain things helpful, but people who are more IT-oriented and are used to relatively incapable conflangs are overwhelmed by the surface level verbosity of flakes, and hesitant to use libraries to deal with it because they take a bit longer getting their heads around the language.
FWIW I like Nixlang, but I agree that static typing would improve it. Maybe Nickel some day, blah blah blah :)
You can do everything without flakes as well by using fetchTarball, fetchGit etc, with shasums, but flakes just improves the ergonomics. Because of the lock files, flakes are also faster, especially nice if you use nix develop (the new nix-shell alt)
> Because of the lock files, flakes are also faster
I consider lock files to be labour-intensive work-arounds for fundamental design problems. One of the things I like about Nix is that its design doesn't need them, and even allows me to automate-away their need in other tools (e.g. defining a project's "main" derivations using import-from-derivation on the result of a lock-file-generating derivation; this works well with legacy tools like Maven, for example)
It's kind of scary because Nix is one of the coolest concepts for how to manage Linux systems... Most everything else has so much baggage from things that were designed around hand-maintained, non-disposable installs.
But the community does seem to be still tinkering focused.
I miss the early 2000s when even the hackers seemed to want to make their stuff easy to use(although my source for that is I saw a screenshot of low orbit ion cannon one time, I don't actually know much about hacker history).
> But the community does seem to be still tinkering focused.
Because Nix does NOT make packaging easier. Maintainers are the ones who create distros, and they can live a happy life with something as crude as PKGBUILD, since build instructions are almost always stable.
Even for users, most of them just don't need to juggle with package versions. Bleeding edge is mostly covered by Arch and package pinning works ridiculously well for daily uses.
So "make their stuff easy to use" doesn't apply here. Rather, Nix is harder to use in reality.
I've never heard of Arch and only fairly rarely heard of Manjaro as being suitable for anyone but tinkerers, at least not in the way Android is.
A few months ago Steam stopped working. Nobody seemed to know why. It's back now, but git-cola is gone and I'm not even sure how I broke it. Some nonsense about type errors in the hotkey module, which I don't have time to debug right now so I'm just ignoring and using the flatpak.
Most everything I use on a daily basis has 100s of MBs of dependencies in several layers... Forgetting the virtualeng when pip installing something that happens to have a PyQT dependency and trashing my git cola is... not great and Linux is full of stuff like this.
The amount of effort needed to avoid or fix this kind trouble is more that I imagine Nix would need if it was fully polished.
On Nix I was able to package a Python app in a matter of hours, and
To date I've paid no attention to Flakes because whenever I look at them, they appear to require me to manually list all target architectures in the Flakes file, which is ridiculous. I'm not going to make the code I publish needlessly dependent on specific architectures.
This problem seems to be solved commonly in two ways:
- People thoughtlessly and senselessly listing only x86;
- People using the popular flake utility repository.
Having to rely on an unendorsed third party just to write architecture-independent code isn't very appealing to me. This seems like a serious deficiency in the design of Flakes, though it would be tolerable at least if this functionality was at least in Nixpkgs.
I haven't personally found this to be an issue. I usually define the arches I intend to hit at the beginning of the flake, then pass that list to pkgs so it can track down the independent dependencies:
> they appear to require me to manually list all target architectures in the Flakes file, which is ridiculous
Well, we're talking about evaluating a pure function (literally the entire philosophy of Nix is treating a build like a pure function). Those things are variable state as an input which affects the output, and therefore must be specified as inputs. I don't see the problem here (if you have already accepted that you want to treat builds as pure functions with total encapsulation of the state required to run them, and thus having deterministic outcomes).
Except using NixOS without flakes doesn't require this manual enumeration so it's clearly not a requirement, but a design choice.
Nothing is ultimately pure since you're running on top of a kernel which can affect computation. It's unclear to me what practical gain you get from trying to obsessively get "maximum purity", which is in any case illusory because you're still running on a kernel from outside the closure.
Making it impossible to write portable code isn't a good design.
How does this make it "impossible to write portable code"? CPU and OS differences produce different binaries, which are fundamentally different output values. Are you not understanding exactly how this works, or something? If you have an old flake that only defines outputs to, say, ARM, and it's 100 years in the future and no active CPU derives from ARM anymore, that's not the flake's problem. You'd arguably find it far easier to work with the flake in that context (perhaps finding an old emulator to execute it on, and THEN trying to work on migrating that to whatever architectures are used then) than finding the old C code (or whatever) and expecting that to build on whatever tooling is available then. The idea that "C is portable" is laughable, already- it's only portable to the extent that the compiler for it is portable- and then you are right back at the original problem, the dependence on OS and CPU architectures as inputs!
> obsessively get "maximum purity", which is in any case illusory
I don't understand this argument. Should I stop using functional languages because a cosmic ray could potentially mutate a variable that I expect to be immutable? Could it be that expecting perfect purity is in fact the enemy of "good" in this case? The fact that I've almost universally had better experiences in languages that emphasize "purity" (despite running on "uncertain" underpinnings) seems to undermine this reasoning.
It would be nice to have a shorthand value that means "evaluate this pure function exactly the same way regardless of the 'system' parameter", which would be helpful for completely architecture-less packages (such as interpreted scripts).
Which deps they pull in is still determined by system because their interpreters are in the dependency closure and what arch Perl is built for affects that Perl package's hash, etc.
But as the other person said, you're still building in assumptions in that case, which is bad (from the perspective of the whole philosophy of the Nix design choices). Because the script assumes that the script runner (which is also compiled to a certain CPU and OS!) will work when given the script as input, for example- and it is not guaranteed to. If you include the OS and CPU arch, it is FAR MORE guaranteed to (although perhaps, not 100% provably).
Perhaps you haven't dealt with enough Python packages that make assumptions about the availability and state/version of underlying OS-level libraries (and Python itself: See the transition from versions 2 to 3 as an example of this chaos) to understand how important it is to control for assumptions.
What you gain in convenience today, you pay tenfold for as "interest" later (this is thus definitely one aspect of the "tech debt" problem).
I certainly have experienced my fair share of architecture-dependant Python horror stories, and I agree with your philosophy of convenience as a kind of loan against tech debt! However, if I package a Python script that appears not to use any system libraries or features (maybe I even wrote it myself), I would define the build for any architecture.
One reason for doing this would be for when $DISTRO declares that they will now support a new architecture. What packages would then be expected to require patches? If existing packages were marked as 'all', those can reasonably be expected to succeed and should cause noisy errors if they don't. Conversely, packages which were explicitly marked for specific architectures (even if that is all the architectures that the distribution supported when they were created) can be expected not to work on the new architecture without modification. This does of course require the packager to actually know the difference between using the keywords and just marking every known architecture. And to be fair, what I was originally advocating for in my comment was more like Debian's 'any' wildcard, which is not quite as strong as the assertion that the package is completely architecture-independent.
I would say that a specific tag for architecture-independent builds actually improves the situation: explicitly acknowledging the assumption that exotic architectures will never be an issue. Of course, as your sibling comment mentions, the interpreter is still part of the closure in Nix, so maybe this is incompatible with the existing choices made in the Nix ecosystem.
> With the goal of ending this current limbo and soothe longstanding tensions in the Nix community
Can someone with more background give a quick explanation about why is this a source of tension in the nix community in the first place? Is this a situation of too many cooks in the kitchen or something else?
For example, Flakes have no concept of cross compilation and makes this use case extremely tedious to use.
Flakes were a RFC then merged as an experimental feature and shilled too much to the community to the point they are now a quasi standardized feature even though they didn't go through RFC and therefore ignored all the valuable feedback.
This whole debacle made a lot of invested people tired on both sides.
> Flakes have no concept of cross compilation and makes this use case extremely tedious to use.
I don't agree at all. I use flakes with cross compilation literally all of the time. Having a concept of "cross-compilation" at the CLI level, instead of being part of the nix evaluation itself would be a travesty IMO. I love being able to do a single nix eval that includes 3 different architecture of native builds for my host toplevels, along with "cross" variants that set hostPlatform to x86 and produce cross-builds.
What? I compile my arm64 system on a amd64 system and send them to my cache server so my arm systems don’t have to do the work and just download the outputs and apply them.
That's something I would like to try for my PinePhone. It's been tedious to do development for it, as the PinePhone's CPU struggles with most compilation tasks. Using Nix would be a good way of building for that platform's somewhat exotic features (arm64 and musl libc) on a more powerful machine, without confusing the system package manager with package versions outside the distribution - I should be able to copy the Nix derivations over and install them temporarily with nix-shell. Thanks for the inspiration!
Make sure you use copy-closure and target the result directory. My fist attempts had some crazy find script copying all of nix-store with copy-closure. You can skip this part if you make the build machine the same as the cache machine as the results are automatically cached.
Because Flakes are simultaneously discouraged and labeled as unfinished, yet used by many.
Some aspects of Flakes are a bit contentious. For example, official adoption of Flakes will mean Nix will no longer be a mono-repository. Plus, Flakes are tightly coupled to Git.
However, Flakes bring welcome improvements to longstanding issues. Most notably, package pinning and explicit versioning, which are problematic when using channels.
I use nix with flakes, have written a couple of flakes day to day use. I am not a nix power user. But based on my current understanding this statement seems incorrect
> Flakes are tightly coupled to Git.
How is it tightly coupled to Git if it supports Mercurial out of the box?
Other than using version control to determine what are the sources of the derivation, what does flakes lean on version control?
> Other than using version control to determine what are the sources of the derivation
I don't think that defaulting to using git to list the sources when inside a git repo means that it is tightly coupled to git. If one doesn't want to commit/stage the flake files in the repo one can do `nix develop .` and it works . It will take a little longer because it will copy the entire directory to the store iiuc.
> However, Flakes bring welcome improvements to longstanding issues. Most notably, package pinning and explicit versioning, which are problematic when using channels.
I'm still not convinced by flakes; however, I agree that channels are problematic (and I still don't fully understand them, after a decade!). The first things I do after installing Nix are to delete all the channels and unset `NIX_PATH`. I used to use `<nixpkgs>` for bootstrapping via `fetchgit`, but even that's unnecessary now that `fetchGit` is part of `builtins` :)
Yes, to get Nixpkgs it's much faster to use `fetchTarball`.
You're right that `builtins.fetchTarball` is faster than `builtins.fetchGit` (due to the ridiculous amount of commits in the Nixpkgs repo). I like to keep such definitions in a single, company-wide/project-agnostic git repo (what the Nix Pills series calls the "repository pattern"), and have individual projects import them via `builtins.fetchGit`.
Many years ago we didn't have `builtins.fetchGit`, so had to use the 'fetchgit' function from Nixpkgs instead. That created a chicken-and-egg situation if we wanted to take the Nixpkgs version from some other git repo; hence needing to "bootstrap" via `(import <nixpkgs> { config = {}; }).fetchgit`, and cross our fingers that `NIX_PATH` wasn't set to some crazy value (which, of course, I would inevitably do... https://github.com/Warbo/haskell-te/blob/24475a229908caa3447... )
Note that we need `config = {};` when importing Nixpkgs to avoid an impurity which tries to read files in $HOME. More recent versions of Nixpkgs also need `overlays = [];` to avoid another impurity (looks like this changed at Nixpkgs 17.03, according to https://github.com/Warbo/nix-helpers/blob/master/nixpkgs.nix )
I think most of the issues are more social than technical. A lot of people feel that flakes were pushed through to serve the needs of their corporate sponsor (target) without adequate time spent responding to community feedback. There is (was?) also some opposition to the way that they were designed to break up the nixpkgs monorepo.
Love nix and flakes, can easily describe my whole infrastructure in nix(even generating terraform files from it, manage secrets(agenix,agenix-rekey), and dev tools required to work on parts of the infrastructure(LSP's, deploy-rs, secrets decrypting using ssh key,rekeying secrets to public keys of machines), all in one flake, one monorepo (virtually split up with the josh project into multiple repos with shared history,works really well)
I love it, only thing I would love if there was a proper way for passing arguments to flakes for build /dev/run only dependencies and other ways to specialize the scope of the user using the flake and infrastructure attached to it :)
NixOS is honestly so beautiful and rare. I'm delighted that the project is moving forward in this way.
A friend of mine called it a "rabbit hole" but TBH it's words of power -- I can speak new instances of my environment into existence, not only on newly-acquired compute devices, but on other OSes as well (I put some effort into segmenting the user environment and system config between home-manager and standard /etc/nixos/*)
> I can speak new instances of my environment into existence
You're not kidding. I used nixos-anywhere [1] for the first time the other day. You can point it to any linux host and it will partition, format, and supplant the target's existing OS with your nixOS config, all with a single command. Incredible.
It feels really good to see this RFC cross the finish line into a finalized plan.
The plan itself seems very well thought out. I had a vague desire for an incremental stabilization of flakes some time ago, but this is so much better.
The flakes divide is one of the biggest remaining problemd facing the community, now that the issues with the release cycle have improved so much and continue to improve. Each step taken in executing this plan will be a real boon for the Nix community.
I still fail to understand the naming conventions behind Nix. I don't know what a "flake" or "derivation" is without double checking, the naming sucks.
It's fine, Nix things are conceptually different from anything before.
You could say flakes are like Rakefile, but that would be a lie. You could say they're like Gemfile and Gemfile.lock, but that would be a lie too.
You could say that derivations are like packages, but that would be a lie, you could say they're like container images but that would be a lie too.
Now, you can try to understand what these concepts are by mapping to known knowledge of other things in terms of use cases they solve, that's fine, but at their core these concepts are different and quite unique, so it only makes sense for them to have different names.
Naming is hard, Nix folks had to pick one for each concept, and they chose not to lie by picking existing names that would not map and create bias in the understanding and expectations. It makes for a steeper learning curve, but I'd argue long term in the learning process it's the right move.
Let me try to give some synthesised definitions (which may be incomplete and lies in the Feynman sense):
- a derivation is the reification (or realisation, as in, "make it real") of a function call on the filesystem. IOW the concrete result is derived from the function call, memoized using content addressing.
- a flake is a central definition of a number of target derivations in the context of a specific source state of dependencies. If you look at an actual (snow)flake there's this recursive/fractal design coming from a central point, which kind of visually represent the conceptual structure underpinning a nix flake.
So for me the names totally make sense! But I can understand that they don't out of the blue (and they did not for me at first!)
It turns out (not really by accident) that these cover use cases that were implemented by this or that tool, and instinctively through a partial understanding of the nix concepts we're in conflict: the other tools give us a (biased) understanding which both increases and is in conflict with our understanding of nix concepts. This is a normal process, but at some point by letting go of what we previously know and trying to understand new things for what they are and not what we project onto them, we open ourselves to fully grok, and both fully leverage the new concepts and realise their limitations.
> a derivation is the reification (or realisation, as in, "make it real") of a function call on the filesystem. IOW the concrete result is derived from the function call, memoized using content addressing.
The docs are much better at describing this as "a derivation is a build task." I don't care that it's the return value of a function call, I don't care that because the language is purely functional it may be called lazy and memoized and so on. They are interesting technologically, but the abstraction is bad if it is so leaky you need to understand the internals to use it.
> You could say that derivations are like packages, but that would be a lie,
> a flake is a central definition of a number of target derivations in the context of a specific source state of dependencies.
It's a package. More specifically, a package definition or description. People understand that the result of package installation depends on the total resolution of dependencies and this may be fairly fine grained or a difficult to parse graph (they just trust that the package manager does the "right" thing). Most modern package managers do this and it's not confusing to call it a package (although, it's in good company because every package manager likes to call their packages something cute and different).
> If you look at an actual (snow)flake there's this recursive/fractal design coming from a central point, which kind of visually represent the conceptual structure underpinning a nix flake
Never thought about it that way, but it kind of makes sense. I thought the name was inspired by the Nix logo.
I'm still in the 'meh' camp for flakes.
I use niv and it gives me enough usability.
I find the need to include additional libraries to make flakes usable for some reason a weird hurdle I don't personally enjoy (i.e. flake-parts or systems)
The thing I actually love about Flakes is the fact that my immutable system configuration now also contains the versions of dependencies, instead of them being in some out-of-band special area. This is super nice for rollbacks and just general visibility.
It's even more of a plus that it is aware of Git and makes rather surprisingly intelligent decisions when automatically upgrading the system on a schedule (as one example, it seems to be able to deal with when the Git repository has staged or unstaged changes just fine, producing commits with just the lockfile changes.)
Except that niv doesn't ensure pure evaluation, and thus a number of non-flakes, niv-friendly projects are unusable with flakes, and are often difficult to work with otherwise due to their impurities.
It also can't do transient overrides which is quite literally the essential reason that Flakes is killer to me.
For example, I can cross-compile to riscv64-linux, including a bunch of 3rd party flakes repos *specifically* because I refer to them and then override their nixpkgs to point to my nixpkgs with various cross-compilation fixes.
Definitely not possible to do this with niv.
It also does nothing to solve the countless issues with channels that I've watched afflict countless new Nix users, every week, for 3+ years. [insert the usual 8-stop troubleshoot list when a user has any issue possibly related to channels]
Niv is fine and good but there's a lot that it will never provide, like the ability to `nix run` packages or `nix flake show` what your project provides with only a URL in hand.
At this point I recommend we take this through another medium like email or feel free to open up a discourse to help fill in the knowledge gap.
Feel free to tag me on it.
It adds a module system to nix flakes. I've been using nix every day for 4 years and make heavy use of flakes but TBH i'm not really sure the benefit flake-parts. It looks like a ton of new boilerplate.
Just today I was setting up a server for a side project and mulling over do I use ol' reliable Ubuntu+Ansible vs finally trying NixOS. I was very sad to see that all of the popular VPS services (Digital Ocean and the like) "no longer" officially support NixOS.
Linode was nice enough to have an official "how to set up NixOS on Linode" guide, but it requires fiddling with partitions by hand. At that point, I feel like all of the repeatability gains are gone. If I want to spin up a fresh server, I have to read a guide and set stuff up by hand? Could spend that same time setting up an Ubuntu by hand each time followed by git pull or scp to deploy. Ended up using Ansible in the end, as it really does let me just get a new VPS and deploy to it very fast when the time comes.
I wonder why the big providers once supported NixOS and then decided to stop!
And in the `result` directory you will have droplet image which can be uploaded to digital ocean as droplet template.
Its probably best to also create separate configuration only for the image. As a bonus, its already configured, so no need to run `nixos-rebuild switch` after droplet creation. Partitioning configuration is also handled by the builded, however, filesystem choice (and partitioning schema) is limited
(I'm not saying that this is easier than out of the box support for NixOS: IMO if you are even aware how to create custom NixOS image then you are probably somewhat experienced NixOS user)
And you can use something like nixos-anywhere with it for a alternative process, if your provider isn't as cool as Linode and won't let you boot arbitrary ISOs: https://github.com/numtide/nixos-anywhere
Building images directly for cloud vendors' platforms on your local system and then pushing them up and assigning them to VMs is probably nicer than actually installing NixOS in the cloud, though. See this comment's siblings for that :)
Those Linode instructions are about installing an OS from an installation ISO from Linode's rescue mode. -- I'd consider that more a 'plus' to Linode that you get to be able to install whatever unsupported Linux on Linode's VMs. But, of course it's not as smooth as the officially supported images.
> At that point, I feel like all of the repeatability gains are gone. If I want to spin up a fresh server, I have to read a guide and set stuff up by hand?
Just as with ansible, "git pull to deploy". You'd keep a copy of your NixOS configuration.nix somewhere else, and would be able to apply it later.
> it really does let me just get a new VPS and deploy to it very fast
Using a tool you're familiar with to get the job done is going to be faster than learning to use a tool you're unfamiliar with.
I believe much of the use of NixOS is for hobby stuff, and for personal machines. (c.f. "In what environments do you use Nix", Development (1242) vs Home Server (845) vs Production (386) https://discourse.nixos.org/t/2022-nix-survey-results/18983).
nixos-infect looks great. Don't know how I didn't find that. Might give it a shot.
> Using a tool you're familiar with to get the job done is going to be faster than learning to use a tool you're unfamiliar with.
I'm well aware of this and had the time to do some upfront investment. During that investment, it seemed hard to boil a fresh deploy down to a couple of clicks. Given the great responses I'm getting, that was probably wrong, but wasn't easy for me to figure out through simple web searches!
One smaller UI improvement I would like to see is being able to retrieve the exact git commit of an installed flake. This seems not to be possible atm. Main argument for not having this is putting a reference to the git commit into the nix store folder would break hermetic evaluation. (You can habe multiple commits resulting in the same code.) It should however not be too hard to log that information separately somewhere else. It is somewhat disapointing for this link to be missing when flakes are already tied to git as they are.
The log entries could also include a flag if the flake was installed "dirty" (having uncomitted changes at the time).
Can someone that understands this "limbo" and "long standing tensions" give a TL;DR for someone that knows what flakes and the new cli are but hasn't been following the community discussions around it?
Flakes are amazing but have been designated as an unstable or beta feature for I think literally years now, which creates tension between the desire to get them polished and perfect and the desire to have them be the one true official way to do things already.
I hope the standardize on aliasing -ise and -ize endings in the CLI instead of throwing errors to folks just wanting to optmise or optimize because it shouldn’t matter.
I wanted to switch to nixos but current segregation between flakes and (traditional) nix features was a huge stop sign for me. Seems like this move is a good sign resolving this issue. Hope they bring things nice together -- features, doc, the community etc.
I empathise with this uncertainty. As I understand it, flakes aren't incompatible with the previous way of doing things. Rather they represent an additional feature which can be used on top of them.
For example if you have a shell.nix that you were running with `nix-shell` which defaults to using channels to obtain nixpkgs
And it will use the locked nixpkgs input defined in your flake. You can run it with the new `nix develop` command, but `nix-shell` will continue to work, giving you the previous behaviour.
Building third party flakes takes forever since every flake uses its own version of nixpkgs. If you don't pin your third party flake urls they might also change under your nose as you run the same command again a day later.
Flakes are coupled to git. You need to remember to stage changes whenever you do Ctrl+S in your editor before rebuilding. I've wasted more time than I'd like to admit wondering why what I'm building doesn't include my latest change.
Flakes copy the entire directory into the nix store. This is terrible for mono-repos - and especially if it contains any large files. There is an issue about making the copying of the entire directory into /nix/store lazy - though this doesn't really address the problem. It just treats some common symptoms.
This kind of copying would likely be a lot more acceptable if it was specified explicitly in flake.nix, rather than implicitly. Then you could also use your own filters for ignoring files, rather than relying on the coupling to git and its staging area.