Categories
devops

NGINX Heroku WordPress

NGINX, Heroku, and WordPress combined. This website is powered by WordPress on Heroku. Details on configuration are here.

My next #DevOps task is to add NGINX in front of the WordPress application. In the future, this could be used as a load balancer. Until then, NGINX will reverse proxy the requests to the Heroku application instance.

To start, I spun up a virtual machine running Ubuntu on Amazon’s EC2. Check out how to install and configure NGINX here. Make sure to open your firewall to HTTP & HTTPS traffic!

I encountered two major issues:

  1. The request passed by NGINX through the reverse proxy was not being understood by Heroku’s application stack.
  2. Once the application stack properly handled the request, WordPress’s response triggered a redirect loop.

Reverse Proxy

Heroku’s stack uses the host of the request to route to the appropriate application instance. The originating Host value is (in my example) ‘wwww.metatooth.com’. Heroku shouldn’t respond to this. Turn off the app’s Custom Domain feature if it does. Update the reverse proxy to set a new Host header that Heroku will respond to.

server {
    server_name www.metatooth.com;

    location / {
        proxy_pass https://calm-waters-18762.herokuapp.com;
        proxy_set_header Host calm-waters-18762.herokuapp.com;
    }

    # configure SSL here
}

Redirect Loop

Setting the Host request header got Heroku’s attention, now WordPress responds to that request with a redirect loop. I encountered this problem while trying to configure an HTTPS-only WordPress installation. The way out of the redirect loop was to update two more request headers and then to use those headers in the WordPress configuration. Here’s the new section of wp-config.php

 
if ( $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' )
{
        $_SERVER['HTTPS']       = 'on';
        $_SERVER['SERVER_PORT'] = '443';
        define('FORCE_SSL_ADMIN', true);
}

if ( isset($_SERVER['HTTP_X_FORWARDED_HOST']) ) {
        $_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST'];
}

That gets WordPress to not redirect to https on these proxied requests, but only if the request headers of X-Forwarded-Proto and X-Forwarded-Host are specified. The NGINX configuration now is:

server {
    server_name www.metatooth.com;

    location / {
        proxy_pass https://calm-waters-18762.herokuapp.com;
        proxy_set_header Host calm-waters-18762.herokuapp.com;
        proxy_set_header X-Forwarded-Host $host;    
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # configure SSL here
}

That’s how I got NGINX, Heroku, and WordPress to play well together. Next task is to use an upstream for the proxy_pass directives. What’s your infrastructure layout and what did you learn along the way? Tell me about it in the comments!