Take Control of Project Configs with Direnv
26 October 2024
Not so long ago, I discovered direnv
, which has become an essential tool in my daily workflow. I found it so practical and easy to use that I thought I’d dedicate a blog post to it.
Direnv is a simple tool that acts as a shell extension, and all it does is load and unload environment variables based on the current directory. Apparently, this doesn’t seem like a big deal, and maybe you don’t see how it could be useful, but let me give you an example.
Key Benefits
Before diving into the details, here’s why direnv is worth your attention:
- Automated Environment Switching: Environment variables load automatically when you enter a project directory
- Project Isolation: Each project maintains its own environment configuration
- Security: Better control over sensitive information
- Development Efficiency: No more manual exports or sourcing of environment files
Let’s say you have multiple projects with different configurations and secrets. The most obvious way to handle this is to have a .env
file in each project and load it manually—unless you want to keep all the secrets in your .bashrc
or .zshrc
file or export them manually every time you switch between projects. This is where direnv
will save you. It will automatically load the .env
file when you cd
into the project directory and unload it when you cd
out.
Let’s see how you can install and use direnv
on your system.
Installation
Direnv comes packaged for most Linux distributions, so you can install it using your package manager. For example, on Ubuntu, you can install it with:
sudo apt install direnv
On macOS, you can use Homebrew:
brew install direnv
You also have the option to install it manually by downloading the binary from the GitHub releases page.
Usage
Now that we have direnv installed, we can use it in any project by changing the directory to our project and create our first environment variable and save it to .envrc
file.
cd my-project
echo export FOO=foo > .envrc
This will create a new file named .envrc
in the project directory with the content export FOO=foo
. To make this environment variable available in the current shell, we need to allow direnv to load it by running:
direnv allow .
With this command we are allowing direnv to load the environment variables found in the .envrc
file in the current directory. With this done, we can check if the environment variable is loaded by running:
echo $FOO
This way, we can expose the secrets and configurations needed by the project without cluttering our shell configuration files. But we can do more: we can tell direnv to automatically load the environment variables when we change to a directory that contains a .envrc
file.
To do that, we need to add the following line at the end of our shell configuration file (.bashrc, .zshrc, etc.). For example, if you are using zsh, you can add the following line to your .zshrc
file:
eval "$(direnv hook zsh)"
With this in place, whenever we change to a directory that contains a .envrc
file, direnv will automatically load the environment variables defined in that file.
One more nice thing that I like to do with direnv is to extend the $PATH variable with the bin
directory of the project. This way, I can have project-specific binaries that I can use in the project directory without having to specify the full path to the binary. This can be done by adding in .envrc file the following line:
export PATH=$PWD/bin:$PATH
Security Note: Remember to add .envrc
to your .gitignore
file to prevent accidentally committing sensitive information:
Conclusion
Direnv is a simple tool that can save you from typing extra commands or forgetting to load the environment variables needed by your project. Not only will it improve your experience with managing configurations and secrets, but it’s also more secure than having all your secrets exposed system-wide.
If you want to find out more, here’s the official documentation. Give it a try, and let me know what you think!