Our latest release of Devbox includes one of our most requested features – the ability to find and install specific versions of Nix packages. This feature makes it easier than ever to build the exact Nix-based development environment that you need for your project.
"packages": [
"go@1.20",
"actionlint@1.6.23",
"golangci-lint@1.52.2"
],
Pinning package versions in the Devbox Config
The new release provides a familiar interface for installing packages with Devbox. In this post, we'll go into more detail of how this improves upon installing packages with vanilla Nix or older versions of Devbox, and share some details on how we built the new search and pinning feature.
To install Devbox 0.5.0, you can run devbox version update
from the command line, or follow the installation instructions on our docs page.
Update: In addition to searching for and installing specific package versions from the Devbox CLI, you can now also search using Nixhub.io.
Background on Nixpkgs
The Nix Package Manager maintains a Github repo with instructions for over 80,000 packages. Maintainers add new packages and remove outdated ones by committing changes to this repo. Developers who want to install packages from Nixpkgs subscribe to a Nix channel, a branch of the Nixpkgs repo whose commits have been verified by Hydra (the NixOS build service). Installing a package from a Nix channel builds the latest version available on that channel.
This setup works well for most cases, but challenges arise if you want to install a specific package version that is no longer available in the latest commit to a channel. To install an older package, developers reference a particular commit of Nix packages that published it. This system leads to a few developer experience challenges:
Nix doesn't provide an easy way to look up the last commit that published a package version. Instead, developers must search manually or use a 3rd party solution.
When installing the older package, developers need to explicitly import a snapshot of the nixpkgs repo for each package. In addition to not being very self-documenting, configs are more complex to write.
In some cases, Nix supports different package versions by providing multiple copies (e.g.,
nodejs_18
,nodejs_19
,nodejs_20
). However, the naming convention for these copies lacks standardization, and developers are still limited to the latest version of each copy for a single commit.
Our Solution: a Devbox Package Index
To address these pain points, we created the Devbox Package Index. Our Package index provides an improved interface for finding and installing packages in your Devbox project:
First, we processed build outputs from Hydra to map package names + version numbers to commits in the Nixpkgs repo. We then created a service that stores this index as a prefix tree, making it easy to search for a specific package and version in Nix.
Next, we created a familiar interface for describing and resolving these references in Devbox. Instead of adding a commit, developers install NodeJS 14.1 by adding
nodejs@14.1
to their project. Devbox will translate this to a Nixpkgs reference and store it in adevbox.lock
file. You can also use this interface to pin the major version of your package usingnodejs@14
, and update to the latest minor version by runningdevbox update
Finally, we created canonical names to group similar versions of popular packages. For example, the canonical name
python
maps to the nix packagespython2
,python
, andpython3
, and we install the correct package based on the version that the user requests.
Example: Installing Node 14.8.1
To show how these changes make installing packages more intuitive, let's consider adding an older version of Node.js (say Node 14.8.1) to our project.
First, we can search for Node.js using devbox search
to see the available packages
$ devbox search nodejs
Warning: Search is experimental and may not work as expected.
Found 168+ results for "nodejs":
* nodejs (19.8.1, 19.7.0, 19.5.0, 19.2.0, 18.16.0, 18.15.0, 18.14.2,
18.13.0, 18.12.1, 18.10.0, 18.8.0, 18.4.0, 18.0.0, 17.9.0, 17.5.0,
17.3.0, 17.0.1, 16.19.1, 16.19.0, 16.18.1, 16.17.1, 16.17.0, 16.15.0,
16.14.0, 16.13.1, 16.13.0, 16.8.0, 16.4.0, 16.0.0, 15.14.0, 15.10.0,
15.5.0, 15.0.1, 14.18.1, 14.18.0, 14.17.5, 14.17.1, 14.16.1, 14.16.0,
14.15.3, 14.15.0, 14.9.0, 14.4.0, 13.14.0, 12.22.12, 12.22.10, 12.22.8,
12.22.7, 12.22.5, 12.22.1, 12.21.0, 12.20.0, 12.19.0, 12.18.3, 12.18.1,
10.24.1, 10.24.0, 10.23.0, 10.22.0, 10.21.0)
...
Search returns a list of available packages and versions
Next, we can add NodeJS 14.8.1 to our project by running devbox add nodejs@14.8.1
. Devbox will use the index to match this to the correct nixpkg commit and package and add it to our project, storing the results in a `devbox.lock` file.
{
"packages": [
"nodejs@14.8.1"
],
"shell": {
"init_hook": null
}
}
devbox.json
{
"lockfile_version": "1",
"packages": {
"nodejs@14.8.1": {
"last_modified": "2022-01-01T22:37:24Z",
"resolved": "github:NixOS/nixpkgs/0fd74961da9fe2640ad2fbd960c3af08246e6749#nodejs-14_x",
"version": "14.18.1"
}
}
}
devbox.lock
We can now verify that we installed the right version by starting a Devbox shell
$ devbox shell
Ensuring packages are installed.
Starting a devbox shell...
(devbox) $ node -v
v14.18.1
The right version of Node is installed when we start our shell
Exactly the package we wanted, and we didn't have to look up a single commit. To ensure other developers get the same packages when using our project, we can check in the devbox.lock
file to source.
Next Steps:
We hope this post demonstrated how easy it is to install specific versions of Nix packages with Devbox. To learn more about how to use the Devbox Package Index, including how to pin major versions or easily update your packages with devbox update
, check out our docs page.
We also have plans on how to improve the Package Index to make it more useful for both Devbox and Nix users, so watch this space for more news over the coming weeks.
We'd also love to hear your feedback on Devbox, or learn more about what you're building! If you'd like to keep up with our progress, you can follow us on Twitter, or chat with our developers on our Discord Server. We also welcome issues and pull requests on our Github Repo.