Secure web app using Let's Encrypt SSL

Install Certbot and issue a new SSL certificate

Install Certbot

1
sudo yum install certbot -y 

Make sure that the Nginx was stopped before issuing the SSL certificate:

1
sudo systemctl stop nginx

Issue a new SSL certificate

1
certbot certonly --standalone

During the process, you will be asked to enter your email address and agree to the terms of service. After that, you will be asked to enter the domain name for which you want to issue the SSL certificate. In my case, I entered hainguyen.dev:

1
2
3
4
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator standalone, Installer None
Enter email address (used for urgent renewal and security notices)
 (Enter 'c' to cancel): [email protected]

then, you will be asked to agree to the terms of service, at the end of the process, you will be asked to enter the domain name for which you want to issue the SSL certificate.

1
2
Please enter in your domain name(s) (comma and/or space separated)  (Enter 'c'
to cancel): hainguyen.dev www.hainguyen.dev

You should save the certificate path and key path for later use which are displayed at the end of the process:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/hainguyen.dev/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/hainguyen.dev/privkey.pem
   Your certificate will expire on 2018-07-01. To obtain a new or
   tweaked version of this certificate in the future, simply run
   certbot again. To non-interactively renew *all* of your
   certificates, run "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Configure Nginx to use the SSL certificate

If you are installing Let’s Encrypt SSL for the first time, you will need to create a new HD parameter:

1
2
sudo mkdir /etc/nginx/ssl/
sudo openssl dhparam 2048 -out /etc/nginx/ssl/dhparam.pem

Update the Nginx configuration file which is now using for the domain:

1
sudo vim /etc/nginx/conf.d/hainguyen.dev.conf
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
server {
    listen 80;
    server_name hainguyen.dev www.hainguyen.dev;
    rewrite ^(.*) https://hainguyen.dev$1 permanent;
}

server {
    listen 443 ssl;
		
	# access_log off;
    access_log /var/www/hainguyen.dev/logs/access.log;
    # error_log off;
    error_log /var/www/hainguyen.dev/logs/error.log;
	    
    server_name hainguyen.dev;
    root /var/www/hainguyen.dev/html;
    
    # SSL
    ssl_certificate /etc/letsencrypt/live/hainguyen.dev/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/hainguyen.dev/privkey.pem;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 
    ssl_prefer_server_ciphers on; 
    ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;

    # Improve HTTPS performance with session resumption
    ssl_session_cache shared:SSL:50m;
    ssl_session_timeout 1d;

    # DH parameters
    ssl_dhparam /etc/nginx/ssl/dhparam.pem;
    # Enable HSTS
    add_header Strict-Transport-Security "max-age=31536000" always;
 
    location / {
        index index.html index.htm;
        try_files $uri $uri/ =404;
    }
	
    # Custom configuration
    include /etc/nginx/sites-enabled/*.conf;
}

Test Nginx configuration and restart Nginx

1
2
sudo nginx -t
sudo systemctl restart nginx

Setup automatic renewal of SSL certificate

To manually renew the certificate for the next 90 days, you will need to run the following command:

1
certbot renew --pre-hook "service nginx stop" --post-hook "service nginx start"

Let create a cron job to automatically renew the SSL certificate every Monday at 3:00 AM:

1
2
```shell
sudo EDITOR=vi crontab -e

Add the following line to the file:

1
0 2 * * 1 /usr/bin/certbot renew --pre-hook "service nginx stop" --post-hook "service nginx start" >> /var/log/le-renew.log

Crontab’s syntax is as follows: minute hour day month day_of_week command

+—————- minute (0 - 59)

| +————- hour (0 - 23)

| | +———- day of month (1 - 31)

| | | +——- month (1 - 12)

| | | | +—- day of week (0 - 6) (Sunday=0 or 7)

| | | | |

* * * * * command to be executed

Remove an SSL certificate

1
certbot delete