I’ve been using Caddy as a reverse proxy for several self-hosted services and love it. It’s insanely easy to get going with just a line or two in the config file (Caddyfile).
However when trying to get WordPress working cleanly behind Caddy as a reverse proxy it’s had me scratching my head.
I tried running Caddy as well on the upstream server hosting WordPress, but this never seemed to work. So I stuck with what WordPress knows best; Apache.
The easy solution to get the Apache WordPress running behind the Caddy reverse proxy which comes up all the time when Googling is to include this line in your Caddyfile:
tls_insecure_ignore_verify
However as Caddy themselves point out, this is not best practise and they will remove this function in time from Caddy. It also begs the question, why bother with SSL/TLS in the first place from the Caddy reverse proxy to the Apache upstream if you’re just going to bypass the certification of the link? SSL is also only required in unsecure networks and if your network from your reverse proxy to your server is unsecure, you’ve got bigger problems than getting Caddy to work as a reverse proxy.
I tried all manner of Caddy configs to get it happy with WordPress behind it, but nothing would work outside of the tls_insecure_ignore_verify
from above.
In the end I came to the realisation that WordPress on the upstream just needed to be run in http (80) mode and to skip https (443) altogether, after all, SSL is what Caddy does best so let that handle it all. Not running https also saves overhead on the web server which is always a good thing.
But running WordPress in plain http mode has its issues; CSS and other assets won’t load across anything other than an SSL connection, so eventually I pinpointed my issue to be one very simple configuration of Apache and it’s even in the Apache documentation; Using WordPress being a reverse proxy
First make sure your WordPress install is configured correctly in the Apache config .conf file as just plain old http on port 80:
<VirtualHost *:80>
<Directory /var/www/<your-domain>/wordpress/>
AllowOverride All
</Directory>
ServerName example.com
ServerAlias www.example.com
ServerAdmin you@example.com
DocumentRoot /var/www/example/wordpress
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Then the magic is to add this to your wp-config.php for the domain, making sure to add it before the last line of require_once ABSPATH . 'wp-settings.php';
which I failed to do first time around and it didn’t work.
define( 'FORCE_SSL_ADMIN', true );
if( strpos( $_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false )
$_SERVER['HTTPS'] = 'on';
Lastly, don’t forget to amend your WordPress Address (URL) and Site Address (URL) under General Settings in your WordPress install to point to http and not https. Your site will still always be served as https due to Caddy handling the connection and forcing https at all times, but the connection from Caddy to WordPress across your network needs to be http and that’s how the WordPress install needs to talk to Caddy.
If you don’t alter the backend General Settings in time, then you can manually force the URL in wp-config.php, but this is a little hacky and it’s best to try and remember to do it in the General Settings page.
define( 'WP_HOME', 'http://example.com' );
define( 'WP_SITEURL', 'http://example.com' );
Then everything will work hunky dory from your Caddy reverse proxy to your WordPress install with just this in your Caddyfile
example.com {
reverse_proxy 192.168.1.2
}
It’s also best to add this to the top of your Caddyfile
servers {
trusted_proxies static private_ranges
}
As is always the way with these things, the solution is always simple and obvious, but unfortunately search results keep pulling you in the direction of the tls_insecure_skip_verify
which is not the proper method.