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 :-
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.
