envelops│v0.1.1│mitstatus: operational
▌ ops panel // self-hosted // oss

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.

[ 01 ]
self-hosted

Single Next.js process, one SQLite file, one volume. Deploy it behind your VPN, behind Tailscale, behind whatever. Your keys never leave.

[ 02 ]
wire-compatible

Speaks the exact protocol the commercial CLI expects. Your team keeps using dotenvx-ops — just pointed at a different hostname.

[ 03 ]
mit licensed

Fork it, audit it, embed it, run it forever. No seats, no feature gates, no surprise pricing page, no phone-home.

§ our thoughts
Not a line-for-line clone. envelops intentionally deviates from the commercial panel in a handful of places — read the why behind each one.
read deviations
§ drop-in

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.

method 01env var
~/.config/dotenvx — method 1
$ DOTENVX_OPS_HOSTNAME=https://ops.mycompany.com dotenvx-ops login
method 02flag
~/.config/dotenvx — method 2
$ dotenvx-ops login --hostname https://ops.mycompany.com
method 03persist
~/.config/dotenvx — method 3
$ echo 'DOTENVX_OPS_HOSTNAME=https://ops.mycompany.com' >> ~/Library/Preferences/dotenvx/.env
§ quickstart

docker run

~30 seconds on a warm machine. Needs only Docker + openssl.
deploy — docker
# 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
alt — local dev
$ npm install
$ npm run db:migrate
$ npm run dev

Server boots at http://localhost:3000.

alt — e2e against real cli
$ npm i -g @dotenvx/dotenvx-ops
$ ENVELOPS_TEST_PORT=3100 \
    ENVELOPS_BASE_URL=http://localhost:3100 \
    PORT=3100 npm run dev &
$ npm run test:e2e

Tests the panel against the upstream commercial CLI.

§ configuration

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.

name
req
ENVELOPS_MASTER_KEY
required
32 raw bytes, hex or base64. Wraps private keys at rest. openssl rand -hex 32.
ENVELOPS_DEV_MODE
dev only
Set to 1 to boot without a master key using a constant insecure dev key. Never set in prod.
ENVELOPS_BASE_URL
recommended
External URL of this server. Baked into OAuth verification_uri.
ENVELOPS_TRUST_PROXY
optional
Set to 1 behind Caddy / Cloudflare / nginx. Required for correct per-IP rate limiting.
DATABASE_URL
optional
Defaults to file:./data/envelops.db. Postgres supported (phase 2).
ENVELOPS_GITHUB_CLIENT_ID
optional
GitHub OAuth app client id. Enables "sign in with github" on the panel.
ENVELOPS_GITHUB_CLIENT_SECRET
optional
Pairs with the client id above.
ENVELOPS_MAILGUN_API_KEY
optional
Mailgun private API key. Combined with the domain, login links ship by email.
ENVELOPS_MAILGUN_EMAIL_DOMAIN
optional
Bare hostname (e.g. mg.mycompany.com). Not a URL.
ENVELOPS_MAILGUN_REGION
optional
us (default) or eu. Picks the Mailgun API host.
§ architecture

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.

runtime
Next.js 16 · React 19 · Node ≥ 22
storage
SQLite (default) · Postgres (phase 2)
crypto
AES-256-GCM at rest · secp256k1 keypairs
auth
email magic link · GitHub OAuth
delivery
Mailgun (us / eu)
footprint
single container · single SQLite volume
§ not yet shipped

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.

§ fin

own the ops panel.

Ten minutes from zero to logged-in. MIT from the first commit to the last.

│star on github
envelops · v0.1.1│mit│© 2026

This project is not affiliated with, endorsed by, or sponsored by dotenvx. It is a clean-room reimplementation of the wire protocol of the commercial dotenvx-ops CLI.