How to configure NGINX as reverse proxy with TLS
Do you have a service running that needs to be reached via a domain name? Do you want to secure it with TLS? Read on to find out how you can use NGINX for this.
Introduction
If you've a service running or if you've a device which you want to be reachable via a domain name, or even perhaps if you want to secure the connection with TLS, you can setup and configure any modern day reverse-proxy, something like Traefik, Apache or NGINX. All of these offer best in class routing and security features out of the box. In this blog post, I'll be focussing on setting up and configuring NGINX to redirect an incoming requrest to the service you're running and securing the request with TLS.
NGINX
Nginx is an open-source tool written in C
programming language, which has been around for nearly two decades, and as its github readme states, is the world's most popular Web Server, high performance Load Balancer, Reverse Proxy, API Gateway and Content Cache. NGINX is many thing, but we're only interested in its capabilities as a reverse-proxy enabling secure HTTPS connections with TLS (Transport Layer Security) so that the communication between your users and your backend servers is encrypted, protecting sensitive data from potential attackers. So, lets focus on how you can set it up and configure properly.
It is assumed here that you've already added an entry to your domain name registrar - like Godaddy, Cloudflare etc with the IP address of the machine you are setting the service on.
Step 1: Install NGINX
Installation of NGINX is fairly simple and straight forward. The process takes advantage of package managers native to specific Linux distributions.
Debian / Ubuntu
For installing on debian or debian based linux like Ubuntu, you can use the following command
sudo apt update
sudo apt install nginx
CentOS / RHEL
On a Red Hat Enterprise linux or a CentOS linux, you can use the following command
sudo yum install nginx
Once installed, you can start the NGINX service:
sudo systemctl start nginx
sudo systemctl enable nginx
You can always check the running status of the service using the following command
sudo systemctl status nginx
You should get the following output
If you get a similar output just like shown above, then your nginx service has been installed correctly. Now lets see how you can configure it.
Step 2: Install Certbot
For secure TLS encryption, you'll need an SSL certificate. You can aquire a certificate from a trusted Certificate Authority (CA). There are many Certificate authorities like DigiCert, GlobalSign etc that sell credible SSL certificates for some price. Enterprise or big Corporates acquire certificates from these certification authorities. Another way is to generate a free certificate from Let's Encrypt. Here, we will use Let's Encrypt.
Now, to setup an SSL certificate, we first need a tool called certbot
. It is the official tool provided by Lets encypt to obtain SSL certificates easily.
The following command installs the tool certbot along with the plugin python3-certbot-nginx
which automatically updates the nginx configuration files whenever a new certificate is installed or an old certificate is renewed.
On Ubuntu/Debian:
On the debian linux or a debian based linux, use the following command to install the certbot
sudo apt install certbot python3-certbot-nginx
On CentOS/RHEL:
On a Red Hat Enterprise linux or a CentOS linux, you can use the following command
sudo yum install certbot python3-certbot-nginx
Once installed, we can use certbot
to issue an SSL certificate for our custom domain.
certbot --nginx -d <DOMAIN_NAME>
--nginx
flag allows the certbot to also update nginx configuration.Certbot will automatically configure NGINX to use SSL, and you'll be able to test your website with HTTPS
Step 3: Configure NGINX
Now that all the tools and the packages have been installed, we can proceed ahead to configure the NGINX.
All the configuration files for nginx are located at the directory /etc/nginx/
. But we are specifically interested in a particular directory - /etc/nginx/conf.d/
. Any file at this path, gets loaded and parsed automatically.
So, if you've to add redirection for a domain name to a service running locally, say at port 1234
, all you need to do is simply create a .conf
file at that location
sudo nano /etc/nginx/conf.d/nginx.conf
and add the following configuration in the file
server {
listen 80;
listen [::]:80;
root /var/www/html;
server_name <DOMAIN_NAME>;
}
and then press CTRL + o
followed by CTRL + x
to save it.
Now, whenever you make changes to an nginx config file, you can test whether the configuration you added is syntactically correct or are there errors. For that, you can test for nginx syntax errors using the following cmd
sudo nginx -t
If everything is correct, it will print out the following on the terminal
And when you are sure, you can reload the nginx service for the changes to take effect, using
sudo nginx -s reload
To issue the TLS (or SSL) certificate, you can use the following command
sudo certbot --nginx -d <DOMAIN_NAME>
What this does is also add the following configuration to the nginx config file
As can be seen in the output above, certbot has created another separate server
section here - one server section listens at the port numer 80
which also has a redirection to https
part added, while the second server section serves all the https
connection requests, encrypted with TLS. You might be thinking why even leave port 80
open for listening. It is because the TLS certificates issued by Let's encrypt are only issued for a period of 90 days. And after every 60 days, they are due to be renewed. The last 30 days is the grace period. And so, the certbot listens on port 80
only to renew the certificates. Rest all the traffic is served via the secure port 443
.
So far, the SSL certificate is issued, but the redirection to the service is not yet added. So, lets add that last missing link as well.
All you need to do now is just add the redirection configuration to service in the server section which listens on port 443
, as shown below.
...
# other Config for server listening on port 443
# Proxy pass to the service for local LAN IP
location / {
proxy_pass http://127.0.0.1:<>;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
The final nginx configuration file should look like this.
Once this is done, make sure to restart the nginx server once again.
Now you should be able to reach your service from a domain name on the internet, served by encrypted connection over the https
protocol.
Automatically Renew Let’s Encrypt Certificates
As mentioned above, Let’s Encrypt certificates expire after 90 days. So, lets add one small thing more, to make sure certbot can renew on its own.
Open the crontab using this command
crontab -e
Go to the very bottom of the file and add the following command to check daily and renew certs if any cert is to be renewed in 30 days.
0 12 * * * /usr/bin/certbot renew --quiet
Save and close the file. All installed certificates will be automatically renewed and reloaded.
Bonus tips
Notice here that you can add as many websites as you want.
For example, if there are three domain names you want to issue SSL certificates for, create a separate server
section for each one of them.
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
server_name abcd.com www.abcd.com;
}
server {
listen 80 ;
listen [::]:80 ;
root /var/www/html;
server_name efgh.com www.efgh.com;
}
server {
listen 80 ;
listen [::]:80 ;
root /var/www/html;
server_name ijkl.com www.ijkl.com;
}
Once done, test the nginx config and reload the nginx using
sudo nginx -t && sudo nginx -s reload
Certbot SSL cert generation
We can also generate all the certs in one command like this
sudo certbot --nginx -d abcd.com -d www.abcd.com \
-d efgh.com -d www.efgh.com \
-d ijkl.com -d www.ijkl.com
Conclusion
As you saw, if takes only a handful of commands and you can easily setup a redirection from a domain to a service you are running locally. This is also used almost everywhere in the industry. Millions of websites and domains use the SSL certificates issued by Let's encrypt and many of them use NGINX as their server and reverse-proxy. I hope this blog post has provided you useful information to setup things on your own.
If you have any questions, opinions or feedback to give, please feel free to write in the comments below.
Also, if you're interested in redirecting an incoming request from a sub-domain or redirecting to some end-point, We've written a detailed blog post here
Further Reading
- How to Install and setup Apache2
- How to Install and setup