2026-05-11 11:19:21 +02:00
|
|
|
{
|
|
|
|
|
config,
|
|
|
|
|
pkgs,
|
|
|
|
|
inputs,
|
|
|
|
|
...
|
|
|
|
|
}: let
|
|
|
|
|
# Netbird mesh VPN range — dashboard only accessible from mesh peers
|
|
|
|
|
netbirdRange = "100.64.0.0/16";
|
|
|
|
|
|
|
|
|
|
# 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);
|
|
|
|
|
in {
|
|
|
|
|
# ── Hermes Dashboard systemd service ───────────────────────────────────
|
|
|
|
|
# Web UI for managing Hermes Agent — sessions, config, kanban, cron, etc.
|
|
|
|
|
# Binds to 0.0.0.0:9119 but firewall restricts to Netbird mesh only.
|
|
|
|
|
systemd.services.hermes-dashboard = {
|
|
|
|
|
description = "Hermes Agent Web Dashboard";
|
|
|
|
|
after = ["network.target" "hermes-agent.service"];
|
|
|
|
|
wants = ["hermes-agent.service"];
|
|
|
|
|
wantedBy = ["multi-user.target"];
|
|
|
|
|
|
|
|
|
|
serviceConfig = {
|
|
|
|
|
Type = "simple";
|
|
|
|
|
User = "hermes";
|
|
|
|
|
Group = "hermes";
|
|
|
|
|
|
2026-05-11 11:39:37 +02:00
|
|
|
# --insecure: required to bind 0.0.0.0 (default refuses non-localhost).
|
|
|
|
|
# Safe because firewall restricts port 9119 to Netbird mesh only.
|
|
|
|
|
ExecStart = "${hermesPkg}/bin/hermes dashboard --host 0.0.0.0 --port 9119 --no-open --insecure";
|
2026-05-11 11:19:21 +02:00
|
|
|
|
|
|
|
|
# Environment matching the hermes-agent service
|
|
|
|
|
Environment = [
|
|
|
|
|
"HERMES_HOME=/var/lib/hermes/.hermes"
|
|
|
|
|
"HERMES_MANAGED=true"
|
|
|
|
|
"HOME=/var/lib/hermes"
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
# Security hardening (matching hermes-agent service pattern)
|
|
|
|
|
NoNewPrivileges = true;
|
|
|
|
|
ProtectSystem = "strict";
|
|
|
|
|
ProtectHome = "read-only";
|
|
|
|
|
ReadWritePaths = ["/var/lib/hermes" "/tmp"];
|
|
|
|
|
PrivateTmp = true;
|
|
|
|
|
|
|
|
|
|
# Restart policy
|
|
|
|
|
Restart = "on-failure";
|
|
|
|
|
RestartSec = 5;
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
# ── Firewall: Dashboard only from Netbird mesh ─────────────────────────
|
|
|
|
|
networking.firewall = {
|
|
|
|
|
# Use extraCommands for source-IP-restricted port (NixOS firewall
|
|
|
|
|
# allowedTCPPorts is all-or-nothing per port).
|
|
|
|
|
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
|
|
|
|
|
'';
|
|
|
|
|
|
|
|
|
|
extraStopCommands = ''
|
|
|
|
|
ip46tables -D nixos-fw -p tcp --dport 9119 -s ${netbirdRange} -j nixos-fw-accept 2>/dev/null || true
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
}
|