Basically, most of the things are on a single trajectory here!
Check what clearly still needs fixing about packages and fix it.
Home-Manager or just buildEnv, but try using a user env constructed via Nix (and see what packages still need fixing)
Build bits of system side within Nix. Maybe try using the stuff from there in the user environment.
Hacky build of a whole system with bootloader update.
Customisable-ish build of a whole system.
Use module system in a way where service configuration can be reused between Nix-managed-BSD and NixOS. Maybe these are technically separate modules who just reimport the config generation logic. But whatever, you can now easily port services between your configs.
NixOS has a lot of cool stuff that’s actually portable and could be shared between NixOS/Linux and NixOS/*BSD
Core NixOS concepts such as
toplevel
the activation script
switch-to-configuration minus the systemd part
environment.*
The NixOS VM test framework. This is barely coupled with NixOS proper.
BSD support could initially be implemented as an alternate module list.
Some interesting first milestones would be
A cross compiled Nix that runs on *BSD
A package like darwin.builder that produces a VM launcher (ie produce a *BSD image containing an SSH server and a Nix that can serve a “remote” build; can be super hacky as long as it works). This will enable anyone to test with *BSD.
Refactor modules such as users-groups.nix to work in a BSD context. Perhaps by splitting into interface vs implementation modules. Load only the modules that you need (and work) with nixpkgsFlake.lib.nixos.evalModules aka (import <nixpkgs/nixos/lib> {}).evalModules.
Not sure why it slipped my mind until now, but I’ve ~recently suggested thinning out modules a little by pulling more configuration logistic code towards the packages (i.e., moving it into passthru functions).
This could benefit Nth module systems and help with things like generating a config for some server you just need to run in a shell.
That’s also what RFC 78 is about, though I don’t know if using the package attributes for it leads to the best outcome. In most cases your config file would depend on too much. For instance you have to know in advance which package you’re going to use, even if the config file doesn’t depend on the package version at all.
Another issue is strictness. By putting the generator on a package attrset you need to evaluate the package first, even if you don’t actually need the package. This could make performance worse and cause some unnecessary errors, like if you’re generating the config file using a platform that the package doesn’t support.
Usually not a problem, but really annoying when it is.
Hm, if it is added via //, won’t the override level be checked first with mkDerivation call not even made if the override level already sets the config generator function attribute?
This is about strictness. Nix doesn’t have good terms for this so let me define
Weak head normal form: the smallest amount of data that can be returned for an expression
for primitives, including strings: the whole thing
for composite types: the “skeleton”, either:
attribute names; attribute values remain thunks
list length; items remain thunks
for functions: a function value; either a primitive function (implementation defined) or a combination of a source location and the scope that applies to it.
“Strict in”: an expression e1 is called strict ine2 when returning the weak head normal form of
So with that out of the way, strictness of a // b is easy to answer: it is strict in both a and b.
That means that pkg // { generateConfig = ...; } is strict in pkg.
pkg itself will be strict in many things, including all the mkDerivation argument attribute names and some of the values, notably including outputs, and the assert statements that precede it in the package nix file.
Most of these sound about right, but I’m a little unsure how to read this bit:
Is this a generic “you” that just describes what Nix needs to know to evaluate the config, or is “you” an end-user who needs to directly reference a package in their NixOS config in order to manage its settings?
If the latter, I should clarify that I’m imagining a transparent refactor (to abstract out reusable bits) from the perspective of someone using/configuring a module.
Both "you"s, kind of.
Nix needs to evaluate the package, and we don’t really know who the “end user” of the function is and whether they can decide what the package should be. Both reasons can become a problem.
Maybe they only want a config file and no package, because the package they want is already in the docker image they’re building, or whatever.
A “stand-alone” function - one that doesn’t have the package in its arguments or scope - doesn’t suffer from this problem.
Maybe the stand-alone function needs to know the package version, but that’s still no reason to depend on the whole package, and most functions don’t even need this.
transparent refactor
I think that’s what we’re all going for. The only disagreement is about how it’s factored out, and where it then ends up. Splitting a module is morally equivalent to factoring out a function.
For the end users they’re equally transparent, but factoring out a module follows less familiar rules, and has more value because you get to reuse the option declarations. (And even better if you use the imports into submodule pattern)
But now I’m just repeating the RFC 78 discussion.
It could use some summarization and clarification, but I don’t think this is the time and place, if that’s ok.
I would love to have NixBSD as an alternative to NixOS, but I wouldn’t want to see NixOS adapted to use the FreeBSD kernel. All I want are derivations to build FreeBSD and modules to manage its configuration. Trying to do anything more than that risks creating a variant with no community to support it (which seems to be what happened to Debian GNU/kFreeBSD).
I have thought a lot about the failure of that project. I think the reasons we are different is that:
Contributing to Debian is really hard
Cross compiling with Debian is really hard
Debian is not a good vehicle for “out there” experimentation in general
The goal of a NixOS with some BSD kernel isn’t even just BSD per-se, it is to open the floodgates to kernel experimentation in general. We should also get RedoxOS, SerenityOS, and many other things thereafter. I have no doubt that the sum total of all these things will be compelling.
N=1 to N=2 is the hardest transition, and BSDs are simply good mature candidates to make that initial leap. N=2 to N=3 and beyond is quite easy, and ideally by slowly expunging architecture issues the whole thing pays for itself (e.g. stuff like sharing NixOS modules between Home Manger and Nix Darwin is also helped).
“Opening the floodgates” was my experience with the Nixpkgs-side work, and now I just want to repeat that with NixOS.