feat(discord-hermes-bridge): pont Discord vers un gateway Hermes dédié
Gateway hermes-agent dédié (profil discord-bridge) sur 127.0.0.1:8643, API Server OpenAI-compatible consommée par le cog hermes.py du discord-bot. Unité systemd écrite à la main (le module NixOS ne gère pas d'instances) et même paquet que le bot Matrix, donc mêmes groupes de deps (edge-tts, stt-whisper). Clé d'API dans secrets/discord-hermes-bridge.yml, port jamais ouvert au firewall (assertion). Côté discord-bot, HERMES_BRIDGE_URL et le nom de rôle viennent d'un EnvironmentFile, seule la clé est secrète.
This commit is contained in:
@@ -36,6 +36,10 @@ creation_rules:
|
||||
key_groups:
|
||||
- age:
|
||||
- *tower
|
||||
- path_regex: secrets/discord-hermes-bridge\.yml$
|
||||
key_groups:
|
||||
- age:
|
||||
- *tower
|
||||
- path_regex: secrets/hermes-dashboard\.yml$
|
||||
key_groups:
|
||||
- age:
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
hermes_discord_bridge_env: ENC[AES256_GCM,data:SJ2zitdGqLLt9seXzmxu3o8uVmJFG6k5pGaMACpZ2aWzqbgP6D8LwTPKlJZiSZ8lwNUnurJrQ3J9RBSJaIOkoKrRtwX0AMs6crxRJe+E6CU=,iv:czq1KzUHEQs2fdDObhA0WmGgQwNwjczVcctQimttFxQ=,tag:LLcMUdPc4gQWhnZdWYD7XQ==,type:str]
|
||||
discord_bot_hermes_bridge_env: ENC[AES256_GCM,data:VHIQgLh0azzLBEB9vemDrSPjqqSvirlp4d1fL+1vXwAmAYWN4UPMpYlUAjWrar23JY+QZ7FkFjbGV18GoPta6UYSIK/2ICVmsPHhHo1G3hEw+BUYYF+X,iv:8lis93YMqPz8mJR7J/ifm/SyYi1k/5s5XZVjglqR8G4=,tag:8i4Ju5C78CD3hfL+KmJXYg==,type:str]
|
||||
sops:
|
||||
age:
|
||||
- enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqendZNnBBdW9FQ0lYOXJT
|
||||
WmN1b1ZoL2htbG1XRndlM2hlU1BjZTNZemprCktteUkvREtZYlFCTCtIdVh5WkFR
|
||||
L1MxblNxKy9pVnRCYU9ScjZZdGhkelEKLS0tIDBmdk0xeGVzY3MwbmZncnFya2Fv
|
||||
Nm4wRFY2UFQ0eFNuYXlGUWFjdytaZDQKjhK7ZpoqiWjdMFEXZ3Fzsas1EdKbTKNq
|
||||
/2rL0KJAmQu/7pn9qKAXdrO7W7qf6XEwiVSmoZ0Z4BATcI6xiX+UPQ==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
recipient: age1usm3v0ugducrzcwud60dda7xfnj49fdhecj7kcsfm7dzwzrzeyqq2jc2hm
|
||||
lastmodified: "2026-09-27T06:54:21Z"
|
||||
mac: ENC[AES256_GCM,data:+tNIeBz2vsvMPNGFIYm/VNaBm/jzDc2XtvhiRZVxYC+3IGM5On+2F8qKEmFEDEejdLo9SkKU2+XI0OBuD3fcBo5Gb9hevQMxS48W7EIzjsQ8KxHsvuRPor8krw8Q0vNyvpxtLOf9SEhcFWoYiFJt5HQ9q6lhvV93ZgQdXiZk4uI=,iv:66NsoDMKqsJHBjD1OO7B5o6B7tbmQIKnHYCyfiz9bKg=,tag:D9Db4M6lLeiWGENN1nMXRA==,type:str]
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.13.3
|
||||
@@ -36,6 +36,7 @@
|
||||
./hermes-webui
|
||||
./hermes-dashboard
|
||||
./discord-bot
|
||||
./discord-hermes-bridge
|
||||
./eternal-terminal
|
||||
./nextcloud-mcp
|
||||
./amazon-mcp
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
inputs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
imports = [inputs.discord-bot.nixosModules.default];
|
||||
@@ -17,5 +18,20 @@
|
||||
port = 8050;
|
||||
};
|
||||
|
||||
# Pont vers le gateway Hermes dédié (services/discord-hermes-bridge).
|
||||
# HERMES_BRIDGE_URL n'est pas secret (loopback local), seule la clé l'est.
|
||||
systemd.services.discord-bot.serviceConfig.EnvironmentFile = lib.mkAfter [
|
||||
config.sops.secrets."discord_bot_hermes_bridge_env".path
|
||||
];
|
||||
systemd.services.discord-bot.environment = {
|
||||
HERMES_BRIDGE_URL = "http://127.0.0.1:8643/v1/chat/completions";
|
||||
HERMES_BRIDGE_ROLE_NAME = "hermes";
|
||||
};
|
||||
|
||||
sops.secrets."discord_bot_env" = {};
|
||||
sops.secrets."discord_bot_hermes_bridge_env" = {
|
||||
sopsFile = ../../secrets/discord-hermes-bridge.yml;
|
||||
owner = "discord-bot";
|
||||
group = "discord-bot";
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
# services/discord-hermes-bridge/default.nix
|
||||
#
|
||||
# Gateway Hermes dedie, profil "discord-bridge" (cree a la main sur tower via
|
||||
# `hermes profile create discord-bridge`, meme mecanique que le profil pocket :
|
||||
# pas de concept d'"instances" dans le module NixOS services.hermes-agent,
|
||||
# donc unite systemd ecrite a la main ici plutot que via cette option).
|
||||
#
|
||||
# Reutilise le MEME paquet hermes-agent (config.services.hermes-agent.package)
|
||||
# que le bot Matrix @hermes dans services/hermes : meme build, donc les memes
|
||||
# groupes de deps optionnelles (edge-tts, stt-whisper...) sont deja presents,
|
||||
# utiles pour la phase 2 (vocal) du pont Discord sans travail supplementaire.
|
||||
#
|
||||
# Expose seulement l'API Server OpenAI-compatible (/v1/chat/completions) en
|
||||
# loopback, consommee par le cog hermes.py du bot (services/discord-bot).
|
||||
# Jamais de port ouvert au firewall : c'est le meme host, meme boucle locale.
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
package = config.services.hermes-agent.package;
|
||||
port = 8643;
|
||||
in {
|
||||
sops.secrets."hermes_discord_bridge_env" = {
|
||||
sopsFile = ../../secrets/discord-hermes-bridge.yml;
|
||||
owner = "hermes";
|
||||
group = "hermes";
|
||||
};
|
||||
|
||||
systemd.services.hermes-discord-bridge = {
|
||||
description = "Hermes Agent gateway dedie (profil discord-bridge, pont vers discord-bot)";
|
||||
after = ["network-online.target"];
|
||||
wants = ["network-online.target"];
|
||||
wantedBy = ["multi-user.target"];
|
||||
|
||||
environment = {
|
||||
HOME = "/var/lib/hermes";
|
||||
HERMES_HOME = "/var/lib/hermes/.hermes";
|
||||
HERMES_MANAGED = "true";
|
||||
# API_SERVER_ENABLED/PORT/KEY sont les seules variables documentees
|
||||
# (pas de API_SERVER_HOST : le bind loopback 127.0.0.1 est le defaut,
|
||||
# non configurable). API_SERVER_KEY vient du fichier sops (EnvironmentFile).
|
||||
API_SERVER_ENABLED = "true";
|
||||
API_SERVER_PORT = toString port;
|
||||
};
|
||||
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
User = "hermes";
|
||||
Group = "hermes";
|
||||
ExecStart = "${package}/bin/hermes -p discord-bridge gateway";
|
||||
EnvironmentFile = [config.sops.secrets."hermes_discord_bridge_env".path];
|
||||
Restart = "always";
|
||||
RestartSec = 5;
|
||||
NoNewPrivileges = true;
|
||||
PrivateTmp = true;
|
||||
ProtectHome = false;
|
||||
ProtectSystem = "strict";
|
||||
ReadWritePaths = ["/var/lib/hermes"];
|
||||
UMask = "0007";
|
||||
WorkingDirectory = "/var/lib/hermes/workspace";
|
||||
};
|
||||
};
|
||||
|
||||
assertions = [
|
||||
{
|
||||
assertion = !(lib.elem port config.networking.firewall.allowedTCPPorts);
|
||||
message = "discord-hermes-bridge : le port ${toString port} (API server local) ne doit pas etre ouvert au firewall.";
|
||||
}
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user