How to install Let's Encrypt SSL Certificate on Ubuntu and Nginx Server
Tags: nginx, ssl, letsencrypt, devops
Published: 2018-04-04 17:43:45

---
title: How to install Let's Encrypt SSL Certificate on Ubuntu and Nginx Server
published: true
description: How to install Let's Encrypt SSL Certificate on Ubuntu and Nginx Server
tags: nginx, ssl, letsencrypt, devops
---
![Your encryption will need keys](https://cdn-images-1.medium.com/max/800/0*mw__iDefkSLbVuki.)
---
> This article appeared on my [blog](https://blog.hoo.gy/2018/03/13/how-to-install-lets-encrypt-ssl-certificate-on-ubuntu-and-nginx-server/), and [medium](https://medium.com/hoopeez/how-to-install-lets-encrypt-ssl-certificate-on-ubuntu-and-nginx-server-ffa363b94723). Share with your friends ;-)

As opposed to other most SSL certificate issuers, _[Let's encrypt](https://letsencrypt.org/getting-started/)_ is not only free to use but also easy to install and update. This write-up highlights steps I followed to install mine on both [Hoo.gy](https://app.hoo.gy) and [Hoo.gy Blog](https://blog.hoo.gy).  

The motivation to write this article is threefold. First, this article serves as a reference for future needs, using _[Let's encrypt](https://letsencrypt.org/getting-started/)_. Second, sharing experience with developer community is another form of learning. Third, as a token of appreciation to [the team that democratizes](https://letsencrypt.org/isrg/) this core part of security infrastructure. 


This article is divided into 4 major sections:

* Install necessary software
* Generate Key and Certificate  
* Install Certificate(s) on Nginx
* Enforce HTTS redirection
* Certificate Auto-renewal
 
> Acknowledgments: To my friend and security nerd *[@jc_uwimpuhwe](https://twitter.com/jc_uwimpuhwe)* for proof-reading and idea enrichments.  

**Install necessary software** 
 
**[Hoo.gy](https://app.hoo.gy)** runs on **Ubuntu 14 LTS** Linux box located at NYC [DigitalOcean](https://www.digitalocean.com/) datacenter. The NodeJS web server is coupled with **Nginx**. From this perspective, I will suppose your system runs a similar stack.

Certificate Issuance is done via a bot, [Certbot](https://certbot.eff.org/#ubuntutrusty-nginx), and covers a wide variety of Operating Systems and Web Servers. First, the step was to update and install latest packages, as well as making sure Ubuntu includes a new source of packages.


```shell
$ sudo apt-get update
$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:certbot/certbot
$ sudo apt-get update
$ sudo apt-get install python-certbot-nginx 
```
The second step installs [certbot](https://certbot.eff.org/#ubuntutrusty-nginx) on the box. The following command is good for Nginx server, but more can be found at [eff.org](https://certbot.eff.org/).

There are two possible modes to generate SSL certificates. That is going to be the subject of the following section.

**Generate Key and Certificate** 

The default mode is designed for regular Linux users. Everything is taken care of after you run the next command. Certbot generates proper keys+certificate and automatically update Nginx configuration files. 
  
```shell
 $ sudo certbot --nginx 
```

For more advanced users, who rather like they key+certificate, and install certificates as it pleases them, this command will help them: 

```shell
 $ sudo certbot --nginx certonly
```

After generating private key and certificate, in addition, you will need to _install certificates_, _re-enforce HTTPS redirection_, and to _automate certificate renewals_.


**Install Certificate(s) on Nginx**

Since you are already running Nginx in production, chances are you don't want anything to mess with your custom configurations. The second command gives you just that. There are two ways to do install certificates: first is to keep your configurations intact, and __symlink__ new certificates. The second is obviously to change configuration links to a new location. I preferred the latter.


```shell
# in /etc/nginx/sites-enabled/[your-config-file]
server{
  ...  
  listen 443 ssl;
  server_name example.com;
  ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;  
  ...
}
```

For some reasons, I was accustomed to __chained.crt__ for certificate and __key.crt__ for the keys. The switch is not that difficult though. Certbot generates same files under slightly different names: __privatekey.pem__ for keys, and __fullchain.pem__ for certificates.
 

**Enforce HTTPS redirection** 

There is a lot of discussions on this topic. Software developers are the worst people to have a discussion with. We always end up in tribalism, and who does it better. One way that made sense in my case, was to create a new server block in existing configuration file and redirect any request to marching this new server block, to a server block that listens only to HTTPS. The new block looks somehow like the following: 

```shell
server{
 listen 80;
 server_name example.com www.example.com;
 
 # redirect, and rewrite all links to https://example.com 
 return 301 https://example.com$request_uri;
 
 # Alternatively: if you want to forward without rewriting requested URL 
 return 301 https://$server_name$request_uri;
}
```

Customization of nginx configuration can be a whole new topic on its own, but I cannot close this post without talking about two things: auto-renewal(using a cron job) and redirect all traffic to secure channel. 

**Automatic renewal**

SSL certificates issues by _**Let's encrypt**_ last for 90 days. Which is not a bad thing on its own. If you have 1000+ servers to update every 90 days, though ... that would be a nightmare. Whence you need some sort of automation. How to go about that, is the last topic in this blog post. 

First of all, to renew certificate from Let's Encrypt takes a second ... if everything works according to the plan. 

```shell
$ sudo certbot renew --dry-run
# or simply:
# $ sudo certbot renew
# restart the nginx server
$ sudo nginx restart 
```

If you are lucky to have a smaller configuration and used auto-renewal strategy, you may have a cronjob similar to the following:
 
```shell
# file: /etc/cron.d/certbot
0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(3600))' && certbot -q renew
```

_Code snippet from [Ishigoya ~ Serverfault](https://serverfault.com/a/879711)_ 

It is possible to customize frequency, and restart command. The cronjob gives you a way to calibrate dates by using this star format: cronjob [minute, hour, the day of the month, month, the day of week].  

- This cron runs every day around 5:30 server time: _30 5 * * * ... _  
- This one runs same time, every bi-monthly(1st and 15th) _30 5 1,15 * * ..._ 
- This last one runs same time, every two months: _30 5 * */2 *_ 

So your cronjob may end up looking like the following if you wish to renew certificates every day around 5:30 server time.

```shell
30 5 * * * certbot renew --post-hook "service nginx restart"
# alternatively: using systemctrl 
# 30 5 * * * certbot renew --post-hook "systemctl reload nginx"
```

Please consider a donation for this service to service at [Let's Encrypt](https://letsencrypt.org/donate/).Even though thoughts discussed in this article seems simple(not to say naive security-wise), there are enhancements done atop Let’s Encrypt foundations, that makes this choice rock solid. If you work in Containers environment, especially Kubernetes, you should check [Kelsey Hightower’s](https://twitter.com/kelseyhightower) [Kube Cert Manager](https://github.com/kelseyhightower/kube-cert-manager) project on Github. Netflix’s [Lemur](https://github.com/Netflix/lemur) is another alternative to manage certificates, you can read an [introductory article here](https://medium.com/netflix-techblog/introducing-lemur-ceae8830f621).

**Reading list**

- [How to setup SSL Let’s Encrypt on Heroku for free](https://medium.com/should-designers-code/how-to-set-up-ssl-with-lets-encrypt-on-heroku-for-free-266c185630db)
- [WebSockets Over SSL With Node.js and Nginx](https://www.exratione.com/2013/06/websockets-over-ssl-with-nodejs-and-nginx/)
- More on Nginx HTTPS redirection discussions: [1](https://serverfault.com/a/258424), [2](https://bjornjohansen.no/redirect-to-https-with-nginx), [3](https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#using-if) 
- [Introducing Lemur](https://medium.com/netflix-techblog/introducing-lemur-ceae8830f621)
- [Elliptic Curve Private Key Structure](https://tools.ietf.org/html/rfc5915)