Hello, world!
I’m currently refactoring my NixOS configuration. My goals are as follows:
-
Reduce code repetition using modules
I want a separation between data and logic; that is, use options to store varying state while keeping the implementation consistent. If two users use ssh, they should be able to reference the same module, but provide different values in options for the content of their configuration and key files. Editing a module should update all consumers of the module. -
Centralize all state in a single file per host / user
I want to ‘lift’ all key parameters that are likely to change often, for both host configurations (networking, users to include, system-wide modules to include) and user configurations (extra groups, ssh match blocks, homeManager modules to include) into a single file for fast and easy modification. -
Flat hierarchy, unidirectorional flow of information
I want to unnest as much as possible by enforcing the way modules are imported into the config. The flake imports hosts, which in turn import users, which in turn import modules. The modules at the end of this chain should be able to access information declared by the hosts that import them; the hosts should not need any awareness of its users.
A basic diagram of what I’ve come up with so far:
I was inspired by EmergentMind and used his config as a basis for my own. I’ve come pretty far, but I’m by no means an expert. Here’s my config as it currently stands.
I’m very happy with what I’ve been able to accomplish, though it’s not fully complete. The key milestone for me is polishing the abstraction to the point of being able to reference the same modules from two very different systems and get the same desktop experience.
I’m running into a few issues:
-
attribute of lib missing
Very likely related to this post.lib.extendseems to be a bad choice in general. -
infinite recursion when passing config to a child attrset
A classic issue that I imagine only requires a bit of careful and deliberate consideration to resolve. Unfortunately my unfamiliarity with best practices for configuration design is a stumbling block here. It seems likespecialArgsor_module.argsis the key to this, but I’m having a hard time with the details. -
Attrs not available when not directly accessed by an imported module
Inserting any indirection, like, for example, adefault.nixmodule that imports all adjecent modules in its same directory, will prevent those adjacent modules from accessing the attrs passed to thedefault.nixmodule.
Beyond just addressing any of the above, I’m really looking for resources regarding well-tread structures for a config of this style that resist the many beginner flaws I’m introducing. I was very piqued by Snowflake-lib, for example. I’m also curious about freeformTypes submodules and if I’m under- or mis-utilizing options. Lastly, there seems to be a great deal more nuance to the module-import system that I don’t fully comprehend, which might be the edge I need; but ideally, folks here with more experience can point me in the right direction for the best impact.
Any feedback, guidance, questions, or conversation would be greatly appreciated. I can gladly share more information as would be useful, or if anyone is just curious. Thank you all for your time ![]()
