You’re not alone!
The AnticipationLet’s Encrypt
announced its public beta on a bitter cold day in December, 2015. I was
attending the inaugural WordCamp US in Philadelphia, PA alongside about 1,800 peers whose personal livelihoods are built on the internet. The mood was electric. Google had been signaling
that they favor HTTPS sites in search rankings for some time. “Finally,
free SSL Certificates for all!” presenters throughout the morning
enthusiastically exclaimed. By lunchtime dozens of developers had
collected in the hallways, fervently entering commands into their
terminal windows, all racing to implement this divine gift bestowed upon
the world by an obscure acronym.
The RealityAs
the day wore on I inquisitively approached a group of people I
overheard discussing Let’s Encrypt. The consensus? Not one of them had
successfully generated a valid SSL certificate for their site using the
Let’s Encrypt software. A rather disheartening inception indeed! Not to
be deterred, over the following months I gathered everything I could
find about implementing Let’s Encrypt SSL certificate generation and
management on my own AWS EC2 instance running Amazon Linux AMI and Apache.
What follows is my process, and since there’s currently very little
documentation of this niche implementation online if this saves just one other person some grief then the time spent will have been worth it.
Blindly follow me into the promised land!
Shameful admission:
I’m adapting this documentation from step-by-step notes taken during my
own install over three months ago, so please excuse any hazy details
and certainly leave feedback if anything is unclear so I can make
improvements!
(In)Compatibility with Amazon Linux AMIAt the time of writing the Let’s Encrypt Certbot still isn’t technically
supported for deployment on the Amazon AMI flavor of Linux. It still
works, though*! At this point it’s also worth it to note that Amazon itself
also offers a free service, although I haven’t tried it because as I
always say: “with just a little coffee and foolhardy perseverance you
too can start generating and managing SSL Certificates yourself, for
free!” Plus, think of the bragging rights.
* As long as you use the
--debug
option on all commandsSo without further ado…
The Install
1. Install Python:
$ yum install python27-devel git
2. Install Let’s Encrypt by cloning the github repository into
/opt/letsencrypt
and running the Let’s Encrypt installer:$ git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt
$ /opt/letsencrypt/letsencrypt-auto --debug
2a. If you’re running Amazon Linux 2 on your EC2 follow these additional steps (thanks @andrenakkurt!) before continuing.
3. Make a configuration file (
/etc/letsencrypt/config.ini
) that will be used to sign all future certificates and renewals with your private key and email address:$ echo "rsa-key-size = 4096" >> /etc/letsencrypt/config.ini
$ echo "email = ________@____.com" >> /etc/letsencrypt/config.ini
Certificate Generation
1. Request a certificate the naked domain (
_______.com
) and www subdomain (www._______.com
), using a “secret file” generated in a directory (.well-known
) in your website’s root folder (/var/www/_______
)$ /opt/letsencrypt/letsencrypt-auto certonly --debug --webroot -w /var/www/_______ -d _______.com -d www._______.com --config /etc/letsencrypt/config.ini --agree-tos
Certificate files (
cert.pem
, chain.pem
, fullchain.pem
, and privkey.pem
) are generated in an individual folder for each domain in /etc/letsencrypt/live/
(e.g. /etc/letsencrypt/live/_______.com/
)- cert.pem: server certificate only.
- chain.pem: root and intermediate certificates only.
- fullchain.pem: combination of server, root and intermediate certificates (replaces
cert.pem
andchain.pem
). - privkey.pem: private key (do not share this with anyone!).
Take a note of your expiration date and other important information displayed on the confirmation screen.
2. Remove the now-empty “secret file” directory, if desired (for cleanliness)
$ rmdir /var/www/______/.well-known
Certificate Renewal — Manual
Let’s Encrypt includes a script to check and renew your certificates:
/opt/letsencrypt/letsencrypt-auto --no-bootstrap renew
Troubleshooting:
One common issue experienced on Amazon Linux AMI is receiving the following error:
Traceback (most recent call last): File "/usr/local/bin/virtualenv", line 7, in <module> from virtualenv import main ImportError: No module named virtualenv
…or similarly:
/opt/letsencrypt/letsencrypt-auto: line 666: virtualenv: command not found
To resolve this, install/reinstall the python package “virtualenv” using PIP
$ sudo easy_install pip $ sudo pip install virtualenv
Certificate Renewal — Automated
The easiest way to automate the above certificate renewal process is to add it to your cron process.
$ sudo nano /etc/crontab
Enter the following for a once-a-day check. Make sure you also refresh Apache, newly renewed certificates won’t be recognized otherwise!
# Renew SSL Certs0 13 * * * ec2-user /opt/letsencrypt/letsencrypt-auto --no-bootstrap renew
# Refresh Server 10 13 * * * root apachectl -k restart > /dev/null 2>&1
If
your certificates fail to renew automatically see “Troubleshooting”
under Certificate Renewal — Manual, many times it’s the virtualenv
package failing to execute during the auto-renew process as well, a
reinstall of that package should fix it.
Certificate Implementation
Adding
your newly generated SSL Certificates to your website just requires
making some additions to your virtual host configuration files.
$ sudo nano /etc/httpd/conf.d/_____.com.conf
If you want to force SSL (a good idea) add the following to the TOP of the config file before anything else:
# Force SSL <IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{HTTPS} !=on RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R=301,L] </IfModule>
Then add the port 443 (SSL) configuration below:
Listen 443 <VirtualHost *:443> ServerAdmin ________@____.com DocumentRoot /var/www/_______.com ServerName _______.com ServerAlias www._______.com
# Logs ErrorLog /var/www/logs/_______.com-ssl_error_log CustomLog /var/www/logs/_______.com-ssl_access_log common
# Certificates SSLEngine on SSLCertificateFile /etc/letsencrypt/live/___.com/cert.pem SSLCertificateKeyFile /etc/letsencrypt/live/___.com/privkey.pem SSLCertificateChainFile /etc/letsencrypt/live/___.com/chain.pem SSLProtocol All -SSLv2 -SSLv3 SSLHonorCipherOrder on SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA !RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS" </VirtualHost>
Refresh Apache for the changes to take effect:
$ sudo apachectl graceful
Certificate Validity Audit
Here
are a couple of methods to use to ensure your new certificate is
configured properly and to check an existing certificate’s expiry date:
HTTP response:
$ curl -sIv https://_______.com |& grep expire
Direct file read:
$ sudo openssl x509 -noout -dates -in /etc/letsencrypt/live/_______.com/cert.pem
The following online tools are indispensable for checking and debugging invalid certificate issues:
- In-depth certificate analysis on Why No Padlock
…and that’s it!
Further Reading
My
own journey would have been impossible without the sages who blazed the
untamed trail before me, to which I owe my sincere gratitude:
- Let’s Encrypt on EC2 — Ivo Petkov ← terse but invaluable resource
- Install Let’s Encrypt to Create SSL Certificates — Linode