nginx setup for WordPress with WP Super Cache in Ubuntu 18.04
I think nginx is a good match for WordPress, even if it's not really “officially” supported. The instructions from here are borrowed/modified slightly from:
http://codex.wordpress.org/Nginx
I had to make a minor adjustment to make it work, and I also prefer that image accesses are logged. First of all, install nginx and php-fpm:
sudo apt-get install nginx php-fpm
Let's get everything set up. php-fpm's defaults on 18.04 should work. Just make sure it's listening on /run/php/php7.2-fpm.sock
(in /etc/php/7.2/fpm/pool.d/www.conf
) and cgi.fix_pathinfo
is defaulting to 1 (which the comments say is the case in /etc/php/7.2/fpm/php.ini
). Create the following files:
/etc/nginx/conf.d/autoindex.conf
:
# Don't allow directory listings. autoindex off;
/etc/nginx/conf.d/php.conf
:
# Upstream to abstract backend connection(s) for PHP. upstream php { # this should match value of "listen" directive in php-fpm pool server unix:/run/php/php7.2-fpm.sock; #server 127.0.0.1:9000; }
/etc/nginx/sites-available/wordpress
:
# Redirect everything to the main site. We use a separate server statement and NOT an if statement - see http://wiki.nginx.org/IfIsEvil #server { # server_name _; # rewrite ^ $scheme://mysite.com$request_uri redirect; #} server { server_name www.mydomain.com mydomain.com; root /var/wordpress; access_log /var/log/nginx/wordpress_access.log; error_log /var/log/nginx/wordpress_error.log; index index.php index.html index.htm; include global/restrictions.conf; # Additional rules go here. # Only include one of the files below. include global/wordpress.conf; # include global/wordpress-ms-subdir.conf; # include global/wordpress-ms-subdomain.conf; }
Create the directory /etc/nginx/global
and create the following files inside of it:
/etc/nginx/global/restrictions.conf
:
# Global restrictions configuration file. # Designed to be included in any server {} block. location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { allow all; log_not_found off; access_log off; } # Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac). # Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban) location ~ /. { deny all; } # Deny access to any files with a .php extension in the uploads directory # Works in sub-directory installs and also in multisite network # Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban) location ~* /(?:uploads|files)/.*.php$ { deny all; }
/etc/nginx/global/wordpress.conf
:
# WordPress single blog rules. # Designed to be included in any server {} block. # This order might seem weird - this is attempted to match last if rules below fail. # Commented out because the WP Super Cache rules work in its place and otherwise nginx fails to start with a duplicate location error. # http://wiki.nginx.org/HttpCoreModule #location / { # try_files $uri $uri/ /index.php?$args; #} # Add trailing slash to */wp-admin requests. rewrite /wp-admin$ $scheme://$host$uri/ permanent; # Directives to send expires headers and turn off 404 error logging. # Changed this to actually do log the errors; I like to see them. Also made the cache expire in 30 days instead of forever. location ~* ^.+.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ { expires 30d; } # Uncomment one of the lines below for the appropriate caching plugin (if used). include global/wordpress-wp-super-cache.conf; #include global/wordpress-w3-total-cache.conf; # Pass all .php files onto a php-fpm/php-fcgi server. location ~ [^/].php(/|$) { fastcgi_split_path_info ^(.+?.php)(/.*)$; if (!-f $document_root$fastcgi_script_name) { return 404; } # This is a robust solution for path info security issue and works with "cgi.fix_pathinfo = 1" in /etc/php.ini (default) include fastcgi_params; fastcgi_index index.php; # fastcgi_intercept_errors on; fastcgi_pass php; }
/etc/nginx/global/wordpress-wp-super-cache.conf
:
# WP Super Cache rules. # Designed to be included from a 'wordpress-ms-…' configuration file. 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 cache uris containing the following segments if ($request_uri ~* "(/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 $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'; } # START MOBILE # Mobile browsers section to server them non-cached version. COMMENTED by default as most modern wordpress themes including twenty-eleven are responsive. Uncomment config lines in this section if you want to use a plugin like WP-Touch # if ($http_x_wap_profile) { # set $cache_uri 'null cache'; #} #if ($http_profile) { # set $cache_uri 'null cache'; #} #if ($http_user_agent ~* (2.0 MMP|240×320|400×240|AvantGo|BlackBerry|Blazer|Cellphone|Danger|DoCoMo|Elaine/3.0|EudoraWeb|Googlebot-Mobile|hiptop|IEMobile|KYOCERA/WX310K|LG/U990|MIDP-2.|MMEF20|MOT-V|NetFront|Newt|Nintendo Wii|Nitro|Nokia|Opera Mini|Palm|PlayStation Portable|portalmmm|Proxinet|ProxiNet|SHARP-TQ-GX10|SHG-i900|Small|SonyEricsson|Symbian OS|SymbianOS|TS21i-10|UP.Browser|UP.Link|webOS|Windows CE|WinWAP|YahooSeeker/M1A1-R2D2|iPhone|iPod|Android|BlackBerry9530|LG-TU915 Obigo|LGE VX|webOS|Nokia5800)) { # set $cache_uri 'null cache'; #} #if ($http_user_agent ~* (w3c |w3c-|acs-|alav|alca|amoi|audi|avan|benq|bird|blac|blaz|brew|cell|cldc|cmd-|dang|doco|eric|hipt|htc_|inno|ipaq|ipod|jigs|kddi|keji|leno|lg-c|lg-d|lg-g|lge-|lg/u|maui|maxo|midp|mits|mmef|mobi|mot-|moto|mwbp|nec-|newt|noki|palm|pana|pant|phil|play|port|prox|qwap|sage|sams|sany|sch-|sec-|send|seri|sgh-|shar|sie-|siem|smal|smar|sony|sph-|symb|t-mo|teli|tim-|tosh|tsm-|upg1|upsi|vk-v|voda|wap-|wapa|wapi|wapp|wapr|webc|winw|winw|xda |xda-)) { # set $cache_uri 'null cache'; #} #END MOBILE # Use cached or actual file if they exists, otherwise pass request to WordPress location / { try_files /wp-content/cache/supercache/$http_host/$cache_uri/index.html $uri $uri/ /index.php?$args ; }
Now, remove the symlink to the “default” site and make a new one that points to the newly-created WordPress site:
rm /etc/nginx/sites-enabled/default
ln -s /etc/nginx/sites-available/wordpress /etc/nginx/sites-enabled/wordpress
Finally, restart nginx and everything should be gravy.
service nginx restart
Not too bad, huh? This is way cleaner than my previous method with lighttpd, and I love being able to use nginx instead of Apache.