At Freelock, we're starting to use Nix to manage different PHP environments, and be able to incrementally update websites. For the past decade or so, running different versions of PHP has caused a bunch of trouble across our infrastructure -- largely because PHP upgrades in the past have caused a lot of things to break across many sites. PHP upgrades have often caused more turmoil than Drupal upgrades!
The problem
Now that all our Drupal sites use Composer, that makes PHP versions even more strict -- if you install modules at one PHP version, you cannot run that site in a lower version, as Composer will throw an error immediately.
If you're running in a Docker environment, it's easy to run different versions of PHP in different containers -- but we have a hybrid environment where the site is loaded into Docker for web access, but we manage it through a shell on the server. Most of our servers are Ubuntu LTS servers, and you have one host-wide PHP version. So for many years we've run the same version of PHP across our entire infrastructure, with a few containers at different versions for sites that don't work in that. Our current version is PHP 8.1 -- that's what all our servers are using now.
We need PHP 8.3 to upgrade to Drupal 11. But if we change our system level to PHP 8.3, suddenly we need to go through and upgrade ALL the sites and fix ALL the bugs in them, because after applying updates under PHP 8.3 the site won't run on anything less.
Nix to the rescue
I've been dabbling with Nix for the past year. Nix is kind of an operating system Swiss army knife -- a bunch of different tools that do all sorts of different things, and can be used in a bunch of different ways. It's a language, a package system, a build tool, and a time machine all in one. Plus it can be a dotfile manager on any operating system, as well as being a full-fledged distribution.
We'll be doing more #Dev Corner posts about Nix, leading up to a presentation I'm giving at DrupalCon next month. So in this post, I'm going to leave that problem hanging a bit, until next time -- because first we need to get set up to use Nix.
There's two things you need to make development with Nix flakes easy - Nix, and direnv.
Getting Nix
Nix itself in this case is installing the Nix language and runtime. There are a bunch of different ways to get going, but I'm going to highlight two options: the nixos.org installer, and the determinate.systems installer.
I've only used the nixos.org installer, as that seems to be the main one for the community. On each Ubuntu server, I run the multi-user installer to get Nix up and available for all users on the system. There are also options there for MacOS and Windows.
After you've installed this way, you do need to enable flakes - we use flakes for development, home manager, more, and while they are still considered experimental, they are widely used and do things you can't do as easily without them. So to activate them, you need to edit the /etc/nix/nix.conf file and add this line:
experimental-features = nix-command flakes
The alternative is Determinate System's installer. I have not used this myself, but it does activate flakes out of the box, so it saves a step.
Direnv
Direnv is a program that integrates with your shell. When you enter a directory, it looks for a .envrc file. If this exists, and has a command it recognizes, Direnv can automatically run that, after you have permitted it with direnv allow
.
As a Drupal user, we used to use Drush Launcher to have a stub to make use of a drush installed in your current project, or fall back to a global drush if that's not found -- in the notes for what to do now that Drush Launcher is considered obsolete, Direnv is one of their recommended options.
Direnv is available as a package for most Linux distributions, but that alone doesn't necessarily hook it up for you -- getting it set up can be a bit tricky.
So let's skip all that and use today's Nix tidbit to get Direnv automatically installed, and get a bunch of other shell goodies while we're at it!
My home manager configuration
Home Manager is a Nix tool for managing dotfiles. Lots of hardcore Linux users "manage dotfiles" so they can easily set their preferences on one machine and easily use them on others -- at its core, that's what Home Manager does. But it does it using Nix, the Nix way -- by having a simple configuration file that declares what you want available along with a slew of configuration options.
You can start with my configuration, here - https://github.com/freelock/home-manager . With Nix and git installed, this is a very quick/easy thing to do. Here's the gist, will explain each part below:
git clone
https://github.com/freelock/home-manager
cd home-manager
- Edit flake.nix, and change the key "john" inside "homeConfigurations" (currently on line 22) to your login name, or some other name (e.g. "user").
- Edit home.nix, and change the values for "username" and "homeDirectory" to match your login and home directory path.
- Get a temporary instance of home-manager, by entering
nix-shell -p home-manager
. - Activate the configuration with
home-manager switch --flake .#user
, replacing "user" with the name you used in step 3. This step may take several minutes. - Log out, and back in again, and you should see a whole new shell, with Direnv active among a bunch of other things!
What other things?
First of all, I've been using Fish shell for years, and this configuration just made it active. Fish shell has a ton of automatic completions which you'll see as you type commands, and you can use by simply pressing tab.
This also configures Starship, an advanced prompt that gives you a lot of information at a glance. As a developer, this is hugely helpful!

