There’s a new web implementation called Caddy, written in Go, with many new features. But the documentation is relatively poor and outdated compared to Nginx and Apache. But Anyway, I have spent an hour or so, and I figured out how to set up migrate my blog to this lovely new server.

Currently on this blog, I’m using:

  • Ubuntu 18.04.1
  • MariaDB 10.3
  • PHP 7.2
  • Caddy 0.11
  • Let’s Encrypt certification service brought by Caddy


Step 1: Add MariaDB mirror and upgrade the system: 

apt-get install software-properties-common
apt-key adv --recv-keys --keyserver hkp:// 0xF1656F24C74CD1D8
add-apt-repository 'deb [arch=amd64,arm64,ppc64el] bionic main'
apt dist-upgrade

Step 2: Install MariaDB and PHP:

apt install mariadb-server php-gd php-mbstring php-xml php-xmlrpc php-soap php-intl php-zip php-fcgi php-fpm php-mysql php-curl

When installing MariaDB in the last step, it will ask you to enter the root password to create a new root account. Remember to create a stronger one. For me, I prefer using uuidgen and generate a random one. Then note it down somewhere offline.

Step 3: Install Caddy binary, from here:

MariaDB Configuration 

Create a new database by:

CREATE DATABASE your_wp_db_name DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Then create a user and assign to this database (remember to change the placeholder):

CREATE USER [email protected] IDENTIFIED BY 'whatever_the_password_is';
GRANT ALL PRIVILEGES ON your_wp_db_name.* to [email protected] IDENTIFIED BY 'whatever_the_password_is';

Finally, commit the changes and exit:


Cuddy Configuration & WordPress Installation

Step 1: Create directories and set the correct privileges:

mkdir /var/www
mkdir /etc/ssl/caddy
mkdir /etc/caddy
chown -R root:www-data /etc/caddy
chown -R www-data /etc/ssl/caddy
chmod 0770 /etc/ssl/caddy

Step 2: Create the configuration file, i.e. /etc/caddy/Caddyfile

Here I assume:

  • I put my WordPress instance to /var/www/wordpress
  • GZip enabled
  • Using Email to apply the certificate
  • Using the newest rewrite rules for WordPress
  • HSTS header enabled
  • PHP FastCGI running with default domain socket, {
 root /var/www/wordpress
 tls [email protected]
 header / Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
 fastcgi / /run/php/php7.2-fpm.sock php
 rewrite {
        if {path} not_match ^\/wp-admin
        to {path} {path}/ /index.php?{query}

Step 3: Download WordPress

Download the tarball and extract to /var/www:

wget -qO- | tar zxv -C /var/www

Then set the permission:

chown -R www-data:www-data /var/www/wordpress
chmod -R 770 /var/www/wordpress

Step 4: Systemd configuration


curl -s -o /etc/systemd/system/caddy.service

Then edit the line started with “ExecStart” and add ” –quicin the end of this line to enable QUIC. But it seems like QUIC doesn’t work correctly as there is a known issue for the QUIC library. But anyway I enabled it in case they fix it in the later versions. Ref

After that, refresh systemd and start the server by:

systemctl daemon-reload
systemctl enable caddy
systemctl start caddy

It’s time for fun

Now just open the browser and fill in the database settings created a moment ago.

Some extra issues I’ve solved

502 Bad Gateway issue

Simply try figuring out where the domain socket is for the PHP FastCGI and correct the settings in the Caddyfile. 

Gutenberg Editor doesn’t work, saying “show_ui not found”

Some of the online tutorials are outdated,  which may lead the newest Gutenberg editor failed to initialize. Use the one in the official sample Caddyfile instead, i.e.

 rewrite {
        if {path} not_match ^\/wp-admin
        to {path} {path}/ /index.php?{query}

HSTS issue

Some online HSTS enforcement checking service saying my blog’s HSTS doesn’t work correctly. To fix this, correct the HSTS header configuration in the Caddyfile:

header / Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"