跳到主要内容

Nix 与 NixOS 设置

Hermes Agent 提供了一个 Nix flake,支持三种集成层级:

LevelWho it's forWhat you get
nix run / nix profile install任意 Nix 用户(macOS、Linux)含全部依赖的预构建二进制,然后直接走标准 CLI 工作流
NixOS module (native)NixOS 服务器部署声明式配置、加固的 systemd 服务、托管式密钥
NixOS module (container)需要自我修改环境的 agent包含以上全部能力,外加一个持久化 Ubuntu 容器,让 agent 可以在里面执行 apt/pip/npm install
What's different from the standard install

curl | bash 安装器会自行管理 Python、Node 和依赖。Nix flake 则完全替代这套机制:所有 Python 依赖都会作为 Nix derivation 通过 uv2nix 构建,运行时工具(Node.js、git、ripgrep、ffmpeg)也会被打包进二进制的 PATH。这里没有运行时 pip、没有 venv 激活,也没有 npm install

对于非 NixOS 用户,变化只发生在安装环节。后续流程(hermes setuphermes gateway install、编辑配置)与标准安装完全一致。

对于 NixOS module 用户,整个生命周期都不同:配置放在 configuration.nix 中,密钥通过 sops-nix / agenix 管理,服务以 systemd unit 形式运行,CLI 配置命令会被阻止。你需要像管理其他 NixOS 服务一样管理 Hermes。

前置要求

  • 启用了 flakes 的 Nix — 推荐 Determinate Nix(默认启用 flakes)
  • API keys,用于你想接入的服务(至少准备一个 OpenRouter 或 Anthropic key)

