Background
Traditionally, most hosting sites have been using Apache bundled with PHP as their web server of choice. However, during the last few years many have migrated from Apache to Nginx due to performance benefits and increased flexibility.
Default settings
Nginx comes pre-configured to use with WordPress in the Seravo setup. There is no need to peruse any guides online on how to set up Nginx with WordPress.
Our default Nginx configuration includes:
Strong HTTPS settings (see example)
A Let’s Encrypt certificate for your public domains
HTTP cache with stale cache configured
Automatic expiration headers for static content
User configurable API
gzip
And lots more…
Configuration
In most generic Apache hosting platforms, you have the ability to use .htaccess files to add custom rules to your web server. There are multiple reasons why this is not optimal, one being the inherently slower execution time for all page loads on the site.
Instead, we give our users access to their nginx configuration through a directory that contains the .conf files which will be read by Nginx on startup. These configuration files can be found in /data/wordpress/nginx/*.conf.
Note: Under the hood, your custom Nginx configuration is included like this:
server {
listen 80 default_server;
server_name your-site.com;
...
include /data/wordpress/nginx/*.conf;
...
}
How to create your own rules
The file /data/wordpress/nginx/examples.conf includes a few examples for you to start with, all disabled by comments. We recommend that you do not edit this file directly. Leave it as a reference instead and create your own custom.conf file from scratch.
cd /data/wordpress/nginx
nano custom.conf
To get started with your configuration you can copy stuff from examples.conf. Remove the comments from the beginning of the line and edit the rules to match the specific needs of your site.
Restarting Nginx
After you’ve made changes to your nginx configuration, please reload the configuration by running:
wp-restart-nginx
If there should be any errors wp-restart-nginx will warn you about them and refuse to restart before the issue is fixed.
Examples
Redirects
Please see our separate documentation page on Redirects. In most cases it is recommended to do the redirection and HTTP request rewrite logic in WordPress/PHP, which is much more flexible than Nginx. There are no downsides to doing redirects in WordPress/PHP as it is equally fast as soon as the first redirect has been cached.
Forcing HTTPS
To force all your users to connect via https, you may redirect them to the https side with a Nginx configuration.
Note: There are many built-in methods in WordPress to enforce HTTPS and the Seravo Plugin also enforces both https and a canonical domain when it can detect that those are available, so most of the time one should not use the Nginx configuration below.
The preferred method in Nginx to force HTTPS is with a custom variable.
Force redirect http -> https
set $force_https 1;
Serve two different sites from the same domain
Sometimes it makes sense to have two separate sites served from the same domain, as it will contribute to a better user experience and improve the search engine ranking for the content of the sites, when compared to having the site split to separate domains or subdomains. For example, the majority of the site example.com could be hosted on WordPress, but the section example.com/store might be on Magento.
This can be achieved using Nginx proxying. For example, create a file called /data/wordpress/nginx/store-proxy.conf with the contents:
location /store/ {
proxy_ssl_server_name on;
proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
proxy_pass https://store.example.com/;
}
Protected/authenticated downloads
The path /wp-content/uploads/woocommerce_uploads/ is pre-configured by Seravo to be protected and accessible only when authentication is done in WooCommerce/WordPress/PHP while the download itself is handled by Nginx via the X-Sendfile header instructions.
One may place any file in that path and it the server will not allow a direct download of it. It can be accessed only if the PHP code emits a special X-Accel-Redirect header with the path of a file in that location.
This is the correct way to implement such a feature, since the PHP worker will not be reserved for the entire download but can continue to serve other PHP requests while the download itself has been offloaded to Nginx to handle.
To make a similar protected folder in a custom location, add the following to e.g. /data/wordpress/nginx/protected-downloads.conf:
location /protected-files {
internal;
alias /data/wordpress/protected-files/;
}
In PHP emit the headers as follows:
// Do authentication etc first
if ( current_user_can( 'download_special_files' ) ) {
// Emit header to Nginx which will send the file to requester
header('X-Accel-Redirect: //protected-files/confidential.pdf');
} else {
echo 'Access denied.';
die();
}
Automatically expiring secure download links
Note: Do not use the secure link feature with WooCommerce. Use the built-in digital download features of WooCommerce instead, which works out-of-the-box at Seravo.
The Nginx Secure Link module can be used to create links to downloadable items (for example a PDF file) that are valid only for a short time.
Example Nginx configuration, e.g. /data/wordpress/nginx/securelink.conf:
# Make folder inaccessible publicly
location /my-restricted-files/ {
internal;
alias /data/wordpress/my-restricted-files/;
}
# Define secure link
location ~ /my-restricted-files/(.*) {
# Define values used in generating secure links
secure_link $arg_md5, $arg_expires;
# Define link form. Replace ASDF1234 with an unique secret
secure_link_md5 "$secure_link_expires$uri ASDF1234";
if ($secure_link = "") {
return 403;
}
if ($secure_link = "0") {
return 410;
}
}
To generate links in PHP use something like:
function securelink($path) {
$secret = 'ASDF1234'; // the same secret as in Nginx config
$expires = time() + 86400; // 24h in seconds
$url = md5sum("$expires/my-restricted-files/example.pdf $SECRET")
}