WordPress with SSL (https) behind a Reverse Proxy (Apache)

As you can see, this blog is accessible through SSL (https) encryption only. Normally this is not a huge problem but WordPress is a little bit clunky if it comes to a setup that also includes a reverse proxy.

The following text is a sum up some pages which can be found on the internet but often lacks information. This WordPress blog that you are currently reading is running on an Apache httpd on localhost. In front of it, there is a second Apache httpd which acts as reverse proxy for different tasks. One of these tasks is to offload SSL (https) encryption.

WordPress installation

In the described setup you should first install the WordPress software on http (port 80) without SSL. If you enable SSL at this time chances are good that you end up in a redirect loop.

Configure SSL (https)

On the reverse proxy configure SSL as usual but be aware, that you have to set RequestHeader set X-Forwarded-Proto "https" inside the SSL virtual host! This information is important as otherwise the URL’s generated by WordPress will be http links and therefore you will get browser warnings later. Do not force a permanent redirect from http to https at this point or you will not be able to install the necessary WordPress plugin which take care on your URL’s.

After you have enabled basic https support install the WordPress extension SSL Insecure Content Fixer and configure it to use the X-Forwarded-Proto header. Afterwards you have to modify the wp-config.php to reflect this settings. If you want use Jetpack, you also have to specify SERVER_PORT otherwise you will receive a error message on wordpress.com during the configuration of your social media connections (There was an error retrieving your site settings.). You also have to force admin SSL usage.

Hopefully this will help some people out there to get this up and running. If this config does not help you, leave a comment!

Apache http reverse proxy config

# ************************************
# Vhost template in module puppetlabs-apache
# Managed by Puppet
# ************************************

<VirtualHost *:443>
 ServerName www.wittedeurbellen.nl
 ServerAdmin webmaster@wittedeurbellen.nl

 ## Vhost docroot
 DocumentRoot "/var/www/html/www.wittedeurbellen.nl"

 ## Directories, there should at least be a declaration for /var/www/html/www.wittedeurbellen.nl

 <Location "/">
 Options None
 Require all granted

 <Location "/wp-admin">
 Options None
 Require all granted

 ## Logging
 ErrorLog "|/usr/sbin/rotatelogs -l -f /var/log/httpd/external/www.wittedeurbellen.nl/error-ssl_log.%Y.%m.%d 86400"
 ServerSignature Off
 CustomLog "|/usr/sbin/rotatelogs -l -f /var/log/httpd/external/www.wittedeurbellen.nl/access-ssl_log.%Y.%m.%d 86400" combined

 ## Request header rules
 ## as per http://httpd.apache.org/docs/2.2/mod/mod_headers.html#requestheader
 RequestHeader set X-Forwarded-Proto "https"

 ## Proxy rules
 ProxyRequests Off
 ProxyPreserveHost On
 ProxyPass / http://blog.wittedeurbellen.lan/ timeout=120
 ProxyPassReverse / http://blog.wittedeurbellen.lan/

 ## Server aliases
 ServerAlias *.wittedeurbellen.nl

 ## SSL directives
 SSLEngine on
 SSLCertificateFile "xxxxx.pem"
 SSLCertificateKeyFile "xxxxx.pem"
 SSLCertificateChainFile "xxxxxchain.pem"
 SSLCACertificatePath "/etc/pki/tls/certs"
 SSLOptions +StdEnvVars +ExportCertData

 # SSL Proxy directives
 SSLProxyEngine On

Nginx reverse proxy

I dont use Nginx at the moment, but it should work in the same manner. Just be shure that the X-Forwarded-Proto header is submitted by the reverse proxy to the backend.

WordPress wp-config.php

define('FORCE_SSL_ADMIN', true);