Nix
Home > Developer Guide > Buildkit
nix is a cross-platform package-manager which provides developer shells. nix runs on top of most Linux
distributions (Debian, Ubuntu, Redhat, etc) as well as macOS and WSL2. Nix packages are stored in a separate folder
(/nix), and you can run multiple versions of any package (with minimal effect on the main host).
nix is used by the CI test-infrastructure for civicrm-core.
??? info "Major features"
These instructions will install the following packages in `/nix`:
* __Interpreters__: PHP-CLI, NodeJS
* __Servers__: Apache HTTPD, MySQL, PHP-FPM, MailHog, Redis <!-- Memcached is installed but disabled by default -->
Additionally, they will install buildkit in `$HOME/buildkit`.
??? info "Trade-offs"
* __Pro__: `nix` runs locally at native speed on Linux+macOS with x86+arm64. Configuration is packaged, editable, and disposable. Can be combined with desktop tools (IDEs/debuggers). Packages don't interfere with host. Closely matches official test environment.
* __Con__: Windows requires virtualization (WSL2). Customization requires learning new language. Major host OS updates sometimes have compatibility issues (but usually fixable).
??? caution "Coexistence with other MySQL services ($HOME/.my.cnf)"
<!-- It would be nice to disable or deprioritize `HOME/.my.cnf` within a nix shell, so we wouldn't need to explain this stuff. But I haven't a found a nice way to disable it. -->
We will use nix to start extra services (Apache, PHP-FPM, MySQL, etc) in a developer shell. These have *soft isolation*, which allows them to coexist with
other services that you installed previously. For example, an old instance of Ubuntu-MySQL (port 3306) can coexist with a new instance of nix-MySQL (port 3307).
However, MySQL (specifically) has an extra consideration: if you are running _multiple instances_ of MySQL, then you should double-check the file `$HOME/.my.cnf`.
This file acts as a global override.
🟢 In many systems, `$HOME/.my.cnf` doesn't exist. No global overrides apply. No extra steps are required.
🟠 In some systems, `$HOME/.my.cnf` has pre-existing credentials for (say) Ubuntu-MySQL. There is a global override.
The presence of a global override will block you from using nix-MySQL (especially with CLI tools like `mysql` or `mysqldump`).
As a simple work-around, you can temporarily rename the file:
```bash
## To unblock access to nix-MySQL, move the file aside.
mv $HOME/.my.cnf $HOME/.my.cnf-orig
## To restore access to Ubuntu-MySQL, put the file back.
mv $HOME/.my.cnf-orig $HOME/.my.cnf
```
Of course, there are other ways to handle the situation -- but this technique is simple.
Requirements
- Host machine with Linux, macOS, or WSL2
- (Note: Generally, you'll get the best results with an OS release that is 3-24 months old -- something recent but not brand new.)
- (Note: For WSL2, the "WSL Settings" should enable "Localhost forwarding" to simplify configuration. This should be default in new WSL2 systems. Non-localhost is possible, but the extra configuration isn't documented here.)
- x86 or arm64
git- Sudo privileges
Profiles
A profile defines a list of pre-selected packages (such as PHP, MySQL, and gzip). Buildkit includes several profiles.
For this tutorial, we'll use the "default" (dfl) profile which includes a middle-of-the-road configuration.
But you may choose another profile if you want specific versions of PHP and MySQL.
??? info "Choosing an alternative profile..."
All buildkit profiles include common utilities (such as `tar`, `gzip`, `redis`, and `mailcatcher`).
The _distinctive_ feature of each profile is how it addresses PHP and MySQL. Let's compare some examples:
| Profile | Description |
| -- | -- |
| `php84m80` | (__Specifically__) PHP 8.4 and MySQL 8.0
| `php83m57` | (__Specifically__) PHP 8.3 and MySQL 5.7
| `php82r106` | (__Specifically__) PHP 8.2 and MariaDB 10.6
| `php85p84` | (__Specifically__) PHP 8.5 and Percona MySQL 8.4
| `php84` | PHP 8.4. (*Also: MySQL 8.0, but this may change every few years.*)
| `php83` | PHP 8.3. (*Also: MySQL 8.0, but this may change every few years.*)
| `php82` | PHP 8.2. (*Also: MySQL 8.0, but this may change every few years.*)
| `dfl` | (__Floating__) _Default_ suggestions. Mid-range versions of PHP/MySQL.
| `min` | (__Floating__) _Minimal_ versions of PHP and MySQL.
| `max` | (__Floating__) _Maximal_ versions of PHP and MySQL.
| `old` | (__Floating__) _Old, unsupported_ versions of PHP and MySQL.
| `edge` | (__Floating__) _New, unsupported_ versions of PHP and MySQL.
Note how some profiles are set to specific versions (as in `php84m80`), while other profiles change over
time (as in `min` or `max`).
When using specific versions, there are many possible permutations. In general, you can combine these parts:
* PHP Version: `php73`, `php74`, `php80`, `php81`, `php82`, `php83`, `php84`
* DBMS Version (MySQL): `m57`, `m80`, `m84`, `m90`
* DBMS Version (MariaDB): `r106`, `r1011`
* DBMS Version (Percona): `p80`, `p84`
In the following steps, we will download and startup `dfl`. However, you can switch to any of these other profiles.
Download
## Download the configuration
git clone https://github.com/civicrm/civicrm-buildkit ~/buildkit
## Download and install the binaries
cd ~/buildkit
PROFILES=dfl ./nix/bin/install-developer.sh
!!! info "The "install-developer.sh" script will download a few gigabytes worth of data.
It may compile some packages from source."
For further discussion about these commands and their variations, see nix/doc/install-developer.md.
Startup
## Open a subshell
use-bknix dfl -s
## Start the services - HTTPD, MySQL, etc
cd ~/buildkit
loco run
!!! info "The "loco run" command will start HTTPD, MySQL, etc on alternative ports.
This allows them to coexist with any other services you have."
For further discussion about these commands and their variations, see nix/doc/usage-loco.md.
Next steps
Finally, once you are able to work with use-bknix and loco, you can move on to using civibuild within the subshell.