Most of the sites that I created are based on WordPress. WordPress is great platform for your sites if you take a little care for it. different kind of abusive behavior on Wordpress systems is very common. Weak points are in most cases plugins, themes and outdated code in general. Many times people think, that security of their websites is all about hosting provider, firewalls… It’s true to some point. But one of the most fundamental steps to better WordPress security is up to the end-user. Take care of your site, update it regularly, use only good plugins and themes… It’s so important that you take care for regular updates and fixes. Also, try to use as least plugins as possible. If you are using only one theme, delete the ones that you don’t use. If you’ll use theme downloaded from internet, only use themes from good providers.
NGINX in combination with good configuration and cache system can make your website lightning fast and super responsive. Memcached, Redis, Opcache are also great for optimizing your site. You definitely want to check into them too. W3 Total Cache plugin is great and easy to configure. More about this another time.
So here is NGINX configuration. I’ll break it down. You can also download configuration from here.
First, define some basic settings like your domain name, document root path, error log … It’s very good practice to redirect 404 errors on static pages and not to load whole website to show error to end-user. In case of brute forcing, your server will probably die.
server { listen 80; server_name mydomain.com www.mydomain.com; root /path/to/document/root; index index.php index.html; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; error_page 404 /404.html; location /404.html { internal; }
Maybe you don’t want that other sites besides yours, are able to use your pictures on their site with your URL link. Here is how to disable hotlinking. You can whitelist other sites that can link your pictures in valid_referers. This is of corse optional and it’s up to you if you want this. It can cause problems if you share your blog posts on social networks as cover photos won’t be shown.
location ~ .(gif|png|jpe?g)$ { valid_referers *.mydomain.com; if ($invalid_referer) { return 403; } }
It’s very important that you disable users from executeing scripts from your uploads directory. This is very common way that hackers are using to executing their scripts from your site.
location ~* /(?:uploads|files)/.*\.(html|htm|shtml|php|js|swf|py|jsp|asp|sh|cgi)$ { deny all; }
Deny access to all hidden files that may be in your document root.
location ~ /\. { deny all; }
Allow only GET, POST and HEAD.
if ($request_method !~ ^(GET|POST|HEAD)$ ) { return 444; }
Includes are in many cases weak point of your WordPress installations. You don’t want that users are able to executing scripts from there.
location ~* wp-admin/includes { deny all; } location ~* wp-includes/theme-compat/ { deny all; } location ~* wp-includes/js/tinymce/langs/.*.php { deny all; } location /wp-includes/ { internal; }
You must disable execution of scripts other than PHP from your document root
location ~* .(pl|cgi|py|sh|lua|asp)$ { return 444; }
Disable access to your configuration files and other files that you don’t want to users are able to see. It’s important that users aren’t able to see your Wordpress version. nginx.conf in my case, is file generated from W3 Total Cache – configuration for nginx.
location ~* /(wp-config.php|readme.html|license.txt|nginx.conf) { deny all; }
It’s very good practice to redirect your administration to secure HTTPS. This will redirect your wp-admin or wp-login to https. In this case, you also want to add this to your wp-config.php: define(‘FORCE_SSL_ADMIN’, true);
location ~ /wp-(?:admin|login) { return 301 https://$host$request_uri; }
Allow pretty links (permalinks).
location / { try_files $uri $uri/ /index.php?$args; }
Prevent brute force attacks on your Wordpress administration. Brute force attacks on wp-login.php are very common.
location = /wp-login.php { limit_req zone=one burst=1 nodelay; include fastcgi_params; fastcgi_pass 127.0.0.1:9000; }
At the end, pass all dynamic files to PHP-FPM.
location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi_params; } }
This should do. Remember, take care for your site and you probably won’t have problems. Also, If you don’t need xmlrpc.php, disable it as it is very common target of brute force attacks also. I’m using Wordpress application on my iPhone also, so I need xmlrpc.php to work. If you don’t need it, you can disable it like so:
location /xmlrpc.php { deny all; }