Use dotenvx with Turborepo
Use dotenvx with Turborepo
Find code examples for this guide on GitHub.
Initial setup
Create a new monorepo.
npx create-turbo@latest
This will create a handful of files and a couple workspaces (apps).
$ ls -1
README.md
apps/
node_modules/
package-lock.json
package.json
packages/
turbo.json
Edit apps/web/app/page.tsx
to include process.env.HELLO
– to say 'Hello World'.
apps/web/app/page.tsx
export default function Page() {
return (
<>
Hello {process.env.HELLO}
</>
);
}
Declare the apps/web
environment variable in turbo.json
by adding a web#build
configuration under the pipeline
configuration key.
turbo.json
...
"pipeline": {
...
"web#build": {
"dependsOn": [
"^build"
],
"env": [
"HELLO"
]
},
...
Run dotenvx
Install dotenvx
under apps/web
cd apps/web
npm install @dotenvx/dotenvx --save
cd ../..
Create a .env
file under apps/web
.
apps/web/.env
# apps/web/.env
HELLO="World"
Adjust your apps/web/package.json
scripts to inject your env using dotenvx
.
apps/web/package.json
...
"scripts": {
"dotenvx": "dotenvx",
"build": "dotenvx run -- turbo build",
"dev": "dotenvx run -- turbo dev",
"lint": "dotenvx run -- turbo lint",
"format": "prettier --write \"**/*.{ts,tsx,md}\""
},
See more about using environment variables with turborepo.
Try running it locally.
$ npm run dev
web:dev: [[email protected]] injecting env (1) from .env
docs:dev: - ready started server on 0.0.0.0:3001, url: http://localhost:3001
web:dev: - ready started server on 0.0.0.0:3002, url: http://localhost:3002
Visit localhost:3002.
Your app will say Hello World
. The values from your .env
file were successfully injected into your env.
Add production environment
Create a .env.production
file under apps/web
.
apps/web/.env.production
# apps/web/.env.production
HELLO="production"
Modify your apps/web/package.json
scripts to use the .env.production
file.
apps/web/package.json
...
"scripts": {
"dotenvx": "dotenvx",
"build": "dotenvx run --env-file=.env.production -- turbo build",
"dev": "dotenvx run --env-file=.env.production -- turbo dev",
"lint": "dotenvx run --env-file=.env.production -- turbo lint",
"format": "prettier --write \"**/*.{ts,tsx,md}\""
},
Your app will say Hello production
, simulating production. Solid. Let's encrypt your secrets next.
Encrypt secrets
Use dotenvx
to encrypt your apps/web
secrets.
dotenvx encrypt apps/web
Also run
dotenvx gitignore
to make sure your.env.keys
file is gitignoreddotenvx gitnore
This generates a .env.vault
and .env.keys
file.
apps/web/.env.vault
#/-------------------.env.vault---------------------/
#/ cloud-agnostic vaulting standard /
#/ [how it works](https://dotenv.org/env-vault) /
#/--------------------------------------------------/
# development
DOTENV_VAULT_DEVELOPMENT="V4NYVn0Pow6Uf2ez2mbHEzTrYURloHL6VDAFRLqnQBppA/OmHI5x5AXoxCMVor7wOg=="
# production
DOTENV_VAULT_PRODUCTION="YZkhtbh1IlzBgIamAAsG5nzGPfH6p8Zbuj9egXoziviVu/eYIyNjJWtIYyhiW/vHhFbqbsvo5+P9b27OC6ZC7qU="
The .env.vault
file contains encrypted (AES-256-GCM) versions of your secrets, and the .env.keys
file contains the decryption keys.
apps/web/.env.keys
#/!!!!!!!!!!!!!!!!!!!.env.keys!!!!!!!!!!!!!!!!!!!!!!/
#/ DOTENV_KEYs. DO NOT commit to source control /
#/ [how it works](https://dotenv.org/env-keys) /
#/--------------------------------------------------/
DOTENV_KEY_DEVELOPMENT="dotenv://:key_e507c60efa8841d8d5bbb85bd701ee92406cf3b06506d1d80f1553c2a72791e4@dotenvx.com/vault/.env.vault?environment=development"
DOTENV_KEY_PRODUCTION="dotenv://:key_10283719af6a30ef49050048617f4fea10c23a38021fbebeb9fd858caa01852e@dotenvx.com/vault/.env.vault?environment=production"
You SHOULD commit .env.vault
to code. It is safe and recommended to do so. But DO NOT commit .env.keys
to code. Keep them somewhere safe like 1Password or dotenvx hub.
We're ready to simulate production by using the DOTENV_KEY
.
Set DOTENV_KEY
Set DOTENV_KEY
using the production key in your .env.keys
file.
DOTENV_KEY='dotenv://:key_10283719af6a30ef49050048617f4fea10c23a38021fbebeb9fd858caa01852e@dotenvx.com/vault/.env.vault?environment=production' npm run dev
Your script starts and env
is successfully injected using the encrypted contents of .env.vault
.
web:dev: [[email protected]] injecting env (1) from encrypted .env.vault
docs:dev: - ready started server on 0.0.0.0:3001, url: http://localhost:3001
web:dev: - ready started server on 0.0.0.0:3002, url: http://localhost:3002
Visit your url and it says Hello production
.
You succesfully used the new .env.vault
standard to encrypt and deploy your secrets. This is much safer than scattering your secrets across multiple third-party platforms and tools. Whenever you need to add or change a secret, just re-encrypt .env.vault
and redeploy.
Great job! That's pretty much it. See the bonus section(s) below to go a little deeper.
Bonus
Try changing the value of .env.production
to your name.
.env.production
# .env.production
HELLO="Mot"
Re-encrypt it.
dotenvx encrypt apps/web
Commit .env.vault
safely to code and re-run npm run dev