Custom nginx config in./nginx; Custom PHP php.ini config in./config; Volumes for nginx, wordpress and mariadb; Bedrock - modern development tools, easier configuration, and an improved secured folder structure for WordPress; Composer; WP-CLI - WP-CLI is the command-line interface for WordPress. MailHog - An email testing tool for developers. So you want to run WordPress on Nginx There are some great managed hosting options available for WordPress, and it’s a hosting niche that seems to be growing quickly.
Topics
- Generic and Multi-Site Support
- Better Performance for Static Files in Multisite
- Resources
While the LAMP stack (Linux + Apache + MySQL + PHP) is very popular for powering WordPress, it is also possible to use Nginx. WordPress supports Nginx, and some large WordPress sites, such as WordPress.com, are powered by Nginx.
When talking about Nginx, it is important to know that there are multiple ways to implement Nginx. It can be setup as a reverse-proxy in front of Apache, which is a very powerful setup that allows you to use all of the features and power of Apache, while benefiting from the speed of Nginx. Most websites that report using Nginx as the server (based on stats gathered from HTTP response headers), are actually Apache running with Nginx as the reverse proxy. (The HTTP response headers showing “Nginx” are being reported by the reverse-proxy, not the server itself.)
This guide is referring to a standalone Nginx setup, where it is used as the primary server instead of Apache. It should be noted that Nginx is not a completely interchangeable substitute for Apache. There are a few key differences affecting WordPress implementation that you need to be aware of before you proceed:
- With Nginx there is no directory-level configuration file like Apache’s .htaccess or IIS’s web.config files. All configuration has to be done at the server level by an administrator, and WordPress cannot modify the configuration, like it can with Apache or IIS.
- Pretty Permalinks functionality is slightly different when running Nginx.
- Since Nginx does not have .htaccess-type capability and WordPress cannot automatically modify the server configuration for you, it cannot generate the rewrite rules for you.
- Without modifications to your install, “index.php” will be added to your Permalinks. (There are ways to mitigate this with plugins (see below) and/or adding custom code to your child theme’s functions.php.)
- However, if you do want to have some (limited) .htaccess capability, it is technically possible to do add by installing the htscanner PECL extension for PHP. (However, this is not a perfect solution so be sure to test and debug thoroughly before using on a live site.)
This guide is not going to cover how to install and configure Nginx, so this assumes that you have already installed Nginx and have a basic understanding of how to work with and debug it.
Generic and Multi-Site Support Generic and Multi-Site Support
To make WordPress work with Nginx you have to configure the backend php-cgi. The options available are ‘fastcgi’ or ‘php-fpm’. Here, php-fpm is being used because it is included with PHP 5.3+, so installing it is straight forward.
The Nginx configuration has been broken up into five distinct files and is heavily commented to make each option easier to understand. The author also made a best-effort attempting to follow “best practices” for nginx configurations.
Main (generic) startup file Main (generic) startup file
This is equivalent to /etc/nginx/nginx.conf (or /etc/nginx/conf/nginx.conf if you’re using Arch Linux).
This is a bit different from standard nginx.conf files. This configuration follows the Ubuntu/Debian method of declaring enabled sites for maximum flexibility – using ‘sites-available’ to store a config and then symlink to the config file from ‘sites-enabled’.
Per Site configuration Per Site configuration
Splitting sections of the configuration into multiple files allows the same logic to be reused over and over. A ‘global’ subdirectory is used to add extra rules for general purpose use (either /etc/nginx/conf/global/ or /etc/nginx/global/ depending on how your nginx install is set up).
Global restrictions file Global restrictions file
General WordPress rules General WordPress rules
For single site installations, here is the ‘global/wordpress.conf’ file:
This is more up-to-date example for Nginx: https://www.nginx.com/resources/wiki/start/topics/recipes/wordpress/
WordPress Multisite Subdirectory rules WordPress Multisite Subdirectory rules
For multisite subdirectory installations, here is the ‘global/wordpress.conf’ file:
NGINX provides 2 special directive: X-Accel-Redirect and map. Using these 2 directives, one can eliminate performance hit for static-file serving on WordPress multisite network.
WordPress Multisite subdomains rules WordPress Multisite subdomains rules
Ref: https://www.nginx.com/resources/wiki/start/topics/recipes/wordpress/
HTTPS in Nginx HTTPS in Nginx
Enabling HTTPS in Nginx is relatively simple.
Mozilla offers an excellent SSL config generation tool as well.
WP Super Cache Rules WP Super Cache Rules
Experimental modifications:
If you are using HTTPS, the latest development version of WP Super Cache may use a different directory structure to differentiate between HTTP and HTTPS. try_files line may look like below:
W3 Total Cache Rules W3 Total Cache Rules
W3 Total Cache uses different directory structure for disk-based cache storage depending on WordPress configuration.
Cache validation checks will remain common as shown below:
FOR Normal WordPress (without Multisite)
Use following:
Wordpress Nginx Reverse Proxy
FOR Multisite with subdirectories
Use the following:
FOR Multisite with Subdomains/Domain-mapping
Use following:
Notes
- Nginx can handle gzip & browser cache automatically so better leave that part to nginx.
- W3 Total Cache Minify rules will work with above config without any issues.
Nginx fastcgi_cache Nginx fastcgi_cache
Nginx can perform caching on its own end to reduce load on your server. When you want to use Nginx’s built-in fastcgi_cache, you better compile nginx with fastcgi_cache_purge module. It will help nginx purge cache for a page when it gets edited. On the WordPress side, you need to install a plugin like Nginx Helper to utilize fastcgi_cache_purge feature.
Config will look like below:
Define a Nginx cache zone in http{…} block, outside server{…} block
For WordPress site config, in server{..} block add a cache check block as follow
Then make changes to PHP handling block
Just add this to the following php block. Note the line fastcgi_cache_valid 200 60m;
which tells nginx only to cache 200 responses(normal pages), which means that redirects are not cached. This is important for multilanguage sites where, if not implemented, nginx would cache the main url in one language instead of redirecting users to their respective content according to their language.
Such that it becomes something like this
Finally add a location for conditional purge
If you get an ‘unknown directive “fastcgi_cache_purge”‘ error check that your Nginx installation has fastcgi_cache_purge module.
Better Performance for Static Files in Multisite Better Performance for Static Files in Multisite
By default, on a Multisite setup, a static file request brings php into picture i.e. ms-files.php
file. You can get much better performance using Nginx Map{..}
directive.
In Nginx config for your site, above server{..}
block, add a section as follows:
It is just a list of site-names and blog-ids. You can use Nginx helper to get such a list of site-name/blog-id pairs. This plugin will also generate a map.conf
file which you can directly include in the map{} section like this:
After creating a map{..}
section, you just need to make one more change in your Nginx config so requests for /files/
will be first processed using nginx map{..}
:
Notes Notes
- Whenever a new site is created, deleted or an extra domain is mapped to an existing site, Nginx helper will update map.conf file automatically but you will still need to reload Nginx config manually. You can do that anytime later. Till then, only files for new sites will be served using php-fpm.
- This method does not generate any symbolic links. So, there will be no issues with accidental deletes or backup scripts that follow symbolic links.
- For large networks, this will scale-up nicely as there will be a single map.conf file.
Notes Notes
A couple of final but important notes: This whole setup assumes that the root of the site is the blog and that all files that will be referenced reside on the host. If you put the blog in a subdirectory such as /blog, then the rules will have to be modified. Perhaps someone can take these rules and make it possible to, for instance, use a:
directive in the main ‘server’ block and have it automagically apply to the generic WP rules.
Warning Warning
- A typo in Global restrictions file can create loopholes. To test if your “uploads” directory is really protected, create a PHP file with some content (example: <?php phpinfo(); ?>), upload it to “uploads” directory (or one of its sub-directories), then try to access (execute) it from your browser.
Resources Resources
Reference Reference
- nginx + php-fpm + PHP APC + WordPress multisite (subdirectory) + WP Super Cache (Thanks bigsite)
- Notes on removing ‘index.php’ from Permalinks (Can be done using Nginx Helper Plugin)
External Links External Links
Scripts & Tools Scripts & Tools
Wordpress Nginx Cache
- For WordPress Nginx scripted installation CentminMod can be used for CentOS.