Nix 与 NixOS 配置
Hermes Agent 提供了一个 Nix flake,包含三个层级的集成:
| 层级 | 适用对象 | 你将获得 |
|---|---|---|
nix run / nix profile install | 所有 Nix 用户(macOS、Linux) | 包含所有依赖项的预构建二进制文件 —— 然后使用标准 CLI 工作流 |
| NixOS 模块(原生) | NixOS 服务器部署 | 声明式配置、强化的 systemd 服务、受管理的密钥 |
| NixOS 模块(容器) | 需要自我修改的代理 | 上述全部功能,外加一个持久化的 Ubuntu 容器,使代理可以 apt/pip/npm install |
curl | bash 安装程序自行管理 Python、Node 和依赖。而 Nix flake 取代了这一切 —— 每个 Python 依赖都是由 uv2nix 构建的 Nix 衍生品,运行时工具(Node.js、git、ripgrep、ffmpeg)也被封装进二进制文件的 PATH 中。无需运行时 pip,无需 venv 激活,也无需 npm install。
对于非 NixOS 用户,这仅改变安装步骤。之后的所有操作(hermes setup、hermes gateway install、配置编辑)与标准安装完全相同。
对于 NixOS 模块用户,整个生命周期完全不同:配置位于 configuration.nix,密钥通过 sops-nix/agenix 管理,服务为 systemd 单元,CLI 配置命令被禁用。你管理 Hermes 的方式,就像管理任何其他 NixOS 服务一样。
先决条件
- 启用 flakes 的 Nix —— 推荐使用 Determinate Nix(默认启用 flakes)
- 使用的服务所需的 API 密钥(至少需要 OpenRouter 或 Anthropic 的密钥)
快速入门(所有 Nix 用户)
无需克隆仓库。Nix 会自动获取、构建并运行所有内容:
# Run directly (builds on first use, cached after)
nix run github:NousResearch/hermes-agent -- setup
nix run github:NousResearch/hermes-agent -- chat
# Or install persistently
nix profile install github:NousResearch/hermes-agent
hermes setup
hermes chat
在 nix profile install 后,hermes、hermes-agent 和 hermes-acp 将出现在你的 PATH 中。从此时起,工作流程与 标准安装 完全一致 —— hermes setup 引导你完成提供者选择,hermes gateway install 设置 launchd(macOS)或 systemd 用户服务,配置文件位于 ~/.hermes/。
从本地克隆构建
git clone https://github.com/NousResearch/hermes-agent.git
cd hermes-agent
nix build
./result/bin/hermes setup
NixOS 模块
该 flake 导出 nixosModules.default —— 一个完整的 NixOS 服务模块,可声明式地管理用户创建、目录、配置生成、密钥、文档和服务生命周期。
此模块需要 NixOS。对于非 NixOS 系统(macOS、其他 Linux 发行版),请使用 nix profile install 和上述标准 CLI 工作流。
添加 Flakes 输入
# /etc/nixos/flake.nix (or your system flake)
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
hermes-agent.url = "github:NousResearch/hermes-agent";
};
outputs = { nixpkgs, hermes-agent, ... }: {
nixosConfigurations.your-host = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
hermes-agent.nixosModules.default
./configuration.nix
];
};
};
}
最小化配置
# configuration.nix
{ config, ... }: {
services.hermes-agent = {
enable = true;
settings.model.default = "anthropic/claude-sonnet-4";
environmentFiles = [ config.sops.secrets."hermes-env".path ];
addToSystemPackages = true;
};
}
仅此而已。nixos-rebuild switch 将创建 hermes 用户,生成 config.yaml,连接密钥,并启动网关 —— 一个长期运行的服务,用于连接代理至消息平台(Telegram、Discord 等)并监听传入消息。
上文的 environmentFiles 行假设你已配置 sops-nix 或 agenix。该文件应至少包含一个 LLM 提供商的密钥(例如 OPENROUTER_API_KEY=sk-or-...)。详见 密钥管理 获取完整设置说明。若尚未配置密钥管理器,可先使用普通文件作为起点——但务必确保其不可被世界读取:
echo "OPENROUTER_API_KEY=sk-or-your-key" | sudo install -m 0600 -o hermes /dev/stdin /var/lib/hermes/env
services.hermes-agent.environmentFiles = [ "/var/lib/hermes/env" ];
设置 addToSystemPackages = true 有两点作用:将 hermes CLI 加入系统 PATH 且 在系统范围内设置 HERMES_HOME,使交互式 CLI 与网关服务共享状态(会话、技能、cron)。若不设置,你在 shell 中运行 hermes 将创建一个独立的 ~/.hermes/ 目录。
验证是否正常工作
在 nixos-rebuild switch 后,检查服务是否正在运行:
# Check service status
systemctl status hermes-agent
# Watch logs (Ctrl+C to stop)
journalctl -u hermes-agent -f
# If addToSystemPackages is true, test the CLI
hermes version
hermes config # shows the generated config
选择部署模式
该模块支持两种模式,由 container.enable 控制:
| 原生(默认) | 容器 | |
|---|---|---|
| 运行方式 | 主机上的强化 systemd 服务 | 持久化的 Ubuntu 容器,挂载 /nix/store |
| 安全性 | NoNewPrivileges、ProtectSystem=strict、PrivateTmp | 容器隔离,以非特权用户身份运行 |
| 代理能否自安装包 | 否 —— 仅限 Nix 提供的 PATH 工具 | 是 —— apt、pip、npm 的安装在重启后仍保留 |
| 配置界面 | 相同 | 相同 |
| 何时选择 | 标准部署、最高安全性、可复现性 | 代理需要运行时安装包、可变环境、实验性工具 |
要启用容器模式,只需添加一行:
{
services.hermes-agent = {
enable = true;
container.enable = true;
# ... rest of config is identical
};
}
容器模式会通过 mkDefault 自动启用 virtualisation.docker.enable。若使用 Podman,请设置 container.backend = "podman" 和 virtualisation.docker.enable = false。
配置
声明式设置
settings 选项接受任意 attrset,将其渲染为 config.yaml。它支持跨多个模块定义进行深度合并(通过 lib.recursiveUpdate),因此你可以将配置拆分到多个文件中:
# base.nix
services.hermes-agent.settings = {
model.default = "anthropic/claude-sonnet-4";
toolsets = [ "all" ];
terminal = { backend = "local"; timeout = 180; };
};
# personality.nix
services.hermes-agent.settings = {
display = { compact = false; personality = "kawaii"; };
memory = { memory_enabled = true; user_profile_enabled = true; };
};
两者在评估时进行深度合并。Nix 声明的键始终优先于磁盘上现有 config.yaml 中的键,但 Nix 未触及的用户添加键将被保留。这意味着如果代理或手动编辑添加了如 skills.disabled 或 streaming.enabled 的键,它们将在 nixos-rebuild switch 后依然存在。
settings.model.default 使用提供方期望的模型标识符。使用 OpenRouter(默认)时,这些名称类似 "anthropic/claude-sonnet-4" 或 "google/gemini-3-flash"。若直接使用提供方(Anthropic、OpenAI),请将 settings.model.base_url 设置为指向其 API 并使用其原生模型 ID(例如 "claude-sonnet-4-20250514")。当未设置 base_url 时,Hermes 默认使用 OpenRouter。
运行 nix build .#configKeys && cat result 以查看从 Python 的 DEFAULT_CONFIG 提取的所有叶级配置键。你可以将现有的 config.yaml 粘贴到 settings attrset 中——结构完全一一对应。
完整示例:所有常见自定义设置
{ config, ... }: {
services.hermes-agent = {
enable = true;
container.enable = true;
# ── Model ──────────────────────────────────────────────────────────
settings = {
model = {
base_url = "https://openrouter.ai/api/v1";
default = "anthropic/claude-opus-4.6";
};
toolsets = [ "all" ];
max_turns = 100;
terminal = { backend = "local"; cwd = "."; timeout = 180; };
compression = {
enabled = true;
threshold = 0.85;
summary_model = "google/gemini-3-flash-preview";
};
memory = { memory_enabled = true; user_profile_enabled = true; };
display = { compact = false; personality = "kawaii"; };
agent = { max_turns = 60; verbose = false; };
};
# ── Secrets ────────────────────────────────────────────────────────
environmentFiles = [ config.sops.secrets."hermes-env".path ];
# ── Documents ──────────────────────────────────────────────────────
documents = {
"SOUL.md" = builtins.readFile /home/user/.hermes/SOUL.md;
"USER.md" = ./documents/USER.md;
};
# ── MCP Servers ────────────────────────────────────────────────────
mcpServers.filesystem = {
command = "npx";
args = [ "-y" "@modelcontextprotocol/server-filesystem" "/data/workspace" ];
};
# ── Container options ──────────────────────────────────────────────
container = {
image = "ubuntu:24.04";
backend = "docker";
extraVolumes = [ "/home/user/projects:/projects:rw" ];
extraOptions = [ "--gpus" "all" ];
};
# ── Service tuning ─────────────────────────────────────────────────
addToSystemPackages = true;
extraArgs = [ "--verbose" ];
restart = "always";
restartSec = 5;
};
}
逃生通道:自定义配置
如果你更希望完全在 Nix 外部管理 config.yaml,请使用 configFile:
services.hermes-agent.configFile = /etc/hermes/config.yaml;
这将完全绕过 settings —— 不进行合并,也不生成。每次激活时,该文件都会原样复制到 $HERMES_HOME/config.yaml。
自定义速查表
快速参考 Nix 用户最常需要自定义的内容:
| 我想…… | 选项 | 示例 |
|---|---|---|
| 更改 LLM 模型 | settings.model.default | "anthropic/claude-sonnet-4" |
| 使用不同的提供方端点 | settings.model.base_url | "https://openrouter.ai/api/v1" |
| 添加 API 密钥 | environmentFiles | [ config.sops.secrets."hermes-env".path ] |
| 给代理赋予个性 | documents."SOUL.md" | builtins.readFile ./my-soul.md |
| 添加 MCP 工具服务器 | mcpServers.<name> | 参见 MCP 服务器 |
| 挂载主机目录到容器 | container.extraVolumes | [ "/data:/data:rw" ] |
| 向容器传递 GPU 访问权限 | container.extraOptions | [ "--gpus" "all" ] |
| 使用 Podman 而非 Docker | container.backend | "podman" |
| 向服务 PATH 添加工具(仅原生) | extraPackages | [ pkgs.pandoc pkgs.imagemagick ] |
| 使用自定义基础镜像 | container.image | "ubuntu:24.04" |
| 覆盖 hermes 包 | package | inputs.hermes-agent.packages.${system}.default.override { ... } |
| 更改状态目录 | stateDir | "/opt/hermes" |
| 设置代理的工作目录 | workingDirectory | "/home/user/projects" |
密钥管理
settings 或 environmentNix 表达式中的值最终会出现在 /nix/store 中,该文件对世界可读。请始终使用 environmentFiles 配合密钥管理器。
:::在激活时(nixos-rebuild switch),environment(非敏感变量)和 environmentFiles(密钥文件)会被合并到 $HERMES_HOME/.env 中。Hermes 在每次启动时都会读取该文件,因此更改会立即生效——无需重新创建容器。
sops-nix
{
sops = {
defaultSopsFile = ./secrets/hermes.yaml;
age.keyFile = "/home/user/.config/sops/age/keys.txt";
secrets."hermes-env" = { format = "yaml"; };
};
services.hermes-agent.environmentFiles = [
config.sops.secrets."hermes-env".path
];
}
密钥文件包含键值对:
# secrets/hermes.yaml (encrypted with sops)
hermes-env: |
OPENROUTER_API_KEY=sk-or-...
TELEGRAM_BOT_TOKEN=123456:ABC...
ANTHROPIC_API_KEY=sk-ant-...
agenix
{
age.secrets.hermes-env.file = ./secrets/hermes-env.age;
services.hermes-agent.environmentFiles = [
config.age.secrets.hermes-env.path
];
}
OAuth / 认证种子注入
对于需要 OAuth 的平台(如 Discord),请使用 authFile 在首次部署时注入凭据:
{
services.hermes-agent = {
authFile = config.sops.secrets."hermes/auth.json".path;
# authFileForceOverwrite = true; # overwrite on every activation
};
}
该文件仅在 auth.json 不存在时被复制(除非指定 authFileForceOverwrite = true)。运行时的 OAuth token 刷新将写入状态目录,并在重建之间持久保留。
文档
documents 选项会将文件安装到代理的工作目录中(即 workingDirectory,代理将其作为工作区读取)。Hermes 会根据约定查找特定文件名:
SOUL.md—— 代理的系统提示/个性设定。Hermes 在启动时读取此文件,并将其作为持久化指令,持续影响其在所有对话中的行为。USER.md—— 关于代理所交互用户的上下文信息。- 其他放置在此处的文件也会被代理视为工作区文件。
{
services.hermes-agent.documents = {
"SOUL.md" = ''
You are a helpful research assistant specializing in NixOS packaging.
Always cite sources and prefer reproducible solutions.
'';
"USER.md" = ./documents/USER.md; # path reference, copied from Nix store
};
}
值可以是内联字符串或路径引用。这些文件会在每次 nixos-rebuild switch 时重新安装。
MCP 服务器
mcpServers 选项以声明方式配置 MCP(模型上下文协议) 服务器。每个服务器使用 stdio(本地命令)或 HTTP(远程 URL)传输方式。
Stdio 传输(本地服务器)
{
services.hermes-agent.mcpServers = {
filesystem = {
command = "npx";
args = [ "-y" "@modelcontextprotocol/server-filesystem" "/data/workspace" ];
};
github = {
command = "npx";
args = [ "-y" "@modelcontextprotocol/server-github" ];
env.GITHUB_PERSONAL_ACCESS_TOKEN = "\${GITHUB_TOKEN}"; # resolved from .env
};
};
}
env 中的环境变量将在运行时从 $HERMES_HOME/.env 解析。使用 environmentFiles 注入密钥——永远不要将令牌直接写入 Nix 配置。
HTTP 传输(远程服务器)
{
services.hermes-agent.mcpServers.remote-api = {
url = "https://mcp.example.com/v1/mcp";
headers.Authorization = "Bearer \${MCP_REMOTE_API_KEY}";
timeout = 180;
};
}
带 OAuth 的 HTTP 传输
对于使用 OAuth 2.1 的服务器,请设置 auth = "oauth"。Hermes 实现了完整的 PKCE 流程:元数据发现、动态客户端注册、令牌交换以及自动刷新。
{
services.hermes-agent.mcpServers.my-oauth-server = {
url = "https://mcp.example.com/mcp";
auth = "oauth";
};
}
令牌存储在 $HERMES_HOME/mcp-tokens/<server-name>.json 中,并在重启和重建之间持久保留。
无头服务器上的初始 OAuth 授权
首次 OAuth 授权需要浏览器式同意流程。在无头部署中,Hermes 会将授权 URL 输出到 stdout/logs,而不是打开浏览器。
方案 A:交互式引导 —— 通过 docker exec(容器)或 sudo -u hermes(原生)运行一次流程:
# Container mode
docker exec -it hermes-agent \
hermes mcp add my-oauth-server --url https://mcp.example.com/mcp --auth oauth
# Native mode
sudo -u hermes HERMES_HOME=/var/lib/hermes/.hermes \
hermes mcp add my-oauth-server --url https://mcp.example.com/mcp --auth oauth
容器使用 --network=host,因此 127.0.0.1 上的 OAuth 回调监听器可从主机浏览器访问。
方案 B:预先注入令牌 —— 在工作站上完成流程后,复制令牌:
hermes mcp add my-oauth-server --url https://mcp.example.com/mcp --auth oauth
scp ~/.hermes/mcp-tokens/my-oauth-server{,.client}.json \
server:/var/lib/hermes/.hermes/mcp-tokens/
# Ensure: chown hermes:hermes, chmod 0600
采样(服务器发起的 LLM 请求)
某些 MCP 服务器可以向代理请求 LLM 完成内容:
{
services.hermes-agent.mcpServers.analysis = {
command = "npx";
args = [ "-y" "analysis-server" ];
sampling = {
enabled = true;
model = "google/gemini-3-flash";
max_tokens_cap = 4096;
timeout = 30;
max_rpm = 10;
};
};
}
管理模式
当 Hermes 通过 NixOS 模块运行时,以下 CLI 命令将被阻止,并返回描述性错误,指引你前往 configuration.nix:
| 被阻止的命令 | 原因 |
|---|---|
hermes setup | 配置是声明式的——请在 Nix 配置中编辑 settings |
hermes config edit | 配置由 settings 生成 |
hermes config set <key> <value> | 配置由 settings 生成 |
hermes gateway install | systemd 服务由 NixOS 管理 |
hermes gateway uninstall | systemd 服务由 NixOS 管理 |
这防止了 Nix 声明与磁盘上实际配置之间的漂移。检测机制依赖两个信号:
HERMES_MANAGED=true环境变量 —— 由 systemd 服务设置,对网关进程可见.managed标记文件位于HERMES_HOME—— 由激活脚本设置,对交互式 shell 可见(例如docker exec -it hermes-agent hermes config set ...也被阻止)
要更改配置,请编辑你的 Nix 配置并运行 sudo nixos-rebuild switch。
容器架构
仅当你使用 container.enable = true 时才相关。原生模式部署可跳过此部分。
启用容器模式后,Hermes 将在持久化的 Ubuntu 容器中运行,Nix 构建的二进制文件以只读方式绑定挂载自宿主机:
Host Container
──── ─────────
/nix/store/...-hermes-agent-0.1.0 ──► /nix/store/... (ro)
/var/lib/hermes/ ──► /data/ (rw)
├── current-package -> /nix/store/... (symlink, updated each rebuild)
├── .gc-root -> /nix/store/... (prevents nix-collect-garbage)
├── .container-identity (sha256 hash, triggers recreation)
├── .hermes/ (HERMES_HOME)
│ ├── .env (merged from environment + environmentFiles)
│ ├── config.yaml (Nix-generated, deep-merged by activation)
│ ├── .managed (marker file)
│ ├── state.db, sessions/, memories/ (runtime state)
│ └── mcp-tokens/ (OAuth tokens for MCP servers)
├── home/ ──► /home/hermes (rw)
└── workspace/ (MESSAGING_CWD)
├── SOUL.md (from documents option)
└── (agent-created files)
Container writable layer (apt/pip/npm): /usr, /usr/local, /tmp
Nix 构建的二进制文件能在 Ubuntu 容器中运行,是因为 /nix/store 被绑定挂载——它自带解释器和所有依赖项,不依赖容器的系统库。容器入口点通过一个 current-package 符号链接解析:/data/current-package/bin/hermes gateway run --replace。在 nixos-rebuild switch 上,仅更新符号链接——容器保持运行。
什么在什么事件下持久存在
| 事件 | 容器是否重建? | /data(状态) | /home/hermes | 可写层(apt/pip/npm) |
|---|---|---|---|---|
systemctl restart hermes-agent | 否 | 持久存在 | 持久存在 | 持久存在 |
nixos-rebuild switch(代码变更) | 否(仅符号链接更新) | 持久存在 | 持久存在 | 持久存在 |
| 宿主机重启 | 否 | 持久存在 | 持久存在 | 持久存在 |
nix-collect-garbage | 否(GC 根) | 持久存在 | 持久存在 | 持久存在 |
镜像变更(container.image) | 是 | 持久存在 | 持久存在 | 丢失 |
| 卷/选项变更 | 是 | 持久存在 | 持久存在 | 丢失 |
environment/environmentFiles 变更 | 否 | 持久存在 | 持久存在 | 持久存在 |
容器仅在其身份哈希发生变化时才会重建。该哈希涵盖:模式版本、镜像、extraVolumes、extraOptions 和入口脚本。环境变量、设置、文档或 Hermes 包本身的变更不会触发重建。
当身份哈希改变(镜像升级、新卷、新容器选项)时,容器会被销毁并从 container.image 的全新拉取中重建。可写层中的任何 apt install、pip install 或 npm install 包都将丢失。但 /data 和 /home/hermes 中的状态会被保留(因为它们是绑定挂载)。
如果代理依赖特定包,建议将其打包进自定义镜像(container.image = "my-registry/hermes-base:latest"),或在代理的 SOUL.md 中编写脚本进行安装。
GC 根保护
preStart 脚本会在 ${stateDir}/.gc-root 创建一个 GC 根,指向当前的 Hermes 包。这可防止 nix-collect-garbage 删除正在运行的二进制文件。若 GC 根意外失效,重启服务即可重建。
开发
开发 Shell
flake 提供了一个开发环境,包含 Python 3.11、uv、Node.js 以及所有运行时工具:
cd hermes-agent
nix develop
# Shell provides:
# - Python 3.11 + uv (deps installed into .venv on first entry)
# - Node.js 20, ripgrep, git, openssh, ffmpeg on PATH
# - Stamp-file optimization: re-entry is near-instant if deps haven't changed
hermes setup
hermes chat
direnv(推荐)
包含的 .envrc 会自动激活开发环境:
cd hermes-agent
direnv allow # one-time
# Subsequent entries are near-instant (stamp file skips dep install)
Flake 检查
flake 包含构建时验证,可在 CI 和本地运行:
# Run all checks
nix flake check
# Individual checks
nix build .#checks.x86_64-linux.package-contents # binaries exist + version
nix build .#checks.x86_64-linux.entry-points-sync # pyproject.toml ↔ Nix package sync
nix build .#checks.x86_64-linux.cli-commands # gateway/config subcommands
nix build .#checks.x86_64-linux.managed-guard # HERMES_MANAGED blocks mutation
nix build .#checks.x86_64-linux.bundled-skills # skills present in package
nix build .#checks.x86_64-linux.config-roundtrip # merge script preserves user keys
每项检查验证的内容
| 检查项 | 验证内容 |
|---|---|
package-contents | hermes 和 hermes-agent 二进制文件存在,且 hermes version 可运行 |
entry-points-sync | pyproject.toml 中每个 [project.scripts] 条目在 Nix 包中都有对应的封装二进制文件 |
cli-commands | hermes --help 暴露 gateway 和 config 子命令 |
managed-guard | HERMES_MANAGED=true hermes config set ... 打印出 NixOS 错误 |
bundled-skills | 技能目录存在,包含 SKILL.md 文件,且包装器中设置了 HERMES_BUNDLED_SKILLS |
config-roundtrip | 7 种合并场景:全新安装、Nix 覆盖、用户密钥保留、混合合并、MCP 附加合并、嵌套深度合并、幂等性 |
选项参考
核心| 选项 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| enable | bool | false | 启用 hermes-agent 服务 |
| package | package | hermes-agent | 要使用的 hermes-agent 包 |
| user | str | "hermes" | 系统用户 |
| group | str | "hermes" | 系统组 |
| createUser | bool | true | 自动创建用户/组 |
| stateDir | str | "/var/lib/hermes" | 状态目录(HERMES_HOME 的父目录) |
| workingDirectory | str | "${stateDir}/workspace" | 代理工作目录(MESSAGING_CWD) |
| addToSystemPackages | bool | false | 将 hermes CLI 添加到系统 PATH,并设置 HERMES_HOME 系统级 |
配置
| 选项 | 类型 | 默认值 | 描述 |
|---|---|---|---|
settings | attrs(深度合并) | {} | 以 config.yaml 形式渲染的声明式配置。支持任意嵌套;多个定义通过 lib.recursiveUpdate 合并 |
configFile | null 或 path | null | 指向现有 config.yaml 的路径。若设置,则完全覆盖 settings |
密钥与环境变量
| 选项 | 类型 | 默认值 | 描述 |
|---|---|---|---|
environmentFiles | listOf str | [] | 包含密钥的 env 文件路径。在激活时合并至 $HERMES_HOME/.env |
environment | attrsOf str | {} | 非敏感环境变量。在 Nix 存储中可见——请勿在此处放置密钥 |
authFile | null 或 path | null | OAuth 凭证种子。仅在首次部署时复制 |
authFileForceOverwrite | bool | false | 在激活时始终从 authFile 覆盖 auth.json |
文档
| 选项 | 类型 | 默认值 | 描述 |
|---|---|---|---|
documents | attrsOf (either str path) | {} | 工作区文件。键为文件名,值为内联字符串或路径。在激活时安装至 workingDirectory |
MCP 服务器
| 选项 | 类型 | 默认值 | 描述 |
|---|---|---|---|
mcpServers | attrsOf submodule | {} | MCP 服务器定义,合并至 settings.mcp_servers |
mcpServers.<name>.command | null 或 str | null | 服务器命令(标准输入输出传输) |
mcpServers.<name>.args | listOf str | [] | 命令参数 |
mcpServers.<name>.env | attrsOf str | {} | 服务器进程的环境变量 |
mcpServers.<name>.url | null 或 str | null | 服务器端点 URL(HTTP/可流式 HTTP 传输) |
mcpServers.<name>.headers | attrsOf str | {} | HTTP 头信息,例如 Authorization |
mcpServers.<name>.auth | null 或 "oauth" | null | 认证方式。"oauth" 启用 OAuth 2.1 PKCE |
mcpServers.<name>.enabled | bool | true | 启用或禁用此服务器 |
mcpServers.<name>.timeout | null 或 int | null | 工具调用超时时间(秒,默认:120) |
mcpServers.<name>.connect_timeout | null 或 int | null | 连接超时时间(秒,默认:60) |
mcpServers.<name>.tools | null 或 submodule | null | 工具过滤(include/exclude 列表) |
mcpServers.<name>.sampling | null 或 submodule | null | 服务器发起的 LLM 请求采样配置 |
服务行为
| 选项 | 类型 | 默认值 | 描述 |
|---|---|---|---|
extraArgs | listOf str | [] | 传递给 hermes gateway 的额外参数 |
extraPackages | listOf package | [] | 服务 PATH 上的额外包(仅原生模式) |
restart | str | "always" | systemd Restart= 策略 |
restartSec | int | 5 | systemd RestartSec= 值 |
容器
| 选项 | 类型 | 默认值 | 描述 |
|---|---|---|---|
container.enable | bool | false | 启用 OCI 容器模式 |
container.backend | enum ["docker" "podman"] | "docker" | 容器运行时 |
container.image | str | "ubuntu:24.04" | 基础镜像(运行时拉取) |
container.extraVolumes | listOf str | [] | 额外卷挂载(host:container:mode) |
container.extraOptions | listOf str | [] | 传递给 docker create 的额外参数 |
目录结构
原生模式
/var/lib/hermes/ # stateDir (owned by hermes:hermes, 0750)
├── .hermes/ # HERMES_HOME
│ ├── config.yaml # Nix-generated (deep-merged each rebuild)
│ ├── .managed # Marker: CLI config mutation blocked
│ ├── .env # Merged from environment + environmentFiles
│ ├── auth.json # OAuth credentials (seeded, then self-managed)
│ ├── gateway.pid
│ ├── state.db
│ ├── mcp-tokens/ # OAuth tokens for MCP servers
│ ├── sessions/
│ ├── memories/
│ ├── skills/
│ ├── cron/
│ └── logs/
├── home/ # Agent HOME
└── workspace/ # MESSAGING_CWD
├── SOUL.md # From documents option
└── (agent-created files)
容器模式
布局相同,挂载至容器中:
| 容器路径 | 主机路径 | 模式 | 说明 |
|---|---|---|---|
/nix/store | /nix/store | ro | Hermes 二进制文件 + 所有 Nix 依赖 |
/data | /var/lib/hermes | rw | 所有状态、配置、工作区数据 |
/home/hermes | ${stateDir}/home | rw | 持久化代理主目录 — pip install --user、工具缓存 |
/usr, /usr/local, /tmp | (可写层) | rw | apt/pip/npm 安装 — 跨重启持久化,重建时丢失 |
更新
# Update the flake input
nix flake update hermes-agent --flake /etc/nixos
# Rebuild
sudo nixos-rebuild switch
在容器模式下,current-package 符号链接会被更新,代理在重启后会自动加载新二进制文件。无需重新创建容器,也不会丢失已安装的包。
故障排查
以下所有 docker 命令在使用 podman 时行为相同。若设置了 container.backend = "podman",请相应替换。
服务日志
# Both modes use the same systemd unit
journalctl -u hermes-agent -f
# Container mode: also available directly
docker logs -f hermes-agent
容器检查
systemctl status hermes-agent
docker ps -a --filter name=hermes-agent
docker inspect hermes-agent --format='{{.State.Status}}'
docker exec -it hermes-agent bash
docker exec hermes-agent readlink /data/current-package
docker exec hermes-agent cat /data/.container-identity
强制重新创建容器
如需重置可写层(全新 Ubuntu 环境):
sudo systemctl stop hermes-agent
docker rm -f hermes-agent
sudo rm /var/lib/hermes/.container-identity
sudo systemctl start hermes-agent
验证密钥是否正确加载
若代理启动但无法认证 LLM 提供商,请检查 .env 文件是否正确合并:
# Native mode
sudo -u hermes cat /var/lib/hermes/.hermes/.env
# Container mode
docker exec hermes-agent cat /data/.hermes/.env
GC 根验证
nix-store --query --roots $(docker exec hermes-agent readlink /data/current-package)
常见问题
| 现象 | 原因 | 解决方法 |
|---|---|---|
Cannot save configuration: managed by NixOS | CLI 保护机制启用 | 编辑 configuration.nix 和 nixos-rebuild switch |
| 容器意外被重新创建 | extraVolumes、extraOptions 或 image 发生变化 | 正常行为 — 可写层已重置。重新安装包或使用自定义镜像 |
hermes version 显示旧版本 | 容器未重启 | systemctl restart hermes-agent |
在 /var/lib/hermes 上权限被拒绝 | 状态目录为 0750 hermes:hermes | 使用 docker exec 或 sudo -u hermes |
nix-collect-garbage 移除了 hermes | GC 根缺失 | 重启服务(preStart 会重建 GC 根) |