快速开始(适用于任意 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 中。之后的流程与 standard installation 完全一致:hermes setup 会带你完成大模型提供商(provider)选择,hermes gateway install 会安装 launchd(macOS)或 systemd user service,而配置则保存在 ~/.hermes/ 中。

Building from a local clone
git clone https://github.com/NousResearch/hermes-agent.git
cd hermes-agent
nix build
./result/bin/hermes setup

NixOS Module

这个 flake 导出了 nixosModules.default:它是一个完整的 NixOS 服务模块,可用声明式方式管理用户创建、目录、配置生成、密钥、文档和服务生命周期。

备注

这个模块要求运行在 NixOS 上。如果你不是 NixOS(例如 macOS 或其他 Linux 发行版),请使用 nix profile install,然后走上面的标准 CLI 工作流。

添加 flake 输入

# /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、接入密钥,并启动网关。这个网关是一个长时间运行的服务,用来把 agent 连接到消息平台(Telegram、Discord 等),并监听传入消息。

Secrets are required

上面的 environmentFiles 假设你已经配置好了 sops-nixagenix。该文件至少需要包含一个 LLM 大模型提供商(provider)密钥(例如 OPENROUTER_API_KEY=sk-or-...)。完整配置请参阅 Secrets Management。如果你还没有密钥管理器,也可以先用一个普通文件起步,但请务必确保它不是全员可读的:

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 就能与网关服务共享状态(sessions、技能、cron)。如果不这样做,在 shell 里运行 hermes 会额外创建一个单独的 ~/.hermes/ 目录。

Container-aware CLI

container.enable = trueaddToSystemPackages = true 时,主机上的所有 hermes 命令都会自动路由进受管容器。这意味着你的交互式 CLI 会话会运行在与网关服务完全相同的环境中,并能访问容器内安装的全部软件包和工具。

  • 路由是透明的:hermes chathermes sessions listhermes version 等命令底层都会自动 exec 进容器
  • 所有 CLI 参数都会原样转发
  • 如果容器没在运行,CLI 会短暂重试(交互式使用时带 spinner 重试 5 秒;脚本场景下静默重试 10 秒),随后明确报错,而不是悄悄回退
  • 如果你是在开发 Hermes 仓库本身,可设置 HERMES_DEV=1 跳过容器路由,直接运行本地 checkout

设置 container.hostUsers 后,会自动创建一个指向服务状态目录的 ~/.hermes 符号链接,让主机 CLI 与容器共享 sessions、config 和 memories:

services.hermes-agent = {
container.enable = true;
container.hostUsers = [ "your-username" ];
addToSystemPackages = true;
};

出现在 hostUsers 中的用户会被自动加入 hermes 组,以获取相应文件权限。

Podman users: NixOS 服务会以 root 身份运行容器。Docker 用户可以通过 docker 组 socket 使用容器,但 Podman 的 rootful 容器需要 sudo。你需要为容器运行时配置免密码 sudo:

security.sudo.extraRules = [{
users = [ "your-username" ];
commands = [{
command = "/run/current-system/sw/bin/podman";
options = [ "NOPASSWD" ];
}];
}];

CLI 会自动探测什么时候需要 sudo,并透明地使用它。否则你就需要手动执行 sudo hermes chat

验证是否工作正常

执行完 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 控制:

Native (default)Container
How it runs在宿主机上作为加固的 systemd 服务运行持久化 Ubuntu 容器,绑定挂载 /nix/store
SecurityNoNewPrivilegesProtectSystem=strictPrivateTmp容器隔离,内部以非特权用户运行
Agent can self-install packages否,只能使用 Nix 提供到 PATH 上的工具可以,aptpipnpm 安装在重启后仍保留
Config surfaceSameSame
When to choose标准部署、最高安全性、强可复现性agent 需要运行时安装软件包、可变环境或实验性工具

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

{
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 没有覆盖的键会被保留。也就是说,如果 agent 或手动编辑增加了像 skills.disabledstreaming.enabled 这样的键,它们在 nixos-rebuild switch 之后仍会存在。

Model naming

settings.model.default 使用的是你的大模型提供商(provider)所期望的模型标识符。以默认的 OpenRouter 为例,通常长这样:"anthropic/claude-sonnet-4""google/gemini-3-flash"。如果你是直接使用某个大模型提供商(provider)(如 Anthropic、OpenAI),请把 settings.model.base_url 指向对方 API,并使用其原生模型 ID(例如 "claude-sonnet-4-20250514")。如果没有设置 base_url,Hermes 默认使用 OpenRouter。

Discovering available config keys

运行 nix build .#configKeys && cat result,可以查看从 Python DEFAULT_CONFIG 中提取出来的所有叶子配置键。你甚至可以把现有的 config.yaml 直接粘进 settings attrset,结构是一一对应的。

Full example: all commonly customized settings
{ 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 = {
"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";
hostUsers = [ "your-username" ];
extraVolumes = [ "/home/user/projects:/projects:rw" ];
extraOptions = [ "--gpus" "all" ];
};

# ── Service tuning ─────────────────────────────────────────────────
addToSystemPackages = true;
extraArgs = [ "--verbose" ];
restart = "always";
restartSec = 5;
};
}

Escape Hatch: Bring Your Own Config

如果你更希望完全在 Nix 之外维护 config.yaml,可以使用 configFile

services.hermes-agent.configFile = /etc/hermes/config.yaml;

这样就会完全绕过 settings:不做合并,也不做自动生成。每次 activation 时,这个文件都会被原样复制到 $HERMES_HOME/config.yaml

自定义速查表

下面是 Nix 用户最常调整项的快速参考:

I want to...OptionExample
Change the LLM modelsettings.model.default"anthropic/claude-sonnet-4"
Use a different provider endpointsettings.model.base_url"https://openrouter.ai/api/v1"
Add API keysenvironmentFiles[ config.sops.secrets."hermes-env".path ]
Give the agent a personality${services.hermes-agent.stateDir}/.hermes/SOUL.md直接管理这个文件
Add MCP tool serversmcpServers.<name>参见 MCP Servers
Mount host directories into containercontainer.extraVolumes[ "/data:/data:rw" ]
Pass GPU access to containercontainer.extraOptions[ "--gpus" "all" ]
Use Podman instead of Dockercontainer.backend"podman"
Share state between host CLI and containercontainer.hostUsers[ "sidbin" ]
Add tools to the service PATH (native only)extraPackages[ pkgs.pandoc pkgs.imagemagick ]
Use a custom base imagecontainer.image"ubuntu:24.04"
Override the hermes packagepackageinputs.hermes-agent.packages.${system}.default.override { ... }
Change state directorystateDir"/opt/hermes"
Set the agent's working directoryworkingDirectory"/home/user/projects"

Secrets Management

Never put API keys in settings or environment

Nix 表达式中的值最终会进入 /nix/store,而那里是所有用户可读的。密钥请始终通过 environmentFiles 搭配密钥管理器来处理。

environment(非敏感环境变量)和 environmentFiles(密钥文件)都会在 activation(nixos-rebuild switch)时合并进 $HERMES_HOME/.env。Hermes 每次启动都会读取这个文件,因此改动只需配合 systemctl restart hermes-agent 就能生效,不需要重建容器。

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 / Auth Seeding

对于需要 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 会写入状态目录,并在后续 rebuild 中保留。


Documents

documents 选项会把文件安装到 agent 的工作目录中(也就是 workingDirectory,agent 会把它视作 workspace)。Hermes 会按约定查找特定文件名:

  • USER.md — agent 当前正在交互的用户相关上下文
  • 你放在这里的其他文件也都会作为工作区文件暴露给 agent

agent 的身份文件是分开的:Hermes 的主 SOUL.md 来自 $HERMES_HOME/SOUL.md,在 NixOS module 中对应 ${services.hermes-agent.stateDir}/.hermes/SOUL.md。把 SOUL.md 放进 documents 只会生成一个工作区文件,并不会替代主 persona 文件。

{
services.hermes-agent.documents = {
"USER.md" = ./documents/USER.md; # path reference, copied from Nix store
};
}

这里的值既可以是内联字符串,也可以是路径引用。每次 nixos-rebuild switch 时都会重新安装这些文件。


MCP Servers

mcpServers 选项可以用声明式方式配置 MCP (Model Context Protocol) 服务器。每台服务器都可以使用 stdio(本地命令)或 HTTP(远程 URL)传输。

Stdio Transport (Local Servers)

{
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 注入,不要把 token 直接写进 Nix 配置。

HTTP Transport (Remote Servers)

{
services.hermes-agent.mcpServers.remote-api = {
url = "https://mcp.example.com/v1/mcp";
headers.Authorization = "Bearer \${MCP_REMOTE_API_KEY}";
timeout = 180;
};
}

HTTP Transport with OAuth

对于使用 OAuth 2.1 的服务器,请设置 auth = "oauth"。Hermes 实现了完整的 PKCE 流程:元数据发现、动态客户端注册、token 交换以及自动刷新。

{
services.hermes-agent.mcpServers.my-oauth-server = {
url = "https://mcp.example.com/mcp";
auth = "oauth";
};
}

token 会保存在 $HERMES_HOME/mcp-tokens/<server-name>.json 中,并在重启和 rebuild 之后继续保留。

Initial OAuth authorization on headless servers

首次 OAuth 授权需要经过浏览器授权同意流程。在无头部署环境中,Hermes 不会尝试直接打开浏览器,而是把授权 URL 打印到 stdout / logs 中。

Option A: Interactive bootstrap — 通过 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 回调端口。

Option B: Pre-seed tokens — 先在工作站上完成授权流程,再把 token 拷过去:

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

Sampling (Server-Initiated LLM Requests)

某些 MCP 服务器可以向 agent 发起 LLM completion 请求:

{
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;
};
};
}

