Moving WordPress to nginx

This WordPress site has been migrated from Apache to nginx. The front-end is an internet-facing reverse-proxy using nginx, with the back-end using nginx and php-fpm. Both ends run inside jails on FreeBSD servers.

This article focusses on the back-end configuration, the nginx instance that serves static content from the WordPress installation at /usr/local/www/wordpress/ and forwards PHP requests to the php-fpm service listening on port 9000.

Installation

The packages are installed using:

# pkg install www/nginx
# pkg install www/wordpress

Add these lines to /etc/rc.conf:

nginx_enable="YES"
php_fpm_enable="YES"

nginx Configuration

In /usr/local/etc/nginx/nginx.conf:

events { }

http {
  include      mime.types;
  default_type application/octet-stream;
  root         /var/empty;
  sendfile     on;
  tcp_nodelay  on;
  tcp_nopush   on;

  upstream php { server 127.0.0.1:9000; }

  map $http_x_forwarded_proto $https_flag {
    default off;
    https   on;
  }

  server {
    listen 80;
    set $controller /af/index.php;

    location /af
      alias /usr/local/www/wordpress;

      index index.php;
      if (!-e $request_filename) { rewrite ^ $controller last; }

      location ~ /wp-content/uploads/ { expires 30d; }

      location ~ \.php$ {
        if (!-f $request_filename) { rewrite ^ $controller last; }

        include       fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $request_filename;
        fastcgi_param HTTPS $https_flag;
        fastcgi_pass  php;
      }

      location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { 
        if (!-f $request_filename) { rewrite ^ $controller last; }
        expires 30d; 
      }
    }
  }
}

We use pretty permalinks exclusively, so all non-static content is simply rewritten to /af/index.php.

The front-end terminates any client SSL connections, the presence of which is conveyed to WordPress using the $https_flag trick above.

nginx and php-fpm run within the same jail, with both services listening on the jail’s assigned IP address. 127.0.0.1 is used above for illustrative purposes only, although valid for a non-jailed environment.

php-fpm Configuration

Copy /usr/local/etc/php-fpm.conf.default to /usr/local/etc/php-fpm.conf and change the listen directive to the IP address assigned to the jail (if applicable).

WordPress Configuration

The only change to WordPress is related to running it in a subdirectory. We define the site URL by adding these lines to /usr/local/www/wordpress/wp-config.php:

define( 'WP_SITEURL', '/af' );
define( 'WP_HOME', '/af' );

We leave out the scheme and the domain to make the reverse-proxy transparent. This works for us but may break some plugins.

References

  1. WordPress recipe
  2. Nginx: alias, try_files and PHP
  3. Previous version of this article