Nginx Server Block For WordPress (SSL Version)

   |  26 Jul, 2015  #
sudo nano /etc/nginx/sites-available/default
## this block redirects all HTTP/HTTPS www traffic to non-www version
server {
    server_name            www.example.com;
    listen                 *:80;
    listen                 [::]:80 ipv6only=on;
    listen                 *:443 ssl;
    listen                 [::]:443 ssl ipv6only=on;
    ssl_certificate        /etc/ssl/nginx.crt;
    ssl_certificate_key    /etc/ssl/nginx.key;
    ## enable below to activate CloudFlare Authenticated Origin Pulls
    ## copy cloudflare.crt from https://blog.cloudflare.com/protecting-the-origin-with-tls-authenticated-origin-pulls/
    # ssl_client_certificate /etc/ssl/cloudflare.crt;
    # ssl_verify_client on;
    return 301 https://example.com$request_uri;
}

## this block redirects all HTTP non-www to HTTPS non-www version
server {
    server_name            example.com;
    listen                 *:80;
    listen                 [::]:80;
    return 301 https://example.com$request_uri;
}

## this block is the default configuration for the live website
server {
    server_name            example.com;
    listen                 443 ssl default_server;
    listen                 [::]:443 ssl;
    ssl_certificate        /etc/ssl/nginx.crt;
    ssl_certificate_key    /etc/ssl/nginx.key;
    ## enable below to activate CloudFlare Authenticated Origin Pulls
    ## copy cloudflare.crt from https://blog.cloudflare.com/protecting-the-origin-with-tls-authenticated-origin-pulls/
    # ssl_client_certificate /etc/ssl/cloudflare.crt;
    # ssl_verify_client on;
    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)(/.+)$;
        ## if using PHP7
        fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        ## if using PHP5
        # fastcgi_pass unix:/var/run/php5-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)(/.+)$;
        ## if using PHP7
        fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        ## if using PHP5
        # 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;
  }
}

For convenience purposes, below is the code for cloudflare.crt:

