Skip to main content

Setting up a WordPress website on NixOS

·4 mins
Table of Contents

Another instance where NixOS makes it easy to self-host services, this time we’re setting up WordPress using the upstream nixpkgs module and some auxiliary functions to help us package themes and plugins.

{ config, lib, pkgs, ... }:

let
  domain = "example.com";

  # Auxiliary functions
  fetchPackage = { name, version, hash, isTheme }:
    pkgs.stdenv.mkDerivation rec {
      inherit name version hash;
      src = let type = if isTheme then "theme" else "plugin";
      in pkgs.fetchzip {
        inherit name version hash;
        url = "https://downloads.wordpress.org/${type}/${name}.${version}.zip";
      };
      installPhase = "mkdir -p $out; cp -R * $out/";
    };

  fetchPlugin = { name, version, hash }:
    (fetchPackage {
      name = name;
      version = version;
      hash = hash;
      isTheme = false;
    });

  fetchTheme = { name, version, hash }:
    (fetchPackage {
      name = name;
      version = version;
      hash = hash;
      isTheme = true;
    });

  # Plugins
  google-site-kit = (fetchPlugin {
    name = "google-site-kit";
    version = "1.103.0";
    hash = "sha256-8QZ4XTCKVdIVtbTV7Ka4HVMiUGkBYkxsw8ctWDV8gxs=";
  });

  # Themes
  astra = (fetchTheme {
    name = "astra";
    version = "4.1.5";
    hash = "sha256-X3Jv2kn0FCCOPgrID0ZU8CuSjm/Ia/d+om/ShP5IBgA=";
  });

in {
  services = {
    nginx.virtualHosts.${domain} = {
      enableACME = true;
      forceSSL = true;
    };

    wordpress = {
      webserver = "nginx";
      sites."${domain}" = {
        plugins = { inherit google-site-kit; };
        themes = { inherit astra; };
        settings = { WP_DEFAULT_THEME = "astra"; };
      };
    };
  };

  # As this is a root on tmpfs system, we use the impermanence
  # NixOS module to persist WordPress state between reboots.
  # You can omit the next two lines if using a regular configuration.
  environment.persistence."/persist".directories =
    [ "/var/lib/mysql" "/var/lib/wordpress" ];
}

I configure WordPress to use Nginx as the web server instead of httpd as it’s what I already use as a reverse proxy for my other self-hosted applications.

After deploying this configuration, you’ll be met with the famous 5-minute WordPress installation at your domain, with a MySQL database and Let’s Encrypt automatically configured for you. For demonstration, the Astra theme and the Google Site Kit plugin will also be automatically installed.

You’re then presented with the usual WordPress dashboard, where you’re free to enable the plugins we just installed and also do other miscellaneous configuration. In theory, these steps can also be declarative using the services.wordpress.sites.<domain>.extraConfig, although I had trouble doing that and was met with database connection errors when rebuilding the configuration.

Beyond the ease of installation, there may be advantages to using WordPress on NixOS instead of a docker-compose setup, for example. WordPress is known to quickly become a remote shell for intruders if not properly looked after and regularly updated. On NixOS, the only themes and plugins the WordPress instance will have access to will be the ones we explicitly set in the NixOS module, preventing the installation of plugins with malware by some distracted administrator through the Web interface. Thanks to the Nix store’s properties of immutability and restricted permissions, it’ll also be harder for malicious plugins to modify themselves when compared to normal setups.

Conclusion #

Once again, NixOS made setting up another self-hosted service very easy.

This post will help you set up a basic WordPress instance, you’re then free to install more plugins and to optimize the website further. There are some suggestions on the relevant NixOS Wiki page.

Although I felt I learned something with this experience, I still prefer using simple Static Site Generators like Hugo for my personal projects. Using Hugo along with ox-hugo allows me to have a website that’s quite “declarative”, configured with plain text files, where I can do easy version control and deploy anywhere, many times for free. It also produces very fast sites without much effort, many times being close to a perfect score on the Lighthouse speed test. I also can be more relieved about security and maintenance as it’s just my webserver serving static files, without any backend or database to be exploited.

Nonetheless, about one third of the Web are WordPress websites and it’s useful to know how to set them up and configure them on NixOS.

References #