Files
2026-02-05 18:47:42 +00:00

297 lines
6.5 KiB
Markdown

---
title: Host Configuration Organization
impact: HIGH
impactDescription: Prevents configuration chaos across multiple hosts
tags: hosts,modules,base-config,directory-structure
---
## Why This Matters
Proper host configuration organization prevents duplication, makes maintenance easier, and ensures consistency across multiple machines.
## Directory Structure
```
nixos-config/
├── flake.nix # Top-level flake
├── hosts/
│ ├── laptop/
│ │ ├── default.nix # Host-specific config
│ │ ├── hardware-configuration.nix # Generated (don't edit)
│ │ └── home.nix # Home Manager config
│ ├── desktop/
│ │ ├── default.nix
│ │ ├── hardware-configuration.nix
│ │ └── home.nix
│ └── base.nix # Shared by all hosts (optional)
├── modules/ # Reusable NixOS modules
├── overlays/ # Custom overlays
├── home-manager/ # Shared Home Manager configs
│ ├── shell/
│ ├── applications/
│ └── common.nix
└── secrets/ # Age-encrypted secrets
```
## Host Configuration Pattern
### Incorrect: Everything in one file
```nix
# hosts/laptop/default.nix
{ config, pkgs, ... }:
{
# Hardware config (copied from hardware-configuration.nix)
boot.initrd.availableKernelModules = [ "xhci_pci" "nvme" "usb_storage" ];
# ... 50 lines of hardware config ...
# Network config
networking.hostName = "laptop";
networking.networkmanager.enable = true;
# User config
users.users.john = {
isNormalUser = true;
extraGroups = [ "wheel" "networkmanager" ];
};
# Packages
environment.systemPackages = with pkgs; [ vim git wget ];
# Services
services.openssh.enable = true;
# Home Manager
imports = [
./home.nix # Or inline the entire home config
];
}
```
**Problems:**
- Hardware config duplicated (should import hardware-configuration.nix)
- User config duplicated across hosts
- No shared configuration
- Hard to maintain
### Correct: Modular structure
```nix
# hosts/laptop/default.nix
{ inputs, pkgs, pkgs-stable, system, ... }:
{
imports = [
./hardware-configuration.nix # Import hardware config
../base.nix # Import shared config
inputs.home-manager.nixosModules.home-manager
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.users.john = import ./home.nix;
home-manager.extraSpecialArgs = {
inherit inputs pkgs-stable system;
};
nixpkgs.overlays = [ inputs.some-overlay.overlays.default ];
}
];
# Host-specific config only
networking.hostName = "laptop";
}
```
## Shared Base Configuration
```nix
# hosts/base.nix
{ config, pkgs, inputs, ... }:
{
# Network
networking.networkmanager.enable = true;
# Time and locale
time.timeZone = "America/New_York";
i18n.defaultLocale = "en_US.UTF-8";
# Users (shared across all hosts)
users.users.john = {
isNormalUser = true;
extraGroups = [ "wheel" "networkmanager" ];
};
# Common packages
environment.systemPackages = with pkgs; [
vim
git
wget
tmux
];
# Common services
services.openssh.enable = true;
# Nix settings
nix.settings.experimental-features = [ "nix-command" "flakes" ];
}
```
## Hardware Configuration
```nix
# hosts/laptop/default.nix
{ ... }:
{
imports = [
./hardware-configuration.nix # Generated by nixos-generate-config
../base.nix
# ...
];
networking.hostName = "laptop";
}
```
**Important:** Don't edit `hardware-configuration.nix` manually. It's generated by `nixos-generate-config` and should be replaced when hardware changes.
## Home Manager Configuration
### Host-specific home.nix
```nix
# hosts/laptop/home.nix
{ config, pkgs, inputs, ... }:
{
imports = [
../../home-manager/shell
../../home-manager/applications
../../home-manager/common.nix
];
# Host-specific user config
home.packages = with pkgs; [
laptop-specific-package
];
}
```
### Shared Home Manager configs
```nix
# home-manager/shell/default.nix
{ config, pkgs, ... }:
{
imports = [
./fish
./neovim
./git
];
}
# home-manager/common.nix
{ config, pkgs, ... }:
{
home.packages = with pkgs; [
jq
ripgrep
fzf
];
programs.git.enable = true;
programs.git.userName = "John Doe";
programs.git.userEmail = "john@example.com";
}
```
## Multiple Hosts Example
```nix
# flake.nix
outputs = { self, nixpkgs, home-manager, ... }@inputs: {
nixosConfigurations.laptop = nixpkgs.lib.nixosSystem {
specialArgs = { inherit inputs; };
modules = [ ./hosts/laptop ];
};
nixosConfigurations.desktop = nixpkgs.lib.nixosSystem {
specialArgs = { inherit inputs; };
modules = [ ./hosts/desktop ];
};
nixosConfigurations.server = nixpkgs.lib.nixosSystem {
specialArgs = { inherit inputs; };
modules = [ ./hosts/server ];
};
};
```
Each host uses the same `base.nix` but can override settings:
```nix
# hosts/server/default.nix
{ ... }:
{
imports = [ ../base.nix ./hardware-configuration.nix ];
# Override time zone for server
time.timeZone = "UTC";
# Add server-specific packages
environment.systemPackages = with pkgs; [
htop
iotop
];
}
```
## Module Pattern
For reusable functionality, create modules:
```nix
# modules/docker.nix
{ config, pkgs, ... }:
{
virtualisation.docker = {
enable = true;
enableOnBoot = true;
};
users.users.john.extraGroups = [ "docker" ];
}
```
Use in host config:
```nix
# hosts/laptop/default.nix
{ ... }:
{
imports = [
../base.nix
../../modules/docker # Import module
./hardware-configuration.nix
];
}
```
## Common Mistakes
1. **Editing hardware-configuration.nix**: Changes are lost when regenerating. Put host-specific config in `default.nix` instead.
2. **Duplicating config across hosts**: Use `base.nix` or modules for shared configuration.
3. **Not separating host-specific and user-specific**: Keep host config in `hosts/*/default.nix`, user config in `home.nix` or `home-manager/`.
4. **Mixing concerns**: Don't put shell config in system packages. Use Home Manager for user-level packages.
## Quick Checklist
- [ ] Each host imports hardware-configuration.nix
- [ ] Shared config in base.nix or modules
- [ ] Home Manager configured in host file
- [ ] Host-specific settings only in host's default.nix
- [ ] User config in home.nix or home-manager/
- [ ] No duplication of hardware config
- [ ] No duplication of user config