stt, mem0, rofi-project-opener
This commit is contained in:
382
AGENTS.md
382
AGENTS.md
@@ -1,283 +1,157 @@
|
||||
# AGENTS.md - NixOS Configuration Repository
|
||||
# NIXOS CONFIGURATION KNOWLEDGE BASE
|
||||
|
||||
**Generated:** 2025-12-29 | **Branch:** master | **Commit:** 460fc92
|
||||
**Generated:** 2025-12-31 16:13:40 UTC
|
||||
**Commit:** ebc8291
|
||||
**Branch:** HEAD
|
||||
|
||||
Multi-host NixOS flake managing servers and workstations with home-manager integration.
|
||||
## OVERVIEW
|
||||
Personal NixOS configuration managing 6 hosts (4 servers, 2 desktops) using flakes, agenix secrets, and feature-based home-manager setup.
|
||||
|
||||
## Host Inventory
|
||||
|
||||
| Host | Type | Purpose | Key Services |
|
||||
|------|------|---------|--------------|
|
||||
| m3-atlas | VPS | Main server | Traefik, containers (n8n, ghost, baserow, vaultwarden, paperless, gitea) |
|
||||
| m3-helios | VPS | DNS/Dashboard | AdGuard Home, Homarr, Traefik |
|
||||
| m3-ares | Workstation | Desktop | WireGuard VPN, Tailscale, sound, podman |
|
||||
| m3-kratos | Workstation | Desktop | WireGuard VPN, Tailscale, Hyprland, gaming |
|
||||
| m3-aether | VM | Cloud-init | Minimal config |
|
||||
| m3-daedalus | - | Home-manager only | Desktop environment (no NixOS config) |
|
||||
|
||||
## Key Inputs
|
||||
|
||||
nixpkgs (unstable), nixpkgs-stable (25.05), home-manager, agenix, disko, nix-colors, m3ta-nixpkgs (private fork)
|
||||
|
||||
## Build/Rebuild Commands
|
||||
|
||||
```bash
|
||||
# NixOS system rebuild
|
||||
sudo nixos-rebuild switch --flake .#<hostname>
|
||||
sudo nixos-rebuild switch --flake .#m3-atlas
|
||||
|
||||
# Home-manager rebuild
|
||||
home-manager --flake . switch
|
||||
home-manager --flake .#m3tam3re@m3-daedalus switch
|
||||
|
||||
# Flake operations
|
||||
nix flake check # Validate flake
|
||||
nix flake update # Update all inputs
|
||||
nix flake lock --update-input <name> # Update single input
|
||||
|
||||
# Development shell
|
||||
nix develop .#infraShell # OpenTofu + nixos-anywhere
|
||||
|
||||
# Format Nix files
|
||||
alejandra . # Format all .nix files
|
||||
alejandra <file.nix> # Format single file
|
||||
## STRUCTURE
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
No formal test suite. Verification is done via:
|
||||
```bash
|
||||
nix flake check # Syntax and evaluation check
|
||||
nix build .#nixosConfigurations.<host>.config.system.build.toplevel --dry-run
|
||||
```
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
.
|
||||
├── flake.nix # Flake definition with all hosts
|
||||
./
|
||||
├── flake.nix # Main entry: host definitions, inputs, outputs
|
||||
├── secrets.nix # Agenix public key mappings
|
||||
├── home/
|
||||
│ ├── common/ # Shared home-manager config (overlays, nix settings)
|
||||
│ ├── features/ # Modular features
|
||||
│ │ ├── cli/ # Shell tools (fish, nushell, starship, zellij)
|
||||
│ │ ├── coding/ # Development tools
|
||||
│ │ └── desktop/ # GUI apps, Hyprland, theming
|
||||
│ └── m3tam3re/ # Per-host user configs
|
||||
├── hosts/
|
||||
│ ├── common/ # Shared NixOS config
|
||||
│ │ ├── extraServices/ # Toggle-able services (ollama, podman, flatpak)
|
||||
│ │ ├── users/ # User definitions
|
||||
│ │ └── ports.nix # Port allocations
|
||||
│ └── m3-*/ # Host-specific configs
|
||||
│ ├── default.nix # Entry point (imports common + host modules)
|
||||
│ ├── configuration.nix # Core system config
|
||||
│ ├── hardware-configuration.nix
|
||||
│ ├── programs.nix # Host-specific programs
|
||||
│ ├── secrets.nix # Agenix secret declarations
|
||||
│ └── services/ # Service configurations
|
||||
│ └── containers/ # OCI container definitions
|
||||
│ ├── common/ # Shared: base config, users, extraServices, ports
|
||||
│ ├── m3-atlas/ # Server: 20+ containerized services with Traefik
|
||||
│ ├── m3-helios/ # Server: AdGuard, internal routing
|
||||
│ ├── m3-ares/ # Desktop: NVIDIA GPU, Btrfs
|
||||
│ ├── m3-kratos/ # Desktop: AMD GPU, ZFS
|
||||
│ └── m3-aether/ # Cloud VM
|
||||
├── home/
|
||||
│ ├── common/ # Home-manager base config
|
||||
│ ├── features/ # Modular feature toggles (cli, desktop, coding)
|
||||
│ └── m3tam3re/ # Per-host user configs
|
||||
├── modules/ # Custom NixOS/home-manager modules
|
||||
├── overlays/ # Nixpkgs overlays (stable, locked, pinned, master)
|
||||
├── overlays/ # Package overlays (stable, locked, pinned, master)
|
||||
├── pkgs/ # Custom package definitions
|
||||
└── secrets/ # Encrypted .age files
|
||||
└── secrets/ # Agenix encrypted .age files (19 secrets)
|
||||
```
|
||||
|
||||
## Code Style Guidelines
|
||||
## WHERE TO LOOK
|
||||
|
||||
### Module Pattern
|
||||
| Task | Location | Notes |
|
||||
|------|----------|-------|
|
||||
| Add new host | `flake.nix` + `hosts/<name>/` | Copy template from m3-atlas (server) or m3-ares (desktop) |
|
||||
| Add service to m3-atlas | `hosts/m3-atlas/services/` | See containers/ for Podman + Traefik pattern |
|
||||
| Configure desktop features | `home/features/desktop/` | Feature toggles with mkEnableOption |
|
||||
| Add CLI tool | `home/features/cli/` | Fish + Nushell integration expected |
|
||||
| Manage secrets | `secrets.nix` + `agenix -e` | SSH keys defined in secrets.nix |
|
||||
| Define ports | `hosts/common/ports.nix` | Centralized port registry |
|
||||
| Add user | `hosts/common/users/` | Shared across all hosts |
|
||||
| Custom packages | `pkgs/default.nix` | Exposed via flake outputs |
|
||||
|
||||
Standard Nix module structure:
|
||||
```nix
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
imports = [
|
||||
./submodule.nix
|
||||
];
|
||||
## CONVENTIONS
|
||||
|
||||
# Configuration here
|
||||
}
|
||||
### Secrets (agenix)
|
||||
- **Create**: `agenix -e secrets/<name>.age` after adding keys to `secrets.nix`
|
||||
- **Reference**: `config.age.secrets.<name>.path` in service configs
|
||||
- **Pattern**: Service env files use `environmentFiles = [config.age.secrets.<service>-env.path]`
|
||||
|
||||
### Service Organization
|
||||
- **Native services**: `hosts/<host>/services/<service>.nix`
|
||||
- **Containers**: `hosts/<host>/services/containers/<service>.nix`
|
||||
- **Traefik integration**: All m3-atlas services include dynamic config for SSL + routing
|
||||
- **Networking**: Containers use dedicated `web` network (10.89.0.0/24) with static IPs
|
||||
|
||||
### Port Management
|
||||
- **Registry**: All ports defined in `hosts/common/ports.nix`
|
||||
- **Access**: `config.m3ta.ports.get "service-name"`
|
||||
- **Convention**: Internal services use 3000-3020 range
|
||||
|
||||
### Home-Manager Features
|
||||
- **Enable**: `features.<category>.<feature>.enable = true` in user config
|
||||
- **Categories**: `cli`, `desktop`, `coding`
|
||||
- **Pattern**: Features are opt-in modules with default.nix aggregators
|
||||
|
||||
### Multiple nixpkgs Inputs
|
||||
- **stable**: 25.11 release
|
||||
- **locked/pinned**: Specific commits for compatibility
|
||||
- **master**: Bleeding edge
|
||||
- **m3ta-nixpkgs**: Custom local overlay at `path:/home/m3tam3re/p/nix/nixpkgs`
|
||||
|
||||
## COMMANDS
|
||||
```bash
|
||||
# Build/deploy specific host
|
||||
sudo nixos-rebuild switch --flake .#m3-ares
|
||||
|
||||
# Build/deploy current host
|
||||
sudo nixos-rebuild switch --flake .#$(uname -n)
|
||||
|
||||
# Home-manager update
|
||||
home-manager --flake . switch
|
||||
|
||||
# Update all flake inputs
|
||||
nix flake update
|
||||
|
||||
# Add/edit secret
|
||||
agenix -e secrets/<name>.age
|
||||
|
||||
# Infrastructure shell (OpenTofu)
|
||||
nix develop .#infraShell
|
||||
|
||||
# Check configuration (no activation)
|
||||
nixos-rebuild dry-build --flake .#<hostname>
|
||||
```
|
||||
|
||||
### Formatting
|
||||
## TRAEFIK PATTERNS (m3-atlas only)
|
||||
|
||||
- **Formatter**: Use `alejandra` (included in CLI packages)
|
||||
- **Indentation**: 2 spaces
|
||||
- **Line length**: No strict limit, but keep readable
|
||||
- **Trailing commas**: Required in lists and attrsets
|
||||
- **Semicolons**: Required after each attribute
|
||||
### SSL Termination
|
||||
- **Provider**: Godaddy DNS challenge
|
||||
- **Cert storage**: `/var/lib/traefik/acme.json`
|
||||
- **Config**: `hosts/m3-atlas/services/traefik.nix`
|
||||
|
||||
### Naming Conventions
|
||||
|
||||
| Type | Convention | Example |
|
||||
|------|------------|---------|
|
||||
| Files | lowercase, hyphenated | `hardware-configuration.nix` |
|
||||
| Hosts | `m3-<name>` | `m3-atlas`, `m3-kratos` |
|
||||
| Options | camelCase path | `extraServices.ollama.enable` |
|
||||
| Feature flags | `features.<category>.<name>.enable` | `features.cli.nushell.enable` |
|
||||
| Secrets | `<service>-env.age` or descriptive | `n8n-env.age`, `wg-DE.age` |
|
||||
|
||||
### Option Definitions
|
||||
|
||||
Use lib functions for custom options:
|
||||
### Service Integration Template
|
||||
```nix
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
with lib; let
|
||||
cfg = config.features.cli.myFeature;
|
||||
in {
|
||||
options.features.cli.myFeature.enable = mkEnableOption "enable myFeature";
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# Configuration when enabled
|
||||
services.traefik.dynamicConfigOptions.http = {
|
||||
services.<name>.loadBalancer.servers = [{ url = "http://127.0.0.1:<port>"; }];
|
||||
routers.<name> = {
|
||||
rule = "Host(`<subdomain>.m3ta.dev`)";
|
||||
service = "<name>";
|
||||
tls.certResolver = "godaddy";
|
||||
};
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### Imports
|
||||
### Container Pattern
|
||||
- **Network**: `--network=web --ip=10.89.0.<sequential>`
|
||||
- **Ports**: Bind localhost only (`127.0.0.1:<external>:<internal>`)
|
||||
- **Database access**: `--add-host=mysql:10.89.0.1` (gateway IP)
|
||||
|
||||
- Import order: inputs/modules first, then local files
|
||||
- Use relative paths: `./subdir` or `../common`
|
||||
- Group related imports together
|
||||
## HOST ROLES
|
||||
|
||||
### Package Lists
|
||||
| Host | Type | Hardware | Purpose |
|
||||
|------|------|----------|---------|
|
||||
| m3-atlas | Server | x86_64, disko | 20+ services, Traefik hub, PostgreSQL, MySQL |
|
||||
| m3-helios | Server | x86_64, disko | AdGuard DNS, internal routing |
|
||||
| m3-ares | Desktop | NVIDIA, Btrfs | Personal workstation, n8n, PostgreSQL |
|
||||
| m3-kratos | Desktop | AMD, ZFS | Workstation, mem0, PostgreSQL |
|
||||
| m3-aether | Cloud | QEMU | General purpose VM |
|
||||
| m3-daedalus | Laptop | home-only | Portable (no full NixOS config) |
|
||||
|
||||
```nix
|
||||
home.packages = with pkgs; [
|
||||
package1
|
||||
package2
|
||||
# Commented packages for reference
|
||||
# disabled-package
|
||||
];
|
||||
```
|
||||
## ANTI-PATTERNS (THIS PROJECT)
|
||||
|
||||
## Secrets Management
|
||||
- **DON'T** add secrets to `secrets/` without updating `secrets.nix` public keys
|
||||
- **DON'T** hardcode ports - use `config.m3ta.ports.get` or add to registry
|
||||
- **DON'T** create containers outside the `web` network on m3-atlas
|
||||
- **DON'T** skip Traefik config for public-facing services on m3-atlas
|
||||
- **DON'T** bypass extraServices flags - use `hosts/common/extraServices/` pattern
|
||||
- **DON'T** commit unencrypted secrets or test with real credentials
|
||||
|
||||
Uses **agenix** for encrypted secrets.
|
||||
## UNIQUE TO THIS CONFIG
|
||||
|
||||
### Adding a New Secret
|
||||
- **Custom m3ta-nixpkgs**: Local overlay for unreleased/patched packages
|
||||
- **extraServices abstraction**: Boolean flags to toggle Podman, Ollama, virtualisation per host
|
||||
- **Mythological naming**: All hosts named after Greek mythology
|
||||
- **Dual domain strategy**: New services on `m3ta.dev`, legacy redirects from `m3tam3re.com`
|
||||
- **Per-host nixpkgs versions**: Different hosts can use different nixpkgs commits via specialArgs
|
||||
- **Container IP registry**: Static IP assignments in 10.89.0.0/24 subnet for predictable networking
|
||||
|
||||
1. Create the secret file:
|
||||
```bash
|
||||
agenix -e secrets/my-secret.age
|
||||
```
|
||||
## NOTES
|
||||
|
||||
2. Register in `secrets.nix`:
|
||||
```nix
|
||||
"secrets/my-secret.age".publicKeys = systems ++ users;
|
||||
```
|
||||
|
||||
3. Declare in host's `secrets.nix`:
|
||||
```nix
|
||||
age.secrets.my-secret = {
|
||||
file = ../../secrets/my-secret.age;
|
||||
owner = "service-user"; # Optional
|
||||
mode = "644"; # Optional
|
||||
};
|
||||
```
|
||||
|
||||
4. Reference in config:
|
||||
```nix
|
||||
environmentFiles = [config.age.secrets.my-secret.path];
|
||||
```
|
||||
|
||||
## Container Services Pattern
|
||||
|
||||
OCI containers via podman:
|
||||
```nix
|
||||
{config, ...}: {
|
||||
virtualisation.oci-containers.containers."service-name" = {
|
||||
image = "registry/image:tag";
|
||||
environmentFiles = [config.age.secrets.service-env.path];
|
||||
ports = ["127.0.0.1:8080:8080"];
|
||||
volumes = ["service_data:/data"];
|
||||
extraOptions = ["--network=web"];
|
||||
};
|
||||
|
||||
# Traefik routing
|
||||
services.traefik.dynamicConfigOptions.http = {
|
||||
services.service-name.loadBalancer.servers = [
|
||||
{ url = "http://localhost:8080/"; }
|
||||
];
|
||||
routers.service-name = {
|
||||
rule = "Host(`service.domain.com`)";
|
||||
tls.certResolver = "godaddy";
|
||||
service = "service-name";
|
||||
entrypoints = "websecure";
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Theming
|
||||
|
||||
Uses **nix-colors** with Dracula scheme:
|
||||
```nix
|
||||
colorScheme = inputs.nix-colors.colorSchemes.dracula;
|
||||
|
||||
# Reference colors
|
||||
"#${config.colorScheme.palette.base00}" # Background
|
||||
"#${config.colorScheme.palette.base05}" # Foreground
|
||||
```
|
||||
|
||||
## Overlays
|
||||
|
||||
Custom overlays in `overlays/default.nix`:
|
||||
- `stable-packages`: nixpkgs-stable as `pkgs.stable.*`
|
||||
- `locked-packages`: Pinned nixpkgs as `pkgs.locked.*`
|
||||
- `master-packages`: nixpkgs-master as `pkgs.master.*`
|
||||
|
||||
Use when you need a specific package version:
|
||||
```nix
|
||||
home.packages = [ pkgs.stable.somePackage ];
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
1. **Missing imports**: Ensure new files are imported in parent `default.nix`
|
||||
2. **Secret paths**: Use `config.age.secrets.<name>.path`, not hardcoded paths
|
||||
3. **Rebuild required**: Changes need `nixos-rebuild` or `home-manager switch`
|
||||
4. **Overlay scope**: Overlays must be added to both `home/common` and `hosts/common`
|
||||
5. **Port conflicts**: Check `hosts/common/ports.nix` before allocating new ports
|
||||
|
||||
## Commit Style
|
||||
|
||||
Short, descriptive messages:
|
||||
- `flake update` - Dependency updates
|
||||
- `+package` - Adding new package
|
||||
- `service-name: description` - Service changes
|
||||
- `host: description` - Host-specific changes
|
||||
|
||||
## Container IP Registry (m3-atlas)
|
||||
|
||||
Network: `10.89.0.0/24`, Gateway: `10.89.0.1` (postgres host)
|
||||
|
||||
| Service | IP | Port |
|
||||
|---------|-----|------|
|
||||
| baserow | 10.89.0.4 | 3001 |
|
||||
| ghost | 10.89.0.10 | 3002 |
|
||||
| slash | 10.89.0.11 | 3010 |
|
||||
| littlelink | 10.89.0.13 | 3004 |
|
||||
| n8n | 10.89.0.14 | 5678 |
|
||||
| restreamer | 10.89.0.15 | 3006 |
|
||||
| kestra | 10.89.0.17 | 3018 |
|
||||
| pangolin | 10.89.0.20 | 3020 |
|
||||
|
||||
**Next available IP**: 10.89.0.22
|
||||
|
||||
## Feature Flags
|
||||
|
||||
Home-manager features use `mkEnableOption` pattern:
|
||||
- `features.cli.*` - Shell tools (nushell, fzf, nitch, starship, secrets)
|
||||
- `features.desktop.*` - GUI apps (crypto, coding, gaming, hyprland, media, office, rofi, fonts, wayland)
|
||||
- `extraServices.*` - NixOS services (ollama, podman, flatpak, virtualisation)
|
||||
|
||||
Enable in per-host configs: `features.cli.nushell.enable = true;`
|
||||
- m3-atlas is the service hub - most complex configuration
|
||||
- Secrets require host SSH keys defined in `secrets.nix` before `agenix -e` works
|
||||
- Fish and Nushell both configured - choose per-user with shell aliases
|
||||
- Color scheme (Dracula) applied via nix-colors across all visual tools
|
||||
- See subdirectory AGENTS.md for deep dives on containers, desktop features, CLI tools
|
||||
|
||||
Reference in New Issue
Block a user