I use nginx to serve my HTTPS domains, and Letsencrypt support for nginx is still in beta. I also have a relatively specialized nginx config setup so I don't want any automated script messing with those files. Below are the steps I took to use the letsencrypt tool to generate and automatically renew a certificate for a domain.
$ git clone https://github.com/letsencrypt/letsencrypt
$ cd letsencrypt
$ ./letsencrypt-auto --help
This installs the tool as well as a number of dependencies. After it's done, the letsencrypt-auto
command is available. I installed this in my home folder.
The tool expects to be able to write the challenge file to disk and that it will be accessible at example.com/.well-known/acme-challenge/*
. The first step to getting the process working was setting up an nginx server block for each http domain.
server {
listen *:80;
server_name aaronpk.com example.com;
location /.well-known/acme-challenge {
default_type "text/plain";
root /tmp/letsencrypt;
}
location / {
return 301 https://$http_host$request_uri;
}
}
This configures nginx to serve the /.well-known/acme-challenge/
path from a folder on disk, and will redirect any other requests to the https version of the domain.
Now we can run the script that will request the cert and respond to the challenge.
~/letsencrypt/letsencrypt-auto certonly -a webroot --webroot-path=/tmp/letsencrypt -d aaronpk.com
If you want to generate a certificate that contains multiple domains, you can add more -d example.com
parameters to the command. Alternately, you can run the command for each domain separately to generate separate certificates.
This tells the script to request the cert and write the challenge to disk, and prefills the domain name it's requesting. If everything goes well, you should see:
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/aaronpk.com/fullchain.pem. Your cert will
expire on 2016-03-06. To obtain a new version of the certificate in
the future, simply run Let's Encrypt again.
Now we can set up the virtual host block which serves the certificate!
server {
listen *:443 ssl;
server_name aaronpk.com;
ssl on;
ssl_certificate /etc/letsencrypt/live/aaronpk.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/aaronpk.com/privkey.pem;
# your normal config stuff goes here
}
(Note that I deliberately left out the other ssl config options from this example, since it's possible to configure them at the top-level nginx config. See indiewebcamp.com/nginx for more details on configuring nginx with https.)
Now that the two configuration blocks are in place, renewal of the certificate can be automated by running the same command with --renew
.
~/letsencrypt/letsencrypt-auto --renew certonly -a webroot --webroot-path=/web/sites/aaronpk.com/letsencrypt -d aaronpk.com
sudo /opt/nginx/sbin/nginx -s reload
I patched OpenSSL and due to the nature of the bug had to tell my old SSL cert that we are never, ever, ever getting back together.
First, a few tools for testing your servers:
Run one of these against your HTTPS server:
./heartbleeder example.com
Turns out in Ubuntu 12.04, running openssl version
will always report "OpenSSL 1.0.1 14 Mar 2012" for all versions of 1.0.1. This makes it more difficult to tell if you've successfully updated.
Update the system openssl libraries:
sudo apt-get update sudo apt-get upgrade
Now, you won't be able to check the version number, but you can check the date that openssl was built:
$ openssl version -a OpenSSL 1.0.1 14 Mar 2012 built on: Mon Apr 7 20:33:29 UTC 2014
Note that unless it has a "built on" date after Apr 7, you've still got a problem.
Now just restart nginx and run the heartbleed test again and you should be fine.
Even if you compile Ruby from source, it should be dynamically linked to the system OpenSSL library, so you should be good to go now! However, I would be more confident if I could confirm that Ruby was in fact using the updated library.
Due to the way Ubuntu OpenSSL works, asking Ruby what OpenSSL version it's using doesn't give us any more helpful information:
$ ruby -r openssl -e 'puts OpenSSL::OPENSSL_VERSION' OpenSSL 1.0.1 14 Mar 2012
(from @sferik)
So let's do a little digging:
$ irb
irb(main):001:0> $:.map{|d| Dir[File.join d, "openssl.so"]}.flatten.compact.first /usr/local/lib/ruby/2.0.0/x86_64-linux/openssl.so
irb(main):002:0> quit
$ ldd /usr/local/lib/ruby/2.0.0/x86_64-linux/openssl.so | grep crypto libcrypto.so.1.0.0 => /lib/x86_64-linux-gnu/libcrypto.so.1.0.0 (0x00007f3331750000)
ls -l /lib/x86_64-linux-gnu/libcrypto.so.1.0.0 -rw-r--r-- 1 root root 1930616 Apr 7 20:37 /lib/x86_64-linux-gnu/libcrypto.so.1.0.0
You should see that libcrypto.so was built on Apr 7. At this point I can be reasonably sure that Ruby is using the updated OpenSSL library. I would feel much more comfortable if I had a malicious server I could test against. Below are the issues on the three repos above about writing a client-testing tool.