Profile picture of Thomas Preece

Thomas Preece

Configuring Caddy for WordPress

WordPress, being a PHP application, generally assumes that your web server is Apache or Ngnix and has PHP support built in. It’s generally expected that you just unzip the application onto your web server and it just works. Caddy doesn’t work in the same way, and you’ll need to configure it manually.

Firstly, there’s no Caddy equivalent of mod_php that implements PHP directly inside the web server process. Instead, Caddy connects to a separate daemon that executes PHP code, known as PHP FastCGI Manager and conventionally abbreviated either as FastCGI or FPM. The two terms aren’t precisely identical, but for our purposes they are the same thing: the Caddy configuration directive is called php_fastcgi, and the package we need to install containing the daemon is called php-fpm.

The Caddy documentation has an extensive page on the php_fastcgi directive and all the things that it can do, which is an excellent reference for advanced configuration. The aim of this page, by contrast, is to provide a simple recipe to get it up and running.

I’m going to assume that you’re running on an Ubuntu or Debian system, and that you already have Caddy installed and use a Caddyfile to configure it. With that in mind, we can proceed to install PHP FPM:

$ sudo apt install php-fpm

The daemon should be enabled and started automatically. You can confirm this as follows:

$ ls /var/run/php
php8.1-fpm.pid  php8.1-fpm.sock  php-fpm.sock

This is for Ubuntu 22.04; the version of PHP installed will of course be the one available in your repositories. On Ubuntu 20.04, for example, it will be 7.4 instead. But regardless of the version number, the existence of the .pid and .sock files shows that FPM is installed and running.

php.fpm.sock is a symlink that points to /etc/alternatives/php-fpm.sock, which in turn points to /var/run/php8.1-fpm.sock (or whatever version you have installed). You can use either socket to connect to PHP FPM; for simplicity’s sake we’ll assume php-fpm.sock for this guide, which is probably the best option unless you’re installing something which depends on a very specific version of PHP.

Now let’s download and unpack WordPress. Let’s assume we’re creating a site for example.com, that we intend to store it in ~/www/example.com, and that Caddy and php-fpm are both running as the user www-data. Obviously you will need to change the directory names in this to the paths you are actually using:

$ cd ~/www
$ wget https://wordpress.org/latest.zip
$ unzip latest.zip
$ mv wordpress example.com
$ sudo chown -R www-data:www-data example.com

The last line - changing the owner of the entire site’s structure to www-data - is important, as WordPress expects to be able to read all of its files and to write to certain places (such as wp-config.php and the wp-content directory). It comes with all the permissions set correctly, as long as it is owned by the web server’s user.

Now let’s configure our Caddyfile - again, changing the paths of the server root and the log file to the ones you are actually using:

example.com {
	encode zstd gzip
	log {
		output file /var/log/caddy/example.com.log
	}
	
	root * /home/username/www/example.com
	php_fastcgi * unix//var/run/php/php-fpm.sock
	file_server
}

Make sure that the domain is pointed to your server in DNS, then restart or reload Caddy and visit your site; you should get the WordPress installation page. From there you can proceed to install WordPress exactly as usual; obviously you will need some other things like a MySQL or MariaDB server and the relevant PHP module to access it, but that’s all fairly typical WordPress stuff - this article is just about the way in which things are different to “normal” when you use Caddy.

If you don’t get to the WordPress installation page, you’ll likely get Caddy’s default blank error page. In this case you will want to check whether Caddy logged any errors when you reloaded it, and then also check:

  1. Is PHP-FPM running, and have you specified the correct path to the socket? Notice that there are two slashes between “unix” and “var” (because it is “unix/” followed by the full path, which begins “/var”).
  2. Have you set the owner of the WordPress tree correctly? It must be the same user that Caddy and PHP-FPM run as; you can check the latter with ls -la /var/run/php/. If Caddy and PHP-FPM are running as two different users, you will need to use groups to ensure that both users can read the WordPress tree and that the Caddy user can access the PHP-FPM socket.

There isn’t really anything in the WordPress installer that will prevent it from running and displaying at least something (even if it’s just an error from WordPress), so if you get a blank page then it is a reasonable assumption that there is a configuration problem with Caddy and/or PHP. If you do have any reason to suspect that there is a problem with WordPress, then a file containing just <?php echo('Hello world!'); ?> or <?php phpinfo(); ?> or something equally simple will of course allow you to prove whether or not your Caddy and PHP setup works.

You’ll also need to install a variety of PHP modules to get WordPress to work - the installer will complain about any essential ones that are missing, and then once it’s installed the Site Health screen will let you which additional ones are recommended.

The above recipe generally works fine if you want WordPress to be at the root of your domain; however, I ran across some issues when serving WordPress in a subdirectory. The following configuration, which essentially pretends to PHP-FPM that the site is really in the root of the domain, seems to solve those issues:

example.com {
	encode zstd gzip
	log {
		output file /var/log/caddy/example.com.log
	}
	
	root * /home/username/www/example.com
	route /blog/* {
		root * /home/username/www/example.com/blog
		uri strip_prefix /blog
		php_fastcgi * unix//var/run/php/php-fpm.sock
	}
	route /blog {
		redir /blog/ permanent
	}
	file_server
}

[ Blog Index | Home ]