dotenvx · Secure and Next-Generation dotenv Successor

Illustration- from dotenv to dotenvx: "dotenv. better. - dotenvx the next gen config library, by the creator of doten
Updates
July 2024 - Add decryption capabilities included in version 1.6.0.
June 2024 - Removal of the .env.vault mechanism (cf. FAQ)

The successor to dotenv (.env files) is just around the corner... Its name? dotenvx!
But first, let's take a look back at its predecessor, dotenv.

(you can still go directly to the dotenvx, section if you wish)

Why dotenv?

From Constants to Environment Variables

To address the environment-specific configuration challenges encountered during application deployment, it was common practice (~2000s) to include dedicated variables in its codebase: via constants or hard-coded in the middle of its instructions. 😬

Over time, another strategy was adopted: the use of environment variables.

It was the Heroku platform, just before the 2010s, which popularized this approach through its "Config Vars" feature. In a platform archive from 2009, we find:

The traditional approach for handling such config vars is to put them under source. This is a slightly error-prone process, and is especially complicated. A better solution is to use environment variables, and keep the keys out of the code.

Almost 15 years later, the feature remains relevant:

Config Vars settings in Heroku Dashboard

This avoids storing secure passwords in version control and enables a developer to make isolated configuration changes for each environment: dev, staging, production…

Concept Theorization and dotenv Creation

Adam Wiggins, one of the co-founders of Heroku, describes the "env var config" concept in 2012 in the "Twelve-twelve-Factor App" (12factor.net). This manifesto presents 12 best practices for app development and deployment, where point number three "Config", details this technique. A 𝑚𝑢𝑠𝑡-𝑟𝑒𝑎𝑑! 📖

Apps sometimes store config as constants in the code. This is a violation of twelve-factor, which requires strict separation of config from code.

So it was on this basis, in 2013, that Scott Motte created the dotenv library with the aim of separating an application's configuration, from its source code and make this mechanism accessible to all.

In literature, this design principle is called: "𝑠𝑒𝑝𝑎𝑟𝑎𝑡𝑖𝑜𝑛 𝑜𝑓 𝑐𝑜𝑛𝑐𝑒𝑟𝑛𝑠".

The dotenv's Limitations

dotenv has gained in popularity, and the use of .env files is now one of the industry's reference points for deploying and configuring applications and websites with more than 30 million downloads per week.

However, the tool is now facing two main criticisms:

  1. Unencrypted storage of secrets.
    In the event of a security breach, this exposes sensitive information such as API keys or passwords to potential exploitation by malicious actors.
API_KEY=1234567890abcdefghijklmnopqrstuvwxyz
DB_USERNAME=admin
DB_PASSWORD=mysecretpassword

.env, with data in plain text and readable by all

  1. Inconsistent syntax across languages and platforms.
    It can lead to configuration errors and unexpected behavior in applications. For example, issues such as problems with quoting, trailing whitespace, or the order of keys can result in configuration files being interpreted differently.

dotenvx, to Save Us!

In response to these challenges, dotenv's creator is actively developing its successor: 𝗱𝗼𝘁𝗲𝗻𝘃𝘅. Its promise can be summed up in 3 key points:

  • cross-platform
  • multi-environment
  • variable encryption

In practical terms, dotenvx is designed to replace plaintext .env files on remote environments with their encrypted versions. The public and private key variable (DOTENV_PUBLIC_KEY / DOTENV_PRIVATE_KEY) are utilized to decrypt the contents of the encrypted file and inject the variables into the application at runtime.

How to Use dotenvx?

As described in the dotenvx documentation and recommended by the library's creator, it's a good idea to opt for global installation.

I am using (and recommending) this approach going forward. – motdotla

In the following, we'll take the example of a dotenvx installation in a Node.js environment using npm.

1. dotenvx installation

Installing dotenvx is straightforward. Simply execute the following command:

# install globally with npm
npm install @dotenvx/dotenvx -g

# Check that dotenvx is installed by viewing the CLI help
dotenvx help

Node.js and npm must be installed

2. dotenvx usage

To begin using dotenvx, create your local .env file with your configuration variables. Here's an example of how your .env file might look:

