I finally followed the crowd and got an SSL certificate for highlightjs.org. The canonical read on the issue seems to be "Private By Default" by Tim Bray. However, Tim's piece is somewhat theoretical, so I took some additional real-world perspective on Hacker News.
The process wasn't terribly difficult, though whenever something involves config files problems are pretty much expected. Here's my experience.
Products
Apparently SSL comes in the form of branded products. For small-to-medium sites there seems to be two alternatives called PositiveSSL and RapidSSL which you can buy from quite a lot of places for wildly different prices. I ended up purchasing mine from my domain name company, Namecheap. But SSLs.com sells them even cheaper, and I don't see anything wrong with it. I probably should've gone with them but I was to deep into my research and lost track of them.
The difference between PositiveSSL and RapidSSL is negligible, and there's no definitive answer to which is the best. It boils down to:
- PositiveSSL is cheaper.
- PositiveSSL comes in the form of several files ("chained certificates") that you have to put manually into one file for your Web server's consumption. RapidSSL is apparently a single file.
- RapidSSL works for a single domain name, PositiveSSL also works for the variant with "www.". (By the way, a wildcard variant that works for *.domain.name is about 10 times more expensive.)
I didn't care for any of the technical differences so I went with the cheaper option.
Registrations, activations, etc.
After you buy your certificate the vendor usually provides a clear instruction for a multi-step setup process that involves among other things:
-
Generating some stuff on your server to tell the certificate provider for whom to generate a certificate. This is called "CSR".
-
Getting a signed certificate in exchange for the CSR.
-
Putting the certificate somewhere on your server and pointing a Web server to it.
My hosting provider — Linode — has a good documentation for generating a CSR and a somewhat excessive one for setting up nginx.
Config caveats
The docs say that "in some cases" you will have to concatenate a chain of certificates into a single file. This is exactly what you have to do with PositiveSSL. You get the whole of 4 files: a "root" certificate, two "intermediate" certificates and the one for your site. You can ignore the root one, as your system most probably already has it. And you combine the rest into a single file. The docs only mentioned having to combine two files instead of three but apparently my particular certificate chain was longer.
On the nginx side, most googleable guides tell you to simply add SSL-specific lines into your server's section:
server {
server_name highlightjs.org;
listen 443 ssl;
ssl_certificate /path/to/combined.crt;
ssl_certificate_key /path/to/private.key;
# ...
}
This won't work for two reasons:
-
First, if your followed the instruction for generating certificates, you made them visible only to the root user and thus unreadable to nginx. I corrected this by chgrp-ing them to "www-data" and chmod-ing to 640.The root-only permissions work fine, I just messed up some other thing at that moment. Disregard. -
Another problem is that trying to access your server via plain HTTP results in an infinite redirect to itself. To fix this you have to explicitly tell nginx what to do: either add
listen 80;
to the server's section to serve it both ways, or, as I did, unconditionally redirect plain HTTP requests to HTTPS:server { listen 80; server_name highlightjs.org; return 301 https://highlightjs.org$request_uri; } server { server_name highlightjs.org; listen 443 ssl; ssl_certificate /path/to/combined.crt; ssl_certificate_key /path/to/private.key; # ... }
I also wanted to redirect "www." prefix to the canonical URL for both protocols, so I needed another section:
server {
server_name www.highlightjs.org;
listen 443 ssl;
ssl_certificate /etc/ssl/private/highlightjs.org.combined.crt;
ssl_certificate_key /etc/ssl/private/highlightjs.org.key;
return 301 https://highlightjs.org$request_uri;
}
It should refer to all the SSL stuff to support HTTPS. Though I have no idea why it works automatically for HTTP too :-).
And that was it.
Comments: 7
http://wiki.nginx.org/Pitfalls#Taxing_Rewrites
also hsts could be enabled
Are you sure about this?
It always seemed to me that SSL certs and keys are read from nginx's master process which usually runs under root and not by workers which run under non-privileged user.
You're right. I just checked one more time and it works as "root.root". Looks like I simply messed up file names at some point and attributed the error to permissions. Thanks!
There are other possible settings that may improve service, besides ssl_certificate.
An useful tool to check TLS server health is https://www.ssllabs.com/ssltest/analyze.html?d=highlightjs.org
Did the same to my blog a week ago. I used StartSSL to acquire SSL certificate (it's free). Then enabled SPDY and SSL in my nginx config (as I use quite old Ubuntu version I needed to compile nginx with OpenSSL by hand). I used https://sslcheck.globalsign.com/en_US/sslcheck/ to audit my nginx configuration.
"First, if your followed the instruction for generating certificates, you made them visible only to the root user and thus unreadable to nginx. I corrected this by chgrp-ing them to "www-data" and chmod-ing to 640."
Even though you've crossed this out, this is the most worst, most harmful advice I've ever read and you would deserve to be hacked if you did this. That you said it in the first place makes me doubt that you know the basics of security.
We may differ on the definition of "basics" but I don't mind admitting that this area is very new to me. This post is directed towards readers who, like me, aren't experts but still want their servers to be secure. I do my best at explaining what I learned.
What's sad though, is not only you claim that anyone could "deserve to be hacked" for not knowing something but you also couldn't be bothered to explain what was so wrong with my first mistake. The only thing that your comment really did was make you feel smug.
In other words, contribute or GTFO.