23 Commits

Author SHA1 Message Date
m3ta-chiron a5d321805b merge into master 2026-06-06 08:02:37 +02:00
m3ta-chiron 0519de4f1d chore: m3-are to new ui 2026-06-06 07:54:30 +02:00
m3ta-chiron 9316aab5ca +nier wallpaper 2026-06-02 19:26:39 +02:00
m3ta-chiron a87234bd7f +dms 2026-06-02 18:20:43 +02:00
m3ta-chiron 651b808f15 +agents-lib in m3ta-home 2026-05-31 14:37:46 +02:00
m3ta-chiron a9ffe3ed28 feat: agent-lib exlude agents 2026-05-31 14:10:15 +02:00
m3ta-chiron 7c5b92c377 Align nixpkgs with Home Manager 26.11 2026-05-31 13:14:24 +02:00
m3ta-chiron 6c4e16de3d feat(m3-kratos): enable agent-lib shared skills 2026-05-30 10:01:47 +02:00
m3ta-chiron f20dd18b5f +babysitter 2026-05-29 18:35:12 +02:00
m3ta-chiron 23b4e825b1 m3ta-home update 2026-05-29 17:38:20 +02:00
m3ta-chiron 2a37ea8fbc fix(kratos): launch Hyprland via wrapper from greetd 2026-05-25 09:51:06 +02:00
m3ta-chiron b1fb63c814 fix(kratos): simplify tuigreet login command
Root cause: The complex concatStringsSep command with power commands
(--power-shutdown, --power-reboot) and multiple --remember flags was
causing tuigreet to display its usage/flags instead of the login UI.
The quoting in the systemd binary paths may have been problematic.

Changes:
- Use lib.getExe instead of manual bin path for tuigreet
- Use simple 'Hyprland' command (found via PATH) instead of
  the full start-hyprland path which may have issues
- Remove unverified options: --remember-session, --remember-user-session,
  --user-menu, --user-menu-min-uid, --power-shutdown, --power-reboot
- Keep only verified options: --time, --remember, --asterisks, --cmd
- Update tmpfiles comment to reflect actual requirement

