composer2nix
composer2nix is a tool that can be used to generate Nix
expressions for PHP composer packages., (*1)
Nix integration makes it possible to use the Nix package manager (as opposed to
composer) to deploy PHP packages including all their required dependencies., (*2)
In addition, generated Nix composer packages
support convenient integration of PHP applications with NixOS services, such as
NixOS' Apache HTTP service., (*3)
Prerequisites
This package requires the following packages to be installed:, (*4)
- Nix package manager
- The Nix prefetch scripts. They can be installed from Nix packages by running:
$ nix-env -f '<nixpkgs>' -iA nix-prefetch-scripts
Consult the Nix documentation for detailed installation instructions., (*5)
Installation
This package can be installed with both composer and the Nix package manager.
To install it with composer, run:, (*6)
$ composer global require svanderburg/composer2nix
To install this package with Nix, clone the Git repository and run:, (*7)
$ nix-env -f release.nix -iA package.x86_64-linux
Building a development version
A development version can be deployed by checking out the Git repository and
running:, (*8)
$ nix-env -f release.nix -iA package.x86_64-linux
The above command installs the development composer2nix executable into the
Nix profile of the user., (*9)
Alternatively, you can use composer directly to install the project
dependencies:, (*10)
$ composer install
Usage
You need a project providing a composer.json and (if applicable) a
composer.lock configuration file., (*11)
Running the following command generates Nix expressions from the composer
configuration files:, (*12)
$ composer2nix
The above command produces three expressions: php-packages.nix containing the
dependencies, composer-env.nix the build infrastructure and default.nix that
can be used to compose the package from its dependencies., (*13)
Running the following command-line instruction deploys the package with Nix
including its dependencies:, (*14)
$ nix-build
Deploying a web application project
We can use composer2nix to automate the deployment of a web application project
as part of a NixOS configuration., (*15)
For example, we can create the following trivial PHP web application
(index.php) that uses the dompdf library to
generate a PDF file from an HTML page:, (*16)
loadHtml('hello world');
$dompdf->setPaper('A4', 'landscape');
$dompdf->render();
$dompdf->stream();
?>
We can write the following composer.json configuration file to configure the
dompdf dependency:, (*17)
{
"name": "exampleapp/exampleapp",
"require": {
"dompdf/dompdf": "^0.8.0"
}
}
With the following commmand we can let composer deploy the dependencies (and
pinpoint the used versions in a composer.lock file):, (*18)
$ composer install
Instead, we can also use composer2nix:, (*19)
$ composer2nix
The above command generates Nix expressions that can be used to deploy the web
application and its dependencies., (*20)
We can use Nix to build a bundle of our web application including its
dependencies:, (*21)
$ nix-build
$ ls result/
index.php vendor/
(As may be observed, the vendor/ folder contains all dependency artifacts)., (*22)
We can attach the generated package to a document root of the Apache server in
a NixOS configuration:, (*23)
{pkgs, config, ...}:
let
myexampleapp = import /home/sander/myexampleapp {
inherit pkgs;
};
in
{
time.timeZone = "UTC";
services.httpd = {
enable = true;
adminAddr = "admin@localhost";
enablePHP = true;
documentRoot = myexampleapp;
};
...
}
We can deploy the above NixOS configuration as follows:, (*24)
$ nixos-rebuild switch
If the above command succeeds, we have a running system with the Apache
webserver serving our web application., (*25)
Deploying a command-line utility project
In addition to web applications, we can also deploy command-line utility
projects implemented in PHP., (*26)
For example, for the composer2nix project, we can generate a CLI-specific
expression by adding the --executable parameter:, (*27)
$ composer2nix --executable
We can install the composer2nix executable in our Nix profile by running:, (*28)
$ nix-env -f default.nix -i
Deploying third-party end user packages
Aside from deploying development projects, we may also want to deploy third
party end-user packages, typically command-line tools., (*29)
We can use composer2nix to automatically generate expressions from a third
party package that comes from Packagist, such as phpunit:, (*30)
$ composer2nix -p phpunit/phpunit
After generating the expressions, we can deploy phpunit in our Nix profile,
by running:, (*31)
$ nix-env -f default.nix -iA phpunit-phpunit
And after installing the package with Nix, we should be able to run:, (*32)
$ phpunit --version
By default, composer2nix attempts to download the latest version of a package.
We can also add a parameter that specifies the version we want to use:, (*33)
$ composer2nix -p phpunit/phpunit --package-version 6.2.0
The above command-line instruction deploys phpunit version 6.2.0., (*34)
The --package-version parameter supports any version specifier supported by
composer, including version ranges., (*35)
Advanced features
composer2nix supports a number of less commonly used advanced features., (*36)
Disabling the deployment of development dependencies
By default composer (and as a result, also composer2nix) will include all
development dependencies. However, in production environments you typically want
to exclude them to reduce the amount of disk space consumed and the deployment
times., (*37)
By overriding the expression (e.g. creating a file named: override.nix) and
appending the noDev = true; parameter, we can disable development
dependencies:, (*38)
{pkgs ? import <nixpkgs> {
inherit system;
}, system ? builtins.currentSystem}:
let
phpPackage = import ./default.nix {
inherit pkgs system;
noDev = true; # Disable development dependencies
};
in
phpPackage
We can deploy the above package with the following command-line instruction:, (*39)
$ nix-build override.nix
Removing composer artifacts
By default, when deploying a composer package with Nix it will also include the
composer configuration files (composer.json and composer.lock) in the
package., (*40)
However, for production scenarios, such as deploying a web application, you
typically do not need these files. It is also possible to remove these composer
configuration files:, (*41)
{pkgs ? import <nixpkgs> {
inherit system;
}, system ? builtins.currentSystem}:
let
phpPackage = import ./default.nix {
inherit pkgs system;
};
in
phpPackage.override {
removeComposerArtifacts = true; # Remove composer configuration files
}
Running post installation instructions
For some packages, we may want to run additional command line instructions after
the packaging process completes, such as running unit tests., (*42)
By creating an override Nix expression that invokes the generated build function
and providing a postInstall hook, we can specify additional command-line
instructions to run:, (*43)
{pkgs ? import <nixpkgs> {
inherit system;
}, system ? builtins.currentSystem}:
let
phpPackage = import ./default.nix {
inherit pkgs system;
};
in
phpPackage.override {
postInstall = ''
php vendor/bin/phpunit tests
'';
}
In the above code fragment, we invoke phpunit to run all our unit tests., (*44)
Adding unspecified dependencies
Some packages may also require non-PHP package dependencies. Since these
dependencies are not specified in a composer configuration file, their
deployments may typically fail in a Nix builder environment, because they cannot
be implicitly found., (*45)
By overriding the generated package expression, we can supply these missing
dependencies ourselves:, (*46)
{pkgs ? import <nixpkgs> {
inherit system;
}, system ? builtins.currentSystem}:
let
phpPackage = import ./default.nix {
inherit pkgs system;
};
in
phpPackage.override {
buildInputs = [ pkgs.graphviz ];
postInstall = ''
php vendor/bin/phpdocumentor -d src -t out
'';
}
The above expression overrides the generated PHP package by supplying graphviz
as an extra dependency. This package is particularly useful when it is desired
to use phpdocumentor -- it uses graphviz to generate class diagrams. If this
tool is not present in the build environment, class diagrams will not be
generated., (*47)
Symlinking dependencies
By default, composer2nix makes copies of all packages that end up in the
vendor/ folder. This is the default option, because some packages load the
autoload.php relative from its resolved location, such as phpunit and may
not work properly if a dependency is a symlink., (*48)
It is also possible to symlink all dependencies as opposed to copying them which
makes deployments faster and more space efficient:, (*49)
$ composer2nix --symlink-dependencies
Limitations
This tool is still in the prototype stage. As a result, it may have some issues.
Furthermore, support for fossil repositories is currently completely absent., (*50)
License
The contents of this package is available under the MIT license, (*51)