dotenvx · Secure and Next-Generation dotenv Successor
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:
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:
- 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.
- 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:
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:
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.