Core Concepts

Project Hierarchy

ev organizes secrets in a five-level hierarchy:

Project
└── App
    └── Environment
        └── Secret
            └── Release

Project

A project maps to a single git repository. It is identified by a unique ID stored in ev.yaml. Every project has a symmetric encryption key that is used to encrypt and decrypt all secret values within the project.

App

An app is a logical service within your project. A single-repo project typically has one app. A monorepo might have frontend, backend, worker, and so on. Apps are defined in ev.yaml with a filesystem path so ev can auto-detect context from your working directory.

Environment

An environment is a named slot within an app — for example dev, staging, or prod. Each environment holds an independent set of secrets. You can create as many environments as you need with ev env create.

Secret

A secret is a key-value pair stored within an environment. Values are encrypted before they leave your machine and are never stored in plaintext on the ev server.

Release

Every ev push creates a release — an immutable snapshot of the full set of secrets at that point in time. Releases are used for ev log, ev diff, and ev rollback. No history is ever deleted.

Roles

ev has three access roles per project:

RoleView secretsPush / pullCreate environmentsManage access
ViewerYesPull onlyNoNo
DeveloperYesYesYesNo
AdminYesYesYesYes

Assign a role when granting access:

ev access grant alice@example.com --role developer
ev access grant bob@example.com --role viewer

The default role is developer.

Encryption Model

ev uses libsodium for all cryptographic operations. The server never sees plaintext values.

Secret Value Encryption

Secret values are encrypted with crypto_secretbox — an authenticated symmetric cipher (XSalsa20-Poly1305). The encryption key is the project key.

plaintext value
  → crypto_secretbox(value, nonce, project_key)
  → ciphertext blob stored on server

Project Key Distribution

Each team member has an asymmetric keypair (Curve25519) stored in ~/.config/ev/. When you are added to a project, the project key is sealed with your public key using crypto_box_seal:

project_key
  → crypto_box_seal(project_key, member_public_key)
  → sealed key stored server-side per member

When you run ev pull or ev push, ev fetches your sealed key, decrypts it with your local private key, and uses the project key to encrypt or decrypt values — all locally.

Key Rotation

Running ev access rotate generates a new project key, re-encrypts all secrets, and re-seals the key for every current team member. Revoked members are excluded, which invalidates their access even if they cached the old key.

What the Server Stores

DataStored as
Secret valuesCiphertext (libsodium)
Project keysSealed per-member ciphertext
Release metadataPlaintext (timestamps, author)
Secret keys (names)Plaintext

Secret names (e.g. DATABASE_URL) are stored in plaintext so the server can serve diffs and metadata without decryption. Only values are encrypted.

On this page