Our great sponsors
-
InfluxDB
Power Real-Time Data Analytics at Scale. Get real-time insights from all types of time series data with InfluxDB. Ingest, query, and analyze billions of data points in real-time with unbounded cardinality.
-
WorkOS
The modern identity platform for B2B SaaS. The APIs are flexible and easy-to-use, supporting authentication, user identity, and complex enterprise features like SSO and SCIM provisioning.
-
impermanence
Modules to help you handle persistent state on systems with ephemeral root storage [maintainer=@talyz]
-
POCO
The POCO C++ Libraries are powerful cross-platform C++ libraries for building network- and internet-based applications that run on desktop, server, mobile, IoT, and embedded systems.
-
spack
A flexible package manager that supports multiple versions, configurations, platforms, and compilers.
-
SaaSHub
SaaSHub - Software Alternatives and Reviews. SaaSHub helps you find the best software and product alternatives
It is correct to say that dynamic linking with rebuild-on-input-dependency-change (like NixOS does) is similar to static linking when it comes to rebuild behaviour.
However, also remember that changing dynamic libraries behind executables back is a concept that only makes sense in the presence of ABI compatibility. This is predominantly a C concept (or at least popular in the C world), and much less so for other linked programming languages like C++, Haskell, Go, and so on. Thus Nix being a general-purpose build system takes the general route here, and builds can also use their dependencies during the build step (e.g. a packaged program's autoconf suite might check the version or a symbol provided by a library), which requires full rebuilds for reproducibility.
(Nix is working on content-addressed instead of input-hash-haddressed builds, which might open the door for avoiding many rebuilds that do not affect build _output_.)
That said, it might still be quite easy to achieve what you want:
* If you want to iterate on a C library that's early in the dependency graph, in am ABI-compatible fashion, you coul duse LD_LIBRARY_PATH or LD_PRELOAD on it.
* If you want to override libc in an ABI-compatible way, you can use `patchelf` with its `--set-interpreter` and `--set-rpath` flags to replace the libc an executable is linked against after the fact. For example, you can make an `.override` of a nix derivation that just `cp -r`'s the existing files, and then calls `patchelf` on them.
I have used both these methods to work around glibc bugs that I patched out, avoiding even to have to recompile my own software at the top of the build dependency tree.
https://github.com/NixOS/nixpkgs/issues/50329
For the system, I like the devos template:
https://github.com/divnix/devos
The idea of flakes is how you define inputs, and you define the system (and packages, and shell etc.) in the outputs using the inputs. The inputs are git repos which point to other flakes. You can mix and match these as much as you want (see the devos repo for examples) and when you build the derivation, it generates a lockfile for exact commits in that point in time what were used in the given inputs.
You commit the lockfile and in the other systems where you pull your config from the repo, it uses exactly those commits and installs the same versions as you did in your other systems.
This was quite annoying and hard to do before flakes. Now it's easy.
The problem what people face with building their system as a flake is combining the packages so you can point to `jq` from the unstable nixos and firefox from the stable train. I think this aspect needs better documentation so it wouldn't be so damn hard to learn (believe me, I know). Luckily there are projects like devos that give a nice template for people to play with (with documentation!)
Another use for flakes is to create a development shell for your repo, an example what I did a while ago:
https://github.com/pimeys/nix-prisma-example
Either have `nix-direnv` installed, enter the directory and say `direnv allow`, or just `nix develop` and it will gather, compile and install the correct versions of packages to your shell. Updating the packages? Call `nix flake update` in the directory, commit the lockfile and everybody else gets the new versions to their shell.
Nix is wonderful, but absolutely under-documented. (In part due to a small community, etc.).
A couple of examples I've run into:
https://github.com/NixOS/nix/issues/2259 showed people trying to make use of the "hello world" package which was given in NixPkgs, but couldn't quite figure out how to get it to build.
e.g. if you want a package that's a simple script, "writeScriptBin" seems like what you'd want. -- But it's really not clear how to use it from the manual; you'd have to read the nixpkgs source.
Looks like these things are being addressed, although from past of experience it probably will take several years :(
1. https://github.com/tweag/nickel - it is a typed language, that might in the future replace nix language
2. looks like likely is addressed by flakes
I think Henrik Lissner (author of Doom Emacs) wrote a really good piece about why someone should choose to use NixOS - https://github.com/hlissner/dotfiles#frequently-asked-questi...
For the purposes of building well-defined systems from one configuration file, I wrote aconfmgr for Arch Linux. One feature it has over typical configuration managers is the ability to import the configuration of an existing system, so you're not limited to Nix to configure the system / software.
https://github.com/CyberShadow/aconfmgr
There's nothing there that needs flakes (an experimental feature which people should not enable without understanding the implications). You could build a system derivation and run a diff against /run/current-system on it.
For what it's worth, nix-diff has very verbose output (it literally diffs everything that is different in the inputs & outputs). A slightly nicer way to diff systems is nvd[0] (example output[1]) which only shows version changes and added/removed packages.
[0]: https://gitlab.com/khumba/nvd
[1]: https://deploys.tvl.fyi/diff/4xmyvkr9nw0cwkn5q38p0cfc58x3jdy...
>They only package linux-libre, so if your device needs proprietary wifi, you're out of luck.
I wouldn't say you're out of luck in that case. If you need upstream Linux, nonguix has it: https://gitlab.com/nonguix/nonguix
Interesting to see exponential growth in NixOS github stars https://star-history.com/#NixOS/nixpkgs&Date . Perhaps the user base is reaching a tipping point where there will be the resources to address some of these problems.
I've recently discovered `asdf` (https://github.com/asdf-vm/asdf). It's as technically clever as nix, but it does allow you to manage version of most language toolchains with one tool.
People have tried: https://github.com/jkcfg/jk
But yeah I agree. The thing is, if all you need is robust determinism why do you need a full functional language with currying and other complex concepts?
Google had the same problem for Bazel, and their solution (Starlark) is way easier to understand.
Not being able to use it in a home directory without root was a major turn off for me. I actually started writing a python module to install packages in a way similar to nix (albeit I never got to reproducibility) but ran into problems building glibc and installing it to the home dir. I’d like to continue it one day.
https://github.com/DylanEHolland/pykgr
This is a pretty good example the kind of victim blaming I'm talking about. It's a kind of insidious toxicity that permeates certain communities, although I've not been able to put my finger on what exactly brings it out, or why it's so tightly clung to as an acceptable behavior in some places.
I actually tried to help for awhile, and even started a help guide https://github.com/kstenerud/nixos-beginners-handbook/
But eventually one gets ground down and demoralized enough to just give up. It's a real shame, because I LOVE what NixOS is trying to accomplish.
> The configuration.nix "defines" the whole system, but obviously doesn't touch anything in /home
home-manager[1]
> or /var, so that's on you to back up, migrate, whatever.
Erase your darlings[2], impermanence[3]
[1]: https://github.com/nix-community/home-manager
[2]: https://grahamc.com/blog/erase-your-darlings
[3]: https://github.com/nix-community/impermanence
> The configuration.nix "defines" the whole system, but obviously doesn't touch anything in /home
home-manager[1]
> or /var, so that's on you to back up, migrate, whatever.
Erase your darlings[2], impermanence[3]
[1]: https://github.com/nix-community/home-manager
[2]: https://grahamc.com/blog/erase-your-darlings
[3]: https://github.com/nix-community/impermanence
Where nixpkgs2105 is a pinned revision of the Nixpkgs repo, defined in another overlay. My current Nix config has pinned Nixpkgs versions going back to 2016. For example, here's a bunch of such overrides:
https://github.com/Warbo/nix-config/blob/master/overrides/fi...
At the moment I'm using niv to manage the pinned Nixpkgs versions (the 'repoXXXX' entries):
https://github.com/Warbo/nix-helpers/blob/master/nix/sources...
Where nixpkgs2105 is a pinned revision of the Nixpkgs repo, defined in another overlay. My current Nix config has pinned Nixpkgs versions going back to 2016. For example, here's a bunch of such overrides:
https://github.com/Warbo/nix-config/blob/master/overrides/fi...
At the moment I'm using niv to manage the pinned Nixpkgs versions (the 'repoXXXX' entries):
https://github.com/Warbo/nix-helpers/blob/master/nix/sources...
Many of the necessary fixes do end up getting pushed upstream, though, thinking especially of stuff like converting CMake projects to use the GNUInstallDirs standard, so there is a benefit to the strictness work that extends beyond even just the Nix community itself.
Of course, sometimes those kinds of changes just never get merged, for a variety of well-understood open-sourcey reasons, eg: https://github.com/pocoproject/poco/pull/3105
I understand the first complaint but not the second
> The second flaw is that NixOS does not actually provide real isolation.
I thought this would going to be about security, but then it was about having to repackage the world. But Nixpkgs is current the biggest and most up to date package repository in the world (we finally beat AUR). Packaging enough stuff is emphatically not the problem.
What I want to see is development be easier with Nix, because winning over the hearts and minds of upstream developers is the final frontier. To that end I wrote https://github.com/NixOS/rfcs/pull/92 and https://github.com/NixOS/rfcs/pull/109.
As a side benefit, autogenerating more Nix means less handwritten Nix! I do think people give the language itself to much grief when the problem is more the library side with the copious override shenanagins and other stuff.
For the system, I like the devos template:
https://github.com/divnix/devos
The idea of flakes is how you define inputs, and you define the system (and packages, and shell etc.) in the outputs using the inputs. The inputs are git repos which point to other flakes. You can mix and match these as much as you want (see the devos repo for examples) and when you build the derivation, it generates a lockfile for exact commits in that point in time what were used in the given inputs.
You commit the lockfile and in the other systems where you pull your config from the repo, it uses exactly those commits and installs the same versions as you did in your other systems.
This was quite annoying and hard to do before flakes. Now it's easy.
The problem what people face with building their system as a flake is combining the packages so you can point to `jq` from the unstable nixos and firefox from the stable train. I think this aspect needs better documentation so it wouldn't be so damn hard to learn (believe me, I know). Luckily there are projects like devos that give a nice template for people to play with (with documentation!)
Another use for flakes is to create a development shell for your repo, an example what I did a while ago:
https://github.com/pimeys/nix-prisma-example
Either have `nix-direnv` installed, enter the directory and say `direnv allow`, or just `nix develop` and it will gather, compile and install the correct versions of packages to your shell. Updating the packages? Call `nix flake update` in the directory, commit the lockfile and everybody else gets the new versions to their shell.
I'd recommend LUKS. NixOS has a guide in the wiki but if you're looking for an example, see my nix readme. Might have a typo or two but it's 99 percent there
https://github.com/NelsonJeppesen/nix-lifestyle#luks-encrypt...
Yeah I agree here, I used to find Nix somewhat unintuitive but I have now managed a few non-trivial projects. One being to package Xilinx ISE as a flake [0], and another to build a non-volatile Linux image using busybox and runit [1]. For the latter I still haven't quite gotten where I want but that's because I realised I needed dbus for avahi and dbus is just so ridiculously complex.
[0] - https://github.com/benpye/nix-fpga-tools/
[1] - https://github.com/benpye/nix-embedded
Yeah I agree here, I used to find Nix somewhat unintuitive but I have now managed a few non-trivial projects. One being to package Xilinx ISE as a flake [0], and another to build a non-volatile Linux image using busybox and runit [1]. For the latter I still haven't quite gotten where I want but that's because I realised I needed dbus for avahi and dbus is just so ridiculously complex.
[0] - https://github.com/benpye/nix-fpga-tools/
[1] - https://github.com/benpye/nix-embedded
You might as well try Spack, it's Python + a dsl to customize builds in a single line. Guix package descriptions look very daunting to me.
[1] https://github.com/spack/spack/
> And about Home Manager, the reason why I think it's over-hyped is because it provides a declarative approach to something that was... already declarative. Your $XDG_CONFIG directory does not need a leaky Nix abstraction on top of it
I don't really agree, I spent about 30mins to get my home-manager config to support an m1 mac [0]. I don't really want to think how long it would take me to look up all of the homebrew package names, and learn a new package manager. Instead, I just pushed all of the linux-specific items into their own bin, a little more logic, and I was able to get back to a comfortable terminal + git + vim settings.
Also, nix exposes congruent configuration management[1]. The state of my system is an exact reflection of the configuration. With other tools like ansible, vagrant, etc, I would get reconciliation configuration which is close on initial install but configuration drift is an ever-present concern; not to mention that large recipes and playbooks can take a very long time to run. Going the homebrew route would be divergent configuration, it would be very hard for me to get back to a certain configuration. With nix (and by extension home-manager), I can version control the configuration, improve it, roll it back, w/e I want.
> Why would I write my i3 config in Nix??
You do get some type checking, although the iteration time would probably be similar. You could also just do `xsession.windowManager.i3.extraConfig = builtins.readFile ./i3.config;` if you really just wanted to wholesale read in your existing profile.
> I'd rather just use `nix-env` personally.
nix-env is a double edge sword. You can rollback (somewhat, I believe it's just a stack of all changes), which is an improvement. However, nix only retains the "derivation name" to try and management. But for packages like python38, if you try to upgrade it, it will determine that `python-3.11-a3` is the package which is the most up-to-date. I try to discourage using nix-env.
[0]: https://github.com/jonringer/nixpkgs-config/commit/37ddfefa1...
Reading about NixOS reminded me of the assign command in Amiga OS: https://github.com/TheBeef/AmigaAssign
Okay, yes, I agree with all of that. Flakes are kind of a module system, but having clearer semantics around functions and classes would definitely help with both code readability and producing better stack traces.
And a proper type system would be awesome.
Regarding docs, it is interesting that portions of the nixpkgs source do seem to have docblock-like comments above the functions, but AFAICT there's no formalized process for extracting or rendering those. Given that https://github.com/nix-community/rnix-parser exists, I wonder how big of a leap it would be to actually extract those, render them into rST pages, and generate a searchable Sphinx manual.