Ключи из переменных окружения и файлов
Помимо хранения секрета в базе данных, запись в хранилище ключей может считывать своё значение во время выполнения задачи из файла на сервере Semaphore или из переменной окружения процесса сервера Semaphore. Это удобно, когда учётные данные уже подготовлены вне Semaphore, например:
- SSH-ключ, смонтированный в контейнер Semaphore как секрет Docker или Kubernetes;
- токен, записываемый на диск агентом (HashiCorp Vault Agent, cert-manager и т. п.) и регулярно ротируемый;
- пароль, внедрённый в окружение контейнера вашим оркестратором.
Semaphore не копирует значение в свою базу данных. Каждый раз, ко гда ключ требуется задаче, сервер заново читает файл или переменную, поэтому ротация учётных данных на диске вступает в силу при следующей задаче.
Файл или переменную читает сервер Semaphore, а не раннер. Если вы используете удалённые раннеры, монтируйте файл на хосте сервера; сервер получает секрет и передаёт его раннеру.
Выбор источника
При создании или редактировании ключа (Хранилище ключей → Новый ключ) в верхней части формы находятся вкладки источника:
| Вкладка | Откуда берётся значение | Что вводить |
|---|---|---|
| Local | База данных Semaphore (в зашифрованном виде) | Логин, пароль или приватный ключ в форме |
| Storage Pro | Внешнее хранилище секретов, например HashiCorp Vault | Хранилище и путь к секрету |
| Env | Переменная окружения процесса сервера Semaphore | Имя переменной, например PROD_SSH_KEY |
| File | Файл на сервере Semaphore | Абсолютный путь к файлу, например /var/lib/semaphore/secrets/prod.json |
При выборе Env или File поля логина, пароля и приватного ключа исчезают. Все учётные данные целиком, включая логин для ключей типа SSH и «Логин с паролем», должны находиться в файле или переменной.
1. Разрешите каталог
В целях безопасности Semaphore читает файлы ключей только из своего каталога секретов. Любой другой путь отклоняется при запуске задачи:
Failed to install inventory: file path must be inside secrets path
Каталог секретов по умолчанию — /tmp/semaphore. Укажите каталог, в котором находятся ваши файлы ключей,
с помощью dirs.secrets в config.json или переменной окружения SEMAPHORE_SECRETS_PATH.
Правила приоритета описаны в разделе Каталог секретов.
Пример Docker Compose, который монтирует каталог хоста и разрешает его:
services:
semaphore:
image: semaphoreui/semaphore:latest
environment:
SEMAPHORE_SECRETS_PATH: /var/lib/semaphore/secrets
volumes:
- /srv/semaphore/secrets:/var/lib/semaphore/secrets:ro
Эквивалентный фрагмент config.json:
{
"dirs": {
"secrets": "/var/lib/semaphore/secrets"
}
}
Правила для пути, вводимого на вкладке File:
- путь должен быть абсолютным (
/var/lib/semaphore/secrets/prod.json, а неprod.json); - путь не должен содержать сегменты
..; - путь должен указывать на расположение внутри каталога секретов (подкаталоги допускаются);
- файл должен быть доступен для чтения пользователю, от имени которого работает Semaphore (в официальном Docker-образе это
semaphore, UID 1001).
Для переменных окружения такого ограничения нет: сервер просто читает переменную с указанным именем из собственного окружения.
2. Подготовьте значение
Содержимое файла (или значение переменной) зависит от типа ключа. Один завершающий перевод строки в конце файла игнорируется; всё остальное используется как есть.
SSH-ключ
Semaphore ожидает JSON-документ, а не «сырой» файл приватного ключа в формате PEM или OpenSSH:
{
"login": "deploy",
"passphrase": "",
"private_key": "-----BEGIN OPENSSH PRIVATE KEY-----\n...\n-----END OPENSSH PRIVATE KEY-----\n"
}
login— имя пользователя SSH, передаётся в Ansible как--user. Оставьте пустым, чтобы решение принимал инвентарь (ansible_user). Для Git-репозиториев пустой логин по умолчанию означаетgit.passphrase— парольная фраза приватного ключа или пустая строка.private_key— приватный ключ, в котором переводы строк закодированы как\n.
Сформируйте обёртку из существующего ключа с помощью jq, который сам позаботится об экранировании:
jq -n --arg login deploy --rawfile key ~/.ssh/id_ed25519 \
'{login: $login, passphrase: "", private_key: $key}' \
> /srv/semaphore/secrets/prod_ssh.json
chmod 0400 /srv/semaphore/secrets/prod_ssh.json
Затем создайте ключ типа SSH, откройте вкладку File и введите /var/lib/semaphore/secrets/prod_ssh.json
(путь таким, каким он виден внутри контейнера).

Указывать на вкладке File «сырой» приватный ключ, например ~/.ssh/id_ed25519, нельзя.
Файл разбирается как JSON, и задача не сможет загрузить инвентарь.
Логин с паролем
Тоже JSON-документ:
{
"login": "svc-ansible",
"password": "s3cr3t"
}
Оставьте login пустым, чтобы использовать ключ как обычный токен или пароль, например как пароль Ansible Vault.
Пример с переменной окружения
Тот же формат JSON применяется и для вкладки Env. В Docker Compose:
services:
semaphore:
image: semaphoreui/semaphore:latest
environment:
PROD_SSH_KEY: '{"login":"deploy","passphrase":"","private_key":"-----BEGIN OPENSSH PRIVATE KEY-----\n...\n-----END OPENSSH PRIVATE KEY-----\n"}'
Создайте ключ типа SSH, выберите вкладку Env и введите PROD_SSH_KEY в качестве имени переменной.
Переменные окружения видны каждому процессу в контейнере и часто попадают в метаданные и логи оркестратора. По возможности предпочитайте вкладку File со смонтированным секретом.
Устранение неполадок
| Ошибка | Причина | Решение |
|---|---|---|
file path must be absolute | Введён относительный путь | Введите полный путь, начинающийся с / |
file path must not contain traversal segments | Путь содержит .. | Введите путь без таких сегментов |
file path must be inside secrets path | Файл находится вне dirs.secrets | Укажите в SEMAPHORE_SECRETS_PATH каталог файла или переместите файл |
no such file or directory | Путь неверен или не смонтирован в контейнер | Проверьте монтирование тома и используйте путь внутри контейнера |
permission denied | Процесс Semaphore не может прочитать файл | Исправьте владельца или права доступа файла |
invalid character '-' looking for beginning of value | Вместо JSON-обёртки указан «сырой» приватный ключ | Оберните ключ в JSON, как показано выше |