--- paginate: true footer: oliverdavies.uk --- # Nix for PHP Developers

Oliver Davies (opdavies) https://www.oliverdavies.uk --- # Nix for ~~PHP Developers~~ everyone

Oliver Davies (opdavies) https://www.oliverdavies.uk --- # About Me - PHP since 2007 - Drupal since 2008 - Full-time Linux since ~2015 - Nix/NixOS since 2022 - Gave my first presentation at unified.diff in September 2012 --- ![bg fit](./book.png) --- # Who has PHP installed
on their computer? --- # Who has multiple versions
of PHP installed? --- # Installing PHP - WAMP (Windows), MAMP (macOS), XAMPP - Homebrew (`brew install php`) - `apt`, `dnf`, `yum`, `pacman` `yay` - Laravel Herd/Sail - Symfony CLI? - Containers (Docker, Podman, LXC, etc) - Virtual machines (VMWare, Virtualbox, etc) --- ![](./NixOS.png) --- # What is Nix? - Package manager with more than **120,000** packages (`nixpkgs`) - Operating system with more than **20,000** packages (NixOS) - Tool for declaratively building software reproducibly - A functional domain-specific configuration language - Home Manager, `nix-darwin`, `devenv` - Started as a research project by Eelco Dolstra around 2003 --- # What is Nix? - Package manager - Build tool - Operating system - Language --- ![](./nix-search.png) --- ![](./nix-search-php.png) --- ![](./nix-search-php2.png) --- ![bg fit](./repology.png) --- # Installing Nix https://nixos.org/download ```sh $ sh <(curl --proto '=https' --tlsv1.2 -L https://nixos.org/nix/install) \ --daemon ``` Different instructions for Linux, macOS and Windows (WSL2). Different instructions for NixOS. ```sh $ nix --version nix (Nix) 2.28.4 ``` --- ``` This installation tool will set up your computer with the Nix package manager. This will happen in a few stages: 1. Make sure your computer doesn't already have Nix. If it does, I will show you instructions on how to clean up your old install. 2. Show you what I am going to install and where. Then I will ask if you are ready to continue. 3. Create the system users (uids [30001..30032]) and groups (gid 30000) that the Nix daemon uses to run builds. To create system users in a different range, exit and run this tool again with NIX_FIRST_BUILD_UID set. 4. Perform the basic installation of the Nix files daemon. 5. Configure your shell to import special Nix Profile files, so you can use Nix. 6. Start the Nix daemon. ``` --- # Installing PHP with Ubuntu ```shell $ apt update -y $ apt-get install php $ which php /usr/bin/php $ php -v PHP 8.3.6 ``` --- # Running PHP with Nix ```shell $ nix run nixpkgs#php -- -v PHP 8.4.11 ``` ```shell $ nix shell nixpkgs#php $ which php /nix/store/s4kv9bzqawhqcyjg9xm2hji3jap6d6kd-php-with-extensions-8.4.11/bin/php $ php -v PHP 8.4.11 ``` --- # Running PHP with Nix ``` $ nix run nixpkgs#php83 -- -v PHP 8.3.25 ```
``` $ nix run nixpkgs#php82 -- -v PHP 8.2.29 ``` --- # Using a `shell.nix` file ```nix { pkgs ? import {} }: pkgs.mkShell { packages = with pkgs; [ php phpPackages.composer phpactor ]; } ``` ```shell $ nix-shell shell.nix [nix-shell:~/my-project]$ composer -V Composer version 2.8.5 2025-01-21 15:23:40 ``` --- # Using a `flake.nix` file ```nix { inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; outputs = inputs: let system = "x86_64-linux"; pkgs = import inputs.nixpkgs { inherit system; }; in { devShells.${system}.default = (import ./shell.nix { inherit pkgs; }); }; } ``` --- # Using a `flake.nix` file ```nix { inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; outputs = inputs: let system = "x86_64-linux"; pkgs = import inputs.nixpkgs { inherit system; }; in { devShells.${system}.default = pkgs.mkShell { packages = with pkgs; [ php phpPackages.composer phpactor ]; }; }; } ``` --- # Structure of a Flake-based project ```shell . ├── composer.json ├── composer.lock ├── flake.lock ├── flake.nix ├── output_dev ├── source └── vendor ```
As well as **flake.nix**, we also get **flake.lock**. --- # Pinning packages ```nix # flake.nix inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-24.11"; nixpkgs-pinned.url = "github:nixos/nixpkgs/45570c299dc2"; } ``` ```nix { let pkgs-stable = import inputs.nixpkgs-stable { inherit system; }; in { packages = [ pkgs-stable.php ]; }; } ``` --- # Managing services With NixOS: ```nix services.mysql.enable = true; services.mysql.initialDatabases = [ { name = "my_project"; } { name = "another_project"; } ]; ```
Without NixOS: --- # Managing services ```nix { inputs = { flake-parts.url = "github:hercules-ci/flake-parts"; nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; process-compose.url = "github:Platonic-Systems/process-compose-flake"; services.url = "github:juspay/services-flake"; }; # ... ``` --- # Managing services ```nix imports = [ inputs.process-compose.flakeModule ]; perSystem = { config, lib, pkgs, ... }: { process-compose."default" = { imports = [ inputs.services.processComposeModules.default ]; services = { # ... }; settings.processes = { # ... }; } ``` --- # Managing services ```nix services = { mysql."mysql1" = { enable = true; initialDatabases = [ { name = "drupal_nix_flake_example"; } ]; }; }; ``` --- # Managing services ```nix settings.processes = { php = { command = pkgs.writeShellApplication { name = "php-local-server"; text = "${getExe php} -S 127.0.0.1:${toString webPort} -t web"; }; depends_on."mysql1".condition = "process_healthy"; }; }; ``` --- # Managing services ```nix devShells.default = pkgs.mkShell { inputsFrom = [ config.process-compose."default".services.outputs.devShell ]; nativeBuildInputs = with pkgs; [ php phpPackages.composer ]; }; }; ```
Run `nix run .` and go to http://localhost:8000. --- ![bg fit](./process-compose.png) --- ![bg fit](./drupal-install.png) --- # Multiple PHPs - Laravel Herd/Sail - Containers - `phpenv`, `brew-php-switcher`, `phpbrew` - Vagrant - VMWare, VirtualBox - Different physical machines? --- # Nix is like `nvm`
for everything --- # My ideal environment ```shell $ php -v The program 'php' is currently not installed. $ cd ~/my-project $ php -v PHP 8.4.10 $ cd ~/another-project $ php -v PHP 8.3.24 ``` --- # Using direnv https://direnv.net > It augments existing shells with a new feature that can load and unload environment variables depending on the current directory.
In NixOS: ```nix { programs.direnv.enable = true; programs.direnv.nix-direnv.enable = true; } ``` --- # The .envrc file If you have a `flake.nix`: ```bash use flake ``` Using a remote Flake: ```bash use flake "git+https://code.oliverdavies.uk/opdavies/dev-shells#php84" ``` ```bash use flake "github:opdavies/dev-shells#php84" ``` --- # Packaging for Nix ```nix stdenv.mkDerivation (finalAttrs: { pname = "hello"; version = "2.12.2"; src = fetchurl { url = "mirror://gnu/hello/hello-${finalAttrs.version}.tar.gz"; hash = "sha256-WpqZbcKSzCTc9BHO6H6S9qrluNE72caBm0x6nc4IGKs="; }; env = lib.optionalAttrs stdenv.hostPlatform.isDarwin { NIX_LDFLAGS = "-liconv"; }; doCheck = true; doInstallCheck = true; # ... ``` --- # Packaging for Nix ```nix pkgs.writeShellApplication { name = "preview"; runtimeInputs = with pkgs.nodePackages; [ browser-sync ]; text = '' browser-sync start --ignore '**/.*' \ --no-notify \ --no-ui \ -sw ''; } ``` --- # Packaging PHP for Nix ```nix php.buildComposerProject2 (finalAttrs: { pname = "phpactor"; version = "2025.07.25.0"; src = fetchFromGitHub { owner = "phpactor"; repo = "phpactor"; tag = finalAttrs.version; hash = "sha256-9XWlWwq+xvqPgKIc7IGoMVTxajjYsrPo/ra/0JIE168="; }; vendorHash = "sha256-3xkt0QjytW4BOCgZdevat7zkSuZTPPvwz3yptiq5zoo="; # ... ``` --- # Packaging PHP for Nix ```nix php.buildComposerProject2 (finalAttrs: { pname = "pest"; version = "3.7.4"; src = fetchFromGitHub { owner = "pestphp"; repo = "pest"; tag = "v${finalAttrs.version}"; hash = "sha256-ddsdVx/Vsg7GG11fGASouBU3HAJLSjs1AQGHx52TWzA="; }; composerLock = ./composer.lock; vendorHash = "sha256-rOJ6PFp4Xfe89usoH455EAT30d2Tu3zd3+C/6K/kGBw="; # ... ``` --- # Packaging Sculpin Packaging Sculpin was essentially the same: https://code.oliverdavies.uk/opdavies/lab/src/branch/main/nix/sculpin ```shell nix build ./result/bin/sculpin generate ``` ```shell . ├── flake.lock ├── flake.nix ├── output_dev │   └── index.html └── source └── index.md ``` --- # Building Nix packages ```shell $ nix repl Nix 2.28.4 Type :? for help. nix-repl> :l . Added 24244 variables. nix-repl> :b phpactor This derivation produced the following outputs: out -> /nix/store/nhq4js2lsj8lb1cz6dj4vrf6xb2r2zbd-phpactor-2025.03.28.0 ``` ```shell /nix/store/nhq4js2lsj8lb1cz6dj4vrf6xb2r2zbd-phpactor-2025.03.28.0/bin/phpactor Phpactor 2025.03.28.0 ``` --- # Not sure? Want to try it, but you're not sure?
```shell $ docker run --rm -it nixos/nix ```
```shell $ podman run --rm -it nixos/nix ``` --- # Thanks! - https://nixos.org - https://github.com/nixos/nixpkgs - https://wiki.nixos.org/wiki/PHP - https://nixos.org/manual/nixpkgs/stable/#ssec-building-php-projects - https://code.oliverdavies.uk/opdavies/lab - https://code.oliverdavies.uk/opdavies/nix-config (laptop and home server) - https://books.oliverdavies.uk/nix-for-php-developers (book, in progress)