Skip to main content

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 setuphermes 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 后,hermeshermes-agenthermes-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 服务模块,可声明式地管理用户创建、目录、配置生成、密钥、文档和服务生命周期。

note

此模块需要 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-nixagenix。该文件应至少包含一个 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

设置 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
安全性NoNewPrivilegesProtectSystem=strictPrivateTmp容器隔离,以非特权用户身份运行
代理能否自安装包否 —— 仅限 Nix 提供的 PATH 工具是 —— aptpipnpm 的安装在重启后仍保留
配置界面相同相同
何时选择标准部署、最高安全性、可复现性代理需要运行时安装包、可变环境、实验性工具

要启用容器模式,只需添加一行:

{
services.hermes-agent = {
enable = true;
container.enable = true;
# ... rest of config is identical
};
}
info

容器模式会通过 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.disabledstreaming.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 而非 Dockercontainer.backend"podman"
向服务 PATH 添加工具(仅原生)extraPackages[ pkgs.pandoc pkgs.imagemagick ]
使用自定义基础镜像container.image"ubuntu:24.04"
覆盖 hermes 包packageinputs.hermes-agent.packages.${system}.default.override { ... }
更改状态目录stateDir"/opt/hermes"
设置代理的工作目录workingDirectory"/home/user/projects"

密钥管理

永远不要将 API 密钥放入 settingsenvironment

Nix 表达式中的值最终会出现在 /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
};
};
}
tip

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 installsystemd 服务由 NixOS 管理
hermes gateway uninstallsystemd 服务由 NixOS 管理

这防止了 Nix 声明与磁盘上实际配置之间的漂移。检测机制依赖两个信号:

  1. HERMES_MANAGED=true 环境变量 —— 由 systemd 服务设置,对网关进程可见
  2. .managed 标记文件位于 HERMES_HOME —— 由激活脚本设置,对交互式 shell 可见(例如 docker exec -it hermes-agent hermes config set ... 也被阻止)

要更改配置,请编辑你的 Nix 配置并运行 sudo nixos-rebuild switch


容器架构

info

仅当你使用 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 变更持久存在持久存在持久存在

容器仅在其身份哈希发生变化时才会重建。该哈希涵盖:模式版本、镜像、extraVolumesextraOptions 和入口脚本。环境变量、设置、文档或 Hermes 包本身的变更不会触发重建。

可写层丢失

当身份哈希改变(镜像升级、新卷、新容器选项)时,容器会被销毁并从 container.image 的全新拉取中重建。可写层中的任何 apt installpip installnpm 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-contentshermeshermes-agent 二进制文件存在,且 hermes version 可运行
entry-points-syncpyproject.toml 中每个 [project.scripts] 条目在 Nix 包中都有对应的封装二进制文件
cli-commandshermes --help 暴露 gatewayconfig 子命令
managed-guardHERMES_MANAGED=true hermes config set ... 打印出 NixOS 错误
bundled-skills技能目录存在,包含 SKILL.md 文件,且包装器中设置了 HERMES_BUNDLED_SKILLS
config-roundtrip7 种合并场景:全新安装、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 系统级 |

配置

选项类型默认值描述
settingsattrs(深度合并){}config.yaml 形式渲染的声明式配置。支持任意嵌套;多个定义通过 lib.recursiveUpdate 合并
configFilenullpathnull指向现有 config.yaml 的路径。若设置,则完全覆盖 settings

密钥与环境变量

选项类型默认值描述
environmentFileslistOf str[]包含密钥的 env 文件路径。在激活时合并至 $HERMES_HOME/.env
environmentattrsOf str{}非敏感环境变量。在 Nix 存储中可见——请勿在此处放置密钥
authFilenullpathnullOAuth 凭证种子。仅在首次部署时复制
authFileForceOverwriteboolfalse在激活时始终从 authFile 覆盖 auth.json

文档

选项类型默认值描述
documentsattrsOf (either str path){}工作区文件。键为文件名,值为内联字符串或路径。在激活时安装至 workingDirectory

MCP 服务器

选项类型默认值描述
mcpServersattrsOf submodule{}MCP 服务器定义,合并至 settings.mcp_servers
mcpServers.<name>.commandnullstrnull服务器命令(标准输入输出传输)
mcpServers.<name>.argslistOf str[]命令参数
mcpServers.<name>.envattrsOf str{}服务器进程的环境变量
mcpServers.<name>.urlnullstrnull服务器端点 URL(HTTP/可流式 HTTP 传输)
mcpServers.<name>.headersattrsOf str{}HTTP 头信息,例如 Authorization
mcpServers.<name>.authnull"oauth"null认证方式。"oauth" 启用 OAuth 2.1 PKCE
mcpServers.<name>.enabledbooltrue启用或禁用此服务器
mcpServers.<name>.timeoutnullintnull工具调用超时时间(秒,默认:120)
mcpServers.<name>.connect_timeoutnullintnull连接超时时间(秒,默认:60)
mcpServers.<name>.toolsnullsubmodulenull工具过滤(include/exclude 列表)
mcpServers.<name>.samplingnullsubmodulenull服务器发起的 LLM 请求采样配置

服务行为

选项类型默认值描述
extraArgslistOf str[]传递给 hermes gateway 的额外参数
extraPackageslistOf package[]服务 PATH 上的额外包(仅原生模式)
restartstr"always"systemd Restart= 策略
restartSecint5systemd RestartSec=

容器

选项类型默认值描述
container.enableboolfalse启用 OCI 容器模式
container.backendenum ["docker" "podman"]"docker"容器运行时
container.imagestr"ubuntu:24.04"基础镜像(运行时拉取)
container.extraVolumeslistOf str[]额外卷挂载(host:container:mode
container.extraOptionslistOf 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/storeroHermes 二进制文件 + 所有 Nix 依赖
/data/var/lib/hermesrw所有状态、配置、工作区数据
/home/hermes${stateDir}/homerw持久化代理主目录 — pip install --user、工具缓存
/usr, /usr/local, /tmp(可写层)rwapt/pip/npm 安装 — 跨重启持久化,重建时丢失

更新

# Update the flake input
nix flake update hermes-agent --flake /etc/nixos

# Rebuild
sudo nixos-rebuild switch

在容器模式下,current-package 符号链接会被更新,代理在重启后会自动加载新二进制文件。无需重新创建容器,也不会丢失已安装的包。


故障排查

Podman 用户

以下所有 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 NixOSCLI 保护机制启用编辑 configuration.nixnixos-rebuild switch
容器意外被重新创建extraVolumesextraOptionsimage 发生变化正常行为 — 可写层已重置。重新安装包或使用自定义镜像
hermes version 显示旧版本容器未重启systemctl restart hermes-agent
/var/lib/hermes 上权限被拒绝状态目录为 0750 hermes:hermes使用 docker execsudo -u hermes
nix-collect-garbage 移除了 hermesGC 根缺失重启服务(preStart 会重建 GC 根)