Is NixBSD a possibility?

The first thing that needs to happen is flake: update nixpkgs: 22.11 -> 23.05 by vcunat · Pull Request #8569 · NixOS/nix · GitHub getting finished.


It looks like a NixOS/kFreeBSD to me.
It has at least two serious hurdles:

  1. NixOS is too tied to Linux
  2. NixOS is too tied to systemd

My idea for now is a bit more modest:

  1. BSD as tier 1, or at least tier 2, on Nixpkgs.
    It makes few to no sense to try it before that “turning point”.
  2. NixBSD from scratch.

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.

  • Make *BSD builds completely transparent (behind a single option on NixOS and/or nix-darwin) Transparent VM builds - a hook to start and stop a builder VM · Issue #8604 · NixOS/nix · GitHub

  • Linux / *BSD multi-boot with bootspec

And to work towards BSD support in NixOS:

  • BSD image support in the NixOS test framework.

  • 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.

  • Establish a pattern for supporting services on both operating systems without duplicating everything. RFC 78 System-agnostic configuration file generators has some ideas for such a pattern.

Disclaimer: I don’t know a lot about the BSDs, but I do know where it should be integrated.


Porting NixOS could look a lot like Split nixos/nix-daemon.nix by roberth · Pull Request #241690 · NixOS/nixpkgs · GitHub
Portability wasn’t even my original goal, but rather it was just a consequence of the cleanup. You’d now only have to port a smaller module that’s exclusively about the daemon service.


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.

1 Like

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.

1 Like

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?

1 Like

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 in e2 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.

1 Like

For reference, something like kFreeBSD seems unlikely to gather a sufficient mass of contributors: Aurélien Jarno - Goodbye Debian GNU/kFreeBSD

1 Like

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).

1 Like

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.


Debian certainly does have high barriers for contribution, at least generally (I’m not so sure about ports).

1 Like

Yeah our basic MO has always been

  1. Take a niche fun thing
  2. Make it easy to try out
  3. Make it easy to contribute to
  4. Make it surprisingly powerful (with the polish of everyone’s contributions)
  5. Expand the Overton window of what feels possible

That applies to many of our projects, and specific initiatives within them, alike. It’s what we do best.

Debian stumbles at every step and therefore can’t get to step 5 without a huge stroke of luck.


This feels like it belongs in a ~gentle manifesto somewhere :slight_smile:


Support cross compiling to BSD and CI it by Ericson2314 · Pull Request #8887 · NixOS/nix · GitHub Making sure cross-build Nix itself is cached and not bitrotting!

Actually using cross-built Nix on BSD is still left as an exercise for the reader :wink:


For the record, NixBSD exists now:


It should be put under the NixOS umbrella, I would say. Or at least under nix-community.


It’s high up on my priority queue to get the Nixpkgs and Nix work of @rhelmot for this upstream. That would just leave the NixOS-inspired part separate (hopefully to someday be merged with regular NixOS!).