Managed Mode

当 Hermes 通过 NixOS module 运行时,下面这些 CLI 命令会被拦截并报错,提示你改去编辑 configuration.nix

Blocked commandWhy
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 marker file in HERMES_HOME — 由 activation script 创建,对交互式 shell 可见(例如 docker exec -it hermes-agent hermes config set ... 也会被阻止)

要修改配置,请编辑 Nix 配置后执行 sudo nixos-rebuild switch


Container Architecture

信息

只有当你启用了 container.enable = true 时,这一节才相关。原生模式部署可以跳过。

启用容器模式后,Hermes 会运行在一个持久化 Ubuntu 容器中,而 Nix 构建出的二进制会以只读方式从宿主机 bind mount 进来:

Host                                    Container
──── ─────────
/nix/store/...-hermes-agent-0.1.0 ──► /nix/store/... (ro)
~/.hermes -> /var/lib/hermes/.hermes (symlink bridge, per hostUsers)
/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)
│ ├── .container-mode (routing metadata: backend, exec_user, etc.)
│ ├── 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 被 bind mount 进去了。它会自带解释器和全部依赖,因此不依赖容器自己的系统库。容器入口点通过 current-package 符号链接解析到 /data/current-package/bin/hermes gateway run --replace。在 nixos-rebuild switch 时,只会更新这个符号链接,容器本身不会被重建。

什么会在什么情况下保留

