Automate Project Environments with Devbox and Direnv
Learn why having an isolated environment is useful, why setting up an environment with Direnv can be tough, and walk through an example of Direnv + Devbox for a sample NodeJS application.
The challenge of managing multiple projects in the same operating system has been met with many different solutions over the years. We've progressed from virtual machines (VirtualBox) to container systems (Docker), and even isolated shells (nix-shell). We built Devbox to make isolated shell environments easy to learn, use, and configure. The combination of easy shell environments with Devbox, combined with convenient environment switching with Direnv makes it simple to manage multiple projects without having their setups interfere or leak into one another.
In this blog we’re going to explore why having an isolated environment is useful, explain why setting up an environment with Direnv can be tough, and showcase an example with our optimal combination: Direnv + Devbox for a sample NodeJS application.
Why have an isolated environment per project?
There are 4 main reasons why an isolated environment is needed:
- Dependency version mismatching: Each application has its own dependency packages meaning two applications may need two different versions of the same dependency. For example, an enterprise developer may use a stable version of NodeJS for work projects but use an edge version of NodeJS which has newer features for a personal project. In this case, some languages have a version manager (e.g.,
nvm
for NodeJS) but with Devbox there is no need to install a version manager per programming language. - Application settings: Each stack might have at least one or two settings that may be different from other applications. For example, you might have
DATABASE_PORT
andDATABASE_PASSWORD
as env variables that are specific to your app. - Secrets: Similar to applications settings, your app might have secrets that are required to access 3rd party tools and platforms such as
API_KEY
andAPI_SECRET
- Compiler options: Depending on the programming language, your app might need to have specific compiler options to compile for a target CPU architecture, or look for libraries in a specific directory. For example, in C++ you may need to setup
LDFLAGS
orCPPFLAGS
and in Java, you may need to setupJAVA_HOME
.
The listed items above are not the only reasons why you might want to have an isolated environment. Based on the use case, there might be other motivations but regardless, setting up isolated environments can be cumbersome and time-consuming. Let’s explore setting up an environment with Direnv below.
Direnv
Direnv is a tool that automates configuring environments on a per-directory basis. So that when you cd
into a directory, it triggers Direnv to activate a pre-configured environment. It makes it very convenient in managing different environments and easily switching between them just by doing cd dir_name
.
The problem with using Direnv is that despite it being a very useful tool, its setup requires investing time and getting over the Nix ecosystem's learning curve. In addition to that, each project requires the developer to spend some time writing a .envrc
file and maintaining it as the requirements for the project change.
Automatic Devbox Environments with Direnv
We at Jetpack loved the convenience of Direnv. So following our philosophy of simplifying complicated tools to make them easy to adopt, we developed an integration between Devbox and Direnv. With this integration, there is no need to setup any .envrc
files to use Direnv. Just having Direnv and Devbox installed on your system is enough to initiate a project environment with Devbox, add its dependencies, and integrate it with Direnv just by running devbox generate direnv
. That way, whenever you cd
to a Devbox + Direnv project, the Devbox environment is automatically setup and ready to go.
Take a look at the example below to see the simple steps required to setup a sample project with Devbox and Direnv:
- Make sure to have both Devbox and Direnv installed.
- In a project directory (or empty dir) run
devbox init
- Add dependencies to Devbox. For example,
devbox add nodejs yarn
- Add Direnv integration
devbox generate direnv
That’s it! You have a working Devbox environment integrated with Direnv. Now any change done to your Devbox environment via devbox.json
is applied by Direnv. Now that we’ve setup the environment, let’s see how we can automate starting a sample NodeJS project:
- Start a yarn project by running
yarn init
and follow the prompts. - Add a small web server to your NodeJS project
yarn add http-server
. - Edit the
"init_hook"
section ofdevbox.json
so that it looks like the following:
{
"packages": [
"nodejs@latest",
"yarn@latest"
],
"shell": {
"init_hook": [
"yarn install",
"yarn run http-server"
]
}
}
This sets up this project so that every time you cd into this project, all NodeJS dependencies get installed and http-server runs. To test this, cd ..
and then cd
back into your project directory and see how Direnv setups up your Devbox environment and runs http-server
. Use Ctrl+C to stop http-server
.
Next Steps
Devbox makes creating and working in isolated dev environments simple and easy. Direnv makes switching between multiple environments convenient. So combining the two provides a great experience for setting up and using your dev environments.
We liked using Direnv so much that we started using it in our development of Devbox. In fact, we use both Devbox and Direnv to develop Devbox! To see it in action check out devbox.json
and .envrc
files in our Github repo.
Stay up to Date with Jetify
If you're reading this, we'd love to hear from you about how you've been using Devbox for your projects. You can follow us on Twitter, or chat with our developers live on our Discord Server. We also welcome issues and pull requests on our Github Repo.