Viewing security View all News

How To Achieve an A+ SSL Configuration on Nginx

Qualys SSL Labs has a wonderful tool to help evaluate your server’s SSL configuration. I recommend you take a moment to scan your site and see how you fare. Go do that now. I’ll wait. If you didn’t get a perfect score, you aren’t alone.

The default configurations for popular server-side software like OpenSSL often support cryptographically weak standards that can put users at risk. Even major corporations have room for improvement.

Keep your server secure

If you’re on a shared server or at the mercy of control panel software like cPanel or Plesk, unfortunately there isn’t anything you can do. But if you have root access and a little knowing of the command-line, this article will help you harden your configuration so you can get a perfect A+.

While the following examples are specific to Nginx, they should be able to help point any readers running Apache or Lighttpd servers in the right direction.

Obtaining a Certificate

First, let’s start with a quick refresher on how you go about getting a certificate in the first place. Make a directory outside your web root, and once in that directory, generate a private key and certificate signing request (CSR). Your key should be at least 2048 bytes. In this example we’ll generate one that is 4096 bytes. If you have an existing key and can’t remember how strong it is, you can type:

openssl rsa -in -text -noout | head -n 1

To generate a new key, use:

mkdir /var/www/
cd /var/www/
openssl req -new -newkey rsa:4096 -nodes -keyout -out

The openssl command will quiz you about your domain and organization. The Common Name (CN) needs to be the fully-qualified-domain-name for which you are purchasing the certificate. Remember, and are technically two different domains, so enter the CN exactly as visitors are expected to reach it. Some certificates, such as Comodo’s PositiveSSL, are magically valid for both www and non-www variants (aren’t they sweet?).

You should now find two files in your ssl directory: and That key is meant to be private, so take a moment to update its permissions. If 600 is too restrictive for your environment, 640 might do the trick.

chmod 0600

Now go buy a certificate. Namecheap offers decent Comodo certificates from as low as $9, or you could spend more money elsewhere. It doesn’t much matter. As part of the certificate activation process, you’ll be asked for the CSR you just created, so keep that handy. Different Certificate Authorities (CA) have different validation processes, so just follow whatever instructions you’re given.

Once your certificate has been issued, upload them to the directory containing your key and CSR. If you are issued two or more bundled certificates (which is a common practice), they must be stitched together into a single file for Nginx. The order is important, so double-check the CA’s documentation. For Comodo PositiveSSL certificates, run the following:

cat COMODORSADomainValidationSecureServerCA.crt COMODORSAAddTrustCA.crt AddTrustExternalCARoot.crt >

Nginx Set Up

By default, OpenSSL uses a weak 1024 byte key for Diffie Hellman key exchanges.  Let’s bump this up to 4096 by running the following command.  It can take a while to complete, so go make a sandwich:

openssl dhparam -out /etc/nginx/dhparams.pem 4096

Now let’s make Nginx’s SSL configuration a little more secure by adding the following code to the http{} block of your /etc/nginx/nginx.conf file:

http {

	# SSL Settings

	## force modern protocols and ciphers
	## and enable ssl cache for a small
	## performance boost

	ssl_prefer_server_ciphers On;
	ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
	ssl_session_cache shared:ssl_session_cache:10m;
	ssl_dhparam /etc/nginx/dhparams.pem;


Now that we have the general out of the way, let’s move onto site-specific configurations. Open the configuration file corresponding to your site, something like /etc/nginx/sites-enabled/

Let’s start by adding a server block to redirect to, and also force HTTPS connections for everything. If is your main domain, simply reverse the www and non-www in the following examples.

server {
	listen 80;
	listen [::]:80 ipv6only=on;


	rewrite ^(.*)$1 permanent;

Now in your main server block for the domain, add the following:

server {
	listen 443 ssl;
	listen [::]:443 ssl ipv6only=on;


	#point to the combined certificate and key we generated earlier.
	ssl_certificate /home/;
	ssl_certificate_key /home/;

	#enable HSTS (in supported browsers) to make sure all subsequent
	#user requests are done over HTTPS regardless of protocol typed.
	add_header Strict-Transport-Security "max-age=31536000";

	#redirect non-canonical domain over SSL.
	#this will only work if your SSL certificate also covers
	if ($host = '' ) {
		rewrite ^(.*)$$1 permanent;

If your server is not configured for IPv6, remove the second listen lines from the above examples. Speaking of IPv6, Nginx only wants to see a single ipv6only=on attribute per port across all your server blocks. If you have additional server blocks defined, simply omit that string from their definitions.

That’s it! Restart Nginx to apply the changes:

service nginx restart

Last Thoughts

You should now have pretty darn good SSL support! But the fun doesn’t end here!

New threats or vulnerabilities can pop up any time, to say nothing of the inevitable march of progress (advances in technology will eventually make your once great setup laughably inadequate).  Make sure you regularly apply any security patches made available to your distribution.  You should also periodically rerun the Qualys SSL Labs scan to see if any tweaks are needed to stay on top.

Posted By
Josh Stoik

BBG Tips: Keep WordPress Tidy

WordPress is kind of magical. It gives site operators the power to quickly and effortlessly extend functionality, tweak design, and preview and post new content.

However, this power of immediate evolution – a key feature that has made so many insightful blogs about cats sleeping in weird places possible – can, over time, lead to clutter, increased hardware costs, and even security vulnerabilities.

Organized Desk

Keeping WordPress tidy is as important as keeping your workspace clean.

Thankfully, a little bit of spring cleaning will go a long way. (Even if you don’t get around to it until the end of summer.) There are two areas to focus on:


First and foremost, conduct a quick census of the plugins installed on your site. If you notice any that aren’t actually being used, deactivate and delete them. All plugins contribute to the overall resource demands made of your server, so at best, unused plugins are needlessly slowing things down.

More importantly, plugins also add a lot of code to your site, code which may contain bugs or security weaknesses that a hacker would love to leverage against you.

Themes are another area that can grow quite cluttered over time. Even though inactive themes won’t contribute one way or another to your site’s performance, you should still delete them from the server as they might contain exploitable security vulnerabilities.

Byte for byte, orphaned thumbnails from uploaded images comprise the most wasted disk space on the average aging blog.

Every time an image is uploaded to WordPress, anywhere from a handful to a boatload of differently-sized thumbnails are generated and saved to the server. The precise dimensions of the thumbnails vary from theme to theme, so for sites that have switched designs, this can lead to a lot of images cropped at resolutions that will never be accessed again.

The plugin Force Regenerate Thumbnails will take care of this, deleting all existing thumbnails, and regenerating only those that are actually required by the current theme. Depending on how many images you have, this can take a while, so go make a sandwich if you’re hungry.


Your database, too, can easily start to look like the dark recesses of an attic, full of tangled and broken holiday decorations, old clothes, and haunted chests. The largest culprit here is usually post revisions.

WordPress maintains a history of all changes made to all posts.

This is nice because it allows you to review any changes you’ve ever made and rollback to a prior version at any time.  But this also generates a lot of bloat, particularly if you can’t decide between desert or dessert or desert or dessert.

Thankfully, this is something you can fix automatically by capping the number of revisions to some sane value. You can do this by adding the following to your wp-config.php file:

//specify the max # of revisions, 3 in this example
define('WP_POST_REVISIONS', 3);

The WP_POST_REVISIONS setting is not enforced retroactively. To remove or prune excessive revisions for existing posts, you can use a plugin like Thin Out Revisions.

The trash can also be an area of database bloat. When you delete a post, it is moved to the trash. Just like the trash on your laptop or the trash in your kitchen, items will linger forever and ever until someone bothers to empty it.

You can automate this task in WordPress, at least, by adding the following to wp-config.php:

//specify the # of days before emptying, 5 in this example
define('EMPTY_TRASH_DAYS', 5);

One last area of data bloat is one that can be really bad on some sites, and nonexistent on others: transient data.  WordPress includes an API for temporarily storing arbitrary key/value pairs for later retrieval.

Most often, transient data is used to cache results that would otherwise take a while to generate, such as a response from another server (for example, a Twitter feed) or the end result of a really convoluted query (like: find all posts published on a Wednesday about apples or oranges but not mangoes…).

By default, WordPress stores these data in the wp_options table.  Though each piece of information is given an expiration, WordPress does not do any automatic garbage collection.

Transient data is only removed if and when it is requested (after expiry).

If a given transient key is not reused, the data will outlive us all.  Fortunately, you can keep expired transient data in check with the help of the aptly named plugin Delete Expired Transients.

That’s it!  Happy cleaning!

Posted By
Josh Stoik