EventContainer recreated?/data (state)/home/hermesWritable layer (apt/pip/npm)
systemctl restart hermes-agentNoPersistsPersistsPersists
nixos-rebuild switch (code change)No (symlink updated)PersistsPersistsPersists
Host rebootNoPersistsPersistsPersists
nix-collect-garbageNo (GC root)PersistsPersistsPersists
Image change (container.image)YesPersistsPersistsLost
Volume/options changeYesPersistsPersistsLost
environment/environmentFiles changeNoPersistsPersistsPersists

只有当容器的identity hash 变化时,容器才会被重新创建。这个哈希覆盖的内容包括:schema version、image、extraVolumesextraOptions 以及 entrypoint script。环境变量、settings、documents 或 Hermes 软件包本身的变化,都不会触发重建。

Writable layer loss

当 identity hash 发生变化时(例如镜像升级、新增 volume、新增容器选项),容器会被销毁并基于新的 container.image 重新创建。写在可写层里的 apt installpip installnpm install 软件包都会丢失。/data/home/hermes 里的状态则会被保留,因为它们是 bind mount。

如果 agent 依赖某些特定软件包,建议把它们烘焙进自定义镜像(例如 container.image = "my-registry/hermes-base:latest"),或在 agent 的 SOUL.md 中写好安装脚本。

GC Root Protection

preStart 脚本会在 ${stateDir}/.gc-root 创建一个指向当前 Hermes 软件包的 GC root,防止 nix-collect-garbage 清掉正在运行的二进制。如果 GC root 不知为何损坏了,重启服务就会重新创建它。


Development

Dev Shell

这个 flake 提供了一个开发 shell,内置 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

仓库自带的 .envrc 会自动激活 dev shell:

cd hermes-agent
direnv allow # one-time
# Subsequent entries are near-instant (stamp file skips dep install)

Flake Checks

这个 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
What each check verifies
CheckWhat it tests
package-contents验证 hermeshermes-agent 二进制存在,且 hermes version 可运行
entry-points-sync验证 pyproject.toml 中每个 [project.scripts] 条目都在 Nix 包里有对应包装二进制
cli-commands验证 hermes --help 暴露了 gatewayconfig 子命令
managed-guard验证 HERMES_MANAGED=true hermes config set ... 会打印 NixOS 管理模式错误
bundled-skills验证技能目录存在,包含 SKILL.md 文件,且包装器中设置了 HERMES_BUNDLED_SKILLS
config-roundtrip验证 7 种合并场景:全新安装、Nix 覆盖、保留用户键、混合合并、MCP 附加合并、嵌套深度合并和幂等性

Options Reference

Core

