WordPress NGINX configuration

I’ve been installing some wordpress sites in my new VPS running with NGINX.

Install wordpress with Nginx is not as complicated as it might seem but you have to do some configurations to increase security and to make it work with cache plugins.

As cache plugin I’ve chosen W3 total cache because the “Page Cache”, “disk:enhanced” method allows to serve static html pages of my site and it includes some other performance improvements.

I’m not going to cover all the process of installing and configuring NGINX. Here you can find some tutorials if you’re looking for that.

First of all you have to include your domain/server configuration in “/etc/nginx/sites-available”. Create a new file with this content and adapt it with your domain / routes:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
server {
    listen   80; ## listen for ipv4
    listen   [::]:80; ## listen for ipv6
    server_name domain.com;
    access_log /var/log/nginx/domain.com.access.log;
    error_log  /var/log/nginx/domain.com.error.log;
 
    root /folder/with/wordpress/installation/;
    
    # Include wordpress config file
    include sites-available/wordpress.conf;
}

As I have various wordpress installations in my server I’m going to separate the wordpress configuration in another file and use it in my different server configurations. I’ve create a new file called “wordpress.conf” in “/etc/nginx/sites-available” (file is commented to explain the different options)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
index index.php index.html;
 
set $cache_uri $request_uri;
    
# POST requests and urls with a query string should always go to PHP
if ($request_method = POST) {
    set $cache_uri 'null cache';
}   
if ($query_string != "") {
    set $cache_uri 'null cache';
}   
# Don't use the cache for logged in users or recent commenters
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in") {
    set $cache_uri 'null cache';
}
 
# Use cached or actual file if they exists, otherwise pass request to WordPress
location / {
    rewrite ^([^.]*[^/])$ $1/ permanent;
    try_files /wp-content/cache/page_enhanced/${host}${cache_uri}_index.html $uri $uri/ /index.php?$args;
}
 
location ~ ^/wp-content/cache/minify/[^/]+/(.*)$ {
   try_files $uri /wp-content/plugins/w3-total-cache/pub/minify.php?file=$1;
}    
 
#    Show "Not Found" 404 errors in place of "Forbidden" 403 errors, because
#    forbidden errors allow attackers potential insight into your server's
#    layout and contents
  error_page 403 =404;
 
#    Prevent access to any files starting with a dot, like .htaccess
#    or text editor temp files
  location ~ /\. { access_log off; log_not_found off; deny all; }
 
#    Prevent access to any files starting with a $ (usually temp files)
  location ~ ~$ { access_log off; log_not_found off; deny all; }
 
#    Do not log access to robots.txt, to keep the logs cleaner
  location = /robots.txt { access_log off; log_not_found off; }
 
#    Do not log access to the favicon, to keep the logs cleaner
  location = /favicon.ico { access_log off; log_not_found off; }
 
#    Keep images, CSS and other static files around in browser cache for
#    as long as possible, to cut down on server load
location ~* .(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
    expires max; log_not_found off; access_log off;
}
 
#    Common deny or internal locations, to help prevent access to areas of
#    the site that should not be public
  location ~* wp-admin/includes { deny all; }
  location ~* wp-includes/theme-compat/ { deny all; }
  location ~* wp-includes/js/tinymce/langs/.*\.php { deny all; }
  location /wp-content/ { internal; }
  location /wp-includes/ { internal; }
#    Protects the wp-config.php|readme.html|license.txt files from being 
#    accessed (uncomment after wordpress installation)
#  location ~ /(\.|wp-config.php|readme.html|license.txt) { deny all; }
 
#    Prevent any potentially-executable files in the uploads directory from
#    being executed by forcing their MIME type to text/plain
  location ~* ^/wp-content/uploads/.*.(html|htm|shtml|php)$ {
      types { }
      default_type text/plain;
  }
 
#    Add trailing slash to */wp-admin requests so the admin interface
#    works correctly
  rewrite /wp-admin$ $scheme://$host$uri/ permanent;
 
location ~ \.php$ {
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include        fastcgi_params; 
}

Now, you have to make a symbolic link of the first file that you have created into “/etc/nginx/sites-enabled” and restart nginx.

After that you can install wordpress normally. Once installed, you want to uncomment the line 59 of the “wordpress.conf” file ( location ~ /(.|wp-config.php|readme.html|license.txt) { deny all; } ) to disallow the access to the config.php file, the readme and the license.

For the W3 Total Cache plugin, you can enable the page Cache as “disk:enhanced” to serve the cached pages of your site. You can also enable minify or any other option (Object and Database Cache, CDN … etc). “Browser cache” is not really necessary because NGINX is going to take care of it.

And that’s all 🙂 Any comment or improvements are more than welcome.

Sources:

https://rtcamp.com/wordpress-nginx/tutorials/

http://blog.bigdinosaur.org/wordpress-on-nginx/