Nix Flake development environment for WordPress

Following example provides a Nix Flake snippet which will spawn a virtual machine with WordPress running on NixOS locally. Custom plugin or theme sources can be mounted into the VM for development purpose.

Let’s start with the Flake-file itself. It can be created inside your theme or plugin directory which you want to work on.

{
  description = "WordPress development shell";

  inputs = {
    nixpkgs.url = "nixpkgs/nixos-24.05";
    nixos-shell.url = "github:Mic92/nixos-shell";
  };

  outputs = { self, nixpkgs, nixos-shell, ... }@inputs:
  let
    pkgs = nixpkgs.legacyPackages.x86_64-linux;
    start =
      pkgs.writeShellScriptBin "start" ''
        set -e
        export QEMU_NET_OPTS="hostfwd=tcp::8080-:80"
        ${pkgs.nixos-shell}/bin/nixos-shell --flake .
       '';
  in {
    nixosConfigurations.vm = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      specialArgs.inputs = inputs;
      modules = [
        ({ lib, config, pkgs, ... }: {

          nixpkgs.overlays = [
            (self: super: {
              wordpress = super.wordpress.overrideAttrs (oldAttrs: rec {
                postInstall = let
                  wpConfig = pkgs.writeTextFile {
                    name = "wp-config-localhost.php";
                    text = ''
                      <?php
                        $table_prefix  = 'wp_';
                        require_once('/var/lib/wordpress/localhost/secret-keys.php');
                        define('DB_CHARSET', 'utf8');
                        define('DB_HOST', 'localhost:3306');
                        define('DB_NAME', 'wordpress');
                        define('DB_PASSWORD', "");
                        define('DB_USER', 'wordpress');
                        define('FS_METHOD', 'direct');
                        if ( !defined('ABSPATH') )
                          define('ABSPATH', dirname(__FILE__) . '/');
                        require_once(ABSPATH . 'wp-settings.php');
                      ?>
                    '';
                  };
                in ''
                  ln -s ${wpConfig} $out/share/wordpress/wp-config.php
                  rm -r $out/share/wordpress/wp-content
                  ln -s /var/lib/wordpress/localhost/wp-content $out/share/wordpress/wp-content
                '';
              });
            })
          ];

          services.wordpress = {
            webserver = "nginx";
            sites."localhost" = { };
          };

          services.nginx.virtualHosts."localhost".root = lib.mkForce "${pkgs.wordpress}/share/wordpress";

          systemd.tmpfiles.rules = [
            "d /var/lib/wordpress/localhost 0750 wordpress caddy - -"
            "d /var/lib/wordpress/localhost/wp-content 0750 wordpress caddy - -"
            "d /var/lib/wordpress/localhost/wp-content/plugins 0750 wordpress caddy - -"
            "d /var/lib/wordpress/localhost/wp-content/themes 0750 wordpress caddy - -"
            "d /var/lib/wordpress/localhost/wp-content/upgrade 0750 wordpress caddy - -"
            "d /var/lib/wordpress/localhost/wp-content/uploads 0750 wordpress caddy - -"
          ];

          nixos-shell.mounts.extraMounts = {
            "/var/lib/wordpress/localhost/wp-content/themes/icynets-simplic" = {
               target = /home/onny/projects/icynets-simplic;
               cache = "none";
            };
          };

          system.stateVersion = "24.05";
          services.getty.autologinUser = "root";
          documentation = {
            info.enable = false;
            man.enable = false;
            nixos.enable = false;
          };
          nix = {
            package = pkgs.nixFlakes;
            registry.nixpkgs.flake = inputs.nixpkgs;
            settings.experimental-features = [ "nix-command" "flakes" ];
          };
        })
        nixos-shell.nixosModules.nixos-shell
      ];
    };

    packages = { inherit start; };
    defaultPackage.x86_64-linux = start;

  };
}

Add this flake.nix file to your Git index and start tracking it.

Using a signle command to spawn a virtual machine and reach your local WordPress instance at http://localhost:8080

nix flake run

How does it work?

The Flake file consists of several parts which you might have to adapt depending on your setup

  • Input-section: This part defines your Flake inputs. This is usefull in case you want to stick your development environment to a specific commit or version of the nixpkgs repository. Here we’re using latest stable version nixos-24.05.
  • Start script: The following start script is a bash script which will get executed with nix flake run. In this script, nixos-shell is used to spawn a virtual machine. The line QEMU_NET_OPTS="hostfwd=tcp::8080-:80" tells Qemu to forward port 8080 on the host to the internal port 80.
  • nixpkgs overlay: Using a overlay, we’ll modify the default WordPress package used in NixOS. It’s a bit hacky, because normally plugins and themes for WordPress will get copied into the read-only Nix store. In the modification we move the wp-content directory to /var/lib/wordpress/HOSTNAME so we can get write permissions. I haven’t figured out how to reuse the wp-config.php file of the native NixOS module, any help would be welcome :)
  • nixos-shell.mounts.extraMounts: This directive will mount my local project directory /home/onny/projects/icynets-simplic to the wp-content/themes directory inside the VM.

💬 Are you interested in our work or have some questions? Join us in our public Signal chat pi crew 👋
🪙 If you like our work or want to supprot us, you can donate MobileCoins to our address.

Leave a Reply

Your email address will not be published. Required fields are marked *