blog.lazkani.io/content/posts/environment-variables-made-easy.md
2025-02-20 21:13:04 +01:00

139 lines
4.1 KiB
Markdown

+++
title = "Environment Variables Made Easy"
author = ["Elia el Lazkani"]
date = 2025-02-20
lastmod = 2025-02-20
tags = ["env", "environment-variable", "envrc", "direnv", "dev", "developement"]
categories = ["misc"]
draft = false
+++
If you've written software in the last decade, then you're probably familiar
with the current technologies at play. You write your code, locally, in your
IDE, build and test it. You've made your _commit_ and pushed it to the revision
control system server and created a _pull request_. Pipelines started, code
built, unit tests ran, magic all over and now it's deployed in _staging_. Once
the code lives in _staging_ long enough to build trust in its performance it
goes to _production_.
This is in a nutshell how it looks like. The big elephant in the room is, of
course, that all of these different environments are, well... different !
This means that the values I used to test my code locally is different than the
values used to test in the pipeline, for security reasons. The same goes for
every single environment. Configuration files could solve a lot of these issues
but, as we all know, they don't solve all of them.
Another solution is to use _environment variables_, which could be easily
injected into scripts, environments and even containers. It's a win-win
everywhere except managing them locally. You're probably thinking my `.profile`
file looks like a mess. You'd be surprised to know that mine is empty, but how ?
<!--more-->
## Direnv {#direnv}
`Direnv` is [described](https://github.com/direnv/direnv) by the developers as
> an extension for your shell. It augments existing shells with a new feature that
> can load and unload environment variables depending on the current directory.
It's as simple as that !
`Direnv` runs on most _operating systems_ and a wide variety of _shells_. The
[installation](https://direnv.net/docs/installation.html) process is well documented and the same goes for configuring
`direnv` to [hook](https://direnv.net/docs/hook.html) to your favorite _shell_.
## How does it work ? {#how-does-it-work}
First, let's start by creating a _new_ project.
```shell
$ mkdir project-1
$ cd project-1
```
Now that we've created a project, let's create a `.envrc` file and populate it
with the following.
```bash
# Add build/bin to $PATH
PATH_add build/bin
# Export environment variables
export DB_HOST="localhost"
export DB_PORT="5432"
export DB_USERNAME="dummy-user"
export DB_PASSWORD="super-secret"
```
Once I save the file and exit the editor, I get greeted with a _lovely_ **error**.
```shell
direnv: error ~/project-1/.envrc is blocked. Run `direnv allow` to approve its content
```
The reason for this is very simple. The `.envrc` file can do a lot, making it a
security risk. This error is there to make sure that you check the `.envrc` and
**only** allow `direnv` with _trusted_ `.envrc` files.
I wrote this `.envrc` file, so I can safely trust it. But you can't !
```shell
$ direnv allow
direnv: loading ~/project-1/.envrc
direnv: export +DB_HOST +DB_PASSWORD +DB_PORT +DB_USERNAME ~PATH
```
This tells us that we've exported a list of environment variables. Let's check
them out.
```shell
$ env | grep DB_
DB_PORT=5432
DB_HOST=localhost
DB_PASSWORD=super-secret
DB_USERNAME=dummy-user
```
We've also used the `PATH_add` to add a project specific directory to our `PATH`
allowing us to run the binaries directly without having to navigate to the
_build_ directory.
<div class="admonition warning">
<p class="admonition-title"><b>Warning</b></p>
It is very important, at this stage, for me to **warn** you about the dangers of
committing your `.envrc` to your _revision control_. This bad boy's got
_passwords_ in it ! Don't do it !
</div>
That's impressive and all but...
I know what you're gonna ask me next and here's the answer.
```shell
$ cd ..
direnv: unloading
```
and now...
```shell
$ env | grep DB_
$
```
Nothing at all. All variables have been unloaded automatically. They will be
loaded again the next time you navigate to the project's directory.
## Conclusion {#conclusion}
Next time you're working on your project, give `direnv` a try. It will change
the way you work for the better, I hope.
Happy Hacking !