СейчасЦелевая архитектура
- Целевая архитектура
- Чеклист быстрой проверки
- Что делает каждый инструмент
- mise фиксирует окружение и команды
- SOPS шифрует значения конфигурации
- age задаёт получателей и identities
- Установка инструментов
- Передача секретов дочернему процессу
- Разделение доступа по контурам
- Эталонный шаблон проекта
- Проверка результата
- Полезные сценарии
- Локальная разработка и подключение нового участника
- Dev, staging и sandbox
- CI/CD
- Безопасные проверочные запуски
- Разделение доступов по контурам
- Что не хранить в project-level сейфе
- С чего начать пилот
- Официальные ресурсы
- Следующий шаг
- Связанные материалы
Связка mise + SOPS + age помогает команде воспроизводимо запускать проект и хранить секреты локального и предбоевого контуров (dev и staging) в репозитории в зашифрованном виде. mise описывает инструменты и команды, SOPS шифрует конфигурацию, а age задаёт публичные получатели шифрования (recipients), для которых соответствующие приватные identities могут расшифровать файл.
Материал сверён с официальной документацией 7 сентября 2026 года. Примеры основаны на документации и требуют проверки в вашем проекте перед рабочим использованием.
Целевая архитектура
В репозитории находятся:
mise.tomlс инструментами, переменными окружения и задачами;.sops.yamlс правилами выбора recipients;- зашифрованные конфиги отдельных контуров;
- публичные age-recipients, если команда хранит их отдельным списком.
Вне репозитория остаются:
- приватные age-identities разработчиков, то есть секретные ключи;
- identity CI, переданная через защищённое хранилище CI-пайплайна;
- production-секреты, если политика команды требует отдельного хранилища секретов на этапе выполнения;
- глобальные административные токены и личные ключи.
Роли разделены следующим образом:
miseописывает инструменты, окружение и команды проекта;- SOPS шифрует конечные значения в YAML, JSON, ENV и INI и хранит MAC, который используется для проверки целостности значений и структуры;
- age задаёт публичные recipients для шифрования и приватные identities для расшифровки.
Одна команда mise run dev может запускать SOPS. SOPS передаёт расшифрованные значения только дочернему процессу, которому они нужны.
Чеклист быстрой проверки
mise.toml с выбранными версиями инструментов и задачами.mise tasks показывает понятные команды dev, test, build и проверочный запуск.dev, staging, sandbox и другим необходимым средам.Что делает каждый инструмент
mise фиксирует окружение и команды
Проектный mise.toml может содержать инструменты, переменные окружения и задачи. Конфигурация проекта и локальные файлы переопределяют глобальные и родительские настройки, при этом правила объединения зависят от конкретного раздела конфигурации.
Основной файл называется mise.toml. Вариант .mise.toml также распознаётся, однако актуальная документация рекомендует начинать с mise.toml в корне проекта.
Минимальный пример:
[tools]
node = "22" # выберите версию, на которой тестируется проект
pnpm = "9" # пример запроса версии менеджера пакетов
python = "3.12" # пример версии Python
[env]
PROJECT_ENV = "dev"
[tasks.hello]
run = "node --eval 'console.log(process.env.PROJECT_ENV)'"Проверка:
mise install
mise run hellomise install установит объявленные инструменты при необходимости, а команда выведет dev.
SOPS шифрует значения конфигурации
SOPS обрабатывает YAML, JSON, ENV и INI как деревья данных и шифрует конечные значения. Имена ключей остаются открытыми, поэтому структура и изменения файла читаются в Git. MAC в метаданных SOPS помогает обнаружить изменение значений или структуры.
Расширение файла влияет на выбор формата. После шифрования лучше сохранять исходное расширение. Если расширение изменено, при расшифровке укажите --input-type. При работе через stdin при необходимости задайте --input-type и --output-type явно.
Не используйте верхнеуровневые массивы в YAML и JSON: SOPS должен добавить ключ sops с метаданными на том же уровне. YAML anchors также не поддерживаются.
age задаёт получателей и identities
Команда age-keygen создаёт identity-файл:
age-keygen -o key.txtКоманда печатает публичный recipient вида age1..., а identity-файл содержит секретный ключ вида AGE-SECRET-KEY-1.... Публичный recipient можно использовать в конфигурации проекта. Приватную identity храните вне репозитория и передавайте SOPS через защищённый механизм, поддерживаемый вашей средой.
Несколько recipients позволяют владельцам соответствующих identities расшифровать один и тот же файл. Скомпрометированная identity требует отдельной процедуры отзыва доступа.
Установка инструментов
На macOS и Linux с Homebrew age устанавливается командой:
brew install ageДля mise и SOPS используйте способы установки из их официальной документации либо доступные пакеты вашей платформы. После установки проверьте доступность CLI:
mise --version
sops --version
age --versionНе фиксируйте в командном шаблоне путь к приватной identity, пока не выбрали единый способ хранения для локальной разработки и CI.
Передача секретов дочернему процессу
Официально документированный способ SOPS — exec-env. Команда расшифровывает файл, помещает значения в окружение дочернего процесса и не записывает открытый конфиг на диск.
[tasks.dev]
description = "Локальный запуск с dev-секретами"
run = "sops exec-env secrets/dev.sops.yaml 'pnpm dev'"
[tasks."sync:dry"]
description = "Проверочный запуск синхронизации без записи"
run = "sops exec-env secrets/dev.sops.yaml 'pnpm sync --dry-run'"Для конфигурации, которую передаёте через exec-env, используйте верхнеуровневые ключи с допустимыми именами переменных окружения, например:
API_URL: https://sandbox.example.invalid
CHECK_VALUE: replace-before-encryptionreplace-before-encryption здесь является безопасной заглушкой. Реальное значение добавляют перед шифрованием и не сохраняют в открытом виде.
Если приложению нужен файл, SOPS предоставляет exec-file. На Unix-подобных системах по умолчанию используется FIFO, то есть именованный канал: открытые данные не записываются на диск, а дочерний процесс читает их через этот канал. Параметр --no-fifo создаёт временный файл и удаляет его после завершения процесса; этот режим требует отдельной оценки риска.
--no-fifo означает появление открытого временного файла. Убедитесь, что права доступа, каталог временных файлов и очистка после завершения соответствуют политике проекта.Разделение доступа по контурам
Файл должен называться .sops.yaml, а не .sops.yml. Если не задан параметр --config, SOPS ищет .sops.yaml в текущем каталоге и родительских каталогах и использует первый найденный файл.
Пример правил для двух контуров:
creation_rules:
- path_regex: secrets/dev\.sops\.yaml$
age:
- age1developer-recipient-placeholder # замените на полный публичный recipient
- age1ci-recipient-placeholder # замените на полный публичный recipient
- path_regex: secrets/staging\.sops\.yaml$
age:
- age1lead-recipient-placeholder # замените на полный публичный recipient
- age1ci-recipient-placeholder # замените на полный публичный recipientПоле age принимает список публичных ключей. Любой recipient из подходящего правила сможет открыть файл при наличии соответствующей приватной identity.
Разделение по контурам уменьшает область доступа:
- разработчик получает доступ к
devилиsandbox; - CI получает только контуры, необходимые его задачам;
- production использует отдельный процесс выдачи и ротации доступа.
Эталонный шаблон проекта
project/
├── mise.toml
├── .sops.yaml
├── secrets/
│ ├── dev.sops.yaml
│ └── staging.sops.yaml
└── age-keys/
├── team.pub # только публичные recipients
└── ci.pub # только публичный recipient CIСобранный mise.toml:
min_version = "2026.1.0" # жёсткий минимум версии mise; выберите подходящую версию
[tools]
node = "22" # выберите версию, на которой тестируется проект
pnpm = "9" # пример запроса версии менеджера пакетов
python = "3.12" # пример версии Python
[env]
PROJECT_ENV = "dev"
[tasks.dev]
description = "Локальный запуск с зашифрованными dev-секретами"
run = "sops exec-env secrets/dev.sops.yaml 'pnpm dev'"
[tasks."sync:dry"]
description = "Проверочный запуск без записи"
run = "sops exec-env secrets/dev.sops.yaml 'pnpm sync --dry-run'" # если проект поддерживает этот флаг
[tasks.smoke]
description = "Smoke-тесты после развёртывания"
run = "pnpm smoke" # команда должна существовать в проектеСтроковая форма min_version задаёт жёсткий минимум версии mise. Значения инструментов, имена задач и флаг sync --dry-run в этом блоке являются шаблоном. Выберите и протестируйте варианты, которые поддерживает ваш код.
Пример .sops.yaml с разделением доступа:
creation_rules:
- path_regex: secrets/dev\.sops\.yaml$
age:
- age1developer-recipient-placeholder # полный публичный recipient разработчика
- age1ci-recipient-placeholder # полный публичный recipient CI
- path_regex: secrets/staging\.sops\.yaml$
age:
- age1lead-recipient-placeholder # полный публичный recipient ответственного
- age1ci-recipient-placeholder # полный публичный recipient CIПроверка результата
Создайте отдельный тестовый секрет без реальных токенов, например с ключом CHECK_VALUE, зашифруйте его по подходящему creation_rule, затем запустите дочерний процесс через SOPS:
sops exec-env secrets/dev.sops.yaml 'printenv CHECK_VALUE'Ожидаемый результат:
- Подходящая identity позволяет запустить команду.
- Дочерний процесс получает значение
CHECK_VALUE. - После завершения рядом с исходным зашифрованным файлом не появляется открытая копия.
mise run hello отдельно проверяет переменную PROJECT_ENV из [env] в mise.toml. Прямой вызов sops exec-env не загружает настройки mise.toml, поэтому для проверки SOPS используйте ключ, который действительно находится в зашифрованном файле.
Дополнительно повторите проверку без доступной identity. Расшифровка должна завершиться ошибкой.
Полезные сценарии
Локальная разработка и подключение нового участника
Задача: дать новому участнику воспроизводимый запуск проекта без передачи токенов в открытом виде. Условие: в репозитории есть mise.toml, зашифрованный dev-конфиг и выдана dev-identity. Действие: участник устанавливает инструменты и запускает стандартную задачу через mise. Результат: проект получает выбранные версии инструментов, а секреты доступны только дочернему процессу. Ограничение: используйте dev или sandbox, а не production-доступ.
Dev, staging и sandbox
Задача: тестировать интеграции с разными уровнями доступа. Условие: для контуров созданы отдельные файлы и наборы recipients. Действие: запускайте задачу с конфигом нужного контура. Результат: разработчик или CI расшифровывает только разрешённый файл. Ограничение: зашифрованный файл всё равно требует ротации значений, если identity была скомпрометирована.
CI/CD
Задача: запускать тесты, сборку и проверочные задачи без ручной передачи секретов. Условие: CI получает отдельную identity через защищённое хранилище pipeline. Действие: передавайте секреты через exec-env и запускайте только разрешённые задачи. Результат: значения доступны процессу задачи и не попадают в репозиторий как открытый текст. Ограничение: не выводите секреты в логи и не используйте команды, печатающие всё окружение.
Безопасные проверочные запуски
Задача: проверить интеграцию с внешней системой без записи в рабочие данные. Условие: есть sandbox-секреты и команда с режимом --dry-run или другим явно проверочным режимом. Действие: запускайте эту команду через mise и SOPS. Результат: можно проверить конфигурацию и права доступа по наблюдаемому выводу. Ограничение: название и поведение проверочного флага зависят от вашего проекта, их нужно подтвердить отдельно.
Разделение доступов по контурам
Задача: не выдавать разработчику или сервису лишние права. Условие: каждый контур имеет собственный набор recipients. Действие: добавляйте identity только в правила нужных файлов. Результат: доступ можно отозвать на уровне конкретного контура. Ограничение: удаление recipient не заменяет ротацию самих секретов после компрометации.
Что не хранить в project-level сейфе
Даже зашифрованный репозиторий не заменяет управление особо чувствительными доступами. Отдельно храните:
- приватные age-identities;
- корневые SSH-ключи;
- личные ключи разработчиков;
- account-wide административные токены;
- production runtime-секреты, если для них принят server secret store или KMS.
Для сервисов создавайте отдельные технические учётные записи с минимальными правами. Процессы добавления, отзыва доступа и ротации документируйте до подключения production.
С чего начать пилот
Выберите некритичный проект: внутренний devtool, sandbox-интеграцию или staging-пайплайн. Добавьте один зашифрованный файл, отдельную identity для CI и две задачи mise: безопасный проверочный запуск и обычный локальный запуск.
Переход к production имеет смысл только после проверки ротации, журналирования, ограничений CI и сценария компрометации ключа.
Официальные ресурсы
- mise: документация по конфигурации
- SOPS: advanced usage и
exec-env, форматы и.sops.yaml - age: официальный репозиторий и примеры CLI, спецификация
Если в команде накопились .env-файлы на разных машинах или токены передаются вручную, начните с одного sandbox-контура и проверьте весь цикл: выдачу доступа, запуск, отзыв и ротацию.
Следующий шаг
Для следующего шага в CI полезно сверить границы доступа и проверочный запуск с руководством по DevSecOps и CI/CD.
Связанные материалы
- Статья: Как мы с Codex превратили хаос серверов в карту управляемой инфраструктуры
- Блог: MCP-серверы больше не надо выставлять в интернет — OpenAI сделали приватные туннели
- База знаний: Справочник команд терминала
Если вы внедряете связку в команде, полезно отдельно обсудить границы CI-доступа и ротацию секретов.
Если захотите обсудить, как это применить у себя или в команде — пишите в Telegram @pimenov
Если хотите разобрать свою задачу — напишите мне Если хотите разобрать свою задачу — напишите мне.
Можно прийти с идеей, черновым контекстом или уже живой задачей. Помогу быстро понять, где реальный следующий шаг, а где лишний шум.
Обычно хватает 2–3 сообщений, чтобы понять, могу ли я здесь реально помочь и в каком формате лучше двигаться дальше.
Дальше по теме
Open-source платформа для управления командами ИИ-агентов: оргструктура, бюджеты, тикеты, heartbeats, скиллы и governance. Версия v2026.722.0.