Easy-hosts, ez-config, snowfall... what do you use?

Hello.
I’m looking for a framework to organize my dotfiles.
Currently I’m using just flake-parts, and I have a neat mess that It’s probably not going to work in any other host but my current laptop :sweat_smile:

I saw that there are several “frameworks” for handling several hosts using several Oses, and I was trying to decide which one to pick, but I’m a total noob, and also I don’t have much free time, so porting my current config is probably something I’m gonna do just once.

Which one has the most wide base of users, and why people pick it?
I saw ez-config, easy-hosts, snowball, Nixverse, nixos-unified… and I’m kind confused on what each is aiming for.

One cool thing I would like to have is a one-line install command, so each time a spin up a new server I can just one command and have everything setup. I just recently read something about creating isos from your nix config, so maybe that could be a neat feature to quickly span virtual machines on proxmox.

This gets a bit tricky knowing that I want it to perform an interactive second step asking for a password to unblock my bitwarden vault and extract an ssh key used to decode the secrets, but that is a topic for the future.

Thanks for your guidance.

5 Likes

Currently in the same situation :upside_down_face:

It seems snowfall is probably the more established one, I was debating using snowfall or nixos-unified witch is a flake-parts’ module.
I’d also like to know the backing of each project and if there are some guarantees that they’ll be maintained.
I manage 2 nixOS PCs and a nixOS server with my config, and might want to deploy it to a new Ubuntu work machine, so I was looking into adding that functionality while I still have some time.

if you end up committing to one, let me know and share your thought!

I honestly wouldn’t look at them too closely, especially when first starting out

Most frameworks in my experience do of course make the initial setup much easier, but over time you will come across some footguns and oddities that can make some tasks much more difficult or actually impossible. Support may also become troublesome in these circumstances, as a lot of big things affecting your configuration may be completely invisible to you and others without some deep diving into how these frameworks really work

IMO it’s much better to stick to the basics, whether that be more minimalistic frameworks like flake-parts and flake-utils, no Flake framework, or dropping Flakes all together and just using a plain configuration.nix. This was very helpful to me at the start, as Nix is a very deep and complicated ecosystem, so taking baby steps like that was a lot less overwhelming than diving straight into the deep end – which is the most common problem I’ve seen with people first getting starting

I’m also not sure how much they would help in this case, as most frameworks only really only handling the “calling” of configurations, etc. rather than helping you share modules between systems; that part will still be up to you most of the time

Back to your question though:

There’s no real numbers on this, but I’ve probably seen Snowfall (I’m assuming “snowball” was a typo, unless there is yet another one of these :laughing:) around the most often. ez-configs seems to also be used a fair bit

I can speak for Nixverse and nixos-unified as I’ve never used or really looked at them, but for the rest:

  • Snowfall
    • Instead of defining stuff like myPackage = pkgs.callPackage ./package.nix { } explicitly in a Flake, everything is automatically imported based on a directory structure. So instead of the above, you can now just place your package.nix in a directory like packages/myPackage/, and it will automagically work
    • It also has a way to configure the pkgs used in the Flake and your configurations from one place, as shown here – though there are some “gotchas” with this, like being limited to one channel for the entire Flake (i.e., it’s impossible to use nixos-unstable stable on one system, but nixos-24.11 on another)
    • As a word of caution, though: it seems this project has not been super actively maintained since the middle of last year (commit history, starting at the most recent of this writing) and the creator has basically moved on from working on it in favor of a different (non-Flake) project
  • ez-configs
    • This is similar to the above in that configurations can be defined using a specific directory structure, but it is solely for configurations and built around flake-parts. The latter point has the advantage of making ez-configs act very similar to how you configure your systems themselves, as well as having pretty nice docs
    • Modules are a big focus here, with a nice ezModules argument being passed to configurations with your current custom modules for them – i.e., if I have a nixosModules.myCoolModule, I can access in a NixOS configuration easily with ezModules.myCoolModule
    • I would also say this is one of the lesser opinionated frameworks, with it not doing much more to affect your actual configurations aside from giving you a nice way to organize them and import stuff. There are still some assumptions that can block what would be otherwise trivial actions though, like again, using different channels on different systems
    • As for maintenance, it’s a bit lackluster in activity, but it’s a smaller project and AFAIK the maintainer still fully supports it
  • easy-hosts
    • This is very much inspired by ez-configs, so take the first bulletpoint above, but replace the docs link with this one
    • On top of what ez-configs does with it’s directory structure and nice API, easy-hosts also has pretty cool ways to specify certain modules and arguments to pass to each “class” of configuration (home-manager, NixOS, nix-darwin, …). These classes are also extendable if you need something a bit more fine grained
    • I’d say this is the least opinionated out of all of 3, with it not really making many assumptions at all, and allowing for a good bit of extensibility in places where it does – like as of two days ago, it even lets you finally use different channels on different systems!
    • It’s also pretty new, so it’s pretty active

