Tooling spotlight: direnv

Categories
Linux penguin logo

tl;dr - You should be using direnv to load ENV variables dynamically per-project.

You don’t necessarily have to buy into the entirety of the 12 factor app manifesto, but you should almost definitely be using ENV-as-configuration by this point.

Even if it’s just a CONFIG ENV var that points to a config.toml that your application reads, passing configuration via environment variables is the tried and true method of configuring applications these days (inside a docker container or out).

But how do you manage your ENV configuration when doing local development? Well that’s where direnv comes in.

If you place a .envrc (or .env) file in a directory, and browse to it in your shell of choice, direnv will load those ENV variables.

Getting started with direnv

Check out the install instructions to get direnv installed, then make a .envrcfile like this:

# let's say you want to use the superior editor
export EDITOR=emacs
# and the superior browser
export BROWSER_BIN=firefox-developer-edition

# Application variables
# (these are what your application needs to run)
export FOO=bar

In addition to just values, you can put whatever you want in your .envrc and it will be evaluated… Which means you can do a lot with .envrc files.

Example: Reading in files and their paths

One example You could get the absolute path to a file or even read it into an ENV var.

# You can get the absolute path to a file
export ABS_PATH_TO_FILE=$(realpath relative/path/to/file)

# You can also read files into ENV vars
export FILE_IN_VAR=$(cat relative/path/to/small/file)

NOTE: you’ll need realpath installed of course, but you could run any other command as well

Example: Configuring git hooks with direnv

One of my favorite uses is to trigger/configure git to do hooks, avoiding the need to use tools like husky:

# While in the project folder tree, git will load hooks from `.githooks` (which can be checked into source control!)
git config --local core.hooksPath $PWD/.githooks

Bonus: .env files work too!

Whether you’re developing a NodeJS app that expects .env files, or you’re working with a file that could be passed to docker (via --envfile), you can configure

In the configuration file for direnv (ex. ~/.config/direnv/direnv.toml) you can add a configuration like this:

[global]
load_dotenv = true

This will enable direnv to read .env files which have a slightly different syntax and are less dynamic:

NODE_ENV=development
FOO=bar

Warning: Don’t forget to .gitignore/.dockerignore your .env files!

If you’re going to use direnv, don’t forget to add .envrc and .env to your .gitignore if you don’t want to check the files in!

You could ignore the files for every repo on your own computer, but the best way to make sure that no one on your team checks the file in either is to put the .gitignore (which includes .envrc/.env) into source control.

Wrapup

direnv is super flexible and I’ve loved having it as part of my go-to tooling for a long time. If you haven’t already, start using it!