This tutorial will show you how to install and secure a Nginx web server on Debian 9 with a TLS certificate issued for free by the Let’s Encrypt Certificate Authority. Furthermore, we will configure automatic renewal of Lets’ Encrypt TLS certificates using a cron job before the certificates expire.
TLS, also known as Transport Layer Security, is a network protocol that uses SSL certificates to encrypt the network traffic which flows between a server and a client, or between a web server, such as Nginx server, and a browser. All data exchanged in between these two entities is secured and the connection cannot be decrypted even if it is intercepted using a technique such as by a man in the middle attack or packet sniffing. The certbot package software is the official client utility provided by Let’s Encrypt CA that can be used in the process of generating and downloading free Let’s Encrypt certificates in Debian.
Requirements
- Install LEMP Stack in Debian 9.
- A public registered domain name with proper DNS records ( A records or CNAME records for subdomains).
- Direct access to server’s console or remote SSH access to server.
- A user account with root privileges or direct access to root account.
Install Certbot Client Utility
In order to install Let’s Encrypt cerbot client utility in Debian 9 from Debian official repositories, open a terminal and issue the following command with root privileges, as illustrated in the following screenshot.
apt-get install certbot
The Debian apt utility, which is the command line interface of the Debian main Package Manager, will ask you, after some preliminary checks, whether if you agree to continue with installing the certbot package and all its required dependencies. To accept the process of installing the software answer with yes (y) in server’s console prompt.
Get Let’s Encrypt Certificate
To generate and download Let’s Encrypt certificates for a domain, first make sure Nginx web server is up and running and at least port 80 is accessible from the internet. To verify if Nginx is running execute the following commands with root privileges.
sudo systemctl status nginx
If the server is not running already, start Nginx daemon with the below command.
sudo systemctl start nginx
In case you have a common firewall installed in Debian, such as UFW firewall, which blocks all incoming connections on port 80 and 443, issue the below commands to open HTTP amd HTTPS port in the system.
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
In order to obtain certificates for your domain, execute the cerbot command in console with the following parameters and flags as explained below. Run the command with root privileges and supply your domain name and all other subdomains you want to obtain certificates for by using the –d flag. Also, supply the --standalone option in order for certbot to not interfere with Nginx configuration files. The Nginx server must be stopped while issuing certificates using this option.
The cerbot command syntax:
sudo certbot certonly --standalone –d yourdomain.com –d www.yourdomain.com
When you first run certbot command and obtain the certificate you will be prompted to add your email address and to agree with Let’s Encrypt terms of service. Write ‘a’ to agree to the service terms ‘no’ to not share your email address with Let’s Encrypt partners. Finally, after you’ve obtained the certificate for your domain, read the footer notes to locate certificates system path and the date they will expire.
Alternative way to get a Let's encrypt SSL certificate
To obtain a Let’s Encrypt certificate via the "webroot" plugin use the below syntax. Add Nginx web root directory, which by default is located in /var/www/html/ system path, while issuing certbot command with the --webroot and –w flags. Also, make sure that Nginx has full write permissions to web root directory in order to create the /.well-known directory.
The --webrot option for cerbot will also ask you add your email address for certificate renewal and security notices. Certbot client has built-in code that can detect a fake email address. You must provide a public accessible e-mail address in order to continue obtaining a certificate.
certbot certonly --webroot –w /var/www/html/ -d yourdomain.com –d www.yourdomain.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel):contact@yourdomain.com #A fake email address will be detected
There seem to be problems with that address. Enter email address (used for
urgent renewal and security notices) If you really want to skip this, you can
run the client with --register-unsafely-without-email but make sure you then
backup your account key from /etc/letsencrypt/accounts (Enter 'c' to cancel):youremail@domain.com
-------------------------------------------------------------------------------
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf. You must agree
in order to register with the ACME server at
https://acme-v01.api.letsencrypt.org/directory
-------------------------------------------------------------------------------
(A)gree/(C)ancel: a
-------------------------------------------------------------------------------
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about EFF and
our work to encrypt the web, protect its users and defend digital rights.
-------------------------------------------------------------------------------
(Y)es/(N)o: n
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for www.domain.com
Using the webroot path /var/www/html/ for all unmatched domains.
Waiting for verification...
Cleaning up challenges
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/www.yourdomain.com/fullchain.pem. Your
cert will expire on 2017-12-28. 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"
- Your account credentials have been saved in your Certbot
configuration directory at /etc/letsencrypt. You should
make a secure backup of this folder now. This configuration
directory will also contain certificates and private keys obtained
by Certbot so making regular backups of this folder is ideal.
- 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 for TLS (SSL)
An Nginx full default TLS configuration file for a domain should look like in the below file excerpt.
/etc/nginx/sites-enabled/default-ssl file sample:
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name www.yourdomain.com yourdomain.com;
#server_name _;
root /var/www/html;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
#SSL Certificates
ssl_certificate "/etc/letsencrypt/live/www.yourdomain.com/cert.pem";
ssl_certificate_key "/etc/letsencrypt/live/www. yourdomain.com/privkey.pem";
ssl_dhparam /etc/nginx/dhparam.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
#ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
add_header Strict-Transport-Security "max-age=31536000;
#includeSubDomains" always;
location / {
index index.php index.html index.htm;
try_files $uri $uri/ /index.php?$args $uri/ =404;
}
set $cache_uri $request_uri;
location ~ /.well-known {
allow all;
}
#
# # With php-fpm (or other unix sockets):
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
# # With php-cgi (or other tcp sockets):
# fastcgi_pass 127.0.0.1:9000;
}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
The code lines for processing PHP scripts via FastCGI Process Manager can also be found in this excerpt and is represented by the following lines.
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
}
Install Let’s Encrypt Certificates in Nginx
Let’s Encrypt certificates and keys are stored in /etc/letsencrypt/live/www.yourdomain.com/ directory in Debian. The ls command against the above directory will reveal all certificate components, such as the chain file, the fullchain file, the private key and the certificate file.
ls /etc/letsencrypt/live/www.yourdomain.com/
To install the Let’s Encrypt certificate in Nginx web server TLS configuration file, open Nginx default-ssl file and update the below lines to reflect Let’s Encrypt certificate file paths for your domain, as shown in the below excerpt.
nano /etc/nginx/sites-enabled/default-ssl
Change the following lines as below:
ssl_certificate "/etc/letsencrypt/live/www.yourdomain.com/cert.pem ";
ssl_certificate_key "/etc/letsencrypt/live/www.yourdomain.com /privkey.pem";
Also, if the ssl_dhparam statement is present in Nginx SSL configuration, you must generate a new 2048 bit Diffie–Hellman key by issuing the following command. The Diffie–Hellman key parameters generation should take a while depending on your system randomness or entropy.
openssl dhparam –out /etc/nginx/dhparam.pem 2048
Finally, before activating Nginx TLS configuration by restarting the Nginx daemon to reflect changes, first check Nginx configurations for potential syntax errors. Afterwards, if Nginx configuration file test is successful, restart Nginx daemon to load the new configuration alongside Let’s Encrypt certificates, by issuing the below commands.
nginx -t
service nginx restart
In order to verify if nginx service owns an opened socket in listening state on port 443, execute netstat command as shown in the below excerpt.
netstat –tulpn | grep -e 443 -e LISTEN
You should also open a browser and navigate to your domain name via HTTPS protocol. If Let’s Encrypt certificates are successfully applied in Nginx, the SSL handshake should work smoothly without throwing up any errors.
https://www.yourdomain.com
Force web traffic to HTTPS
To force your domain visitors to browse your website only via HTTPS protocol, open Nginx sites-enabled default configuration file and add the following line, which forces all requests that hit port 80 to be redirected with a 301 status code (permanently moved) to port 443.
nano /etc/nginx/sites-enabled/default
Redirect statement should look like presented in the below excerpt.
server_name www.yourdomain.com yourdomain.com;
return 301 https://$server_name$request_uri;
Subsequently, restart Nginx daemon to apply the change, by issuing the below command.
service nginx restart
Final Checks
To further investigate the certificates generated by Let’s Encrypt CA, you can use a modern web browser, such as Chrome. Visit your domain from Chrome browser and press F12 function key to open Developer Tools. Navigate to Security tab and hit on View certificate button in order to open the certificate, as shown in the following screenshots.
Another useful utility in investigating SSL certificates proves to be the openssl command line utility. In order to show extra information for an Let’s Encrypt CA certificate, execute the below command in a Linux console.
openssl s_client –connect www.yourdomain.com:443
Auto Renew Let’s Encrypt Certificate
In order to automatically renew a certificate issued by Let’s Encrypt CA before the expiration date, schedule a crontab job to run once a day at 2:00 AM, by issuing the following command. The output of the executed cron job will be directed to a log file, stored in /var/log/letsencrypt.log
crontab –e
Cron job to renew the certificate.
0 2 * * * certbot renew >> /var/log/letsencrypt.log
That’s all! For other more advanced configurations concerning Let’s Encrypt certificates and utility visit official documentation at the following internet address https://certbot.eff.org/docs/.