And as for what I use? flake-parts and my own Flake module I wrote a few months ago because I got tired of using this

{
  nixosConfigurations = lib.mapAttrs (_: nixpkgs.lib.nixosSystem) {
    myDesktop = { modules = [ ./desktop/configuration.nix ]; };
    myLaptop = { modules = [ ./laptop/configuration.nix ]; };
  } // {
    myServer = nixpkgs-stable.lib.nixosSystem { modules = [ ./server/configuration.nix ]; };
  };
}

You can see it in action here. Maybe one day I’ll commit to it more and add another framework to this list :stuck_out_tongue:

8 Likes

I continue to think that using any frameworks for NixOS desktop deployments is largely pointless, and only serves to obfuscate things. If you want to use a framework because you don’t know what you’re doing, you’re just going to end up not knowing what you’re doing while using a framework that prevents you from even seeing what you’re doing.

This also applies to flake-parts, it’s completely overkill for NixOS deployments (yes, even multi-host ones), and may well be part of why you feel you need yet another framework. NixOS systems don’t even need the main reason people use flake-parts, system is inherently machine-specific.

Learn to use the NixOS module system properly first, after that you can consider if there is some higher level abstraction that is better suited for expressing your use case. IMO there is not for most, NixOS’ module system itself is an excellent framework, and there are only very few small gripes with the nixosSystem function that could even be cleaned up.

You’re looking for nixos-anywhere, but in practice you will still need to tweak your config for a new system, unless they are truly cattle, in which case you’re looking at a devops deployment which is very different from the type of personal desktop config people usually ask about in this kind of post.

For VM images, you can create a packages output that uses nixos-generators to build an ISO.

2 Likes

Wow what a great and comprehensive response thank you very much. Actually what I was hoping is to get some structure out of these frameworks cuz currently my folder structure is a mess and the module organization is a mess. I was looking for better ways to have easy to navigate and easy to reuse modules for my main machines, which are just my two Darwin laptops and maybe one or two virtual machines (home servers to be configured in a repeatable fashion, instead of stupid random lists of steps).

Will probably stick to basic flake parts, but will give a loot to easy-hosts

1 Like

That is a very valid point and I completely agree.
I’m think I’m looking for solutions to problems that I impose to myself rather than trying to fix them myself.
However I’m not going to use NixOS as my main driver anytime soon, so things that can work on Darwin and maybe be useful to play with virtual machines is what I really need.

Hehe, I didn’t expect to see easy-hosts out in the wild, and on the discourse no less.

Yes I would say this was very much the goal. To provide a semi stable api that is catered as much to new people as to more experienced people. Mainly because I ironically disagree with the concept of configuration frameworks.

4 Likes

I personally use Snowfall.

#1 absurd footgun to get out of the way before I even start talking about it: It gives all users managed by it sudo privileges by default.
See https://github.com/snowfallorg/lib/issues/107


It absolutely does not make things simpler, but I use it to reduce coupling, allow for easier refactoring of my config, and enforce a somewhat consistent directory layout.

  • Only in exceptional cases do I need to manually import anything—I can just add and remove modules without needing to edit a extra file to be in sync every time.
  • I can also freely reorganize and move files around
    • The only files that use imports are directly adjacent in a dedicated directory, so relative import paths won’t be broken by moving them around together.
    • Snowfall includes library functions to trivially get a path relative to the flake root. So, e.g. I can refactor my modules however I want, and a reference to a hostname-dependent SOPS file in systems won’t be broken

A lot of it is kinda janky, but I’m still figuring out how I like my modules organized, so being able to refactor with minimal friction has been worth it for me.