1Password
Получайте ключи API провайдеров из 1Password прямо при старте процесса, вместо того чтобы хранить их в открытом виде в ~/.hermes/.env. Вы держите ключи как элементы 1Password и ссылаетесь на них через op://vault/item/field; ротация учётных данных сводится к одному изменению внутри 1Password.
Как это работает
- Вы устанавливаете официальный 1Password CLI (
op) и аутентифицируете его — либо токеном сервисного аккаунта (для headless-серверов), либо через интерактивную/десктопную сессию (на вашем ноутбуке). - Вы сопоставляете имена переменных окружения со ссылками
op://в~/.hermes/config.yaml. - При каждом запуске
hermes(или шлюза, или cron-задачи), уже после того как загрузился~/.hermes/.env, Hermes выполняетop readдля каждой ссылки и записывает полученные значения вos.environ. - По умолчанию Hermes переопределяет значения, уже присутствующие в окружении, — так источником истины остаётся 1Password: обновили учётные данные один раз, и каждый процесс Hermes подхватит их при следующем запуске. Установите
override_existing: false, если хотите, чтобы приоритет оставался за.env.
Hermes никогда не аутентифицируется от вашего имени и никогда не скачивает op — он лишь вызывает через shell уже установленный и уже доверенный вами CLI. Если op отсутствует, сессия заблокирована или ссылка указана неверно, Hermes выводит однострочное предупреждение и продолжает работать с теми учётными данными, которые уже были в .env. Запуск он не блокирует ни при каких обстоятельствах.
Аутентификация
op поддерживает два режима, дружественных к неинтерактивному запуску, и Hermes работает с обоими:
- Сервисные аккаунты (рекомендуется для серверов/CI): создайте сервисный аккаунт в 1Password, выдайте ему доступ на чтение к нужному хранилищу и экспортируйте его токен как
OP_SERVICE_ACCOUNT_TOKENв~/.hermes/.env. Сам токен и есть учётные данные — относитесь к нему как к любому другому bearer-токену. - Десктопные / интерактивные сессии (ноутбуки): выполните
op signin(или включите интеграцию с CLI в приложении 1Password). Hermes передаёт ваши переменныеOP_SESSION_*дочернему процессуop. Ключ кэша 1Password строится с учётом этих переменных сессии, поэтому вход в другой аккаунт никогда не отдаст значение, закэшированное под прежней учётной записью.
Токен для начальной загрузки
Когда вы аутентифицируетесь токеном сервисного аккаунта, этот токен сам по себе становится начальными учётными данными, без которых Hermes не сможет разрешить ни одной ссылки op://. Он должен присутствовать в os.environ каждого процесса, который разрешает секреты, — включая cron-задачи (kanban.dispatch_in_gateway: false), вызовы подпроцессов, запуски CLI, агенты macOS launchd и Docker-контейнеры, а не только интерактивный шлюз. Сделать его доступным можно тремя способами, в порядке приоритета:
-
В
~/.hermes/.env(рекомендуется). Командаhermes secrets onepassword setup --token <token>записывает токен в~/.hermes/.env— точно так же, какBWS_ACCESS_TOKENу Bitwarden. Посколькуload_hermes_dotenv()всегда загружает.env, токен становится доступен везде без какой-либо дополнительной настройки. Это самый простой и надёжный вариант. -
В
~/.hermes/.op.env(в.gitignore). Если вы предпочитаете не держать токен сервисного аккаунта в.env— например, чтобы.envможно было закоммитить в приватный репозиторий с дотфайлами, а токен при этом оставался вне контроля версий, — поместите его в~/.hermes/.op.env:echo 'OP_SERVICE_ACCOUNT_TOKEN=ops_...' > ~/.hermes/.op.env chmod 600 ~/.hermes/.op.envHermes автоматически загружает
.op.envпри старте, после.env, и никогда не переопределяет токен, уже присутствующий в окружении..op.envдобавлен в.gitignore, так что токен никогда не попадёт в закоммиченный файл. -
Через
EnvironmentFileв systemd (Linux-шлюз). Если шлюз запущен под systemd, токен можно внедрить прямо в окружение сервиса:[Service] EnvironmentFile=-/home/youruser/.hermes/.op.envТокен, внедрённый таким способом, получает приоритет — Hermes обнаруживает, что
OP_SERVICE_ACCOUNT_TOKENуже установлен, и полностью пропускает загрузку.op.env.
Если токен доступен только через интерактивную оболочку (op signin, экспорт OP_SESSION_* в .bashrc и тому подобное), он не унаследуется cron-задачами или заново созданными подпроцессами: в таких контекстах будет записано предупреждение, а Hermes откатится к тем учётным данным, что уже были в .env. Для любой неинтерактивной нагрузки используйте один из трёх способов выше.
Настройка
1. Установите op и войдите в аккаунт
Следуйте руководству по началу работы с 1Password CLI. Проверьте, что всё работает:
op whoami
2. Включите интеграцию
hermes secrets onepassword setup
Эта команда проверяет, что op доступен в PATH (либо используйте --binary-path), сохраняет настройки аккаунта/токена, проверяет наличие активной сессии и переключает secrets.onepassword.enabled в true. Флаги для неинтерактивного режима:
hermes secrets onepassword setup \
--account my.1password.com \
--token-env OP_SERVICE_ACCOUNT_TOKEN \
--token "$OP_SERVICE_ACCOUNT_TOKEN"
3. Сопоставьте учётные данные
Формат ссылки — op://<vault>/<item>/<field>:
hermes secrets onepassword set OPENAI_API_KEY "op://Private/OpenAI/api key"
hermes secrets onepassword set ANTHROPIC_API_KEY "op://Private/Anthropic/credential"
4. Проверьте и подтвердите
hermes secrets onepassword sync # пробный запуск: разрешает ссылки сейчас и показывает, что было бы применено
hermes secrets onepassword status # конфигурация + бинарник + ссылки + аутентификация
С этого момента каждый вызов hermes разрешает ссылки при старте. При первом применении секретов в рамках процесса вы увидите однострочную сводку в stderr.
CLI
| Команда | Что делает |
|---|---|
hermes secrets onepassword setup | Проверяет op, задаёт аккаунт / переменную окружения токена, включает интеграцию |
hermes secrets onepassword status | Показывает конфигурацию, бинарник, аутентификацию и настроенные ссылки |
hermes secrets onepassword token | Ротация токена сервисного аккаунта: проверяет его через op whoami, затем сохраняет в .env |
hermes secrets onepassword set ENV_VAR "op://…" | Сопоставляет переменную окружения со ссылкой (сохраняется в очищенном и провалидированном виде) |
hermes secrets onepassword remove ENV_VAR | Удаляет сопоставление |
hermes secrets onepassword sync | Пробный запуск: разрешает ссылки сейчас и показывает, что было бы применено |
hermes secrets onepassword sync --apply | Разрешает ссылки и экспортирует их в окружение текущей оболочки |
hermes secrets onepassword disable | Переключает enabled: false; сопоставления остаются на месте |
op и 1password принимаются как псевдонимы для onepassword.
Конфигурация
Значения по умолчанию в ~/.hermes/config.yaml:
secrets:
onepassword:
enabled: false
env:
OPENAI_API_KEY: "op://Private/OpenAI/api key"
ANTHROPIC_API_KEY: "op://Private/Anthropic/credential"
account: ""
service_account_token_env: OP_SERVICE_ACCOUNT_TOKEN
binary_path: ""
cache_ttl_seconds: 300
override_existing: true
| Ключ | По умолчанию | Что делает |
|---|---|---|
enabled | false | Главный переключатель. Пока false, op вообще не вызывается. |
env | {} | Сопоставление имени переменной окружения со ссылкой op://vault/item/field. Записи, у которых имя не является допустимым именем переменной окружения либо значение не является ссылкой op://, пропускаются с предупреждением. |
account | "" | Сокращённое имя аккаунта / адрес для входа, передаётся как op read --account. Пустое значение означает использование аккаунта op по умолчанию. |
service_account_token_env | OP_SERVICE_ACCOUNT_TOKEN | Переменная окружения, из которой Hermes считывает токен сервисного аккаунта. Её значение экспортируется дочернему процессу op под именем OP_SERVICE_ACCOUNT_TOKEN (именно такого имени ожидает op). Оставьте переменную неустановленной, чтобы использовать десктопную/интерактивную сессию. |
binary_path | "" | Абсолютный путь к op. Если задан, используется как есть, а PATH не учитывается вовсе — закрепите это значение, чтобы не полагаться на первый попавшийся op в PATH. |
cache_ttl_seconds | 300 | Как долго переиспользуются разрешённые значения (в процессе и на диске). Установите 0, чтобы отключить оба слоя кэша — тогда значения вообще не будут записываться на диск. |
override_existing | true | Когда true, разрешённые значения перезаписывают всё, что уже есть в окружении (так ротация вступает в силу). Переключите на false, чтобы приоритет оставался за .env / экспортами оболочки; такие ссылки в этом случае пропускаются ещё до вызова op. |
Сценарии сбоев
1Password никогда не блокирует запуск Hermes. Если что-то пошло не так, вы увидите однострочное предупреждение в stderr, а Hermes продолжит работу:
| Симптом | Причина | Как исправить |
|---|---|---|
the op CLI was not found on PATH | op не установлен / отсутствует в PATH | Установите CLI либо задайте secrets.onepassword.binary_path |
op read failed for 'op://…': … | Сессия заблокирована, токен истёк, либо нет доступа к хранилищу | Выполните op signin, запустите hermes secrets onepassword token для ротации токена сервисного аккаунта или откройте сервисному аккаунту доступ |
op read returned an empty value for 'op://…' | Указанное поле существует, но пустое | Исправьте элемент/поле в 1Password (пустое значение никогда не применяется — уже существующая переменная окружения остаётся нетронутой) |
… is not an op:// secret reference | Значение сопоставления не является ссылкой op:// | Переустановите его в правильном формате op://vault/item/field |
op read timed out | Заблокирована сеть либо 1Password отвечает медленно | Проверьте соединение / интеграцию с десктопным приложением |
Предупреждения при запуске теперь включают строку с исправлением, начинающуюся с →, которая точно указывает, какая команда устранит сбой.
Кэширование
Успешные полные выгрузки кэшируются в процессе и на диске, в <hermes_home>/cache/op_cache.json (запись атомарная, права доступа 0600), так что идущие подряд короткоживущие вызовы hermes не запускают op заново для каждой ссылки. Кэш:
- хранит только разрешённые значения секретов — никогда токен сервисного аккаунта или любые сырые данные аутентификации (данные аутентификации превращаются в отпечаток и попадают в ключ кэша);
- инвалидируется при изменении токена, аккаунта, переменных
OP_SESSION_*или набора ссылок; - не записывается, если при выгрузке возникла ошибка хотя бы по одной ссылке, — так временный сбой аутентификации не «замораживается» на весь срок жизни TTL;
- полностью отключается — и чтение, и запись — при
cache_ttl_seconds: 0.
Замечания по безопасности
- Токен сервисного аккаунта 1Password способен прочитать любой секрет, к которому у аккаунта есть доступ. Храните его в
~/.hermes/.env(не вconfig.yaml), а при утечке немедленно отзовите и перевыпустите его в 1Password. - Hermes не даёт разрешённому значению перезаписать саму переменную окружения токена, даже при
override_existing: true. - Дочерний процесс
opполучает минимальное окружение из белого списка (переменные аутентификации/сессии плюсPATH/HOMEи переменные расположения конфигаop—OP_CONFIG_DIR/XDG_CONFIG_HOME), а не копию полногоos.environ, поэтому учётные данные провайдеров, загруженные после dotenv, дочернему процессу целиком не достаются. ЗадайтеOP_CONFIG_DIR, если~/.configнедоступен для записи пользователю Hermes (обычное дело в контейнерах). - Ссылки проверяются на то, что начинаются с
op://, и передаются после разделителя опций--, так что специально сконструированное значение нельзя выдать за флагop.
Когда этим НЕ стоит пользоваться
- Личные однокомпьютерные настройки, где
~/.hermes/.envвполне достаточно. - Изолированные (air-gapped) среды, у которых нет доступа к 1Password.
- CI/CD, где уже настроен собственный механизм внедрения секретов — выбирайте один путь, а не оба сразу.
Хороший сценарий для этой интеграции — парк из нескольких машин, общие dev-серверы, шлюзовые VPS или любой случай, когда нужна централизованная ротация и отзыв секретов сразу для нескольких инсталляций Hermes.