Use dotenvx with Fly

Use dotenvx with Fly

Initial setup

Install the necessary web server libraries in the language of your choice.

npm install express --save

Create a simple Hello World program.

// index.js
const express = require('express')
const app = express()
const PORT = process.env.PORT || 3000

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

app.listen(PORT, () => {
  console.log(`Server running on port:${PORT}`)
})

Create Dockerfile.

# Dockerfile
FROM node:20
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "index.js"]

Create .dockerignore.

.dockerignore

# .dockerignore
.env.keys

Create fly.toml.

[http_service]
  internal_port = 3000

Commit that to code and deploy it to Fly.

flyctl launch
flyctl deploy
yourapp.fly.dev

Once deployed, your app will say 'Hello [blank]' as it doesn't have a way to access the environment variable yet. Let's do that next.

Run dotenvx

Install dotenvx in your Dockerfile and prepend your app command with dotenvx run --.

# Dockerfile
FROM node:20
WORKDIR /app

# Install dotenvx
RUN curl -fsS https://dotenvx.sh/ | sh

COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000

# Prepend dotenvx run
CMD ["dotenvx", "run", "--", "node", "index.js"]

Add production environment

Create .env.production in the root of your project.

# .env.production
HELLO="production"

Encrypt production

dotenvx set HELLO production --encrypt -f .env.production

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

.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="

.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 on Fly using the production key in your .env.keys file. We'll use the fly cli, but you can also use their dashboard.

flyctl secrets set DOTENV_PRIVATE_KEY_PRODUCTION='424d0ea072eb17c6bee9b4b42ff6333513cf128ea3d5d60ccf79246ca7c3f786'

Redeploy.

flyctl deploy

Your app restarts and env is successfully injected using the encrypted contents of .env.production.

$ flyctl logs
[info] INFO Preparing to run: `docker-entrypoint.sh dotenvx run -- node index.js` as root
[info][[email protected]] injecting env (2) from .env.production
[info]Server running on port:3000

Visit your url and it says Hello production.

yourapp.fly.com

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 --encrypt

Commit .env.production safely to code and redeploy.