This provides a minimal, stable login that works reliably.
User can reboot to test.
2026-05-25 09:34:01 +02:00
m3ta-chiron 32677cfb40 fix(kratos): replace gdm with greetd/tuigreet login manager 2026-05-25 09:19:08 +02:00
m3tam3re 9f1e7fd568 Merge pull request 'fix: enable Hermes voice STT dependencies' (#21) from fix/hermes-voice-stt-deps into master
Reviewed-on: #21
2026-05-23 11:30:18 +02:00
m3ta-chiron 95aaddd8c0 fix: enable Hermes voice STT dependencies 2026-05-23 10:32:11 +02:00
m3tam3re 6588586a26 Merge pull request 'Set Hermes default model to GPT 5.5' (#20) from chore/hermes-gpt55-default-fallbacks into master
Reviewed-on: #20
2026-05-23 09:22:18 +02:00
m3ta-chiron 2c8d4da6ff Set Hermes default model to GPT 5.5 2026-05-23 09:19:38 +02:00
m3tam3re 06cc749b69 Merge pull request 'Optimize Hermes Nix service configuration' (#19) from fix/hermes-matrix-mautrix-deps into master
Reviewed-on: #19
2026-05-23 08:58:00 +02:00
m3ta-chiron b49d5c4f72 Optimize Hermes Nix service configuration 2026-05-23 08:55:05 +02:00
m3tam3re d90a20123e Merge pull request 'Fix Hermes Matrix deps for v2026.5.16' (#18) from fix/hermes-matrix-mautrix-deps into master
Reviewed-on: #18
2026-05-23 08:16:35 +02:00
m3ta-chiron 1bd78b5de8 Fix Hermes Matrix deps for v2026.5.16 2026-05-23 08:06:01 +02:00
m3ta-chiron 59ada8585f feat(atlas): deploy self-hosted honcho 2026-05-20 20:52:15 +02:00
m3tam3re 42acdbc98f flake update 2026-05-18 20:17:24 +02:00
32 changed files with 7696 additions and 557 deletions
+3
View File
@@ -0,0 +1,3 @@
node_modules/
runs/
*.log
+5
View File
@@ -0,0 +1,5 @@
{
"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
@@ -0,0 +1,9 @@
{
"name": "nixos-config-a5c",
"version": "1.0.0",
"private": true,
"type": "module",
"dependencies": {
"@a5c-ai/babysitter-sdk": "latest"
}
}
+596
View File
@@ -0,0 +1,596 @@
{
"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
@@ -0,0 +1,238 @@
# 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
@@ -0,0 +1,53 @@
{
"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."
}
}
+7
View File
@@ -46,3 +46,10 @@ CLAUDE.md
.dolt/ .dolt/
*.db *.db
.beads-credential-key .beads-credential-key
# --- babysitter managed ---
.a5c/creds.env
.a5c/creds.env.tmp.*
.a5c/logs/
.a5c/runs/
# --- end babysitter managed ---
File diff suppressed because it is too large Load Diff
Generated
+283 -469
View File
File diff suppressed because it is too large Load Diff
+17 -33
View File
@@ -15,7 +15,7 @@
url = "github:nix-community/home-manager"; url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-25.11"; nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-25.11";
nixpkgs-45570c2.url = "github:nixos/nixpkgs/45570c299dc2b63c8c574c4cd77f0b92f7e2766e"; nixpkgs-45570c2.url = "github:nixos/nixpkgs/45570c299dc2b63c8c574c4cd77f0b92f7e2766e";
nixpkgs-locked.url = "github:nixos/nixpkgs/2744d988fa116fc6d46cdfa3d1c936d0abd7d121"; nixpkgs-locked.url = "github:nixos/nixpkgs/2744d988fa116fc6d46cdfa3d1c936d0abd7d121";
@@ -39,41 +39,32 @@
nixos-generators = {url = "github:nix-community/nixos-generators";}; nixos-generators = {url = "github:nix-community/nixos-generators";};
hyprpanel.url = "github:Jas-SinghFSU/HyprPanel";
rose-pine-hyprcursor.url = "github:ndom91/rose-pine-hyprcursor"; rose-pine-hyprcursor.url = "github:ndom91/rose-pine-hyprcursor";
nix-colors.url = "github:misterio77/nix-colors"; nix-colors.url = "github:misterio77/nix-colors";
m3ta-home = { m3ta-home = {
url = "git+ssh://gitea@code.m3ta.dev/m3tam3re/m3ta-home"; url = "git+ssh://gitea@code.m3ta.dev/m3tam3re/m3ta-home";
# url = "path:/home/m3tam3re/p/NIX/m3ta-home";
<<<<<<< HEAD
||||||| a9ffe3e
# url = "git+ssh://gitea@code.m3ta.dev/m3tam3re/m3ta-home";
url = "path:/home/m3tam3re/p/NIX/m3ta-home";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
agents = { agent-lib = {
# url = "path:/home/m3tam3re/p/AI/AGENTS"; url = "path:/home/m3tam3re/p/NIX/agent-lib";
url = "git+ssh://gitea@code.m3ta.dev/m3tam3re/AGENTS"; =======
inputs.nixpkgs.follows = "nixpkgs";
}; };
## Skills
skills-basecamp = { agent-lib = {
url = "github:basecamp/basecamp-cli"; url = "git+ssh://gitea@code.m3ta.dev/m3tam3re/agent-lib";
flake = false; >>>>>>> feature/agent-lib-m3-kratos
inputs.nixpkgs.follows = "nixpkgs";
}; };
skills-anthropic = {
url = "github:anthropics/skills"; hermes-agent.url = "github:NousResearch/hermes-agent/v2026.5.29.2";
flake = false;
};
skills-kestra = {
url = "github:kestra-io/agent-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.7";
rustfs = { rustfs = {
url = "github:rustfs/rustfs-flake"; url = "github:rustfs/rustfs-flake";
@@ -88,7 +79,6 @@
nixpkgs, nixpkgs,
m3ta-nixpkgs, m3ta-nixpkgs,
nur, nur,
agents,
... ...
} @ inputs: let } @ inputs: let
inherit (self) outputs; inherit (self) outputs;
@@ -191,11 +181,6 @@
inherit system; inherit system;
config.allowUnfree = true; # Allow unfree packages in devShell 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 { in {
default = pkgs.mkShell { default = pkgs.mkShell {
buildInputs = with pkgs; [ buildInputs = with pkgs; [
@@ -206,7 +191,6 @@
statix statix
deadnix deadnix
]; ];
inherit (rules) instructions shellHook;
}; };
}); });
}; };
+2 -1
View File
@@ -21,7 +21,8 @@
useGlobalPkgs = true; useGlobalPkgs = true;
useUserPackages = true; useUserPackages = true;
extraSpecialArgs = { extraSpecialArgs = {
inherit inputs outputs system; inputs = inputs // {agents = null;};
inherit outputs system;
videoDrivers = config.services.xserver.videoDrivers or []; videoDrivers = config.services.xserver.videoDrivers or [];
}; };
}; };
+5
View File
@@ -39,6 +39,11 @@
outline = 3019; outline = 3019;
authentik = 3023; authentik = 3023;
tuwunel = 3024; tuwunel = 3024;
honcho = 3025;
# Agent infrastructure
hermes-api = 8642;
hermes-dashboard = 9119;
# Home automation # Home automation
homarr = 7575; homarr = 7575;
+1
View File
@@ -90,6 +90,7 @@
hyprland.enable = true; hyprland.enable = true;
rofi.enable = true; rofi.enable = true;
wayland.enable = true; wayland.enable = true;
dms.enable = true;
}; };
apps = { apps = {
crypto.enable = true; crypto.enable = true;
+1
View File
@@ -1,6 +1,7 @@
{pkgs, ...}: { {pkgs, ...}: {
imports = [ imports = [
./containers ./containers
./greetd.nix
./hermes-agent.nix ./hermes-agent.nix
./netbird.nix ./netbird.nix
#./n8n.nix #./n8n.nix
+38
View File
@@ -0,0 +1,38 @@
# greetd login manager for m3-kratos (replaces broken GDM on nixos-unstable).
# Uses tuigreet as the greeter, launching Hyprland after authentication.
{
pkgs,
config,
lib,
...
}: let
tuigreet = "${lib.getExe pkgs.tuigreet}";
# Use start-hyprland wrapper to avoid Hyprland startup warnings
# withUWSM=true is set in programs.nix; start-hyprland handles this correctly
hyprlandCmd = "${config.programs.hyprland.package}/bin/start-hyprland";
in {
services.greetd = {
enable = true;
settings = {
default_session = {
user = "greeter";
# Minimal config: verified supported flags only
# The --time and --remember are tested; power commands omitted
# to avoid potential quoting/parsing issues
command = builtins.concatStringsSep " " [
tuigreet
"--time"
"--remember"
"--asterisks"
"--cmd ${hyprlandCmd}"
];
};
};
};
# Required for --remember to persist username between logins
systemd.tmpfiles.rules = [
"d /var/cache/tuigreet 0755 greeter greeter - -"
];
}
+13 -2
View File
@@ -17,10 +17,21 @@ in {
settings = { settings = {
# ── Model ────────────────────────────────────────────────────────── # ── Model ──────────────────────────────────────────────────────────
model = { model = {
default = "glm-5.1"; default = "gpt-5.5";
provider = "zai"; provider = "openai-codex";
}; };
fallback_providers = [
{
provider = "zai";
model = "glm-5.1";
}
{
provider = "minimax";
model = "MiniMax-M2.7";
}
];
credential_pool_strategies = { credential_pool_strategies = {
zai = "fill_first"; zai = "fill_first";
}; };
+8
View File
@@ -3,6 +3,14 @@
secrets = { secrets = {
baserow-env = {file = ../../secrets/baserow-env.age;}; baserow-env = {file = ../../secrets/baserow-env.age;};
ghost-env = {file = ../../secrets/ghost-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 = { kestra-config = {
file = ../../secrets/kestra-config.age; file = ../../secrets/kestra-config.age;
mode = "644"; mode = "644";
@@ -2,6 +2,7 @@
imports = [ imports = [
./baserow.nix ./baserow.nix
./ghost.nix ./ghost.nix
./honcho.nix
./kestra.nix ./kestra.nix
./littlelink.nix ./littlelink.nix
./matomo.nix ./matomo.nix
@@ -0,0 +1,209 @@
{
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
'';
}
+2 -1
View File
@@ -28,6 +28,7 @@
host kestra kestra 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 netbird netbird 10.89.0.0/24 scram-sha-256
host authentik authentik 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 # Deny all other connections
local all all reject local all all reject
@@ -38,7 +39,7 @@
services.postgresqlBackup = { services.postgresqlBackup = {
enable = true; enable = true;
startAt = "03:10:00"; startAt = "03:10:00";
databases = ["baserow" "paperless" "kestra" "authentik" "netbird"]; databases = ["baserow" "paperless" "kestra" "authentik" "netbird" "honcho"];
}; };
networking.firewall = { networking.firewall = {
extraCommands = '' extraCommands = ''
+71 -41
View File
@@ -1,5 +1,6 @@
{ {
config, config,
lib,
pkgs, pkgs,
inputs, inputs,
... ...
@@ -7,40 +8,51 @@
# Edge TTS: Seraphina — friendly, multilingual German female voice (free, no API key) # Edge TTS: Seraphina — friendly, multilingual German female voice (free, no API key)
edgeVoice = "de-DE-SeraphinaMultilingualNeural"; edgeVoice = "de-DE-SeraphinaMultilingualNeural";
# Extra Python packages from the container's writable venv layer. agentLock = builtins.fromJSON (builtins.readFile ../../../agent-sources.lock.json);
# matrix-nio is installed via pip in /home/hermes/.venv but the hermes
# process uses the read-only Nix store Python, so we inject the venv's
# site-packages via PYTHONPATH and provide libstdc++ for libolm (e2e).
# NOTE: v0.13.0 upgraded to Python 3.12 — path updated accordingly.
venvSitePackages = "/home/hermes/.venv/lib/python3.12/site-packages";
gccLibPath = "${pkgs.stdenv.cc.cc.lib}/lib";
# Build skills using agents flake lib for hermes user agentSkillSelections = {
hermesSkills = inputs.agents.lib.mkSkills { m3ta-agents.exclude = [];
inherit pkgs; anthropic.exclude = ["pdf" "skill-creator" "xlsx"];
customSkills = "${inputs.agents}/skills"; basecamp.exclude = [];
externalSkills = [ kestra.exclude = [];
{ mattpocock.exclude = ["grill-me" "caveman"];
src = inputs.skills-basecamp; superpowers.exclude = ["brainstorming" "systematic-debugging"];
skillsDir = "skills"; vercel.exclude = [];
}
{
src = inputs.skills-anthropic;
skillsDir = "skills";
}
{
src = inputs.skills-kestra;
skillsDir = "skills";
}
];
}; };
sourceRoot = source:
builtins.fetchGit {
inherit (source) url rev;
};
selectedSkillNames = sourceName: let
source = agentLock.sources.${sourceName};
excluded = agentSkillSelections.${sourceName}.exclude;
in
lib.subtractLists excluded (builtins.attrNames source.items.skills);
copySkill = sourceName: skillName: let
source = agentLock.sources.${sourceName};
item = source.items.skills.${skillName};
in ''
cp -R ${sourceRoot source}/${source.root}/${item.path} $out/${skillName}
'';
copySourceSkills = sourceName:
lib.concatMapStringsSep "\n" (copySkill sourceName) (selectedSkillNames sourceName);
# Build skills from the agent-lib lockfile instead of the legacy AGENTS flake.
hermesSkills = pkgs.runCommand "hermes-agent-lib-skills" {} ''
mkdir -p $out
${lib.concatMapStringsSep "\n" copySourceSkills (builtins.attrNames agentSkillSelections)}
'';
in { in {
virtualisation.docker.enable = true; virtualisation.docker.enable = true;
systemd.tmpfiles.rules = [ systemd.tmpfiles.rules = [
"d /home/hermes/.config 0755 hermes hermes -" "d /var/lib/hermes/.config 0755 hermes hermes -"
"d /home/hermes/.config/tea 0755 hermes hermes -" "d /var/lib/hermes/.config/tea 0755 hermes hermes -"
"L+ /home/hermes/.config/tea/yml - - - - ${pkgs.writeText "tea-yml" '' "L+ /var/lib/hermes/.config/tea/yml - - - - ${pkgs.writeText "tea-yml" ''
logins: logins:
- name: m3ta - name: m3ta
url: https://code.m3ta.dev url: https://code.m3ta.dev
@@ -64,19 +76,30 @@ in {
''; '';
}; };
# Ensure 'uv' is in the hermes-agent service PATH so CronJobs and terminal
# sessions can use 'uv run' for PEP 723 scripts (e.g. garmin-daily.py).
systemd.services.hermes-agent.path = [pkgs.uv];
services.hermes-agent = { services.hermes-agent = {
enable = true; enable = true;
addToSystemPackages = true; addToSystemPackages = true;
# v0.14 lazy-installs heavy optional backends by default. In the sealed
# Nix package, include the backends this host config actively uses so the
# gateway, Matrix bridge, memory, web search, TTS, and local STT work
# without runtime pip/uv mutation.
extraDependencyGroups = [
"matrix"
"honcho"
"exa"
"edge-tts"
"voice"
];
extraPackages = with pkgs; [ extraPackages = with pkgs; [
docker docker
git git
curl
jq
tea tea
nix nix
python3Minimal
uv
zellij zellij
]; ];
@@ -105,7 +128,7 @@ in {
# Bind to 0.0.0.0 so the Netbird interface can reach it. # Bind to 0.0.0.0 so the Netbird interface can reach it.
API_SERVER_ENABLED = "true"; API_SERVER_ENABLED = "true";
API_SERVER_HOST = "0.0.0.0"; API_SERVER_HOST = "0.0.0.0";
API_SERVER_PORT = "8642"; API_SERVER_PORT = toString (config.m3ta.ports.get "hermes-api");
}; };
# ── Container mode (podman) ────────────────────────────────────────── # ── Container mode (podman) ──────────────────────────────────────────
@@ -113,21 +136,27 @@ in {
enable = false; enable = false;
backend = "podman"; backend = "podman";
extraVolumes = ["/home/m3tam3re/p:/projects:rw"]; extraVolumes = ["/home/m3tam3re/p:/projects:rw"];
extraOptions = [ extraOptions = [];
"--env"
"PYTHONPATH=${venvSitePackages}"
"--env"
"LD_LIBRARY_PATH=${gccLibPath}"
];
}; };
settings = { settings = {
# ── Model ────────────────────────────────────────────────────────── # ── Model ──────────────────────────────────────────────────────────
model = { model = {
default = "glm-5.1"; default = "gpt-5.5";
provider = "zai"; provider = "openai-codex";
}; };
fallback_providers = [
{
provider = "zai";
model = "glm-5.1";
}
{
provider = "minimax";
model = "MiniMax-M2.7";
}
];
credential_pool_strategies = { credential_pool_strategies = {
zai = "fill_first"; zai = "fill_first";
}; };
@@ -139,6 +168,7 @@ in {
max_turns = 90; max_turns = 90;
gateway_timeout = 1800; gateway_timeout = 1800;
tool_use_enforcement = "auto"; tool_use_enforcement = "auto";
reasoning_effort = "high";
}; };
# ── Skills ───────────────────────────────────────────────────────── # ── Skills ─────────────────────────────────────────────────────────
+11 -7
View File
@@ -7,6 +7,8 @@
# Netbird mesh VPN range — dashboard only accessible from mesh peers. # Netbird mesh VPN range — dashboard only accessible from mesh peers.
# m3-atlas Traefik proxies to this port over Netbird. # m3-atlas Traefik proxies to this port over Netbird.
netbirdRange = "100.64.0.0/16"; netbirdRange = "100.64.0.0/16";
apiPort = config.m3ta.ports.get "hermes-api";
dashboardPort = config.m3ta.ports.get "hermes-dashboard";
# Reference the hermes-agent package from the running service config # Reference the hermes-agent package from the running service config
hermesPkg = config.services.hermes-agent.package or (inputs.hermes-agent.packages.${pkgs.stdenv.hostPlatform.system}.default or pkgs.hermes-agent); hermesPkg = config.services.hermes-agent.package or (inputs.hermes-agent.packages.${pkgs.stdenv.hostPlatform.system}.default or pkgs.hermes-agent);
@@ -14,10 +16,10 @@ in {
# ── Hermes Dashboard systemd service ─────────────────────────────────── # ── Hermes Dashboard systemd service ───────────────────────────────────
# Web UI for managing Hermes Agent — sessions, config, kanban, cron, etc. # Web UI for managing Hermes Agent — sessions, config, kanban, cron, etc.
# #
# Flow: Browser → dash.m3ta.dev (TLS via m3-atlas Traefik) → Netbird → :9119 # Flow: Browser → dash.m3ta.dev (TLS via m3-atlas Traefik) → Netbird → :${toString dashboardPort}
# #
# --insecure is required to bind 0.0.0.0 (hermes refuses non-localhost otherwise). # --insecure is required to bind 0.0.0.0 (hermes refuses non-localhost otherwise).
# Safe because firewall restricts port 9119 to Netbird mesh only. # Safe because firewall restricts the dashboard/API ports to Netbird mesh only.
systemd.services.hermes-dashboard = { systemd.services.hermes-dashboard = {
description = "Hermes Agent Web Dashboard"; description = "Hermes Agent Web Dashboard";
after = ["network.target" "hermes-agent.service"]; after = ["network.target" "hermes-agent.service"];
@@ -29,7 +31,7 @@ in {
User = "hermes"; User = "hermes";
Group = "hermes"; Group = "hermes";
ExecStart = "${hermesPkg}/bin/hermes dashboard --host 0.0.0.0 --port 9119 --no-open --insecure"; ExecStart = "${hermesPkg}/bin/hermes dashboard --host 0.0.0.0 --port ${toString dashboardPort} --no-open --insecure";
# Environment matching the hermes-agent service # Environment matching the hermes-agent service
Environment = [ Environment = [
@@ -51,15 +53,17 @@ in {
}; };
}; };
# ── Firewall: Dashboard only from Netbird mesh ───────────────────────── # ── Firewall: Hermes network endpoints only from Netbird mesh ──────────
networking.firewall = { networking.firewall = {
extraCommands = '' extraCommands = ''
# Allow Hermes Dashboard (9119/tcp) only from Netbird mesh VPN # Allow Hermes Dashboard and OpenAI-compatible API only from Netbird mesh VPN
ip46tables -A nixos-fw -p tcp --dport 9119 -s ${netbirdRange} -j nixos-fw-accept ip46tables -A nixos-fw -p tcp --dport ${toString dashboardPort} -s ${netbirdRange} -j nixos-fw-accept
ip46tables -A nixos-fw -p tcp --dport ${toString apiPort} -s ${netbirdRange} -j nixos-fw-accept
''; '';
extraStopCommands = '' extraStopCommands = ''
ip46tables -D nixos-fw -p tcp --dport 9119 -s ${netbirdRange} -j nixos-fw-accept 2>/dev/null || true ip46tables -D nixos-fw -p tcp --dport ${toString dashboardPort} -s ${netbirdRange} -j nixos-fw-accept 2>/dev/null || true
ip46tables -D nixos-fw -p tcp --dport ${toString apiPort} -s ${netbirdRange} -j nixos-fw-accept 2>/dev/null || true
''; '';
}; };
} }
+2 -1
View File
@@ -11,10 +11,11 @@
boot.supportedFilesystems = ["zfs"]; boot.supportedFilesystems = ["zfs"];
boot.zfs.package = pkgs.zfs_unstable; boot.zfs.package = pkgs.zfs_unstable;
boot.zfs.forceImportAll = false; boot.zfs.forceImportAll = false;
boot.zfs.forceImportRoot = false;
boot.loader.systemd-boot.enable = true; boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true; boot.loader.efi.canTouchEfiVariables = true;
boot.initrd.kernelModules = ["amdgpu"]; boot.initrd.kernelModules = ["amdgpu"];
boot.kernelPackages = pkgs.linuxPackages_6_18; boot.kernelPackages = pkgs.linuxPackages_7_0;
services.xserver.videoDrivers = ["amdgpu"]; services.xserver.videoDrivers = ["amdgpu"];
security.polkit.enable = true; security.polkit.enable = true;
security.pam.services.gdm.enableGnomeKeyring = true; security.pam.services.gdm.enableGnomeKeyring = true;
+1
View File
@@ -48,6 +48,7 @@
podman.enable = true; podman.enable = true;
virtualisation.enable = true; virtualisation.enable = true;
}; };
services.power-profiles-daemon.enable = true;
services.ollama = { services.ollama = {
environmentVariables = { environmentVariables = {
# HCC_AMDGPU_TARGET = "gfx1103"; # HCC_AMDGPU_TARGET = "gfx1103";
+4 -1
View File
@@ -4,10 +4,14 @@
# m3ta-home via the profile mapping in hosts/common/users/m3tam3re.nix. # m3ta-home via the profile mapping in hosts/common/users/m3tam3re.nix.
{ {
config, config,
inputs,
lib, lib,
... ...
}: }:
with lib; { with lib; {
imports = [
];
config = mkMerge [ config = mkMerge [
# ── XDG / MIME defaults ── # ── XDG / MIME defaults ──
{ {
@@ -56,7 +60,6 @@ with lib; {
]; ];
windowrule = [ windowrule = [
"match:class dev.zed.Zed, workspace 1" "match:class dev.zed.Zed, workspace 1"
"match:class Msty, workspace 1"
"match:class ^(com.obsproject.Studio)$, workspace 2" "match:class ^(com.obsproject.Studio)$, workspace 2"
"match:class ^(brave-browser)$, workspace 4, opacity 1.0" "match:class ^(brave-browser)$, workspace 4, opacity 1.0"
"match:class ^(vivaldi-stable)$, workspace 4, opacity 1.0" "match:class ^(vivaldi-stable)$, workspace 4, opacity 1.0"
+2 -1
View File
@@ -1,6 +1,7 @@
{pkgs, ...}: { {pkgs, ...}: {
imports = [ imports = [
./containers ./containers
./greetd.nix
./mem0.nix ./mem0.nix
# ./n8n.nix # ./n8n.nix
./netbird.nix ./netbird.nix
@@ -29,6 +30,6 @@
userServices = true; userServices = true;
}; };
}; };
displayManager.gdm.enable = true; # displayManager.gdm.enable = true;
}; };
} }
+38
View File
@@ -0,0 +1,38 @@
# greetd login manager for m3-kratos (replaces broken GDM on nixos-unstable).
# Uses tuigreet as the greeter, launching Hyprland after authentication.
{
pkgs,
config,
lib,
...
}: let
tuigreet = "${lib.getExe pkgs.tuigreet}";
# Use start-hyprland wrapper to avoid Hyprland startup warnings
# withUWSM=true is set in programs.nix; start-hyprland handles this correctly
hyprlandCmd = "${config.programs.hyprland.package}/bin/start-hyprland";
in {
services.greetd = {
enable = true;
settings = {
default_session = {
user = "greeter";
# Minimal config: verified supported flags only
# The --time and --remember are tested; power commands omitted
# to avoid potential quoting/parsing issues
command = builtins.concatStringsSep " " [
tuigreet
"--time"
"--remember"
"--asterisks"
"--cmd ${hyprlandCmd}"
];
};
};
};
# Required for --remember to persist username between logins
systemd.tmpfiles.rules = [
"d /var/cache/tuigreet 0755 greeter greeter - -"
];
}
+3
View File
@@ -38,6 +38,9 @@ in {
"secrets/basecamp-client-id.age".publicKeys = systems ++ users; "secrets/basecamp-client-id.age".publicKeys = systems ++ users;
"secrets/basecamp-client-secret.age".publicKeys = systems ++ users; "secrets/basecamp-client-secret.age".publicKeys = systems ++ users;
"secrets/gitea-runner-token.age".publicKeys = systems ++ users; "secrets/gitea-runner-token.age".publicKeys = systems ++ users;
"secrets/honcho-selfhost-db-password.age".publicKeys = systems ++ users;
"secrets/honcho-selfhost-env.age".publicKeys = systems ++ users;
"secrets/honcho-selfhost-jwt-secret.age".publicKeys = systems ++ users;
"secrets/outline-key.age".publicKeys = systems ++ users; "secrets/outline-key.age".publicKeys = systems ++ users;
"secrets/restreamer-env.age".publicKeys = systems ++ users; "secrets/restreamer-env.age".publicKeys = systems ++ users;
"secrets/searx.age".publicKeys = systems ++ users; "secrets/searx.age".publicKeys = systems ++ users;
+31
View File
@@ -0,0 +1,31 @@
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IDVrd2NzQSBJV1Fa
U2gzWjJKOHlsK202dXAzVENFdmZ5ZmJsc01STnRnTWMvdjFyZ21NCjU5Q0hwbVlV
dVlRTUZDb0JESHBaTzk5ancrTWNpLzYrMFk2QWU0Z0EvUmsKLT4gc3NoLWVkMjU1
MTkgM0JjcjF3IEdia0tSQTZWcEE3ODE4VjU2M0ZGay9rbXlzbFNqZWxpb1lGSExw
RW5keGsKWDlwRzcwT1BaTDByT0R6T3hqWTE1UWVyN2xhSzhSMlhBdW5FakNjZ1Ux
NAotPiBzc2gtZWQyNTUxOSA5ZDRZSVEgcnNJRnA2SVVkMHRXZTErc0VFbmduMDBz
ZkQzK3dMQ2xadkMyYllhOE1rOAprWmg4T3RiaTF5QXdmRGUxVDVpVnZWdWxRYTJv
WGVUQUhsT0VjKzl0NnJrCi0+IHNzaC1lZDI1NTE5IDROTEtydyAvc1ZTc0hRd3R4
V2U4dEpaeEZEZlVyc2ZHSlNiVSt3T1M3bndsVXpPNkhVCmt2WlplcVcza2YxV05T
bnRIOWpMYWpxck5jSzRtQVZ2L2ZQS3J1VjVTWDgKLT4gc3NoLWVkMjU1MTkgYzRO
UWxBIHZCKzR5RXN2RmYvc3ZPTGJRRG1peUN6bmNuVFpSd2NPdWJwTTJYdHllRW8K
TEo4QUI1a3ZzQ3NSQldSN1lTMlVwVGhTcTRPaHpYVHZVdHowYmZqR1czVQotPiBz
c2gtcnNhIERRbEU3dwpvRzJjS0h3b2p4RXJrSDI1VEszQ1BvckNUS2laV3hGVVlx
TXd0VkcvQ1hvWElNWnVNa1JoeHhMTDFUUWZnV0YxCjNHajRtZ0lmQzVXZmhyM1Nq
SWoyVTFFdmowNTdZV0J0WHE5cXdZb2U1OVJOb1hYb1lnSjdqN09Bd2IvOUFlckMK
d3hBc3pUK1J2Y3VnTjNSR0Q0cVJUVlluNllBazJ2L1dmOXVvZXI0WjVYbjI1RXhr
Rm1EMzkxcStrYWRJTFNJKwo3YjZ6MEZ3RmtLZytiWGdBWWZEYU9EQWxEZWtzV3dD
dGhJUUd0ajcvUFlxVGJqTVhlWmhSeHpkMHQyWWs5ZS9DClNEV0gzcWM2YlJTQ1lM
bE4zTFJKSFU1VjAybFJvY1FQR2tNSFo2NFVDczBTUW9UWjY4aDVNUzlYaVlkdzJm
dUsKckVaVld4YXpsdGYwWHVrWEtTbDJBU2cwcXlJSGY4ZEhlT2o4QlRBVGxWRHNL
OXlMTGp5b1ZWbnJYV2pzaFFIcApQVmJzVi9kWnRpeWcyaS9weVN3SncxQjhlanBV
dW5FU0VtL2lpS0NSTWtoOVI4akxXOUlhWW5xMkp2SUszSU9QCk1rZVdoNkI5TGRB
L2twWWpPYVlSWUxrRElRcjhHMFczM29lcWlWWlJhbk0vcGFEQmw3UGdXWXJBNXJV
VURYcFQKCi0+IHNzaC1lZDI1NTE5IENTTXloZyBpOEE3YUFzcytOYndXWWNreThp
ZEdveGFlbHlPa0FwZ2xBY0lCcmIycTM4CnI0ZE1DM2d1bzZPV3diL2lZQi9SUnB1
UWFjVVFueTFpMzRINm9Ob0pZMTQKLS0tIFJwZy9uRklOUEl0Z2hDNmx1YWsyNVov
aHZ5VVhtMnVyYTMwbCtkaFFtR28KZzkT96InPG4YYyVKq0ZOrIBPtCJBbTXUJu+8
9G03diIRwzYb6cSBRMtKKGl5NEfbJE7B2OnXeHPeCIPiGArKudKxFg9COHGOUP0h
hUDDL9RGVhd4sMs8zRkxNghRwQzD
-----END AGE ENCRYPTED FILE-----
+30
View File
@@ -0,0 +1,30 @@
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IDVrd2NzQSBKZllV
QytCeGYyVmtRMUxudm5iWmF3aWdITlRQVE53RnhFNUFabXkwbkg0CkE5Wk1mbXdm
TzRuQTdvNklORUdSdHFIZm1zSVdvMWVnWWpRTUxDSzFBMHcKLT4gc3NoLWVkMjU1
MTkgM0JjcjF3IDlISlRMdC9Sc2hic3JRV1o0WDNsbzByNmdFNnZDdjJSLytEa0xS
VzRzQ2sKYXJGSjJDa2xuYThLNnhIMFhwTTNUSHJWbnFFYzZSRFQxVlVWK2xjNWgv
dwotPiBzc2gtZWQyNTUxOSA5ZDRZSVEgaGUweXhJZmhTOGt3VFQ2R04rQjNOckxx
c3BCMTBWZ0lsQmU3NmlVRkRYWQp6QlMvQkZmemVjekdLVWlDTUlNRG04MTlzaHAz
cW9xd2JjNlE0eFF4NzNvCi0+IHNzaC1lZDI1NTE5IDROTEtydyBWQ2FGUCtFQ2FZ
Wk5uSzZyTDNBTHRPUTkvTlRWR0Q1bHdqRjBycmU0VFc0CkdpSUNZZGw1aGJwUVk0
VnlIR2IxVTJNaFVSNHJQSDR2YWxuN2ZiSERQSUEKLT4gc3NoLWVkMjU1MTkgYzRO
UWxBIHlDYUlJRGxabTZxSnNpTUNWUDRXWUtHa0h3Z3BYTlZkUEtkall1OUh1VzQK
ZEQzSW5tM0xFdWd1a3hibXlxa0N2N2RlemUyMkplRW5CNFZHUCtTSEhWdwotPiBz
c2gtcnNhIERRbEU3dwpoNE9FdlpHYXJFZVRYQnBZNFZPTUhLb3RDdWpNcWxtU2gv
MVF5Tm1tdHBuK3NLQjBnM2JudFFwQVZnb0VpUUljCjhKQk5HQnVrY05yeU53QWhK
MG9QUVN5M2NXUEw2eEhQajFmaHZ4cWpFaXcwd3ZrSzNRWFNRREl5bERac1Y2LzYK
c3BDVXlvQ20xaUt4KzZVRkhiNU5TYkpsbGQraFdvM3RvSkFZRU54SUV4ZWNnVG0y
VVR6Q2swV2RFeUZwNGZxdQoveVhYN3JXVXBpQzdxa1ZKVXROcXRDQXladml5c2ZD
ZjFVSVRaUkZiRVlNUHA3bDg2ek9mcXJnVG9YYStza3BFCktzVXlyZHNCZ1BxYTBO
TUt1T3ZYQmR2VjErdVpPWVBOVDlFZm14Ukp0dkdUamNxODZPNFNTMXNabzNWUzVT
MHIKUkJocFBhNitCMzFkWUhyV29FU3RMWjkvMWNxbzJFbTBHb2NpbW9Cb1dheHhn
Y0N6S2FIQ2NROWtqQm5ORWxtYwo1NnF2RVQybnY2Wm5CQlJZOXVTVVNLUGZIbWZh
V2laZWFQaXhEaGdma3pIWnlSaFpjSlRqNHlRZGNiaWhsWXlYCi9UM0Z2MldUMW01
ekZja1hLNXptaFVCVFN5UVVlRGh0L2wvekxEckNmNTJOTUdoUE9wRzFaNzhqQnpM
dThmWDUKCi0+IHNzaC1lZDI1NTE5IENTTXloZyB5ZzV4Q1pIOGpBOEtUcG1rNVZB
QjFPbEt0OThxNWl3V1VhRTV2RFVrUGhRCmpwSHpUTnhNdlRHMnRvYWk2emJlSlhJ
aWwweUg5dG1rYmRMMEVDTVdHdnMKLS0tIHp6alVpN1IvQ2E5UEV0Zm1nQk53cWJQ
WCtTN08wSXlCSktkaDlPRG9Wa0UKyLX9C4xDpcPIVFsimn4OmCWAKZ1IPxeSzgr0
W6Shg1EWCeMm3dQVJ8O9mji4JW/SJHKwqlJvFTMPhIwcdIo=
-----END AGE ENCRYPTED FILE-----
+31
View File
@@ -0,0 +1,31 @@
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IDVrd2NzQSBTNk5O
dmZTRnRnOU5JMHU4QitlWWMyaXhscm1aQWNQSWJmVjU3MHdvVmowClkrVTV6VVVV
Q0tiWXlkcGtHS3AwTUtqYmJwdnowMXFLcGNYb1dVZmpVTGcKLT4gc3NoLWVkMjU1
MTkgM0JjcjF3IGVpdFlFTUFZQS9IMzVaRkNHSHltcHV1QlFmYk1yRitvZjhZZzI2
ZDlTR3MKQ0RKT0tWZ0JGOUZCMTk2bitENmxnZzc1VDloNktvaVJFdGxyaVFaMjhJ
VQotPiBzc2gtZWQyNTUxOSA5ZDRZSVEgdmw1MTg1R3lLR1NFNGUzQXpnUS9TNjRq
czVtYlFzUmJnbmJ1c3JFRVZCQQoyYzBmQzdPbFVyU3diWlNuc1JoaHptOTFCUFBX
RFpDZk4rWHByOGp2bkJFCi0+IHNzaC1lZDI1NTE5IDROTEtydyBIZWdsejNPVkdZ
dkN3Z1FLTkNCVTdKSHNIOGU4UUUwdklhS0oxMlc5ekVjCnNZL0ZsV1VMU1p0eEFp
YzBOdndIRzB3KzZXNGRFaHBpVDQ4Wm1jb2E1Z1kKLT4gc3NoLWVkMjU1MTkgYzRO
UWxBIGFteVpubkxhcm80VEllY1llYkx4YXRTRHU4clNwK1F1SWlMTWxtMTYvRncK
YjhvRXBod2I5dUZaWGlyOHcwa3MvWjNPOCtKendiMk9zVE5mVlpTS1RVMAotPiBz
c2gtcnNhIERRbEU3dwpoenRXZkF2ck1LWDhxK25ldG1HVmRzVEh4TVNuaTdwQmVW
eW80TE5kYzd5YkFpZXZhdWVSdEh4VTA2TzhnMzNsCkZud1AvTUdWSHJtOWtEZzlj
ai9SdG1PRUtCN3VWQXlyamVpV1dWTEZkaFZpZHIxQ0c0eHIva1dzeDN6MlJla24K
dXcrNUxUWVdMTFpaRk1YbkszazNDdFhuSVdxbE9rVHNNWDBvbDF4WGlWT0d5RTJR
WmxCSFAzbDVVNWJneWhJZApPVnozRkRsS2J2VkFRVEpDVWJicmhhWXA0eVEvZFEz
eWtsY3ZaNEk1MzlDYVJDb09lZGRsVk9YMXhyOWJsNmJYCk5HRTRjb0RrdlRydjNs
T3prdXMvbnF0Y0FlL0VUbHNuVzZPNWJSK09TdEpuVU83dytiUDJRbmpFazludkkz
d3AKUUp6TkVWSWRHMkozR0lQR1JlNmZ5Nk05WkUwbWJaODUzNmJIVkNEazVRcFFO
ZnVZengyeFhQSlFsbUlta0tPRwo5OURlRTlPNERLWlF6aE9QaS91T0kyb2tIS0kz
L0FYNjhWVWp1Q2xqUVRialcyWkhXbTJwU0R5VmVkbE1GeGEyCmROTFErS2VsMEo1
VHdta2RObmtwMWtJTzRuaEhRbTFFbEE0V1RKbUk3SCtLWlE1cHR5c09ncThxbVY1
cnRETkUKCi0+IHNzaC1lZDI1NTE5IENTTXloZyBZbW1NSStwWGd5RE1kRkk5aTZX
alZtUWk5M3pnU1ZTSFU5UExnS0d4NkcwCjAvblBmUG5MUVVTOEpncjJjY0I1QzN1
eVVNMlVZenJ6MzVDRXFaMVgxREUKLS0tIFIwd1ZtanJuU0Q2Ym9kN3lSS1NtQlky
NC93UWJXa0tXTUVON3NmNVpUR0kKX71fenkAzKU3aIHFjLTpemNxsc5unQTy9f1O
jpfhFHRPG5HuUBtmi6Fuv2n8J8Gw70D0XKs6UgAYV5GY0Db1daJZRbgF9EExbadB
JQm3DLy8LG6KAM250ooGHKJoJSfQ
-----END AGE ENCRYPTED FILE-----