How do you organize your configuration?

I’m sure this is a fairly frequent question, however I haven’t seen any concrete discussion on the whys and hows of your configuration. This is primarily from my search for a solution that I enjoy using, with a primary focus on a consistent configuration across multiple machines. I can elaborate a bit on my own configuration:

  • I initially, like everyone, did everything in a single configuration.nix file, installed some packages here, configured some things there. Once I installed NixOS on my desktop machine I needed a way to have separate machine configuration but wanted my “userland” to stay the same.
  • At some point I figured out I could create machine specific configurations by having a separate configuration.nix files that I symlinked from my ~/.dotfiles repo into /etc/nixos/configuration.nix that imported configuration files/ I had something like graphical.nix that configured my Plasma/graphical apps that I’d import but keep machine specific configuration in their own configuration.nix files.
  • I discovered home-manager and integrated it into my configuration as a NixOS module, moving over my dotfiles and merging them into my system configuration. I really enjoyed this, sans finding it annoying that I had to rebuild my system to get new changes for small dotfile changes, so I just symlinked parts of the config that I changed all the time instead of building it with Nix (my Emacs configuration especially).
  • I then switched to the unstable branch for my machines with nix-channel. After having tried out niv for some projects where I needed to pin dependencies and seeing a few people try it out on their configuration I switched to using it for managing my channels and overlays. This works, but due to how I’ve configured things I have to rebuild my system twice for it to update to the latest unstable as mandated by niv… and I managed to completely break my store by not reading the documentation on what a command did and now I can’t update anymore… which leads me to this.

I’m looking at a way to restructure my configuration and dotfiles, not really sure how yet but I liked where I was conceptually heading, a pinned nixpkgs version that’s consistent across my machines. I might also try out using home-manager as a regular program and not a NixOS module due to frustrations with having to build the system on minor changes.

Anyone willing to share thoughts, experiences on how they ended up with the configuration they have now, pain points, things they want to improve etc? :slightly_smiling_face:

Mine is not that complicated. I have a git repo with all my nix configs. I clone it to /etc/nixos/nix-configs. Inside nix-configs is a nix file for each machine plus a modules directory which has any nix modules that are shared between configurations.

When I build a new machine, I just clone nix-configs and edit the configuration.nix so it does nothing but include the hardware-configuration.nix and nix-configs/machine-name.nix.

You can get an overview on this wiki page.

A common pattern is separate folders for packages, modules, tests and system configs, for example.

Yeah, I also struggling with organizing dotfiles. I’ve looked at the home manager, but it seems like it solves a slightly different problem.

What I ended up with is a home directory in my config repo, and a sync.py script which recursively symlinks stuff, which I run manually. Instead of sync.py, I’d love to just say “sync /home/matklad/config/home to /home/matklad” in my configuration.nix, but I don’t know how.

Hi,
mine is a single org-mode file that tangle to many small files,
I can’t even tell why, I simply start like that and left in
place… Essentially I divide my org config in headings and any
first-level heading tangle to a single file…

– Ingmar

1 Like

I’ve looked at enough repos that I’m nearly cross eyed now, I’m not really looking for code but more of an discussion on why you chose to do things the way you did :slightly_smiling_face:

I actually have something for this, but you need home-manager for it. I have a execute function that I found somewhere on GitHub that you can use to run arbitrary shell expressions after activation of packages. It’s how I symlink my Emacs configuration at build-time.

1 Like

Maybe I am misunderstanding what you are trying to achieve, but symlinking stuff is one of the things home-manager does. What I like conceptually about it most is that you don’t have to manage dotffiles any more, if you don’t want to: The mess of scattered files polluting your home directory is reduced to an implementation detail of your user environment configuration.

To answer your original question: I follow the common pattern of separating machines, modules and configuration units in folders. System and user configuration are separated, since I use both Linux and Darwin, and my user environment (at least in the shell) should be portable. User configuration directories are additionally separated by abilities, such as Linux/Darwin, textual/graphical. Maybe that is a bit overkill, but at some point I felt it was was more convenient than hand-picking for each machine. Maybe I’ll revert that.

Bootstrapping NixOS is running a script in the system repo, and the system configuration has a service which bootstraps my user environment if it’s not in place - also by running a script, i.e. without having to assume much about it. That way I don’t need home-manager as a system module. That one-command bootstrapping is very nice to have. It also includes a custom variant of nixos-infect that I use for VPS.

Secrets are considered state and are imported from USB onto the file system during bootstrap.

That whole setup runs so well that I have barely touched it in months, and only for additions. I would very much like to have more control over my Mac, but haven’t had the time to look into nix-darwin yet.

My user environment can be found
here. I don’t have my systems public because of some private parts concerning shared folders and other users. Maybe I will separate that out at some point, but probably not.