Nginx Server Block For WordPress Websites
Up until a few years ago, installing WordPress on an Nginx server still tended to be a little bit janky. In the early days, many websites were forced to deal with ugly permalink schemes that included the “/index.php/” root in every single link. Even after that hurdle was eliminated, other issues existed such as poor compatibility of several WordPress plugins with Nginx, rendering many of them useless. In other cases, special rules needed to be written to the Nginx server block to make a plugin or script work properly, which left many WordPress webmasters at a complete loss of what to do.
While many of these rumors still abound, the truth is that Nginx now works perfectly with WordPress with very little configuration required (if any at all) after initial server setup has been completed. Even popular WordPress plugins like Yoast SEO erroneously claim that special re-write rules are (still) required for their plugin to work properly, which is simply not true (and hasn’t been true for at least a few years already). Moreover, even WordPress.com and other enterprise-level websites owned by Automattic (the company behind WordPress) are powered by Nginx servers and have been for years!
Unlike Apache’s “virtual hosts” or having to upload messy .htaccess files all over your server, Nginx is renowned for its powerful simplicity. Pretty much all required server security and rewrite rules can take place directly in the server block located under /etc/nginx/sites-available/default
and can overwrite default rules in /etc/nginx/nginx.conf
The below Nginx server block code has been specifically optimized for WordPress speed and security, although many of the rules would apply to other CMS systems too. In general, this is the setup that we use for all LittleBizzy clients.
Note: This server block is meant to be used in conjunction with our recommended Nginx configuration. Specifically, the section on rate limiting will cause errors unless rate limiting is also enabled in your nginx.conf
file too.
First, you will need to edit the default “site available” on your Nginx server:
sudo nano /etc/nginx/sites-available/default
Copy and paste entire code below, making sure to change the domain name as appropriate:
## this block redirects all HTTP non-www to HTTP www version server { server_name example.com; listen *:80; listen [::]:80 ipv6only=on; return 301 http://www.example.com$request_uri; } ## this block is the default configuration for the live website server { server_name www.example.com; listen *:80 default_server; listen [::]:80; root /home/example/www; index index.php index.html index.htm; autoindex off; ## improve public caching (no need for Last Modified too, and eTag is enabled by default in new Nginx versions) expires 30d; add_header Cache-Control "public"; add_header Pragma public; if_modified_since before; ## first try files, then directories, otherwise query index location / { ## force trailing slashes (don't enable for bbPress/BuddyPress) # rewrite ^([^.]*[^/])$ $1/ permanent; try_files $uri $uri/ /index.php?$args; } ## make sure PHP loads via FCGI for better performance location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php5-fpm.sock; ## if using PHP7 # fastcgi_pass unix:/run/php/php7.0-fpm.sock; fastcgi_index index.php; ## older nginx versions use: include fastcgi_params include fastcgi.conf; ## below line should not be needed # include snippets/fastcgi-php.conf; } location = /wp-login.php { ## prevent brute force attacks (must enable in nginx.conf) limit_req zone=one burst=1 nodelay; ## re-include basic FCGI settings for PHP files fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_index index.php; ## older nginx versions use: include fastcgi_params include fastcgi.conf; } ## block any attempted access to dotfiles location ~ /\. { deny all; log_not_found off; access_log off; } ## no need to log any access requests for favicon location = /favicon.ico { ## 204 > 404 if favicon not found try_files $uri =204; log_not_found off; access_log off; } ## don't log robots file and allow any requests location = /robots.txt { allow all; log_not_found off; access_log off; } ## block any attempted XMLRPC attacks location = /xmlrpc.php { deny all; } ## comment this until WP is properly setup (blocks access) location = /wp-config.php { deny all; } ## block access to hackers checking WP version location ~* (licence|readme|license)\.(html|txt) { deny all; } ## deny access to PHP files in various directories location ~* /(?:uploads|files|wp-content|wp-includes)/.*\.php$ { deny all; } ## avoid any font problems in Firefox and IE location ~ \.(eot|ttf|ttc|otf|woff|woff2|svg|css|js)$ { add_header Access-Control-Allow-Origin "*"; } ## set maximum expiry times for static files location ~* \.(js|css|png|jpg|jpeg|gif|ico|mp4|svg|svgz|ogg|ogv|webm|htc)$ { log_not_found off; access_log off; } ## define error pages in the web directory error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } ## flag to tell Comet Cache to shhh location ~* \.php$ { fastcgi_param WP_NGINX_CONFIG done; } }
Before you restart the Nginx service be sure to test it:
sudo nginx -t
Then go ahead and restart it:
sudo service nginx restart
Looks very interesting, although nginx failed to start with this code block at least in my case.
What I miss about Apache is that in case of error, it tells you which line is causing problems. In this case I just get “Fail” after restarting nginx. Such a bummer.
Hi Mauricio, not sure if you are spamming or what, but anyway this Nginx block works like a charm on all of our client servers. Be sure you comment out the rate limiting section if you don’t enable the rate limiting that is used in our recommended
nginx.conf
tutorial here: https://www.littlebizzy.com/blog/nginx-configurationAs you can see, I’m new using nginx. My complaint was about knowing what went wrong in a particular case. In the other link I discovered the comman “sudo nginx -t”, which is precisely that. In my case (using Ubuntu 14.04), the problem was the fastcgi.conf file, which is actually fastcgi_params, as your configurations says.
Thank you so much.
MERGED: Thank you for your response. I’m sure I’m not spamming, I’m just trying to learn. Thank you for the link, I’ll start reading it.
Sorry for the confusion as some people make weird comments just to spam links! Yes that command is a perfect way to test Nginx configuration
sudo nginx -t
and will tell you if any problems with SSL or other settings. Cheers!Do you erase everything in the “/etc/nginx/sites-available/default” file and past this block, or do you just add this block to the bottom?
Yes that is correct, you must clear the file and replace with this block.