Secure Wordpress Nginx Configuration

From Bonus Bits
Jump to: navigation, search


Description

This article gives a secure Nginx with PHP-FPM 7.0 configuration example for a Wordpress server.


Example

In this example a load balancer terminates SSL/TLS traffic and sends on the backend Clear HTTP to the server. In order for the server to understand the traffic was secured and the load balancer is dealing with the encryption we look for a X Forward Protocol Header as an identification. So in the Wordpress configuration we have https://www.example.com and all the published URLs will include HTTPS. I believe that this will work fine even if only using HTTP due to the condition, but I have not tested it.

127.0.0.1:9000 is what PHP-FPM is default listening on. This is set in the /etc/php-fpm-7.0.d/www.conf file.

vim /etc/nginx/conf.d/wordpress.conf
server {
    listen 80;
    server_name www.example.com;
    root   /usr/share/nginx/html/wordpress;
    index index.php;

    # If you are running multiple websites on one system you may want to split off logging to its own files.
    #access_log /var/log/nginx/wordpress_access.log;
    #error_log /var/log/nginx/wordpressi_error.log;

    # Root Traffic Handler
    location / {
        # Recognize if HTTPS Terminate Prior to Nginx Getting Hands on it
        if ($http_x_forwarded_proto != 'https') {
                rewrite ^ https://$host$request_uri? permanent;
        }
        try_files $uri $uri/ @handler;
    }

    location @handler {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_param SCRIPT_FILENAME /var/www/html/wordpress/index.php;
        include /etc/nginx/fastcgi_params;
        fastcgi_param SCRIPT_NAME /index.php;
    }

    location ~ .php$ {
        try_files $uri @handler;
        fastcgi_pass    127.0.0.1:9000;
        fastcgi_index   index.php;
        fastcgi_param SCRIPT_FILENAME /var/www/html/wordpress$fastcgi_script_name;
        include fastcgi_params;
    }

    # Deny direct access to uploads directory
    location ~* /(?:uploads)/.*\.php$ {
        deny all;
    }

    #    Exclude all access from the cache directory
    #location ^~ /cache/ { deny all; }

    #    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 and CSS around in browser cache for as long as possible,
    #    to cut down on server load
    location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
        try_files $uri /index.php;
        expires max;
        log_not_found off;
    }

    #    Mark all of these directories as "internal", which means that they cannot
    #    be explicitly accessed by clients. However, the web server can still use
    #    and serve the files inside of them. This keeps people from poking around
    #    in the wiki's internals.
    location ^~ /bin/ { internal; }
    location ^~ /docs/ { internal; }
    location ^~ /extensions/ { internal; }
    location ^~ /includes/ { internal; }
    location ^~ /maintenance/ { internal; }
    #location ^~ /mw-config/ { internal; } #Uncomment after installation
    location ^~ /resources/ { internal; } # Breaks Default Logo (mv logo to images)
    location ^~ /serialized/ { internal; }
    location ^~ /tests/ { internal; }
    location ^~ /skins/ { internal; }
    location ^~ /vendor/ { internal; }

    #    Force potentially-malicious files in the /images directory to be served
    #    with a text/plain mime type, to prevent them from being executed by
    #    the PHP handler
    location ~* ^/images/.*.(html|htm|shtml|php)$ {
        types { }
        default_type text/plain;
    }

    #    Redirect all requests for unknown URLs out of images and back to the
    #    root index.php file
    location ^~ /images/ {
        try_files $uri /index.php;
    }
}


Related Articles


Sources