Starship has around a 100 different modules, most of which show context related to your current directory. For Drupal development those git status flags, along with the PHP version are particularly useful.
Atuin is an advanced shell-history manager. Besides making it easy to search your shell history, you can also view it with timestamps if you want to go back to a particular time, or see what you were working on on a particular day.
Tealdeer (tldr) is a handy tool -- a play on tldr
(too long, didn't read, which is what you actually type) that provides shortened help with examples of most commands you might want to use.
Ripgrep (rg) is a very fast recursive grep (search) tool -- you can search a code base for a string very quickly, while skipping ignored directories.
HttPie (http) is an alternative to Curl, which shows headers by default and pretty-prints json.
Commitizen (cz) is a "Conventional Commits" commit message formatter wizard.
Neovim is a modern re-implementation of vim, which Nix makes easy to install.
One of these tools hasn't worked for me on Ubuntu, but I can run it in a nix-shell and then it works:
nix-shell -p fishPlugins.forgit
... forgit is mind-blowing. It provides some shortcuts that expand to git-forgit, which uses fzf to provide powerful search on all sorts of git operations. I particularly use ga
- git add, glo
- git log, and gd
- git diff, often.

For more on Forgit, this Medium article has a good summary.
Customizing your home manager further
Nix provides so much that you can easily drop in, and make available on all your machines. Once you've dialed in your home manager config, you can push it into your own repo to deploy anywhere you want to use it -- and as you update and refine it, you can simply pull your changes to your other machines and apply.
As for what to add or configure, the main home-manager configuration can load anything that's in nixpkgs -- the main Nix package repository. If you want to try something out temporarily, nix-shell
is a super simple way to install anything you want, just in the shell you run it in. Want to try some new software? If it's available in nixpkgs, you can probably install it with a single command -- temporarily, in a way that will disappear when you leave the shell and collect garbage.
This goes well beyond just shell tools. Nixpkgs has over 120K packages available, and more than 20K options. You probably shouldn't install graphical software on a server -- but if you're on a desktop and want to give say Blender a try, you can install it and all its dependencies temporarily using nix-shell -p blender
and then use blender
to run it.
To find things to install or configure, Search.nixos.org is the place to go. You can use nix-shell -p with almost all the packages to install temporarily, and you can add them to your home.nix file in the packages list to install permanently in your portable profile.
If you want to install something permanently, I do suggest searching the NixOS Options tab first. Many of these options may not make sense in Home Manager, but a lot of programs do provide options that supply configuration as well as the package -- you can see this in the home.nix "programs.neovim", "programs.atuin" and other sections of my home.nix. Compared to other dotfile managers, this is your starting point -- use the Nix options first, if they are available. There are other ways to manage entire configuration files if you need them -- in my case I tend to use the defaults with just a few overrides.
And that wraps up our intro to Nix, using Home Manager to add power to your shell! If nothing else, it makes it easy to get direnv running, everywhere you install your configuration. We'll get into using a flake.nix in your development projects next!
Update: It turns out my…
Update: It turns out my config is only working properly with Fish shell. I've added a line that should load direnv support in Bash, but it's not working for everyone...
Add new comment