SSL
Generating an SSL key and signed certificate
These instructions will adapt to the input you provide so that you can easily copy and paste the required commands into your terminal.
This process involves writing and reading several files. Create a new directory and cd
into it. The rest of these instructions assume that you stay in this directory.
1. Generate a random private key
Run the following command to randomly generate a private key:
openssl genrsa 4096 > .key
You should never show this key to anyone, not even StartSSL. Your web server (e.g., nginx) will use this key to encrypt / decrypt traffic, but otherwise, no one else should see it. If you lose it, you will need to go through this whole process again. Worse, if someone else has access to it, they could potentially read all the traffic going to and from your server, as if your visitors were using plain http://
That command creates a 4096-bit key. You could probably get away with 2048 bits, but 4096 is a safe value.
If you look at the contents of .key
, it should begin with the line -----BEGIN RSA PRIVATE KEY-----
and end with the line -----END RSA PRIVATE KEY-----
, with several (~49) lines of random characters in between.
2. Generate a certificate signing request
This is where your domain name actually gets involved. You can specify all the arguments when calling openssl
at the command line, but we'll use a config file.
Create a file called .config
with the following text:
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
CN=
O=
emailAddress=
L=
ST=
C=
And then run the following command:
openssl req -new -config .config -key .key > .csr
That generates a file called .csr
, which we'll use in the next step. .csr
should begin with the line -----BEGIN CERTIFICATE REQUEST-----
and end with the line -----END CERTIFICATE REQUEST-----
, again with a lot of random-looking characters in between.
3. Request the certificate
We'll use StartCom's free certificate-signing service, StartSSL, so you'll need to make an account at https://www.startssl.com/. Then go to the Control Panel, and select the "Validations Wizard" tab. Select the "Type", "Domain Name Validation", and follow the steps there to validate your domain. It will you show you a list of email addresses associated with your domain that it can use to validate that you own that domain, so you'll probably need to be able to read email sent to postmaster@
(if none of the other email addresses will forward to you).
Once you receive the validation email, you'll be able to use the "Certificates Wizard" tab on the StartSSL site.
- Select the Certificate Target called "Web Server SSL/TLS Certificate"
- On the Generate Private Key page, click "Skip »»"
- Paste in the contents of the
.csr
file you created in the previous step. - It should say Certificate Request Received. Click "Continue »»"
- On the Add Domains page,
is probably the only possible Domain selection, otherwise select
- It will ask you what subdomain you want to use with this certificate (in addition to no subdomain).
www
is a typical choice.
When the signing is complete, it will show you a multiline textbox with the contents of your signed certificate. Save this in a file called .crt
TODO: add remark about the certificate trust chain
4. Install the certificate on your server
You should now have the following two files (the other files aren't actually used in the encryption / decryption process, but useful to keep around):
.key
.crt
Precisely how you use these depends on your application.
Suppose you want to use nginx, at least as your SSL termination point (which isn't a bad idea). Copy the key and certificate to your server, into these locations:
/etc/nginx/certs/.key
/etc/nginx/certs/.crt
To serve static files from /var/www
, use the following config file:
server {
server_name ;
listen 443 ssl;
ssl_certificate /etc/nginx/certs/.crt;
ssl_certificate_key /etc/nginx/certs/.key;
location / {
root /var/www;
}
}
The important bit are the ssl_certificate
and ssl_certificate_key
directives. You would use much the same configuration if you were back-proxying to some other application, just with a different location
directive, e.g., location / { proxy_pass http://127.0.0.1:8080; }
Obligatory SSL configuration remark: for tighter security, include the following SSL-specific directives in your nginx configuration file:
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;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;
add_header Strict-Transport-Security "max-age=31536000";
Note that the StartSSL certificate has the expiration date set to a year from when StartCom generated it. If you want a longer-lasting certificate, consider the following alternatives:
- WoSign: Free, expires after 3 years, but it takes ~4 hours for them to validate your request and send you the certificate.
- SSLs.com: The interface is easier to use than StartSSL's, but there's no free option. The cheapest option, Comodo PositiveSSL, starts at $4.99 / year if you pay for 3 years.
5. Verification
You can use the following services to verify your configuration