TOPICS
Guides

Use Let's Encrypt for SSL

In this tutorial, we'll integrate Let's Encrypt with an existing webserver, and set up automatic certificate renewal.

First, install certbot, a Let's Encrypt client. On Debian or Ubuntu:

sudo add-apt-repository -y ppa:certbot/certbot
sudo apt update
sudo apt install -y certbot

If you're using Apache or nginx, also install the certbot plugin for your webserver:

sudo apt install -y python-certbot-apache
sudo apt install -y python-certbot-nginx

Now that certbot is installed, let's use it to get our initial SSL certificates! If you're using Apache or nginx, use the corresponding command below:

sudo certbot --apache -d www.yourdomain.com,yourdomain.com --email you@example.com
sudo certbot --nginx -d www.yourdomain.com,yourdomain.com --email you@example.com

Otherwise, if you're using a different webserver, stop your webserver, and then use the standalone plugin (which will bind to TCP port 80):

sudo certbot --standalone -d www.yourdomain.com,yourdomain.com --email you@example.com

Follow the instructions to accept the Let's Encrypt terms. After the command completes, unless there was an error, our SSL certificates should be stored in /etc/letsencrypt/live/www.yourdomain.com/!

You'll now need to configure your webserver to use the new certificates. For example, in nginx:

server {
	listen 443 ssl;
	listen [::]:443 ssl;
	server_name YOUR_DOMAIN.com;

	ssl_certificate /etc/letsencrypt/live/YOUR_DOMAIN.com/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/YOUR_DOMAIN.com/privkey.pem;
	ssl_session_timeout 5m;
	ssl_session_cache shared:SSL:5m;

	ssl_dhparam /etc/nginx/dhparam.pem;
	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:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-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;
	# ...

(You may need to run openssl dhparam -out /etc/nginx/dhparam.pem 2048 to create the dhparam.pem file. For other webservers, see Mozilla's Server-Side TLS guide for instructions on robustly configuring SSL.).

After reloading the webserver, HTTPS should be working using the new certificates!

Finally, let's update /etc/crontab and set up a cron job that runs certbot daily to check whether certificates need to be renewed, and if so, to renew them:

sudo bash -c 'echo "$((RANDOM%60)) $((RANDOM%24)) * * * root certbot -q renew" >> /etc/crontab'