Update: I added rewrite rules for WordPress permalinks to the Caddyfile. I also removed all unnecessary bits which are not needed anymore since Caddy now has built-in HTTPS support with Let’s Encrypt.
Recently I discovered an amazing open source project: Caddy, a fully functional HTTP/2 webserver, written in Go.
Caddy is a lightweight, general-purpose web server for Windows, Mac, Linux, BSD, and Android. It is a capable alternative to other popular and easy to use web servers.
The most notable features are HTTP/2, Virtual Hosts, TLS + SNI, and easy configuration with a Caddyfile. Usually, you have one Caddyfile per site. Most directives for the Caddyfile invoke a layer of middleware which can be used in your own Go programs.
In this tutorial I will explain how to run WordPress with Caddy server (on Ubuntu), using Caddy’s FastCGI support and PHP-FPM (i.e. PHP FastCGI Process Manager). Of course you also need MySQL/MariaDB to run WordPress.
MySQL
I assume that you have a MySQL server up and running (or that you have the knowledge to do so) .
PHP
Install PHP-FPM:
$ sudo apt-get install php5-fpm
PHP-FPM listens to FastCGI requests on a unix socket by default (on Ubuntu and Arch Linux): unix:/var/run/php5-fpm.sock (or unix:/var/run/php/php7.0-fpm.sock for PHP 7). So we’ll have to tell the webserver to pass the PHP requests to it.
You could also use a regular UDP socket if you want: change listen in /etc/php5/fpm/pool.d/www.conf to 127.0.0.1:9000. On some operating systems (e.g. FreeBSD), PHP-FPM listens on this UDP socket by default.
Caddyfile
Now we need to configure Caddy so it will use PHP-FPM. We also need to specify virtual hosts for the domain(s) we will be using.
The following Caddyfile contains everything you need to run WordPress with PHP-FPM on HTTP/2.
www.my-wordpress-blog.com {
redir https://my-wordpress-blog.com{uri}
}
my-wordpress-blog.com {
root wordpress
log access.log
errors error.log
# PHP-FPM with Unix socket
fastcgi / /var/run/php5-fpm.sock php
# PHP-FPM with regular udp socket
# fastcgi / 127.0.0.1:9000 php
# Routing for WordPress
rewrite /{
to {path} {path}/ /index.php?{query}
}
}
Caddy will use the wordpress folder as document root, and will pass all PHP requests to a FastCGI process (which is the PHP-FPM process). It will also automatically install SSL certificates (from Let’s Encrypt) and serve the website over HTTPS. HTTP requests will be redirected to the HTTPS domain.
The Caddy documentation contains more detailed information on the available directives. Checkout my other blogposts if you need help Running Caddy Server as a service or Creating a self-signed certificate.
WordPress
Now it’s time to install WordPress. Simple download WordPress and copy the files to the wordpress folder. To install WordPress you can just follow the steps on the screen like any other easy WordPress configuration.
If you want to use HTTP/2, you should configure WordPress with HTTPS enabled. You can do this in Settings, General: change http in the urls to https.
Most browsers only speak HTTP/2 when using TLS. Although TLS only is not marked as mandatory in the RFC 7540, Firefox and Chrome development teams have no actual intents to implement HTTP/2 without TLS.

Why you don’t just use the Caddy built-in HTTPS/Let’sEncrypt functionality?
I should indeed tell more about built-in Let’s Encrypt support in Caddy. At the time of writing Let’s Encrypt wasn’t available yet, and Caddy didn’t have support for it…
Thanks for commenting on this!
I keep getting a 502 Bad Gateway error. PHP5-FPM is installed and I tried both listening methods. Any clues?
In your Caddyfile: under
log access.log, adderrors error.logAnd post here both the output from the
access.logand theerror.logfor the request that triggers the bad gateway.You’re the man! Through the log I saw it said “08/Jan/2016:16:14:01 +0000 [ERROR 502 /] dial unix /var/run/php5-fpm.sock: no such file or directory” so I checked and there was indeed no file at that location. So I changed the directive to use 127.0.0.1:9000 and it magically started working. What’s weird is that I tried that three-four times last night and it still wouldn’t work. This wouldn’t be the first time I run into linux stuff mysteriously start working on its own lol.
Anyway much obliged!
No problem 🙂
Since I will have wordpress on my VPS too, I do not want to install mysql, postgresql, phpmyadmin etc. Thus hope there will be a wordpress solution as long as drupal solution etc.
How do you mean exactly? You can’t run WordPress without a database, can you?
Stuff like PHPMyAdmin can be omitted by using lightweight scripts like Adminer: https://www.adminer.org
Your Caddyfile may result in url errors in the wordpress admin…
have a look at the rewrite here ~> https://github.com/caddyserver/examples/blob/master/wordpress/Caddyfile
Does my Caddyfile pose any problems for your WordPress installation?
Because for me it works perfect with the single redirect.
# Routing for WordPressrewrite /{
to {path} {path}/ /index.php?{query}
}
I don’t have the original copy of the caddyfile I made after first consulting this post, but I used it on a site I manage and we had issues regarding the links in the admin menu for instance having the “wp-admin” missing & as a result clicking on things like “all posts” would take you to the frontend and a 404 because the “wp-admin” was “lost”.
https://mvesesani.com/edit.php
instead of
https://mvesesani.com/wp-admin/edit.php
Accessing the admin was fine. Even direct navigation to admin pages using urls worked perfectly. Just links in the interface didn’t work as expected.
Can’t compare your config to my old config now because I didn’t keep it though. Unfortunate.
What’s your current Caddyfile?
Which version of Caddy are/were you running?
I get “No such host at :2015”. What should I do? I don’t know what to do anymore. I tried a lot of things, but wordpress is still not working.
With my Caddyfile, WordPress is served on your domain, on port 80 and 443, not on 2015. Are you sure your Caddyfile is actually used by Caddy?
I wanted to test this first on my server before I go live. That’s why thought to use localhost. With your routing for wordpress i get an error. (caddyfile:15 – Parse error: Unknown directive ‘to’) That’s why I took the routing for wordpress from the example file on github.(https://github.com/caddyserver/examples/blob/master/wordpress/Caddyfile)
At the moment my caddyfile looks like:
localhost:8080
root /var/www/html/wordpresstest/
gzip
log access.log
errors error.log
# PHP-FPM with Unix socket
fastcgi / /var/run/php5-fpm.sock php
# PHP-FPM with regular udp socket
# fastcgi / 127.0.0.1:9000 php
# Routing for WordPress
rewrite {
if {path} not_match ^/wp-admin
to {path} {path}/ /index.php?_url={uri}
}
I start caddy with ./caddy -conf=”caddyfile”. So yes it should take the caddyfile above.
If have no clue why you’re seeing
No such host at :2015when Caddy is running on port8080. It’s like you’re going tohttp://localhost:2015in your browser, but even then, you shouldn’t get a webpage, since Caddy isn’t listening on that port…sorry I get the respond: “No such host at :8080”. It depends which port I use in the caddyfile. I tried a lot. Do I have to give some files more permissions?
caddy is working with the index.html file in the same folder when I don’t use the caddyfile. But it seems that caddy with the caddyfile thinks the path to my wordpress files is wrong. I double checked the path and it should work. But do I have to change some permissions to the wordpress files?
Ok I got it with some help… Localhost was the problem. It’s 0.0.0.0:8080 in the caddyfile…. thanks for your help!
Thanks Tobi, that worked for me!
Using your Caddyfile doesn’t give any problem detecting the correct host.
What’s the output of the Caddy process, and which URL you use to access it in the browser?