Environment secrets, encrypted, scoped, and audited — as a hosted product, or run entirely on your own infrastructure.
Envi is an environment-secret manager: encrypted .env values, scoped access, an audit trail, and a CLI that gets a secret from your database into a running process without anyone typing it into Slack. Envi is built and run as a product — this repository is also the entire self-hostable stack, for teams who'd rather keep everything on infrastructure they control.
Full documentation: docs.envisecrets.com
curl -fsSL https://install.envisecrets.com | shirm https://install.envisecrets.com/install.ps1 | iexThe script detects your OS and CPU architecture, verifies a SHA-256 checksum before installing, and works on macOS, Linux, Termux, and Windows.
Or through a package manager, if Node is already in your stack:
npm install -g @shellhaki/envi-cli # or: bun add -g / pnpm add -g / yarn global addNo install script runs: the binary arrives as an optional dependency chosen by os and cpu, so it works under npm ci --ignore-scripts and pnpm's defaults. envi update knows which way you installed and uses the matching route.
- Encrypted at rest — every secret is sealed with AES-256-GCM before it touches Postgres. Nothing is ever stored in plaintext, including in the version history kept for every change.
- Scoped access — grant a collaborator
read,write, ormanageon a project or a single environment. Production doesn't get touched by accident. - Passwordless auth — sign in with a one-time email code or approve a device from your browser. No passwords exist anywhere in the system to leak.
- Service tokens — long-lived, scoped credentials for CI/CD pipelines and deploy scripts, independent of any human's session.
- Multiple environments — dev, staging, prod as separate sets of secrets in one project.
envi origin switch prodrepoints your working directory;envi push .env origin prodwrites to one you aren't on. - No
.envon disk —envi run -- npm startinjects secrets into the process that needs them and exits with that process's own status.envi modedits them in a terminal editor, andenvi push --cleanremoves the file once it is up. Nothing plaintext has to stay on your filesystem. Prefer not to typeenvi run?envi hook installloads a project's secrets when youcdinto it, after a one-timeenvi allow. - Runs in a container —
ENTRYPOINT ["envi", "run", "--"]and oneENVI_TOKENvariable. No.envin the image, no environment id baked into a layer, same image in every environment. - Key-value store — a project-wide store your application reads and writes at runtime over HTTP, encrypted like everything else. Separate from your secrets: if your code writes it, it goes here; if you deploy it, it's a secret.
- Full audit trail — every write and delete is logged against the org, the actor, and the exact secret touched. Reads are logged once per environment with the number of secrets they covered, so a command you run all day stays readable in the feed.
- Email invitations — invite a teammate by address; they click through, sign in (or sign up on the spot if they're new), and land with access already waiting.
- Copy a whole environment out — platforms that build and run your code themselves, like Vercel or Netlify, have no process for
envi runto wrap. Copy all on the dashboard puts every secret on your clipboard as.envtext, which their environment-variable screens parse in one paste.envi copydoes the same from the terminal, andenvi copy --singlepicks out one value. - CLI and dashboard, one API —
envi pull/push/diffyour.envfiles from the terminal, or manage everything visually. Same backend, same permissions, your choice of interface.
git clone https://github.com/shellhaki/envi.git
cd envi
cp .env.example .env # fill in the four required values
docker compose up -dThat brings up Postgres, Redis, the API, the install-script server, and the dashboard together. The database schema is applied automatically on first start. The dashboard lands on localhost:3000.
You need four values in .env before it will start:
| Variable | What it is |
|---|---|
ENVI_ENCRYPTION_KEY |
Exactly 32 characters — openssl rand -hex 16. Decrypts every secret you store. |
ENVI_SESSION_SECRET |
At least 32 characters — signs dashboard session cookies. |
RESEND_API_KEY |
For one-time sign-in codes and invitations. |
RESEND_FROM |
Sender address, on a domain verified with Resend. |
Prefer running the binaries directly under a process manager instead? See the deployment walkthrough.
flowchart LR
CLI["envi CLI"] -->|bearer token| API["Go API"]
Web["Next.js dashboard"] -->|session cookie| API
API --> PG[("Postgres\nencrypted secrets\n+ key-value store")]
API --> Redis[("Redis\nOTP codes")]
API --> Mail["Resend\nemail delivery"]
The CLI and the dashboard are two clients of the same API — neither one is a special case. Secrets are encrypted before they reach Postgres and decrypted only in memory, on demand, for a request that has already passed the access-grant check.
| Path | What it is |
|---|---|
cmd/api |
The API server — the entire backend |
cmd/envi |
The CLI, released for macOS, Linux, Termux, and Windows |
cmd/install |
Tiny server for the curl | sh install scripts |
internal/ |
Domain packages: secrets, auth, access, invitations, audit, mail |
npm/ |
Builds the npm packages that install the CLI binary |
ui/ |
The Next.js dashboard (deployable separately, e.g. to Vercel) |
docs/ |
The documentation site, its own Next.js app |
migrations/ |
schema.sql for a fresh database, numbered files to catch one up |
traefik/ |
Reverse-proxy config for a non-Docker deployment |
- Secret values: AES-256-GCM, one key, sealed before every write.
- Tokens: access, refresh, service, and invitation tokens are all stored as hashes — the plaintext exists only once, at issuance, in the response the caller already has.
- Sessions: HMAC-signed, HTTP-only,
SameSite=Strictcookies on the web; rotating refresh tokens everywhere. - Rate limits: OTP requests and attempts are capped; invitations are capped per sender, so a compromised account can't be used to burn a sending domain's reputation.
| Command | What it does |
|---|---|
envi auth |
Sign in — browser device flow by default, --email for a one-time code |
envi init |
Link the current directory to a project and environment |
envi pull |
Write the environment's secrets to .env |
envi push |
Send local .env changes up, with conflict detection |
envi push <file> [origin <name>] |
Push a named file, optionally to another environment |
envi push --clean |
Push, then delete the file |
envi diff |
Show what's changed between local and remote before you push |
envi run -- <command> |
Run a command with the secrets injected, without writing a .env |
envi hook install |
Load a project's secrets automatically when you cd into it (zsh, bash, fish, PowerShell) |
envi allow / envi deny |
Let this folder load its secrets automatically, or stop it |
envi mod |
Edit this origin's secrets in a terminal editor, nothing written to disk |
envi clean |
Delete the local .env once the server already has it |
envi copy |
Copy the whole origin to the clipboard as .env text |
envi copy <key> |
Copy one secret's value |
envi copy --single |
Pick a secret from a list and copy it |
envi project create <name> |
Create a project |
envi key create --name <name> |
Create a personal API key |
envi auth --key <key> |
Sign in with an API key instead of the browser |
envi origin list |
List the project's environments, marking the current one |
envi origin switch <name> |
Point this directory at another environment and pull it |
envi origin create <name> |
Create an environment under the current project |
envi share <email> |
Invite a collaborator with scoped access |
envi invite accept <token> |
Accept an invitation |
envi token create --name <name> |
Mint a scoped service token for CI/CD |
envi activity |
Recent reads and writes across your org |
envi logout |
Revoke the current session |
envi update |
Check for or install a new version |
envi uninstall |
Remove envi from this machine |
Full reference, including flags and exit codes: docs.envisecrets.com/cli.
Postgres and Redis running locally, then:
make db-init # apply the schema, or bring migrations up to date
make build-api build-install # binaries into bin/
cd ui && bun dev # dashboard on :3000
cd docs && bun dev # docs site on :3001make help lists every target.
MIT — see LICENSE.