DEV Community

Cover image for Magically use environment variables without a .env file
BlackMagiq
BlackMagiq

Posted on

Magically use environment variables without a .env file

Image description

TLDR: You can build or use a pre-made CLI together with your application's start command to inject environment variables for local development and avoid using a .env file altogether.

Recently, I wrote about fetching environment variables for applications so teams always have access to the right variables. The method was simple: store environment variables in a secret management platform, then have the application fetch them back and cache them at runtime. This, however, came with a nuance of having to manage yet another token to fetch these variables.

In this article, however, I discuss an enhanced approach specifically for local development to inject environment variables into an application without needing a .env file at all.

It sucks to fetch environment variables back for an application if the method still requires managing one environment variable

This is a common complaint and debate amongst developers considering to use a secret management platform to store their environment variables only to find out that they still need to manage a token to gain access to the platform.

While the approach of storing a token in a .env file and using it to fetch back environment variables tamed secret sprawl, it did little to improve on the security front. After all, you could still leak the token to source control and, if not revoked, bad actors could use it to access your environment variables.

I'm glad to say, however, that you can use a secret management platform and fetch environment variables back without needing to store another proxy token. Here's how:

You can inject environment variables into your application using a CLI

Let me explain.

It turns out that your application running in local development is just a process and it's possible to pass environment variables into that process as it starts up. This means that you can build a platform-agnostic CLI to fetch back environment variables from a centralized source and wrap it around your application's start command. Couple the CLI with authentication logic and proper credential storage on your system and you can have a secure workflow that pulls and injects environment variables into your local development process.

Moving forward, members of your team only need to install the CLI onto their machine, authenticate with the secret management platform via the CLI, and start up their application via CLI with environment variables injected - Wizardry.

That's enough, show me your recommendation, gimme the code

While you can code the CLI yourself and connect it to an existing secret management platform, I wouldn't recommended it for most developers since this isn't a quick endeavor. Instead, I'm going to be using the Infisical CLI to pull and inject environment variables in local development from Infisical, a popular open-source, end-to-end encrypted secret management platform that you can store environment variables with.

It's worth noting that Infisical is self-hostable on your own infrastructure and well-documented.

Image description

Getting started

Before we can fetch environment variables back into your application, you need to add them to a project in Infisical Cloud or in a self-hosted instance of Infisical.

Okay, let's get started.

First, install the CLI onto your machine.

MacOS (using brew):

brew install infisical/get-cli/infisical
Enter fullscreen mode Exit fullscreen mode

Windows (using scoop):

scoop bucket add org https://github.com/Infisical/scoop-infisical.git
Enter fullscreen mode Exit fullscreen mode
scoop install infisical
Enter fullscreen mode Exit fullscreen mode

Arch Linux (using yay):

yay -S infisical-bin
Enter fullscreen mode Exit fullscreen mode

Check out the documentation for more installation options like Redhat/CentOS/Amazon and Debian/Ubuntu if your system is missing above.

Next, authenticate with Infisical using the CLI:

infisical login
Enter fullscreen mode Exit fullscreen mode

This command authenticates the CLI with Infisical Cloud or your self-hosted instance and stores credentials in your system keyring. 

Next, navigate to the root of your project and run the initialization command:

infisical init
Enter fullscreen mode Exit fullscreen mode

This command creates a infisical.json file holding a reference to your project in Infisical Cloud or self-hosted instance; the file can be committed to source control.

Finally, start your application in local development with the help of the CLI:

infisical run -- <your application start command>
Enter fullscreen mode Exit fullscreen mode

If you're using a self-hosted instance of Infisical, you can run this command instead:

infisical --domain="https://your-self-hosted-infisical.com/api" run -- <your application start command>
Enter fullscreen mode Exit fullscreen mode

This command fetches environment variables back from the development environment of your project in Infisical and starts up your application with the variables injected. The environment variables become available in the application environment. For example, they're accessible on process.env in Node.js or on os.environ in Python.

While the CLI comes with a few helpful subcommands and flags that you can read more about in the documentation, in practice, the basic command above is all you need 99% of the time.

Here're some examples for common frameworks:

# example with node
infisical run -- node index.js

# example with node (nodemon)
infisical run -- nodemon index.js

# example with Next.js
infisical run -- npm run dev

# example with flask
infisical run -- flask run

# example with django
infisical run -- python manage.py runserver

# example with laravel
infisical run -- php artisan serve

# example with rails
infisical run -- bin/rails server

# example with .NET
infisical run -- dotnet run
Enter fullscreen mode Exit fullscreen mode

That's it!

Now you can use environment variables in local development without a .env file and feel confident that your team will not leak anything to source control. You're now also able to view all the environment variables for your application from one central place and avoid any missing environment variables.

How do I trust a secret manager?

I'm including this section because it has been helpful to developers in past articles.

Adopting a secret manager can be daunting at first and rightfully so. You have to trust that the solution you're working with is secure, that the vendor won't view or tamper with your data, and that the underlying infrastructure will work and deliver environment variables reliably when needed. There is, however, a right tool for every task and using dedicated tooling to manage environment variables is surely better than any manual process that's either not efficient or prone to error.

The analogy I like to use is password managers like 1Password and Bitwarden. Before using one, I was content with managing dozens of passwords manually and occasionally forgetting them. The minute I started to face password sprawl, however, I was compelled to upgrade my workflow and sign up for a password manager. 

Similarly, in the realm of secret managers, when you're a solo developer, you can use manual approaches to store your environment variables. The minute, however, you start to scale to above five engineers, you start to face secret sprawl and that's where a secret management solution can really help. My suggestions for selecting one:

  • Pick a solution that's either open source or made by the big cloud providers; it will be more resilient that way and you can inspect and, in the open source case, make changes to the code if needed.

  • Pick something that provides a good developer experience for the size of your team. If you have site reliability engineers and teams for process, you can afford to go with more complex tools. Otherwise, if you're a smaller team, go frictionless and focus on building the rest of your application.

Conclusion

We developers often debate the practicality of using a secret management platform when faced with the need to yet manage another token to access environment variables or secrets. This unfortunately comes off as counterintuitive to many developers who then hesitate on adopting a secret management solution.

In this article, however, I demonstrate a workflow using a CLI that fetches environment variables and injects them into any application upon starting up; the method avoids storing any proxy token in a .env file. With this CLI approach, development teams stop risking leaking environment variables to source control by not storing any variables in plaintext in .env files on their machines.

Top comments (0)