9.7 KiB
composer2nix
composer2nix
is a tool that can be used to generate Nix
expressions for PHP composer packages.
Nix integration makes it possible to use the Nix package manager (as opposed to composer) to deploy PHP packages including all their required dependencies.
In addition, generated Nix composer packages support convenient integration of PHP applications with NixOS services, such as NixOS' Apache HTTP service.
Prerequisites
This package requires the following packages to be installed:
- 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.
Installation
This package can be installed with both composer
and the Nix package manager.
To install it with composer, run:
$ composer global require svanderburg/composer2nix
To install this package with Nix, clone the Git repository and run:
$ 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:
$ 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.
Alternatively, you can use composer
directly to install the project
dependencies:
$ composer install
Usage
You need a project providing a composer.json
and (if applicable) a
composer.lock
configuration file.
Running the following command generates Nix expressions from the composer configuration files:
$ 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.
Running the following command-line instruction deploys the package with Nix including its dependencies:
$ 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.
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:
<?php
require 'vendor/autoload.php';
use Dompdf\Dompdf;
$dompdf = new Dompdf();
$dompdf->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:
{
"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):
$ composer install
Instead, we can also use composer2nix
:
$ composer2nix
The above command generates Nix expressions that can be used to deploy the web application and its dependencies.
We can use Nix to build a bundle of our web application including its dependencies:
$ nix-build
$ ls result/
index.php vendor/
(As may be observed, the vendor/
folder contains all dependency artifacts).
We can attach the generated package to a document root of the Apache server in a NixOS configuration:
{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:
$ nixos-rebuild switch
If the above command succeeds, we have a running system with the Apache webserver serving our web application.
Deploying a command-line utility project
In addition to web applications, we can also deploy command-line utility projects implemented in PHP.
For example, for the composer2nix
project, we can generate a CLI-specific
expression by adding the --executable
parameter:
$ composer2nix --executable
We can install the composer2nix
executable in our Nix profile by running:
$ 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.
We can use composer2nix
to automatically generate expressions from a third
party package that comes from Packagist, such as phpunit
:
$ composer2nix -p phpunit/phpunit
After generating the expressions, we can deploy phpunit
in our Nix profile,
by running:
$ nix-env -f default.nix -iA phpunit-phpunit
And after installing the package with Nix, we should be able to run:
$ 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:
$ composer2nix -p phpunit/phpunit --package-version 6.2.0
The above command-line instruction deploys phpunit
version 6.2.0
.
The --package-version
parameter supports any version specifier supported by
composer
, including version ranges.
Advanced features
composer2nix
supports a number of less commonly used advanced features.
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.
By overriding the expression (e.g. creating a file named: override.nix
) and
appending the noDev = true;
parameter, we can disable development
dependencies:
{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:
$ 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.
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:
{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.
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:
{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.
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.
By overriding the generated package expression, we can supply these missing dependencies ourselves:
{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.
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.
It is also possible to symlink all dependencies as opposed to copying them which makes deployments faster and more space efficient:
$ 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.
License
The contents of this package is available under the MIT license