Nginx Wordpress Configuration
Discuss Wordpress and Centmin Mod Nginx on the forums here.
If you prefer using Memcached server for caching instead of fastcgi caching, check out new WP-FFPC Plugin guide.
Guide last revision: Friday August 19th, 2016 (previous update Sunday June 7th, 2015)
- Basic Nginx Wordpress configuration
- Advanced Nginx Wordpress configuration + fastcgi_cache + Nginx Helper plugin
- Advanced Nginx Wordpress configuration + fastcgi_cache + ngx_pagespeed
Setting up MySQL database
Enable InnoDB MySQL Engine and Table support by ensuring your MySQL config settings for /etc/my.cnf have the following InnoDB related settings set. If not set in /etc/my.cnf change them to the following and restart MySQL server:
innodb=ON default-storage-engine = InnoDB
On a fresh Centmin Mod install, you may also want to enable server wide MySQL global UTF-8 support. Enabling this will apply to every MySQL database and tables you create on your MySQL server instance. To change defaults respectively for character set and collation to utf8 and utf8_general_ci, you need to add under [mysqld] group in /etc/my.cnf the following line character-set-server=utf8:
[mysqld] character-set-server=utf8
Note: Only MySQL databases and tables created after this change will by default be created as utf8 character set and collations. Any databases before this change, will still be latin1.
Restart MySQL server:
service mysql restart
Or restart with Centmin Mod command shortcut:
mysqlrestart
Basic Nginx Wordpress configuration: [top]
1. If you want to enable Wordpress Permalinks, you'll need to edit your site's Vhost configuration file and add the following and restart Nginx web server:
location /wordpress { try_files $uri $uri/ /wordpress/index.php?q=$request_uri; }
Where /wordpress is where you installed Wordpress i.e. yourdomain.com/wordpress
2. Create a file named wpsecure.conf at /usr/local/nginx/conf/wpsecure.conf and add following lines:
# Deny access to any files with a .php extension in the uploads directory # Works in sub-directory installs and also in multisite network location ~* /(?:uploads|files)/.*\.php$ { deny all; } # Make sure files with the following extensions do not get loaded by nginx because nginx would display the source code, and these files can contain PASSWORDS! location ~* \.(engine|inc|info|install|make|module|profile|test|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)$|^(\..*|Entries.*|Repository|Root|Tag|Template)$|\.php_ { return 444; } #nocgi location ~* \.(pl|cgi|py|sh|lua)\$ { return 444; } #disallow location ~* (roundcube|webdav|smtp|http\:|soap|w00tw00t) { return 444; } location ~ /(\.|wp-config\.php|readme\.html|license\.txt) { deny all; }
3. Create a file named wpnocache.conf at /usr/local/nginx/conf/wpnocache.conf and add following lines:
# Add trailing slash to */wp-admin requests. rewrite /wp-admin$ $scheme://$host$uri/ permanent;
4. Configure your Nginx vhost by adding these 2 lines and try_files for Wordpress permalinks.
include /usr/local/nginx/conf/wpsecure.conf; include /usr/local/nginx/conf/wpnocache.conf;
So Vhost configuration file changes from:
server { listen 80; server_name localhost; root html; # limit_conn limit_per_ip 16; # ssi on; location / { # Enables directory listings when index file not found # autoindex on; # Shows file listing times as local time # autoindex_localtime on; # Enable for vBulletin usage WITHOUT vbSEO installed # try_files $uri $uri/ /index.php; } include /usr/local/nginx/conf/staticfiles.conf; include /usr/local/nginx/conf/php.conf; include /usr/local/nginx/conf/drop.conf; #include /usr/local/nginx/conf/errorpage.conf; }
to:
server { listen 80; server_name localhost; root html; # limit_conn limit_per_ip 16; # ssi on; location / { # Enables directory listings when index file not found # autoindex on; # Shows file listing times as local time # autoindex_localtime on; # Enable for vBulletin usage WITHOUT vbSEO installed # try_files $uri $uri/ /index.php; } location /wordpress { include /usr/local/nginx/conf/wpsecure.conf; include /usr/local/nginx/conf/wpnocache.conf; try_files $uri $uri/ /index.php?q=$request_uri; } include /usr/local/nginx/conf/staticfiles.conf; include /usr/local/nginx/conf/php.conf; include /usr/local/nginx/conf/drop.conf; #include /usr/local/nginx/conf/errorpage.conf; }
Advanced Nginx Wordpress configuration + fastcgi_cache + Nginx Helper plugin [top]
Notes:
- The following configuration was tested on Centmin Mod v1.2.3+ and higher.
- Some Centmin Mod users on our Google+ Community site have reported a minor issue when logged into Wordpress Admin Dashboard, that previewing new post links result in 404 not found errors. A workaround for now is open preview link in new tab/window for browser and on preview link (404) error page, clear cookies and refresh page. That sometimes allows admin to still be logged in but see preview link. If anyone finds the permanent solution, please share on our Google+ Community site. Or try alternative cache method with Wordpress + WP-FFPC plugin memcached caching + ngx_pagespeed
This advanced Nginx Wordpress configuration was the result of compiling various sources of reading and then translating all of it to be compatible with Centmin Mod Nginx's vhost configuration format. Sources of info include:
- http://wiki.nginx.org/HttpFastcgiModule
- http://wiki.nginx.org/HttpUpstreamModule
- http://rtcamp.com/tutorials/nginx-wordpress-fastcgi_cache-with-conditional-purging/
- http://vpsboard.com/index.php?/topic/108-nginx-wordpress-with-caching/
1. Edit /usr/local/nginx/conf/nginx.conf to add fastcgi_cache settings. For Centmin Mod users, you can quickly access /usr/local/nginx/conf/nginx.conf via command line shortcut 'nginxconf' which will invoke nano text editor to open /usr/local/nginx/conf/nginx.conf.
Find starting http container
http {
and add below it the following line
http { include /usr/local/nginx/conf/wp_fastcgicache.conf;
Then create file named wp_fastcgicache.conf at include /usr/local/nginx/conf/wp_fastcgicache.conf and ensure /var/cache/nginx exists add following lines:
fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=WPCACHE:16m max_size=32m inactive=50m; fastcgi_cache_key "$scheme$request_method$host$request_uri"; fastcgi_cache_use_stale error timeout invalid_header http_500; log_format cache '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" nocache:$no_cache ' '$upstream_cache_status'; ### Map Mobile map $http_user_agent $is_mobile { default 0; ~*android|ip(hone|od)|windows\s+(?:ce|phone) 1; ~*symbian|sonyericsson|samsung|lg|blackberry 1; ~*mobile 1; }
2. Create a file named wpsecure.conf at /usr/local/nginx/conf/wpsecure.conf and add following lines:
# Deny access to any files with a .php extension in the uploads directory # Works in sub-directory installs and also in multisite network location ~* /(?:uploads|files)/.*\.php$ { deny all; } # Make sure files with the following extensions do not get loaded by nginx because nginx would display the source code, and these files can contain PASSWORDS! location ~* \.(engine|inc|info|install|make|module|profile|test|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)$|^(\..*|Entries.*|Repository|Root|Tag|Template)$|\.php_ { return 444; } #nocgi location ~* \.(pl|cgi|py|sh|lua)\$ { return 444; } #disallow location ~* (roundcube|webdav|smtp|http\:|soap|w00tw00t) { return 444; } location ~ /(\.|wp-config\.php|readme\.html|license\.txt) { deny all; }
3. Create a file named wpcache.conf at /usr/local/nginx/conf/wpcache.conf and add following lines:
If wordpress installed in subdirectory i.e. /wordpress, you meed to add /wordpress in front of /(memcache\.php
i.e.
if ($request_uri ~* "/wordpress/(memcache\.php
/usr/local/nginx/conf/wpcache.conf contents:
#fastcgi_cache start set $no_cache 0; # POST requests and urls with a query string should always go to PHP if ($request_method = POST) { set $no_cache 1; } if ($query_string != "") { set $no_cache 1; } # Don't cache uris containing the following segments # If wordpress installed in subdirectory i.e. /wordpress # meed tp add /wordpress in front of /(memcache\.php # i.e. if ($request_uri ~* "/wordpress/(memcache\.php if ($request_uri ~* "/\?add-to-cart=|cart/|my-account/|checkout/|shop/checkout/|store/checkout/|customer-dashboard/|addons/|(memcache\.php|apc\.php|wp-admin/.*|xmlrpc\.php|wp-(app|cron|login|register|mail)\.php|wp-.*\.php|feed/|index\.php|wp-comments-popup\.php|wp-links-opml\.php|wp-locations\.php|sitemap(_index)?\.xml|[a-z0-9_-]+-sitemap([0-9]+)?\.xml)") { set $no_cache 1; } # Don't use the cache for logged in users or recent commenters if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in|edd_items_in_cart|woocommerce_items_in_cart|wordpress-sec") { set $no_cache 1; } # Add trailing slash to */wp-admin requests. rewrite /wp-admin$ $scheme://$host$uri/ permanent; # Centmin Mod Nginx has nginx_cache_purge module # added http://centminmod.com/nginx.html location ~ /purge(/.*) { fastcgi_cache_purge WPCACHE "$scheme$request_method$host$1"; return 200; allow 127.0.0.1; deny all; }
4. Create a file named wpnocache.conf at /usr/local/nginx/conf/wpnocache.conf and add following lines:
# Add trailing slash to */wp-admin requests. rewrite /wp-admin$ $scheme://$host$uri/ permanent;
5. Create a duplicate copy of /usr/local/nginx/conf/php.conf file and name it /usr/local/nginx/conf/phpwpcache.conf
cp -a /usr/local/nginx/conf/php.conf /usr/local/nginx/conf/phpwpcache.conf
Add the following lines at bottom of /usr/local/nginx/conf/phpwpcache.conf just above the last ending curly brace }
Cache 200 and 302 status requests for 2 minutes, 301 redirects for 1 hour and any other requests for 2 minutes.
fastcgi_cache_bypass $no_cache $is_mobile; fastcgi_no_cache $no_cache $is_mobile; fastcgi_cache WPCACHE; fastcgi_cache_valid 200 302 2m; fastcgi_cache_valid 301 1h; fastcgi_cache_valid any 2m; fastcgi_cache_min_uses 1; add_header X-Cached $upstream_cache_status;
So the full file contents for /usr/local/nginx/conf/phpwpcache.conf looks like below:
location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass 127.0.0.1:9000; #fastcgi_pass unix:/tmp/php5-fpm.sock; fastcgi_index index.php; #fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_connect_timeout 60; fastcgi_send_timeout 180; fastcgi_read_timeout 180; fastcgi_buffer_size 256k; fastcgi_buffers 4 256k; fastcgi_busy_buffers_size 256k; fastcgi_temp_file_write_size 256k; fastcgi_intercept_errors on; # comment out PATH_TRANSLATED line if /usr/local/lib/php.ini sets following: # cgi.fix_pathinfo=0 # as of centminmod v1.2.3-eva2000.01 default is set to cgi.fix_pathinfo=1 fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param REQUEST_URI $request_uri; fastcgi_param DOCUMENT_URI $document_uri; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param GATEWAY_INTERFACE CGI/1.1; fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; fastcgi_param REMOTE_ADDR $remote_addr; fastcgi_param REMOTE_PORT $remote_port; fastcgi_param SERVER_ADDR $server_addr; fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name; # PHP only, required if PHP was built with --enable-force-cgi-redirect fastcgi_param REDIRECT_STATUS 200; fastcgi_cache_bypass $no_cache $is_mobile; fastcgi_no_cache $no_cache $is_mobile; fastcgi_cache WPCACHE; fastcgi_cache_valid 200 302 2m; fastcgi_cache_valid 301 1h; fastcgi_cache_valid any 2m; fastcgi_cache_min_uses 1; add_header X-Cached $upstream_cache_status; }
6. Now to put all the pieces together and edit your Centmin Mod Nginx vhost for your specific site. For this example Wordpress is installed at /wp.
The additional entries of note are:
access_log /var/log/nginx/access.cache.log cache;
Place these 3 lines in /wp location if wordpress is installed at /wp. This will ensure only wordpress at /wp uses fastcgi_cache and not other scripts located outside of /wp.
include /usr/local/nginx/conf/wpsecure.conf; include /usr/local/nginx/conf/wpcache.conf; include /usr/local/nginx/conf/phpwpcache.conf;
Otherwise if wordpress installed at root location /, use these 2 lines within root location / container
include /usr/local/nginx/conf/wpsecure.conf; include /usr/local/nginx/conf/wpcache.conf;
So it would like like the below example if wordpress installed at root / location.
location / { include /usr/local/nginx/conf/wpsecure.conf; include /usr/local/nginx/conf/wpcache.conf; # block common exploits, sql injections etc #include /usr/local/nginx/conf/block.conf; #Enables directory listings when index file not found #autoindex on; }
Change try_files line. If wordpress is installed at /wp change from:
location /wp { try_files $uri $uri/ /wp/index.php?q=$request_uri; }
to:
location /wp { try_files $uri $uri/ /wp/index.php?q=$args; }
If wordpress is installed at / change from:
location / { try_files $uri $uri/ /index.php?q=$request_uri; }
to:
location / { try_files $uri $uri/ /index.php?q=$args; }
If wordpress installed at root location /, you will need to comment out (with hash # in front the default php.conf and use phpwpcache.conf).
include /usr/local/nginx/conf/phpwpcache.conf; #include /usr/local/nginx/conf/php.conf;
Otherwise if wordpress installed at location /wp, leave the default php.conf in place below root / location
include /usr/local/nginx/conf/staticfiles.conf; include /usr/local/nginx/conf/php.conf; #include /usr/local/nginx/conf/phpstatus.conf; include /usr/local/nginx/conf/drop.conf; #include /usr/local/nginx/conf/errorpage.conf;
Using the default main server Nginx vhost at /usr/local/nginx/conf/conf.d/virtual.conf as an example, edit it to the below format for wordpress installed at /wp.
server { # listen 80; listen 80 default_server; server_name localhost; root html; access_log /var/log/nginx/localhost.access.log main buffer=32k; error_log /var/log/nginx/localhost.error.log error; access_log /var/log/nginx/access.cache.log cache; # ngx_pagespeed & ngx_pagespeed handler include /usr/local/nginx/conf/pagespeed.conf; include /usr/local/nginx/conf/pagespeedhandler.conf; # limit_conn limit_per_ip 16; # ssi on; location / { # block common exploits, sql injections etc #include /usr/local/nginx/conf/block.conf; #Enables directory listings when index file not found #autoindex on; } location /wp { include /usr/local/nginx/conf/wpsecure.conf; include /usr/local/nginx/conf/wpcache.conf; include /usr/local/nginx/conf/phpwpcache.conf; try_files $uri $uri/ /wp/index.php?q=$request_uri; } # example nginx-http-concat # /csstest/??one.css,two.css #location /csstest { #concat on; #concat_max_files 20; #} include /usr/local/nginx/conf/staticfiles.conf; include /usr/local/nginx/conf/php.conf; #include /usr/local/nginx/conf/phpstatus.conf; include /usr/local/nginx/conf/drop.conf; #include /usr/local/nginx/conf/errorpage.conf; }
Note, some common security settings are already contained in /usr/local/nginx/conf/drop.conf
location = /robots.txt { access_log off; log_not_found off; } location = /favicon.ico { access_log off; log_not_found off; expires 30d; } location ~ /\. { access_log off; log_not_found off; deny all; } location ~ ~$ { access_log off; log_not_found off; deny all; } location ~ /\.git { access_log off; log_not_found off; deny all; }
7. Save your Nginx vhost conf file and then restart Nginx server
service nginx restart
or via command line shortcut
ngxrestart
8. Install Nginx Helper Wordpress Plugin
Install Nginx Helper Wordpress plugin. The plugin has a hard coded path to fastcgi_cache_path which is /var/run/nginx-cache which differs from configuration defined /var/cache/nginx outlined above. (see first FAQ question at https://github.com/rtCamp/nginx-helper).
You need to change the hard coded path by adding a line in wp-config.php like below:
define( 'RT_WP_NGINX_HELPER_CACHE_PATH','/var/cache/nginx');
Advanced Nginx Wordpress configuration + fastcgi_cache + ngx_pagespeed [top]
Follow above Advanced Nginx Wordpress configuration guide and then enable Nginx ngx_pagespeed module as per instructions here.
Nginx ngx_pagespeed module pretty much makes any Wordpress cache plugin redundant (W3 Total Cache, WP Super Cache as ngx_pagespeed minifies all css and js and combines css and js and much more including caching. No more messing around with Wordpress Caching plugins !
To illustrate this, I installed the Responsive Wordpress theme and ran Firefox Firebug to show the differences. Notice number of requests are reduced as is page load times (~24.5% faster page load times and ~27.5% faster onload times).
First, with Nginx ngx_pagespeed module disabled.
Chrome PageSpeed Score = 94
Second, with Nginx ngx_pagespeed module enabled with default Centmin Mod preset settings. Notice number of requests on page were reduced from 8 to 7 requests.
Chrome PageSpeed Score = 95
Third, with Nginx ngx_pagespeed module enabled with default Centmin Mod preset settings + enabling combine_javascript filter. Notice number of requests on the page was further reduced from 7 to just 6 requests. The benefits increase as your serve more css and js files.
Chrome PageSpeed Score = 98