HTTPS with Let's Encrypt and nginx
HTTPS is a secure protocol for the internet. Unlike the communication in HTTP, which happens in plain-text, the data transferred between the server and the client with HTTPS is encrypted. HTTPS also verifies the identity of the website we are accessing with a
SSL/TLS certificate. It was initially used in online payment website, but in the recent age of privacy, it is deemed mandatory. That’s where Let’s Encrypt comes in.
Let’s Encrypt is a
Certificate Authority, they verify a website and issues certificates. The browsers have a list of trusted Certificate Authorities whose certificates it will accept. There are a lot of Certificate Authorities, so what make Let’s Encrypt different?
Two main issues with SSL certificates was that, it was paid and the process is not generally automated. Let’s Encrypt solves both these issues. Let’s Encrypt issues certificates
free of cost and it can be automated. You just need root terminal access to the server. It is currently in public beta and is backed by major players like Mozilla, Facebook, Google, etc.
In this article, we will see how to create a certificate with Let’s Encrypt and use it to host our server via HTTPS. We will be using an
nginx server here but the process is similar to all servers.
Installing Let’s Encrypt
Use SSH to log into your server as
root user. If you have
git installed in the server, you can clone the Let’s Encrypt repo in
Otherwise, download the latest
tar.gz package from
https://github.com/letsencrypt/letsencrypt/releases with wget. Extract this to
/opt/ and rename the folder to
letsencrypt. Latest version at the time of writing was
v0.2.0, so the commands for this are.
Now we have letsencrypt installed at
/opt/letsencrypt. You can add this to
Let’s Encrypt Configuration
Before you add SSL certificates, you need to register a domain and the domain must point to the server’s public address. For this, you need to a set up a
CNAME record with your DNS. You can check with your domain registar or custom DNS service to do this. If you have a HTTP site running in the server, you would have already done this.
Let’s Encrypt need to verify that you own the domain before they provide you with the certificates. This can be done in various ways. If you are running
Apache server, Let’s Encrypt can use it to verify your ownership and even install the certificates in the server for you. There is also something similar for
nginx, but it’s still experimental and not production-ready.
Another method is
standalone, where the Let’s Encrypt client will create a temporary webserver for verification. However, this need our
nginx server to be shutdown while creating and renewing our certificates. That’s just not viable.
So we will go with the
webroot method. In this method, we provide a folder path as
webroot-path. This folder must be served by our server. A temporary file will be made inside
<webroot-path>/.well-known/acme-challenge/ by the client. Let’s Encrypt will access it from the domain to verify the ownership.
For example, if the domain in
www.example.com and the
/usr/share/nginx/html. The client will create a temporary file named something like
/usr/share/nginx/html/.well-known/acme-challenge/ and it will accessed from
www.example.com/.well-known/acme-challenge/1PnCIkY for verification of the domain ownership.
The configuration needed to create the certificates are put in a file named
You need to provide your email address for recovering the certificate credentials. Also add the domains for which you want the certificates for seperated by commas like,
We need to set up nginx to serve the
webroot-path folder with nginx. If you have not installed
nginx yet, install it with,
Now, open the nginx configuration at
/etc/nginx/sites-available/default and change it as following to serve
Finally, we are ready to create our first certificate. Execute the following commands.
certonly parameter creates the certificate.
--agree-tos flag is used say that we are accepting the terms.
--config flag is used to point to the configuration file, which is found in
This creates the SSL certificates in
/etc/letsencrypt/live/<domain-name>/ folder. Whenever we renew the certificates, the latest will be found in this folder.
Nginx HTTPS configuration
Now that we have the certificates, we can change the configuration in nginx to serve via HTTPS. The HTTPS connection is done via the port
443. The first server block in nginx configuration at
/etc/nginx/sites-available/default is to redirect the HTTP traffic to HTTPS. We are also returning a
301 Moved Permanently header back. Replace the
domain-name here to your domain.
The second server block is for HTTPS running at port 443. It uses the certificates found at
You can reload the nginx with,
If your are using reverse-proxy to host in some other port, the configuration will look like this.
error_page 497 is used to redirect the HTTP traffic to port
4125 to HTTPS.
Let’s Encrypt certificates are only valid for 90 days, so you would have to renew them. To renew, you just have to run the client with
--renew-by-default flag also. The command would look like this.
This command will renew the certificate. We can automate renewal by running this command as a
cron job. Cron is a time-based job scheduler. We can make this command run once a month to renew certificates at a monthly basis to prevent it from being expired. We also need to reload the nginx configurations.
To add a new cron job, type the following command.
Add the following lines to the end of the cron file.
This causes the command to run every month on the 1st at 4:30AM. The output of this command is stored in
As a side note, there are some limits on the number of certificates we can make a week for a single domain. So to try these command with no limits, you can add the flag
--server https://acme-staging.api.letsencrypt.org/directory to Let’s Encrypt commands. This creates dummy certificates, which are NOT valid but you can use it to test the working of the cron job.