Перейти к содержимому

Настройка Nix и NixOS

Hermes Agent поставляется как Nix-flake с тремя уровнями интеграции:

УровеньДля когоЧто вы получаете
nix run / nix profile installЛюбой пользователь Nix (macOS, Linux)Предварительно собранный бинарный файл со всеми зависимостями — затем используйте стандартный процесс CLI
NixOS module (native)Развёртывание на серверах NixOSДекларативная конфигурация, защищённый systemd-сервис, управляемые секреты
NixOS module (container)Агентам, которым нужна самодоработка средыВсё вышеперечисленное плюс постоянный контейнер Ubuntu, где агент может выполнять apt/pip/npm install

:::info Чем это отличается от стандартной установки Установщик curl | bash сам управляет Python, Node и зависимостями. Nix-flake заменяет всю эту схему: каждая Python-зависимость собирается как Nix-деривация через uv2nix, а инструменты времени выполнения — Node.js, git, ripgrep, ffmpeg — уже обёрнуты в PATH бинарника. Никакого runtime pip, активации venv или npm install здесь нет.

Для пользователей не-NixOS это меняет только шаг установки. Всё после этого (hermes setup, hermes gateway install, редактирование конфигурации) работает точно так же, как при стандартной установке.

Для пользователей NixOS module весь жизненный цикл отличается: конфигурация находится в configuration.nix, секреты проходят через sops-nix/agenix, сервис представляет собой unit systemd, а команды конфигурации CLI заблокированы. Вы управляете hermes так же, как любым другим сервисом NixOS. :::

  • Nix с включёнными flakes — рекомендуется Determinate Nix (по умолчанию включает flakes)
  • Ключи API для сервисов, которые вы хотите использовать (как минимум: ключ OpenRouter или Anthropic)

Клонирование не требуется. 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 на Linux, а конфигурация хранится в ~/.hermes/.

Сборка из локального клона
Окно терминала
git clone https://github.com/NousResearch/hermes-agent.git
cd hermes-agent
nix build
./result/bin/hermes setup

Flake экспортирует nixosModules.default — полноценный сервисный модуль NixOS, который декларативно управляет созданием пользователя, директориями, генерацией конфигурации, секретами, документами и жизненным циклом сервиса.

# /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, подключает секреты и запускает gateway — долгоживущий сервис, который соединяет агента с платформами обмена сообщениями (Telegram, Discord и т. д.) и принимает входящие сообщения.

:::warning Секреты обязательны Строка 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" ];

:::

:::tip addToSystemPackages Параметр addToSystemPackages = true делает две вещи: помещает hermes CLI в ваш системный PATH и задаёт HERMES_HOME на уровне всей системы, чтобы интерактивная сессия CLI разделяла состояние (сессии, навыки, cron) с сервисом gateway. Без этого запуск hermes в вашей shell создаёт отдельный каталог ~/.hermes/. :::

Когда включены container.enable = true и addToSystemPackages = true, каждая команда hermes на хосте автоматически перенаправляется в управляемый контейнер. Это означает, что ваша интерактивная сессия CLI выполняется в той же среде, что и сервис gateway, — с доступом ко всем пакетам и инструментам, установленным в контейнере.

  • Перенаправление прозрачно: hermes chat, hermes sessions list, hermes version и т. д. все под капотом выполняются в контейнере через exec
  • Все флаги CLI передаются как есть
  • Если контейнер не запущен, CLI ненадолго повторяет попытки (5 с со спиннером для интерактивного использования, 10 с без вывода для скриптов), а затем завершается с понятной ошибкой — без тихого отката
  • Для разработчиков, работающих над кодовой базой hermes, установите HERMES_DEV=1, чтобы обойти перенаправление в контейнер и запускать локальный checkout напрямую

Установите container.hostUsers, чтобы создать символическую ссылку ~/.hermes на каталог состояния сервиса, чтобы хостовый CLI и контейнер совместно использовали сессии, конфигурацию и память:

services.hermes-agent = {
container.enable = true;
container.hostUsers = [ "your-username" ];
addToSystemPackages = true;
};
```Пользователи, перечисленные в `hostUsers`, автоматически добавляются в группу `hermes` для доступа к правам файлов.
**Пользователи Podman:** Сервис NixOS запускает контейнер от root. Пользователи Docker получают доступ через сокет группы `docker`, но rootful-контейнеры Podman требуют sudo. Предоставьте passwordless sudo для вашего runtime контейнеров:
```nix
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:

