Properly setting up an SSL cert for a site running on a Debian/Linux server with Apache 2.2, mod_ssl and Nginx

Jan 17th, 2013 | By | Category: Linux / Freebsd

Well after doing this and redoing it again and spending way too much time re-learning how to do it the second time I’m just going to bite the bullet and take the extra hour to blog about the process so that  next time I can just follow my easy step-by-step guide(and hopefully you can too to save you some time)

So you have a web server running Apache 2.2(and Mod_ssl) and Nginx and you want to setup a proper security cert for an ecommerce site or something else running off of port :443?  Well that’s what I have and the setup process isn’t quite as straight and after the god damn thing taking my entire server down it’s not something you want to fuck with unless you have teh entire process prepared and mapped out before hand.  So what do you need to do?

As a note I’m assuming you have your server all setup for this stuff which basically means you need mod_ssl installed and activated and nginx built with HttpSslModule.  If not then you’re not going to find instructions on that side of things here, just getting and setting up the cert and the domains themselves.

1.) Get your Cert

Obviously before you can do anything you need to get yourself a security cert.  Keep in mind here I’m not talking about an unsigned cert, this article deals with a signed cert.  I’ve looked around and the best deal I’ve found is at Comodo with their instant cert.  it’s cheap and it does what you need and is fairly painless to acquire.  So before you can even get a cert from them you need to generate a csr for them.  It’s fairly straight forward to generate and I’m assuming that you have openssl installed on your server.. If not you’re going to need to go install that.  Once that’s done you need to run the following command

openssl req -nodes -newkey rsa:2048 -keyout myserver.key -out server.csr

Obviously you can changed the .key and .csr filenames to whatever you want.  It’s going to ask you a few questions and there is really only one question that is misleading and frankly kind of stupidly worded.  It’s this one: “Common Name (eg, YOUR name) []” .  *TAKE NOTE* that when they ask for ‘YOUR name’ they are actually asking for YOUR DOMAIN name’ because if you put in your name here Comodo is going to reject your CSR and tell you to redo it.  Stupid? Yes?  Completely fucking retarded? Absolutely.  But whatever, lesson learned so you don’t have to make the same mistake 🙂  Put in your domain name here and you are good to go.  In terms of the challenge password, you can leave it blank.

Just copy the entire contents of the generated CSR file and send that to Comodo upon request and they will send you back a nice little zip file with two files in it: a .crt file and a .bundle file.    Keep that .key file handy as that is going to come in handy later.

With your package from Comodo in hand I would go and create a sub-dir in /etc/apache2/ssl for this new domain (ie: /etc/apache2/ssl/domain.com) and you are going to unzip everything from the package in there as well as move the .key file that was generated in the beginning in there as well.

According to the instructions I’ve seen you need to combine that .bundle file with your .key file.  So first off make sure everything is backed up and then just do a simple

#cat domain_ca.bundle >> domain_ca.crt

and it’ll tack the bundle file on to the end of the .crt file.  Apparently nginx handles the chains all at once instead of how apache handles it where you need to put something extra like this in your apache vhost:  “SSLCertificateChainFile /etc/ssl/crt/yourSERVERNAME.ca-bundle”

 

Redirecting http to https:

For my setup I need all traffic to use https but for you you might only need to have a certain subdomain or a directory/path/alias(ie: /checkout) use :443.  For the latter this might not be exactly the setup you need but I’m sure a little googling will point you in the right direction.. The gist of will be the same.  

Also note that you shuoldn’t restart apache or nginx until you do all of the steps below(i’ll let you know when) as restarting it half way through is just going to take down your domain

The only time we are going to use apache for this process is to handle the redirects, everything else is going to flow through nginx.  So what we need is anyone hitting the domain on port 80, on in this case with nginx setup port 8080 they are going to be redirected to port :443.  I’m going to assume that you already have the domain setup as a standard http virtualhost at this point so you are actually going to be doing two things in this step, first setting up the redirect and secondly modifying the original vhost to work on :443 instead of whatever http port you have configured(8080 is what I have).

So first the redirect:

It’s simple enough, just add a vhost like what I have below and note that I have 127.0.0.1 for my vhost.conf file but you could have an something completely different depending on how the rest of your vhosts are setup

