Unclutter environment variables

How to manage project specific environment variables using direnv.

We usually store app/tool configuration (that is likely to vary between deploys) in environment variables. This is a best practice also described by the 12-Factor application pattern:

The twelve-factor app stores config in environment variables

It might be challenging however to keep track of these variables in such a way, so it is easy to switch between. You might need to test your project in Dev, Stage and Production. You might play around, and test some of your work in a sandbox env.

Different tools (Ansible, Terraform, OCI-CLI, Python projects, etc.) requires access to different environment variables depending on the "where" you run it.

In the past, I sometimes used VS Code to store the environment variables in project specific terminal.integrated.env.* configuration. I have also created different bash functions to activate manually cloud environments.

Recently I started to use direnv to manage project specific variables as it is not VS Code specific.

direnv augments existing shells with a new feature that can load and unload environment variables depending on the current directory.

Uses-cases for direnv is to load 12factor apps environment variables, secrets, project specific variables.

direnv checks for the existence of a .envrc file in the project directory. If it is approved with the direnv allow . command, it will load the variables automatically.

.envrc includes bash like variable definitions:

export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
export TWINE_USERNAME=""
export TWINE_PASSWORD=""
export TWINE_REPOSITORY_URL=""
.envrc file

It is a good idea to add .envrc to the gitignore file of the project, to not push secret keys to the repository.

Installation of the utility is a two steps process:

  1. Use package manager, download the binary, or use brew (brew install direnv) on macOS as described here.
  2. hook direnv into your shell.

Lot of tools are using the .env file as the default for loading ENV variables. It is possible to instruct direnv to use this file by creating ~/.config/direnv/direnv.toml configuration file:

[global]
load_dotenv = true

direnv allows to activate automatically a pipenv environments. For this, you just have to add layout pipenv to the .envrc file.

export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
export TWINE_USERNAME=""
export TWINE_PASSWORD=""
export TWINE_REPOSITORY_URL=""
layout pipenv
.envrc file

This is a perfect setup, anytime change path to project directory, direnv will automatically load the environment variables and activate python environment with pipenv.

References:

  • https://direnv.net
  • https://kellner.io/direnv.html
  • https://kylerconway.com/2020/11/25/python-pipenv-direnv/
  • https://dev.to/charlesloder/tidbit-get-direnv-to-use-env-5fkn