
Безопасное, эфемерное совместное использование секретов для разработчиков.
Безопасный, эфемерный обмен секретами для разработчиков.
Хватит вставлять секреты в Slack. enseal делает безопасный путь быстрее небезопасного — делитесь файлами .env и секретами через зашифрованные одноразовые каналы одной командой без настройки.```bash
$ enseal share .env Share code: 7-guitarist-revenge Secrets: 14 variables (staging) Expires: on first receive
$ enseal receive 7-guitarist-revenge ok: 14 secrets written to .env
## Установка
### Из crates.io```bash
cargo install enseal
``````bash
git clone https://github.com/FlerAlex/enseal.git
cd enseal
cargo build --release
# binary at ./target/release/enseal
Загрузить из GitHub Releases для Linux (x86_64, aarch64), macOS (Intel, Apple Silicon) и Windows.
Делитесь секретами с помощью одноразового кода. Никаких ключей, никаких аккаунтов — работает сразу.```bash
enseal share .env Share code: 7-guitarist-revenge Secrets: 14 variables Expires: on first receive
enseal receive 7-guitarist-revenge ok: 14 secrets written to .env
Работает также с одиночными секретами:```bash
# terminal 1 — pipe a token
echo "my-api-token" | enseal share --label "API key"
Share code: 4-orbital-hammock
# terminal 2 — prints to stdout
enseal receive 4-orbital-hammock
my-api-token
Оба терминала должны быть открыты одновременно — отправитель ждет, пока получатель подключится.
Для команд с установленным доверием к ключам. Шифрование по имени, координация не требуется.```bash
enseal keys init enseal keys export > my-key.pub # share this with teammates enseal keys import teammate-key.pub # import theirs
enseal share .env --to sarah
enseal share .env --to sarah --relay wss://relay.enseal.dev
enseal share .env --to sarah --output ./drop/
### Внедрить секреты в процесс (никогда не касаясь диска)```bash
# anonymous mode: sender gives you a code
enseal inject 7-guitarist-revenge -- npm start
# identity mode: listen on relay, sender pushes when ready
enseal inject --listen --relay wss://relay.enseal.dev -- docker compose up
# from an encrypted file drop
enseal inject ./staging.env.age -- python manage.py runserver
Секреты существуют только в памяти дочернего процесса. Когда он завершается, они исчезают.
Анонимный режим (по умолчанию) — на основе wormhole, без настройки. Всё, что нужно — читаемый человеком код. Взаимная аутентификация SPAKE2 предотвращает MITM-атаки.```bash enseal share .env # generates wormhole code enseal receive 7-guitarist-revenge # uses code
С флагом `--relay`, анонимный режим обходит wormhole и использует transport enseal relay вместо этого. Обе стороны должны использовать один и тот же relay:```bash
enseal share .env --relay ws://relay.internal:4443 # generates channel code
enseal receive 3421-amber-frost --relay ws://relay.internal:4443
Асинхронная загрузка (--upload) — только для отправителя. Шифрует локально и отправляет на burnurl.dev, возвращая самоуничтожающуюся ссылку, которую получатель открывает в браузере. CLI не требуется на стороне получателя.```bash
enseal share .env --upload
Получатель открывает URL в любом браузере — установка enseal не требуется. Добавьте `--passphrase` для шифрования на стороне клиента перед загрузкой (сервер видит только шифротекст):```bash
enseal share .env --upload --passphrase # prompts for passphrase
enseal share .env --upload --ttl 4 # 4-hour TTL (max 24)
Для доступа к API требуется тарифный план Pro или Team на burnurl.dev. Установите BURNURL_API_KEY как ваш ключ. Переопределите базовый URL для автономных экземпляров: BURNURL_URL=https://burnurl.internal.
Режим идентификации — шифрование с открытым ключом для знакомых участников команды. Шифруйте для указанного имени.```bash enseal keys init # one-time setup enseal share .env --to sarah # encrypt to sarah's public key
Режим Identity поддерживает три варианта транспорта:```bash
# wormhole (default, no --relay): generates a code like anonymous mode
enseal share .env --to sarah
# relay push (with --relay): zero codes, pushes directly to recipient's channel
enseal share .env --to sarah --relay wss://relay.enseal.dev
# file drop (with --output): no network, produces encrypted file
enseal share .env --to sarah --output ./drop/
# produces ./drop/[email protected]
enseal принимает секреты из нескольких источников:```bash
enseal share .env enseal share staging.env
enseal share --env staging # resolves to .env.staging
echo "sk_live_abc123" | enseal share cat secrets.env | enseal share pass show stripe/key | enseal share --to sarah
enseal share --secret "API_KEY=sk_live_abc123"
echo "sk_live_abc123" | enseal share --as STRIPE_KEY
### Интерполяция переменных
Ссылки `${VAR}` разрешаются перед отправкой, чтобы получатели получили полностью развернутые значения:```env
DB_HOST=postgres.internal
DB_PORT=5432
DATABASE_URL=postgres://user:pass@${DB_HOST}:${DB_PORT}/myapp
Поддерживает синтаксис подстановки ${VAR:-default}. Циклические и прямые ссылки обнаруживаются и отклоняются. Используйте --no-interpolate для отправки сырого синтаксиса ${VAR}.
Управляйте, какие переменные отправляются:```bash
enseal share .env --exclude "^PUBLIC_|^NEXT_PUBLIC_"
enseal share .env --include "^DB_|^API_"
enseal share .env --no-filter
### Умный приём
Вывод адаптируется к тому, что было отправлено:```bash
# .env payload -> writes to file
enseal receive CODE
ok: 14 secrets written to .env
# write to specific file
enseal receive CODE --output staging.env
# raw string -> prints to stdout (pipe-friendly)
enseal receive CODE
sk_live_abc123
# force clipboard
enseal receive CODE --clipboard
ok: copied to clipboard
# force stdout for any payload
enseal receive CODE --no-write
# receive from encrypted file drop (identity mode)
enseal receive ./staging.env.age
ok: signature verified, file decrypted
ok: 14 secrets written to .env
Получайте секреты и внедряйте их непосредственно как переменные окружения в дочерний процесс. Секреты никогда не касаются файловой системы.```bash
enseal inject 7-guitarist-revenge -- npm start
enseal inject --listen --relay wss://relay.enseal.dev -- docker compose up
enseal inject ./staging.env.age -- python manage.py runserver
С помощью `--listen` получатель подключается к ретранслятору и ожидает. Отправитель выполняет команду `enseal share .env --to alex --relay wss://relay.enseal.dev` — никакого обмена кодами, координация не требуется.
### .env Набор инструментов
Помимо обмена, enseal — это полный набор инструментов безопасности для `.env`:```bash
# check: verify your .env has all required vars
enseal check
error: missing from .env (present in .env.example):
JWT_SECRET, REDIS_URL
# diff: compare two .env files (keys only, never values)
enseal diff .env.development .env.staging
+ REDIS_CLUSTER_URL (only in staging)
- DEBUG (only in development)
# redact: strip values for safe sharing of structure
enseal redact .env
DATABASE_URL=<REDACTED>
API_KEY=<REDACTED>
PORT=<REDACTED>
# validate: check values against schema rules
enseal validate .env
error: missing required: JWT_SECRET
error: PORT value "abc" is not an integer
ok: 11/14 variables passed validation
# template: generate .env.example with type hints
enseal template .env
# DATABASE_URL=<postgres connection string>
# API_KEY=<32+ character string>
# PORT=<integer, 1024-65535>
Шифруйте файлы .env для безопасного хранения в git с помощью шифрования age:```bash
enseal encrypt .env ok: .env encrypted in-place (14 variables, age key)
enseal decrypt .env
enseal encrypt .env --per-var
enseal encrypt .env --to sarah --to alex
### Идентификация и управление ключами```bash
# generate your keypair
enseal keys init
# share your public key with teammates
enseal keys export > my-key.pub
# import a teammate's key (shows fingerprint, prompts for confirmation)
enseal keys import sarah.pub
# list all trusted keys and aliases
enseal keys list
# show your key fingerprint (for out-of-band verification)
enseal keys fingerprint
# remove a trusted key
enseal keys remove [email protected]
# create aliases for convenience
enseal keys alias sarah [email protected]
# create groups for multi-recipient sharing
enseal keys group create backend-team
enseal keys group add backend-team sarah
enseal keys group add backend-team alex
enseal keys group list backend-team
enseal share .env --to backend-team
# delete a group
enseal keys group delete backend-team
Бесплатное публичное реле доступно по адресу wss://relay.enseal.dev. Используйте его для быстрого тестирования или когда вам не нужно частное реле.```bash
curl https://relay.enseal.dev/health
enseal share .env --to sarah --relay wss://relay.enseal.dev enseal inject --listen --relay wss://relay.enseal.dev -- npm start
export ENSEAL_RELAY=wss://relay.enseal.dev
#### Попробуйте сами```bash
# 1. generate keys (one-time)
enseal keys init
# 2. export and import your own key (for self-testing)
enseal keys export > /tmp/mykey.pub
enseal keys import /tmp/mykey.pub
# enter an alias when prompted (e.g. "mykey")
# 3. test file drop (no network needed)
enseal share --secret "TEST=works" --to mykey --output /tmp/
enseal receive /tmp/mykey.env.age
# 4. test relay push (two terminals)
# terminal 1 (receiver):
enseal inject --listen --relay wss://relay.enseal.dev -- env | grep TEST
# terminal 2 (sender):
enseal share --secret "TEST=relay_works" --to mykey --relay wss://relay.enseal.dev
Держите всё в пределах вашей сети. Ретранслятор не хранит состояние — он видит только шифротекст.```bash
docker run -d -p 4443:4443 enseal/relay
enseal serve --port 4443
curl http://localhost:4443/health
`enseal serve` использует обычный WebSocket (`ws://`). Для TLS поместите обратный прокси-сервер (Caddy, nginx) перед ним и подключайтесь через `wss://`.
С установленным `--relay` все режимы маршрутизируются через ваш релей.```bash
# Anonymous mode — generates enseal channel code instead of wormhole code
enseal share .env --relay ws://relay.internal:4443
# info: Share code: 3421-amber-frost
enseal receive 3421-amber-frost --relay ws://relay.internal:4443
# Or set globally
export ENSEAL_RELAY=ws://relay.internal:4443
enseal share .env
Режим идентификации с самостоятельно размещенным реле полностью бескодовый:```bash
enseal inject --listen --relay ws://relay.internal:4443 -- npm start
enseal share .env --to alex --relay ws://relay.internal:4443 ok: pushed to alex
### Валидация схемы
Определите правила в `.enseal.toml` в корне проекта:```toml
[schema]
required = ["DATABASE_URL", "API_KEY", "JWT_SECRET"]
[schema.rules.DATABASE_URL]
pattern = "^postgres://"
description = "PostgreSQL connection string"
[schema.rules.PORT]
type = "integer"
range = [1024, 65535]
[schema.rules.API_KEY]
min_length = 32
Затем проверьте:```bash enseal validate .env
Проверка также выполняется автоматически при получении файлов `.env` — улавливая сломанные конфиги до того, как они вызовут путаницу.
### Профили окружения```bash
enseal share --env staging # shares .env.staging
enseal validate --env production # validates .env.production
enseal diff .env.development .env.production
Wormhole (по умолчанию, без --relay):
ageРетранслятор никогда не видит открытый текст. Код wormhole обеспечивает взаимную аутентификацию.
Ретранслятор Enseal (--relay):
age и отправляет её на ретранслятор enseal под сгенерированным кодом каналаВ этом режиме нет SPAKE2 — код канала является единственным учётным данным.
--upload)Envelope (JSON, контрольная сумма SHA-256)--passphrase)burnurl.dev/api/secret через HTTPSОтправитель передаёт URL. Получатель открывает его в любом браузере — enseal не требуется. С --passphrase парольную фразу нужно передать отдельно; сервер никогда не видит открытый текст.
Тарифы: Доступ к API требует тарифа Pro или Team на burnurl.dev. Установите BURNURL_API_KEY как свой ключ — на бесплатном тарифе нет доступа к API.
Переопределите BURNURL_URL, чтобы указать на собственный экземпляр burnurl.
age получателяed25519Доверие основано на том, какие ключи вы импортировали.
Варианты транспорта в режиме идентификации:
При push через ретранслятор получатель слушает с помощью enseal inject --listen --relay URL -- cmd или получает файловую каплю с помощью enseal receive ./file.env.age.
Защищено:
Не защищено:
Необязательный .enseal.toml в корне проекта:```toml
[defaults]
relay = "wss://relay.enseal.dev" # public relay (identity mode)
[filter] exclude = ["^PUBLIC_", "^NEXT_PUBLIC_", "^REACT_APP_"]
[identity] default_recipient = "devops-team"
[schema] required = ["DATABASE_URL", "API_KEY", "JWT_SECRET"]
## Справочник по CLI```
CORE
enseal share [<file>] Send secrets (file, pipe, or --secret)
enseal receive [<code|file>] Receive secrets
enseal inject [<code>] -- <cmd> Inject secrets into a process
enseal keys <subcommand> Manage identity keys and aliases
enseal serve Run self-hosted relay server
.ENV TOOLKIT
enseal check [file] Verify .env has all vars from .env.example
enseal diff <file1> <file2> Compare .env files (keys only)
enseal redact <file> Replace values with <REDACTED>
enseal validate <file> Validate against schema rules
enseal template <file> Generate .env.example with type hints
ENCRYPTION
enseal encrypt <file> Encrypt .env for git storage
enseal decrypt <file> Decrypt an encrypted .env
--to Identity mode: encrypt to recipient (alias, group, or identity) --output
File drop: write encrypted file (identity mode, no network) --upload Post to burnurl.dev (async, browser-readable, no CLI on recipient side) --ttl Secret TTL for --upload (1-24, default: 24) --passphrase Encrypt client-side before --upload (prompts; server never sees plaintext) --secret Inline secret (raw string or KEY=VALUE) --label Human label for raw/piped secrets --as Wrap raw input as KEY= --relay Route through relay server. Anonymous mode: uses enseal relay transport (generates channel code, bypasses wormhole). Identity mode: push to recipient's channel. Also: ENSEAL_RELAY env var. --env Environment profile (resolves to .env.) --exclude Regex to exclude vars --include Regex to include only matching vars --no-filter Send raw file, skip .env parsing --no-interpolate Don't resolve ${VAR} references before sending --words Words in wormhole code (2-5, default: 2). Wormhole mode only (no --relay). --quiet / -q Minimal output### `receive` флаги```
--output <path> Write to specific file
--clipboard Copy to clipboard instead of stdout/file
--no-write Print to stdout even for .env payloads
--relay <url> Use specific relay server
--quiet / -q Minimal output
inject флаги```--listen Listen for incoming identity-mode transfer (requires --relay) --relay Use specific relay server (also: ENSEAL_RELAY) --quiet / -q Minimal output
### `keys` подкоманды```
enseal keys init Generate your keypair
enseal keys export Print your public key bundle
enseal keys import <file> Import a colleague's public key
enseal keys list Show all trusted keys and aliases
enseal keys remove <identity> Remove a trusted key
enseal keys fingerprint Show your key fingerprint
enseal keys alias <name> <identity> Map short name to identity
enseal keys group create <name> Create a named group
enseal keys group add <group> <id> Add identity to group
enseal keys group remove <group> <id> Remove identity from group
enseal keys group list [name] List groups or group members
enseal keys group delete <name> Delete a group
serve флаги```--port Listen port (default: 4443) --bind Bind address (default: 0.0.0.0) --max-mailboxes Max concurrent channels (default: 100) --channel-ttl Idle channel lifetime (default: 300) --max-payload Max WebSocket message size (default: 1048576) --rate-limit Max connections per minute per IP (default: 10) --health Print server health check and exit
### `encrypt` / `decrypt` флаги```
--per-var Per-variable encryption (keys visible, values encrypted)
--to <name> Encrypt to specific recipients (multi-key)
--verbose / -v Debug output (never prints secret values) --quiet / -q Minimal output (for scripting)
## Сравнение
| | enseal | Slack DM | 1Password Share | dotenvx | croc |
|---|---|---|---|---|---|
| Нулевая настройка | Да | Да | Нет | Нет | Да |
| Сквозное шифрование | Да | Нет | Да | Н/Д | Да |
| Эфемерный (без истории) | Да | Нет | Да | Н/Д | Да |
| Поддержка .env | Да | Нет | Нет | Да | Нет |
| Внедрение в процессы | Да | Нет | Нет | Да | Нет |
| Проверка схемы | Да | Нет | Нет | Нет | Нет |
| Шифрование в покое | Да | Н/Д | Н/Д | Да | Нет |
| Самостоятельно размещаемый ретранслятор | Да | Нет | Нет | Н/Д | Да |
| Поддержка сырых строк/каналов | Да | Да | Нет | Нет | Да |
## План развития
- **v0.1** — Ядро: отправка/получение, канал/стандартный ввод, набор инструментов .env (проверка, сравнение, редактирование) *(готово)*
- **v0.2** — Режим идентификации: ключи, псевдонимы, флаг `--to` *(готово)*
- **v0.3** — Команда внедрения, самостоятельный ретранслятор *(готово)*
- **v0.4** — Проверка схемы, шаблоны, интерполяция, профили *(готово)*
- **v0.5** — Шифрование в покое (шифрование/расшифровка) *(готово)*
- **v0.10** — Группы, диаграмма Helm, документация *(готово)*
- **v0.11** — Укрепление безопасности, синхронизация документации *(готово)*
- **v0.12** — .enseal.toml подключён, частный ретранслятор для анонимного режима *(готово)*
- **v0.16** — Асинхронная загрузка через burnurl.dev (`--upload`) *(текущий)*
- **v1.0** — Публикация на crates.io, финальная полировка
## Лицензия
MIT
| Транспорт | Флаг | Принцип работы |
|---|
| Wormhole (по умолчанию) | --to sarah | Генерирует код, как в анонимном режиме, но с подписью |
| Push через ретранслятор | --to sarah --relay URL | Отправляет на детерминированный канал получателя, без кода |
| Файловая капля | --to sarah --output ./dir/ | Создаёт зашифрованный файл .env.age, без сети |