Deploying Let’s Encrypt on an Amazon Linux AMI EC2 Instance

Are you experiencing migraines trying to install Let’s Encrypt on your Amazon Linux AMI EC2 Instance?

[skip preface]

You’re not alone!

The Anticipation
Let’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 Reality
As 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 AMI
At 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 commands

So 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 /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 =" >> /etc/letsencrypt/config.ini

Certificate Generation

1. Request a certificate the naked domain ( and www subdomain (, 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 -d --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/ )

  • cert.pem: server certificate only.
  • chain.pem: root and intermediate certificates only.
  • fullchain.pem: combination of server, root and intermediate certificates (replaces cert.pem and chain.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


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 Certs
0 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/

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]

Then add the port 443 (SSL) configuration below:

Listen 443
<VirtualHost *:443>
DocumentRoot /var/www/
# Logs
ErrorLog /var/www/logs/
CustomLog /var/www/logs/ common
# Certificates
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/
SSLCertificateKeyFile /etc/letsencrypt/live/
SSLCertificateChainFile /etc/letsencrypt/live/
SSLProtocol All -SSLv2 -SSLv3
SSLHonorCipherOrder on

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 |& grep expire

Direct file read:

$ sudo openssl x509 -noout -dates -in /etc/letsencrypt/live/

The following online tools are indispensable for checking and debugging invalid certificate issues:

…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:


Programmer. If I can’t find a solution, I write one. <3/>

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Response to FTC Task Force on Anti-Competition: 3 Investigative Tactics to Ferret Out Facebook’s…

Libertas — The Big Picture

Risk Acceptance and Mitigation

Skynet TryHackMe Writeup

Which company will become the best provider of cloud infrastructure services?

Exploring Popular zkEVM Solutions: AppliedZKP, Matter Labs, Hermez, and Sin7Y

Spammers and Scammers are Flooding YouTube and Using your Comments to Increase Their Karma

{UPDATE} Pop Night BabyCat Hack Free Resources Generator

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Gifford Nowland

Gifford Nowland

Programmer. If I can’t find a solution, I write one. <3/>

More from Medium

How to share docker images without Docker hub or any registry

Backup Elasticsearch cluster to minio S3 server (Part 1)

How to install Jenkins without installing Java?(Using docker)

Visualization testing with BDD — using Applitools