NAME=Bob
ENVIRONMENT=development

Next, inject these variables at application startup using the dotenvx run command:

dotenvx run -- node -e \
"console.log('Hello ' + process.env.NAME + ' from ' + process.env.ENVIRONMENT);"

You should get:

[dotenvx@1.6.4] injecting env (2) from .env
Hello Bob from development

That's all! We've used the Node.js command line evaluation here, but it's the same principle for any application you start via JavaScript file (eg. server.js or index.js):

dotenvx run -- node index.js

Ensure that the variables have been injected and their values can be accessed via process.env.<variable-name>.

For further examples and detailed documentation on using dotenvx with frameworks like Astro, Express.js, Nest.js or Remix, refer to the official documentation: Use dotenvx with Node.js.

3. dotenvx multi-environments

You can easily manage multiple environments. In fact, you can create as many environment files as needed, each tailored to a specific environment:

  • .env (for local development)
  • .env.staging
  • .env.production
  • ...

Simply target the appropriate environment file when starting your application, and the corresponding values will be injected automatically. Here's an example:

dotenvx run --env-file=.env.local -- node index.js

More information for managing environments on the documentation page: Environments.

4. dotenvx encryption and deployment

The next step is to encrypt your .env, .env.production, or any other environment file so that you can securely share or deploy it on any VPS or deployment platform, such as Railway, Azure, or AWS.

The dotenvx CLI provides us with the encrypt command to accomplish this:

dotenvx encrypt -f .env

On the first run, this will produce the following output:

✔ encrypted (.env)
✔ key added to .env.keys (DOTENV_PRIVATE_KEY)

The .env file is now encrypted. The environment variables are no longer readable, and the file contains a new DOTENV_PUBLIC_KEY variable enabling these values to be decrypted.

To fully decrypt them, the public key must be associated with a private key. This is the role of the .env.keys file, which contains the DOTENV_PRIVATE_KEY variable. Unlike .env files, which can now be versioned since they have been encrypted, the .env.keys file must not be committed at all.

The final step is to define the DOTENV_PRIVATE_KEY variable on the runtime platform as an environment variable, which will decrypt the .env file and inject the variables into your application.

You can verify this locally. For the previous example, this works as follows:

DOTENV_PRIVATE_KEY='<DOTENV_PRIVATE_KEY_VALUE>' \
dotenvx run -- node -e \
"console.log('Hello ' + process.env.NAME + ' from ' + process.env.ENVIRONMENT);"

You'll get:

[dotenvx@1.6.4] injecting env (2) from .env
Hello Bob from development

That means the encryption process was successful, bravo! 👏

For each environment, just make sure that the DOTENV_PRIVATE_KEY variable matches the target environment. Also, you don't need to define the input environment file explicitly, the tool will find the right one for you. For the production environment, simply define DOTENV_PRIVATE_KEY_PRODUCTION , and dotenvx will load .env.production.

More information on the documentation page: Encryption.

5. Useful commands

  • Retrieve initial value(s) from and encrypted .env file:
dotenvx get {KEY} [-f,--env-file]                   # Return a single value
dotenvx get [-f,--env-file] [-pp,--pretty-print]    # Return all values
  • Set a new encrypted key/value:
dotenvx set {KEY} {VALUE} [-f,--env-file]
  • Decrypt an encrypted environment file:
dotenvx decrypt [-f,--env-file] [--stdout]
  • More information and details about the CLI:
dotenvx --help

Railway Template

Get started with dotenvx quickly by deploying the following template on the Railway platform. Simply click the button below to deploy the project in one click:

Deploy on Railway

Conclusion

dotenvx represents the next generation of configuration management, introducing new encryption capabilities within .env files. By enhancing security without additional costs or proprietary solutions, dotenvx aims to simplify the configuration of our future applications! 🤩

Happy coding! 👨‍💻✌


Additional Note

Focus on Your Clients: Let Us Handle Your Code

Shift your focus to serving your clients while we handle your source code.
Explore cycaas.com to discover our suite of services, from code review to refactoring, allowing you to deliver top-notch solutions without distraction.