1 Commits

Author SHA1 Message Date
m3tam3re 52e070120a dolt remote info 2026-06-13 08:18:23 +02:00
183 changed files with 7 additions and 14358 deletions
-3
View File
@@ -1,3 +0,0 @@
node_modules/
runs/
*.log
-5
View File
@@ -1,5 +0,0 @@
{
"projectRoot": "/home/m3tam3re/p/NIX/nixos-config",
"isNewProject": false,
"additionalContext": "Install and configure babysitter for this existing NixOS flake configuration repository. Respect AGENTS.md instructions, Beads workflow, Nix conventions, and avoid interactive/destructive operations unless explicitly approved."
}
-4570
View File
File diff suppressed because it is too large Load Diff
-9
View File
@@ -1,9 +0,0 @@
{
"name": "nixos-config-a5c",
"version": "1.0.0",
"private": true,
"type": "module",
"dependencies": {
"@a5c-ai/babysitter-sdk": "latest"
}
}
-596
View File
@@ -1,596 +0,0 @@
{
"projectName": "nixos-config",
"description": "A reliable, elegant, multi-system NixOS flake configuration for personal desktop, server, cloud, Home Manager, package, overlay, and secret management.",
"goals": [
{
"id": "goal-reliability-1",
"description": "Keep all managed NixOS systems reproducible, reliable, and easy to validate before deployment.",
"category": "reliability",
"priority": "high",
"status": "active"
},
{
"id": "goal-architecture-1",
"description": "Maintain an elegant multi-system architecture with clear host boundaries and reusable common modules.",
"category": "architecture",
"priority": "high",
"status": "active"
},
{
"id": "goal-modularization-1",
"description": "Continue breaking up the former monorepo by keeping Home Manager profiles in m3ta-home and custom packages/modules in m3ta-nixpkgs where appropriate.",
"category": "modularization",
"priority": "high",
"status": "active"
},
{
"id": "goal-cicd-1",
"description": "CI/CD is not currently configured; add useful Gitea Actions validation later for formatting, linting, flake evaluation, and safe host checks.",
"category": "automation",
"priority": "medium",
"status": "deferred"
}
],
"techStack": {
"languages": [
{
"name": "Nix",
"role": "primary system, module, overlay, and package configuration language"
},
{
"name": "Markdown",
"role": "project, agent, and workflow documentation"
},
{
"name": "JSON/YAML",
"role": "tool configuration and metadata"
}
],
"frameworks": [
{
"name": "Nix flakes",
"category": "reproducible dependency and output model"
},
{
"name": "NixOS modules",
"category": "host and service configuration"
},
{
"name": "Home Manager",
"category": "user environment management"
},
{
"name": "Agenix",
"category": "encrypted secret management"
},
{
"name": "Disko",
"category": "server disk provisioning"
},
{
"name": "NUR",
"category": "community package access"
},
{
"name": "llm-agents.nix",
"category": "LLM agent packages overlay"
},
{
"name": "m3ta-home",
"category": "external reusable Home Manager profiles"
},
{
"name": "m3ta-nixpkgs",
"category": "external custom packages/modules/overlays"
}
],
"databases": [],
"infrastructure": [
{
"name": "m3-ares",
"category": "desktop NixOS host"
},
{
"name": "m3-kratos",
"category": "desktop NixOS host"
},
{
"name": "m3-daedalus",
"category": "portable laptop/Home Manager configuration"
},
{
"name": "m3-atlas",
"category": "primary server NixOS host"
},
{
"name": "m3-helios",
"category": "minimal server/AdGuard host"
},
{
"name": "m3-hermes",
"category": "secondary server/Hermes host"
},
{
"name": "m3-aether",
"category": "cloud VM/minimal server host"
}
],
"buildTools": [
"nix",
"nixos-rebuild",
"nix build",
"nix flake show",
"alejandra",
"statix",
"deadnix"
],
"packageManagers": [
"nix flakes"
]
},
"architecture": {
"pattern": "Pure Nix flake-based NixOS configuration repository with host-specific modules, common shared modules, overlays, custom packages, agenix secrets, and externalized Home Manager/package inputs.",
"modules": [
{
"name": "flake.nix",
"path": "flake.nix",
"description": "Top-level entry point defining inputs, packages, overlays, Home Manager modules, NixOS configurations, and dev shells."
},
{
"name": "hosts/common",
"path": "hosts/common",
"description": "Shared NixOS configuration, nix settings, overlays, Home Manager setup, ports, extra services, and users."
},
{
"name": "hosts",
"path": "hosts",
"description": "Per-host NixOS/Home Manager configurations for desktops, servers, and cloud VM."
},
{
"name": "modules/nixos",
"path": "modules/nixos",
"description": "Reusable NixOS modules."
},
{
"name": "modules/home-manager",
"path": "modules/home-manager",
"description": "Reusable Home Manager module exports."
},
{
"name": "overlays",
"path": "overlays",
"description": "Nixpkgs overlays for stable, locked, pinned, master, temporary, and agent packages."
},
{
"name": "pkgs",
"path": "pkgs",
"description": "Custom package export set."
},
{
"name": "secrets",
"path": "secrets",
"description": "Encrypted agenix secret files and registry."
}
],
"entryPoints": [
"flake.nix",
"hosts/<host>/default.nix",
"hosts/<host>/configuration.nix",
"hosts/common/default.nix",
"hosts/common/users/m3tam3re.nix",
"overlays/default.nix",
"pkgs/default.nix",
"secrets.nix"
],
"dataFlow": "flake.nix wires inputs, overlays, packages, NixOS modules, and Home Manager. Host modules import common configuration and host-specific hardware/programs/services/secrets. Host profile flags in hosts/common/users/m3tam3re.nix feed the external m3ta-home mkHome integration. Secrets flow through agenix registry and host secret modules."
},
"team": [
{
"name": "m3tam3re",
"role": "solo developer and operator",
"responsibilities": [
"architecture",
"implementation",
"host maintenance",
"deployments",
"review"
]
},
{
"name": "m3ta-chiron",
"role": "agent contributor",
"responsibilities": [
"semi-autonomous implementation",
"validation",
"documentation updates",
"conventional commits"
]
}
],
"workflows": [
{
"name": "development",
"description": "Default feature-branch workflow for solo development with conventional commits and validation before push.",
"steps": [
"review Beads issues with bd ready --json",
"claim work with bd update <id> --claim when applicable",
"edit Nix modules or project files",
"run alejandra .",
"run statix check .",
"run targeted nix flake or host dry-run checks",
"commit with conventional commit format",
"pull --rebase and push"
],
"triggers": [
"new feature",
"bug fix",
"refactor",
"agent task"
]
},
{
"name": "nix validation",
"description": "Quality gate for Nix configuration changes.",
"steps": [
"alejandra .",
"statix check .",
"deadnix check or deadnix -w when appropriate",
"nix flake show",
"sudo nixos-rebuild dry-run --flake .#<host> for affected hosts"
],
"triggers": [
"Nix code changes",
"before deployment",
"before commit"
]
},
{
"name": "host deployment",
"description": "Manual deployment after successful dry-run validation.",
"steps": [
"sudo nixos-rebuild dry-run --flake .#<host>",
"sudo nixos-rebuild switch --flake .#<host>"
],
"triggers": [
"manual host update"
]
},
{
"name": "dependency/input update",
"description": "Controlled flake input updates without manually editing flake.lock.",
"steps": [
"use nix flake update or nixos-rebuild --update-input <input>",
"validate affected outputs",
"commit flake.nix/flake.lock changes"
],
"triggers": [
"planned dependency update",
"security update"
]
},
{
"name": "beads issue tracking",
"description": "Persistent issue tracking and session handoff workflow.",
"steps": [
"bd ready --json",
"bd show <id>",
"bd update <id> --claim",
"bd close <id> --reason <summary>",
"bd dolt push"
],
"triggers": [
"start of tracked work",
"completion of tracked work"
]
}
],
"processes": [
{
"id": "cradle/project-install",
"name": "Babysitter project install",
"status": "installing",
"purpose": "Create and save a Babysitter project profile and setup recommendations."
}
],
"tools": {
"formatting": [
{
"name": "alejandra",
"purpose": "Nix formatting",
"configPaths": [
"flake.nix devShells.default"
]
}
],
"linting": [
{
"name": "statix",
"purpose": "Nix anti-pattern linting",
"configPaths": [
"flake.nix devShells.default"
]
},
{
"name": "deadnix",
"purpose": "Detect unused Nix code",
"configPaths": [
"flake.nix devShells.default"
]
}
],
"testing": [
{
"name": "nix flake show",
"purpose": "Evaluate flake outputs",
"configPaths": [
"flake.nix"
]
},
{
"name": "nixos-rebuild dry-run",
"purpose": "Validate host configurations without applying changes",
"configPaths": [
"flake.nix",
"hosts/*"
]
},
{
"name": "nix build",
"purpose": "Build selected outputs such as host toplevels or ISOs",
"configPaths": [
"flake.nix"
]
}
],
"issueTracking": [
{
"name": "Beads",
"command": "bd",
"purpose": "Persistent task tracking"
}
]
},
"services": [
{
"name": "code.m3ta.dev",
"type": "git hosting",
"url": "git+ssh://gitea@code.m3ta.dev"
},
{
"name": "GitHub",
"type": "flake input hosting",
"url": "github:* flake inputs"
},
{
"name": "Agenix",
"type": "secret encryption",
"url": "github:ryantm/agenix"
},
{
"name": "Hermes Agent",
"type": "NixOS module/agent service",
"url": "github:NousResearch/hermes-agent"
},
{
"name": "RustFS",
"type": "NixOS server service flake",
"url": "github:rustfs/rustfs-flake"
}
],
"externalIntegrations": [
{
"service": "Beads",
"category": "issue tracking",
"enabled": true
},
{
"service": "Dolt",
"category": "Beads storage/sync",
"enabled": true
},
{
"service": "Agenix",
"category": "secrets",
"enabled": true
},
{
"service": "Home Manager",
"category": "user environment",
"enabled": true
},
{
"service": "m3ta-home",
"category": "external home profiles",
"enabled": true
},
{
"service": "m3ta-nixpkgs",
"category": "external Nix modules/packages",
"enabled": true
},
{
"service": "NUR",
"category": "Nix packages",
"enabled": true
},
{
"service": "Disko",
"category": "disk provisioning",
"enabled": true
},
{
"service": "Hermes Agent",
"category": "LLM/agent service",
"enabled": true
}
],
"cicd": {
"provider": null,
"enabled": false,
"configPaths": [],
"pipelines": [],
"notes": "CI/CD is intentionally disabled for now. If re-enabled later, prefer Gitea Actions because this repository is hosted on code.m3ta.dev.",
"babysitterIntegration": {
"enabled": false,
"triggerOn": [],
"processIds": []
}
},
"painPoints": [
{
"id": "pp-architecture-1",
"description": "The repository is transitioning away from a monorepo; boundaries with m3ta-home and m3ta-nixpkgs must remain clear.",
"severity": "high",
"category": "architecture",
"discoveredVia": "user interview",
"suggestedRemediation": "Keep host-specific decisions local while moving reusable Home Manager profiles and package/module abstractions to their dedicated inputs."
},
{
"id": "pp-validation-1",
"description": "A single shared Nix change can require validating several hosts to be confident.",
"severity": "medium",
"category": "validation",
"discoveredVia": "repo structure and AGENTS workflow",
"suggestedRemediation": "Use targeted affected-host validation locally for now; add a Gitea Actions validation matrix later if CI/CD is re-enabled."
},
{
"id": "pp-dependency-1",
"description": "Multiple pinned, locked, stable, master, and external SSH flake inputs increase update complexity.",
"severity": "medium",
"category": "dependency management",
"discoveredVia": "flake and history analysis",
"suggestedRemediation": "Update inputs intentionally, group related updates, and validate affected host outputs."
},
{
"id": "pp-operations-1",
"description": "Service additions often need synchronized module, secret, and network/TLS changes.",
"severity": "medium",
"category": "operations",
"discoveredVia": "git history and tree structure",
"suggestedRemediation": "Use checklist-style issue templates or Babysitter processes for service changes."
}
],
"bottlenecks": [
{
"id": "bn-flake-1",
"description": "flake.nix and flake.lock are high-churn files whose changes can affect many hosts at once.",
"impact": "High; evaluation failures can block all hosts.",
"location": "flake.nix, flake.lock",
"frequency": "very frequent"
},
{
"id": "bn-secrets-1",
"description": "Secret registry and host secret modules must stay aligned with encrypted .age files.",
"impact": "Medium to high; missing or mismatched secrets break host deployment.",
"location": "secrets.nix, hosts/*/secrets.nix, secrets/*.age",
"frequency": "recurring"
},
{
"id": "bn-services-1",
"description": "Server service changes can span service modules, secrets, Traefik/networking, and flake inputs.",
"impact": "High for m3-atlas and m3-hermes changes; requires host-specific dry-runs.",
"location": "hosts/m3-atlas/services, hosts/m3-hermes/services, hosts/common",
"frequency": "frequent"
},
{
"id": "bn-home-1",
"description": "Home Manager behavior depends on both the external m3ta-home input and local host flags.",
"impact": "Medium; may require coordinated updates across repositories.",
"location": "flake.nix, hosts/common/users/m3tam3re.nix, m3ta-home input",
"frequency": "frequent after migration"
}
],
"conventions": {
"naming": {
"files": "hyphen-case for Nix/docs where practical; host directories use m3-* names",
"hosts": "m3-<greek-name>",
"modules": "one module per file/directory where possible",
"nixVariables": "camelCase"
},
"git": {
"branchStrategy": "default feature branches for non-trivial work; master as integration branch",
"commits": "conventional commits for agent work",
"reviews": "optional for solo development",
"releaseCadence": "continuous/manual as needed",
"remote": "code.m3ta.dev over SSH for private inputs and repo access"
},
"codeStyle": {
"formatter": "alejandra",
"indentation": "2 spaces",
"nixStyle": "explicit pkgs references preferred; avoid with pkgs, builtins.fetchTarball, import <nixpkgs>, builtins.getAttr/hasAttr"
},
"importOrder": [
"module function arguments",
"imports",
"let bindings",
"options/config"
],
"errorHandling": "Nix configuration should fail explicitly during evaluation/build; avoid hiding errors or impure paths.",
"testingConventions": "Run alejandra, statix, deadnix as appropriate, nix flake show, and host-specific nixos-rebuild dry-run before switching.",
"additionalRules": [
"Use Beads for persistent task tracking.",
"Use non-interactive flags for shell file operations.",
"Do not modify flake.lock directly; use nix flake update.",
"Do not commit plaintext secrets.",
"Use SSH URLs for code.m3ta.dev flake inputs.",
"Operate Babysitter semi-autonomously with breakpoints for destructive, deployment, or architecture-changing decisions."
]
},
"repositories": [
{
"name": "nixos-config",
"path": "/home/m3tam3re/p/NIX/nixos-config",
"role": "primary multi-host NixOS configuration"
},
{
"name": "m3ta-home",
"url": "git+ssh://gitea@code.m3ta.dev/m3tam3re/m3ta-home",
"role": "external Home Manager profiles"
},
{
"name": "m3ta-nixpkgs",
"url": "git+ssh://gitea@code.m3ta.dev/m3tam3re/nixpkgs",
"role": "external custom packages/modules/overlays"
}
],
"claudeMdInstructions": [
"Respect AGENTS.md as the source of project workflow rules.",
"Resolve the active Babysitter process library before using library processes.",
"Use cradle/project-install for project setup or profile refresh.",
"Use evolutionary GSD: map affected Nix modules/hosts, make focused changes, verify, and iterate.",
"Prefer alejandra, statix, deadnix, nix flake show, and targeted host dry-runs for Nix changes.",
"Preserve boundaries between nixos-config, m3ta-home, and m3ta-nixpkgs.",
"Use breakpoints for destructive operations, deployments, architecture changes, and secret-handling decisions.",
"Babysitter CI/CD is not currently enabled; if re-added later, use Gitea Actions rather than GitHub Actions."
],
"installedSkills": [
"project-install",
"babysit",
"specializations/devops-sre-platform/skills/cicd-pipelines/SKILL.md",
"specializations/devops-sre-platform/skills/gitops/SKILL.md",
"specializations/devops-sre-platform/skills/secrets-management/SKILL.md"
],
"installedAgents": [
"general-purpose",
"specializations/devops-sre-platform/agents/platform-engineer/AGENT.md",
"specializations/devops-sre-platform/agents/cicd-specialist/AGENT.md"
],
"installedProcesses": [
"cradle/project-install",
"methodologies/gsd/quick.js",
"methodologies/gsd/verify-work.js",
"methodologies/gsd/iterative-convergence.js",
"methodologies/evolutionary.js",
"specializations/devops-sre-platform/iac-testing.js"
],
"preferences": {
"babysitterAutonomy": "semi-autonomous",
"breakpointTolerance": "moderate",
"externalIntegrationsRequested": false,
"cicdDesired": false,
"cicdNote": "Deferred for now; Gitea Actions is the preferred provider if CI/CD is added later."
},
"createdAt": "2026-05-29T15:50:48.754Z",
"updatedAt": "2026-05-29T16:07:19.245463Z",
"version": 1
}
-238
View File
@@ -1,238 +0,0 @@
# Project Profile: nixos-config
A reliable, elegant, multi-system NixOS flake configuration for personal desktop, server, cloud, Home Manager, package, overlay, and secret management.
> Last updated: 2026-05-29T16:02:11.092188Z | Version: 1
## Goals
- **reliability** [high]: Keep all managed NixOS systems reproducible, reliable, and easy to validate before deployment. (active)
- **architecture** [high]: Maintain an elegant multi-system architecture with clear host boundaries and reusable common modules. (active)
- **modularization** [high]: Continue breaking up the former monorepo by keeping Home Manager profiles in m3ta-home and custom packages/modules in m3ta-nixpkgs where appropriate. (active)
- **automation** [medium]: CI/CD is not currently configured; add useful Gitea Actions validation later for formatting, linting, flake evaluation, and safe host checks. (deferred)
## Tech Stack
### Languages
- Nix (primary system, module, overlay, and package configuration language)
- Markdown (project, agent, and workflow documentation)
- JSON/YAML (tool configuration and metadata)
### Frameworks
- Nix flakes [reproducible dependency and output model]
- NixOS modules [host and service configuration]
- Home Manager [user environment management]
- Agenix [encrypted secret management]
- Disko [server disk provisioning]
- NUR [community package access]
- llm-agents.nix [LLM agent packages overlay]
- m3ta-home [external reusable Home Manager profiles]
- m3ta-nixpkgs [external custom packages/modules/overlays]
### Infrastructure
- m3-ares [desktop NixOS host]
- m3-kratos [desktop NixOS host]
- m3-daedalus [portable laptop/Home Manager configuration]
- m3-atlas [primary server NixOS host]
- m3-helios [minimal server/AdGuard host]
- m3-hermes [secondary server/Hermes host]
- m3-aether [cloud VM/minimal server host]
**Build tools:** nix, nixos-rebuild, nix build, nix flake show, alejandra, statix, deadnix
**Package managers:** nix flakes
## Architecture
**Pattern:** Pure Nix flake-based NixOS configuration repository with host-specific modules, common shared modules, overlays, custom packages, agenix secrets, and externalized Home Manager/package inputs.
**Data flow:** flake.nix wires inputs, overlays, packages, NixOS modules, and Home Manager. Host modules import common configuration and host-specific hardware/programs/services/secrets. Host profile flags in hosts/common/users/m3tam3re.nix feed the external m3ta-home mkHome integration. Secrets flow through agenix registry and host secret modules.
### Modules
| Module | Path | Description |
|--------|------|-------------|
| flake.nix | `flake.nix` | Top-level entry point defining inputs, packages, overlays, Home Manager modules, NixOS configurations, and dev shells. |
| hosts/common | `hosts/common` | Shared NixOS configuration, nix settings, overlays, Home Manager setup, ports, extra services, and users. |
| hosts | `hosts` | Per-host NixOS/Home Manager configurations for desktops, servers, and cloud VM. |
| modules/nixos | `modules/nixos` | Reusable NixOS modules. |
| modules/home-manager | `modules/home-manager` | Reusable Home Manager module exports. |
| overlays | `overlays` | Nixpkgs overlays for stable, locked, pinned, master, temporary, and agent packages. |
| pkgs | `pkgs` | Custom package export set. |
| secrets | `secrets` | Encrypted agenix secret files and registry. |
**Entry points:** `flake.nix`, `hosts/<host>/default.nix`, `hosts/<host>/configuration.nix`, `hosts/common/default.nix`, `hosts/common/users/m3tam3re.nix`, `overlays/default.nix`, `pkgs/default.nix`, `secrets.nix`
## Team
- **m3tam3re** (solo developer and operator): architecture, implementation, host maintenance, deployments, review
- **m3ta-chiron** (agent contributor): semi-autonomous implementation, validation, documentation updates, conventional commits
## Workflows
### development
Default feature-branch workflow for solo development with conventional commits and validation before push.
**Triggers:** new feature, bug fix, refactor, agent task
1. review Beads issues with bd ready --json
2. claim work with bd update <id> --claim when applicable
3. edit Nix modules or project files
4. run alejandra .
5. run statix check .
6. run targeted nix flake or host dry-run checks
7. commit with conventional commit format
8. pull --rebase and push
### nix validation
Quality gate for Nix configuration changes.
**Triggers:** Nix code changes, before deployment, before commit
1. alejandra .
2. statix check .
3. deadnix check or deadnix -w when appropriate
4. nix flake show
5. sudo nixos-rebuild dry-run --flake .#<host> for affected hosts
### host deployment
Manual deployment after successful dry-run validation.
**Triggers:** manual host update
1. sudo nixos-rebuild dry-run --flake .#<host>
2. sudo nixos-rebuild switch --flake .#<host>
### dependency/input update
Controlled flake input updates without manually editing flake.lock.
**Triggers:** planned dependency update, security update
1. use nix flake update or nixos-rebuild --update-input <input>
2. validate affected outputs
3. commit flake.nix/flake.lock changes
### beads issue tracking
Persistent issue tracking and session handoff workflow.
**Triggers:** start of tracked work, completion of tracked work
1. bd ready --json
2. bd show <id>
3. bd update <id> --claim
4. bd close <id> --reason <summary>
5. bd dolt push
## Processes
- **Babysitter project install** (`cradle/project-install`, undefined)
## Tools
### Linting
- statix
- deadnix
### Testing
- nix flake show
- nixos-rebuild dry-run
- nix build
### Formatting
- alejandra
## Services
- **code.m3ta.dev** (git hosting) - git+ssh://gitea@code.m3ta.dev
- **GitHub** (flake input hosting) - github:* flake inputs
- **Agenix** (secret encryption) - github:ryantm/agenix
- **Hermes Agent** (NixOS module/agent service) - github:NousResearch/hermes-agent
- **RustFS** (NixOS server service flake) - github:rustfs/rustfs-flake
## CI/CD
**Status:** Not configured/enabled for now.
No Babysitter CI/CD workflow is currently installed. If CI/CD is added later, prefer Gitea Actions because this repository is hosted on code.m3ta.dev.
## Pain Points
- **high** [architecture]: The repository is transitioning away from a monorepo; boundaries with m3ta-home and m3ta-nixpkgs must remain clear.
- Remediation: Keep host-specific decisions local while moving reusable Home Manager profiles and package/module abstractions to their dedicated inputs.
- **medium** [validation]: A single shared Nix change can require validating several hosts to be confident.
- Remediation: Use targeted affected-host validation locally for now; add a Gitea Actions validation matrix later if CI/CD is re-enabled.
- **medium** [dependency management]: Multiple pinned, locked, stable, master, and external SSH flake inputs increase update complexity.
- Remediation: Update inputs intentionally, group related updates, and validate affected host outputs.
- **medium** [operations]: Service additions often need synchronized module, secret, and network/TLS changes.
- Remediation: Use checklist-style issue templates or Babysitter processes for service changes.
## Bottlenecks
- flake.nix and flake.lock are high-churn files whose changes can affect many hosts at once. at flake.nix, flake.lock (very frequent)
Impact: High; evaluation failures can block all hosts.
- Secret registry and host secret modules must stay aligned with encrypted .age files. at secrets.nix, hosts/*/secrets.nix, secrets/*.age (recurring)
Impact: Medium to high; missing or mismatched secrets break host deployment.
- Server service changes can span service modules, secrets, Traefik/networking, and flake inputs. at hosts/m3-atlas/services, hosts/m3-hermes/services, hosts/common (frequent)
Impact: High for m3-atlas and m3-hermes changes; requires host-specific dry-runs.
- Home Manager behavior depends on both the external m3ta-home input and local host flags. at flake.nix, hosts/common/users/m3tam3re.nix, m3ta-home input (frequent after migration)
Impact: Medium; may require coordinated updates across repositories.
## Conventions
### Naming
- **files:** hyphen-case for Nix/docs where practical; host directories use m3-* names
- **hosts:** m3-<greek-name>
- **modules:** one module per file/directory where possible
- **nixVariables:** camelCase
### Git
- **branchStrategy:** default feature branches for non-trivial work; master as integration branch
- **commits:** conventional commits for agent work
- **reviews:** optional for solo development
- **releaseCadence:** continuous/manual as needed
- **remote:** code.m3ta.dev over SSH for private inputs and repo access
**Import order:** module function arguments > imports > let bindings > options/config
**Error handling:** Nix configuration should fail explicitly during evaluation/build; avoid hiding errors or impure paths.
**Testing:** Run alejandra, statix, deadnix as appropriate, nix flake show, and host-specific nixos-rebuild dry-run before switching.
### Additional Rules
- Use Beads for persistent task tracking.
- Use non-interactive flags for shell file operations.
- Do not modify flake.lock directly; use nix flake update.
- Do not commit plaintext secrets.
- Use SSH URLs for code.m3ta.dev flake inputs.
- Operate Babysitter semi-autonomously with breakpoints for destructive, deployment, or architecture-changing decisions.
## Repositories
- **nixos-config** [`/home/m3tam3re/p/NIX/nixos-config`]
- **m3ta-home** - git+ssh://gitea@code.m3ta.dev/m3tam3re/m3ta-home
- **m3ta-nixpkgs** - git+ssh://gitea@code.m3ta.dev/m3tam3re/nixpkgs
## CLAUDE.md Instructions
- Respect AGENTS.md as the source of project workflow rules.
- Resolve the active Babysitter process library before using library processes.
- Use cradle/project-install for project setup or profile refresh.
- Use evolutionary GSD: map affected Nix modules/hosts, make focused changes, verify, and iterate.
- Prefer alejandra, statix, deadnix, nix flake show, and targeted host dry-runs for Nix changes.
- Preserve boundaries between nixos-config, m3ta-home, and m3ta-nixpkgs.
- Use breakpoints for destructive operations, deployments, architecture changes, and secret-handling decisions.
- Babysitter CI/CD is not currently enabled; if re-added later, use Gitea Actions rather than GitHub Actions.
## Installed Extensions
- Skills: project-install, babysit, specializations/devops-sre-platform/skills/cicd-pipelines/SKILL.md, specializations/devops-sre-platform/skills/gitops/SKILL.md, specializations/devops-sre-platform/skills/secrets-management/SKILL.md
- Agents: general-purpose, specializations/devops-sre-platform/agents/platform-engineer/AGENT.md, specializations/devops-sre-platform/agents/cicd-specialist/AGENT.md
- Processes: cradle/project-install, methodologies/gsd/quick.js, methodologies/gsd/verify-work.js, methodologies/gsd/iterative-convergence.js, methodologies/evolutionary.js, specializations/devops-sre-platform/iac-testing.js
-53
View File
@@ -1,53 +0,0 @@
{
"qualityThreshold": 80,
"testCoverage": {
"minimum": 0,
"rationale": "NixOS configuration repository without a coverage-producing test suite."
},
"formatting": [
{
"name": "alejandra",
"command": "alejandra .",
"ciCommand": "alejandra --check ."
}
],
"linting": [
{
"name": "statix",
"command": "statix check ."
},
{
"name": "deadnix",
"command": "deadnix . --fail"
}
],
"evaluation": [
{
"name": "flake outputs",
"command": "nix flake show"
},
{
"name": "affected host dry-run",
"command": "sudo nixos-rebuild dry-run --flake .#<host>",
"when": "Run for affected hosts when practical and safe."
}
],
"commitChecks": [
"alejandra .",
"statix check .",
"deadnix . --fail",
"nix flake show"
],
"deployGates": [
"formatting passes",
"linting passes",
"flake outputs evaluate",
"affected host dry-run succeeds",
"secrets are encrypted and host secret modules remain aligned"
],
"cicdIntegrationPoints": [],
"cicd": {
"enabled": false,
"notes": "No CI/CD integration is currently configured. Add Gitea Actions later if automated Babysitter or Nix validation is desired."
}
}
-73
View File
@@ -1,73 +0,0 @@
# Dolt database (managed by Dolt, not git)
dolt/
embeddeddolt/
# Runtime files
bd.sock
bd.sock.startlock
sync-state.json
last-touched
.exclusive-lock
# Daemon runtime (lock, log, pid)
daemon.*
# Interactions log (runtime, not versioned)
interactions.jsonl
# Push state (runtime, per-machine)
push-state.json
# Lock files (various runtime locks)
*.lock
# Credential key (encryption key for federation peer auth — never commit)
.beads-credential-key
# Local version tracking (prevents upgrade notification spam after git ops)
.local_version
# Worktree redirect file (contains relative path to main repo's .beads/)
# Must not be committed as paths would be wrong in other clones
redirect
# Sync state (local-only, per-machine)
# These files are machine-specific and should not be shared across clones
.sync.lock
export-state/
export-state.json
# Ephemeral store (SQLite - wisps/molecules, intentionally not versioned)
ephemeral.sqlite3
ephemeral.sqlite3-journal
ephemeral.sqlite3-wal
ephemeral.sqlite3-shm
# Dolt server management (auto-started by bd)
dolt-server.pid
dolt-server.log
dolt-server.lock
dolt-server.port
dolt-server.activity
# Corrupt backup directories (created by bd doctor --fix recovery)
*.corrupt.backup/
# Backup data (auto-exported JSONL, local-only)
backup/
# Per-project environment file (Dolt connection config, GH#2520)
.env
# Legacy files (from pre-Dolt versions)
*.db
*.db?*
*.db-journal
*.db-wal
*.db-shm
db.sqlite
bd.db
# NOTE: Do NOT add negation patterns here.
# They would override fork protection in .git/info/exclude.
# Config files (metadata.json, config.yaml) are tracked by git by default
# since no pattern above ignores them.
-81
View File
@@ -1,81 +0,0 @@
# Beads - AI-Native Issue Tracking
Welcome to Beads! This repository uses **Beads** for issue tracking - a modern, AI-native tool designed to live directly in your codebase alongside your code.
## What is Beads?
Beads is issue tracking that lives in your repo, making it perfect for AI coding agents and developers who want their issues close to their code. No web UI required - everything works through the CLI and integrates seamlessly with git.
**Learn more:** [github.com/steveyegge/beads](https://github.com/steveyegge/beads)
## Quick Start
### Essential Commands
```bash
# Create new issues
bd create "Add user authentication"
# View all issues
bd list
# View issue details
bd show <issue-id>
# Update issue status
bd update <issue-id> --claim
bd update <issue-id> --status done
# Sync with Dolt remote
bd dolt push
```
### Working with Issues
Issues in Beads are:
- **Git-native**: Stored in Dolt database with version control and branching
- **AI-friendly**: CLI-first design works perfectly with AI coding agents
- **Branch-aware**: Issues can follow your branch workflow
- **Always in sync**: Auto-syncs with your commits
## Why Beads?
**AI-Native Design**
- Built specifically for AI-assisted development workflows
- CLI-first interface works seamlessly with AI coding agents
- No context switching to web UIs
🚀 **Developer Focused**
- Issues live in your repo, right next to your code
- Works offline, syncs when you push
- Fast, lightweight, and stays out of your way
🔧 **Git Integration**
- Automatic sync with git commits
- Branch-aware issue tracking
- Dolt-native three-way merge resolution
## Get Started with Beads
Try Beads in your own projects:
```bash
# Install Beads
curl -sSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash
# Initialize in your repo
bd init
# Create your first issue
bd create "Try out Beads"
```
## Learn More
- **Documentation**: [github.com/steveyegge/beads/docs](https://github.com/steveyegge/beads/tree/main/docs)
- **Quick Start Guide**: Run `bd quickstart`
- **Examples**: [github.com/steveyegge/beads/examples](https://github.com/steveyegge/beads/tree/main/examples)
---
*Beads: Issue tracking that moves at the speed of thought*
-56
View File
@@ -1,56 +0,0 @@
# Beads Configuration File
# This file configures default behavior for all bd commands in this repository
# All settings can also be set via environment variables (BD_* prefix)
# or overridden with command-line flags
# Issue prefix for this repository (used by bd init)
# If not set, bd init will auto-detect from directory name
# Example: issue-prefix: "myproject" creates issues like "myproject-1", "myproject-2", etc.
# issue-prefix: ""
# Use no-db mode: JSONL-only, no Dolt database
# When true, bd will use .beads/issues.jsonl as the source of truth
# no-db: false
# Enable JSON output by default
# json: false
# Feedback title formatting for mutating commands (create/update/close/dep/edit)
# 0 = hide titles, N > 0 = truncate to N characters
# output:
# title-length: 255
# Default actor for audit trails (overridden by BEADS_ACTOR or --actor)
# actor: ""
# Export events (audit trail) to .beads/events.jsonl on each flush/sync
# When enabled, new events are appended incrementally using a high-water mark.
# Use 'bd export --events' to trigger manually regardless of this setting.
# events-export: false
# Multi-repo configuration (experimental - bd-307)
# Allows hydrating from multiple repositories and routing writes to the correct database
# repos:
# primary: "." # Primary repo (where this database lives)
# additional: # Additional repos to hydrate from (read-only)
# - ~/beads-planning # Personal planning repo
# - ~/work-planning # Work planning repo
# JSONL backup (periodic export for off-machine recovery)
# Auto-enabled when a git remote exists. Override explicitly:
# backup:
# enabled: false # Disable auto-backup entirely
# interval: 15m # Minimum time between auto-exports
# git-push: false # Disable git push (export locally only)
# git-repo: "" # Separate git repo for backups (default: project repo)
# Integration settings (access with 'bd config get/set')
# These are stored in the database, not in this file:
# - jira.url
# - jira.project
# - linear.url
# - linear.api-key
# - github.org
# - github.repo
sync.remote: "git+ssh://gitea@code.m3ta.dev/m3tam3re/nixos-config.git"
-24
View File
@@ -1,24 +0,0 @@
#!/usr/bin/env sh
# --- BEGIN BEADS INTEGRATION v1.0.3 ---
# This section is managed by beads. Do not remove these markers.
if command -v bd >/dev/null 2>&1; then
export BD_GIT_HOOK=1
_bd_timeout=${BEADS_HOOK_TIMEOUT:-300}
if command -v timeout >/dev/null 2>&1; then
timeout "$_bd_timeout" bd hooks run post-checkout "$@"
_bd_exit=$?
if [ $_bd_exit -eq 124 ]; then
echo >&2 "beads: hook 'post-checkout' timed out after ${_bd_timeout}s — continuing without beads"
_bd_exit=0
fi
else
bd hooks run post-checkout "$@"
_bd_exit=$?
fi
if [ $_bd_exit -eq 3 ]; then
echo >&2 "beads: database not initialized — skipping hook 'post-checkout'"
_bd_exit=0
fi
if [ $_bd_exit -ne 0 ]; then exit $_bd_exit; fi
fi
# --- END BEADS INTEGRATION v1.0.3 ---
-24
View File
@@ -1,24 +0,0 @@
#!/usr/bin/env sh
# --- BEGIN BEADS INTEGRATION v1.0.3 ---
# This section is managed by beads. Do not remove these markers.
if command -v bd >/dev/null 2>&1; then
export BD_GIT_HOOK=1
_bd_timeout=${BEADS_HOOK_TIMEOUT:-300}
if command -v timeout >/dev/null 2>&1; then
timeout "$_bd_timeout" bd hooks run post-merge "$@"
_bd_exit=$?
if [ $_bd_exit -eq 124 ]; then
echo >&2 "beads: hook 'post-merge' timed out after ${_bd_timeout}s — continuing without beads"
_bd_exit=0
fi
else
bd hooks run post-merge "$@"
_bd_exit=$?
fi
if [ $_bd_exit -eq 3 ]; then
echo >&2 "beads: database not initialized — skipping hook 'post-merge'"
_bd_exit=0
fi
if [ $_bd_exit -ne 0 ]; then exit $_bd_exit; fi
fi
# --- END BEADS INTEGRATION v1.0.3 ---
-24
View File
@@ -1,24 +0,0 @@
#!/usr/bin/env sh
# --- BEGIN BEADS INTEGRATION v1.0.3 ---
# This section is managed by beads. Do not remove these markers.
if command -v bd >/dev/null 2>&1; then
export BD_GIT_HOOK=1
_bd_timeout=${BEADS_HOOK_TIMEOUT:-300}
if command -v timeout >/dev/null 2>&1; then
timeout "$_bd_timeout" bd hooks run pre-commit "$@"
_bd_exit=$?
if [ $_bd_exit -eq 124 ]; then
echo >&2 "beads: hook 'pre-commit' timed out after ${_bd_timeout}s — continuing without beads"
_bd_exit=0
fi
else
bd hooks run pre-commit "$@"
_bd_exit=$?
fi
if [ $_bd_exit -eq 3 ]; then
echo >&2 "beads: database not initialized — skipping hook 'pre-commit'"
_bd_exit=0
fi
if [ $_bd_exit -ne 0 ]; then exit $_bd_exit; fi
fi
# --- END BEADS INTEGRATION v1.0.3 ---
-24
View File
@@ -1,24 +0,0 @@
#!/usr/bin/env sh
# --- BEGIN BEADS INTEGRATION v1.0.3 ---
# This section is managed by beads. Do not remove these markers.
if command -v bd >/dev/null 2>&1; then
export BD_GIT_HOOK=1
_bd_timeout=${BEADS_HOOK_TIMEOUT:-300}
if command -v timeout >/dev/null 2>&1; then
timeout "$_bd_timeout" bd hooks run pre-push "$@"
_bd_exit=$?
if [ $_bd_exit -eq 124 ]; then
echo >&2 "beads: hook 'pre-push' timed out after ${_bd_timeout}s — continuing without beads"
_bd_exit=0
fi
else
bd hooks run pre-push "$@"
_bd_exit=$?
fi
if [ $_bd_exit -eq 3 ]; then
echo >&2 "beads: database not initialized — skipping hook 'pre-push'"
_bd_exit=0
fi
if [ $_bd_exit -ne 0 ]; then exit $_bd_exit; fi
fi
# --- END BEADS INTEGRATION v1.0.3 ---
-24
View File
@@ -1,24 +0,0 @@
#!/usr/bin/env sh
# --- BEGIN BEADS INTEGRATION v1.0.3 ---
# This section is managed by beads. Do not remove these markers.
if command -v bd >/dev/null 2>&1; then
export BD_GIT_HOOK=1
_bd_timeout=${BEADS_HOOK_TIMEOUT:-300}
if command -v timeout >/dev/null 2>&1; then
timeout "$_bd_timeout" bd hooks run prepare-commit-msg "$@"
_bd_exit=$?
if [ $_bd_exit -eq 124 ]; then
echo >&2 "beads: hook 'prepare-commit-msg' timed out after ${_bd_timeout}s — continuing without beads"
_bd_exit=0
fi
else
bd hooks run prepare-commit-msg "$@"
_bd_exit=$?
fi
if [ $_bd_exit -eq 3 ]; then
echo >&2 "beads: database not initialized — skipping hook 'prepare-commit-msg'"
_bd_exit=0
fi
if [ $_bd_exit -ne 0 ]; then exit $_bd_exit; fi
fi
# --- END BEADS INTEGRATION v1.0.3 ---
-3
View File
@@ -1,3 +0,0 @@
{"_type":"issue","id":"home-profile-restructuring-edz","title":"Create copy-hermes-skills systemd service","status":"closed","priority":1,"issue_type":"task","assignee":"m3tm3re","owner":"p@m3ta.dev","estimated_minutes":1,"created_at":"2026-04-26T12:30:10Z","created_by":"m3tm3re","updated_at":"2026-04-26T12:44:42Z","started_at":"2026-04-26T12:36:30Z","closed_at":"2026-04-26T12:44:42Z","close_reason":"Created systemd service in hosts/m3-hermes/services/hermes-agent.nix - copies skills to /var/lib/hermes/.agents/skills before hermes-agent starts","labels":["hermes-agent","nixos"],"dependencies":[{"issue_id":"home-profile-restructuring-edz","depends_on_id":"home-profile-restructuring-ycz","type":"blocks","created_at":"2026-04-26T14:30:57Z","created_by":"m3tm3re","metadata":"{}"}],"dependency_count":1,"dependent_count":1,"comment_count":0}
{"_type":"issue","id":"home-profile-restructuring-ycz","title":"Build hermes-agent skills using mkOpencodeSkills","status":"closed","priority":1,"issue_type":"task","assignee":"m3tm3re","owner":"p@m3ta.dev","estimated_minutes":2,"created_at":"2026-04-26T12:30:09Z","created_by":"m3tm3re","updated_at":"2026-04-26T12:35:15Z","started_at":"2026-04-26T12:31:35Z","closed_at":"2026-04-26T12:35:15Z","close_reason":"Added inputs to module signature and defined hermesSkills via inputs.agents.lib.mkOpencodeSkills with basecamp, anthropic, and kestra external skills. Verified with nixos-rebuild dry-run --flake .#m3-hermes (no errors).","labels":["hermes-agent","nixos"],"dependency_count":0,"dependent_count":1,"comment_count":0}
{"_type":"issue","id":"home-profile-restructuring-cxa","title":"Verify skills available at /var/lib/hermes/.agents/skills","status":"closed","priority":2,"issue_type":"task","assignee":"m3tm3re","owner":"p@m3ta.dev","estimated_minutes":1,"created_at":"2026-04-26T12:30:10Z","created_by":"m3tm3re","updated_at":"2026-04-26T12:50:58Z","started_at":"2026-04-26T12:38:15Z","closed_at":"2026-04-26T12:50:58Z","close_reason":"Manually verified - skills are present at /var/lib/hermes/.agents/skills on m3-hermes","labels":["hermes-agent","testing"],"dependencies":[{"issue_id":"home-profile-restructuring-cxa","depends_on_id":"home-profile-restructuring-edz","type":"blocks","created_at":"2026-04-26T14:30:57Z","created_by":"m3tm3re","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
-7
View File
@@ -1,7 +0,0 @@
{
"database": "dolt",
"backend": "dolt",
"dolt_mode": "embedded",
"dolt_database": "home_profile_restructuring",
"project_id": "664fc7e3-94eb-4874-aab6-e47835abe9d8"
}
-3
View File
@@ -1,3 +0,0 @@
# Use bd merge for beads JSONL files
.beads/issues.jsonl merge=beads
-55
View File
@@ -1,55 +0,0 @@
# Sisyphus work session data
.sisyphus/
# Editor files
*~
.*.swp
.*.swo
.*.swx
# Build artifacts
result
result-*
.direnv/
# IDE
.vscode/
.idea/
*.iml
# OS
.DS_Store
Thumbs.db
# Opencode rules
.opencode-rules
opencode.json
# AI agent state
.claude/
.sidecar/
.sidecar-*
.sisyphus/
.sidecar-agent
.sidecar-task
.sidecar-pr
.sidecar-start.sh
.sidecar-base
.td-root
.cache
.pi*
.worktrees/
docs/plans/
CLAUDE.md
# Beads / Dolt files (added by bd init)
.dolt/
*.db
.beads-credential-key
# --- babysitter managed ---
.a5c/creds.env
.a5c/creds.env.tmp.*
.a5c/logs/
.a5c/runs/
# --- end babysitter managed ---
-445
View File
@@ -1,445 +0,0 @@
# Agent Instructions
This project uses **bd** (beads) for issue tracking. Run `bd prime` for full workflow context.
## Quick Reference
```bash
bd ready # Find available work
bd show <id> # View issue details
bd update <id> --claim # Claim work atomically
bd close <id> # Complete work
bd dolt push # Push beads data to remote
```
## Non-Interactive Shell Commands
**ALWAYS use non-interactive flags** with file operations to avoid hanging on confirmation prompts.
Shell commands like `cp`, `mv`, and `rm` may be aliased to include `-i` (interactive) mode on some systems, causing the agent to hang indefinitely waiting for y/n input.
**Use these forms instead:**
```bash
# Force overwrite without prompting
cp -f source dest # NOT: cp source dest
mv -f source dest # NOT: mv source dest
rm -f file # NOT: rm file
# For recursive operations
rm -rf directory # NOT: rm -r directory
cp -rf source dest # NOT: cp -r source dest
```
**Other commands that may prompt:**
- `scp` - use `-o BatchMode=yes` for non-interactive
- `ssh` - use `-o BatchMode=yes` to fail instead of prompting
- `apt-get` - use `-y` flag
- `brew` - use `HOMEBREW_NO_AUTO_UPDATE=1` env var
<!-- BEGIN BEADS INTEGRATION v:1 profile:minimal hash:ca08a54f -->
## Beads Issue Tracker
This project uses **bd (beads)** for persistent task tracking. Run `bd prime` for full workflow context.
### Why Beads?
- **Prefer Beads over ad-hoc markdown TODO lists** — Beads provides structured, queryable, shareable issue tracking with dependency management
- **Never use `bd edit`** — it opens an interactive editor which blocks agent workflows
- **Use flags and stdin instead** — `bd update <id> --claim`, `bd create --title "..." --estimate 2`
### Slash Commands (Agent Workflow)
| Command | Purpose |
|---------|---------|
| `/beads:ready` | Find unblocked issues |
| `/beads:create` | Create a new issue |
| `/beads:update` | Update an issue (claim, status) |
| `/beads:close` | Close completed work |
| `/beads:stats` | Project-level snapshot |
### Core Workflow (6 Steps)
#### 1. Find Unblocked Work
```bash
bd ready --json
```
Lists issues with no blocking dependencies that are ready to work on.
#### 2. Claim Work
```bash
bd update <id> --claim
```
Atomically assigns the issue to you (sets status to "in-progress").
#### 3. Inspect Details
```bash
bd show <id>
```
View full issue details including:
- Description and acceptance criteria
- Blocking/blocked-by dependencies
- Time estimates
- Status history
#### 4. Create Newly Discovered Work
```bash
# Create a new issue
bd create \
--title "Fix audio on m3-helios" \
--estimate 2 \
--priority high \
--labels nixos,audio
# Link dependencies
bd dep <id> --blocks <blocked-id> # This issue blocks another
bd dep <id> --after <after-id> # This issue after another completes
bd dep <id> --requires <requires-id> # This issue requires another
```
#### 5. Complete Work
```bash
bd close <id> --reason "Added PulseAudio fallback to configuration.nix"
```
Provide a concise summary of what was done. The `--reason` is mandatory.
#### 6. Project Snapshot
```bash
bd status --json # Current state of all issues
bd stats # Metrics: velocity, cycle time, bottlenecks
```
### Example Complete Workflow
```bash
# Start session - find work
bd ready --json
# Claim available issue
bd update 42 --claim
# Do the work...
# Discover something else needed
bd create --title "Document hermes-agent setup" --estimate 1
# Link as related
bd dep 43 --after 42
# Complete original
bd close 42 --reason "Added Hyprland idle timeout config"
# Close related
bd close 43 --reason "Added setup docs to AGENTS.md"
# Push state to remote
bd dolt push
```
### Rules
- Use `bd` for ALL task tracking — do NOT use TodoWrite, TaskCreate, or markdown TODO lists
- Run `bd prime` for detailed command reference and session close protocol
- Use `bd remember` for persistent knowledge — do NOT use MEMORY.md files
## Session Completion
**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds.
**MANDATORY WORKFLOW:**
1. **File issues for remaining work** - Create issues for anything that needs follow-up
2. **Run quality gates** (if code changed) - Tests, linters, builds
3. **Update issue status** - Close finished work, update in-progress items
4. **PUSH TO REMOTE** - This is MANDATORY:
```bash
git pull --rebase
bd dolt push
git push
git status # MUST show "up to date with origin"
```
5. **Clean up** - Clear stashes, prune remote branches
6. **Verify** - All changes committed AND pushed
7. **Hand off** - Provide context for next session
**CRITICAL RULES:**
- Work is NOT complete until `git push` succeeds
- NEVER stop before pushing - that leaves work stranded locally
- NEVER say "ready to push when you are" - YOU must push
- If push fails, resolve and retry until it succeeds
<!-- END BEADS INTEGRATION -->
# Project Agent
**Workspace Path:** `/home/m3tam3re/p/NIX/nixos-config`
_(Note to Pi: Your file write/edit tools run in a different directory by default. You MUST use absolute paths starting with the Workspace Path above for ALL file operations!)_
**Generated:** 2026-04-26
---
## Stack
| Component | Version/Source |
| ---------------- | --------------------------------- |
| **Nixpkgs** | nixos-unstable + 25.05 stable |
| **Home Manager** | github:nix-community/home-manager |
| **m3ta-home** | code.m3ta.dev/m3tam3re/m3ta-home |
| **m3ta-nixpkgs** | code.m3ta.dev/m3tam3re/nixpkgs |
| **Agenix** | github:ryantm/agenix |
| **Disko** | github:nix-community/disko |
| **NUR** | github:nix-community/NUR |
| **Formatter** | alejandra |
| **Linters** | statix, deadnix |
| **IDE** | nixd |
| **Hermes Agent** | NousResearch/hermes-agent |
| **LLM Agents** | numtide/llm-agents.nix |
---
## Structure
```
nixos-config/
├── flake.nix # Entry point: hosts, overlays, dev shells, m3ta-home input
├── coding-rules.json # Opencode rules configuration
├── hosts/ # Per-host NixOS configurations
│ ├── common/ # Shared across all hosts
│ │ ├── users/
│ │ │ └── m3tam3re.nix # ← Central user + m3ta-home integration
│ │ ├── default.nix # Shared NixOS settings, overlays, home-manager setup
│ │ ├── ports.nix # Network ports config
│ │ └── extraServices/ # Common service toggles
│ ├── m3-ares/ # TUXEDO laptop (desktop)
│ │ └── home.nix # Hyprland: eDP-1 + HDMI, XDG/MIME
│ ├── m3-kratos/ # AMD desktop (desktop)
│ │ └── home.nix # Hyprland: dual DP, XDG/MIME
│ ├── m3-daedalus/ # Portable laptop (desktop, no Hyprland)
│ │ └── home.nix # XDG/MIME only
│ ├── m3-atlas/ # Primary server (server + coding)
│ ├── m3-helios/ # AdGuard DNS server (minimal server)
│ ├── m3-hermes/ # Secondary server (minimal server)
│ └── m3-aether/ # Cloud VM (minimal server)
├── modules/ # Reusable NixOS modules
│ └── nixos/ # NixOS-specific modules
├── overlays/ # Package overlays (stable/locked/master/pinned)
│ ├── default.nix
│ └── mods/
├── pkgs/ # Custom packages
├── secrets/ # Encrypted secrets (agenix)
│ └── secrets.nix
├── .opencode-rules/ # Opencode AI rules
│ ├── concerns/
│ ├── languages/nix.md
│ └── USAGE.md
└── .pi/ # Agent configuration
```
### Home-Manager Integration
Home-Manager configs are managed centrally in the **`m3ta-home`** repository:
- **Repo**: `code.m3ta.dev/m3tam3re/m3ta-home`
- **Docs**: See m3ta-home README for full documentation
What lives where:
| Concern | Location | Why |
|---------|----------|-----|
| Shell, CLI tools, editors, apps | `m3ta-home/profiles/` | Portable across all hosts |
| User identity (git, SSH, JJ) | `m3ta-home/users/` | Switchable: private vs work |
| Feature flags (enable/disable) | `nixos-config/hosts/common/users/m3tam3re.nix` | Per-host decisions |
| Monitor layouts, window rules | `nixos-config/hosts/<name>/home.nix` | Hardware-specific |
| XDG/MIME defaults | `nixos-config/hosts/<name>/home.nix` | Host-specific preferences |
| NixOS overlays | `nixos-config/overlays/` | System-level package management |
#### Host → Profile Mapping
Defined in `hosts/common/users/m3tam3re.nix`:
```nix
hostProfiles = {
# Desktop hosts
m3-ares = { context = "desktop"; sets = ["coding" "gaming" "media"]; };
m3-kratos = { context = "desktop"; sets = ["coding" "gaming" "media"]; };
m3-daedalus = { context = "desktop"; sets = ["coding" "media"]; };
# Server hosts
m3-atlas = { context = "server"; sets = ["coding"]; };
m3-helios = { context = "server"; sets = []; };
m3-hermes = { context = "server"; sets = []; };
m3-aether = { context = "server"; sets = []; };
};
```
#### Work Identity Use Case
The same `m3ta-home` repo supports a **work identity** for company machines:
```nix
# On a work NixOS machine:
(m3ta-lib.mkHome {
user = "m3tam3re";
identity = "work"; # ← switches git to sascha.koenig, SSH to AZ hosts
context = "desktop";
sets = ["coding"];
})
```
This provides the familiar shell/editor/CLI setup but with work git credentials and SSH configuration.
---
## Commands
| Action | Command | Notes |
| -------------------- | ---------------------------------------------------------------------- | ------------------------------------------------- |
| **Enter dev shell** | `nix develop` | Includes alejandra, nixd, agenix, statix, deadnix |
| **Build host** | `sudo nixos-rebuild switch --flake .#m3-ares` | Replace hostname as needed |
| **Dry run build** | `sudo nixos-rebuild dry-run --flake .#m3-ares` | Validate without applying |
| **List hosts** | `nix flake show` | Shows all NixOS configurations |
| **Update flake** | `sudo nixos-rebuild switch --flake .#m3-ares --update-input nixpkgs` | Update specific input |
| **Format code** | `alejandra .` | Run before committing |
| **Check lint** | `statix check .` | Run statix for antipatterns |
| **Remove dead code** | `deadnix -w .` | Clean up unused let bindings |
| **Build ISO** | `nix build .#nixosConfigurations.m3-ares.config.system.build.isoImage` | Generate install ISO |
---
## Conventions
### Formatting & Style
- **Formatter:** `alejandra` (mandatory, run before commits)
- **Indentation:** 2 spaces (alejandra default)
- **Variables:** camelCase (e.g., `maxRetryAttempts`)
- **Types/Modules:** PascalCase (e.g., `MyService`)
- **Constants:** UPPER_SNAKE_CASE (e.g., `MAX_RETRIES`)
- **Files:** hyphen-case (e.g., `my-file.nix`)
### Nix Module Patterns
```nix
{ config, lib, pkgs, ... }:
{
options.myService.enable = lib.mkEnableOption "my service";
config = lib.mkIf config.myService.enable {
services.myService.enable = true;
};
}
```
### Conditionals
```nix
config = lib.mkMerge [
(lib.mkIf cfg.enable { ... })
(lib.mkIf cfg.extraConfig { ... })
];
```
### Anti-Patterns (AVOID)
- **Never use `with pkgs;`** — always use explicit package references
- **Never use `builtins.fetchTarball`** — use flake inputs instead
- **Never use `import <nixpkgs>`** — always use inputs
- **Never use `builtins.getAttr/hasAttr`** — use `lib.attrByPath` or `lib.optionalAttrs`
- **Avoid anonymous functions in config** — extract to named lets
### Imports
- Use flake inputs for dependencies (e.g., `inputs.home-manager.nixosModules.home-manager`)
- Import relative paths with `./` or `../`
- Never use absolute paths in imports
### Secrets
- Secrets managed via **agenix** in `secrets/` directory
- Never commit plaintext secrets
- Use `.nix` extension for secret files
### Flake Input URLs
All `code.m3ta.dev` inputs use **SSH** URLs:
```nix
url = "git+ssh://gitea@code.m3ta.dev/m3tam3re/<repo>";
```
Anonymous HTTPS git on Gitea is unreliable and prompts for auth. SSH works with configured keys.
---
## Key Files
| File | Purpose |
| ---------------------------------- | ------------------------------------------------------------------------------------------ |
| `flake.nix` | Central entry point defining all hosts, overlays, packages, dev shells, and nixpkgs config |
| `hosts/common/default.nix` | Shared Nix settings, nixpkgs overlays, home-manager setup (`useGlobalPkgs = true`) |
| `hosts/common/users/m3tam3re.nix` | User definition + m3ta-home mkHome integration + per-host feature flags |
| `hosts/<name>/home.nix` | Host-specific overrides: monitors, workspaces, window rules, XDG/MIME |
| `overlays/default.nix` | Package version overrides (stable/locked/master branches) |
| `.opencode-rules/languages/nix.md` | Nix-specific conventions and patterns |
---
## What to Avoid
1. **Don't modify `flake.lock`** directly — use `nix flake update`
2. **Don't use impure operations** — this is a pure flake-based config
3. **Don't commit without formatting** — always run `alejandra .` first
4. **Don't add packages to hosts directly** — prefer adding to overlays or using NUR
5. **Don't hardcode paths** — use `inputs` and relative imports
6. **Don't create monolithic modules** — keep functions under 20 lines
7. **Don't skip the dry-run** — always test with `--dry-run` before switching
8. **Don't use lib.mkDefault lightly** — understand the precedence implications
---
## Notes
### Adding a New Host
1. Add entry to `flake.nix` → `nixosConfigurations`
2. Create directory in `hosts/` with:
- `default.nix` — imports common + specific configs
- `configuration.nix` — host-specific system config
- `hardware-configuration.nix` — from `nixos-generate-config`
- `programs.nix`, `services/`, `secrets.nix` as needed
3. Add entry to `hostProfiles` in `hosts/common/users/m3tam3re.nix`
4. Add feature flags in the `hostFlags` section
5. Create `hosts/<name>/home.nix` if the host needs monitor/XDG overrides
6. Run `sudo nixos-generate-config --dir ./hosts/new-host` first time
### Adding a New Package
1. For simple packages: add to appropriate overlay in `overlays/default.nix`
2. For complex packages: create in `pkgs/` directory
3. For upstream packages: use NUR or add as flake input
### Adding a New Home-Manager Feature
1. Create the module in `m3ta-home` under the appropriate profile directory
2. Add the import to the parent `default.nix` in m3ta-home
3. Enable it per-host via feature flags in `hosts/common/users/m3tam3re.nix`
### Development Workflow
1. Edit config files
2. Run `alejandra .` to format
3. Run `statix check .` for linting
4. Run `sudo nixos-rebuild dry-run --flake .#m3-ares`
5. If successful: `sudo nixos-rebuild switch --flake .#m3-ares`
### Remote Building
```bash
# Build on remote machine
nix copy --to ssh://user@host .#nixosConfigurations.m3-ares.config.system.build.toplevel
ssh user@host 'sudo nixos-rebuild switch --flake /nix/store/...-closure'
```
+7
View File
@@ -0,0 +1,7 @@
This repository is being used as a Dolt remote.
ref=refs/dolt/data
head=b30121458bb0b75b61e483e49b5084835b3777d8
timestamp=2026-06-13T06:18:23Z
-1
View File
@@ -1 +0,0 @@
{"$schema":"https://opencode.ai/config.json","instructions":[".opencode-rules/concerns/coding-style.md",".opencode-rules/concerns/naming.md",".opencode-rules/concerns/documentation.md",".opencode-rules/concerns/testing.md",".opencode-rules/concerns/git-workflow.md",".opencode-rules/concerns/project-structure.md",".opencode-rules/languages/nix.md"]}
Generated
-1590
View File
File diff suppressed because it is too large Load Diff
-218
View File
@@ -1,218 +0,0 @@
{
description = ''
For questions just DM me on X: https://twitter.com/@m3tam3re
There is also some NIXOS content on my YT channel: https://www.youtube.com/@m3tam3re
One of the best ways to learn NIXOS is to read other peoples configurations. I have personally learned a lot from Gabriel Fontes configs:
https://github.com/Misterio77/nix-starter-configs
https://github.com/Misterio77/nix-config
Please also check out the starter configs mentioned above.
'';
inputs = {
home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
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+ssh://gitea@code.m3ta.dev/m3tam3re/nixpkgs";
llm-agents.url = "github:numtide/llm-agents.nix";
#
nur = {
url = "github:nix-community/NUR";
inputs.nixpkgs.follows = "nixpkgs";
};
agenix.url = "github:ryantm/agenix";
disko = {
url = "github:nix-community/disko";
inputs.nixpkgs.follows = "nixpkgs";
};
nixos-generators = {url = "github:nix-community/nixos-generators";};
hyprpanel.url = "github:Jas-SinghFSU/HyprPanel";
rose-pine-hyprcursor.url = "github:ndom91/rose-pine-hyprcursor";
nix-colors.url = "github:misterio77/nix-colors";
m3ta-home = {
# url = "git+ssh://gitea@code.m3ta.dev/m3tam3re/m3ta-home";
url = "path:/home/m3tam3re/p/NIX/m3ta-home";
inputs.nixpkgs.follows = "nixpkgs";
};
agents = {
# url = "path:/home/m3tam3re/p/AI/AGENTS";
url = "git+ssh://gitea@code.m3ta.dev/m3tam3re/AGENTS";
};
## Skills
skills-basecamp = {
url = "github:basecamp/basecamp-cli";
flake = false;
};
skills-anthropic = {
url = "github:anthropics/skills";
flake = false;
};
skills-kestra = {
url = "github:kestra-io/agent-skills";
flake = false;
};
skills-mattpocock = {
url = "github:mattpocock/skills";
flake = false;
};
skills-superpowers = {
url = "github:obra/superpowers";
flake = false;
};
skills-vercel = {
url = "github:vercel-labs/skills";
flake = false;
};
hermes-agent.url = "github:NousResearch/hermes-agent/v2026.5.16";
rustfs = {
url = "github:rustfs/rustfs-flake";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = {
self,
agenix,
home-manager,
nixpkgs,
m3ta-nixpkgs,
nur,
agents,
...
} @ inputs: let
inherit (self) outputs;
systems = [
"aarch64-linux"
"i686-linux"
"x86_64-linux"
"aarch64-darwin"
"x86_64-darwin"
];
forAllSystems = nixpkgs.lib.genAttrs systems;
allOverlays = import ./overlays {inherit inputs outputs;};
in {
packages =
forAllSystems (system: import ./pkgs nixpkgs.legacyPackages.${system});
overlays = removeAttrs allOverlays ["mkLlmAgentsOverlay"];
lib.mkLlmAgentsOverlay = allOverlays.mkLlmAgentsOverlay;
homeManagerModules = import ./modules/home-manager;
nixosConfigurations = {
m3-ares = nixpkgs.lib.nixosSystem {
specialArgs = {
inherit inputs outputs;
system = "x86_64-linux";
hostname = "m3-ares";
};
modules = [
./hosts/m3-ares
agenix.nixosModules.default
m3ta-nixpkgs.nixosModules.default
inputs.hermes-agent.nixosModules.default
];
};
m3-atlas = nixpkgs.lib.nixosSystem {
specialArgs = {
inherit inputs outputs;
system = "x86_64-linux";
};
modules = [
./hosts/m3-atlas
inputs.disko.nixosModules.disko
agenix.nixosModules.default
m3ta-nixpkgs.nixosModules.default
inputs.rustfs.nixosModules.rustfs
];
};
m3-kratos = nixpkgs.lib.nixosSystem {
specialArgs = {
inherit inputs outputs;
system = "x86_64-linux";
hostname = "m3-kratos";
};
modules = [
./hosts/m3-kratos
agenix.nixosModules.default
nur.modules.nixos.default
m3ta-nixpkgs.nixosModules.default
inputs.hermes-agent.nixosModules.default
];
};
m3-helios = nixpkgs.lib.nixosSystem {
specialArgs = {
inherit inputs outputs;
system = "x86_64-linux";
};
modules = [
./hosts/m3-helios
inputs.disko.nixosModules.disko
agenix.nixosModules.default
m3ta-nixpkgs.nixosModules.default
];
};
m3-hermes = nixpkgs.lib.nixosSystem {
specialArgs = {
inherit inputs outputs;
system = "x86_64-linux";
};
modules = [
./hosts/m3-hermes
inputs.disko.nixosModules.disko
agenix.nixosModules.default
m3ta-nixpkgs.nixosModules.default
inputs.hermes-agent.nixosModules.default
];
};
};
homeConfigurations = {
"m3tam3re@m3-daedalus" = home-manager.lib.homeManagerConfiguration {
pkgs = nixpkgs.legacyPackages."x86_64-linux";
extraSpecialArgs = {
inherit inputs outputs;
system = "x86_64-linux";
hostname = "m3-daedalus";
};
modules = [./home/m3tam3re/m3-daedalus.nix];
};
};
devShells = forAllSystems (system: let
pkgs = import nixpkgs {
inherit system;
config.allowUnfree = true; # Allow unfree packages in devShell
};
m3taLib = m3ta-nixpkgs.lib.x86_64-linux;
rules = m3taLib.coding-rules.mkCodingRules {
inherit agents;
languages = ["nix"];
};
in {
default = pkgs.mkShell {
buildInputs = with pkgs; [
alejandra
nixd
openssh
agenix.packages.${system}.default
statix
deadnix
];
inherit (rules) instructions shellHook;
};
});
};
}
-76
View File
@@ -1,76 +0,0 @@
# 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/<name>/
- **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
-82
View File
@@ -1,82 +0,0 @@
# Common configuration for all hosts
{
config,
pkgs,
lib,
inputs,
outputs,
system,
...
}: {
imports = [
./extraServices
./ports.nix
./users
inputs.home-manager.nixosModules.home-manager
];
environment.pathsToLink = ["/share/xdg-desktop-portal" "/share/applications"];
home-manager = {
useGlobalPkgs = true;
useUserPackages = true;
extraSpecialArgs = {
inherit inputs outputs system;
videoDrivers = config.services.xserver.videoDrivers or [];
};
};
nixpkgs = {
# You can add overlays here
overlays = [
# Add overlays your own flake exports (from overlays and pkgs dir):
#outputs.overlays.additions
#outputs.overlays.modifications
outputs.overlays.stable-packages
outputs.overlays.locked-packages
outputs.overlays.pinned-packages
outputs.overlays.master-packages
inputs.m3ta-nixpkgs.overlays.default
inputs.m3ta-nixpkgs.overlays.modifications
(outputs.lib.mkLlmAgentsOverlay system)
# You can also add overlays exported from other flakes:
# neovim-nightly-overlay.overlays.default
# Or define it inline, for example:
# (final: prev: {
# hi = final.hello.overrideAttrs (oldAttrs: {
# patches = [ ./change-hello-to-hi.patch ];
# });
# })
];
# Configure your nixpkgs instance
config = {
# Disable if you don't want unfree packages
allowUnfree = true;
};
};
nix = {
settings = {
experimental-features = "nix-command flakes";
cores = 2;
max-jobs = 8;
trusted-users = [
"root"
"m3tam3re"
]; # Set users that are allowed to use the flake command
};
gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 30d";
};
optimise.automatic = true;
registry =
(lib.mapAttrs (_: flake: {inherit flake;}))
((lib.filterAttrs (_: lib.isType "flake")) inputs);
nixPath = ["/etc/nix/path"];
};
users.defaultUserShell = pkgs.nushell;
}
-8
View File
@@ -1,8 +0,0 @@
{
imports = [
./flatpak.nix
./podman.nix
./ollama.nix
./virtualisation.nix
];
}
-23
View File
@@ -1,23 +0,0 @@
{
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.extraServices.flatpak;
in {
options.extraServices.flatpak.enable = mkEnableOption "enable flatpak";
config = mkIf cfg.enable {
services.flatpak.enable = true;
xdg.portal = {
# xdg desktop intergration (required for flatpak)
enable = true;
extraPortals = with pkgs; [
xdg-desktop-portal-hyprland
];
config.common.default = "*";
};
};
}
-33
View File
@@ -1,33 +0,0 @@
{
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.extraServices.ollama;
in {
options.extraServices.ollama.enable = mkEnableOption "enable ollama";
config = mkIf cfg.enable {
services.ollama = {
enable = true;
package =
if config.services.xserver.videoDrivers == ["amdgpu"]
then pkgs.ollama-rocm
else if config.services.xserver.videoDrivers == ["nvidia"]
then pkgs.ollama-cuda
else pkgs.ollama-cpu;
host = "[::]";
openFirewall = true;
environmentVariables = {
OLLAMA_ORIGINS = "https://msty.studio";
OLLAMA_HOST = "0.0.0.0";
};
};
nixpkgs.config = {
rocmSupport = config.services.xserver.videoDrivers == ["amdgpu"];
cudaSupport = config.services.xserver.videoDrivers == ["nvidia"];
};
};
}
-33
View File
@@ -1,33 +0,0 @@
{
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.extraServices.podman;
in {
options.extraServices.podman.enable = mkEnableOption "enable podman";
config = mkIf cfg.enable {
virtualisation = {
podman = {
enable = true;
dockerCompat = true;
dockerSocket.enable = true;
autoPrune = {
enable = true;
dates = "weekly";
flags = [
"--filter=until=24h"
"--filter=label!=important"
];
};
defaultNetwork.settings.dns_enabled = true;
};
};
environment.systemPackages = with pkgs; [
podman-compose
];
};
}
@@ -1,29 +0,0 @@
{
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.extraServices.virtualisation;
in {
options.extraServices.virtualisation.enable = mkEnableOption "enable virtualisation";
config = mkIf cfg.enable {
virtualisation = {
libvirtd = {
enable = true;
qemu = {
package = pkgs.qemu_kvm;
runAsRoot = true;
swtpm.enable = true;
};
};
};
programs.virt-manager.enable = true;
systemd.services.virt-secret-init-encryption.enable = false;
environment = {
systemPackages = [pkgs.qemu];
};
};
}
-80
View File
@@ -1,80 +0,0 @@
{config, ...}: {
m3ta.ports = {
enable = true;
definitions = {
# System services
ssh = 22;
# Web & proxy services
traefik = 80;
traefik-ssl = 443;
# Databases
postgres = 5432;
mysql = 3306;
redis = 6379;
# VPN & networking
wireguard = 51820;
tailscale = 41641;
headscale = 3009;
netbird-stun = 3478;
netbird-proxy = 8443;
netbird-metrics = 9090;
netbird-health = 9000;
# Containers & web apps
gitea = 3030;
baserow = 3001;
ghost = 3002;
wastebin = 3003;
littlelink = 3004;
searx = 3005;
restreamer = 3006;
paperless = 3012;
vaultwarden = 3013;
slash = 3010;
slash-nemoti = 3016;
kestra = 3018;
outline = 3019;
authentik = 3023;
tuwunel = 3024;
honcho = 3025;
# Agent infrastructure
hermes-api = 8642;
hermes-dashboard = 9119;
# Home automation
homarr = 7575;
# DNS
adguardhome = 53;
};
hostOverrides = {
# Host-specific overrides
m3-ares = {
# Any custom port overrides for m3-ares
};
m3-atlas = {
# Any custom port overrides for m3-atlas
};
m3-helios = {
# Any custom port overrides for m3-helios
};
m3-kratos = {
# Any custom port overrides for m3-kratos
};
};
};
environment.etc."info/all-ports.json" = {
text = builtins.toJSON {
hostname = config.networking.hostName;
ports = config.m3ta.ports.all; # TODO should only return actually used ports
};
};
}
-3
View File
@@ -1,3 +0,0 @@
{
imports = [./m3tam3re.nix];
}
-256
View File
@@ -1,256 +0,0 @@
# hosts/common/users/m3tam3re.nix — Central user definition with m3ta-home integration.
#
# This module:
# 1. Creates the m3tam3re NixOS user
# 2. Loads the m3ta-home profile system via mkHome
# 3. Sets per-host feature flags based on a host profile mapping
# 4. Imports per-host home.nix overrides (monitors, HW-specific config)
#
# To add a new host:
# 1. Add entry to hostProfiles below
# 2. Add feature flags in the hostFlags section
# 3. Create hosts/<hostname>/home.nix if the host needs overrides (monitors, etc.)
{
config,
pkgs,
inputs,
...
}: let
hostname = config.networking.hostName;
# ── Per-host profile mapping ──
# Determines which m3ta-home context and sets each host gets.
hostProfiles = {
# ── Desktop hosts ──
m3-ares = {
context = "desktop";
sets = ["coding" "gaming" "media"];
};
m3-kratos = {
context = "desktop";
sets = ["coding" "gaming" "media"];
};
m3-daedalus = {
context = "desktop";
sets = ["coding" "media"];
};
# ── Server hosts ──
m3-atlas = {
context = "server";
sets = [];
};
m3-helios = {
context = "server";
sets = [];
};
m3-hermes = {
context = "server";
sets = [];
};
m3-aether = {
context = "server";
sets = [];
};
};
profile =
hostProfiles.${
hostname
} or {
context = "server";
sets = [];
};
m3ta-lib = inputs.m3ta-home.lib;
# Check if a per-host home.nix exists
hostHomeFile = ./../../${hostname}/home.nix;
hostHomeExists = builtins.pathExists hostHomeFile;
# ── Per-host feature flags ──
# These enable/disable specific m3ta-home modules per host.
hostFlags =
if hostname == "m3-ares" || hostname == "m3-kratos"
then {
# Full desktop workstation
base = {
shell = {
fish.enable = true;
nushell.enable = true;
starship.enable = true;
};
cliTools = {
fzf.enable = true;
nitch.enable = true;
television.enable = true;
};
secrets.enable = true;
};
desktop = {
wm = {
hyprland.enable = true;
rofi.enable = true;
wayland.enable = true;
};
apps = {
crypto.enable = true;
obsidian.enable = true;
office.enable = true;
};
theme = {
fonts.enable = true;
wallpapers.enable = true;
};
};
coding = {
editors = {
neovim.enable = true;
zed.enable = true;
};
lsp.enable = true;
packages.enable = true;
languages = {
python.enable = true;
javascript.enable = true;
rustToolchain.enable = true;
go.enable = true;
typescript.enable = true;
};
};
profiles.gaming = {
steam.enable = true;
gamescope.enable = true;
};
profiles.media = {
obs.enable = true;
ffmpeg.enable = true;
kdenlive.enable = true;
ytDlp.enable = true;
};
}
else if hostname == "m3-daedalus"
then {
# Portable laptop — desktop without gaming, no Hyprland
base = {
shell = {
fish.enable = true;
nushell.enable = true;
starship.enable = true;
};
cliTools = {
fzf.enable = true;
nitch.enable = true;
television.enable = true;
};
secrets.enable = true;
};
desktop = {
wm = {
hyprland.enable = false;
wayland.enable = false;
};
apps = {
crypto.enable = false;
obsidian.enable = true;
office.enable = false;
};
theme = {
fonts.enable = true;
wallpapers.enable = false;
};
};
coding = {
editors = {
neovim.enable = true;
zed.enable = true;
};
lsp.enable = true;
packages.enable = true;
languages = {
python.enable = true;
javascript.enable = true;
rustToolchain.enable = true;
go.enable = true;
typescript.enable = true;
};
};
profiles.media = {
ytDlp.enable = true;
};
}
else if hostname == "m3-atlas"
then {
# Primary server — coding capable
base = {
shell = {
nushell.enable = true;
starship.enable = true;
};
cliTools = {
fzf.enable = true;
nitch.enable = true;
zellij.enable = true;
};
};
coding.editors.neovim.enable = true;
}
else {
# m3-helios, m3-hermes, m3-aether — minimal server
base = {
shell = {
fish.enable = true;
starship.enable = true;
};
cliTools = {
fzf.enable = true;
nitch.enable = true;
};
};
};
in {
# ── NixOS user definition ──
users.users.m3tam3re = {
password = "12345";
isNormalUser = true;
description = "m3tam3re";
extraGroups = [
"wheel"
"networkmanager"
"libvirtd"
"flatpak"
"audio"
"video"
"plugdev"
"input"
"kvm"
"qemu-libvirtd"
"adbusers"
];
openssh.authorizedKeys.keys = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC3YEmpYbM+cpmyD10tzNRHEn526Z3LJOzYpWEKdJg8DaYyPbDn9iyVX30Nja2SrW4Wadws0Y8DW+Urs25/wVB6mKl7jgPJVkMi5hfobu3XAz8gwSdjDzRSWJrhjynuaXiTtRYED2INbvjLuxx3X8coNwMw58OuUuw5kNJp5aS2qFmHEYQErQsGT4MNqESe3jvTP27Z5pSneBj45LmGK+RcaSnJe7hG+KRtjuhjI7RdzMeDCX73SfUsal+rHeuEw/mmjYmiIItXhFTDn8ZvVwpBKv7xsJG90DkaX2vaTk0wgJdMnpVIuIRBa4EkmMWOQ3bMLGkLQeK/4FUkNcvQ/4+zcZsg4cY9Q7Fj55DD41hAUdF6SYODtn5qMPsTCnJz44glHt/oseKXMSd556NIw2HOvihbJW7Rwl4OEjGaO/dF4nUw4c9tHWmMn9dLslAVpUuZOb7ykgP0jk79ldT3Dv+2Hj0CdAWT2cJAdFX58KQ9jUPT3tBnObSF1lGMI7t77VU= m3tam3re@m3-nix"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBZcjCKl0DRuOUOMXbM0GKY5JjvmyFpVZ/tRlTKWu/zp razr"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEZbg/Z9mnflXuLahGY8WOSBMqbgeqVIkIwRkquys1Ml sascha.koenig@azintec.com"
];
packages = [inputs.home-manager.packages.${pkgs.stdenv.hostPlatform.system}.default];
};
# ── Home-Manager configuration via m3ta-home ──
home-manager.users.m3tam3re = {
imports =
[
# Load m3ta-home composition engine
(m3ta-lib.mkHome {
user = "m3tam3re";
identity = "private";
inherit (profile) context sets;
})
# Per-host feature flags
hostFlags
]
# Per-host home.nix (Hyprland monitors, XDG/MIME, HW-specific overrides)
++ (
if hostHomeExists
then [hostHomeFile]
else []
);
};
}
-111
View File
@@ -1,111 +0,0 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page, on
# https://search.nixos.org/options and in the NixOS manual (`nixos-help`).
{pkgs, ...}: {
imports = [
# Include the results of the hardware scan.
./disko-config.nix
./hardware-configuration.nix
];
# Bootloader.
boot.loader.grub = {
efiSupport = true;
efiInstallAsRemovable = true;
};
networking.hostName = "m3-helios"; # Define your hostname.
networking.hostId = "3ebf1cd3";
# Pick only one of the below networking options.
# networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.
networking.networkmanager.enable =
true; # Easiest to use and most distros use this by default.
# Set your time zone.
time.timeZone = "Europe/Berlin";
# Configure network proxy if necessary
# networking.proxy.default = "http://user:password@proxy:port/";
# networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
# Select internationalisation properties.
i18n.defaultLocale = "en_US.UTF-8";
# console = {
# font = "Lat2-Terminus16";
# keyMap = "us";
# useXkbConfig = true; # use xkb.options in tty.
# };
# Enable the X11 windowing system.
# services.xserver.enable = true;
# Enable the GNOME Desktop Environment.
# services.xserver.displayManager.gdm.enable = true;
# services.xserver.desktopManager.gnome.enable = true;
# Configure keymap in X11
# services.xserver.xkb.layout = "us";
# services.xserver.xkb.options = "eurosign:e,caps:escape";
# Enable CUPS to print documents.
# services.printing.enable = true;
# Enable sound.
# hardware.pulseaudio.enable = true;
# OR
# Enable touchpad support (enabled default in most desktopManager).
# services.libinput.enable = true;
# Define a user account. Don't forget to set a password with passwd.
# List packages installed in system profile. To search, run:
# $ nix search wget
environment.systemPackages = with pkgs; [neovim git];
# Some programs need SUID wrappers, can be configured further or are
# started in user sessions.
# programs.mtr.enable = true;
# programs.gnupg.agent = {
# enable = true;
# enableSSHSupport = true;
# };
# List services that you want to enable:
# Enable the OpenSSH daemon.
services.openssh.enable = true;
services.fstrim = {
enable = true; # For SSD/thin-provisioned storage
interval = "weekly";
};
# Open ports in the firewall.
# networking.firewall.allowedTCPPorts = [ ... ];
# networking.firewall.allowedUDPPorts = [ ... ];
# Or disable the firewall altogether.
# networking.firewall.enable = false;
# Copy the NixOS configuration file and link it from the resulting system
# (/run/current-system/configuration.nix). This is useful in case you
# accidentally delete configuration.nix.
# system.copySystemConfiguration = true;
# This option defines the first version of NixOS you have installed on this particular machine,
# and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions.
#
# Most users should NEVER change this value after the initial install, for any reason,
# even if you've upgraded your system to a new NixOS release.
#
# This value does NOT affect the Nixpkgs version your packages and OS are pulled from,
# so changing it will NOT upgrade your system - see https://nixos.org/manual/nixos/stable/#sec-upgrading for how
# to actually do that.
#
# This value being lower than the current NixOS release does NOT mean your system is
# out of date, out of support, or vulnerable.
#
# Do NOT change this value unless you have manually inspected all the changes it would make to your configuration,
# and migrated your data accordingly.
#
# For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion .
system.stateVersion = "24.11"; # Did you read the comment?
}
-50
View File
@@ -1,50 +0,0 @@
# A staring point is the basic NIXOS configuration generated by the ISO installer.
# On an existing NIXOS install you can use the following command in your flakes basedir:
# sudo nixos-generate-config --dir ./hosts/m3tam3re
#
# Please make sure to change the first couple of lines in your configuration.nix:
# { config, inputs, ouputs, lib, pkgs, ... }:
#
# {
# imports = [ # Include the results of the hardware scan.
# ./hardware-configuration.nix
# inputs.home-manager.nixosModules.home-manager
# ];
# ...
#
# Moreover please update the packages option in your user configuration and add the home-manager options:
# users.users = {
# m3tam3re = {
# isNormalUser = true;
# initialPassword = "12345";
# extraGroups = [ "wheel" ]; # Enable sudo for the user.
# packages = [ inputs.home-manager.packages.${pkgs.system}.default ];
# };
# };
#
# home-manager = {
# useUserPackages = true;
# extraSpecialArgs = { inherit inputs outputs; };
# users.m3tam3re =
# import ../../home/m3tam3re/${config.networking.hostName}.nix;
# };
#
# Please also change your hostname accordingly:
#:w
# networking.hostName = "nixos"; # Define your hostname.
{
imports = [
../common
./configuration.nix
./programs.nix
./secrets.nix
./services
];
extraServices = {
flatpak.enable = true;
ollama.enable = false;
podman.enable = true;
virtualisation.enable = false;
};
}
-39
View File
@@ -1,39 +0,0 @@
{
disko.devices = {
disk = {
main = {
type = "disk";
device = "/dev/sda";
content = {
type = "gpt";
partitions = {
boot = {
size = "1M";
type = "EF02"; # for GRUB MBR
priority = 1;
};
esp = {
size = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = ["defaults" "umask=0077"];
};
};
root = {
size = "100%";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
mountOptions = ["noatime" "nodiratime" "discard"];
};
};
};
};
};
};
};
}
@@ -1,28 +0,0 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{
config,
lib,
pkgs,
modulesPath,
...
}: {
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = ["ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod"];
boot.initrd.kernelModules = [];
boot.kernelModules = [];
boot.extraModulePackages = [];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.ens18.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}
-14
View File
@@ -1,14 +0,0 @@
{pkgs, ...}: {
programs.nix-ld.enable = true;
programs.nix-ld.libraries = with pkgs; [
# Add any missing dynamic libraries for unpackaged programs
# here, NOT in environment.systemPackages
];
programs.fish.enable = true;
programs.nh = {
enable = true;
clean.enable = true;
clean.extraArgs = "--keep-since 4d --keep 3";
flake = "/home/m3tam3re/p/nixos/nixos-config";
};
}
-15
View File
@@ -1,15 +0,0 @@
{
age = {
secrets = {
traefik = {
file = ../../secrets/traefik.age;
mode = "770";
owner = "traefik";
};
m3tam3re-secrets = {
file = ../../secrets/m3tam3re-secrets.age;
owner = "m3tam3re";
};
};
};
}
-7
View File
@@ -1,7 +0,0 @@
{
services.cloud-init = {
enable = true;
ext4.enable = true;
network.enable = true;
};
}
-5
View File
@@ -1,5 +0,0 @@
{
imports = [
./cloud-init.nix
];
}
-133
View File
@@ -1,133 +0,0 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page, on
# https://search.nixos.org/options and in the NixOS manual (`nixos-help`).
{pkgs, ...}: {
imports = [
# Include the results of the hardware scan.
./hardware-configuration.nix
];
specialisation = {
"NVIDIA".configuration = {
system.nixos.tags = ["NVIDIA"];
services.xserver.videoDrivers = ["nvidia"];
hardware.nvidia-container-toolkit.enable = true;
};
};
# Bootloader.
boot.loader.systemd-boot.enable = true;
boot.loader.systemd-boot.memtest86.enable = true;
boot.initrd.services.lvm.enable = false;
# boot.kernelModules = [];
boot.kernelPackages = pkgs.linuxPackages_latest;
boot.extraModprobeConfig = ''
options kvm_intel nested=1
options kvm_intel emulate_invalid_guest_state=0
options kvm ignore_msrs=1
'';
boot.blacklistedKernelModules = ["nova_core"];
# CRITICAL FIX #4: Kernel parameters to prevent nouveau from loading early
networking.hostName = "m3-ares"; # Define your hostname.
# warp-terminal update fix
# networking.extraHosts = ''
# 127.0.0.1 releases.warp.dev
# 127.0.0.1 app.warp.dev
# '';
# Pick only one of the below networking options.
# networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.
networking.networkmanager.enable =
true; # Easiest to use and most distros use this by default.
# Set your time zone.
time.timeZone = "Europe/Berlin";
# Configure network proxy if necessary
# networking.proxy.default = "http://user:password@proxy:port/";
# networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
# Select internationalisation properties.
i18n.defaultLocale = "en_US.UTF-8";
# console = {
# font = "Lat2-Terminus16";
# keyMap = "us";
# useXkbConfig = true; # use xkb.options in tty.
# };
# Enable the X11 windowing system.
# services.xserver.enable = true;
# Enable the GNOME Desktop Environment.
# services.xserver.displayManager.gdm.enable = true;
# services.xserver.desktopManager.gnome.enable = true;
# displayManager.gdm.enable = true;
# Configure keymap in X11
# services.xserver.xkb.layout = "us";
# services.xserver.xkb.options = "eurosign:e,caps:escape";
# Enable CUPS to print documents.
# services.printing.enable = true;
# Enable sound.
# hardware.pulseaudio.enable = true;
# OR
# Enable touchpad support (enabled default in most desktopManager).
# services.libinput.enable = true;
# Define a user account. Don't forget to set a password with passwd.
# List packages installed in system profile. To search, run:
# $ nix search wget
environment.systemPackages = with pkgs; [neovim git];
# Some programs need SUID wrappers, can be configured further or are
# started in user sessions.
# programs.mtr.enable = true;
# programs.gnupg.agent = {
# enable = true;
# enableSSHSupport = true;
# };
# List services that you want to enable:
# Enable the OpenSSH daemon.
services.openssh = {
enable = true;
settings.PermitRootLogin = "no";
settings = {
PasswordAuthentication = false;
};
};
services.fstrim.enable = true;
# Open ports in the firewall.
# networking.firewall.allowedTCPPorts = [ ... ];
# networking.firewall.allowedUDPPorts = [ ... ];
# Or disable the firewall altogether.
# networking.firewall.enable = false;
# Copy the NixOS configuration file and link it from the resulting system
# (/run/current-system/configuration.nix). This is useful in case you
# accidentally delete configuration.nix.
# system.copySystemConfiguration = true;
# This option defines the first version of NixOS you have installed on this particular machine,
# and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions.
#
# Most users should NEVER change this value after the initial install, for any reason,
# even if you've upgraded your system to a new NixOS release.
#
# This value does NOT affect the Nixpkgs version your packages and OS are pulled from,
# so changing it will NOT upgrade your system - see https://nixos.org/manual/nixos/stable/#sec-upgrading for how
# to actually do that.
#
# This value being lower than the current NixOS release does NOT mean your system is
# out of date, out of support, or vulnerable.
#
# Do NOT change this value unless you have manually inspected all the changes it would make to your configuration,
# and migrated your data accordingly.
#
# For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion .
system.stateVersion = "24.11"; # Did you read the comment?
}
-51
View File
@@ -1,51 +0,0 @@
# A staring point is the basic NIXOS configuration generated by the ISO installer.
# On an existing NIXOS install you can use the following command in your flakes basedir:
# sudo nixos-generate-config --dir ./hosts/m3tam3re
#
# Please make sure to change the first couple of lines in your configuration.nix:
# { config, inputs, ouputs, lib, pkgs, ... }:
#
# {
# imports = [ # Include the results of the hardware scan.
# ./hardware-configuration.nix
# inputs.home-manager.nixosModules.home-manager
# ];
# ...
#
# Moreover please update the packages option in your user configuration and add the home-manager options:
# users.users = {
# m3tam3re = {
# isNormalUser = true;
# initialPassword = "12345";
# extraGroups = [ "wheel" ]; # Enable sudo for the user.
# packages = [ inputs.home-manager.packages.${pkgs.system}.default ];
# };
# };
#
# home-manager = {
# useUserPackages = true;
# extraSpecialArgs = { inherit inputs outputs; };
# users.m3tam3re =
# import ../../home/m3tam3re/${config.networking.hostName}.nix;
# };
#
# Please also change your hostname accordingly:
#:w
# networking.hostName = "nixos"; # Define your hostname.
{
imports = [
../common
./configuration.nix
./hardware.nix
./programs.nix
./secrets.nix
./services
];
extraServices = {
flatpak.enable = true;
ollama.enable = false;
podman.enable = true;
virtualisation.enable = true;
};
}
-73
View File
@@ -1,73 +0,0 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{
config,
lib,
modulesPath,
...
}: {
imports = [(modulesPath + "/installer/scan/not-detected.nix")];
boot.initrd.availableKernelModules = ["xhci_pci" "thunderbolt" "ahci" "nvme" "usb_storage" "sd_mod"];
boot.initrd.kernelModules = [];
boot.kernelModules = ["kvm-intel"];
boot.extraModulePackages = [];
boot.supportedFilesystems = ["nfs"];
fileSystems."/" = {
device = "/dev/disk/by-uuid/3a50bf0a-024b-488b-aa11-56b32f2fb54d";
fsType = "btrfs";
options = ["subvol=root" "compress=zstd"];
};
fileSystems."/home" = {
device = "/dev/disk/by-uuid/3a50bf0a-024b-488b-aa11-56b32f2fb54d";
fsType = "btrfs";
options = ["subvol=home" "compress=zstd"];
};
fileSystems."/nix" = {
device = "/dev/disk/by-uuid/3a50bf0a-024b-488b-aa11-56b32f2fb54d";
fsType = "btrfs";
options = ["subvol=home" "compress=zstd" "noatime"];
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/4811-EA6E";
fsType = "vfat";
};
fileSystems."/opt" = {
device = "/dev/disk/by-uuid/3574df3a-2a90-4b54-9c21-128f1d01ff8f";
fsType = "btrfs";
options = ["noatime" "compress=zstd"];
};
fileSystems."/mnt/skynet-bkg" = {
device = "192.168.1.100:/volume3/bkg";
fsType = "nfs";
options = ["noauto" "x-systemd.automount"];
};
fileSystems."/mnt/skynet" = {
device = "192.168.1.100:/volume3/m3-skynet";
fsType = "nfs";
options = ["noauto" "x-systemd.automount"];
};
swapDevices = [];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.enp46s0.useDHCP = lib.mkDefault true;
# networking.interfaces.wlo1.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
hardware.cpu.intel.updateMicrocode =
lib.mkDefault config.hardware.enableRedistributableFirmware;
}
-58
View File
@@ -1,58 +0,0 @@
{
config,
pkgs,
inputs,
...
}: {
# Workaround for tuxedo-drivers module bug in unstable (nixpkgs#480391)
# The unstable module has a type error - use stable module until fix propagates
# disabledModules = [ "hardware/tuxedo-drivers.nix" ];
# imports =
# [ "${inputs.nixpkgs-stable}/nixos/modules/hardware/tuxedo-drivers.nix" ];
hardware.nvidia = {
prime = {
offload.enable = false;
# Bus ID of the Intel GPU. You can find it using lspci, either under 3D or VGA
intelBusId = "PCI:0:2:0";
# Bus ID of the NVIDIA GPU. You can find it using lspci, either under 3D or VGA
nvidiaBusId = "PCI:1:0:0";
};
modesetting.enable = true;
powerManagement.finegrained = false;
powerManagement.enable = true;
open = false;
dynamicBoost.enable = true;
nvidiaSettings = true;
package = config.boot.kernelPackages.nvidiaPackages.production;
};
hardware.tuxedo-drivers.enable = true;
hardware.bluetooth.enable = true;
hardware.keyboard.zsa.enable = true;
hardware.graphics.enable = true;
services.hardware.bolt.enable = true;
services.auto-cpufreq.enable = true;
services.tlp = {
enable = true;
settings = {
START_CHARGE_THRESH_BAT0 = 75;
STOP_CHARGE_THRESH_BAT0 = 80;
};
};
environment.systemPackages = with pkgs; [tuxedo-backlight];
security.sudo.extraRules = [
{
users = ["@wheel"];
commands = [
{
command = "/run/current-system/sw/bin/set-backlight";
options = ["NOPASSWD"];
}
];
}
];
}
-71
View File
@@ -1,71 +0,0 @@
# hosts/m3-ares/home.nix — Host-specific home-manager overrides.
# TUXEDO laptop: eDP-1 + HDMI-A-1 external monitor.
# Everything else (shell, editors, gaming, media, theme, etc.) comes from
# m3ta-home via the profile mapping in hosts/common/users/m3tam3re.nix.
{
config,
lib,
...
}:
with lib; {
config = mkMerge [
# ── XDG / MIME defaults ──
{
xdg = {
enable = true;
configFile."mimeapps.list".force = true;
mimeApps = {
enable = true;
associations.added = {
"application/zip" = ["org.gnome.FileRoller.desktop"];
"application/csv" = ["calc.desktop"];
"application/pdf" = ["vivaldi-stable.desktop"];
"x-scheme-handler/http" = ["vivaldi-stable.desktop"];
"x-scheme-handler/https" = ["vivaldi-stable.desktop"];
};
defaultApplications = {
"application/zip" = ["org.gnome.FileRoller.desktop"];
"application/csv" = ["calc.desktop"];
"application/pdf" = ["vivaldi-stable.desktop"];
"application/md" = ["dev.zed.Zed.desktop"];
"application/text" = ["dev.zed.Zed.desktop"];
"x-scheme-handler/http" = ["vivaldi-stable.desktop"];
"x-scheme-handler/https" = ["vivaldi-stable.desktop"];
};
};
};
}
# ── Hyprland monitor layout ──
(mkIf config.desktop.wm.hyprland.enable {
wayland.windowManager.hyprland = {
enable = true;
settings = {
exec-once = ["tuxedo-backlight"];
monitor = [
"eDP-1,preferred,0x0,1.25"
"HDMI-A-1,1920x1080@120,2560x0,1"
];
workspace = [
"1, monitor:eDP-1, default:true"
"2, monitor:eDP-1"
"3, monitor:eDP-1"
"4, monitor:HDMI-A-1"
"5, monitor:HDMI-A-1,border:false,rounding:false"
"6, monitor:HDMI-A-1"
];
windowrule = [
"match:class dev.zed.Zed, workspace 1"
"match:class Msty, workspace 1"
"match:class ^(com.obsproject.Studio)$, workspace 2"
"match:class ^(brave-browser)$, workspace 4, opacity 1.0"
"match:class ^(vivaldi-stable)$, workspace 4, opacity 1.0"
"match:class ^steam_app_\\d+$, fullscreen on"
"match:class ^steam_app_\\d+$, workspace 5"
"match:class ^steam_app_\\d+$, idle_inhibit focus"
];
};
};
})
];
}
-45
View File
@@ -1,45 +0,0 @@
{pkgs, ...}: {
programs.nix-ld.enable = true;
programs.nix-ld.libraries = with pkgs; [
# Add any missing dynamic libraries for unpackaged programs
# here, NOT in environment.systemPackages
];
programs.hyprland = {
enable = true;
xwayland.enable = true;
withUWSM = true;
};
programs.steam = {
enable = true;
remotePlay.openFirewall = true;
dedicatedServer.openFirewall = true;
gamescopeSession = {
enable = true;
args = [
"-W 1920"
"-H 1080"
];
};
};
programs.gamescope = {
enable = true;
capSysNice = true;
};
programs.fish.enable = true;
programs.thunar = {
enable = true;
plugins = with pkgs; [thunar-archive-plugin thunar-volman];
};
programs.gnupg.agent = {
enable = true;
enableSSHSupport = true;
pinentryPackage = pkgs.pinentry-gnome3;
settings = {default-cache-ttl = 10800;};
};
programs.nh = {
enable = true;
clean.enable = true;
clean.extraArgs = "--keep-since 4d --keep 3";
flake = "/home/m3tam3re/p/nixos/nixos-config";
};
}
-59
View File
@@ -1,59 +0,0 @@
{
age = {
secrets = {
anytype-key = {
file = ../../secrets/anytype-key-ares.age;
owner = "m3tam3re";
};
wg-DE = {
file = ../../secrets/wg-DE.age;
path = "/etc/wireguard/DE.conf";
};
wg-NL = {
file = ../../secrets/wg-NL.age;
path = "/etc/wireguard/NL.conf";
};
wg-NO = {
file = ../../secrets/wg-NO.age;
path = "/etc/wireguard/NO.conf";
};
wg-US = {
file = ../../secrets/wg-US.age;
path = "/etc/wireguard/US.conf";
};
wg-BR = {
file = ../../secrets/wg-BR.age;
path = "/etc/wireguard/BR.conf";
};
ref-key = {
file = ../../secrets/ref-key.age;
owner = "m3tam3re";
};
exa-key = {
file = ../../secrets/exa-key.age;
owner = "m3tam3re";
};
outline-key = {
file = ../../secrets/outline-key.age;
owner = "m3tam3re";
};
basecamp-client-id = {
file = ../../secrets/basecamp-client-id.age;
owner = "m3tam3re";
};
basecamp-client-secret = {
file = ../../secrets/basecamp-client-secret.age;
owner = "m3tam3re";
};
tailscale-key.file = ../../secrets/tailscale-key.age;
m3tam3re-secrets = {
file = ../../secrets/m3tam3re-secrets.age;
owner = "m3tam3re";
};
hermes-env = {
file = ../../secrets/hermes-env.age;
owner = "m3tam3re";
};
};
};
}
@@ -1,4 +0,0 @@
{
imports = [
];
}
-53
View File
@@ -1,53 +0,0 @@
{pkgs, ...}: {
imports = [
./containers
./hermes-agent.nix
./netbird.nix
#./n8n.nix
./mem0.nix
./postgres.nix
./restic.nix
./sound.nix
./udev.nix
./wireguard.nix
];
# console.useXkbConfig = true;
# services.xserver.xkb = {
# layout = "de,us";
# options = "ctrl:nocaps";
# };
# optional, falls du auch die TTY-Konsole deutsch willst:
services = {
hypridle.enable = true;
espanso = {
enable = true;
package = pkgs.espanso-wayland;
};
printing.enable = true;
gvfs.enable = true;
trezord.enable = true;
gnome.gnome-keyring.enable = true;
qdrant.enable = true;
# qdrant = {
# enable = true;
# settings = {
# service = {
# host = "0.0.0.0";
# };
# };
# };
upower.enable = true;
avahi = {
enable = true;
nssmdns4 = true;
publish = {
addresses = true;
workstation = true;
userServices = true;
};
};
displayManager.gdm.enable = true;
};
}
-195
View File
@@ -1,195 +0,0 @@
{config, ...}: let
# Default ElevenLabs voice: Bella (German-capable female)
elevenlabsVoiceId = "hpp4J3VqNfWAUOO0d1Us";
in {
services.hermes-agent = {
enable = true;
addToSystemPackages = true;
# Secrets via agenix
environmentFiles = [config.age.secrets."hermes-env".path];
# Non-secret environment variables
environment = {
GLM_BASE_URL = "https://api.z.ai/api/coding/paas/v4/";
};
settings = {
# ── Model ──────────────────────────────────────────────────────────
model = {
default = "gpt-5.5";
provider = "openai-codex";
};
fallback_providers = [
{
provider = "zai";
model = "glm-5.1";
}
{
provider = "minimax";
model = "MiniMax-M2.7";
}
];
credential_pool_strategies = {
zai = "fill_first";
};
toolsets = ["all"];
# ── Agent ──────────────────────────────────────────────────────────
agent = {
max_turns = 90;
gateway_timeout = 1800;
tool_use_enforcement = "auto";
};
# ── Terminal ───────────────────────────────────────────────────────
terminal = {
backend = "ssh";
modal_mode = "auto";
cwd = ".";
timeout = 180;
persistent_shell = true;
};
# ── Browser ────────────────────────────────────────────────────────
browser = {
inactivity_timeout = 120;
command_timeout = 30;
cloud_provider = "local";
};
# ── Checkpoints / Compression ──────────────────────────────────────
checkpoints = {
enabled = true;
max_snapshots = 50;
};
file_read_max_chars = 100000;
compression = {
enabled = true;
threshold = 0.5;
target_ratio = 0.2;
protect_last_n = 20;
};
# ── Display ────────────────────────────────────────────────────────
display = {
compact = false;
personality = "kawaii";
resume_display = "full";
busy_input_mode = "interrupt";
inline_diffs = true;
skin = "default";
tool_progress = "all";
};
# ── TTS / STT / Voice ──────────────────────────────────────────────
tts = {
provider = "elevenlabs";
elevenlabs = {
voice_id = elevenlabsVoiceId;
model_id = "eleven_multilingual_v2";
};
};
stt = {
enabled = true;
provider = "local";
local = {model = "base";};
};
voice = {
record_key = "ctrl+b";
max_recording_seconds = 120;
silence_threshold = 200;
silence_duration = 3.0;
};
# ── Memory ─────────────────────────────────────────────────────────
memory = {
memory_enabled = true;
user_profile_enabled = true;
memory_char_limit = 2200;
user_char_limit = 1375;
};
# ── Delegation ─────────────────────────────────────────────────────
delegation = {
max_iterations = 50;
};
# ── Discord ────────────────────────────────────────────────────────
discord = {
require_mention = true;
auto_thread = true;
reactions = true;
};
# ── Approvals / Security ───────────────────────────────────────────
approvals = {
mode = "manual";
timeout = 60;
};
security = {
redact_secrets = true;
tirith_enabled = true;
tirith_fail_open = true;
};
# ── Cron / Session ─────────────────────────────────────────────────
cron = {wrap_response = true;};
session_reset = {
mode = "both";
idle_minutes = 1440;
at_hour = 4;
};
# ── Web ────────────────────────────────────────────────────────────
web = {backend = "exa";};
# ── Platform Toolsets ──────────────────────────────────────────────
platform_toolsets = {
cli = [
"browser"
"clarify"
"code_execution"
"cronjob"
"delegation"
"file"
"image_gen"
"memory"
"session_search"
"skills"
"terminal"
"todo"
"tts"
"vision"
"web"
];
telegram = [
"browser"
"clarify"
"code_execution"
"cronjob"
"delegation"
"file"
"image_gen"
"memory"
"session_search"
"skills"
"terminal"
"todo"
"tts"
"vision"
"web"
];
};
};
};
}
-23
View File
@@ -1,23 +0,0 @@
{
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";
};
};
};
}
-11
View File
@@ -1,11 +0,0 @@
{
services.n8n = {
enable = true;
openFirewall = true;
};
systemd.services.n8n = {
environment = {
N8N_SECURE_COOKIE = "false";
};
};
}
-29
View File
@@ -1,29 +0,0 @@
{pkgs, ...}: {
services.netbird.enable = true;
environment.systemPackages = with pkgs; [netbird-ui];
systemd.services.netbird = {
environment = {
NB_DISABLE_SSH_CONFIG = "true";
};
path = [
pkgs.shadow
pkgs.util-linux
];
};
programs.ssh.extraConfig = ''
Match exec "${pkgs.netbird}/bin/netbird ssh detect %h %p"
PreferredAuthentications password,publickey,keyboard-interactive
PasswordAuthentication yes
PubkeyAuthentication yes
BatchMode no
ProxyCommand ${pkgs.netbird}/bin/netbird ssh proxy %h %p
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
CheckHostIP no
LogLevel ERROR
'';
networking.firewall.checkReversePath = "loose";
}
-22
View File
@@ -1,22 +0,0 @@
{pkgs, ...}: {
services.postgresql = {
enable = true;
package = pkgs.postgresql_17;
extensions = with pkgs.postgresql17Packages; [
pgvector
];
authentication = ''
local all all trust
host all all 127.0.0.1/32 trust
host all all ::1/128 trust
host all all 10.88.0.0/16 trust
host all all 19.89.0.0/16 trust
'';
initialScript = pkgs.writeText "initialScript.sql" ''
CREATE USER n8n WITH PASSWORD 'n8n';
CREATE DATABASE n8n;
GRANT ALL PRIVILEGES ON DATABASE n8n TO n8n;
'';
};
}
-25
View File
@@ -1,25 +0,0 @@
{
services.restic.backups = {
skynet = {
repository = "/mnt/skynet-bkg/m3-nix";
passwordFile = "/etc/nixos/restic-pass";
initialize = true;
paths = ["/home/m3tam3re"];
exclude = [
"/home/m3tam3re/.cache"
"/home/m3tam3re/Bilder/"
"/home/m3tam3re/Videos/"
"/home/m3tam3re/Downloads"
"/home/m3tam3re/Library"
"/home/m3tam3re/Projekte"
"/home/m3tam3re/Sync"
"/home/m3tam3re/.local/share/Trash"
];
timerConfig = {
OnCalendar = "09:30";
RandomizedDelaySec = "2h";
Persistent = true;
};
};
};
}
-11
View File
@@ -1,11 +0,0 @@
{
security.rtkit.enable = true;
services.pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
jack.enable = false;
wireplumber.enable = true;
};
}
-10
View File
@@ -1,10 +0,0 @@
{pkgs, ...}: {
services.udev.extraRules = ''
SUBSYSTEM=="usb", MODE="0666"
SUBSYSTEM=="leds", KERNEL=="rgb:kbd_backlight*", ACTION=="add", RUN+="${pkgs.coreutils}/bin/chmod a+w /sys/class/leds/%k/multi_intensity"
KERNEL=="uinput", MODE="0660", GROUP="input", OPTIONS+="static_node=uinput"
KERNEL=="event*", SUBSYSTEM=="input", MODE="0660", GROUP="input" '';
environment.systemPackages = with pkgs; [
zsa-udev-rules
];
}
-25
View File
@@ -1,25 +0,0 @@
{config, ...}: {
networking.wg-quick.interfaces = {
DE = {
configFile = config.age.secrets.wg-DE.path;
autostart = false;
};
NL = {
configFile = config.age.secrets.wg-NL.path;
autostart = false;
};
NO = {
configFile = config.age.secrets.wg-NO.path;
autostart = false;
};
US = {
configFile = config.age.secrets.wg-US.path;
autostart = false;
};
BR = {
configFile = config.age.secrets.wg-BR.path;
autostart = false;
};
};
services.resolved.enable = true;
}
-116
View File
@@ -1,116 +0,0 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page, on
# https://search.nixos.org/options and in the NixOS manual (`nixos-help`).
{pkgs, ...}: {
imports = [
# Include the results of the hardware scan.
./disko-config.nix
./hardware-configuration.nix
];
# Bootloader.
boot.loader.grub = {
efiSupport = true;
efiInstallAsRemovable = true;
};
networking.hostName = "m3-atlas"; # CHANGE ME.
networking.hostId = "15b60253"; # CHANGE ME
# Pick only one of the below networking options.
# networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.
networking.networkmanager.enable = true; # Easiest to use and most distros use this by default.
# Set your time zone.
time.timeZone = "Europe/Berlin";
# Configure network proxy if necessary
# networking.proxy.default = "http://user:password@proxy:port/";
# networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
# Select internationalisation properties.
i18n.defaultLocale = "en_US.UTF-8";
# console = {
# font = "Lat2-Terminus16";
# keyMap = "us";
# useXkbConfig = true; # use xkb.options in tty.
# };
# Enable the X11 windowing system.
# services.xserver.enable = true;
# Enable the GNOME Desktop Environment.
# services.xserver.displayManager.gdm.enable = true;
# services.xserver.desktopManager.gnome.enable = true;
# Configure keymap in X11
# services.xserver.xkb.layout = "us";
# services.xserver.xkb.options = "eurosign:e,caps:escape";
# Enable CUPS to print documents.
# services.printing.enable = true;
# Enable sound.
# hardware.pulseaudio.enable = true;
# OR
# Enable touchpad support (enabled default in most desktopManager).
# services.libinput.enable = true;
# Define a user account. Don't forget to set a password with passwd.
# List packages installed in system profile. To search, run:
# $ nix search wget
environment.systemPackages = with pkgs; [
neovim
git
ghostty.terminfo
];
# Some programs need SUID wrappers, can be configured further or are
# started in user sessions.
# programs.mtr.enable = true;
# programs.gnupg.agent = {
# enable = true;
# enableSSHSupport = true;
# };
# List services that you want to enable:
# Enable the OpenSSH daemon.
services.openssh = {
enable = true;
settings.PermitRootLogin = "no";
settings = {
PasswordAuthentication = false;
};
};
# [[Open ports in the firewall.
# networking.firewall.allowedTCPPorts = [ ... ];
# networking.firewall.allowedUDPPorts = [ ... ];
# Or disable the firewall altogether.
# networking.firewall.enable = false;
# Copy the NixOS configuration file and link it from the resulting system
# (/run/current-system/configuration.nix). This is useful in case you
# accidentally delete configuration.nix.
# system.copySystemConfiguration = true;
# This option defines the first version of NixOS you have installed on this particular machine,
# and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions.
#
# Most users should NEVER change this value after the initial install, for any reason,
# even if you've upgraded your system to a new NixOS release.
#
# This value does NOT affect the Nixpkgs version your packages and OS are pulled from,
# so changing it will NOT upgrade your system - see https://nixos.org/manual/nixos/stable/#sec-upgrading for how
# to actually do that.
#
# This value being lower than the current NixOS release does NOT mean your system is
# out of date, out of support, or vulnerable.
#
# Do NOT change this value unless you have manually inspected all the changes it would make to your configuration,
# and migrated your data accordingly.
#
# For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion .
system.stateVersion = "24.11"; # Did you read the comment?
}
-50
View File
@@ -1,50 +0,0 @@
# A staring point is the basic NIXOS configuration generated by the ISO installer.
# On an existing NIXOS install you can use the following command in your flakes basedir:
# sudo nixos-generate-config --dir ./hosts/m3tam3re
#
# Please make sure to change the first couple of lines in your configuration.nix:
# { config, inputs, ouputs, lib, pkgs, ... }:
#
# {
# imports = [ # Include the results of the hardware scan.
# ./hardware-configuration.nix
# inputs.home-manager.nixosModules.home-manager
# ];
# ...
#
# Moreover please update the packages option in your user configuration and add the home-manager options:
# users.users = {
# m3tam3re = {
# isNormalUser = true;
# initialPassword = "12345";
# extraGroups = [ "wheel" ]; # Enable sudo for the user.
# packages = [ inputs.home-manager.packages.${pkgs.system}.default ];
# };
# };
#
# home-manager = {
# useUserPackages = true;
# extraSpecialArgs = { inherit inputs outputs; };
# users.m3tam3re =
# import ../../home/m3tam3re/${config.networking.hostName}.nix;
# };
#
# Please also change your hostname accordingly:
#:w
# networking.hostName = "nixos"; # Define your hostname.
{
imports = [
../common
./configuration.nix
./programs.nix
./secrets.nix
./services
];
extraServices = {
flatpak.enable = false;
ollama.enable = false;
podman.enable = true;
virtualisation.enable = false;
};
}
-39
View File
@@ -1,39 +0,0 @@
{
disko.devices = {
disk = {
main = {
type = "disk";
device = "/dev/vda"; # CHANGE ME
content = {
type = "gpt";
partitions = {
boot = {
size = "1M";
type = "EF02"; # for GRUB MBR
priority = 1;
};
esp = {
size = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = ["defaults" "umask=0077"];
};
};
root = {
size = "100%";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
mountOptions = ["noatime" "nodiratime" "discard"];
};
};
};
};
};
};
};
}
-31
View File
@@ -1,31 +0,0 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{
lib,
modulesPath,
...
}: {
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = ["ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod"];
boot.initrd.kernelModules = [];
boot.kernelModules = [];
boot.extraModulePackages = [];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.ens18.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
fileSystems."/var/storage" = {
device = "46.38.248.210:/voln723044a1";
fsType = "nfs";
};
}
-14
View File
@@ -1,14 +0,0 @@
{pkgs, ...}: {
programs.nix-ld.enable = true;
programs.nix-ld.libraries = with pkgs; [
# Add any missing dynamic libraries for unpackaged programs
# here, NOT in environment.systemPackages
];
programs.fish.enable = true;
programs.nh = {
enable = true;
clean.enable = true;
clean.extraArgs = "--keep-since 4d --keep 3";
flake = "/home/m3tam3re/p/nixos/nixos-config";
};
}
-84
View File
@@ -1,84 +0,0 @@
{
age = {
secrets = {
baserow-env = {file = ../../secrets/baserow-env.age;};
ghost-env = {file = ../../secrets/ghost-env.age;};
honcho-selfhost-db-password = {
file = ../../secrets/honcho-selfhost-db-password.age;
owner = "postgres";
group = "postgres";
mode = "400";
};
honcho-selfhost-env = {file = ../../secrets/honcho-selfhost-env.age;};
honcho-selfhost-jwt-secret = {file = ../../secrets/honcho-selfhost-jwt-secret.age;};
kestra-config = {
file = ../../secrets/kestra-config.age;
mode = "644";
};
kestra-env = {file = ../../secrets/kestra-env.age;};
littlelink-m3tam3re = {file = ../../secrets/littlelink-m3tam3re.age;};
minio-root-cred = {file = ../../secrets/minio-root-cred.age;};
rustfs-access-key = {file = ../../secrets/rustfs-access-key.age;};
rustfs-secret-key = {file = ../../secrets/rustfs-secret-key.age;};
n8n-env = {file = ../../secrets/n8n-env.age;};
netbird-auth-secret = {
file = ../../secrets/netbird-auth-secret.age;
};
netbird-db-password = {
file = ../../secrets/netbird-db-password.age;
};
netbird-encryption-key = {
file = ../../secrets/netbird-encryption-key.age;
};
netbird-dashboard-env = {
file = ../../secrets/netbird-dashboard-env.age;
};
netbird-server-env = {
file = ../../secrets/netbird-server-env.age;
};
netbird-proxy-env = {
file = ../../secrets/netbird-proxy-env.age;
};
paperless-key = {file = ../../secrets/paperless-key.age;};
restreamer-env = {file = ../../secrets/restreamer-env.age;};
searx = {file = ../../secrets/searx.age;};
tailscale-key = {file = ../../secrets/tailscale-key.age;};
tuwunel-registration-token = {
file = ../../secrets/tuwunel-registration-token.age;
owner = "tuwunel";
};
traefik = {
file = ../../secrets/traefik.age;
owner = "traefik";
};
vaultwarden-env = {file = ../../secrets/vaultwarden-env.age;};
m3tam3re-secrets = {
file = ../../secrets/m3tam3re-secrets.age;
owner = "m3tam3re";
};
gitea-runner-token = {
file = ../../secrets/gitea-runner-token.age;
mode = "600";
owner = "gitea-runner";
group = "gitea-runner";
};
ref-key = {
file = ../../secrets/ref-key.age;
owner = "m3tam3re";
};
exa-key = {
file = ../../secrets/exa-key.age;
owner = "m3tam3re";
};
basecamp-client-id = {
file = ../../secrets/basecamp-client-id.age;
owner = "m3tam3re";
};
basecamp-client-secret = {
file = ../../secrets/basecamp-client-secret.age;
owner = "m3tam3re";
};
authentik-env = {file = ../../secrets/authentik-env.age;};
};
};
}
@@ -1,85 +0,0 @@
# 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.<name> = {
image = "registry/image:tag";
ports = ["127.0.0.1:<external>:<internal>"];
volumes = ["/var/lib/<service>:/data"];
environmentFiles = [config.age.secrets.<name>-env.path];
extraOptions = [
"--network=web"
"--ip=10.89.0.<sequential>"
"--add-host=mysql:10.89.0.1" # If DB needed
];
};
```
### Traefik Integration
```nix
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";
};
# Legacy redirect (if needed)
routers.<name>-old = {
rule = "Host(`<subdomain>.m3tam3re.com`)";
service = "<name>";
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: `<service>-env.age` with environment variables
@@ -1,67 +0,0 @@
{config, ...}: let
image = "ghcr.io/goauthentik/server:2026.2.0";
serverIp = "10.89.0.22";
workerIp = "10.89.0.23";
postgresHost = "10.89.0.1";
postgresPort = config.m3ta.ports.get "postgres";
authentikPort = config.m3ta.ports.get "authentik";
sharedEnv = {
AUTHENTIK_POSTGRESQL__HOST = postgresHost;
AUTHENTIK_POSTGRESQL__PORT = toString postgresPort;
AUTHENTIK_POSTGRESQL__USER = "authentik";
AUTHENTIK_POSTGRESQL__NAME = "authentik";
};
in {
virtualisation.oci-containers.containers = {
"authentik-server" = {
inherit image;
cmd = ["server"];
environment = sharedEnv;
environmentFiles = [config.age.secrets.authentik-env.path];
ports = ["127.0.0.1:${toString authentikPort}:9000"];
volumes = [
"authentik_media:/media"
"authentik_templates:/templates"
];
extraOptions = [
"--add-host=postgres:${postgresHost}"
"--ip=${serverIp}"
"--network=web"
];
};
"authentik-worker" = {
inherit image;
cmd = ["worker"];
user = "root";
environment = sharedEnv;
environmentFiles = [config.age.secrets.authentik-env.path];
volumes = [
"authentik_media:/media"
"authentik_certs:/certs"
"authentik_templates:/templates"
];
extraOptions = [
"--add-host=postgres:${postgresHost}"
"--ip=${workerIp}"
"--network=web"
];
};
};
services.traefik.dynamicConfigOptions.http = {
services.authentik.loadBalancer.servers = [
{url = "http://localhost:${toString authentikPort}/";}
];
routers.authentik = {
rule = "Host(`auth.m3ta.dev`)";
tls = {certResolver = "godaddy";};
service = "authentik";
entrypoints = "websecure";
};
};
}
@@ -1,35 +0,0 @@
{config, ...}: {
virtualisation.oci-containers.containers."baserow" = {
image = "docker.io/baserow/baserow:2.0.6";
environmentFiles = [config.age.secrets.baserow-env.path];
ports = ["127.0.0.1:${toString (config.m3ta.ports.get "baserow")}:80"];
volumes = ["baserow_data:/baserow/data"];
extraOptions = ["--add-host=postgres:10.89.0.1" "--ip=10.89.0.10" "--network=web"];
};
# Traefik configuration specific to baserow
services.traefik.dynamicConfigOptions.http = {
services.baserow.loadBalancer.servers = [
{
url = "http://localhost:${toString (config.m3ta.ports.get "baserow")}/";
}
];
routers.baserow = {
rule = "Host(`br.m3ta.dev`)";
tls = {
certResolver = "godaddy";
};
service = "baserow";
entrypoints = "websecure";
};
routers.baserow-old = {
rule = "Host(`br.m3tam3re.com`)";
tls = {
certResolver = "godaddy";
};
service = "baserow";
entrypoints = "websecure";
middlewares = ["subdomain-redirect"];
};
};
}
@@ -1,22 +0,0 @@
{lib, ...}: {
imports = [
./baserow.nix
./ghost.nix
./honcho.nix
./kestra.nix
./littlelink.nix
./matomo.nix
./netbird.nix
# ./n8n.nix
# ./pangolin.nix
./restreamer.nix
./slash.nix
./slash-nemoti.nix
./authentik.nix
];
system.activationScripts.createPodmanNetworkWeb = lib.mkAfter ''
if ! /run/current-system/sw/bin/podman network exists web; then
/run/current-system/sw/bin/podman network create web --subnet=10.89.0.0/24 --internal
fi
'';
}
@@ -1,37 +0,0 @@
{config, ...}: {
virtualisation.oci-containers.containers."ghost" = {
image = "docker.io/ghost:latest";
environmentFiles = [config.age.secrets.ghost-env.path];
ports = ["127.0.0.1:3002:2368"];
volumes = ["ghost_data:/var/lib/ghost/content"];
extraOptions = ["--add-host=mysql:10.89.0.1" "--ip=10.89.0.11" "--network=web"];
};
# Traefik configuration specific to ghost
services.traefik.dynamicConfigOptions.http = {
services.ghost.loadBalancer.servers = [
{
url = "http://localhost:3002/";
}
];
routers = {
ghost = {
rule = "Host(`m3ta.dev`) || Host(`www.m3ta.dev`)";
tls = {
certResolver = "godaddy";
};
service = "ghost";
entrypoints = "websecure";
middlewares = ["strip-www"];
};
ghost-old = {
rule = "Host(`www.m3tam3re.com`)";
tls = {
certResolver = "godaddy";
};
service = "ghost";
entrypoints = "websecure";
middlewares = ["domain-redirect"];
};
};
};
}
@@ -1,209 +0,0 @@
{
config,
lib,
pkgs,
...
}: let
serviceName = "honcho";
image = "ghcr.io/plastic-labs/honcho:v3.0.6";
apiIp = "10.89.0.24";
deriverIp = "10.89.0.25";
redisIp = "10.89.0.26";
postgresHost = "10.89.0.1";
postgresPort = config.m3ta.ports.get "postgres";
honchoPort = config.m3ta.ports.get "honcho";
# m3-atlas Netbird mesh address, discovered from `netbird status -d`.
# Binding the host port here keeps self-hosted Honcho off public interfaces.
netbirdBindAddress = "100.81.142.56";
netbirdRange = "100.64.0.0/16";
dbName = "honcho";
dbUser = "honcho";
redisName = "${serviceName}-redis";
runtimeDirectory = "/run/${serviceName}";
runtimeEnvFile = "${runtimeDirectory}/env";
# Keep auth disabled for the first deployment because Honcho clients need
# generated JWTs. The JWT secret is still provisioned so enabling auth later is
# a one-line change here plus client token generation.
authUseAuth = false;
sharedEnvironment = {
CACHE_ENABLED = "true";
CACHE_URL = "redis://${redisName}:6379/0?suppress=true";
LOG_LEVEL = "INFO";
TELEMETRY_ENABLED = "false";
VECTOR_STORE_MIGRATED = "false";
VECTOR_STORE_TYPE = "pgvector";
AUTH_USE_AUTH = lib.boolToString authUseAuth;
};
sharedEnvironmentFiles = [
runtimeEnvFile
config.age.secrets."${serviceName}-selfhost-env".path
];
webNetwork = ip: [
"--add-host=postgres:${postgresHost}"
"--network=web:ip=${ip}"
];
# The shared web network is intentionally internal. API and deriver also join
# this egress-only network so LLM provider calls can leave the host without
# exposing any extra inbound ports.
networksWithEgress = ip:
(webNetwork ip)
++ [
"--network=${serviceName}-egress"
];
apiHealthCmd = ''/app/.venv/bin/python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health', timeout=2).read()"'';
in {
system.activationScripts.createPodmanNetworkHonchoEgress = lib.mkAfter ''
if ! /run/current-system/sw/bin/podman network exists ${serviceName}-egress; then
/run/current-system/sw/bin/podman network create ${serviceName}-egress
fi
'';
virtualisation.oci-containers.containers = {
"${serviceName}-redis" = {
image = "docker.io/redis:8.2";
autoStart = true;
volumes = ["${serviceName}_redis_data:/data"];
extraOptions =
(webNetwork redisIp)
++ [
"--health-cmd=redis-cli ping"
"--health-interval=5s"
"--health-timeout=5s"
"--health-retries=5"
];
};
"${serviceName}-api" = {
inherit image;
autoStart = true;
entrypoint = "sh";
cmd = ["docker/entrypoint.sh"];
environment = sharedEnvironment;
environmentFiles = sharedEnvironmentFiles;
ports = ["${netbirdBindAddress}:${toString honchoPort}:8000"];
dependsOn = [redisName];
extraOptions =
(networksWithEgress apiIp)
++ [
"--health-cmd=${apiHealthCmd}"
"--health-interval=5s"
"--health-timeout=5s"
"--health-retries=5"
"--health-start-period=10s"
];
};
"${serviceName}-deriver" = {
inherit image;
autoStart = true;
entrypoint = "/app/.venv/bin/python";
cmd = ["-m" "src.deriver"];
environment = sharedEnvironment;
environmentFiles = sharedEnvironmentFiles;
dependsOn = ["${serviceName}-api" redisName];
extraOptions = networksWithEgress deriverIp;
};
};
systemd.services = {
"${serviceName}-postgres-bootstrap" = {
description = "Bootstrap Honcho PostgreSQL role, database, password, and pgvector";
after = ["postgresql.service" "agenix.service"];
requires = ["postgresql.service" "agenix.service"];
before = ["${serviceName}-env.service" "podman-${serviceName}-api.service" "podman-${serviceName}-deriver.service"];
requiredBy = ["podman-${serviceName}-api.service" "podman-${serviceName}-deriver.service"];
path = [
config.services.postgresql.package
pkgs.coreutils
];
serviceConfig = {
Type = "oneshot";
User = "postgres";
Group = "postgres";
};
script = ''
set -euo pipefail
test -s ${config.age.secrets."${serviceName}-selfhost-db-password".path}
psql -v ON_ERROR_STOP=1 --dbname=postgres <<'SQL'
DO $$
BEGIN
CREATE ROLE ${dbUser} LOGIN;
EXCEPTION WHEN duplicate_object THEN
NULL;
END
$$;
SELECT 'CREATE DATABASE ${dbName} OWNER ${dbUser}'
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '${dbName}')\gexec
ALTER DATABASE ${dbName} OWNER TO ${dbUser};
\set honcho_password `cat ${config.age.secrets."${serviceName}-selfhost-db-password".path}`
ALTER ROLE ${dbUser} WITH LOGIN PASSWORD :'honcho_password';
SQL
psql -v ON_ERROR_STOP=1 --dbname=${dbName} <<'SQL'
CREATE EXTENSION IF NOT EXISTS vector;
GRANT ALL PRIVILEGES ON DATABASE ${dbName} TO ${dbUser};
SQL
'';
};
"${serviceName}-env" = {
description = "Generate Honcho runtime environment file with agenix secrets";
after = ["agenix.service" "${serviceName}-postgres-bootstrap.service"];
requires = ["agenix.service" "${serviceName}-postgres-bootstrap.service"];
before = ["podman-${serviceName}-api.service" "podman-${serviceName}-deriver.service"];
requiredBy = ["podman-${serviceName}-api.service" "podman-${serviceName}-deriver.service"];
path = [
pkgs.coreutils
pkgs.python3
];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
script = ''
set -euo pipefail
install -d -m 0750 ${runtimeDirectory}
db_password_encoded=$(
python3 -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.stdin.read().strip(), safe=""))' \
< ${config.age.secrets."${serviceName}-selfhost-db-password".path}
)
jwt_secret=$(tr -d '\r\n' < ${config.age.secrets."${serviceName}-selfhost-jwt-secret".path})
umask 077
cat > ${runtimeEnvFile} <<ENV
DB_CONNECTION_URI=postgresql+psycopg://${dbUser}:$db_password_encoded@postgres:${toString postgresPort}/${dbName}
AUTH_JWT_SECRET=$jwt_secret
ENV
'';
};
"podman-${serviceName}-api" = {
after = ["${serviceName}-env.service" "${serviceName}-postgres-bootstrap.service"];
requires = ["${serviceName}-env.service" "${serviceName}-postgres-bootstrap.service"];
};
"podman-${serviceName}-deriver" = {
after = ["${serviceName}-env.service" "${serviceName}-postgres-bootstrap.service"];
requires = ["${serviceName}-env.service" "${serviceName}-postgres-bootstrap.service"];
};
};
networking.firewall.extraCommands = ''
# Self-hosted Honcho API: only Netbird mesh peers may reach ${netbirdBindAddress}:${toString honchoPort}.
ip46tables -A nixos-fw -p tcp --dport ${toString honchoPort} -s ${netbirdRange} -j nixos-fw-accept
'';
}
@@ -1,32 +0,0 @@
{config, ...}: {
virtualisation.oci-containers.containers."kestra" = {
image = "docker.io/kestra/kestra:latest";
environmentFiles = [config.age.secrets.kestra-env.path];
cmd = ["server" "standalone" "--config" "/etc/config/application.yaml"];
ports = ["127.0.0.1:3018:8080"];
user = "root";
volumes = [
"/var/run/docker.sock:/var/run/docker.sock"
"${config.age.secrets.kestra-config.path}:/etc/config/application.yaml"
"kestra_data:/app/storage"
"/tmp/kestra-wd:/tmp/kestra-wd"
];
extraOptions = ["--add-host=postgres:10.89.0.1" "--ip=10.89.0.18" "--network=web"];
};
systemd.tmpfiles.rules = [
"d /tmp/kestra-wd 0750 1000 1000 - -"
];
# Traefik configuration specific to littlelink
services.traefik.dynamicConfigOptions.http = {
services.kestra.loadBalancer.servers = [{url = "http://localhost:3018/";}];
routers.kestra = {
rule = "Host(`k.m3ta.dev`)";
tls = {certResolver = "godaddy";};
service = "kestra";
entrypoints = "websecure";
};
};
}
@@ -1,25 +0,0 @@
{config, ...}: {
virtualisation.oci-containers.containers."littlelink_m3tam3re" = {
image = "ghcr.io/techno-tim/littlelink-server";
environmentFiles = [config.age.secrets.littlelink-m3tam3re.path];
ports = ["127.0.0.1:3004:3000"];
extraOptions = ["--ip=10.89.0.4" "--network=web"];
};
# Traefik configuration specific to littlelink
services.traefik.dynamicConfigOptions.http = {
services.littlelink-m3tam3re.loadBalancer.servers = [
{
url = "http://localhost:3004/";
}
];
routers.littlelink-m3tam3re = {
rule = "Host(`links.m3tam3re.com`)";
tls = {
certResolver = "godaddy";
};
service = "littlelink-m3tam3re";
entrypoints = "websecure";
};
};
}
@@ -1,43 +0,0 @@
{
virtualisation.oci-containers.containers."matomo" = {
image = "docker.io/matomo:latest";
ports = ["127.0.0.1:3011:80"];
volumes = ["matomo_data:/var/www/html"];
environment = {
MATOMO_DATABASE_HOST = "mysql";
MATOMO_DATABASE_USERNAME = "matomo";
MATOMO_DATABASE_PASSWORD = "matomo";
MATOMO_DATABASE_DBNAME = "matomo";
MYSQL_DATABASE = "matomo";
PHP_MEMORY_LIMIT = "2048M";
};
extraOptions = ["--add-host=mysql:10.89.0.1" "--ip=10.89.0.16" "--network=web"];
};
# Traefik configuration specific to ghost
services.traefik.dynamicConfigOptions.http = {
services.matomo.loadBalancer.servers = [
{
url = "http://localhost:3011/";
}
];
routers = {
matomo-nemoti = {
rule = "Host(`stats.nemoti.com`)";
tls = {
certResolver = "godaddy";
};
service = "matomo";
entrypoints = "websecure";
};
matomo-m3tam3re = {
rule = "Host(`stats.m3tam3re.com`)";
tls = {
certResolver = "godaddy";
};
service = "matomo";
entrypoints = "websecure";
};
};
};
}
@@ -1,27 +0,0 @@
{config, ...}: {
virtualisation.oci-containers.containers."n8n" = {
image = "docker.n8n.io/n8nio/n8n";
environmentFiles = [config.age.secrets.n8n-env.path];
ports = ["127.0.0.1:5678:5678"];
volumes = ["n8n_data:/home/node/.n8n"];
extraOptions = ["--add-host=postgres:10.89.0.1" "--ip=10.89.0.14" "--network=web"];
};
# Traefik configuration specific to n8n
services.traefik.dynamicConfigOptions.http = {
services.n8n.loadBalancer.servers = [
{
url = "http://localhost:5678/";
}
];
routers.n8n = {
rule = "Host(`wf.m3tam3re.com`)";
tls = {
certResolver = "godaddy";
};
service = "n8n";
entrypoints = "websecure";
};
};
}
@@ -1,244 +0,0 @@
{
config,
pkgs,
...
}: let
serviceName = "netbird";
stunPort = config.m3ta.ports.get "netbird-stun";
proxyTlsPort = config.m3ta.ports.get "netbird-proxy";
metricsPort = config.m3ta.ports.get "netbird-metrics";
healthPort = config.m3ta.ports.get "netbird-health";
postgresPort = config.m3ta.ports.get "postgres";
wireguardPort = config.m3ta.ports.get "wireguard";
domain = "v.m3ta.dev";
proxyDomain = "p.m3ta.dev";
ipBase = "10.89.0";
ipOffset = 50;
dashboardIp = "${ipBase}.${toString ipOffset}";
serverIp = "${ipBase}.${toString (ipOffset + 1)}";
proxyIp = "${ipBase}.${toString (ipOffset + 2)}";
# Database configuration
dbName = "netbird";
dbUser = "netbird";
dbHost = "${ipBase}.1";
# NetBird config as Nix attribute set
netbirdConfig = {
server = {
listenAddress = ":80";
exposedAddress = "https://${domain}:443";
stunPorts = [stunPort];
metricsPort = metricsPort;
healthcheckAddress = ":${toString healthPort}";
logLevel = "info";
logFile = "console";
dataDir = "/var/lib/netbird";
auth = {
issuer = "https://${domain}/oauth2";
localAuthDisabled = true;
signKeyRefreshEnabled = true;
dashboardRedirectURIs = [
"https://${domain}/nb-auth"
"https://${domain}/nb-silent-auth"
];
cliRedirectURIs = ["http://localhost:53000/"];
};
reverseProxy = {
trustedHTTPProxies = ["${ipBase}.1/32"];
};
# Proxy feature
proxy = {
enabled = true;
domain = proxyDomain;
};
store = {
engine = "postgres";
postgres = {
host = dbHost;
port = postgresPort;
database = dbName;
username = dbUser;
};
};
};
};
# Generate YAML from Nix attribute set
yamlFormat = pkgs.formats.yaml {};
configYamlBase = yamlFormat.generate "netbird-config-base.yaml" netbirdConfig;
# Script that injects secrets at runtime
configGenScript = pkgs.writeShellScript "netbird-gen-config" ''
set -euo pipefail
AUTH_SECRET=$(cat "$1")
DB_PASSWORD=$(cat "$2")
ENCRYPTION_KEY=$(cat "$3")
${pkgs.yq-go}/bin/yq eval "
.server.authSecret = \"$AUTH_SECRET\" |
.server.store.encryptionKey = \"$ENCRYPTION_KEY\" |
.server.store.postgres.password = \"$DB_PASSWORD\"
" ${configYamlBase}
'';
in {
age.secrets."${serviceName}-auth-secret".file = ../../../../secrets/${serviceName}-auth-secret.age;
age.secrets."${serviceName}-db-password".file = ../../../../secrets/${serviceName}-db-password.age;
age.secrets."${serviceName}-encryption-key".file = ../../../../secrets/${serviceName}-encryption-key.age;
age.secrets."${serviceName}-dashboard-env".file = ../../../../secrets/${serviceName}-dashboard-env.age;
age.secrets."${serviceName}-server-env".file = ../../../../secrets/${serviceName}-server-env.age;
age.secrets."${serviceName}-proxy-env".file = ../../../../secrets/${serviceName}-proxy-env.age;
# Oneshot systemd service that generates the config with injected secrets
systemd.services."${serviceName}-config" = {
description = "Generate NetBird config with secrets";
wantedBy = ["multi-user.target"];
before = ["podman-${serviceName}-server.service"];
requiredBy = ["podman-${serviceName}-server.service"];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = pkgs.writeShellScript "netbird-write-config" ''
mkdir -p /var/lib/${serviceName}
${configGenScript} \
${config.age.secrets."${serviceName}-auth-secret".path} \
${config.age.secrets."${serviceName}-db-password".path} \
${config.age.secrets."${serviceName}-encryption-key".path} \
> /var/lib/${serviceName}/config.yaml
chmod 600 /var/lib/${serviceName}/config.yaml
'';
};
};
virtualisation.oci-containers.containers = {
"${serviceName}-dashboard" = {
image = "netbirdio/dashboard:latest";
autoStart = true;
environmentFiles = [config.age.secrets."${serviceName}-dashboard-env".path];
extraOptions = [
"--ip=${dashboardIp}"
"--network=web"
];
};
"${serviceName}-server" = {
image = "netbirdio/netbird-server:latest";
autoStart = true;
ports = ["${toString stunPort}:${toString stunPort}/udp"];
environmentFiles = [config.age.secrets."${serviceName}-server-env".path];
volumes = [
"${serviceName}_data:/var/lib/netbird"
"/var/lib/${serviceName}/config.yaml:/etc/netbird/config.yaml:ro"
];
cmd = ["--config" "/etc/netbird/config.yaml"];
extraOptions = [
"--ip=${serverIp}"
"--network=web"
];
};
"${serviceName}-proxy" = {
image = "netbirdio/reverse-proxy:latest";
autoStart = true;
ports = ["${toString wireguardPort}:${toString wireguardPort}/udp"];
volumes = [
"${serviceName}_proxy_certs:/certs"
];
environmentFiles = [config.age.secrets."${serviceName}-proxy-env".path];
cmd = [
"--domain=${proxyDomain}"
"--mgmt=https://${domain}:443"
"--addr=:${toString proxyTlsPort}"
"--cert-dir=/certs"
"--acme-certs"
"--trusted-proxies=${ipBase}.1/32"
];
dependsOn = ["${serviceName}-server"];
extraOptions = [
"--ip=${proxyIp}"
"--network=web"
];
};
};
services.traefik.dynamicConfigOptions = {
# HTTP services and routers
http = {
services = {
"${serviceName}-dashboard".loadBalancer.servers = [
{url = "http://${dashboardIp}:80/";}
];
"${serviceName}-server".loadBalancer.servers = [
{url = "http://${serverIp}:80/";}
];
"${serviceName}-server-h2c".loadBalancer.servers = [
{url = "h2c://${serverIp}:80";}
];
};
routers = {
# gRPC (Signal + Management)
"${serviceName}-grpc" = {
rule = "Host(`${domain}`) && (PathPrefix(`/signalexchange.SignalExchange/`) || PathPrefix(`/management.ManagementService/`) || PathPrefix(`/management.ProxyService/`))";
entrypoints = "websecure";
tls.certResolver = "godaddy";
service = "${serviceName}-server-h2c";
priority = 100;
};
# Backend (relay, WebSocket, API, OAuth2)
"${serviceName}-backend" = {
rule = "Host(`${domain}`) && (PathPrefix(`/relay`) || PathPrefix(`/ws-proxy/`) || PathPrefix(`/api`) || PathPrefix(`/oauth2`))";
entrypoints = "websecure";
tls.certResolver = "godaddy";
service = "${serviceName}-server";
priority = 100;
};
# Dashboard (catch-all, lowest priority)
"${serviceName}-dashboard" = {
rule = "Host(`${domain}`)";
entrypoints = "websecure";
tls.certResolver = "godaddy";
service = "${serviceName}-dashboard";
priority = 1;
};
};
};
# TCP for proxy TLS passthrough
tcp = {
services."${serviceName}-proxy-tls".loadBalancer.servers = [
{address = "${proxyIp}:${toString proxyTlsPort}";}
];
routers."${serviceName}-proxy-passthrough" = {
entryPoints = ["websecure"];
rule = "HostSNI(`*`)";
service = "${serviceName}-proxy-tls";
priority = 1;
tls.passthrough = true;
};
};
# ServersTransport for Proxy Protocol v2 (optional)
serversTransports."pp-v2" = {
proxyProtocol.version = 2;
};
};
networking.firewall.allowedUDPPorts = [
stunPort # STUN
wireguardPort # WireGuard for proxy
];
}
@@ -1,75 +0,0 @@
{config, ...}: {
virtualisation.oci-containers.containers."restreamer" = {
image = "docker.io/datarhei/restreamer:latest";
environmentFiles = [config.age.secrets.restreamer-env.path];
# Modified ports to include RTMPS
ports = [
"127.0.0.1:${toString (config.m3ta.ports.get "restreamer")}:8080" # Web UI
"127.0.0.1:1936:1935" # RTMP
];
volumes = [
"restreamer_data:/core/data"
"restreamer_config:/core/config"
];
extraOptions = ["--add-host=postgres:10.89.0.1" "--ip=10.89.0.13" "--network=web"];
};
# Traefik configuration
services.traefik = {
dynamicConfigOptions = {
http = {
services.restreamer.loadBalancer.servers = [
{
url = "http://localhost:${toString (config.m3ta.ports.get "restreamer")}/";
}
];
routers.restreamer = {
rule = "Host(`stream.m3ta.dev`)";
tls = {
certResolver = "godaddy";
};
service = "restreamer";
entrypoints = ["websecure"];
};
};
tcp = {
services = {
rtmp-service.loadBalancer.servers = [
{
address = "localhost:1936";
}
];
rtmps-service.loadBalancer.servers = [
{
address = "localhost:1936";
}
];
};
routers = {
rtmp = {
rule = "HostSNI(`*`)"; # Changed to accept all SNI
service = "rtmp-service";
entryPoints = ["rtmp"];
};
rtmps = {
rule = "HostSNI(`stream.m3tam3re.com`)";
service = "rtmps-service";
entryPoints = ["rtmps"];
tls = {
certResolver = "godaddy";
passthrough = false;
};
};
};
};
};
};
# Firewall configuration
networking.firewall = {
allowedTCPPorts = [1935 1945];
};
}
@@ -1,27 +0,0 @@
{
virtualisation.oci-containers.containers."slash-nemoti" = {
image = "docker.io/yourselfhosted/slash:latest";
ports = ["127.0.0.1:3016:5231"];
volumes = [
"slash-nemoti_data:/var/opt/slash"
];
extraOptions = ["--ip=10.89.0.17" "--network=web"];
};
# Traefik configuration specific to littlelink
services.traefik.dynamicConfigOptions.http = {
services.slash-nemoti.loadBalancer.servers = [
{
url = "http://localhost:3016/";
}
];
routers.slash-nemoti = {
rule = "Host(`l.nemoti.art`)";
tls = {
certResolver = "godaddy";
};
service = "slash-nemoti";
entrypoints = "websecure";
};
};
}
@@ -1,27 +0,0 @@
{
virtualisation.oci-containers.containers."slash" = {
image = "docker.io/yourselfhosted/slash:latest";
ports = ["127.0.0.1:3010:5231"];
volumes = [
"slash_data:/var/opt/slash"
];
extraOptions = ["--ip=10.89.0.15" "--network=web"];
};
# Traefik configuration specific to littlelink
services.traefik.dynamicConfigOptions.http = {
services.slash.loadBalancer.servers = [
{
url = "http://localhost:3010/";
}
];
routers.slash = {
rule = "Host(`l.m3ta.dev`)";
tls = {
certResolver = "godaddy";
};
service = "slash";
entrypoints = "websecure";
};
};
}
-18
View File
@@ -1,18 +0,0 @@
{
imports = [
./tuwunel.nix
./containers
./gitea.nix
./gitea-actions-runner.nix
./rustfs.nix
./mysql.nix
./netbird.nix
./n8n.nix
./paperless.nix
./postgres.nix
./searx.nix
./traefik.nix
./vaultwarden.nix
./wastebin.nix
];
}
@@ -1,57 +0,0 @@
{
config,
pkgs,
...
}: {
services.gitea-actions-runner = {
instances.default = {
enable = true;
name = "${config.networking.hostName}-runner";
url = "https://code.m3ta.dev";
tokenFile = config.age.secrets.gitea-runner-token.path;
# nixos:host is primary, ubuntu is fallback
labels = [
"nixos:host"
];
# Host execution packages
hostPackages = with pkgs; [
bash
curl
coreutils
git
jq
nix
nix-update
nodejs
# Add any other tools you need for nix-update workflows
];
# Advanced settings
settings = {
runner = {
capacity = 4; # One job at a time (increase if you have resources)
timeout = "4h"; # Nix builds can take a while
};
cache = {enabled = true;};
container = {
enable_ipv6 = true;
privileged = false;
};
};
};
};
# User management (auto-created by module, but ensuring proper setup)
users.users.gitea-runner = {
home = "/var/lib/gitea-runner";
group = "gitea-runner";
isSystemUser = true;
createHome = true;
};
users.groups.gitea-runner = {};
# Firewall: Allow Podman bridge networks for cache actions
networking.firewall.trustedInterfaces = ["br-+"];
}
-46
View File
@@ -1,46 +0,0 @@
{config, ...}: {
services.gitea = {
enable = true;
settings = {
server = {
ROOT_URL = "https://code.m3ta.dev";
HTTP_PORT = config.m3ta.ports.get "gitea";
};
mailer.SENDMAIL_PATH = "/run/wrappers/bin/sendmail";
service.DISABLE_REGISTRATION = true;
};
lfs.enable = true;
dump = {
enable = true;
type = "tar.gz";
interval = "03:30:00";
backupDir = "/var/backup/gitea";
};
};
# Traefik configuration specific to gitea
services.traefik.dynamicConfigOptions.http = {
services.gitea.loadBalancer.servers = [
{
url = "http://localhost:${toString (config.m3ta.ports.get "gitea")}/";
}
];
routers.gitea = {
rule = "Host(`code.m3ta.dev`)";
tls = {
certResolver = "godaddy";
};
service = "gitea";
entrypoints = "websecure";
};
routers.gitea-old = {
rule = "Host(`code.m3tam3re.com`)";
tls = {
certResolver = "godaddy";
};
service = "gitea";
entrypoints = "websecure";
middlewares = ["subdomain-redirect"];
};
};
}
-27
View File
@@ -1,27 +0,0 @@
{pkgs, ...}: {
services.mysql = {
enable = true;
package = pkgs.mysql84;
ensureDatabases = [
"ghost"
"matomo"
];
initialScript = pkgs.writeText "initial-script.sql" ''
CREATE USER 'ghost'@'10.89.%' IDENTIFIED BY 'ghost';
GRANT ALL PRIVILEGES ON ghost.* TO 'ghost'@'10.89.%';
CREATE USER 'matomo'@'10.89.%' IDENTIFIED BY 'matomo';
GRANT ALL PRIVILEGES ON matomo.* TO 'matomo'@'10.89.%'; '';
};
services.mysqlBackup = {
enable = true;
calendar = "03:00:00";
databases = ["ghost" "matomo"];
};
networking.firewall = {
extraCommands = ''
iptables -A INPUT -p tcp -s 127.0.0.1 --dport 3306 -j ACCEPT
iptables -A INPUT -p tcp -s 10.89.0.0/24 --dport 3306 -j ACCEPT
'';
};
}
-34
View File
@@ -1,34 +0,0 @@
{
config,
lib,
...
}: {
services.n8n = {
enable = true;
environment.WEBHOOK_URL = "https://wf.m3tam3re.com";
};
# Temporary fix for upstream module
systemd.services.n8n.serviceConfig.LoadCredential = lib.mkForce [];
systemd.services.n8n.environment.N8N_RUNNERS_AUTH_TOKEN_FILE = lib.mkForce null;
systemd.services.n8n.serviceConfig = {
EnvironmentFile = ["${config.age.secrets.n8n-env.path}"];
};
# Traefik configuration specific to n8n
services.traefik.dynamicConfigOptions.http = {
services.n8n.loadBalancer.servers = [
{
url = "http://localhost:5678/";
}
];
routers.n8n = {
rule = "Host(`wf.m3ta.dev`)";
tls = {
certResolver = "godaddy";
};
service = "n8n";
entrypoints = "websecure";
};
};
}
-28
View File
@@ -1,28 +0,0 @@
{pkgs, ...}: {
services.netbird.enable = true;
systemd.services.netbird = {
environment = {
NB_DISABLE_SSH_CONFIG = "true";
};
path = [
pkgs.shadow
pkgs.util-linux
];
};
programs.ssh.extraConfig = ''
Match exec "${pkgs.netbird}/bin/netbird ssh detect %h %p"
PreferredAuthentications password,publickey,keyboard-interactive
PasswordAuthentication yes
PubkeyAuthentication yes
BatchMode no
ProxyCommand ${pkgs.netbird}/bin/netbird ssh proxy %h %p
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
CheckHostIP no
LogLevel ERROR
'';
networking.firewall.checkReversePath = "loose";
}
-40
View File
@@ -1,40 +0,0 @@
{config, ...}: {
services.paperless = {
enable = true;
port = config.m3ta.ports.get "paperless";
database.createLocally = true;
passwordFile = config.age.secrets.paperless-key.path;
configureTika = true;
settings = {
PAPERLESS_URL = "https://pl.m3ta.dev";
DATABASE_URL = "postgresql://paperless:paperless@127.0.0.1:${toString (config.m3ta.ports.get "postgres")}/paperless";
PAPERLESS_CONSUMER_IGNORE_PATTERN = [
".DS_STORE/*"
"desktop.ini"
".env"
];
PAPERLESS_OCR_LANGUAGE = "deu+eng";
PAPERLESS_OCR_USER_ARGS = {
optimize = 1;
pdfa_image_compression = "lossless";
};
};
};
# Traefik configuration for headscale
services.traefik.dynamicConfigOptions.http = {
services.paperless.loadBalancer.servers = [
{
url = "http://localhost:${toString (config.m3ta.ports.get "paperless")}/";
}
];
routers.paperless = {
rule = "Host(`pl.m3ta.dev`)";
tls = {
certResolver = "godaddy";
};
service = "paperless";
entrypoints = "websecure";
};
};
}
-50
View File
@@ -1,50 +0,0 @@
{
pkgs,
config,
...
}: {
services.postgresql = {
enable = true;
enableTCPIP = true;
package = pkgs.postgresql_17;
extensions = with pkgs.postgresql17Packages; [
pgvector
];
authentication = pkgs.lib.mkOverride 10 ''
# Local connections (Unix socket)
local all postgres peer
local paperless paperless scram-sha-256
# Localhost connections (IPv4 and IPv6)
host all postgres 127.0.0.1/32 scram-sha-256
host all postgres ::1/128 scram-sha-256
host outline outline 127.0.0.1/32 scram-sha-256
host outline outline ::1/128 scram-sha-256
host paperless paperless 127.0.0.1/32 scram-sha-256
host paperless paperless ::1/128 scram-sha-256
# Podman network connections for Baserow
host baserow baserow 10.89.0.0/24 scram-sha-256
host kestra kestra 10.89.0.0/24 scram-sha-256
host netbird netbird 10.89.0.0/24 scram-sha-256
host authentik authentik 10.89.0.0/24 scram-sha-256
host honcho honcho 10.89.0.0/24 scram-sha-256
# Deny all other connections
local all all reject
host all all 0.0.0.0/0 reject
host all all ::/0 reject
'';
};
services.postgresqlBackup = {
enable = true;
startAt = "03:10:00";
databases = ["baserow" "paperless" "kestra" "authentik" "netbird" "honcho"];
};
networking.firewall = {
extraCommands = ''
iptables -A INPUT -p tcp -s 127.0.0.1 --dport ${toString (config.m3ta.ports.get "postgres")} -j ACCEPT
iptables -A INPUT -p tcp -s 10.89.0.0/24 --dport ${toString (config.m3ta.ports.get "postgres")} -j ACCEPT
'';
};
}
-56
View File
@@ -1,56 +0,0 @@
{
config,
inputs,
pkgs,
...
}: {
services.rustfs = {
enable = true;
package = inputs.rustfs.packages.${pkgs.stdenv.hostPlatform.system}.default;
# Reuse existing MinIO data directory
volumes = "/var/storage/s3";
# Keep same ports as MinIO to avoid changing Traefik and client configs
address = ":3008";
consoleEnable = true;
consoleAddress = ":3007";
# Credentials via agenix
accessKeyFile = config.age.secrets.rustfs-access-key.path;
secretKeyFile = config.age.secrets.rustfs-secret-key.path;
logLevel = "info";
};
# Traefik configuration — same routes as before
services.traefik.dynamicConfigOptions.http = {
services.minio-console.loadBalancer.servers = [
{
url = "http://localhost:3007/";
}
];
services.minio.loadBalancer.servers = [
{
url = "http://localhost:3008/";
}
];
routers.minio = {
rule = "Host(`s3.m3tam3re.com`)";
tls = {
certResolver = "godaddy";
};
service = "minio";
entrypoints = "websecure";
};
routers.minio-console = {
rule = "Host(`minio.m3tam3re.com`)";
tls = {
certResolver = "godaddy";
};
service = "minio-console";
entrypoints = "websecure";
};
};
}
-37
View File
@@ -1,37 +0,0 @@
{pkgs, ...}: {
services.searx = {
enable = true;
package = pkgs.searxng;
settings = {
server.port = 3005;
server.secret_key = "@SEARX_SECRET_KEY@";
search.formats = ["html" "json"];
};
};
# Traefik configuration specific to searx
services.traefik.dynamicConfigOptions.http = {
services.searx.loadBalancer.servers = [
{
url = "http://localhost:3005/";
}
];
routers.searx = {
rule = "Host(`search.m3ta.dev`)";
tls = {
certResolver = "godaddy";
};
service = "searx";
entrypoints = "websecure";
};
routers.searx-old = {
rule = "Host(`search.m3tam3re.com`)";
tls = {
certResolver = "godaddy";
};
service = "searx";
entrypoints = "websecure";
middlewares = ["subdomain-redirect"];
};
};
}
-116
View File
@@ -1,116 +0,0 @@
{config, ...}: {
services.traefik = {
enable = true;
staticConfigOptions = {
log = {level = "WARN";};
certificatesResolvers = {
godaddy = {
acme = {
email = "letsencrypt.org.btlc2@passmail.net";
storage = "/var/lib/traefik/acme.json";
caserver = "https://acme-v02.api.letsencrypt.org/directory";
dnsChallenge = {
provider = "godaddy";
resolvers = ["1.1.1.1:53" "8.8.8.8:53"];
propagation = {
delayBeforeChecks = 60;
disableChecks = true;
};
};
};
};
};
api = {};
entryPoints = {
web = {
address = ":80";
http.redirections.entryPoint = {
to = "websecure";
scheme = "https";
};
};
rtmp = {
address = ":1935";
};
rtmps = {
address = ":1945";
};
websecure = {
address = ":443";
};
};
};
dynamicConfigOptions = {
http = {
services = {
# ── Hermes Dashboard (m3-hermes over Netbird) ────────────────
hermes-dashboard = {
loadBalancer.servers = [
{url = "http://100.81.231.152:9119";}
];
};
dummy = {
loadBalancer.servers = [
{url = "http://192.168.0.1";} # Diese URL wird nie verwendet
];
};
};
middlewares = {
domain-redirect = {
redirectRegex = {
regex = "^https://www\\.m3tam3re\\.com(.*)";
replacement = "https://m3ta.dev$1";
permanent = true;
};
};
strip-www = {
redirectRegex = {
regex = "^https://www\\.(.+)";
replacement = "https://$1";
permanent = true;
};
};
subdomain-redirect = {
redirectRegex = {
regex = "^https://([a-zA-Z0-9-]+)\\.m3tam3re\\.com(.*)";
replacement = "https://$1.m3ta.dev$2";
permanent = true;
};
};
auth = {
basicAuth = {
users = ["m3tam3re:$apr1$1xqdta2b$DIVNvvp5iTUGNccJjguKh."];
};
};
};
routers = {
# ── Hermes Dashboard — Netbird mesh only ─────────────────────
hermes-dashboard = {
rule = "Host(`dash.m3ta.dev`)";
service = "hermes-dashboard";
entrypoints = ["websecure"];
tls = {
certResolver = "godaddy";
};
};
api = {
rule = "Host(`r.m3tam3re.com`)";
service = "api@internal";
middlewares = ["auth"];
entrypoints = ["websecure"];
tls = {
certResolver = "godaddy";
};
};
};
};
};
};
systemd.services.traefik.serviceConfig = {
EnvironmentFile = ["${config.age.secrets.traefik.path}"];
};
networking.firewall.allowedTCPPorts = [80 443];
}
-50
View File
@@ -1,50 +0,0 @@
{config, ...}: let
# Tuwunel uses a list for ports
tuwunel-port = config.m3ta.ports.get "tuwunel";
in {
services.matrix-tuwunel = {
enable = true;
settings.global = {
server_name = "m3ta.dev";
address = ["127.0.0.1"];
port = [tuwunel-port];
max_request_size = 20000000;
allow_registration = true;
registration_token_file = config.age.secrets."tuwunel-registration-token".path;
allow_encryption = true;
allow_federation = true;
trusted_servers = ["matrix.org"];
};
};
# Traefik configuration for Tuwunel
services.traefik.dynamicConfigOptions.http = {
services.tuwunel.loadBalancer.servers = [
{
url = "http://localhost:${toString tuwunel-port}/";
}
];
routers.tuwunel = {
rule = "Host(`matrix.m3ta.dev`)";
tls = {
certResolver = "godaddy";
};
service = "tuwunel";
entrypoints = "websecure";
};
# Federation endpoint on base domain
routers.tuwunel-federation = {
rule = "Host(`m3ta.dev`) && PathPrefix(`/_matrix`)";
tls = {
certResolver = "godaddy";
};
service = "tuwunel";
entrypoints = "websecure";
};
};
# Open federation port
networking.firewall.allowedTCPPorts = [8448];
}
-29
View File
@@ -1,29 +0,0 @@
{config, ...}: {
services.vaultwarden = {
enable = true;
backupDir = "/var/backup/vaultwarden";
config = {
ROCKET_ADDRESS = "127.0.0.1";
ROCKET_PORT = 3013;
};
environmentFile = "${config.age.secrets.vaultwarden-env.path}";
};
# Traefik configuration for headscale
services.traefik.dynamicConfigOptions.http = {
services.vaultwarden.loadBalancer.servers = [
{
url = "http://localhost:3013/";
}
];
routers.vaultwarden = {
rule = "Host(`vw.m3ta.dev`)";
tls = {
certResolver = "godaddy";
};
service = "vaultwarden";
entrypoints = "websecure";
};
};
}
-37
View File
@@ -1,37 +0,0 @@
{
services.wastebin = {
enable = true;
settings = {
WASTEBIN_TITLE = "m3tam3re's wastebin";
WASTEBIN_BASE_URL = "https://bin.m3ta.dev";
WASTEBIN_ADDRESS_PORT = "0.0.0.0:3003";
WASTEBIN_MAX_BODY_SIZE = 1048576;
};
};
# Traefik configuration specific to wastebin
services.traefik.dynamicConfigOptions.http = {
services.wastebin.loadBalancer.servers = [
{
url = "http://localhost:3003/";
}
];
routers.wastebin = {
rule = "Host(`bin.m3ta.dev`)";
tls = {
certResolver = "godaddy";
};
service = "wastebin";
entrypoints = "websecure";
};
routers.wastebin-old = {
rule = "Host(`bin.m3tam3re.com`)";
tls = {
certResolver = "godaddy";
};
service = "wastebin";
entrypoints = "websecure";
middlewares = ["subdomain-redirect"];
};
};
}
-37
View File
@@ -1,37 +0,0 @@
# hosts/m3-daedalus/home.nix — Host-specific home-manager overrides.
# Portable laptop: no Hyprland, no external monitors.
# Everything else (shell, editors, media, theme, etc.) comes from
# m3ta-home via the profile mapping in hosts/common/users/m3tam3re.nix.
{
config,
lib,
...
}:
with lib; {
config = {
# ── XDG / MIME defaults ──
xdg = {
enable = true;
configFile."mimeapps.list".force = true;
mimeApps = {
enable = true;
associations.added = {
"application/zip" = ["org.gnome.FileRoller.desktop"];
"application/csv" = ["calc.desktop"];
"application/pdf" = ["vivaldi-stable.desktop"];
"x-scheme-handler/http" = ["vivaldi-stable.desktop"];
"x-scheme-handler/https" = ["vivaldi-stable.desktop"];
};
defaultApplications = {
"application/zip" = ["org.gnome.FileRoller.desktop"];
"application/csv" = ["calc.desktop"];
"application/pdf" = ["vivaldi-stable.desktop"];
"application/md" = ["dev.zed.Zed.desktop"];
"application/text" = ["dev.zed.Zed.desktop"];
"x-scheme-handler/http" = ["vivaldi-stable.desktop"];
"x-scheme-handler/https" = ["vivaldi-stable.desktop"];
};
};
};
};
}
-111
View File
@@ -1,111 +0,0 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page, on
# https://search.nixos.org/options and in the NixOS manual (`nixos-help`).
{pkgs, ...}: {
imports = [
# Include the results of the hardware scan.
./disko-config.nix
./hardware-configuration.nix
];
# Bootloader.
boot.loader.grub = {
efiSupport = true;
efiInstallAsRemovable = true;
};
networking.hostName = "m3-helios"; # Define your hostname.
networking.hostId = "3ebf1cd3";
# Pick only one of the below networking options.
# networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.
networking.networkmanager.enable =
true; # Easiest to use and most distros use this by default.
# Set your time zone.
time.timeZone = "Europe/Berlin";
# Configure network proxy if necessary
# networking.proxy.default = "http://user:password@proxy:port/";
# networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
# Select internationalisation properties.
i18n.defaultLocale = "en_US.UTF-8";
# console = {
# font = "Lat2-Terminus16";
# keyMap = "us";
# useXkbConfig = true; # use xkb.options in tty.
# };
# Enable the X11 windowing system.
# services.xserver.enable = true;
# Enable the GNOME Desktop Environment.
# services.xserver.displayManager.gdm.enable = true;
# services.xserver.desktopManager.gnome.enable = true;
# Configure keymap in X11
# services.xserver.xkb.layout = "us";
# services.xserver.xkb.options = "eurosign:e,caps:escape";
# Enable CUPS to print documents.
# services.printing.enable = true;
# Enable sound.
# hardware.pulseaudio.enable = true;
# OR
# Enable touchpad support (enabled default in most desktopManager).
# services.libinput.enable = true;
# Define a user account. Don't forget to set a password with passwd.
# List packages installed in system profile. To search, run:
# $ nix search wget
environment.systemPackages = with pkgs; [neovim git];
# Some programs need SUID wrappers, can be configured further or are
# started in user sessions.
# programs.mtr.enable = true;
# programs.gnupg.agent = {
# enable = true;
# enableSSHSupport = true;
# };
# List services that you want to enable:
# Enable the OpenSSH daemon.
services.openssh.enable = true;
services.fstrim = {
enable = true; # For SSD/thin-provisioned storage
interval = "weekly";
};
# Open ports in the firewall.
# networking.firewall.allowedTCPPorts = [ ... ];
# networking.firewall.allowedUDPPorts = [ ... ];
# Or disable the firewall altogether.
# networking.firewall.enable = false;
# Copy the NixOS configuration file and link it from the resulting system
# (/run/current-system/configuration.nix). This is useful in case you
# accidentally delete configuration.nix.
# system.copySystemConfiguration = true;
# This option defines the first version of NixOS you have installed on this particular machine,
# and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions.
#
# Most users should NEVER change this value after the initial install, for any reason,
# even if you've upgraded your system to a new NixOS release.
#
# This value does NOT affect the Nixpkgs version your packages and OS are pulled from,
# so changing it will NOT upgrade your system - see https://nixos.org/manual/nixos/stable/#sec-upgrading for how
# to actually do that.
#
# This value being lower than the current NixOS release does NOT mean your system is
# out of date, out of support, or vulnerable.
#
# Do NOT change this value unless you have manually inspected all the changes it would make to your configuration,
# and migrated your data accordingly.
#
# For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion .
system.stateVersion = "24.11"; # Did you read the comment?
}
-50
View File
@@ -1,50 +0,0 @@
# A staring point is the basic NIXOS configuration generated by the ISO installer.
# On an existing NIXOS install you can use the following command in your flakes basedir:
# sudo nixos-generate-config --dir ./hosts/m3tam3re
#
# Please make sure to change the first couple of lines in your configuration.nix:
# { config, inputs, ouputs, lib, pkgs, ... }:
#
# {
# imports = [ # Include the results of the hardware scan.
# ./hardware-configuration.nix
# inputs.home-manager.nixosModules.home-manager
# ];
# ...
#
# Moreover please update the packages option in your user configuration and add the home-manager options:
# users.users = {
# m3tam3re = {
# isNormalUser = true;
# initialPassword = "12345";
# extraGroups = [ "wheel" ]; # Enable sudo for the user.
# packages = [ inputs.home-manager.packages.${pkgs.system}.default ];
# };
# };
#
# home-manager = {
# useUserPackages = true;
# extraSpecialArgs = { inherit inputs outputs; };
# users.m3tam3re =
# import ../../home/m3tam3re/${config.networking.hostName}.nix;
# };
#
# Please also change your hostname accordingly:
#:w
# networking.hostName = "nixos"; # Define your hostname.
{
imports = [
../common
./configuration.nix
./programs.nix
./secrets.nix
./services
];
extraServices = {
flatpak.enable = true;
ollama.enable = false;
podman.enable = true;
virtualisation.enable = false;
};
}
-39
View File
@@ -1,39 +0,0 @@
{
disko.devices = {
disk = {
main = {
type = "disk";
device = "/dev/sda";
content = {
type = "gpt";
partitions = {
boot = {
size = "1M";
type = "EF02"; # for GRUB MBR
priority = 1;
};
esp = {
size = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = ["defaults" "umask=0077"];
};
};
root = {
size = "100%";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
mountOptions = ["noatime" "nodiratime" "discard"];
};
};
};
};
};
};
};
}
@@ -1,28 +0,0 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{
config,
lib,
pkgs,
modulesPath,
...
}: {
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = ["ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod"];
boot.initrd.kernelModules = [];
boot.kernelModules = [];
boot.extraModulePackages = [];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.ens18.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}
-14
View File
@@ -1,14 +0,0 @@
{pkgs, ...}: {
programs.nix-ld.enable = true;
programs.nix-ld.libraries = with pkgs; [
# Add any missing dynamic libraries for unpackaged programs
# here, NOT in environment.systemPackages
];
programs.fish.enable = true;
programs.nh = {
enable = true;
clean.enable = true;
clean.extraArgs = "--keep-since 4d --keep 3";
flake = "/home/m3tam3re/p/nixos/nixos-config";
};
}

Some files were not shown because too many files have changed in this diff Show More