Secure your website with Let's Encrypt and Nginx
The internet is becoming more and more insecure, and HTTPS connections might be a must for some projects, specially when dealing with sensitive user data.
Let's Encrypt allows the generation of free SSL/TLS certificates for HTTPS connections. Nginx is a reverse proxy software that can handle these certificates and secure the connection to your website or webservice from the user's browser.
Requirements
- Have a Virtual Private Server
- Have a configured DNS Domain pointing to your server
- Have a webservice exposed through a local port or a static website
Securing your website/webservice
The procedure is relatively easy and simple. This example will assume Ubuntu Server as operating system, let's proceed.
Installing Let's Encrypt Certbot
We must first install the Let's Encrypt Certbot to generate the SSL/TLS certificates (and renew them):
sudo add-apt-repository ppa:certbot/certbot
sudo apt update
sudo apt install python-certbot-nginx
Installing Nginx
In case Nginx is not installed, proceed with this command:
sudo apt-get install nginx
Create the secure certificate
In this example we will assume a static website that will be exposed over www.mydomain.info
and a web service over port 9000
to be exposed over service.mydomain.info
(it is important to have configured A records in the DNS config environment that make @
, www
and service
to our server IP).
Run the certbot to make the certificates:
sudo certbot --nginx -d mydomain.info -d www.mydomain.info -d service.mydomain.info
It is possible to add additional subdomains with the -d
option. If certbot asks redirect HTTP traffic, choose No. The certbot will make the certificate now.
Configuring Nginx
Create a new .conf
file for each website and webapp in your server inside /etc/nginx/sites-available/
.
Static Website
Create first /etc/nginx/sites-available/website.conf
and put in there:
#HTTP Server
server {
listen 80;
server_name mydomain.info www.mydomain.info;
return 301 https://mydomain.info$request_uri;
}
# HTTPS Server
server {
listen 443 ssl default_server;
server_name mydomain.info;
client_max_body_size 50M;
location / {
root /var/www/html;
}
ssl on;
ssl_certificate /etc/letsencrypt/live/mydomain.info/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mydomain.info/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
ssl_session_timeout 5m;
}
Remember to change mydomain.info
for the name of your domain and /var/www/html
in root
for the location of your static site (your index.html
, for example).
Webservice/Webapp
Create a /etc/nginx/sites-available/service.conf
and put in there:
#HTTP Server
server {
listen 80;
server_name mydomain.info www.mydomain.info;
return 301 https://mydomain.info$request_uri;
}
# HTTPS Server
server {
listen 443 ssl default_server;
server_name mydomain.info;
client_max_body_size 50M;
location / {
proxy_pass http://localhost:9000;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
}
ssl on;
ssl_certificate /etc/letsencrypt/live/mydomain.info/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mydomain.info/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
ssl_session_timeout 5m;
}
Remember to change mydomain.info
for the name of your domain and http://localhost:9000
in proxy_pass
for the port location of your webservice.
Test and enable Nginx configuration
Enable your site making a softlink to the Nginx enabled sites:
sudo ln -s /etc/nginx/sites-available/website.conf /etc/nginx/sites-enabled/website.conf
sudo ln -s /etc/nginx/sites-available/service.conf /etc/nginx/sites-enabled/service.conf
Now test your new configurations:
sudo nginx -t
If test passes, reload Nginx to make changes effective:
sudo service nginx restart
Configure firewall
Configure firewall to allow communication over ports 80
and 443
. In case of using ufw
, this two-liner can solve all:
sudo ufw allow 'Nginx Full'
sudo ufw reload
Wrapping up
This certbot will auto-renew your service periodically and automatically with a cronjob, ensuring that your site has secure certificates.
You can test the renewal process with:
sudo certbot renew --dry-run
Enjoy your secure server now. Cheers!