Core Concepts
Understanding how envctl works will help you use it effectively. This page covers the fundamental concepts: identities, projects, environments, sync, and encryption.
Identity and Keypairs
Your identity is how envctl knows who you are. When you run envctl init, it generates a cryptographic keypair:
- Private key — Encrypted with your passphrase, stored locally. Never leaves your machine.
- Public key — Shared with teammates so they can encrypt secrets for you.
Your identity is identified by a fingerprint—a hash of your public key:
$ envctl whoami
Name: alice-macbook
Fingerprint: sha256:7f3a9b2c4d5e6f7a...
This fingerprint is used to verify that you're communicating with the right person. When you invite someone to a project, you share their fingerprint to confirm their identity.
Where Keys Are Stored
| File | Contents | Sensitive? |
|---|---|---|
~/.config/envctl/identity.enc |
Encrypted private key | Yes (encrypted) |
~/.config/envctl/identity.pub |
Public key | No (shareable) |
~/.config/envctl/identity.json |
Metadata (name, created date) | No |
Hardware-Backed Keys (YubiKey)
For extra security, you can store your private key on a YubiKey. The key never leaves the hardware device—signing operations happen on the YubiKey itself.
$ envctl init --yubikey
Projects
A project is a collection of secrets and the team members who have access to them. Projects are typically associated with a codebase or service.
$ envctl project create myapp
Each project has:
- A name — Identifies the project (e.g., "myapp", "backend-api")
- Members — The people who can access secrets
- Environments — Separate sets of secrets (dev, staging, prod)
- A membership chain — Cryptographic record of who joined, left, and what access they have
Project Directory
When you create or link a project, envctl creates a .envctl/ directory:
myapp/
├── .envctl/
│ ├── config # Project settings
│ ├── dev.enc # Encrypted dev secrets
│ ├── staging.enc # Encrypted staging secrets
│ └── prod.enc # Encrypted prod secrets
├── src/
└── package.json
The .envctl/ directory can be committed to git—the secrets are encrypted. This enables GitOps workflows where your CI can decrypt secrets from the repository.
Environments
Environments are separate namespaces for secrets within a project. By default, projects have three environments:
- dev — Local development
- staging — Testing and QA
- prod — Production
Each environment has its own set of secrets and its own access control. A team member might have access to dev and staging, but not prod.
$ envctl env list
Environments for myapp:
* dev (3 members)
staging (2 members)
prod (1 member)
The asterisk (*) shows your current environment. Use envctl env use <name> to switch.
Environment-Based Access Control
Access is granted per-environment:
# Grant access to dev and staging
$ envctl project grant bob --env dev,staging
# Later, grant prod access
$ envctl project grant bob --env prod
This allows you to follow the principle of least privilege—developers get dev access by default, and prod access is granted only when necessary.
The Ops Chain (How Sync Works)
envctl uses an ops chain to track changes to secrets. Think of it like a git log for your environment variables—every change is recorded as an operation.
What's in an Operation?
Each operation contains:
- Type — What happened (set, delete, etc.)
- Key — Which variable was affected
- Value — The new value (encrypted)
- Timestamp — When it happened
- Author — Who made the change (signed)
- Previous hash — Links to the previous operation
Operations are cryptographically signed and hash-linked. You can't tamper with history without invalidating all subsequent operations.
How Sync Works
- You make a change:
envctl env var set API_KEY=secret - envctl creates an operation, signs it with your key, and adds it to your local chain
- The daemon broadcasts the operation to connected peers
- Peers verify your signature and apply the operation to their chain
- Peers re-broadcast to their peers (if not already seen)
This is eventually consistent—all peers will converge to the same state, but there might be brief delays during sync.
Conflict Resolution
If two people set the same variable at the same time, both operations are recorded. The "winner" is determined by timestamp (last write wins), but both operations remain in the chain for audit purposes.
Encryption Model
envctl uses a hybrid encryption scheme designed for post-quantum security:
Algorithms
| Purpose | Algorithm | Notes |
|---|---|---|
| Key encapsulation | ML-KEM-768 | Post-quantum secure (FIPS 203) |
| Symmetric encryption | AES-256-GCM | Authenticated encryption |
| Signatures | Ed25519 | Fast, compact signatures |
| Key derivation (passphrase) | Argon2id | Memory-hard password hashing |
| Key derivation (keys) | HKDF-SHA256 | Derives AES key from shared secret |
How Secret Encryption Works
When you set a secret:
- envctl generates a random AES-256 key for this operation
- The secret value is encrypted with AES-256-GCM
- The AES key is encapsulated using ML-KEM for each recipient
- The operation is signed with your Ed25519 key
Each team member receives a copy of the AES key, encrypted to their public key. Only recipients can decrypt the secret.
Identity Key Encryption
Your private key is encrypted at rest:
- Your passphrase is fed through Argon2id with a random salt
- The derived key encrypts your private key with AES-256-GCM
- The encrypted key and salt are stored in
identity.enc
Without your passphrase, your private key cannot be recovered.
Relay Servers
The relay is an optional server that enables async sync. It's useful when:
- Team members are in different time zones and rarely online together
- You're working from different networks (no direct P2P possible)
- You want guaranteed delivery even when peers are offline
What the Relay Sees
| Data | Visible to Relay? |
|---|---|
| Secret values | No (encrypted) |
| Secret keys (variable names) | No (encrypted) |
| Who is syncing | Yes (IP addresses, timing) |
| Message sizes | Yes |
| Project/team identifiers | Yes (for routing) |
The relay is a store-and-forward service. It holds encrypted messages until recipients come online to collect them. It cannot read your secrets.
Enabling the Relay
$ envctl project relay set relay.envctl.dev
✓ Relay configured for myapp
See the Relay guide for more details.
The Daemon
The daemon is a background process that handles P2P networking and sync. It:
- Listens for incoming peer connections
- Discovers peers on the local network via mDNS
- Maintains connections to the relay (if configured)
- Broadcasts changes when you modify secrets
- Applies incoming changes from peers
$ envctl daemon start
✓ Daemon started
P2P port: 7834
Web UI: http://localhost:7835
The daemon is optional for local-only use. If you're only using secrets on one machine without syncing, you don't need to run it.
Daemon vs. CLI
Most commands work without the daemon running:
| Feature | Daemon Required? |
|---|---|
| Set/get secrets locally | No |
| Export .env file | No |
| CI bundle operations | No |
| Sync with peers | Yes |
| Relay connection | Yes |
| Web UI | Yes |
Membership Chain
In addition to the ops chain (for secrets), each project has a membership chain that tracks:
- Who created the project
- Who was invited and when
- Who was removed and why
- Access level changes
- Environment access grants/revocations
This chain is also cryptographically signed and immutable. You can audit membership history:
$ envctl project log
2024-03-01 16:00 alice Removed bob (reason: Left company)
2024-02-15 11:30 alice Granted bob reader access to prod
2024-01-20 14:00 alice Added charlie (member)
2024-01-10 09:00 alice Added bob (member)
2024-01-05 10:00 alice Created project myapp
Summary
- Identity — Your cryptographic keypair, protected by a passphrase
- Project — A collection of secrets and team members
- Environment — A namespace for secrets (dev, staging, prod)
- Ops chain — Append-only log of all secret changes
- Membership chain — Append-only log of team changes
- Relay — Optional server for async sync
- Daemon — Background process for P2P networking
Next Steps
- Command Reference — Full list of all commands
- Security Best Practices — Recommendations for secure usage
- Multiple Environments — Managing dev, staging, and prod