Still Work in progress!
A Nixos config meant for mutliple hosts and high level of modularity. Idea being that modules can be toggled on/off and everything will configure itself where only thing that would need configuration is the hosts themselves, the modules it needs enabled and defintion of what hardware it has.
Config will be very fine tuned for my spesfic setup and needs.
.
├── flake.nix # Flake entrypoint
├── hosts/ # One directory per host
│ ├── <hostname>/
│ │ ├── config.nix # Host-specific logic, imports, options
│ │ └── hardware-configuration.nix # Machine-generated hardware profile
├── lib/ # Shared library helpers
│ └── default.nix # mkHostConfiguration helper
└── modules/
├── core/ # Global options and secure defaults
└── my/ # Custom options for info about host
- Make a new directory
./hosts/<hostname> - Generate the default configurations files
nixos-generate-config --dir ./hosts/<hostname> - Still work in progress, i'll see how i proceed
To keep personal information (like locale settings, usernames, or email
addresses) out of this public repository, this configuration uses a privacy
module. This separates the public configuration logic from your private,
host-specific data.
But, because Nix needs to fetch this repository before it can build your system, there is a one-time "chicken-and-egg" problem to solve.
The solution is a two-stage build process.
- First Build: You'll build the system without the private repository. This build's only job would be to add an SSH rule to your system so it learns how to access the private repo.
- Second Build: Now that your system has the SSH rule, you'll build it again with the private repository enabled. This build will succeed.
[!NOTE] There might be possible simplifications when installing trough nix installer image by manually adding the ssh rule, but has not been tested
[!NOTE] If youre able to have your private repo locally you can swap to using
url = "git+file:///absolute/path/to/repo";Avoiding the whole ssh setup problem
On a new machine, you must first tell your system how to resolve the private repository's address.
-
Edit
flake.nix: Openflake.nixand comment out theprivacyinput:# in flake.nix { inputs = { # ... # COMMENT OUT THIS INPUT FOR THE FIRST BUILD # privacy = { # url = "git+ssh://<alias>/<user>/<repo>.git"; # flake = false; # }; }; # ... rest of your flake ... }
-
Edit Host Configuration: Open your host's configuration file (e.g.,
hosts/<yourHost>/configuration.nix) and enable themy.privacy.sshAliasConfigmodule. You must set thesshKeypath to your secret key (as a string). Also update anything else spesfic to your case
[!NOTE] You must manually copy your private SSH key to this path before running the build.
# in hosts/<yourHost>/configuration.nix
{ pkgs, ... }: {
my.privacy = {
# You can leave this enabled; it will just load an empty set for now.
enable = true;
# Enable the sshAliasConfig and set the key path
sshAliasConfig = {
enable = true;
sshKey = "/etc/nixos/secrets/id_ed25519_privacy";
};
};
# ... rest of your configuration ...
}-
Run the First Build: Now, apply this configuration.
sudo nixos-rebuild switch --flake .#your-hostThis build will succeed and install a new rule in
/etc/ssh/ssh_configthat defines thenixos-privacyhost alias.
Now that your system has the SSH rule, you can safely fetch the private repository.
-
Edit
flake.nix: Go back to yourflake.nixand uncomment theprivacyinput. Make sure its URL uses the same alias as sshAliasConfig.# in flake.nix { inputs = { # ... # UNCOMMENT THIS INPUT privacy = { url = "git+ssh://<alias>/<user>/<repo>.git"; flake = false; }; }; # ... rest of your flake ... }
-
Run the Second Build: Run the build command one more time.
sudo nixos-rebuild switch --flake .#your-host
Nix will now successfully use your SSH key and the nixos-privacy alias to
fetch your private repository, and your system will build with all your private
data. Your setup is complete
-
Flake Input: The system relies on a flake input named
privacy. You must point this input to a private Git repository containing your personal data. This can be done by overriding the input in yourflake.lockfile. -
Data Structure: The private repository must contain a
hosts/directory, with a separate.nixfile for each host (likehosts/titan.nix). Each file must return a Nix attribute set. -
Enabling Per-Host: To use this feature, you must explicitly enable it for each host by setting
my.privacy.enable = true;in its configuration.
If enabled, the module will load the corresponding file from your private
repository and make the data available at config.my.privacy.data. The build
will fail with a descriptive error if the privacy input is missing or the
host-specific file cannot be found, making sure the configuration is always
correct.
I cant yet figure out how i want to structure this config. The idea im left with
is having config.my where my attribute will be defined to hold information
about the host nix cant possibly know.
For example, disk information, define
config.my.disk.<disk_idetifier>.type = "ssd", which could allow other modules
to enable special options to optimize for ssd's.
But then complexity arises where for that to be useful a relation between disks, partitions and file systems has to be made, atleast from my current understanding. I'll leave this idea behind for now so i dont get stuck on this.
Moving on looking at the defintion for user(s), i stumble on a question
regarding "How much do i want to abstract?". Let's say i want to define a user
using config.my.users.<username> with options, that would basically be
re-impleming the existing users.users.<name>. Rendering it really just
useless.
So i will for now atleast not be doing this, ill simply implement a spesific
"hardcoded" implementation for titan and eventually expand config.my and/or
create modules as i see fit with the main purpose for the attributes under
config.my to answer this with yes:
Does it provide information to NixOS previously not known? , meaning my idea
about disks would be useful, but i just lack the knowledge to yet implementing
and structure it in a way that makese sense.
Atleast config.my.host feels like it belongs there as it gives NixOS
information it didnt have.
With time ive gained better undertstanding and a clearer view on what i want. The goals i want is also for other people than be to also be able to use the config and only need to essentially define their own host, set host spesific configurations then apply some predefined profiles (comming soon) that pre-configures modules
Meaning hosts//... would strictly be used for specifying host spesific details (like i can think of graphics card for now)