-----BEGIN CERTIFICATE-----
MIIGBjCCA/CgAwIBAgIIV5G6lVbCLmEwCwYJKoZIhvcNAQENMIGQMQswCQYDVQQG
EwJVUzEZMBcGA1UEChMQQ2xvdWRGbGFyZSwgSW5jLjEUMBIGA1UECxMLT3JpZ2lu
IFB1bGwxFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xEzARBgNVBAgTCkNhbGlmb3Ju
aWExIzAhBgNVBAMTGm9yaWdpbi1wdWxsLmNsb3VkZmxhcmUubmV0MB4XDTE1MDEx
MzAyNDc1M1oXDTIwMDExMjAyNTI1M1owgZAxCzAJBgNVBAYTAlVTMRkwFwYDVQQK
ExBDbG91ZEZsYXJlLCBJbmMuMRQwEgYDVQQLEwtPcmlnaW4gUHVsbDEWMBQGA1UE
BxMNU2FuIEZyYW5jaXNjbzETMBEGA1UECBMKQ2FsaWZvcm5pYTEjMCEGA1UEAxMa
b3JpZ2luLXB1bGwuY2xvdWRmbGFyZS5uZXQwggIiMA0GCSqGSIb3DQEBAQUAA4IC
DwAwggIKAoICAQDdsts6I2H5dGyn4adACQRXlfo0KmwsN7B5rxD8C5qgy6spyONr
WV0ecvdeGQfWa8Gy/yuTuOnsXfy7oyZ1dm93c3Mea7YkM7KNMc5Y6m520E9tHooc
f1qxeDpGSsnWc7HWibFgD7qZQx+T+yfNqt63vPI0HYBOYao6hWd3JQhu5caAcIS2
ms5tzSSZVH83ZPe6Lkb5xRgLl3eXEFcfI2DjnlOtLFqpjHuEB3Tr6agfdWyaGEEi
lRY1IB3k6TfLTaSiX2/SyJ96bp92wvTSjR7USjDV9ypf7AD6u6vwJZ3bwNisNw5L
ptph0FBnc1R6nDoHmvQRoyytoe0rl/d801i9Nru/fXa+l5K2nf1koR3IX440Z2i9
+Z4iVA69NmCbT4MVjm7K3zlOtwfI7i1KYVv+ATo4ycgBuZfY9f/2lBhIv7BHuZal
b9D+/EK8aMUfjDF4icEGm+RQfExv2nOpkR4BfQppF/dLmkYfjgtO1403X0ihkT6T
PYQdmYS6Jf53/KpqC3aA+R7zg2birtvprinlR14MNvwOsDOzsK4p8WYsgZOR4Qr2
gAx+z2aVOs/87+TVOR0r14irQsxbg7uP2X4t+EXx13glHxwG+CnzUVycDLMVGvuG
aUgF9hukZxlOZnrl6VOf1fg0Caf3uvV8smOkVw6DMsGhBZSJVwao0UQNqQIDAQAB
o2YwZDAOBgNVHQ8BAf8EBAMCAAYwEgYDVR0TAQH/BAgwBgEB/wIBAjAdBgNVHQ4E
FgQUQ1lLK2mLgOERM2pXzVc42p59xeswHwYDVR0jBBgwFoAUQ1lLK2mLgOERM2pX
zVc42p59xeswCwYJKoZIhvcNAQENA4ICAQDKDQM1qPRVP/4Gltz0D6OU6xezFBKr
LWtDoA1qW2F7pkiYawCP9MrDPDJsHy7dx+xw3bBZxOsK5PA/T7p1dqpEl6i8F692
g//EuYOifLYw3ySPe3LRNhvPl/1f6Sn862VhPvLa8aQAAwR9e/CZvlY3fj+6G5ik
3it7fikmKUsVnugNOkjmwI3hZqXfJNc7AtHDFw0mEOV0dSeAPTo95N9cxBbm9PKv
qAEmTEXp2trQ/RjJ/AomJyfA1BQjsD0j++DI3a9/BbDwWmr1lJciKxiNKaa0BRLB
dKMrYQD+PkPNCgEuojT+paLKRrMyFUzHSG1doYm46NE9/WARTh3sFUp1B7HZSBqA
kHleoB/vQ/mDuW9C3/8Jk2uRUdZxR+LoNZItuOjU8oTy6zpN1+GgSj7bHjiy9rfA
F+ehdrz+IOh80WIiqs763PGoaYUyzxLvVowLWNoxVVoc9G+PqFKqD988XlipHVB6
Bz+1CD4D/bWrs3cC9+kk/jFmrrAymZlkFX8tDb5aXASSLJjUjcptci9SKqtI2h0J
wUGkD7+bQAr+7vr8/R+CBmNMe7csE8NeEX6lVMF7Dh0a1YKQa6hUN18bBuYgTMuT
QzMmZpRpIBB321ZBlcnlxiTJvWxvbCPHKHj20VwwAz7LONF59s84ZsOqfoBv8gKM
s0s5dsq5zpLeaw==
-----END CERTIFICATE-----

The above configuration is as simple as it gets. However, for some high traffic websites or high value web properties, the above code will not be good enough. Why? Because a strong number of their visitors are using outdated web browsers and will not be able to access their website unless the code is adjusted. Enter the best tool on the web for calculating the variable SSL rules for your server: Mozilla's very nifty SSL Configuration Generator.

server {
    listen 443 ssl spdy default_server;
    listen [::]:443 ssl spdy ipv6only=on;
    ssl_certificate /etc/ssl/nginx.crt;
    ssl_certificate_key /etc/ssl/nginx.key;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;

    # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
    ssl_dhparam /path/to/dhparam.pem;

    # intermediate configuration. tweak to your needs.
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
    ssl_prefer_server_ciphers on;

    # HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
    add_header Strict-Transport-Security max-age=15768000;

    # OCSP Stapling ---
    # fetch OCSP records from URL in ssl_certificate and cache them
    ssl_stapling on;
    ssl_stapling_verify on;

    ## verify chain of trust of OCSP response using Root CA and Intermediate certs
    ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates;

    resolver ;
 
    ....
}

Of course, if that still doesn't satisfy your inner-nerd, maybe this documentation on TLS will do the trick. You may finish up your installation by testing your SSL using third party tools like this one from SSL Labs.

sudo service nginx restart

Photo Credit:

Share This Article:

No comments yet on "Nginx Server Block For WordPress (SSL Version)":

    Leave a Reply

    Your email address will not be published.*