Нативный (по умолчанию)Контейнер
Как запускаетсяЗащищённый сервис systemd на хостеПостоянный контейнер Ubuntu с bind mount для /nix/store
БезопасностьNoNewPrivileges, ProtectSystem=strict, PrivateTmpИзоляция контейнера, запуск от непривилегированного пользователя внутри
Агент может сам устанавливать пакетыНет — только инструменты в PATH, предоставленном NixДа — установки apt, pip, npm сохраняются после перезапусков
Поверхность конфигурацииОдинаковаяОдинаковая
Когда выбиратьСтандартные развертывания, максимальная безопасность, воспроизводимостьАгенту нужна установка пакетов во время выполнения, изменяемая среда, экспериментальные инструменты

Чтобы включить контейнерный режим, добавьте одну строку:

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

Контейнерный режим автоматически включает virtualisation.docker.enable через mkDefault. Если вы используете 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.

:::note Именование моделей 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. :::

:::tip Как найти доступные ключи конфигурации Выполните nix build .#configKeys && cat result, чтобы увидеть каждый конечный ключ конфигурации, извлечённый из Python DEFAULT_CONFIG. Вы можете вставить существующий config.yaml в attrset settings — структура совпадает 1:1. :::

Полный пример: все часто настраиваемые параметры
nix
{ config, ... }: {
services.hermes-agent = {
enable = true;
container.enable = true;
# ── Модель ──────────────────────────────────────────────────────────
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; };
};
# ── Секреты ────────────────────────────────────────────────────────
environmentFiles = [ config.sops.secrets."hermes-env".path ];
# ── Документы ──────────────────────────────────────────────────────
documents = {
"USER.md" = ./documents/USER.md;
};
# ── Серверы MCP ────────────────────────────────────────────────────
mcpServers.filesystem = {
command = "npx";
args = [ "-y" "@modelcontextprotocol/server-filesystem" "/data/workspace" ];
};
# ── Параметры контейнера ──────────────────────────────────────────────
container = {
image = "ubuntu:24.04";
backend = "docker";
hostUsers = [ "your-username" ];
extraVolumes = [ "/home/user/projects:/projects:rw" ];
extraOptions = [ "--gpus" "all" ];
};
# ── Настройка сервиса ─────────────────────────────────────────────────
addToSystemPackages = true;
extraArgs = [ "--verbose" ];
restart = "always";
restartSec = 5;
};
}

If you’d rather manage config.yaml entirely outside Nix, use configFile:

