Работа в CLI
Обзор
С помощью консольного клиента tuna можно получать секреты, автоматически конфигурировать текущую среду или передавать конфигурацию в env нужного приложения. Кроме того, из консоли доступно управление самой структурой — проектами, окружениями, конфигурациями и сервисными ключами.
| Команды | Для чего |
|---|---|
list, get, set, delete, upload | Чтение и изменение секретов в конфигурации |
run | Запуск приложения с секретами в переменных окружения |
download, substitute | Выгрузка секретов в файл или шаблон |
setup, open | Привязка каталога к конфигурации, открытие в браузере |
projects, environments, configs | Управление структурой и сервисными ключами |
Для получения секретов через консольное приложение tuna или API необходим API-ключ пользователя или Сервисный ключ конфигурации. При локальной разработке удобнее использовать глобальные API-ключи пользователя, но для работы в CI/CD, Production и других общих средах мы настоятельно рекомендуем использовать Сервисный ключ конфигурации.
Почему tuna secrets лучше direnv при локальной разработке?
direnv - прекрасная утилита для локальной конфигурации, но она всё таки заставляет следить за локальным файлом .env и если на Production появились новые переменные, вы можете не сразу узнать об этом и потратить часы на бессмысленную отладку. В tuna secrets предусмотрена автоматическая синхронизация секретов, что значительно упрощает этот процесс.
Почему tuna secrets лучше Gitlab/Github/Bitbucket Variables?
На самом деле причина тут та же, что и с direnv. Например, у вас есть специальный проект предназначенный для сборки и публикации приложения с помощью goreleaser и он может требовать множество ключей и токенов для разных внешних интеграций, при этом для разных окружений и использовать для этого Gitlab/Github/Bitbucket Variables неудобно, а ещё неудобнее следить за этим, плюс сложность в разграничении прав. В tuna secrets доступ к окружениям регулируется RBAC и вы можете точечно распределять доступ только нужным людям/роботам/скриптам. А обновив секрет или добавив новый, он сразу начнёт работать в CI.
Авторизация
Для доступа к секретам понадобится Сервисный ключ определённой конфигурации или пользовательский API-ключ. Его можно передать через флаг --api-key, переменную окружения TUNA_API_KEY или сохранить в конфиг файл tuna config save-api-key <your-key>
Ключи различаются не только областью действия, но и набором доступных команд:
| Ключ | Что можно |
|---|---|
Сервисный ключ конфигурации (tst_) | Читать секреты своей конфигурации: run, download, list, get. С доступом write — ещё set, delete и upload в ту же конфигурацию |
Пользовательский API-ключ (tak_) | Всё то же плюс управление структурой: projects, environments, configs и выпуск сервисных ключей |
Обращение сервисным ключом к чужой конфигурации возвращает 403, а к командам управления структурой — 401. Поэтому в CI/CD держите сервисный ключ конфигурации, а проекты и конфигурации заводите пользовательским ключом.
Проект и конфигурация
Почти каждая команда работает в контексте проекта и конфигурации. Их можно задать тремя способами, в порядке приоритета:
- флагами
--project(-p) и--config(-c); - переменными окружения
TUNA_SECRETS_PROJECTиTUNA_SECRETS_CONFIG; - привязкой каталога к конфигурации — командой
setup.
Флаг --scope (по умолчанию .) указывает, для какого каталога брать привязку. Подробнее — в разделе про setup.
tuna secrets list --project api-php --config stage
tuna secrets list -p api-php -c stage
tuna secrets list # проект и конфигурация из привязки каталога
Формат вывода
Клиент разделяет данные и служебные сообщения:
- данные идут в
stdout; - статусные сообщения, предупреждения и ошибки — в
stderr.
Поэтому вывод любой команды можно перенаправлять в файл и передавать по конвейеру, не боясь поймать в него лишние строки:
tuna secrets list --only-names > names.txt
tuna secrets list | grep API_
Таблицы
Человеку команды печатают таблицу без рамок: заголовки капсом, пустая ячейка — -, даты в формате RFC3339 в вашей локальной временной зоне. Такую таблицу удобно резать awk и она не разъезжается в узком терминале.
$ tuna secrets list
NAME VALUE TYPE NOTE UPDATED
JKLNRFEDUILNNIF hmac:cea41705 string - 2026-09-17T11:56:51+04:00
Отпечатки значений
В колонке VALUE по умолчанию печатается не значение секрета, а его отпечаток вида hmac:cea41705 — HMAC-SHA256 от значения на ключе команды.
Одинаковые значения дают одинаковый отпечаток, а из отпечатка нельзя восстановить значение. Поэтому отпечатки можно сравнивать между конфигурациями («в stage и prod действительно разные пароли к базе?») и печатать в логи CI, не раскрывая секрет.
Так выглядит сравнение двух окружений: API_TOKEN и API_ENABLED в dev и prod совпадают, API_DB и LOG_LEVEL различаются — и всё это видно, не раскрывая ни одного значения.
Настоящие значения показывают list --values и get:
$ tuna secrets list --values
NAME VALUE TYPE NOTE UPDATED
JKLNRFEDUILNNIF vcTpFuptQLtJ0beoTQA13rHNeAaGNtjs string - 2026-09-17T11:56:51+04:00
JSON и YAML
Флаг -o (--output) со значением json или yaml есть у всех подкоманд tuna secrets, включая команды записи: set, delete, upload, create, rename, lock и остальные печатают в машинном виде то, что получилось в результате.
$ tuna secrets set FOO=bar2 -o json
{
"FOO": {
"id": 42,
"name": "FOO",
"value": "bar2",
"fingerprint": "hmac:b274b135",
"value_type": "string",
"visibility": "masked",
"override": false,
"note": "",
"can_be_converged": false,
"can_be_promoted": false,
"reminder": null,
"created_at": "2026-09-18T06:43:10Z",
"updated_at": "2026-09-18T06:43:10Z"
}
}
В машинном выводе секрет приходит со всеми полями и с настоящим значением — в отличие от таблицы, где по умолчанию стоит отпечаток. Помните об этом, перенаправляя такой вывод в файл или в лог. Исключение — секрет с видимостью restricted: сервер не отдаёт ни значение, ни отпечаток, поэтому оба поля приходят пустыми.
Пустой результат — это всегда валидный [] или {}, а не пустой вывод, так что парсер в скрипте не придётся защищать отдельной проверкой.
Сырые значения для скриптов
Флаг --plain у команд get и configs tokens create печатает только само значение, без перевода строки в конце. Это удобно для подстановки в другую команду:
$ docker login -u robot -p "$(tuna secrets get REGISTRY_PASSWORD --plain)" registry.example.com
Ошибки
Ошибки печатаются в stderr, код возврата в этом случае — 1:
$ tuna secrets list -p test -c nonexistent
Error: Failed to list secrets in test/nonexistent: Config does not exist
Code: NotFound
Request ID: 83d3961b1452ab3c7174965acbfbd711
С -o json ошибка тоже становится JSON — его можно разобрать и, например, приложить request_id к обращению в поддержку:
{"code":"NotFound","error":"Failed to list secrets in test/nonexistent: Config does not exist","request_id":"83d3961b1452ab3c7174965acbfbd711"}
Работа с секретами
List
Список секретов конфигурации. Алиас — ls.
| Флаг | Описание |
|---|---|
--values | Показывать значения вместо отпечатков |
--only-names | Только имена, одной колонкой |
$ tuna secrets list
NAME VALUE TYPE NOTE UPDATED
JKLNRFEDUILNNIF hmac:cea41705 string - 2026-09-17T11:56:51+04:00
В записи видно, как отпечаток LOG_LEVEL меняется вместе со значением, а list --values показывает уже само значение:
Get
Значения одного или нескольких секретов. В отличие от list, get показывает значения сразу.
| Флаг | Описание |
|---|---|
--plain | Только значения, без таблицы и без перевода строки в конце |
$ tuna secrets get API_TOKEN API_DB
NAME VALUE TYPE NOTE UPDATED
API_DB postgres://postgres@db:5432/api string - 2026-09-17T11:56:51+04:00
API_TOKEN PwZayIp9NpNntNYd2jkAAQgViM6dXdIm string - 2026-09-17T11:56:51+04:00
Если запрошенного секрета в конфигурации нет, команда завершится ошибкой и не напечатает ничего — так опечатка в имени не превратится в пустую переменную.
Set
Запись одного или нескольких секретов.
| Флаг | Описание |
|---|---|
--type | Тип значения: string, json, boolean, integer, decimal, email, url, yaml, xml, date, datetime |
--note | Комментарий к секрету |
--visibility | Видимость значения в веб-интерфейсе: masked или unmasked |
--no-interactive | Не спрашивать значение интерактивно, а завершиться ошибкой |
Значение можно передать четырьмя способами:
$ tuna secrets set API_TOKEN=PwZayIp9NpNntNYd2jkAAQgViM6dXdIm # inline
$ tuna secrets set API_TOKEN PwZayIp9NpNntNYd2jkAAQgViM6dXdIm # отдельным аргументом
$ openssl rand -hex 32 | tuna secrets set API_TOKEN # из stdin
$ tuna secrets set API_TOKEN # интерактивно
Интерактивный ввод включается только для одного имени без =, когда в stdin ничего не пришло; с --no-interactive вместо него будет ошибка. Ввести можно и многострочное значение, например приватный ключ: ввод заканчивается пустой строкой, а следом строкой с одной точкой.
За один вызов можно записать несколько секретов, флаги --type, --note и --visibility применяются ко всем сразу:
$ tuna secrets set API_ENABLED=true API_DEBUG=false --type boolean
В ответ команда печатает записанные секреты:
$ tuna secrets set FOO=bar
NAME VALUE TYPE NOTE UPDATED
FOO hmac:bd154f88 string - 2026-09-18T10:43:10+04:00
Флаг --visibility принимает и значение restricted, но пользоваться им сейчас не стоит: сервер перестаёт отдавать значение такого секрета вообще всем — в том числе tuna secrets run, — а tuna secrets download для всей конфигурации начинает отвечать 403. Вернуть значение после этого нельзя.
Если кто-то изменил тот же секрет между чтением и записью, команда сообщит об этом и завершится ошибкой, не затирая чужое изменение. В этом случае достаточно повторить вызов.
Delete
Удаление одного или нескольких секретов. Алиас — rm.
$ tuna secrets delete FOO
NAME VALUE TYPE NOTE UPDATED
API_TOKEN hmac:3e96898b string - 2026-09-18T10:43:09+04:00
DB_HOST hmac:829a119e string - 2026-09-18T10:43:09+04:00
DB_PORT hmac:620ef1fa string - 2026-09-18T10:43:09+04:00
Команда печатает конфигурацию в том виде, в каком она осталась после удаления.
Если хотя бы одного из перечисленных секретов в конфигурации нет, не удаляется ничего.
Upload
Загрузка секретов из файла .env или .json.
$ tuna secrets upload .env
NAME VALUE TYPE NOTE UPDATED
API_TOKEN hmac:1ea77bae string - 2026-09-18T10:43:11+04:00
DB_HOST hmac:829a119e string - 2026-09-18T10:43:09+04:00
DB_PORT hmac:620ef1fa string - 2026-09-18T10:43:09+04:00
REDIS_URL hmac:3df78001 string - 2026-09-18T10:43:11+04:00
Как и delete, команда печатает конфигурацию целиком — уже после слияния.
Содержимое файла дополняет конфигурацию: секреты с совпадающими именами перезаписываются, остальные остаются на месте. Полной заменой конфигурации upload не является.
Запуск приложений
Команда run запускает ваше приложение, передавая ему секреты в переменных окружения. Сами секреты при этом не попадают ни в файл, ни в историю команд.
tuna secrets run -- yarn start
Что передаётся процессу
| Флаг | Описание |
|---|---|
--command | Выполнить строку через оболочку: --command "echo $HOME && env" |
--only-secrets | Передать только секреты и минимум системных переменных (PATH, HOME, PS1, USER, SHELL, TMPDIR) |
--preserve-env | Список имён через запятую, для которых приоритет у уже существующего значения в окружении; без значения флаг означает true — сохранить все |
--name-transformer | Преобразовать имена: upper-camel, camel, lower-snake, lower-kebab, tf-var, dotnet-env |
--forward-signals | Пробрасывать сигналы дочернему процессу; по умолчанию включено, когда stdout не терминал |
tuna возвращает код выхода дочернего процесса, поэтому обёртку можно ставить в CI-джобу, не ломая её логику.
$ tuna secrets run --project api-php --config stage -- yarn start
$ tuna secrets run --scope /home/user/src/api -- yarn start
$ tuna secrets run --only-secrets -- env
Автоматический перезапуск при изменении секрета
Если передать флаг --watch, клиент подписывается на изменения конфигурации и перезапускает процесс с новыми значениями.
tuna secrets run --watch -- yarn start
Перезапуск происходит не мгновенно: сервер сверяет конфигурацию раз в 30 секунд и только после этого присылает событие. Столько же может пройти между изменением секрета и рестартом приложения — если пару десятков секунд ничего не происходит, это нормальная работа, а не сломанный --watch.
Момент перезапуска видно в stderr:
Secrets changed; restarting process
В записи приложение печатает значение раз в пять секунд: сначала идёт старое, затем строка о перезапуске, затем новое.
Лучше всего работу продемонстрирует данное видео:
- VK Видео
- YouTube
В видео мы запускаем вот такую команду:
tuna secrets run --watch -- bash -c 'while true; do echo -n "$(date -Is) [pid: $$] ==> " ; echo ${API_TOKEN} ; sleep 1; done'
Секреты файлом вместо переменных окружения
Некоторые приложения читают конфигурацию только из файла. Флаг --mount создаёт временный именованный канал (named pipe), кладёт в него секреты и передаёт путь дочернему процессу в переменной TUNA_SECRETS_MOUNT_PATH. В переменные окружения секреты в этом режиме не попадают.
Канал создаётся по указанному пути с правами 0600, но значения живут только в памяти клиента: каждое открытие файла на чтение получает полный снимок и EOF, записанного файла с секретами на диске не появляется. После выхода процесса канал удаляется.
$ tuna secrets run --mount ./secrets.json --mount-format json -- ./app --config "$TUNA_SECRETS_MOUNT_PATH"
| Флаг | Описание |
|---|---|
--mount | Путь к создаваемому каналу |
--mount-format | Формат содержимого: env (по умолчанию), env-no-quotes, json, yaml, docker |
--mount-template | Файл-шаблон, который рендерится в канал вместо фиксированного формата |
--mount-max-reads | Сколько раз файл можно прочитать, 0 — без ограничения |
Флаг --mount-max-reads N удаляет канал после N чтений — удобно, когда секреты читает ровно один процесс при старте.
Именованные каналы не поддерживаются в Windows, там --mount работать не будет.
Если клиент убить сигналом SIGKILL, канал останется на диске и следующий запуск откажется стартовать: mount path already exists. Такой файл нужно удалить вручную.
Офлайн-режим
run умеет хранить последние успешно полученные секреты в зашифрованном файле и использовать их, когда API недоступен — приложение не встанет из-за проблем с сетью.
| Флаг | Описание |
|---|---|
--fallback | Путь к файлу; по умолчанию вычисляется из адреса API, ключа, проекта и конфигурации |
--fallback-only, --offline | Читать только файл, не обращаясь к API |
--fallback-readonly | Использовать файл, но не обновлять его |
--no-fallback | Не читать и не писать файл |
--fallback-passphrase | Парольная фраза; по умолчанию вычисляется из ключа, проекта и конфигурации. Также читается из TUNA_SECRETS_FALLBACK_PASSPHRASE |
Если API ответил, что доступ запрещён или конфигурация не найдена (401, 403, 404), файл удаляется: устаревшая копия секретов после отзыва доступа опаснее, чем остановка приложения. При сетевых ошибках и 5xx клиент, наоборот, читает файл и печатает предупреждение.
Парольная фраза по умолчанию выводится из API-ключа, проекта и конфигурации — значит, после ротации ключа старый файл расшифровать уже нельзя. Если файл должен пережить ротацию, задайте фразу явно: флаг --fallback-passphrase имеет приоритет над переменной TUNA_SECRETS_FALLBACK_PASSPHRASE.
Старые файлы можно убрать командой run clean:
$ tuna secrets run clean --dry-run
Would delete 0 fallback file(s)
$ tuna secrets run clean --max-age 720h
$ tuna secrets run clean --all
По умолчанию удаляются файлы старше 14 дней (--max-age 336h).
Первый запуск ходит в API и попутно пишет файл, второй с --offline обходится без сети:
Выгрузка секретов
Download
Получение секретов конфигурации в файл или на стандартный вывод.
tuna secrets download
| Флаг | Описание |
|---|---|
--format | json (по умолчанию), yaml, env, env-no-quotes, docker |
--no-file | Печатать на стандартный вывод вместо записи в файл |
--name-transformer | Преобразовать имена: upper-camel, camel, lower-snake, lower-kebab, tf-var, dotnet, dotnet-env |
--scope | Каталог, привязку которого использовать |
Настройки можно задать и переменными окружения.
Передача проекта и конфигурации
Флаги --project и --config принимают на вход имя (алиас) проекта и конфигурации.
По умолчанию конфигурация сохранится в файл tuna.json в текущем каталоге.
$ tuna secrets download --project api-php --config stage
Downloaded secrets to tuna.json
$ cat tuna.json
{
"API_DB": "postgres://postgres:postgres@localhost:5432/postgres",
"API_TOKEN": "PwZayIp9NpNntNYd2jkAAQgViM6dXdIm"
}
Передача формата
Можно указать, в каком формате вам нужен файл.
- json
- yaml
- env
$ tuna secrets download --project api-php --config stage --format json
Downloaded secrets to tuna.json
$ cat tuna.json
{
"API_DB": "postgres://postgres:postgres@localhost:5432/postgres",
"API_TOKEN": "PwZayIp9NpNntNYd2jkAAQgViM6dXdIm"
}
$ tuna secrets download --project api-php --config stage --format yaml
Downloaded secrets to tuna.yaml
$ cat tuna.yaml
API_DB: postgres://postgres:postgres@localhost:5432/postgres
API_TOKEN: PwZayIp9NpNntNYd2jkAAQgViM6dXdIm
$ tuna secrets download --project api-php --config stage --format env
Downloaded secrets to tuna.env
$ cat tuna.env
API_DB="postgres://postgres:postgres@localhost:5432/postgres"
API_TOKEN="PwZayIp9NpNntNYd2jkAAQgViM6dXdIm"
Неизвестный формат — ошибка, а не молчаливая выгрузка «чего-нибудь».
Формат docker
Формат docker печатает пары KEY=value без кавычек — то же, что env-no-quotes. Такой файл подходит для docker run --env-file, где кавычки стали бы частью значения:
$ tuna secrets download --format docker --no-file
API_TOKEN=s3cr3t-token-value
DB_HOST=db.internal
DB_PORT=5432
$ tuna secrets download --format docker tuna.env
$ docker run --env-file tuna.env myapp
Преобразование имён
Флаг --name-transformer меняет стиль имён — полезно, когда потребитель секретов ждёт не SCREAMING_SNAKE_CASE:
$ tuna secrets download --no-file --format json --name-transformer camel
{
"apiDb": "postgres://postgres:postgres@localhost:5432/postgres",
"apiToken": "PwZayIp9NpNntNYd2jkAAQgViM6dXdIm"
}
Трансформер dotnet есть только у download: он даёт имена вида Section:Key, а двоеточие в имени переменной окружения недопустимо. Поэтому у tuna secrets run его нет — для .NET там dotnet-env с двойным подчёркиванием.
Свой файл
В команде можно передать путь и определить свой файл.
$ tuna secrets download --project api-php --config stage foo-bar.json
Downloaded secrets to foo-bar.json
Вывод в stdout
Флаг --no-file отключает запись в файл и печатает конфигурацию на стандартный вывод.
$ tuna secrets download --project api-php --config stage --no-file --format env
API_TOKEN="PwZayIp9NpNntNYd2jkAAQgViM6dXdIm"
API_DB="postgres://postgres:postgres@localhost:5432/postgres"
Substitute
Рендер файла-шаблона со значениями секретов. Подходит для конфигов, у которых свой формат: nginx.conf, application.yml, .ini и подобных.
Шаблон — это text/template Go, данными служит набор пар имя-значение:
database_url = {{ .DB_URL }}
api_key = {{ index . "API-KEY" }}
extra = {{ index . "FEATURES" | fromjson | tojson }}
$ tuna secrets substitute config.tmpl --output config.ini
$ tuna secrets substitute config.tmpl | kubectl apply -f -
Без --output результат печатается на стандартный вывод. С --output файл пишется атомарно и с правами 0600.
Обращение вида {{ index . "DB-NAME" }} нужно для имён, которые не являются идентификаторами Go. Кроме стандартных функций доступны tojson и fromjson.
Если в шаблоне упомянут секрет, которого нет в конфигурации, команда не подставляет пустое значение, а завершается с кодом 1. В сообщении видно и позицию в шаблоне, и само имя:
$ tuna secrets substitute app.conf.tpl
Error: Failed to render template: template: secrets:2:11: executing "secrets" at <.API_TOKN>: map has no entry for key "API_TOKN"
По той же причине условие {{ if .DEBUG }} для необязательного секрета тоже будет ошибкой. Пишите его через index — на отсутствующем ключе он возвращает пустую строку:
{{ if index . "DEBUG" }}debug{{ else }}quiet{{ end }}
Так же строго рендерится шаблон в tuna secrets run --mount-template — движок там общий.
Настройка окружения
Setup
Привязка каталога к проекту и конфигурации — после неё --project и --config можно не передавать. Привязки хранятся в конфиг файле клиента.
tuna secrets setup
Без флагов команда предложит выбрать проект и конфигурацию из списка.
Настройка без меню
Как и в случае с download, в setup можно передать --project и --config:
$ tuna secrets setup --project api-php --config stage
SCOPE PROJECT CONFIG
/home/user/src/api api-php stage
Флаг --no-interactive (или переменная TUNA_SECRETS_NO_INTERACTIVE) запрещает спрашивать недостающие значения — команда завершится ошибкой. Это то, что нужно в CI и в скриптах установки.
Настройка каталога, отличного от текущего
Если вы хотите настроить не текущий каталог, передайте нужный путь во флаг --scope:
tuna secrets setup --project api-php --config stage --scope /home/user/src/api
Файл tuna.yaml в репозитории
Чтобы новому разработчику хватило одной команды tuna secrets setup, положите в корень репозитория файл tuna.yaml:
setup:
- project: api-php
config: dev
Для монорепозитория можно описать несколько привязок, у каждой записи свой path относительно корня:
setup:
- project: api-php
config: dev
path: backend
- project: ui
config: dev
path: frontend
Файл читается только тогда, когда проект и конфигурация не заданы флагами или переменными окружения, и только в каталоге --scope — вверх по дереву клиент не поднимается.
Как выглядит привязка
Результат setup попадает в конфиг файл клиента:
$ cat ~/.config/tuna/tuna.yml
secrets:
scoped:
/home/user/src/api:
project: api-php
config: stage
Находясь в /home/user/src/api, проект и конфигурацию передавать не нужно. Из другого каталога — либо передайте их явно, либо укажите --scope:
$ pwd
/home/user/src/worker
$ tuna secrets download --format env --no-file --scope /home/user/src/api
API_TOKEN="PwZayIp9NpNntNYd2jkAAQgViM6dXdIm"
API_DB="postgres://postgres:postgres@localhost:5432/postgres"
Open
Открыть текущую конфигурацию в веб-интерфейсе:
tuna secrets open
Если браузер открыть не удалось, команда напечатает ссылку. С -o json она печатает только адрес.
Управление структурой
Проекты, окружения и конфигурации можно создавать и менять прямо из консоли — те же действия, что и в веб-интерфейсе.
Проекты
$ tuna secrets projects
SLUG NAME DESCRIPTION CONFIGS SECRETS CREATED
test test - 5 12 2026-09-17T11:20:40+04:00
| Команда | Описание |
|---|---|
projects | Список проектов |
projects get [project] | Информация о проекте |
projects create [name] | Создать проект: --slug, --description |
projects update [project] | Изменить: --name, --slug, --description |
projects delete [project] | Удалить; без аргумента предложит выбрать из списка |
$ tuna secrets projects create "API PHP" --slug api-php --description "Основное API"
Окружения
$ tuna secrets environments --project api-php
SLUG NAME PERSONAL CONFIGS CREATED
dev Development yes 2026-09-18T10:43:08+04:00
stage Staging no 2026-09-18T10:43:09+04:00
prod Production no 2026-09-18T10:43:09+04:00
| Команда | Описание |
|---|---|
environments | Список окружений проекта |
environments get ENVIRONMENT | Информация об окружении |
environments create NAME | Создать: --slug, --personal-configs |
environments rename ENVIRONMENT | Переименовать: --name, --slug |
environments delete ENVIRONMENT | Удалить окружение |
Алиасы команды — envs и environment.
Конфигурации
$ tuna secrets configs --project api-php
SLUG ENVIRONMENT TYPE LOCKED CREATED LAST FETCH
dev dev original yes 2026-09-17T11:20:40+04:00 2026-09-17T16:20:35+04:00
prod/fghd prod duplicate no 2026-09-17T11:55:14+04:00 2026-09-17T16:17:42+04:00
Колонка TYPE различает основную конфигурацию окружения (original) и её копию (duplicate), LAST FETCH показывает, когда секреты забирали в последний раз — по ней видно, пользуется ли кто-нибудь конфигурацией.
| Команда | Описание |
|---|---|
configs | Список конфигураций проекта, фильтр — --environment |
configs get [config] | Информация о конфигурации |
configs create [name] | Создать в окружении: --environment, --locked |
configs clone [config] | Скопировать внутри окружения: --name |
configs rename [config] | Переименовать: --name |
configs lock [config] | Запретить изменения |
configs unlock [config] | Снять запрет |
configs delete [config] | Удалить конфигурацию |
configs logs | История изменений: --page, --page-size |
История изменений
$ tuna secrets configs logs
TIME ACTOR ACTION SECRET
2026-09-17T16:20:37+04:00 Женя secret_delete CLAUDE_ML
История изменений конфигурации сейчас доступна только за последние трое суток — более старые записи удаляются автоматически. Это текущее ограничение, а не настройка тарифа.
Сервисные ключи
Сервисный ключ ограничен одной конфигурацией — это то, что стоит использовать в CI/CD вместо пользовательского API-ключа.
| Команда | Описание |
|---|---|
configs tokens | Список ключей конфигурации |
configs tokens create | Выпустить ключ: --description, --access, --max-age, --plain |
configs tokens revoke ID | Отозвать ключ по идентификатору |
Флаг create | Описание |
|---|---|
--access | read (по умолчанию) или write |
--max-age | Срок жизни в формате Go-длительности, например 720h; без него ключ бессрочный |
--description | Описание, по которому ключ потом можно узнать в списке |
--plain | Напечатать только сам ключ, без таблицы и без перевода строки |
Значение ключа показывается один раз — при создании:
$ tuna secrets configs tokens create --description ci --access read --max-age 720h
Save this token - it will not be shown again
ID DESCRIPTION ACCESS EXPIRES CREATED TOKEN
5 ci read 2026-10-18T10:43:31+04:00 2026-09-18T10:43:31+04:00 tst_...
$ tuna secrets configs tokens
ID DESCRIPTION ACCESS EXPIRES CREATED
6 ci-plain read 2026-10-18T10:43:31+04:00 2026-09-18T10:43:31+04:00
5 ci read 2026-10-18T10:43:31+04:00 2026-09-18T10:43:31+04:00
Предупреждение «Save this token» идёт в stderr, поэтому в скрипте ключ можно забрать прямо в переменную:
$ TUNA_API_KEY=$(tuna secrets configs tokens create --description "gitlab ci" --access read --max-age 720h --plain)