Cloudflare Agents SDK — фреймворк для stateful AI-агентов поверх Durable Objects: каждый агент — отдельный «микросервер» с SQLite, WebSocket, планировщиком и hibernation. Разбираем…
Связка mise + sops + age решает две практические задачи в проектах команды: воспроизводимый запуск окружения и безопасное хранение project-level секретов. В репозиторий коммитится зашифрованный конфиг, приватный ключ для расшифровки живёт отдельно — у разработчика, в Keychain, 1Password или CI secrets.
Что это такое
mise — менеджер версий и команд проекта. В одном файле .mise.toml вы фиксируете, какие Node, Python, pnpm нужны проекту, и описываете команды вроде mise run dev или mise run smoke. Заменяет nvm, pyenv, asdf и зоопарк самописных скриптов. Новый человек клонирует репозиторий, делает mise install — и у него ровно те же версии и те же команды, что у вас.
sops — утилита от Mozilla для шифрования конфигов. Берёт ваш YAML или JSON и шифрует только значения, оставляя ключи открытыми. Diff в Git остаётся читаемым: видно, какое поле поменялось, а само значение зашифровано. Файл secrets/dev.sops.yaml спокойно лежит в репозитории — без приватного ключа из него ничего не достать.
age — современная замена GPG для команд. Простой формат ключей, понятный CLI, никакого keyring и веб-доверия. Публичный ключ — одна короткая строка, её можно коммитить рядом с проектом. Приватный ключ живёт у каждого человека отдельно: в Keychain, 1Password или в файле с правильными правами. Именно age решает, кто имеет право расшифровать sops-файл.
Как они работают вместе. mise запускает проект, в нужный момент дёргает sops, тот через age расшифровывает секреты и подсовывает их в окружение. Снаружи это одна команда mise run dev. Внутри — три инструмента, каждый отвечает за свой слой: окружение, формат конфига, криптография.
Целевая архитектура
В этой связке три инструмента закрывают три разных слоя проекта.
miseотвечает за окружение и команды: версии Node, Python, pnpm, ENV-переменные, задачиdev,test,build,smoke.sopsотвечает за зашифрованные файлы конфигурации: YAML, JSON,.env-подобные структуры, которые безопасно лежат в репозитории.ageотвечает за саму криптографию: публичный ключ коммитится в проект, приватный ключ хранится вне репозитория.
Идея простая: репозиторий перестаёт быть местом, куда «случайно попал .env». Там лежит инструкция запуска и зашифрованный сейф, а право открыть этот сейф у конкретных людей и сервисов.
Чеклист быстрой проверки
Пройдите по списку перед тем, как внедрять связку в команде.
.mise.toml с фиксированными версиями инструментов.mise tasks показывает понятный набор команд (dev, test, sync:dry, build, smoke).secrets/<contour>.sops.yaml с разделением по контурам..sops.yaml.age-ключи команды собраны в одном файле и закоммичены.age-ключи разработчиков хранятся в Keychain или 1Password, а не в репозитории.age-ключ с правами только на свой контур.Роли инструментов
mise — воспроизводимое окружение
mise фиксирует версии runtime и описывает команды проекта в одном файле. Новый человек открывает репозиторий и запускает mise install плюс одну понятную команду вместо ручной установки Node, pnpm и Python нужных версий.
sops — зашифрованные конфиги
sops шифрует значения в YAML или JSON, оставляя ключи в открытом виде. Diff в Git остаётся читаемым: видно, какое поле изменилось, а само значение зашифровано. Файлы вида secrets/dev.sops.yaml спокойно коммитятся в репозиторий.
age — криптография под капотом
age — современная замена GPG для команд. Простой формат ключей, понятный CLI, никакого keyring и веб-доверия. Публичный ключ лежит в проекте рядом с .sops.yaml, приватный — у владельца.
Варианты применения в команде
1. Быстрый запуск проекта новым человеком
В проект кладётся .mise.toml с версиями инструментов и понятными задачами. Новый разработчик клонирует репозиторий, получает age-ключ, и через десять минут уже запускает mise run dev или mise run sync:dry.
2. Зашифрованные dev и staging секреты
В репозитории живут secrets/dev.sops.yaml и secrets/staging.sops.yaml. Расшифровать их может только человек или CI с подходящим приватным ключом. Если ключ скомпрометирован, он отзывается, файлы перешифровываются, история в Git остаётся чистой.
3. Безопасные dry-run и sandbox сценарии
Для интеграций с Notion, Telegram, Directus, OpenAI и CRM удобно держать отдельные sandbox-секреты. Это даёт возможность проверять скрипты без доступа к production-данным и без риска случайных live writes.
4. Управляемый CI/CD
CI получает свой отдельный ключ расшифровки и запускает только разрешённые задачи: тесты, сборку, sync:dry, smoke. Секреты не лежат в репозитории как простой текст и не передаются вручную между людьми.
5. Разделение доступов по контурам
Один файл — один контур: dev, staging, production, client-demo, sandbox. У каждого контура свой набор recipients. Разработчик читает dev-секреты, но не production. CI читает только то, что ему нужно для своей задачи.
6. Операционный стандарт команды
Связка помогает зафиксировать рабочую дисциплину: где лежат секреты, кто имеет доступ, как добавить нового человека, как отозвать доступ, как ротировать ключи и какие команды считаются безопасными для запуска без approval.
Что НЕ класть в project secrets
В project-level сейфе не должно быть глобальных админских токенов, root SSH, личных ключей разработчиков, account-wide доступов Cloudflare, приватных age identities и production-секретов без отдельного процесса ротации. Для таких вещей подходят:
- Keychain или 1Password — для личных и админских ключей.
- CI secrets — для токенов, которыми пользуется только pipeline.
- Server secret store — для production runtime.
- Отдельный технический пользователь с минимальными правами — вместо того чтобы выдавать сервису ключи владельца аккаунта.
Эталонный шаблон проекта
Минимальная рабочая структура для команды.
project/
├── .mise.toml
├── .sops.yaml
├── secrets/
│ ├── dev.sops.yaml
│ └── staging.sops.yaml
└── age-keys/
├── team.pub # публичные ключи команды
└── ci.pub # публичный ключ CIПример .mise.toml с базовыми задачами:
[tools]
node = "20"
pnpm = "9"
python = "3.12"
[env]
PROJECT_ENV = "dev"
[tasks.dev]
description = "Локальный запуск с расшифровкой dev-секретов"
run = "sops exec-env secrets/dev.sops.yaml 'pnpm dev'"
[tasks."sync:dry"]
description = "Dry-run синхронизации без записи"
run = "sops exec-env secrets/dev.sops.yaml 'pnpm sync --dry-run'"
[tasks.smoke]
description = "Smoke-тесты после деплоя"
run = "pnpm smoke"Пример .sops.yaml, разделяющий доступ по контурам:
creation_rules:
- path_regex: secrets/dev\.sops\.yaml$
age: >-
age1devkey...,
age1cikey...
- path_regex: secrets/staging\.sops\.yaml$
age: >-
age1leadkey...,
age1cikey...С чего начать пилот
Начинайте не с production-критичных систем. Хорошие первые проекты для пилота:
- Контентные пайплайны и Notion-to-site синхронизация.
- Sandbox-боты и staging-интеграции.
- Внутренние devtools и скрипты команды.
- Тестовые контуры новых интеграций до выхода в production.
Production runtime и клиентские live-секреты стоит переводить только после отдельного preflight и плана ротации.
mise запускает проект в правильном порядке, sops открывает зашифрованный конфиг там, где есть право доступа, age определяет, у кого это право есть.По теме
Если в команде уже накопились проекты с .env-файлами по разным машинам или ручной передачей токенов в личке, имеет смысл проверить на одном пилоте, насколько mise + sops + age упрощает жизнь.
Захотите обсудить, как это применить у себя или в команде — пишите в Telegram @pimenov