From b49d5c4f72141f435b2c9260d9a626c9203259f3 Mon Sep 17 00:00:00 2001 From: m3ta-chiron Date: Sat, 23 May 2026 08:55:05 +0200 Subject: [PATCH] Optimize Hermes Nix service configuration --- hosts/common/ports.nix | 4 ++ hosts/m3-hermes/services/hermes-agent.nix | 63 ++++++------------- hosts/m3-hermes/services/hermes-dashboard.nix | 18 +++--- 3 files changed, 33 insertions(+), 52 deletions(-) diff --git a/hosts/common/ports.nix b/hosts/common/ports.nix index 090673b..9d9c03b 100644 --- a/hosts/common/ports.nix +++ b/hosts/common/ports.nix @@ -41,6 +41,10 @@ tuwunel = 3024; honcho = 3025; + # Agent infrastructure + hermes-api = 8642; + hermes-dashboard = 9119; + # Home automation homarr = 7575; diff --git a/hosts/m3-hermes/services/hermes-agent.nix b/hosts/m3-hermes/services/hermes-agent.nix index b1df9f6..48aea11 100644 --- a/hosts/m3-hermes/services/hermes-agent.nix +++ b/hosts/m3-hermes/services/hermes-agent.nix @@ -7,31 +7,6 @@ # Edge TTS: Seraphina — friendly, multilingual German female voice (free, no API key) edgeVoice = "de-DE-SeraphinaMultilingualNeural"; - # Hermes v0.14 moved Matrix from matrix-nio to lazy-installed mautrix. - # Lazy pip installs cannot work in the read-only Nix Python environment, so - # provide the Matrix runtime deps declaratively and put their site-packages on - # the gateway process PYTHONPATH at interpreter startup. - matrixPython = pkgs.python312.withPackages (ps: let - # Hermes lazy_deps pins this exact version. nixpkgs currently ships an - # older aiosqlite, and lazy_deps treats version mismatches as missing. - aiosqlite_0_22_1 = ps.aiosqlite.overridePythonAttrs (_old: rec { - version = "0.22.1"; - src = pkgs.fetchFromGitHub { - owner = "omnilib"; - repo = "aiosqlite"; - tag = "v${version}"; - hash = "sha256-voOOFo1OwaRQ3JsDHlBrngP+8ajf0kTNKXJyOaJiTs4="; - }; - }); - in [ - (ps.mautrix.override {withOlm = true;}) - ps.markdown - aiosqlite_0_22_1 - ps.asyncpg - ps.aiohttp-socks - ]); - matrixPythonPath = "${matrixPython}/lib/python3.12/site-packages"; - # Build skills using agents flake lib for hermes user hermesSkills = inputs.agents.lib.mkSkills { inherit pkgs; @@ -54,17 +29,10 @@ in { virtualisation.docker.enable = true; - # Matrix E2EE uses libolm via python-olm. libolm is archived upstream and - # marked insecure in nixpkgs, but Hermes Matrix encrypted rooms currently - # still require it through mautrix[encryption]. - nixpkgs.config.permittedInsecurePackages = [ - "olm-3.2.16" - ]; - systemd.tmpfiles.rules = [ - "d /home/hermes/.config 0755 hermes hermes -" - "d /home/hermes/.config/tea 0755 hermes hermes -" - "L+ /home/hermes/.config/tea/yml - - - - ${pkgs.writeText "tea-yml" '' + "d /var/lib/hermes/.config 0755 hermes hermes -" + "d /var/lib/hermes/.config/tea 0755 hermes hermes -" + "L+ /var/lib/hermes/.config/tea/yml - - - - ${pkgs.writeText "tea-yml" '' logins: - name: m3ta url: https://code.m3ta.dev @@ -88,24 +56,29 @@ 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]; - environment = { - PYTHONPATH = matrixPythonPath; - }; - }; - services.hermes-agent = { enable = 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, and TTS work + # without runtime pip/uv mutation. + extraDependencyGroups = [ + "matrix" + "honcho" + "exa" + "edge-tts" + ]; extraPackages = with pkgs; [ docker git + curl + jq tea nix + python3Minimal + uv zellij ]; @@ -134,7 +107,7 @@ in { # Bind to 0.0.0.0 so the Netbird interface can reach it. API_SERVER_ENABLED = "true"; API_SERVER_HOST = "0.0.0.0"; - API_SERVER_PORT = "8642"; + API_SERVER_PORT = toString (config.m3ta.ports.get "hermes-api"); }; # ── Container mode (podman) ────────────────────────────────────────── diff --git a/hosts/m3-hermes/services/hermes-dashboard.nix b/hosts/m3-hermes/services/hermes-dashboard.nix index 931e03a..4304e87 100644 --- a/hosts/m3-hermes/services/hermes-dashboard.nix +++ b/hosts/m3-hermes/services/hermes-dashboard.nix @@ -7,6 +7,8 @@ # Netbird mesh VPN range — dashboard only accessible from mesh peers. # m3-atlas Traefik proxies to this port over Netbird. 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 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 ─────────────────────────────────── # 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). - # 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 = { description = "Hermes Agent Web Dashboard"; after = ["network.target" "hermes-agent.service"]; @@ -29,7 +31,7 @@ in { User = "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 = [ @@ -51,15 +53,17 @@ in { }; }; - # ── Firewall: Dashboard only from Netbird mesh ───────────────────────── + # ── Firewall: Hermes network endpoints only from Netbird mesh ────────── networking.firewall = { extraCommands = '' - # Allow Hermes Dashboard (9119/tcp) only from Netbird mesh VPN - ip46tables -A nixos-fw -p tcp --dport 9119 -s ${netbirdRange} -j nixos-fw-accept + # Allow Hermes Dashboard and OpenAI-compatible API only from Netbird mesh VPN + 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 = '' - 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 ''; }; }