envelops
Self-hosted open-source alternative to the dotenvx Ops panel. Run your team's private keys on your own infrastructure.
Wire-protocol compatible with the commercial dotenvx-ops CLI — swap the hostname, everything works.
Single Next.js process, one SQLite file, one volume. Deploy it behind your VPN, behind Tailscale, behind whatever. Your keys never leave.
Speaks the exact protocol the commercial CLI expects. Your team keeps using dotenvx-ops — just pointed at a different hostname.
Fork it, audit it, embed it, run it forever. No seats, no feature gates, no surprise pricing page, no phone-home.
point the cli at your box
Three equivalent ways. Flag, env var, or persisted preference. Pick whichever your ops runbook prefers.
Then follow the login URL, sign in, enter the device code. The CLI finishes logging in and dotenvx-ops commands just work.
$ DOTENVX_OPS_HOSTNAME=https://ops.mycompany.com dotenvx-ops login$ dotenvx-ops login --hostname https://ops.mycompany.com$ echo 'DOTENVX_OPS_HOSTNAME=https://ops.mycompany.com' >> ~/Library/Preferences/dotenvx/.envdocker run
openssl.# 1. generate a master key (32 random bytes)
$ openssl rand -hex 32 > .master-key
# 2. boot the server, mount a data volume, hand over the key
$ docker run -d --name envelops \
-p 3000:3000 \
-v envelops-data:/data \
-e ENVELOPS_MASTER_KEY=$(cat .master-key) \
-e ENVELOPS_BASE_URL=https://ops.mycompany.com \
ghcr.io/itsjustmechris/envelops:latest
# 3. point the CLI at it
$ DOTENVX_OPS_HOSTNAME=https://ops.mycompany.com dotenvx-ops login$ npm install
$ npm run db:migrate
$ npm run devServer boots at http://localhost:3000.
$ npm i -g @dotenvx/dotenvx-ops
$ ENVELOPS_TEST_PORT=3100 \
ENVELOPS_BASE_URL=http://localhost:3100 \
PORT=3100 npm run dev &
$ npm run test:e2eTests the panel against the upstream commercial CLI.
env(5) — envelops(7)
Everything is an environment variable. No config files, no YAML, no runtime admin panels. Deploy it the same way you deploy a Rails monolith in 2011 — and it'll survive just as long.
openssl rand -hex 32.us (default) or eu. Picks the Mailgun API host.one process. one file. one backup.
A single Next.js process. SQLite by default — one file, one volume, one backup. Private keys are wrapped with AES-256-GCM under a server master key.
honest about the gaps
- ▸automated rotation connectors
Manual rotation works today. Automated pluggable connectors (GitHub Actions, Vercel, Fly, AWS) are staged for phase 2.
- ▸SAML / generic OIDC
GitHub OAuth covers the common case. Generic OIDC + SAML are planned but not in the box yet.
- ▸per-project RBAC
Everyone in the instance is an operator today. Per-project roles are planned behind a stable API.
- ▸postgres driver
SQLite ships today. Postgres is wired in the drizzle layer but the deploy story is still baking.
own the ops panel.
Ten minutes from zero to logged-in. MIT from the first commit to the last.