Use dotenvx with Nx

Use dotenvx with Nx

Initial setup

Create a new monorepo.

npx create-nx-workspace --preset=express

If prompted for a workspace, type app. This will create a handful of files and a couple workspaces (apps).

$ ls -1
README.md
apps/
jest.config.ts
jest.preset.js
node_modules/
nx.json
package-lock.json
package.json
tsconfig.base.json

Edit apps/app/src/main.ts to include process.env.HELLO – to say 'Hello World'.

apps/app/src/main.ts

import express from 'express';
import * as path from 'path';

const app = express();

app.use('/assets', express.static(path.join(__dirname, 'assets')));

app.get('/', (req, res) => {
  res.send(`Hello ${process.env.HELLO}`);
});

const port = process.env.PORT || 3333;
const server = app.listen(port, () => {
  console.log(`Listening at http://localhost:${port}/`);
});
server.on('error', console.error);

Run dotenvx

Install dotenvx via brew, npm, or other options. Here I'm using brew.

brew install dotenvx/brew/dotenvx

Create a .env file under apps/app.

apps/app/.env

# apps/app/.env
HELLO="World"

Run nx serve prefaced by dotenvx.

$ dotenvx run --env-file=apps/app/.env -- npx nx serve app

[[email protected]] injecting env (1) from apps/app/.env

> nx run app:serve:development
...

Visit localhost:3333.

localhost:3333

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/app.

apps/app/.env.production

# apps/app/.env.production
HELLO="production"

Encrypt production

dotenvx encrypt -f apps/app/.env.production

Your .env.production file is now encrypted, and you have a .env.keys file.

apps/app/.env.production

#/-------------------[DOTENV_PUBLIC_KEY]--------------------/
#/            public-key encryption for .env files          /
#/       [how it works](https://dotenvx.com/encryption)     /
#/----------------------------------------------------------/
DOTENV_PUBLIC_KEY_PRODUCTION="025a54defaeff32caa2bbe60537b88b5b89716eade6df08418d7a68f5c4f742be6"

# .env.production
HELLO="encrypted:BD+uttK9iBuXnfx6HukDK06IGk0pQARwivtxM+ZiePvhRxHyQL3UD0sf0ayLw/P5Y/BED//zRiTlUf6nENuu7QhNJ24g3uADfrDfhvYi/MOHjmfKyRiu+yOxSw6e+c0yRNukS+n8SxONnec="

apps/app/.env.keys

#/------------------!DOTENV_PRIVATE_KEYS!-------------------/
#/ private decryption keys. DO NOT commit to source control /
#/     [how it works](https://dotenvx.com/encryption)       /
#/----------------------------------------------------------/

# .env.production
DOTENV_PRIVATE_KEY_PRODUCTION="424d0ea072eb17c6bee9b4b42ff6333513cf128ea3d5d60ccf79246ca7c3f786"

We're ready to inject the encrypted .env.production secrets into the app on boot.

Set decryption key

Set DOTENV_PRIVATE_KEY_PRODUCTION using the production key in your apps/app/.env.keys file.

DOTENV_PRIVATE_KEY_PRODUCTION="424d0ea072eb17c6bee9b4b42ff6333513cf128ea3d5d60ccf79246ca7c3f786" dotenvx run -f apps/app/.env.production -- npx nx serve app

Your script starts and env is successfully injected using the encrypted contents of .env.production.

[[email protected]] injecting env (2) from apps/app/.env.production
Listening at http://localhost:3333/

Visit your url and it says Hello production.

localhost:3333

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.

npm run dotenvx -- set HELLO Mot -f .env.production

Commit .env.production safely to code and redeploy.