From 841d7abbe792f35e043a28e0c7e0fa944944e1c0 Mon Sep 17 00:00:00 2001
From: m3tm3re
Date: Fri, 2 Jan 2026 15:12:26 +0100
Subject: [PATCH] stt, mem0, rofi-project-opener
---
AGENTS.md | 382 +++++++------------
flake.lock | 46 +--
flake.nix | 4 +-
home/AGENTS.md | 51 ---
home/features/AGENTS.md | 64 ----
home/features/cli/AGENTS.md | 65 ++++
home/features/cli/default.nix | 9 +-
home/features/cli/nushell.nix | 2 +-
home/features/coding/default.nix | 3 +-
home/features/desktop/AGENTS.md | 79 ++++
home/features/desktop/default.nix | 6 +-
home/features/desktop/hyprland.nix | 6 +-
home/features/desktop/rofi.nix | 8 +
home/features/desktop/webapps.nix | 55 +++
hosts/AGENTS.md | 64 ----
hosts/common/AGENTS.md | 76 ++++
hosts/m3-ares/services/default.nix | 1 -
hosts/m3-atlas/services/AGENTS.md | 63 ---
hosts/m3-atlas/services/containers/AGENTS.md | 85 +++++
hosts/m3-kratos/services/default.nix | 1 +
hosts/m3-kratos/services/mem0.nix | 23 ++
21 files changed, 562 insertions(+), 531 deletions(-)
delete mode 100644 home/AGENTS.md
delete mode 100644 home/features/AGENTS.md
create mode 100644 home/features/cli/AGENTS.md
create mode 100644 home/features/desktop/AGENTS.md
delete mode 100644 hosts/AGENTS.md
create mode 100644 hosts/common/AGENTS.md
delete mode 100644 hosts/m3-atlas/services/AGENTS.md
create mode 100644 hosts/m3-atlas/services/containers/AGENTS.md
create mode 100644 hosts/m3-kratos/services/mem0.nix
diff --git a/AGENTS.md b/AGENTS.md
index cadf74f..346fadb 100644
--- a/AGENTS.md
+++ b/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 .#
-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 # Update single input
-
-# Development shell
-nix develop .#infraShell # OpenTofu + nixos-anywhere
-
-# Format Nix files
-alejandra . # Format all .nix files
-alejandra # Format single file
+## STRUCTURE
```
-
-## Testing
-
-No formal test suite. Verification is done via:
-```bash
-nix flake check # Syntax and evaluation check
-nix build .#nixosConfigurations..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//` | 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/.age` after adding keys to `secrets.nix`
+- **Reference**: `config.age.secrets..path` in service configs
+- **Pattern**: Service env files use `environmentFiles = [config.age.secrets.-env.path]`
+
+### Service Organization
+- **Native services**: `hosts//services/.nix`
+- **Containers**: `hosts//services/containers/.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...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/.age
+
+# Infrastructure shell (OpenTofu)
+nix develop .#infraShell
+
+# Check configuration (no activation)
+nixos-rebuild dry-build --flake .#
```
-### 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-` | `m3-atlas`, `m3-kratos` |
-| Options | camelCase path | `extraServices.ollama.enable` |
-| Feature flags | `features...enable` | `features.cli.nushell.enable` |
-| Secrets | `-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..loadBalancer.servers = [{ url = "http://127.0.0.1:"; }];
+ routers. = {
+ rule = "Host(`.m3ta.dev`)";
+ service = "";
+ tls.certResolver = "godaddy";
};
-}
+};
```
-### Imports
+### Container Pattern
+- **Network**: `--network=web --ip=10.89.0.`
+- **Ports**: Bind localhost only (`127.0.0.1::`)
+- **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..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
diff --git a/flake.lock b/flake.lock
index 67b4327..ba87705 100644
--- a/flake.lock
+++ b/flake.lock
@@ -146,11 +146,11 @@
]
},
"locked": {
- "lastModified": 1766682973,
- "narHash": "sha256-GKO35onS711ThCxwWcfuvbIBKXwriahGqs+WZuJ3v9E=",
+ "lastModified": 1766387499,
+ "narHash": "sha256-AjK3/UKDzeXFeYNLVBaJ3+HLE9he1g5UrlNd4/BM3eA=",
"owner": "nix-community",
"repo": "home-manager",
- "rev": "91cdb0e2d574c64fae80d221f4bf09d5592e9ec2",
+ "rev": "527ad07e6625302b648ed3b28c34b62a79bd103e",
"type": "github"
},
"original": {
@@ -209,11 +209,11 @@
"nixpkgs": "nixpkgs_2"
},
"locked": {
- "lastModified": 1766564648,
- "narHash": "sha256-xgMcrwKhFSQeSQN7ak0iUHNsnxaprEzuRYRo2ADeTtg=",
+ "lastModified": 1762493267,
+ "narHash": "sha256-W/eYgKKVqCh7SJLHk6Asc4LvU3YXvGtlL29yBMGymz4=",
"owner": "Jas-SinghFSU",
"repo": "HyprPanel",
- "rev": "17ecff630bece1ac81569e427088ee8b11322f36",
+ "rev": "f9a04192e8fb90a48e1756989f582dc0baec2351",
"type": "github"
},
"original": {
@@ -227,11 +227,11 @@
"nixpkgs": "nixpkgs_3"
},
"locked": {
- "lastModified": 1766478371,
- "narHash": "sha256-x9lJbQ0HuwpG17OColK0ueLYsZYz8/9+KBIVlZG18RU=",
+ "lastModified": 1767362052,
+ "narHash": "sha256-NfrV9/JtD37WX7+H4UaFcTSnqmpSpr8f2Za+qo1duxM=",
"ref": "refs/heads/master",
- "rev": "d7d64634eef57179b1411b251496154c0c54578b",
- "revCount": 11,
+ "rev": "0b4c2efc8f4298168befc24d6a55cb732772caae",
+ "revCount": 18,
"type": "git",
"url": "https://code.m3ta.dev/m3tam3re/nixpkgs"
},
@@ -374,11 +374,11 @@
},
"nixpkgs-master": {
"locked": {
- "lastModified": 1766753232,
- "narHash": "sha256-gUj5f8xuGUg7dT+BDlWyb6FnyD7f8n6UrFcSGzwLv/E=",
+ "lastModified": 1766476350,
+ "narHash": "sha256-JbSaOKi9jBGu1KG+BANYiocKsc+EI8Qb4MUKgtXnaTE=",
"owner": "nixos",
"repo": "nixpkgs",
- "rev": "a2eef3d4a9e42d1bfb122c4ca9550544ec7ccab1",
+ "rev": "48c44c67646d5a8c7c168e1ded8adf6fd8f3831b",
"type": "github"
},
"original": {
@@ -390,16 +390,16 @@
},
"nixpkgs-stable": {
"locked": {
- "lastModified": 1766687554,
- "narHash": "sha256-DegN7KD/EtFSKXf2jvqL6lvev6GlfAAatYBcRC8goEo=",
+ "lastModified": 1767047869,
+ "narHash": "sha256-tzYsEzXEVa7op1LTnrLSiPGrcCY6948iD0EcNLWcmzo=",
"owner": "nixos",
"repo": "nixpkgs",
- "rev": "fd0ca39c92fdb4012ed8d60e1683c26fddadd136",
+ "rev": "89dbf01df72eb5ebe3b24a86334b12c27d68016a",
"type": "github"
},
"original": {
"owner": "nixos",
- "ref": "nixos-25.05",
+ "ref": "nixos-25.11",
"repo": "nixpkgs",
"type": "github"
}
@@ -454,11 +454,11 @@
},
"nixpkgs_5": {
"locked": {
- "lastModified": 1766651565,
- "narHash": "sha256-QEhk0eXgyIqTpJ/ehZKg9IKS7EtlWxF3N7DXy42zPfU=",
+ "lastModified": 1766309749,
+ "narHash": "sha256-3xY8CZ4rSnQ0NqGhMKAy5vgC+2IVK0NoVEzDoOh4DA4=",
"owner": "nixos",
"repo": "nixpkgs",
- "rev": "3e2499d5539c16d0d173ba53552a4ff8547f4539",
+ "rev": "a6531044f6d0bef691ea18d4d4ce44d0daa6e816",
"type": "github"
},
"original": {
@@ -492,11 +492,11 @@
]
},
"locked": {
- "lastModified": 1766741918,
- "narHash": "sha256-FOb58l2rT3ZxDY0px1lGFUNPhaSKRcGwH94pWGl3vzQ=",
+ "lastModified": 1766476441,
+ "narHash": "sha256-IUN09o1u22yEv3YaLUq5BE9xvVNsqHRrINUTrZxxnwM=",
"owner": "nix-community",
"repo": "NUR",
- "rev": "f85ac5163eb68087550897c67542a0f478651782",
+ "rev": "1a2c4782c53dccd364e404fc0eec7fddee46d815",
"type": "github"
},
"original": {
diff --git a/flake.nix b/flake.nix
index 59f6cb6..02ddacf 100644
--- a/flake.nix
+++ b/flake.nix
@@ -16,14 +16,14 @@
inputs.nixpkgs.follows = "nixpkgs";
};
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
- nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-25.05";
+ nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-25.11";
nixpkgs-45570c2.url = "github:nixos/nixpkgs/45570c299dc2b63c8c574c4cd77f0b92f7e2766e";
nixpkgs-locked.url = "github:nixos/nixpkgs/2744d988fa116fc6d46cdfa3d1c936d0abd7d121";
nixpkgs-9e58ed7.url = "github:nixos/nixpkgs/9e58ed7ba759d81c98f033b7f5eba21ca68f53b0";
nixpkgs-master.url = "github:nixos/nixpkgs/master";
m3ta-nixpkgs.url = "git+https://code.m3ta.dev/m3tam3re/nixpkgs";
- #m3ta-nixpkgs.url = "path:/home/m3tam3re/p/nix/nixpkgs";
+ # m3ta-nixpkgs.url = "path:/home/m3tam3re/p/NIX/nixpkgs";
#
nur = {
url = "github:nix-community/NUR";
diff --git a/home/AGENTS.md b/home/AGENTS.md
deleted file mode 100644
index 928993e..0000000
--- a/home/AGENTS.md
+++ /dev/null
@@ -1,51 +0,0 @@
-# home/ - Home Manager Configurations
-
-User-level configurations managed by home-manager.
-
-## Structure
-
-```
-home/
-├── common/ # Shared home-manager config
-│ └── default.nix # Overlays, nix-colors, allowUnfree
-├── features/ # Modular, toggle-able features
-│ ├── cli/ # Shell tools (see features/AGENTS.md)
-│ ├── coding/ # Dev tools
-│ └── desktop/ # GUI, Hyprland, theming
-└── m3tam3re/ # Per-host user configs
- ├── home.nix # Shared user config (git, ssh, packages)
- └── m3-.nix # Host-specific (imports features, monitor layouts)
-```
-
-## Per-Host Config Pattern
-
-Each `m3-.nix`:
-1. Imports `../common`, `./home.nix`, and needed `../features/*`
-2. Enables specific features via `features...enable`
-3. Overrides host-specific settings (monitors, default apps)
-
-Example:
-```nix
-{
- imports = [../common ./home.nix ../features/cli ../features/desktop];
-
- features.cli.nushell.enable = true;
- features.desktop.hyprland.enable = true;
-
- wayland.windowManager.hyprland.settings.monitor = ["DP-1,2560x1440,0x0,1"];
-}
-```
-
-## Theming
-
-Uses nix-colors (Dracula scheme). Access colors:
-```nix
-"#${config.colorScheme.palette.base00}" # Background
-"#${config.colorScheme.palette.base05}" # Foreground
-```
-
-## Adding New User Config
-
-1. Create `m3tam3re/m3-.nix`
-2. Import needed features
-3. Add to `flake.nix` homeConfigurations (standalone) or host's home-manager.users
diff --git a/home/features/AGENTS.md b/home/features/AGENTS.md
deleted file mode 100644
index 5f5d879..0000000
--- a/home/features/AGENTS.md
+++ /dev/null
@@ -1,64 +0,0 @@
-# features/ - Modular Home Manager Features
-
-Toggle-able feature modules using `mkEnableOption` pattern.
-
-## Structure
-
-```
-features/
-├── cli/ # Shell & terminal tools
-│ ├── default.nix # Always-on CLI tools (bat, eza, direnv, carapace)
-│ ├── nushell.nix # features.cli.nushell.enable
-│ ├── fzf.nix # features.cli.fzf.enable
-│ ├── starship.nix # features.cli.starship.enable
-│ ├── zellij.nix # Always-on zellij config
-│ └── secrets.nix # features.cli.secrets.enable
-├── coding/ # Dev tools
-│ └── default.nix # features.coding.* (zed, neovim)
-└── desktop/ # GUI applications
- ├── default.nix # Always-on (kitty, xdg, cursor)
- ├── hyprland.nix # features.desktop.hyprland.enable
- ├── gaming.nix # features.desktop.gaming.enable
- ├── media.nix # features.desktop.media.enable
- └── ...
-```
-
-## Creating a New Feature
-
-1. Create `/.nix`:
-```nix
-{config, lib, ...}:
-with lib; let
- cfg = config.features..;
-in {
- options.features...enable =
- mkEnableOption "description";
-
- config = mkIf cfg.enable {
- # Configuration when enabled
- };
-}
-```
-
-2. Import in `/default.nix`
-3. Enable in user configs: `features...enable = true;`
-
-## Feature Categories
-
-| Category | Purpose | Key features |
-|----------|---------|--------------|
-| cli | Shell tools | nushell, fzf, starship, nitch, secrets |
-| coding | Development | (in default.nix, no sub-features yet) |
-| desktop | GUI/WM | hyprland, gaming, media, office, crypto, fonts, rofi, wayland |
-
-## Always-On vs Toggle-able
-
-- **default.nix**: Configuration that applies when the category is imported (no enable flag)
-- **.nix**: Must be explicitly enabled via `features.*.enable = true`
-
-## Desktop Feature Details
-
-- `hyprland.nix`: Window manager config, keybinds, window rules (host overrides monitors/workspaces)
-- `gaming.nix`: Steam, gamemode, mangohud
-- `media.nix`: mpv, obs-studio, spotify
-- `wayland.nix`: Clipboard, screenshots, idle management
diff --git a/home/features/cli/AGENTS.md b/home/features/cli/AGENTS.md
new file mode 100644
index 0000000..24f1920
--- /dev/null
+++ b/home/features/cli/AGENTS.md
@@ -0,0 +1,65 @@
+# CLI FEATURES (home-manager)
+
+**Shell and terminal tooling with Fish + Nushell dual configuration**
+
+## OVERVIEW
+8 CLI modules with integrated tooling across Fish and Nushell shells.
+
+## STRUCTURE
+```
+cli/
+├── default.nix # Imports + shared tools (bat, eza, direnv)
+├── fish.nix # Fish shell + aliases
+├── fzf.nix # Fuzzy finder
+├── nitch.nix # System info tool
+├── nushell.nix # Nushell + aliases
+├── secrets.nix # Password-store integration
+├── starship.nix # Shell prompt
+└── zellij.nix # Terminal multiplexer
+```
+
+## WHERE TO LOOK
+
+| Task | Location | Notes |
+|------|----------|-------|
+| Add CLI tool | default.nix home.packages | Check if shell integration needed |
+| Shell aliases | fish.nix or nushell.nix | Kept in sync between shells |
+| Prompt config | starship.nix | Uses nerd-fonts symbols |
+| Secret access | secrets.nix | Agenix integration |
+
+## CONVENTIONS
+
+### Shell Integration Pattern
+Tools with shell hooks enabled in both Fish and Nushell:
+- **carapace**: Completions
+- **zoxide**: Smart cd
+- **eza**: ls replacement
+- **direnv**: Directory environments
+- **fzf**: Fuzzy finding
+
+### NixOS Rebuild Aliases (both shells)
+```
+nr/nrs - nixos-rebuild [switch]
+snr/snrs - sudo nixos-rebuild [switch]
+hms - home-manager switch
+```
+
+### Bat Theme
+Custom `universal` theme generated from nix-colors palette in default.nix (lines 34-157).
+
+### Secrets Integration
+Fish/Nushell source `$HOME/.secrets` if `secrets.enable = true` (CLI secrets feature).
+
+## ANTI-PATTERNS
+
+- **DON'T** add aliases to only one shell - keep Fish/Nushell in sync
+- **DON'T** use `programs.bash` - Nushell is default shell
+- **DON'T** bypass carapace for completions - integrated by default
+
+## NOTES
+
+- zellij-ps custom package for project session management
+- Default shell set to Nushell in hosts/common/default.nix
+- Bat theme dynamically generated (no external theme files)
+- lf file manager uses bat for previews
+- Agenix CLI (agenix-cli) included for secret management
diff --git a/home/features/cli/default.nix b/home/features/cli/default.nix
index b92d817..3b59b82 100644
--- a/home/features/cli/default.nix
+++ b/home/features/cli/default.nix
@@ -12,7 +12,12 @@
./starship.nix
./zellij.nix
];
-
+ cli.stt-ptt = {
+ enable = true;
+ whisperPackage = pkgs.whisper-cpp-vulkan;
+ model = "ggml-large-v3-turbo";
+ notifyTimeout = 2000;
+ };
programs.carapace = {
enable = true;
enableFishIntegration = true;
@@ -192,6 +197,7 @@
agenix-cli
alejandra
bc
+ bun
claude-code
comma
coreutils
@@ -209,6 +215,7 @@
llm
lf
nix-index
+ libnotify
nushellPlugins.skim
progress
ripgrep
diff --git a/home/features/cli/nushell.nix b/home/features/cli/nushell.nix
index 6a9251d..46ebb19 100644
--- a/home/features/cli/nushell.nix
+++ b/home/features/cli/nushell.nix
@@ -25,7 +25,7 @@ in {
$env.FZF_DEFAULT_COMMAND = "fd --type f --exclude .git --follow --hidden"
$env.SSH_AUTH_SOCK = "/run/user/1000/gnupg/S.gpg-agent.ssh"
$env.FLAKE = $"($env.HOME)/p/nixos/nixos-config"
- $env.PATH = ($env.PATH | split row (char esep) | prepend $"($env.HOME)/.cache/.bun/bin" | uniq)
+ $env.PATH = ($env.PATH | split row (char esep) | append "/home/m3tam3re/.cache/.bun/bin" | uniq)
source /run/agenix/${config.home.username}-secrets
'';
configFile.text = ''
diff --git a/home/features/coding/default.nix b/home/features/coding/default.nix
index 367061b..782703b 100644
--- a/home/features/coding/default.nix
+++ b/home/features/coding/default.nix
@@ -1,9 +1,8 @@
{pkgs, ...}: {
home.packages = with pkgs; [
- bun
- code2prompt
devpod
#devpod-desktop
+ code2prompt
nur.repos.charmbracelet.crush
(python3.withPackages (ps:
with ps; [
diff --git a/home/features/desktop/AGENTS.md b/home/features/desktop/AGENTS.md
new file mode 100644
index 0000000..1c9fbb7
--- /dev/null
+++ b/home/features/desktop/AGENTS.md
@@ -0,0 +1,79 @@
+# DESKTOP FEATURES (home-manager)
+
+**Wayland/Hyprland environment with color-coordinated tooling**
+
+## OVERVIEW
+12 modular desktop features with nix-colors (Dracula) integration across all components.
+
+## STRUCTURE
+```
+desktop/
+├── default.nix # Imports + XDG + Kitty config
+├── coding.nix # Development tools (VSCode, etc.)
+├── crypto.nix # Crypto wallets/tools
+├── fonts.nix # Font packages
+├── gaming.nix # Gaming tools/Steam
+├── hyprland.nix # Hyprland WM configuration
+├── media.nix # Media players/editors
+├── office.nix # LibreOffice, document tools
+├── rofi.nix # Application launcher
+├── theme.nix # GTK/Qt theming
+├── wayland.nix # Wayland utilities
+└── webapps.nix # Browser-based apps
+```
+
+## WHERE TO LOOK
+
+| Task | Location | Notes |
+|------|----------|-------|
+| Add desktop app | Relevant feature .nix | Update home.packages |
+| Configure Hyprland | hyprland.nix | Window manager settings |
+| Fix colors | Check colorScheme references | Uses config.colorScheme.palette.base* |
+| Add font | fonts.nix | Increases system closure size |
+
+## CONVENTIONS
+
+### Color Scheme Integration
+All color-aware tools reference `config.colorScheme.palette.base00` through `base0F`:
+- **base00-07**: Grayscale (dark to light)
+- **base08**: Red/errors
+- **base09**: Orange
+- **base0A**: Yellow/strings
+- **base0B**: Green/functions
+- **base0C**: Cyan
+- **base0D**: Blue/types
+- **base0E**: Purple/constants
+- **base0F**: Brown
+
+Template:
+```nix
+foreground = "#${config.colorScheme.palette.base05}";
+background = "#${config.colorScheme.palette.base00}";
+```
+
+### Session Variables
+Set in default.nix for Wayland/Hyprland:
+```nix
+NIXOS_OZONE_WL = "1";
+QT_QPA_PLATFORM = "wayland";
+XDG_CURRENT_DESKTOP = "Hyprland";
+```
+
+### XDG Defaults
+- **PDF**: okular
+- **Text**: nvim
+- **Browser**: Zen (io.github.zen_browser.zen)
+- **Archive**: file-roller
+
+## ANTI-PATTERNS
+
+- **DON'T** hardcode hex colors - use colorScheme palette
+- **DON'T** install fonts globally - keep in user packages
+- **DON'T** bypass XDG defaults - set in mimeApps
+
+## NOTES
+
+- Kitty terminal configured in default.nix (not separate file)
+- Bibata-Modern-Ice cursor theme hardcoded
+- Session path includes cargo, npm-global, bun
+- Desktop features are always-enabled (no feature flags in this dir)
diff --git a/home/features/desktop/default.nix b/home/features/desktop/default.nix
index e0547d8..a22e429 100644
--- a/home/features/desktop/default.nix
+++ b/home/features/desktop/default.nix
@@ -14,6 +14,7 @@
./rofi.nix
./theme.nix
./wayland.nix
+ ./webapps.nix
];
xdg = {
@@ -51,7 +52,7 @@
XDG_SESSION_TYPE = "wayland";
XDG_SESSION_DESKTOP = "Hyprland";
};
- home.sessionPath = ["\${XDG_BIN_HOME}" "\${HOME}/.cargo/bin" "$HOME/.npm-global/bin"];
+ home.sessionPath = ["\${XDG_BIN_HOME}" "\${HOME}/.cargo/bin" "$HOME/.npm-global/bin" "$HOME/.cache/.bun/bin"];
fonts.fontconfig.enable = true;
@@ -125,7 +126,7 @@
home.packages = with pkgs; [
appimage-run
- anytype
+ stable.anytype
# blueberry
bemoji
brave
@@ -165,7 +166,6 @@
telegram-desktop
vivaldi
vivaldi-ffmpeg-codecs
- warp-terminal
# wl-clipboard
# wlogout
# wtype
diff --git a/home/features/desktop/hyprland.nix b/home/features/desktop/hyprland.nix
index 9150a49..965e882 100644
--- a/home/features/desktop/hyprland.nix
+++ b/home/features/desktop/hyprland.nix
@@ -169,13 +169,13 @@ in {
"$mainMod SHIFT, S, exec, uwsm app -- rofi -show emoji"
"$mainMod, P, exec, uwsm app -- rofi-pass"
"$mainMod SHIFT, P, pseudo"
+ "$mainMod, R, exec, stt-ptt start"
"$mainMod, J, togglesplit"
"$mainMod, h, movefocus, l"
"$mainMod, l, movefocus, r"
"$mainMod, k, movefocus, u"
"$mainMod, j, movefocus, d"
"$mainMod, 1, workspace, 1"
-
"$mainMod, 2, workspace, 2"
"$mainMod, 3, workspace, 3"
"$mainMod, 4, workspace, 4"
@@ -198,7 +198,9 @@ in {
"$mainMod, mouse_down, workspace, e+1"
"$mainMod, mouse_up, workspace, e-1"
];
-
+ bindr = [
+ "$mainMod, R, exec, stt-ptt stop"
+ ];
bindm = [
"$mainMod, mouse:272, movewindow"
"$mainMod, mouse:273, resizewindow"
diff --git a/home/features/desktop/rofi.nix b/home/features/desktop/rofi.nix
index f2163ef..c6f49e7 100644
--- a/home/features/desktop/rofi.nix
+++ b/home/features/desktop/rofi.nix
@@ -179,5 +179,13 @@ in {
}
'');
};
+ cli.rofi-project-opener = {
+ enable = true;
+ projectDirs = [
+ "$HOME/p/NIX"
+ ];
+ terminal = pkgs.kitty;
+ terminalCommand = "opencode";
+ };
};
}
diff --git a/home/features/desktop/webapps.nix b/home/features/desktop/webapps.nix
index e69de29..57ed3fc 100644
--- a/home/features/desktop/webapps.nix
+++ b/home/features/desktop/webapps.nix
@@ -0,0 +1,55 @@
+{
+ pkgs,
+ lib,
+ ...
+}: let
+ icons = {
+ teams = pkgs.fetchurl {
+ url = "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/microsoft-teams.svg";
+ sha256 = "sha256-Pr9QS8nnXJq97r4/G3c6JXi34zxHl0ps9gcyI8cN/s8=";
+ };
+ outlook = pkgs.fetchurl {
+ url = "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/microsoft-outlook.svg";
+ sha256 = "sha256-3u8t5QNHFZvrAegxBiGicO4PjtMWhEaQSCv7MSSfLLc=";
+ };
+ opencode = pkgs.fetchurl {
+ url = "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/opencode-dark.svg";
+ sha256 = "1lms4f8habamvdh2qqqz9psx4py9wx23mmlkkds44pvrbq3bkj3n";
+ };
+ };
+in {
+ xdg.desktopEntries = {
+ teams = {
+ name = "Microsoft Teams";
+ exec = "launch-webapp https://teams.microsoft.com";
+ comment = "Open Microsoft Teams as a Desktop App";
+ categories = ["Application" "Network" "Chat"];
+ terminal = false;
+ icon = icons.teams;
+ };
+ outlook = {
+ name = "Microsoft Outlook";
+ exec = "launch-webapp https://outlook.office.com/mail/";
+ comment = "Open Microsoft Outlook as a Desktop App";
+ categories = ["Application" "Network"];
+ terminal = false;
+ icon = icons.outlook;
+ };
+ basecamp = {
+ name = "Basecamp";
+ exec = "launch-webapp https://3.basecamp.com/5996442/";
+ comment = "Open Basecamp as a Desktop App";
+ categories = ["Application" "Network"];
+ terminal = false;
+ icon = "/home/sascha.koenig/.local/share/icons/basecamp-logo.png";
+ };
+ opencode = {
+ name = "Opencode";
+ exec = "rofi-project-opener";
+ comment = "Open Opencode Terminal App";
+ categories = ["Application" "Development"];
+ terminal = false;
+ icon = icons.opencode;
+ };
+ };
+}
diff --git a/hosts/AGENTS.md b/hosts/AGENTS.md
deleted file mode 100644
index c7c88eb..0000000
--- a/hosts/AGENTS.md
+++ /dev/null
@@ -1,64 +0,0 @@
-# hosts/ - NixOS Host Configurations
-
-Host-specific NixOS system configurations. Each `m3-*` directory is a complete host.
-
-## Structure
-
-```
-hosts/
-├── common/ # Shared by ALL hosts
-│ ├── extraServices/ # Toggle-able services (ollama, podman, flatpak)
-│ ├── users/ # User definitions
-│ ├── ports.nix # Central port registry
-│ └── default.nix # Overlays, nix settings, home-manager integration
-└── m3-*/ # Per-host configurations
- ├── default.nix # Entry point (imports common + enables extraServices)
- ├── configuration.nix # Core system (boot, networking, stateVersion)
- ├── hardware-configuration.nix
- ├── programs.nix # Host-specific packages
- ├── secrets.nix # Agenix secret declarations
- └── services/ # Service configs
- └── containers/ # OCI container definitions (m3-atlas only has many)
-```
-
-## Adding a New Host
-
-1. Create `hosts/m3-/` with required files
-2. Add to `flake.nix` nixosConfigurations
-3. Create matching `home/m3tam3re/m3-.nix`
-
-## Host Quick Reference
-
-| Host | extraServices | Has disko | Key services/ files |
-|------|---------------|-----------|---------------------|
-| m3-atlas | podman | Yes | traefik, postgres, gitea, containers/* |
-| m3-helios | - | Yes | adguard, traefik, containers/homarr |
-| m3-ares | podman | No | wireguard, tailscale, sound |
-| m3-kratos | podman, ollama | No | wireguard, tailscale, sound |
-| m3-aether | - | Yes | cloud-init (minimal) |
-
-## extraServices Pattern
-
-Enable in host's `default.nix`:
-```nix
-extraServices = {
- podman.enable = true;
- ollama.enable = true;
- flatpak.enable = false;
- virtualisation.enable = false;
-};
-```
-
-## Port Allocation
-
-ALWAYS check `common/ports.nix` before adding new services. Register new ports there.
-
-## Secrets Declaration
-
-Each host's `secrets.nix` declares only secrets it needs:
-```nix
-age.secrets.service-name = {
- file = ../../secrets/service-name.age;
- owner = "optional-user";
-};
-```
diff --git a/hosts/common/AGENTS.md b/hosts/common/AGENTS.md
new file mode 100644
index 0000000..ea6331d
--- /dev/null
+++ b/hosts/common/AGENTS.md
@@ -0,0 +1,76 @@
+# COMMON HOST CONFIGURATION
+
+**Shared base configuration and abstractions for all hosts**
+
+## OVERVIEW
+Common imports, overlays, and custom patterns (extraServices, ports) used across 6 hosts.
+
+## STRUCTURE
+```
+common/
+├── default.nix # Base imports, overlays, nix settings
+├── ports.nix # Centralized port registry
+├── extraServices/ # Optional service modules
+│ ├── default.nix
+│ ├── flatpak.nix
+│ ├── ollama.nix
+│ ├── podman.nix
+│ └── virtualisation.nix
+└── users/
+ ├── default.nix
+ └── m3tam3re.nix # Primary user definition
+```
+
+## WHERE TO LOOK
+
+| Task | Location | Notes |
+|------|----------|-------|
+| Add port definition | ports.nix | Use config.m3ta.ports.get |
+| Enable optional service | Host config extraServices | Boolean flags |
+| Modify overlays | default.nix lines 27-36 | 5 overlay sources |
+| Add new user | users/ | Shared across all hosts |
+
+## CONVENTIONS
+
+### Port Registry Pattern
+```nix
+# Define in ports.nix
+definitions = {
+ myservice = 3099;
+};
+
+# Access in host config
+config.m3ta.ports.get "myservice" # Returns 3099
+```
+
+### extraServices Abstraction
+Host configs enable via boolean:
+```nix
+extraServices = {
+ podman.enable = true; # Container runtime
+ ollama.enable = true; # LLM inference
+ flatpak.enable = false; # Flatpak apps
+ virtualisation.enable = true; # QEMU/KVM
+};
+```
+
+### Overlay Precedence (bottom overrides top)
+1. stable-packages (nixpkgs-stable)
+2. locked-packages (nixpkgs-locked)
+3. pinned-packages (nixpkgs-45570c2, nixpkgs-9e58ed7)
+4. master-packages (nixpkgs-master)
+5. m3ta-nixpkgs (local custom overlay)
+
+## ANTI-PATTERNS
+
+- **DON'T** add host-specific logic to common/ - belongs in hosts//
+- **DON'T** bypass port registry - hardcoded ports break consistency
+- **DON'T** modify user shell globally - set per-user if needed
+
+## NOTES
+
+- Nix GC runs weekly, keeps 30 days
+- Trusted users: root, m3tam3re
+- Default shell: Nushell (set line 77)
+- Home-manager integrated at common level, not per-host
+- TODO on line 69: ports should only return actually used ports
diff --git a/hosts/m3-ares/services/default.nix b/hosts/m3-ares/services/default.nix
index 22d414c..d4e9149 100644
--- a/hosts/m3-ares/services/default.nix
+++ b/hosts/m3-ares/services/default.nix
@@ -33,7 +33,6 @@
userServices = true;
};
};
- displayManager.gdm.enable = true;
};
systemd.sleep.extraConfig = ''
AllowSuspend=no
diff --git a/hosts/m3-atlas/services/AGENTS.md b/hosts/m3-atlas/services/AGENTS.md
deleted file mode 100644
index 2fb7815..0000000
--- a/hosts/m3-atlas/services/AGENTS.md
+++ /dev/null
@@ -1,63 +0,0 @@
-# services/ - m3-atlas Service Configurations
-
-Main server services including Traefik reverse proxy and containerized apps.
-
-## Container Network
-
-- **Network**: `web` (podman network)
-- **Subnet**: `10.89.0.0/24`
-- **Gateway/Postgres**: `10.89.0.1`
-- **DNS Challenge**: GoDaddy via Traefik
-
-## Adding a New Container
-
-1. Pick next available IP from registry (currently: `10.89.0.22`)
-2. Register port in `hosts/common/ports.nix`
-3. Create `containers/.nix`:
-
-```nix
-{config, ...}: {
- virtualisation.oci-containers.containers."service" = {
- image = "registry/image:tag";
- environmentFiles = [config.age.secrets.service-env.path];
- ports = ["127.0.0.1:PORT:PORT"];
- volumes = ["service_data:/data"];
- extraOptions = [
- "--add-host=postgres:10.89.0.1"
- "--ip=10.89.0.XX"
- "--network=web"
- ];
- };
-
- services.traefik.dynamicConfigOptions.http = {
- services.service.loadBalancer.servers = [{ url = "http://localhost:PORT/"; }];
- routers.service = {
- rule = "Host(`service.domain.com`)";
- tls.certResolver = "godaddy";
- service = "service";
- entrypoints = "websecure";
- };
- };
-}
-```
-
-4. Import in `containers/default.nix`
-5. Add secret to `secrets.nix` and root `secrets.nix`
-6. Update IP registry in root AGENTS.md
-
-## Service Files (non-container)
-
-| File | Purpose |
-|------|---------|
-| traefik.nix | Reverse proxy, TLS, entrypoints |
-| postgres.nix | Native PostgreSQL for containers |
-| tailscale.nix | Mesh VPN |
-| gitea.nix | Native Gitea (not containerized) |
-| minio.nix | S3-compatible storage |
-
-## Traefik Patterns
-
-- HTTP redirect to HTTPS: automatic via `web` entrypoint
-- TLS: `certResolver = "godaddy"` (DNS challenge)
-- Auth middleware: `middlewares = ["auth"]` (basic auth)
-- Domain redirects: See `traefik.nix` middlewares
diff --git a/hosts/m3-atlas/services/containers/AGENTS.md b/hosts/m3-atlas/services/containers/AGENTS.md
new file mode 100644
index 0000000..b05b4e0
--- /dev/null
+++ b/hosts/m3-atlas/services/containers/AGENTS.md
@@ -0,0 +1,85 @@
+# CONTAINER SERVICES (m3-atlas)
+
+**Container orchestration with Podman + Traefik reverse proxy**
+
+## OVERVIEW
+11 containerized services on dedicated `web` network (10.89.0.0/24) with Traefik SSL termination.
+
+## STRUCTURE
+```
+containers/
+├── default.nix # Network setup + service imports
+├── baserow.nix # 10.89.0.10 - No-code database
+├── ghost.nix # 10.89.0.11 - Blog platform
+├── kestra.nix # 10.89.0.12 - Workflow orchestration
+├── littlelink.nix # 10.89.0.13 - Link aggregator
+├── matomo.nix # 10.89.0.14 - Analytics
+├── restreamer.nix # 10.89.0.15 - Video streaming
+├── slash.nix # 10.89.0.16 - Link shortener
+└── slash-nemoti.nix # 10.89.0.17 - Personal link shortener
+```
+
+## WHERE TO LOOK
+
+| Task | Action | Notes |
+|------|--------|-------|
+| Add container | Copy existing .nix, increment IP | Must update default.nix imports |
+| Fix networking | Check IP conflicts in 10.89.0.0/24 | Gateway always 10.89.0.1 |
+| Debug Traefik | Check router rules in service file | Domain must match DNS |
+| Access database | Use `--add-host=mysql:10.89.0.1` | Gateway IP for host services |
+
+## CONVENTIONS
+
+### Container Definition Template
+```nix
+virtualisation.oci-containers.containers. = {
+ image = "registry/image:tag";
+ ports = ["127.0.0.1::"];
+ volumes = ["/var/lib/:/data"];
+ environmentFiles = [config.age.secrets.-env.path];
+ extraOptions = [
+ "--network=web"
+ "--ip=10.89.0."
+ "--add-host=mysql:10.89.0.1" # If DB needed
+ ];
+};
+```
+
+### Traefik Integration
+```nix
+services.traefik.dynamicConfigOptions.http = {
+ services..loadBalancer.servers = [{
+ url = "http://127.0.0.1:";
+ }];
+ routers. = {
+ rule = "Host(`.m3ta.dev`)";
+ service = "";
+ tls.certResolver = "godaddy";
+ };
+ # Legacy redirect (if needed)
+ routers.-old = {
+ rule = "Host(`.m3tam3re.com`)";
+ service = "";
+ middlewares = ["redirect-m3ta"];
+ };
+};
+```
+
+### IP Allocation
+- **10.89.0.1**: Gateway (host)
+- **10.89.0.10-17**: Assigned containers
+- **10.89.0.18+**: Available for new services
+
+## ANTI-PATTERNS
+
+- **DON'T** expose ports publicly - bind to 127.0.0.1 only
+- **DON'T** skip static IP assignment - routing breaks without it
+- **DON'T** hardcode secrets - use age-encrypted env files
+- **DON'T** forget to add imports to default.nix
+
+## NOTES
+
+- Network created via activation script in default.nix
+- All services behind Traefik - no direct external access
+- MySQL/PostgreSQL run on host, accessed via gateway IP
+- Secrets pattern: `-env.age` with environment variables
diff --git a/hosts/m3-kratos/services/default.nix b/hosts/m3-kratos/services/default.nix
index 98b0c3c..e144c10 100644
--- a/hosts/m3-kratos/services/default.nix
+++ b/hosts/m3-kratos/services/default.nix
@@ -1,6 +1,7 @@
{
imports = [
./containers
+ ./mem0.nix
./n8n.nix
./postgres.nix
./sound.nix
diff --git a/hosts/m3-kratos/services/mem0.nix b/hosts/m3-kratos/services/mem0.nix
new file mode 100644
index 0000000..fdf7e97
--- /dev/null
+++ b/hosts/m3-kratos/services/mem0.nix
@@ -0,0 +1,23 @@
+{
+ m3ta.mem0 = {
+ enable = true;
+ port = 8000;
+ host = "127.0.0.1";
+
+ # LLM Configuration
+ llm = {
+ provider = "openai";
+ apiKeyFile = "/var/lib/mem0/openai-api-key-1"; # Use agenix or sops-nix
+ };
+
+ # Vector Storage Configuration
+ vectorStore = {
+ provider = "qdrant"; # or "chroma", "pinecone", etc.
+ config = {
+ host = "localhost";
+ port = 6333;
+ collection_name = "mem0_alice";
+ };
+ };
+ };
+}