OptionTypeDefaultDescription
enableboolfalse启用 hermes-agent 服务
packagepackagehermes-agent要使用的 hermes-agent 软件包
userstr"hermes"系统用户
groupstr"hermes"系统用户组
createUserbooltrue自动创建用户 / 组
stateDirstr"/var/lib/hermes"状态目录(HERMES_HOME 的父目录)
workingDirectorystr"${stateDir}/workspace"agent 工作目录(MESSAGING_CWD
addToSystemPackagesboolfalsehermes CLI 加入系统 PATH,并在系统范围内设置 HERMES_HOME

Configuration

OptionTypeDefaultDescription
settingsattrs (deep-merged){}声明式配置,会渲染为 config.yaml。支持任意嵌套;多个定义通过 lib.recursiveUpdate 合并
configFilenull or pathnull现有 config.yaml 的路径;设置后会完全覆盖 settings

Secrets & Environment

OptionTypeDefaultDescription
environmentFileslistOf str[]保存密钥的 env 文件路径;activation 时会合并进 $HERMES_HOME/.env
environmentattrsOf str{}非敏感环境变量。会暴露在 Nix store 中,请勿放密钥
authFilenull or pathnullOAuth 凭据种子文件,仅在首次部署时复制
authFileForceOverwriteboolfalse每次 activation 都用 authFile 覆盖 auth.json

Documents

OptionTypeDefaultDescription
documentsattrsOf (either str path){}工作区文件。键是文件名,值是内联字符串或路径;activation 时安装到 workingDirectory

MCP Servers

OptionTypeDefaultDescription
mcpServersattrsOf submodule{}MCP 服务器定义,会合并进 settings.mcp_servers
mcpServers.<name>.commandnull or strnull服务器命令(stdio transport)
mcpServers.<name>.argslistOf str[]命令参数
mcpServers.<name>.envattrsOf str{}服务器进程使用的环境变量
mcpServers.<name>.urlnull or strnull服务器端点 URL(HTTP / StreamableHTTP transport)
mcpServers.<name>.headersattrsOf str{}HTTP headers,例如 Authorization
mcpServers.<name>.authnull or "oauth"null认证方式;"oauth" 会启用 OAuth 2.1 PKCE
mcpServers.<name>.enabledbooltrue启用或禁用该服务器
mcpServers.<name>.timeoutnull or intnull工具调用超时(秒,默认 120)
mcpServers.<name>.connect_timeoutnull or intnull连接超时(秒,默认 60)
mcpServers.<name>.toolsnull or submodulenull工具过滤(include / exclude 列表)
mcpServers.<name>.samplingnull or submodulenull供服务器发起 LLM 请求时使用的 sampling 配置

Service Behavior

OptionTypeDefaultDescription
extraArgslistOf str[]传给 hermes gateway 的额外参数
extraPackageslistOf package[]额外加入服务 PATH 的软件包(仅原生模式)
restartstr"always"systemd Restart= 策略
restartSecint5systemd RestartSec=

Container

OptionTypeDefaultDescription
container.enableboolfalse启用 OCI 容器模式
container.backendenum ["docker" "podman"]"docker"容器运行时
container.imagestr"ubuntu:24.04"基础镜像(运行时拉取)
container.extraVolumeslistOf str[]额外挂载卷(host:container:mode
container.extraOptionslistOf str[]额外传给 docker create 的参数
container.hostUserslistOf str[]会获得 ~/.hermes 符号链接并自动加入 hermes 组的交互用户

Directory Layout

Native Mode

/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)

Container Mode

同样的目录布局,只是它们会被挂载进容器:

Container pathHost pathModeNotes
/nix/store/nix/storeroHermes 二进制和全部 Nix 依赖
/data/var/lib/hermesrw全部状态、配置和工作区
/home/hermes${stateDir}/homerw持久化 agent home,用于 pip install --user、工具缓存等
/usr, /usr/local, /tmp(writable layer)rwapt/pip/npm 安装内容;重启保留,重建丢失

Updating

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

# Rebuild
sudo nixos-rebuild switch

在容器模式下,current-package 符号链接会被更新,agent 在重启后就会用到新的二进制。无需重建容器,也不会丢失后来安装的软件包。


Troubleshooting

Podman users

下面所有 docker 命令都可以用 podman 等价替代。如果你设置了 container.backend = "podman",请自行替换。

Service Logs

# Both modes use the same systemd unit
journalctl -u hermes-agent -f

# Container mode: also available directly
docker logs -f hermes-agent

Container Inspection

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

Force Container Recreation

如果你需要重置可写层(获得一个全新的 Ubuntu 容器):

sudo systemctl stop hermes-agent
docker rm -f hermes-agent
sudo rm /var/lib/hermes/.container-identity
sudo systemctl start hermes-agent

Verify Secrets Are Loaded

如果 agent 能启动,但无法向 LLM 大模型提供商(provider)认证,请检查 .env 是否已正确合并:

# Native mode
sudo -u hermes cat /var/lib/hermes/.hermes/.env

# Container mode
docker exec hermes-agent cat /data/.hermes/.env

GC Root Verification

nix-store --query --roots $(docker exec hermes-agent readlink /data/current-package)

Common Issues

SymptomCauseFix
Cannot save configuration: managed by NixOSCLI 守卫已启用编辑 configuration.nix 后执行 nixos-rebuild switch
Container recreated unexpectedlyextraVolumesextraOptionsimage 发生变化这是预期行为。可写层会重置,请重新安装软件包或使用自定义镜像
hermes version shows old version容器尚未重启执行 systemctl restart hermes-agent
Permission denied on /var/lib/hermes状态目录权限是 0750 hermes:hermes使用 docker execsudo -u hermes
nix-collect-garbage removed hermesGC root 丢失重启服务(preStart 会重新创建 GC root)
no container with name or ID "hermes-agent" (Podman)Podman rootful 容器对普通用户不可见为 podman 配置免密码 sudo(见 Container-aware CLI
unable to find user hermes容器仍在启动中(entrypoint 还没创建用户)等几秒再试,CLI 本身也会自动重试