
Condivisione sicura ed effimera di segreti per sviluppatori.
Condivisione sicura e effimera di segreti per sviluppatori.
Smetti di incollare segreti su Slack. enseal rende il percorso sicuro più veloce di quello insicuro — condividi file .env e segreti attraverso canali crittografati e monouso con un solo comando e zero configurazione.```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
## Installazione
### Da crates.io```bash
cargo install enseal
git clone https://github.com/FlerAlex/enseal.git cd enseal cargo build --release
### Binari precompilati
Scarica da [GitHub Releases](https://github.com/FlerAlex/enseal/releases) per Linux (x86_64, aarch64), macOS (Intel, Apple Silicon) e Windows.
## Avvio rapido
### Modalità anonima (nessuna configurazione)
Condividi segreti usando un codice monouso. Nessuna chiave, nessun account — funziona immediatamente.```bash
# terminal 1 (sender)
enseal share .env
Share code: 7-guitarist-revenge
Secrets: 14 variables
Expires: on first receive
# terminal 2 (recipient) — enter the code
enseal receive 7-guitarist-revenge
ok: 14 secrets written to .env
Funziona anche con segreti singoli:```bash
echo "my-api-token" | enseal share --label "API key" Share code: 4-orbital-hammock
enseal receive 4-orbital-hammock my-api-token
Entrambi i terminali devono essere aperti contemporaneamente — il mittente attende che il destinatario si connetta.
### Modalità identità (basato su chiavi, senza codici)
Per team con fiducia nelle chiavi già stabilita. Crittografa a un nome, nessuna coordinazione necessaria.```bash
# one-time setup
enseal keys init
enseal keys export > my-key.pub # share this with teammates
enseal keys import teammate-key.pub # import theirs
# sender encrypts to recipient by name
enseal share .env --to sarah
# or push through the public relay (no codes at all)
enseal share .env --to sarah --relay wss://relay.enseal.dev
# or produce an encrypted file (no network)
enseal share .env --to sarah --output ./drop/
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
I segreti esistono solo nella memoria del processo figlio. Quando esce, scompaiono.
## Caratteristiche
### Tre modalità di condivisione
**Modalità anonima** (predefinita) — basata su wormhole, configurazione zero. Tutto ciò che serve è un codice leggibile dall'uomo. L'autenticazione reciproca SPAKE2 previene gli attacchi MITM.```bash
enseal share .env # generates wormhole code
enseal receive 7-guitarist-revenge # uses code
Con --relay, la modalità anonima bypassa wormhole e utilizza invece il relay transport enseal. Entrambi i lati devono utilizzare lo stesso relay:```bash
enseal share .env --relay ws://relay.internal:4443 # generates channel code
enseal receive 3421-amber-frost --relay ws://relay.internal:4443
**Caricamento asincrono (`--upload`)** — solo mittente. Cripta localmente e pubblica su [burnurl.dev](https://burnurl.dev), restituendo un URL autodistruggente che il destinatario apre in un browser. Nessuna CLI richiesta lato destinatario.```bash
enseal share .env --upload
# Secret URL: https://burnurl.dev/s/a3f9c2e1...
# Expires: 2026-03-08 19:42:00 UTC (24h)
# Reads: 1 (self-destructs on first open)
Il destinatario apre l'URL in qualsiasi browser — non è necessaria l'installazione di enseal. Aggiungi --passphrase per crittografare lato client prima del caricamento (il server vede solo testo cifrato):```bash
enseal share .env --upload --passphrase # prompts for passphrase
enseal share .env --upload --ttl 4 # 4-hour TTL (max 24)
L'accesso API richiede un piano Pro o Team su burnurl.dev. Imposta `BURNURL_API_KEY` con la tua chiave. Sostituisci l'URL base per istanze self-hosted: `BURNURL_URL=https://burnurl.internal`.
**Modalità identità** — crittografia a chiave pubblica per membri del team conosciuti. Crittografa verso un nome.```bash
enseal keys init # one-time setup
enseal share .env --to sarah # encrypt to sarah's public key
Identity mode supporta tre opzioni di trasporto:```bash
enseal share .env --to sarah
enseal share .env --to sarah --relay wss://relay.enseal.dev
enseal share .env --to sarah --output ./drop/
### Input Flessibile
enseal accetta segreti da più fonti:```bash
# .env file (default)
enseal share .env
enseal share staging.env
# environment profile
enseal share --env staging # resolves to .env.staging
# pipe from stdin
echo "sk_live_abc123" | enseal share
cat secrets.env | enseal share
pass show stripe/key | enseal share --to sarah
# inline (careful — visible in shell history)
enseal share --secret "API_KEY=sk_live_abc123"
# wrap raw string as KEY=VALUE
echo "sk_live_abc123" | enseal share --as STRIPE_KEY
${VAR} I riferimenti vengono risolti prima dell'invio, in modo che i destinatari ricevano valori completamente espansi:```env
DB_HOST=postgres.internal
DB_PORT=5432
DATABASE_URL=postgres://user:pass@${DB_HOST}:${DB_PORT}/myapp
Supporta la sintassi di fallback `${VAR:-default}`. I riferimenti circolari e in avanti vengono rilevati e respinti. Usa `--no-interpolate` per inviare la sintassi grezza `${VAR}`.
### Filtraggio
Controlla quali variabili vengono inviate:```bash
# exclude public/non-secret vars
enseal share .env --exclude "^PUBLIC_|^NEXT_PUBLIC_"
# send only matching vars
enseal share .env --include "^DB_|^API_"
# skip .env parsing entirely (send raw file)
enseal share .env --no-filter
L'output si adatta a ciò che è stato inviato:```bash
enseal receive CODE ok: 14 secrets written to .env
enseal receive CODE --output staging.env
enseal receive CODE sk_live_abc123
enseal receive CODE --clipboard ok: copied to clipboard
enseal receive CODE --no-write
enseal receive ./staging.env.age ok: signature verified, file decrypted ok: 14 secrets written to .env
### Inject
Riceve segreti e li inietta direttamente come variabili d'ambiente in un processo figlio. I segreti non toccano mai il filesystem.```bash
# anonymous mode: inject via wormhole code
enseal inject 7-guitarist-revenge -- npm start
# identity mode: listen for incoming transfer on relay
enseal inject --listen --relay wss://relay.enseal.dev -- docker compose up
# from encrypted file drop
enseal inject ./staging.env.age -- python manage.py runserver
With --listen, the destinatario si collega al relay e attende. Il mittente invia con enseal share .env --to alex --relay wss://relay.enseal.dev — nessun codice scambiato, zero coordinazione necessaria.
Oltre alla condivisione, enseal è un toolkit di sicurezza completo per .env:```bash
enseal check error: missing from .env (present in .env.example): JWT_SECRET, REDIS_URL
enseal diff .env.development .env.staging
enseal redact .env DATABASE_URL= API_KEY= PORT=
enseal validate .env error: missing required: JWT_SECRET error: PORT value "abc" is not an integer ok: 11/14 variables passed validation
enseal template .env
### Crittografia a riposo
Crittografa i file `.env` per un archivio git sicuro usando age encryption:```bash
# whole-file encryption
enseal encrypt .env
ok: .env encrypted in-place (14 variables, age key)
enseal decrypt .env
# per-variable: keys visible for diffing, values encrypted
enseal encrypt .env --per-var
# DB_HOST=ENC[age:abc123...]
# DB_PORT=ENC[age:def456...]
# multi-recipient: anyone on the team can decrypt
enseal encrypt .env --to sarah --to alex
enseal keys init
enseal keys export > my-key.pub
enseal keys import sarah.pub
enseal keys list
enseal keys fingerprint
enseal keys remove [email protected]
enseal keys alias sarah [email protected]
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
enseal keys group delete backend-team
### Relay Pubblico
Un relay pubblico gratuito è disponibile all'indirizzo `wss://relay.enseal.dev`. Usalo per test rapidi o quando non hai bisogno di un relay privato.```bash
# check relay health
curl https://relay.enseal.dev/health
# use it for identity-mode transfers
enseal share .env --to sarah --relay wss://relay.enseal.dev
enseal inject --listen --relay wss://relay.enseal.dev -- npm start
# or set it globally
export ENSEAL_RELAY=wss://relay.enseal.dev
enseal keys init
enseal keys export > /tmp/mykey.pub enseal keys import /tmp/mykey.pub
enseal share --secret "TEST=works" --to mykey --output /tmp/ enseal receive /tmp/mykey.env.age
enseal inject --listen --relay wss://relay.enseal.dev -- env | grep TEST
enseal share --secret "TEST=relay_works" --to mykey --relay wss://relay.enseal.dev
### Relay auto-ospitato
Mantieni tutto all'interno della tua rete. Il relay è stateless — vede solo testo cifrato.```bash
# Docker (one command)
docker run -d -p 4443:4443 enseal/relay
# Or as a binary
enseal serve --port 4443
# Check relay health
curl http://localhost:4443/health
enseal serve parla WebSocket semplice (ws://). Per TLS, metti un reverse proxy (Caddy, nginx) davanti e connettiti con wss://.
Con --relay impostato, tutte le modalità instradano attraverso il tuo relay:```bash
enseal share .env --relay ws://relay.internal:4443
enseal receive 3421-amber-frost --relay ws://relay.internal:4443
export ENSEAL_RELAY=ws://relay.internal:4443 enseal share .env
La modalità identità con un relay auto-ospitato è completamente senza codice:```bash
# receiver listens on the relay
enseal inject --listen --relay ws://relay.internal:4443 -- npm start
# sender pushes directly — no code generated
enseal share .env --to alex --relay ws://relay.internal:4443
ok: pushed to alex
Definisci le regole in .enseal.toml alla radice del progetto:```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
Poi valida:```bash
enseal validate .env
La validazione viene eseguita automaticamente anche quando si ricevono file .env — intercettando configurazioni errate prima che causino confusione.
enseal share --env staging # shares .env.staging enseal validate --env production # validates .env.production enseal diff .env.development .env.production
## Come Funziona
### Modalità Anonima
**Wormhole (predefinita, senza `--relay`):**
1. Il mittente crittografa il payload con `age`
2. Uno scambio di chiavi SPAKE2 stabilisce un segreto condiviso tramite il relay pubblico di wormhole
3. Il payload crittografato transita attraverso il relay
4. Il destinatario decifra con la chiave negoziata
5. Il canale viene distrutto — utilizzo singolo, con limite di tempo
Il relay non vede mai il testo in chiaro. Il codice wormhole fornisce autenticazione reciproca.
**Relay Enseal (`--relay`):**
1. Il mittente crittografa il payload con `age` e lo invia al relay enseal con un codice di canale generato
2. Il destinatario si connette allo stesso relay con lo stesso codice e riceve il payload
3. Il canale viene consumato al primo ricevimento
Non c'è SPAKE2 in questa modalità — il codice del canale è l'unica credenziale.
### Caricamento Asincrono (`--upload`)
1. Il mittente serializza il payload in un `Envelope` (JSON, controllo di integrità SHA-256)
2. Opzionalmente lo crittografa lato client con una passphrase age scrypt (`--passphrase`)
3. Invia il payload tramite POST a `burnurl.dev/api/secret` su HTTPS
4. burnurl.dev lo memorizza con AES-256-GCM lato server a riposo e restituisce un URL autodistruttivo
5. L'URL è valido per il TTL configurato (fino a 24 ore nel piano gratuito), sola lettura singola
Il mittente condivide l'URL. Il destinatario lo apre in qualsiasi browser — non è necessario enseal. Con `--passphrase`, la passphrase deve essere condivisa separatamente; il server non vede mai il testo in chiaro.
**Piani:** L'accesso API richiede un piano Pro o Team su burnurl.dev. Imposta `BURNURL_API_KEY` con la tua chiave — il piano gratuito non ha accesso API.
Sovrascrivi `BURNURL_URL` per puntare a un'istanza burnurl self-hosted.
### Modalità Identità (Chiave Pubblica)
1. Il mittente crittografa con la chiave pubblica `age` del destinatario
2. Il mittente firma con la propria chiave `ed25519`
3. Il payload transita attraverso relay, file drop o wormhole
4. Il destinatario decifra con la propria chiave privata
5. Il destinatario verifica la firma del mittente
La fiducia si basa su quali chiavi hai importato.
**Opzioni di trasporto in modalità identità:**
| Trasporto | Flag | Come funziona |
|---|---|---|
| Wormhole (predefinita) | `--to sarah` | Genera un codice, come la modalità anonima ma con firma |
| Invio tramite relay | `--to sarah --relay URL` | Spinge al canale deterministico del destinatario, nessun codice |
| File drop | `--to sarah --output ./dir/` | Produce un file crittografato `.env.age`, nessuna rete |
Con l'invio tramite relay, il destinatario ascolta con `enseal inject --listen --relay URL -- cmd` o riceve il file drop con `enseal receive ./file.env.age`.
## Modello di Sicurezza
**Protetto:**
- Segreti in transito (canale crittografato)
- Segreti nella cronologia di Slack/email (effimeri, nessuna persistenza)
- Attacchi MITM (SPAKE2 / autenticazione a chiave pubblica)
- Relay malintenzionato (crittografia E2E, il relay vede solo il testo cifrato)
- Impersonazione del mittente (modalità identità: firme ed25519)
- Segreti su disco (modalità inject: solo memoria di processo)
- Segreti in git (crittografa: crittografia a riposo)
**Non protetto:**
- Endpoint compromessi (se la macchina è posseduta, nulla aiuta)
- Distribuzione delle chiavi (ti fidi delle chiavi che importi — nessun PKI, nessuna CA)
## Configurazione
Opzionale `.enseal.toml` nella root del progetto:```toml
[defaults]
relay = "wss://relay.enseal.dev" # public relay (identity mode)
# relay = "ws://relay.internal:4443" # self-hosted without TLS
# relay = "wss://relay.internal:4443" # self-hosted with TLS reverse proxy
[filter]
exclude = ["^PUBLIC_", "^NEXT_PUBLIC_", "^REACT_APP_"]
[identity]
default_recipient = "devops-team"
[schema]
required = ["DATABASE_URL", "API_KEY", "JWT_SECRET"]
CORE
enseal share [] Send secrets (file, pipe, or --secret)
enseal receive [<code|file>] Receive secrets
enseal inject [] -- Inject secrets into a process
enseal keys 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 Compare .env files (keys only) enseal redact Replace values with enseal validate Validate against schema rules enseal template Generate .env.example with type hints
ENCRYPTION enseal encrypt Encrypt .env for git storage enseal decrypt Decrypt an encrypted .env
### `share` flag```
--to <name> Identity mode: encrypt to recipient (alias, group, or identity)
--output <dir> File drop: write encrypted file (identity mode, no network)
--upload Post to burnurl.dev (async, browser-readable, no CLI on recipient side)
--ttl <hours> Secret TTL for --upload (1-24, default: 24)
--passphrase Encrypt client-side before --upload (prompts; server never sees plaintext)
--secret <value> Inline secret (raw string or KEY=VALUE)
--label <name> Human label for raw/piped secrets
--as <KEY> Wrap raw input as KEY=<value>
--relay <url> 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 <profile> Environment profile (resolves to .env.<profile>)
--exclude <pattern> Regex to exclude vars
--include <pattern> Regex to include only matching vars
--no-filter Send raw file, skip .env parsing
--no-interpolate Don't resolve ${VAR} references before sending
--words <n> Words in wormhole code (2-5, default: 2). Wormhole mode only (no --relay).
--quiet / -q Minimal output
receive flag```--output Write to specific file --clipboard Copy to clipboard instead of stdout/file --no-write Print to stdout even for .env payloads --relay Use specific relay server --quiet / -q Minimal output
### `inject` flag```
--listen Listen for incoming identity-mode transfer (requires --relay)
--relay <url> Use specific relay server (also: ENSEAL_RELAY)
--quiet / -q Minimal output
keys sottocomandi```enseal keys init Generate your keypair enseal keys export Print your public key bundle enseal keys import Import a colleague's public key enseal keys list Show all trusted keys and aliases enseal keys remove Remove a trusted key enseal keys fingerprint Show your key fingerprint enseal keys alias Map short name to identity enseal keys group create Create a named group enseal keys group add Add identity to group enseal keys group remove Remove identity from group enseal keys group list [name] List groups or group members enseal keys group delete Delete a group
### Flag di `serve````
--port <port> Listen port (default: 4443)
--bind <addr> Bind address (default: 0.0.0.0)
--max-mailboxes <n> Max concurrent channels (default: 100)
--channel-ttl <seconds> Idle channel lifetime (default: 300)
--max-payload <bytes> Max WebSocket message size (default: 1048576)
--rate-limit <n> Max connections per minute per IP (default: 10)
--health Print server health check and exit
encrypt / decrypt flag```--per-var Per-variable encryption (keys visible, values encrypted) --to Encrypt to specific recipients (multi-key)
### Flag globali```
--verbose / -v Debug output (never prints secret values)
--quiet / -q Minimal output (for scripting)
| enseal | Slack DM | 1Password Share | dotenvx | croc | |
|---|---|---|---|---|---|
| Zero configurazione | Sì | Sì | No | No | Sì |
| Crittografia end-to-end | Sì | No | Sì | N/D | Sì |
| Effimero (nessuna cronologia) | Sì | No | Sì | N/D | Sì |
| Consapevole di .env | Sì | No | No | Sì | No |
| Iniezione di processo | Sì | No | No | Sì | No |
| Validazione dello schema | Sì | No | No | No | No |
| Crittografia a riposo | Sì | N/D | N/D | Sì | No |
| Relay auto-ospitabile | Sì | No | No | N/D | Sì |
| Supporto stringa grezza/pipe | Sì | Sì | No | No | Sì |
--to (completato)--upload) (corrente)MIT