Configuration for my NixOS based systems and Home Manager
1# NixOS + Home Manager Configuration
2
3This repository contains my personal NixOS system configurations and Home Manager setup, managed via Nix flakes.
4
5## Overview
6
7This is a multi-host NixOS configuration using:
8- **Nix Flakes** for reproducible builds and dependency management
9- **Home Manager** for user environment configuration
10- **agenix** for secrets management (age-based encryption)
11- **pre-commit-hooks** for code quality
12
13## Hosts
14
15| Hostname | Purpose | Platform |
16|----------|---------|----------|
17| **odin** | Main workstation with AMD GPU, Docker, Coder server, Valheim game server | x86_64-linux |
18| **misaki** | NAS/Server with ZFS, Plex, Jellyfin, Immich, Nginx reverse proxy | x86_64-linux |
19| **shizuri** | Steam/gaming machine with LXQt desktop and XRDP | x86_64-linux |
20| **touma-wsl** | WSL2 NixOS configuration | x86_64-linux |
21| **aleister-noah** | macOS workstation (Home Manager only) | aarch64-darwin |
22
23## Repository Structure
24
25```
26.
27├── flake.nix # Main flake configuration defining all hosts
28├── flake.lock # Lock file for reproducible builds
29├── shell.nix # Development shell configuration
30├── boot.nix # Bootloader configuration (shared)
31├── common.nix # Common system settings (timezone, locale, gc, etc.)
32├── users.nix # User definitions and SSH keys
33├── services.nix # Shared service configurations
34├── default-home.nix # Default Home Manager configuration
35├── host-specific/ # Per-host configurations
36│ ├── odin/
37│ ├── misaki/
38│ ├── shizuri/
39│ └── touma-wsl.nix
40├── overlays/ # Package overlays
41├── secrets/ # Encrypted secrets (agenix)
42├── nvim/ # Neovim configuration
43├── fish/ # Fish shell configuration
44├── aerc/ # aerc email client configuration
45├── scripts/ # Custom utility scripts
46└── README.md # This file
47```
48
49## Host Configuration Pattern
50
51Each host in `host-specific/<hostname>/` follows a modular structure:
52- `configuration.nix` - Main entry point, imports other modules
53- `hardware-configuration.nix` - Auto-generated hardware config
54- `boot.nix` - Bootloader and kernel settings
55- `networking.nix` - Network configuration
56- `packages.nix` - System packages
57- `services.nix` - Service definitions
58- `gui.nix` - GUI/Desktop environment settings (where applicable)
59- `users.nix` - Host-specific users and groups
60
61## Adding a New Host
62
631. Create a new directory under `host-specific/<hostname>/`
642. Copy the hardware configuration from the target machine:
65 ```bash
66 nixos-generate-config --show-hardware-config > host-specific/<hostname>/hardware-configuration.nix
67 ```
683. Create `configuration.nix` importing necessary modules
694. Add the host to `flake.nix` in the `nixosConfigurations` output:
70 ```nix
71 nixosConfigurations.newhost = basicSystem {
72 useUnstable = true;
73 modules = [
74 ./host-specific/newhost/configuration.nix
75 ];
76 };
77 ```
785. Build and switch:
79 ```bash
80 sudo nixos-rebuild switch --flake .#newhost
81 ```
82
83## Secrets Management
84
85Secrets are encrypted using [agenix](https://github.com/ryantm/agenix) with age encryption.
86
87- Secrets are stored in `secrets/` with `.age` extension
88- Public keys for hosts/users are defined in `secrets/secrets.nix`
89- Each secret specifies which hosts/users can decrypt it
90- Deployed secrets are owned by specific users/groups with appropriate permissions
91
92To add a new secret:
931. Add the secret file to `secrets/`
942. Define recipients in `secrets/secrets.nix`
953. Encrypt: `agenix -e secrets/my-secret.age`
964. Reference in your configuration via `age.secrets.my-secret`
97
98## Development
99
100This repo includes a development shell with formatting and linting tools:
101
102```bash
103nix develop
104```
105
106Pre-commit hooks are configured to run automatically on commit:
107- `nixfmt-rfc-style` - Nix code formatting
108- `nil` - Nix language server / linter
109- `luacheck` - Lua linting (for Neovim config)
110
111## Key Features
112
113### Overlays
114- `neovim.nix` - Pins Neovim to specific version
115- `lmstudio.nix` - Local LLM GUI (AppImage wrapper)
116- `inetutils.nix` - Version override for inetutils
117
118### Home Manager
119The `default-home.nix` provides a comprehensive development environment including:
120- Neovim with extensive LSP and plugin configuration
121- Fish shell with custom configuration
122- Multiple language toolchains (Rust, Go, Clojure, Python, etc.)
123- Git configuration with delta/difftastic
124- Development tools (direnv, fzf, tmux, etc.)
125
126## Building
127
128### NixOS System
129```bash
130sudo nixos-rebuild switch --flake .#<hostname>
131```
132
133### Home Manager (standalone)
134```bash
135home-manager switch --flake .#noah
136# or for macOS
137home-manager switch --flake .#noah-aleister
138```
139
140### Remote Builders
141
142`shizuri` and `odin` are configured as trusted `x86_64-linux` Nix remote builders. Client hosts import `modules/nix-remote-builders.nix` through `common.nix`, so NixOS hosts in this flake will try to use both builders except for the current host itself.
143
144Builder access uses the `nixremote` user declared in `modules/nix-builder.nix`. Client private keys live at `/root/.ssh/nix-remote-builder`; their public keys are declared in `users.users.nixremote.openssh.authorizedKeys.keys`.
145
146#### Add client access
147
148On the client, generate the key and print its public half:
149
150```bash
151sudo install -d -m 700 /root/.ssh
152sudo ssh-keygen -t ed25519 -N '' -C "nix-remote-builder@$(hostname)" -f /root/.ssh/nix-remote-builder
153sudo cat /root/.ssh/nix-remote-builder.pub
154```
155
156Add the public key to `modules/nix-builder.nix`, then rebuild the builders once:
157
158```bash
159sudo nixos-rebuild switch --flake .#shizuri
160sudo nixos-rebuild switch --flake .#odin
161```
162
163Trust builder host keys on the client:
164
165```bash
166sudo ssh-keyscan -H shizuri odin | sudo tee -a /root/.ssh/known_hosts >/dev/null
167```
168
169#### NixOS clients
170
171NixOS hosts in this flake already import the remote builder config through `common.nix`. After adding client access, rebuild the client:
172
173```bash
174sudo nixos-rebuild switch --flake .#<client-hostname>
175```
176
177Smoke test:
178
179```bash
180sudo ssh -i /root/.ssh/nix-remote-builder nixremote@shizuri nix-store --version
181sudo ssh -i /root/.ssh/nix-remote-builder nixremote@odin nix-store --version
182sudo nix build nixpkgs#hello --max-jobs 0 -L
183```
184
185#### Standalone Home Manager clients
186
187Standalone Home Manager uses the host's Nix daemon. After adding client access, put the builder list in `/etc/nix/nix.conf`:
188
189```conf
190experimental-features = nix-command flakes
191builders-use-substitutes = true
192builders = ssh-ng://nixremote@shizuri x86_64-linux /root/.ssh/nix-remote-builder 24 4 nixos-test,benchmark,big-parallel,kvm - ; ssh-ng://nixremote@odin x86_64-linux /root/.ssh/nix-remote-builder 24 4 nixos-test,benchmark,big-parallel,kvm -
193```
194
195Restart the daemon and run Home Manager:
196
197```bash
198sudo systemctl restart nix-daemon
199home-manager switch --flake .#noah
200```
201
202Linux builders cannot build normal Darwin outputs; `homeConfigurations.noah-aleister` needs Darwin builders.
203
204#### Set up a new build host
205
206Import `modules/nix-builder.nix` from the new host configuration:
207
208```nix
209{
210 imports = [
211 ../../modules/nix-builder.nix
212 ];
213}
214```
215
216Add a matching entry to the `builders` list in `modules/nix-remote-builders.nix`.
217
218Rebuild the new builder first, then rebuild each client that should use it:
219
220```bash
221sudo nixos-rebuild switch --flake .#new-builder
222sudo ssh-keyscan -H new-builder | sudo tee -a /root/.ssh/known_hosts >/dev/null
223sudo nixos-rebuild switch --flake .#<client-hostname>
224```
225
226## Maintenance
227
228Regular maintenance tasks:
229- Update flakes: `nix flake update`
230- Garbage collect: `nix-collect-garbage -d` (also automatic via `common.nix`)
231- Check configuration: `nix flake check`
232
233## License
234
235This configuration is personal and not licensed for redistribution.