init by ai
This commit is contained in:
390
ARCHITECTURE.md
Normal file
390
ARCHITECTURE.md
Normal file
@@ -0,0 +1,390 @@
|
||||
# Architecture & Design Principles
|
||||
|
||||
An overview of how your portable NixOS configuration is structured and why.
|
||||
|
||||
## Core Design Goals
|
||||
|
||||
1. **Portability**: Deploy to new machines, existing NixOS, or non-NixOS with minimal effort
|
||||
2. **Modularity**: Enable/disable features independently without tight coupling
|
||||
3. **Reproducibility**: Flakes + lock files ensure identical environments across machines
|
||||
4. **Maintainability**: Clear separation of concerns (system vs home, shared vs per-machine)
|
||||
5. **Secrets Management**: Encrypted, portable secrets with sops-nix
|
||||
6. **Scalability**: Easy to add new machines and modules
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
```
|
||||
nix-los/
|
||||
├── flake.nix # Single source of truth for all configurations
|
||||
│ # Defines: inputs, outputs, configurations
|
||||
│
|
||||
├── hosts/ # Per-machine specific overrides
|
||||
│ ├── laptop/ # Machine-specific hardware, features
|
||||
│ └── server/ # (template for new machines)
|
||||
│
|
||||
├── nixos/ # System-level modules (NixOS only)
|
||||
│ ├── default.nix # Imports all modules
|
||||
│ └── modules/ # Toggleable features
|
||||
│ ├── system.nix # Users, sudo, locale
|
||||
│ ├── development.nix # Languages, tools
|
||||
│ ├── shell.nix # Shell config
|
||||
│ └── secrets-example.nix (inactive)
|
||||
│
|
||||
├── home/ # User-level configuration (portable)
|
||||
│ ├── default.nix # Imports all modules, can run standalone
|
||||
│ └── modules/ # User-level features
|
||||
│ ├── shell.nix # Zsh, direnv, starship
|
||||
│ ├── editor.nix # Neovim, VSCode
|
||||
│ ├── git.nix # Git configuration
|
||||
│ └── dev-tools.nix # Tmux, utilities
|
||||
│
|
||||
├── secrets/ # Encrypted credentials
|
||||
│ ├── .sops.yaml # Encryption keys (DO NOT COMMIT UNENCRYPTED)
|
||||
│ └── secrets.yaml # Encrypted secrets
|
||||
│
|
||||
├── flake.lock # Pinned versions (COMMIT THIS)
|
||||
└── docs/
|
||||
├── README.md # Getting started
|
||||
├── SETUP.md # Detailed setup instructions
|
||||
├── QUICKREF.md # Command reference
|
||||
├── CUSTOMIZATION.md # Extension patterns
|
||||
└── ARCHITECTURE.md # This file
|
||||
```
|
||||
|
||||
## Data Flow
|
||||
|
||||
### On a NixOS System
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ flake.nix (configuration) │
|
||||
│ - Defines all inputs (nixpkgs, etc) │
|
||||
│ - Specifies nixosConfigurations │
|
||||
└──────────────────┬──────────────────────┘
|
||||
│
|
||||
┌──────────┴──────────┬─────────────────┐
|
||||
│ │ │
|
||||
┌────▼────┐ ┌─────▼──────┐ ┌─────▼──────┐
|
||||
│ hosts/* │ │ nixos/* │ │ home/* │
|
||||
│(device) │ ──────► │(system cfg)│ │(user cfg) │
|
||||
└────┬────┘ └─────┬──────┘ └─────┬──────┘
|
||||
│ │ │
|
||||
└────────────────────┼─────────────────┘
|
||||
│
|
||||
┌────────────▼──────────────┐
|
||||
│ nixos-rebuild switch │
|
||||
│ (applies both system+home)│
|
||||
└───────────┬────────────────┘
|
||||
│
|
||||
┌───────────────────┴───────────────────┐
|
||||
│ │
|
||||
┌────▼──────────────┐ ┌──────────────▼─────┐
|
||||
│ NixOS System │ │ Home Manager │
|
||||
│ /etc/nixos/* │ │ ~/.config/* │
|
||||
│ Services, kernel │ │ Packages, dotfiles │
|
||||
└───────────────────┘ └────────────────────┘
|
||||
```
|
||||
|
||||
### On Non-NixOS System
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────┐
|
||||
│ flake.nix (homeConfigurations only) │
|
||||
└──────────────────┬───────────────────┘
|
||||
│
|
||||
┌──────────▼──────────────┐
|
||||
│ home/* (user config) │
|
||||
└──────────┬───────────────┘
|
||||
│
|
||||
┌──────────▼──────────────────┐
|
||||
│ home-manager switch --flake │
|
||||
└──────────┬───────────────────┘
|
||||
│
|
||||
┌──────────▼──────────────────┐
|
||||
│ Home Manager │
|
||||
│ ~/.config, ~/.local/share │
|
||||
│ Packages, dotfiles │
|
||||
└────────────────────────────┘
|
||||
```
|
||||
|
||||
## Module Design Pattern
|
||||
|
||||
Each module follows this pattern for maximum flexibility:
|
||||
|
||||
```nix
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
# 1. Define options (schema)
|
||||
options.custom.feature = {
|
||||
enable = lib.mkEnableOption "Feature";
|
||||
setting1 = lib.mkOption { /* ... */ };
|
||||
};
|
||||
|
||||
# 2. Conditionally implement
|
||||
config = let
|
||||
cfg = config.custom.feature;
|
||||
in lib.mkIf cfg.enable {
|
||||
# Implementation here
|
||||
environment.systemPackages = [ /* ... */ ];
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
**Why this pattern:**
|
||||
- ✅ **Declarative**: Clear what can be configured
|
||||
- ✅ **Composable**: Modules don't interfere
|
||||
- ✅ **Overridable**: Host can override any setting
|
||||
- ✅ **Conditional**: Only included when enabled
|
||||
|
||||
## Separation of Concerns
|
||||
|
||||
### System Level (nixos/) - Run once, affects all users
|
||||
|
||||
- OS-level packages (compilers, tools)
|
||||
- Services (SSH, web servers)
|
||||
- Bootloader, kernel, hardware
|
||||
- User creation and permissions
|
||||
- Firewall, networking
|
||||
- System-wide environment variables
|
||||
|
||||
**When to put config here:**
|
||||
- Affects the entire system
|
||||
- Required by multiple users
|
||||
- Needs root/sudo privileges
|
||||
|
||||
### User Level (home/) - Per-user, portable
|
||||
|
||||
- Shell configuration and aliases
|
||||
- Editor settings and plugins
|
||||
- User-installed packages
|
||||
- Dotfiles (~/.config/*)
|
||||
- Environment variables (user-specific)
|
||||
- Git, SSH client configuration
|
||||
|
||||
**When to put config here:**
|
||||
- Only one user needs it
|
||||
- Doesn't require system privileges
|
||||
- Configurable per-user
|
||||
- Want to port to non-NixOS systems
|
||||
|
||||
## Configuration Hierarchy
|
||||
|
||||
Settings are applied in this order (later overrides earlier):
|
||||
|
||||
1. **nixos/default.nix** - Base system defaults
|
||||
2. **nixos/modules/*.nix** - System feature modules
|
||||
3. **hosts/hostname/default.nix** - Machine-specific overrides
|
||||
4. **home/default.nix** - User base defaults
|
||||
5. **home/modules/*.nix** - User feature modules
|
||||
|
||||
Example with `custom.development.languages`:
|
||||
|
||||
```nix
|
||||
# Start: undefined
|
||||
|
||||
# nixos/modules/development.nix:
|
||||
# options.custom.development.languages = lib.mkOption { default = []; ... };
|
||||
|
||||
# hosts/laptop/default.nix:
|
||||
custom.development.languages = [ "rust" "python" ]; # Override
|
||||
|
||||
# Result: [ "rust" "python" ]
|
||||
```
|
||||
|
||||
## Flakes Architecture
|
||||
|
||||
### Inputs (Dependencies)
|
||||
|
||||
```nix
|
||||
inputs = {
|
||||
nixpkgs = "..."; # Stable packages
|
||||
nixpkgs-unstable = "..."; # Cutting-edge packages
|
||||
home-manager = "..."; # User config management
|
||||
sops-nix = "..."; # Secrets management
|
||||
disko = "..."; # Disk partitioning
|
||||
};
|
||||
```
|
||||
|
||||
**Why these inputs:**
|
||||
- **nixpkgs + unstable**: Mix stable (secure) with latest (features)
|
||||
- **home-manager**: User config separate from system
|
||||
- **sops-nix**: Encrypted secrets, portable
|
||||
- **disko**: Declarative disk setup for new machines
|
||||
|
||||
### Outputs (What's available)
|
||||
|
||||
```nix
|
||||
outputs = {
|
||||
nixosConfigurations = {
|
||||
laptop = nixosSystem { ... }; # Full system config
|
||||
server = nixosSystem { ... };
|
||||
};
|
||||
homeConfigurations = {
|
||||
"myuser@linux" = homeManagerConfiguration { ... }; # Standalone HM
|
||||
};
|
||||
devShells = {
|
||||
default = mkShell { ... }; # Development environment
|
||||
};
|
||||
apps = {
|
||||
installer = { ... }; # Bootstrap helper
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Secrets Flow
|
||||
|
||||
```
|
||||
secrets/
|
||||
├── .sops.yaml # Key configuration (WHO can decrypt)
|
||||
└── secrets.yaml (encrypted)
|
||||
│
|
||||
├─ SSH keys
|
||||
├─ API tokens
|
||||
└─ Passwords
|
||||
|
||||
When applied:
|
||||
│
|
||||
▼
|
||||
Sops decrypts (using ~/.config/sops/age/keys.txt)
|
||||
│
|
||||
▼
|
||||
sops.secrets.* paths available in Nix
|
||||
│
|
||||
▼
|
||||
Placed in /run/secrets/* at boot
|
||||
│
|
||||
▼
|
||||
Referenced in system/home config
|
||||
```
|
||||
|
||||
**Key insight**: Secrets are encrypted on disk, decrypted at boot, never stored in nix store in plaintext.
|
||||
|
||||
## Multi-Machine Scaling
|
||||
|
||||
To support N machines:
|
||||
|
||||
1. Add new host in `hosts/newhost/default.nix`
|
||||
2. Register in `flake.nix` under `nixosConfigurations.newhost`
|
||||
3. Deploy with: `sudo nixos-rebuild switch --flake .#newhost`
|
||||
|
||||
Each machine:
|
||||
- Shares `nixos/` modules
|
||||
- Shares `home/` modules
|
||||
- Has unique `hosts/` overrides
|
||||
- Uses same `secrets.yaml` (all machines can decrypt)
|
||||
|
||||
```
|
||||
Common Base Per-Machine Override
|
||||
───────────── ──────────────────
|
||||
nixos/default.nix → hosts/laptop/default.nix
|
||||
nixos/modules/ → (machine-specific features)
|
||||
home/modules/ → (shared everywhere)
|
||||
```
|
||||
|
||||
## Update Strategy
|
||||
|
||||
```
|
||||
Stable ← └─ Pinned via flake.lock
|
||||
│
|
||||
├─ Low risk, predictable
|
||||
└─ Most system components
|
||||
|
||||
Unstable → Override in modules when needed
|
||||
│
|
||||
├─ Fast-moving
|
||||
└─ For specific packages (bleeding edge editor, tools)
|
||||
```
|
||||
|
||||
Update process:
|
||||
```bash
|
||||
# Pin current state
|
||||
git commit flake.lock
|
||||
|
||||
# Update specific input
|
||||
nix flake update nixpkgs
|
||||
|
||||
# Test
|
||||
sudo nixos-rebuild test --flake .#laptop
|
||||
|
||||
# Deploy
|
||||
sudo nixos-rebuild switch --flake .#laptop
|
||||
|
||||
# Save new state
|
||||
git commit flake.lock
|
||||
```
|
||||
|
||||
## Extension Points
|
||||
|
||||
### Add Feature: Create a new module
|
||||
|
||||
1. Create `nixos/modules/myfeature.nix` or `home/modules/myfeature.nix`
|
||||
2. Follow module pattern (options + config)
|
||||
3. Import in `nixos/default.nix` or `home/default.nix`
|
||||
4. Enable in host config: `custom.myfeature.enable = true`
|
||||
|
||||
### Add Machine: Copy host template
|
||||
|
||||
1. Create `hosts/newmachine/default.nix`
|
||||
2. Customize for that machine
|
||||
3. Add to `flake.nix` under `nixosConfigurations`
|
||||
4. Deploy with `sudo nixos-rebuild switch --flake .#newmachine`
|
||||
|
||||
### Add Dependency: Update flake inputs
|
||||
|
||||
1. Edit `flake.nix` inputs section
|
||||
2. Run `nix flake update`
|
||||
3. Commit `flake.lock`
|
||||
|
||||
### Add Secret: Edit secrets.yaml
|
||||
|
||||
1. Run `sops secrets/secrets.yaml`
|
||||
2. Add key-value pair
|
||||
3. Reference in module with `config.sops.secrets."key".path`
|
||||
|
||||
## Testing & Safety
|
||||
|
||||
### Before Deploying
|
||||
|
||||
```bash
|
||||
nix flake check # Syntax validation
|
||||
nix flake show # Check all outputs
|
||||
sudo nixos-rebuild test # Build without activating
|
||||
```
|
||||
|
||||
### Rollback if Issues
|
||||
|
||||
```bash
|
||||
# NixOS (automatic previous generation)
|
||||
sudo nixos-rebuild --rollback switch
|
||||
|
||||
# Home Manager (manual)
|
||||
home-manager switch --flake .#myuser@linux ~/.local/state/home-manager/previous
|
||||
```
|
||||
|
||||
### Validate Changes
|
||||
|
||||
```bash
|
||||
# What changed?
|
||||
sudo nixos-rebuild diff --flake .#laptop
|
||||
|
||||
# What will happen?
|
||||
sudo nixos-rebuild test --flake .#laptop
|
||||
|
||||
# Apply
|
||||
sudo nixos-rebuild switch --flake .#laptop
|
||||
```
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
- **Flakes**: Slow evaluation (1-2 seconds) but reproducible
|
||||
- **Modularity**: More files but faster edits
|
||||
- **Secrets**: Decryption only at boot (fast)
|
||||
- **Unstable**: More binary cache misses (compilation time)
|
||||
|
||||
## See Also
|
||||
|
||||
- **README.md** - Getting started
|
||||
- **SETUP.md** - Step-by-step installation
|
||||
- **QUICKREF.md** - Common commands
|
||||
- **CUSTOMIZATION.md** - Extension patterns
|
||||
Reference in New Issue
Block a user