nix
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 ] | | Придать агенту индивидуальность | ${services.hermes-agent.stateDir}/.hermes/SOUL.md | управлять файлом напрямую | | Добавить серверы инструментов MCP | mcpServers.<name> | См. [серверы MCP | | Смонтировать каталоги хоста в контейнер | container.extraVolumes | [ "/data:/data:rw" ] | | Передать доступ к GPU в контейнер | container.extraOptions | [ "--gpus" "all" ] | | Использовать Podman вместо Docker | container.backend | "podman" | | Совместно использовать состояние между хостом CLI и контейнером | container.hostUsers | [ "sidbin" ] | | Сделать дополнительные инструменты доступными агенту | 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" |


:::danger Никогда не помещайте ключи API в settings или environment Значения в выражениях Nix попадают в /nix/store, который доступен для чтения всем. Всегда используйте environmentFiles вместе с менеджером секретов. :::

И environment (несекретные переменные), и environmentFiles (секретные файлы) объединяются в $HERMES_HOME/.env во время активации (nixos-rebuild switch). Hermes читает этот файл при каждом запуске, поэтому изменения вступают в силу после systemctl restart hermes-agent — пересоздавать контейнер не нужно.

{
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-...
{
age.secrets.hermes-env.file = ./secrets/hermes-env.age;
services.hermes-agent.environmentFiles = [
config.age.secrets.hermes-env.path
];
}

Для платформ, требующих 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-токена во время выполнения записываются в каталог состояния и сохраняются между пересборками.


Параметр documents устанавливает файлы в рабочий каталог агента (workingDirectory, который агент читает как свое рабочее пространство). Hermes по соглашению ищет определенные имена файлов:

  • USER.md — контекст о пользователе, с которым взаимодействует агент.
  • Любые другие файлы, которые вы разместите здесь, будут видны агенту как файлы рабочего пространства.

Файл идентичности агента отделен: Hermes загружает свой основной SOUL.md из $HERMES_HOME/SOUL.md, который в модуле NixOS является ${services.hermes-agent.stateDir}/.hermes/SOUL.md. Размещение SOUL.md в documents только создает файл рабочего пространства и не заменит основной файл персоны.

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

Значения могут быть встроенными строками или ссылками на пути. Файлы устанавливаются при каждом nixos-rebuild switch.


Параметр mcpServers декларативно настраивает серверы MCP (Model Context Protocol). Каждый сервер использует транспорт либо stdio (локальная команда), либо HTTP (удаленный URL).

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

Установите auth = "oauth" для серверов, использующих OAuth 2.1. 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-авторизация на headless-серверах

Для первой OAuth-авторизации требуется поток согласия через браузер. В headless-развёртывании Hermes выводит URL авторизации URL в stdout/logs, вместо того чтобы открывать браузер.

Вариант A: Интерактивный bootstrap — запустите поток один раз через docker exec (container) или sudo -u hermes (native):

Окно терминала
# 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

Container использует --network=host, поэтому слушатель callback OAuth на 127.0.0.1 доступен из браузера на хосте.

Вариант 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)

Заголовок раздела «Сэмплирование (инициируемые сервером запросы 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Конфигурация декларативная — редактируйте settings в вашей конфигурации Nix
hermes config editКонфигурация генерируется из settings
hermes config set <key> <value>Конфигурация генерируется из settings
hermes gateway installСервис systemd управляется NixOS
hermes gateway uninstallСервис systemd управляется NixOS

Это предотвращает расхождения между тем, что объявлено в Nix, и тем, что находится на диске. Для обнаружения используются два сигнала:

  1. Переменная окружения HERMES_MANAGED=true — задаётся сервисом systemd, видна процессу gateway
  2. Файл-маркер .managed в HERMES_HOME — задаётся скриптом активации, виден интерактивным оболочкам (например, 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)
~/.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 — он приносит собственный интерпретатор и все зависимости, поэтому нет зависимости от системных библиотек контейнера. Entry point контейнера разрешается через символьную ссылку current-package: /data/current-package/bin/hermes gateway run --replace. На nixos-rebuild switch обновляется только символьная ссылка — контейнер продолжает работать.

Что сохраняется при каких условиях| Событие | Контейнер пересоздаётся? | /data (состояние) | /home/hermes | Записываемый слой (apt/pip/npm) |

Заголовок раздела «Что сохраняется при каких условиях| Событие | Контейнер пересоздаётся? | /data (состояние) | /home/hermes | Записываемый слой (apt/pip/npm) |»

|---|---|---|---|---| | systemctl restart hermes-agent | Нет | Сохраняется | Сохраняется | Сохраняется | | nixos-rebuild switch (изменение кода) | Нет (symlink обновлён) | Сохраняется | Сохраняется | Сохраняется | | Перезагрузка хоста | Нет | Сохраняется | Сохраняется | Сохраняется | | nix-collect-garbage | Нет (GC root) | Сохраняется | Сохраняется | Сохраняется | | Изменение образа (container.image) | Да | Сохраняется | Сохраняется | Теряется | | Изменение Volume/options | Да | Сохраняется | Сохраняется | Теряется | | Изменение environment/environmentFiles | Нет | Сохраняется | Сохраняется | Сохраняется |

Контейнер пересоздаётся только при изменении его identity hash. Хеш включает: версию схемы, образ, extraVolumes, extraOptions и entrypoint script. Изменения переменных окружения, настроек, документов или самого пакета hermes не вызывают пересоздание.

:::warning Потеря записываемого слоя Когда identity hash меняется (обновление образа, новые volumes, новые параметры контейнера), контейнер уничтожается и пересоздаётся из свежего pull container.image. Все пакеты apt install, pip install или npm install в записываемом слое теряются. Состояние в /data и /home/hermes сохраняется (это bind mounts).

Если агент зависит от конкретных пакетов, подумайте о том, чтобы встроить их в пользовательский образ (container.image = "my-registry/hermes-base:latest") или прописать их установку в SOUL.md агента. :::

Скрипт preStart создаёт GC root в ${stateDir}/.gc-root, указывающий на текущий пакет hermes. Это не позволяет nix-collect-garbage удалить запущенный бинарник. Если GC root по какой-то причине сломается, перезапуск сервиса создаст его заново.


Модуль NixOS поддерживает декларативную установку плагинов — без необходимости в императивном hermes plugins install.

Для плагинов, которые представляют собой просто дерево исходников с plugin.yaml + __init__.py (например, hermes-lcm):

services.hermes-agent.extraPlugins = [
(pkgs.fetchFromGitHub {
owner = "stephenschoettler";
repo = "hermes-lcm";
rev = "v0.7.0";
hash = "sha256-...";
})
];

Плагины симлинкуются в $HERMES_HOME/plugins/ во время активации. Hermes обнаруживает их через своё обычное сканирование директории. Удаление плагина из списка и запуск nixos-rebuild switch удаляет симлинк.

Для упакованных через pip плагинов, которые регистрируются через [project.entry-points."hermes_agent.plugins"] (например, rtk-hermes):

services.hermes-agent.extraPythonPackages = [
(pkgs.python312Packages.buildPythonPackage {
pname = "rtk-hermes";
version = "1.0.0";
src = pkgs.fetchFromGitHub {
owner = "ogallotti";
repo = "rtk-hermes";
rev = "v1.0.0";
hash = "sha256-...";
};
format = "pyproject";
build-system = [ pkgs.python312Packages.setuptools ];
})
];

Пакетный site-packages добавляется в PYTHONPATH в обёртке hermes. importlib.metadata обнаруживает точку входа при запуске сессии.

Плагину директории со сторонними зависимостями Python нужны оба варианта:

services.hermes-agent = {
extraPlugins = [ my-plugin-src ];
# plugin source
extraPythonPackages = [ pkgs.python312Packages.redis ];
# its Python dep
extraPackages = [ pkgs.redis ];
# system binary it needs
};

Внешние flakes могут переопределять пакет напрямую:

{
inputs.hermes-agent.url = "github:NousResearch/hermes-agent";
outputs = { hermes-agent, nixpkgs, ... }: {
nixpkgs.overlays = [ hermes-agent.overlays.default ];
# Then: pkgs.hermes-agent.override { extraPythonPackages = [...]; }
};
}

Плагины всё ещё нужно включать в config.yaml. Добавьте их через декларативные настройки:

services.hermes-agent.settings.plugins.enabled = [
"hermes-lcm"
"rtk-rewrite"
];

Flake предоставляет среду разработки с Python 3.12, uv, Node.js и всеми runtime-инструментами:

Окно терминала
cd hermes-agent
nix develop
# Shell provides:
#
- Python 3.12 + uv (deps installed into .venv on first entry)
#
- Node.js 22, 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 включает проверку на этапе сборки, которая запускается в 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` | Каждая запись `[project.scripts]` в `pyproject.toml` имеет обёрнутый бинарный файл в пакете Nix | | `cli-commands` | `hermes --help` предоставляет подкоманды `gateway` и `config` | | `managed-guard` | `HERMES_MANAGED=true hermes config set ...` выводит ошибку NixOS | | `bundled-skills` | Каталог навыков существует, содержит файлы SKILL.md, в wrapper задан `HERMES_BUNDLED_SKILLS` | | `config-roundtrip` | 7 сценариев слияния: новая установка, переопределение Nix, сохранение пользовательского ключа, смешанное слияние, аддитивное слияние MCP, глубокое вложенное слияние, идемпотентность |

ОпцияТипПо умолчаниюОписание
enableboolfalseВключить сервис hermes-agent
packagepackagehermes-agentПакет hermes-agent для использования
userstr"hermes"Системный пользователь
groupstr"hermes"Системная группа
createUserbooltrueАвтоматически создавать user/group
stateDirstr"/var/lib/hermes"Каталог состояния (родительский для HERMES_HOME)
workingDirectorystr"${stateDir}/workspace"Рабочий каталог агента (MESSAGING_CWD)
addToSystemPackagesboolfalseДобавить hermes CLI в системный PATH и задать HERMES_HOME на уровне системы
ОпцияТипПо умолчаниюОписание
settingsattrs (глубокое слияние){}Декларативная конфигурация, отображаемая как config.yaml. Поддерживает произвольную вложенность; несколько определений объединяются через lib.recursiveUpdate
configFilenull или pathnullПуть к существующему config.yaml. Полностью переопределяет settings, если задан

Секреты и окружение| Option | Type | Default | Описание |

Заголовок раздела «Секреты и окружение| Option | Type | Default | Описание |»

|---|---|---|---| | environmentFiles | listOf str | [] | Пути к env-файлам с секретами. Объединяются в $HERMES_HOME/.env во время активации | | environment | attrsOf str | {} | Несекретные env-переменные. Видимы в Nix store — не помещайте сюда секреты | | authFile | null or path | null | Начальные OAuth credentials. Копируются только при первом развертывании | | authFileForceOverwrite | bool | false | Всегда перезаписывать auth.json из authFile при активации |

OptionTypeDefaultОписание
documentsattrsOf (either str path){}Файлы workspace. Ключи — это имена файлов, значения — встроенные строки или пути. Устанавливаются в workingDirectory при активации
OptionTypeDefaultОписание
mcpServersattrsOf submodule{}Определения серверов MCP, объединяются в settings.mcp_servers
mcpServers.<name>.commandnull or strnullКоманда сервера (транспорт stdio)
mcpServers.<name>.argslistOf str[]Аргументы команды
mcpServers.<name>.envattrsOf str{}Переменные окружения для процесса сервера
mcpServers.<name>.urlnull or strnullEndpoint сервера URL (транспорт HTTP/StreamableHTTP)
mcpServers.<name>.headersattrsOf str{}Заголовки HTTP, например 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Конфигурация sampling для инициируемых сервером запросов LLM

Поведение сервиса| Опция | Тип | По умолчанию | Описание |

Заголовок раздела «Поведение сервиса| Опция | Тип | По умолчанию | Описание |»

|---|---|---|---| | extraArgs | listOf str | [] | Дополнительные аргументы для hermes gateway | | extraPackages | listOf package | [] | Дополнительные пакеты, доступные агенту. Добавляются в профиль пользователя hermes на уровне пользователя, чтобы команды терминала, навыки и cron jobs все их видели | | extraPlugins | listOf package | [] | Пакеты плагинов-каталогов для создания symlink в $HERMES_HOME/plugins/. Каждый должен содержать plugin.yaml | | extraPythonPackages | listOf package | [] | Python-пакеты, добавляемые в PYTHONPATH для обнаружения плагинов через entry point. Сборка с помощью python312Packages | | restart | str | "always" | Политика systemd Restart= | | restartSec | int | 5 | Значение systemd 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
container.hostUserslistOf str[]Интерактивные пользователи, которые получают symlink ~/.hermes на stateDir сервиса и автоматически добавляются в группу hermes

/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/storeroБинарный файл Hermes + все зависимости Nix
/data/var/lib/hermesrwВсё состояние, конфиг, рабочее пространство
/home/hermes${stateDir}/homerwПостоянный домашний каталог агента — pip install --user, кэши инструментов
/usr, /usr/local, /tmp(записываемый слой)rwУстановки apt/pip/npm — сохраняются между перезапусками, теряются при пересоздании

Окно терминала
# Update the flake input (run from the directory containing flake.nix)
cd /etc/nixos && nix flake update hermes-agent
# Rebuild
sudo nixos-rebuild switch

В режиме контейнера обновляется символическая ссылка current-package, и после перезапуска агент подхватывает новый бинарный файл. Пересоздание контейнера не требуется, потери установленных пакетов нет.


:::tip Пользователи 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

Если нужно сбросить writable layer (чистый 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
Окно терминала
nix-store --query --roots $(docker exec hermes-agent readlink /data/current-package)
СимптомПричинаРешение
Cannot save configuration: managed by NixOSguards CLI активныОтредактируйте configuration.nix и nixos-rebuild switch
Контейнер неожиданно пересоздалсяИзменились extraVolumes, extraOptions или imageЭто ожидаемо — writable layer сбрасывается. Переустановите пакеты или используйте пользовательский образ
hermes version показывает старую версиюКонтейнер не был перезапущенsystemctl restart hermes-agent
Отказано в доступе к /var/lib/hermesКаталог состояния — 0750 hermes:hermesИспользуйте docker exec или sudo -u hermes
nix-collect-garbage удалил hermesОтсутствует GC rootПерезапустите сервис (preStart заново создаёт GC root)
no container with name or ID "hermes-agent" (Podman)rootful-контейнер Podman не виден обычному пользователюДобавьте sudo без пароля для podman (см. раздел Container Mode)
unable to find user hermesКонтейнер всё ещё запускается (entrypoint ещё не создал пользователя)Подождите несколько секунд и повторите попытку — CLI автоматически выполняет повторные попытки
Инструмент, добавленный через extraPackages, не найден в терминалеТребуется nixos-rebuild switch для обновления профиля пользователяПересоберите и перезапустите: nixos-rebuild switch && systemctl restart hermes-agent