How to Encrypt a .env File and Run Your App with Dotenvx
Updated
Run dotenvx encrypt to turn your .env values into ciphertext, commit the encrypted file with git, then start your app with dotenvx run -- <your command> so the secrets are decrypted and injected at runtime. This works for any language or framework, and the only thing your infrastructure needs is the private key — not the plaintext secrets.
Before You Start
You need:
- A project with a
.envfile containing the values you want to protect. - Dotenvx installed (see the Quickstart on dotenvx.com).
- Git initialized in the project, since the encrypted file is meant to travel with your code.
- A way to set one private key in your runtime environment. Dotenvx's design is built around a single private key held on your infrastructure.
Step 1: Encrypt the .env File
$ dotenvx encrypt
◈ encrypted (.env)
Input: your existing plaintext .env.
Action: dotenvx encrypt converts the values into ciphertext.
Expected result: the .env file now holds ciphertext, and only your private key can unlock the values.
After this step, the file is safe to share through git — the values are unreadable without the key.
Step 2: Commit the Encrypted File
$ git add .env
$ git commit -m "encrypt .env"
Input: the encrypted .env.
Action: stage and commit it alongside your code.
Expected result: the encrypted secrets travel with the repository. Anyone with the repo gets the ciphertext; only holders of the private key can decrypt it.
This is the core shift: instead of coordinating secrets out-of-band, you deliver them the same way you deliver code.
Step 3: Run Your App
$ dotenvx run -- node index.js
⟐ injected env (2) from .env
Input: the encrypted .env plus your private key available to the process.
Action: dotenvx run -- <command> decrypts the values and injects them as environment variables just-in-time.
Expected result: your app starts with the secrets available as normal environment variables. The injected env (2) line confirms how many variables were loaded.
Swap node index.js for whatever starts your app — the pattern is the same for any language or framework.
How the Pieces Fit
Dotenvx is built from three primitives the site names directly:
| Primitive | Role |
|---|---|
| Git | Distributes the encrypted file with your code |
.env |
The open standard for loading secrets into code |
| secp256k1 | Asymmetric encryption that keeps values unreadable |
The design keeps the decryption key separate from the code, following twelve-factor config: secrets travel with code without becoming part of it. Because only one private key needs to be set on your infrastructure, there's no async coordination of secrets and no centralized service that can go down and take your secret delivery with it.
Common Snags
- App can't decrypt values. The private key isn't available to the
dotenvx runprocess. Confirm the key is set in the environment where the command executes. - You committed plaintext by mistake. Run
dotenvx encryptfirst, then commit. The commit step is only safe after encryption. - You expected a secrets server. Dotenvx deliberately avoids one; delivery happens through git and decryption happens locally at runtime.
When This Approach Fits
Choose Dotenvx if you want secrets to ship with your repository and be decrypted at runtime from a single private key, with no central secrets service in the path. If your workflow depends on a hosted secrets manager with rotation and access auditing, that's a different model — Dotenvx's stated design is to reuse git, .env, and secp256k1 rather than build a new delivery mechanism.