<VirtualHost 127.0.0.1:8080>
ServerAdmin webmaster@domain.com
ServerName domain.com
ServerAlias *.domain.com
Redirect permanent / https://domain.com/
</VirtualHost>

Now you need to just find the original vhost for this domain and change the very first line of it from something like this

<VirtualHost 127.0.0.1:8080>

to something like this

<VirtualHost 127.0.0.1:443>

Done and done, that’s all the apache we need to do, it should no forward every single person that comes to your domain through a secured port

Setting up the Nginx vhost entry

 

So right now your vhost entry probably looks more or less something like this:

server {
listen 0.0.0.0:80;
server_name domain.com *.domain.com *.domain.com;
# access_log /usr/domain/logs/domain.com/access.log main;
location / {
root /path/to/domain.com;
ssi on;
proxy_pass http://127.0.0.1:8080;
proxy_redirect off;
proxy_read_timeout 1200;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header HOST $host;
}
location ~* ^.+.(jpg|gif|ico|css|js|png|flv|wmv|mpg)$ {
root /path/to/domain.com;
}
}

 

#Note: The listen IP should be specific to your server and NOT 0.0.0.0

What we need to do here is to change a couple of the ports to tell nginx that we should be listening on port :443 as that’s where apache is proxying this domain to now and that we should be serving content on port :443 as well.  I suppose you could have it listen to something like port :4430 if you wanted to but I have mine setup to listen and serve on the same port.   You also need to enable and specify the ssl ciphers and protocols you are going to use.  I can’t remember why I chose the ones I did but they were what was recommend so if you want to learn more about which ones are which I’m sure google will provide ample info.  In the end your new vhost entry is going to look like this.

server {
listen 0.0.0.0:443;
server_name domain.com *.domain.com *.domain.com;
# access_log /usr/domain/logs/domain.com/access.log main;
location / {
root /path/to/domain.com;
ssi on;
proxy_pass http://127.0.0.1:443;
proxy_redirect off;
proxy_read_timeout 1200;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header HOST $host;
}
location ~* ^.+.(jpg|gif|ico|css|js|png|flv|wmv|mpg)$ {
root /path/to/domain.com;
}
ssl on;
ssl_certificate /etc/apache2/ssl/domain/domain_com.crt;
ssl_certificate_key /etc/apache2/ssl/domain/myserver.crt;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;

}

#Note: The listen IP should be specific to your server and NOT 0.0.0.0 and the .crt files should be specific to what you named it upon generation and what Comodo gave you in the bundle.  Another thing, if you only have a certain page or directory off your domain that needs SSL but the rest of the domain will operate on http(port 80) you should make a copy of the original nginx vhost entry so that you have one for port 443 and port 80.

 

That should be all that you need to do, the site should be all setup and working properly now with encryption enabled.  Now when I started testing immediately afterwards I ran into dumb ass problem where the page would just hang and not load.  After checking the apache logs(as the nginx logs showed nothing) I found this error:

“\x16\x03\x01\x01\x8C\x01\x00\x01\x88\x03\x01P\xF8]\x81\xD3\x9E\x5C\x0B\xE3]\xBFr\xC8\xF7\xDF\xE7#n\xA6yJ\x85\xC5\xC0\x0Ceq\x0C\x1B\xB7C= U\xC7\xA9y\xDE\xD9MO\xF1\xCD\xEC\x82\x88L\x0En#\xCAB\xB5\x22\x09\xA1\xA8\xC3\x9F\xE2\xE8xp_\xD4\x00H\xC0” “400” 172 “-” “-” “-“

Clearly not the most descriptive error message.  I tested everything else out, triple checked it all and it all looked fine.  It was only after loading the same url in a different browser that I realized it was Chrome cache that was fucking with me so I opened and incognito window and it loaded fine.  Make sure you clear your cache if you run into problems after testing.

 

Hope that helps anyone looking to setup something similar

Tags: , , , , , , ,

One Comment to “Properly setting up an SSL cert for a site running on a Debian/Linux server with Apache 2.2, mod_ssl and Nginx”

  1. Anina says:

    Can I thank you! is that enough for this post? Hmm no i don’t think so! Awesome work done…

Leave a Comment