Wordpress on Debian 5 with nginx, apache2 and admin under HTTPS

January 16th, 2010 | by jim |

This Wordpress instance is being served by a combination of Nginx and Apache2, with the admin pages under HTTPS using the Admin SSL plugin. It’s all done with the Debian 5 packaged versions and some nifty configuration …

Nginx

The public webserver is Nginx, which is the high-performance front-end webserver you should be using. Nginx is listening for both HTTP and HTTPS. It is directly serving all static content it can, based on a regexp to detect the types.

As added complications, the /wp-uploads/ files are in a different location, and need to have the requested file name rewritten. And there’s no point wasting our time sending static content over HTTPS, we’re going to redirect all of it to HTTP. This will trigger browser warnings regarding mixed content, but that’s not a big problem.

location ~ \.(html|css|js|png|gif|jpg|svg|ico|txt)$ {
    if ($scheme = https) {
        # Refuse to serve static content under HTTPS
        rewrite ^/(.*)$ http://$host/$1 break;
    }
    # Intercept and serve static files directly
    if ($request_uri ~ /wp-uploads/.*$) {
        rewrite ^/wp-uploads/(.*)$ /$1 break;
        root /var/www/wp-uploads/inode.co.nz;
    }
    if ($request_uri !~ /wp-uploads/.*$) {
        root /var/www/inode.co.nz;
    }
}

Everything else is proxied down to an Apache running mod_php, on localhost. This is pretty straightforward, except the Apache itself is running HTTP and HTTPS (using the same certificates as Nginx), so I have to choose which proxy to talk to :-

# Choose the proxy based on the current encryption scheme
if ($scheme = http) {
    proxy_pass http://127.0.1.1:80;
}
if ($scheme = https) {
    proxy_pass https://127.0.1.1:443;
}

We are also setting up some new headers so that Apache can use mod_rpaf, enabling it to log real end-user IP addresses in its logfiles.

Apache

The application webserver is Apache, running mod_php (libapache2-mod-php5), mod_rewrite (which is not enabled by default on Debian) and mod_rpaf (libapache2-mod-rpaf). Apache is listening to both HTTP and HTTPS, but will look out for requests to /wp-admin/ and /wp-login.php and make sure that they are redirected to HTTPS. This is basically the same setup as recommended by the Wordpress Codex.

# Bounce sensitive requests to https
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteRule ^/wp-admin(.*) https://inode.co.nz/wp-admin$1 [QSA,L]
    RewriteRule ^/wp-login.php(.*) https://inode.co.nz/wp-login.php$1 [QSA,L]
</IfModule>

The HTTPS server will also rewrite non-admin page requests, and direct you back to the HTTP version.

# Bounce non-sensitive requests to http
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteRule !^/wp-admin(.*) - [C]
    RewriteRule !^/wp-login.php(.*) - [C]
    RewriteRule ^/(.*) http://inode.co.nz/$1 [QSA,L]
</IfModule>

Admin SSL

This is almost enough, as most of the admin URLs presented by Wordpress are relative, and will therefore be HTTPS if the requested page was HTTPS. But for Wordpress versions below 2.6 (i.e. the standard Debian version is 2.5.1) you will need to install the Admin SSL plugin. The default configuration is fine, just install and enable the plugin (specifically, we are not using Shared SSL).

Conclusion

Here is a diagram showing what we have achieved :-

Wordpress under nginx & apache

HTTPS will be automatically invoked when accessing admin pages, and will be automatically switched off at all other times. Only requests that need PHP will be passed on to Apache, everything else will be handled by nginx.

Tags: , , ,

Post a Comment