{"id":5741,"date":"2021-02-27T14:04:45","date_gmt":"2021-02-27T14:04:45","guid":{"rendered":"https:\/\/blog.ssdnodes.com\/blog\/?p=5741"},"modified":"2025-07-16T15:01:31","modified_gmt":"2025-07-16T15:01:31","slug":"nginx-tls-setup-certbot-lets-encrypt","status":"publish","type":"post","link":"https:\/\/www.ssdnodes.com\/blog\/nginx-tls-setup-certbot-lets-encrypt\/","title":{"rendered":"Nginx Basics &#8211; Part 1: Easy TLS \/ SSL setup using Certbot and Let&#8217;s Encrypt"},"content":{"rendered":"<h2>TL;DR Version<\/h2>\n<p>To install Nginx and Certbot on Ubuntu\/Debian systems, you first need to make sure that your FQDN has an A record pointing at your server's public IP, and then simply run:<\/p>\n<\/p>\n<pre>$ sudo apt install nginx;\n$ sudo snap install core; sudo snap refresh core\n$ sudo snap install --classic certbot<\/pre>\n<p>To issue a free SSL\/TLS certificate from Let's Encrypt, and automatically modify Nginx to use those certificates, run the below command:<\/p>\n<pre>$ sudo certbot --nginx<\/pre>\n<p>That's it! Nginx is now serving it's default website, at <em>\/etc\/nginx\/sites-enabled\/default\u00a0<\/em>as an HTTPS website.<\/p>\n<h2>A More Detailed Explanation<\/h2>\n<p>One of the most basic tasks you will perform while setting up your next website, app or API server is to ensure that the traffic is encrypted between the client and the server, and that the identity of the original server is verifiable. TLS enables us to do that.<br \/>\nContinuing our series on <a href=\"https:\/\/www.ssdnodes.com\/blog\/nginx-configuration-files\/\">Nginx Basic<\/a>s, we will see how to procure a TLS (also known as SSL) certificate and make Nginx use it to encrypt and secure all web traffic.<\/p>\n<h2>Prerequisites<\/h2>\n<p>In order to follow along, you need the following:<\/p>\n<ul>\n<li>A very basic understanding of Nginx configuration, as discussed <a href=\"https:\/\/www.ssdnodes.com\/blog\/nginx-configuration-files\/\">here<\/a>.<\/li>\n<li>A very basic understanding of how TLS works<\/li>\n<li>A VPS with a public IP, running Ubuntu 20.04 LTS. If you don't already have one, head over to <a href=\"https:\/\/www.ssdnodes.com\/\">SSDNodes<\/a> and treat yourself to some delicious compute \ud83d\ude42<\/li>\n<li>A registered domain name, like <em>www.example.com<\/em> where you want to host your project.<\/li>\n<\/ul>\n<h2>Initial Setup<\/h2>\n<h3>1. Setting Up DNS Record<\/h3>\n<p>The first thing you need to do, is to point visit the DNS management service that you are using. This could be the very place that you bought your domain name from, like Hover, Namecheap, Gandi or GoDaddy. Or it could be the third party DNS service provider like Cloudflare. At your name server control panel, create an A record for your domain pointing to the Public IP address of your VPS.<\/p>\n<p>For example, if you own <em><strong>example.com<\/strong><\/em> and want to run a website called test.example.com, then create an <strong><em>A record<\/em><\/strong> for <strong><em>test.example.com <\/em><\/strong>pointing at\u00a0 your IP address which itself would look something like <strong><em>127.74.45.11<br \/>\n<\/em><\/strong>Here, <em>example.com\u00a0<\/em>is known as your <strong><em>Domain Name<\/em><\/strong> and, <em>test.example.com\u00a0<\/em>is known as your <em>Fully Qualified Domain Name or\u00a0<strong>FQDN<\/strong><\/em><\/p>\n<p>To find your IP, simply use the command:<\/p>\n<pre>$ ip addr<\/pre>\n<p>Output:<\/p>\n<pre>1: lo: &lt;LOOPBACK,UP,LOWER_UP&gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000\n    link\/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00\n    inet 127.0.0.1\/8 scope host lo\n       valid_lft forever preferred_lft forever\n    inet6 ::1\/128 scope host\n       valid_lft forever preferred_lft forever\n<strong>2: enp3s0<\/strong>: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc fq_codel state UP group default qlen 1000\n    link\/ether 52:54:fe:d4:a4:87 brd ff:ff:ff:ff:ff:ff\n    <strong>inet 63.250.55.96\/24<\/strong> brd 63.250.55.255 scope global noprefixroute enp3s0\n       valid_lft forever preferred_lft forever\n    inet6 fe80::5054:feff:fed4:a487\/64 scope link noprefixroute\n       valid_lft forever preferred_lft forever\n<\/pre>\n<p>Depending on what you have installed on your VPS, Docker, LXD etc there might be quite a few network interfaces and to figure out which one is your public interface can get a bit tricky. But by default, there are only two. A loopback interface, called <em>lo<\/em>, and our public interface usually called <strong><em>enp3s0<\/em><\/strong>\u00a0<em>or <strong>eth0<\/strong> or <strong>ens3. <\/strong><\/em>In our case it is <strong><em>enp3s0\u00a0<\/em><\/strong>and the IP address (listed as <em>inet<\/em>)\u00a0is <strong>63.250.55.96<\/strong><\/p>\n<p>The IP address will be different in your case, set an A record for it, and then we can move on to step two.<\/p>\n<h3>2. Installing Necessary Packages<\/h3>\n<p>Apart from the obviously needed <em>Nginx <\/em>package we will also need <em>Certbot\u00a0<\/em>to fetch TLS certificates and automatically configure Nginx for us. For Ubuntu 20.04 and Debian 10 systems you can run the following commands:<\/p>\n<pre>$ sudo apt install nginx -y\n$ sudo systemctl start nginx\n$ sudo snap install core; sudo snap refresh core\n$ sudo snap install --classic certbot<\/pre>\n<p>Once, Nginx is installed you will be able to see a basic HTML website if you type in your public IP address into your web browser's address bar.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-5684\" src=\"https:\/\/www.ssdnodes.com\/wp-content\/uploads\/2021\/02\/Nginx-1024x436.png\" alt=\"Nginx Default Webpage\" width=\"1024\" height=\"436\" srcset=\"https:\/\/www.ssdnodes.com\/wp-content\/uploads\/2021\/02\/Nginx-1024x436.png 1024w, https:\/\/www.ssdnodes.com\/wp-content\/uploads\/2021\/02\/Nginx-300x128.png 300w, https:\/\/www.ssdnodes.com\/wp-content\/uploads\/2021\/02\/Nginx-768x327.png 768w, https:\/\/www.ssdnodes.com\/wp-content\/uploads\/2021\/02\/Nginx-1536x654.png 1536w, https:\/\/www.ssdnodes.com\/wp-content\/uploads\/2021\/02\/Nginx-2048x872.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<h3>3. Adding Server Name to Nginx config<\/h3>\n<p>In order to make things easier, for Certbot, we can modify the file <strong><em>\/etc\/nginx\/sites-enabled\/default\u00a0<\/em><\/strong>and replace the following line:<\/p>\n<pre>server_name _;<\/pre>\n<p>With the proper FQDN of your server:<\/p>\n<pre>server_name test.example.com;<\/pre>\n<p>Make sure to use your own specific FQDN instead of just <em>example.com\u00a0<\/em>this will be read by Certbot to automatically try and fetch certificate for it.<\/p>\n<h2>Fetching Let's Encrypt TLS Certificate Using Certbot<\/h2>\n<p>Let's Encrypt is the certificate authority that we will be using to issue a free TLS certificate for our website. Certbot is the program that will talk to Let's Encrypt and automatically fetch the certificate for us. To learn more about how TLS and Let's Encrypt works you can check out this <a href=\"https:\/\/www.ssdnodes.com\/blog\/https-lets-encrypt\/\">blog post<\/a>.<\/p>\n<p>To fetch and install the certificates in a single command:<\/p>\n<pre>$ sudo certbot --nginx<\/pre>\n<p>It will prompt you to enter your email address, which is needed for certificate renewals and other security updates:<\/p>\n<pre>Saving debug log to \/var\/log\/letsencrypt\/letsencrypt.log\nPlugins selected: Authenticator nginx, Installer nginx\nEnter email address (used for urgent renewal and security notices)\n(Enter 'c' to cancel): <strong><em>name@example.com<\/em><\/strong><\/pre>\n<p>Next, you need to accept Let's Encrypt's Terms of Service:<\/p>\n<pre>- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\nPlease read the Terms of Service at\nhttps:\/\/letsencrypt.org\/documents\/LE-SA-v1.2-November-15-2017.pdf. You must\nagree in order to register with the ACME server. Do you agree?\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n(Y)es\/(N)o: Y<\/pre>\n<p>This will be followed by an option to sign up for their newsletter, which you can agree to, or deny. After this, certbot will go through all your nginx configuration files and if you have been following along so far, it will grab your FQDN automatically, like so:<\/p>\n<pre>Account registered.\n\nWhich names would you like to activate HTTPS for?\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n1: test.iranvir.com\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\nSelect the appropriate numbers separated by commas and\/or spaces, or leave input\nblank to select all options shown (Enter 'c' to cancel):<\/pre>\n<p>Press <em><strong>ENTER<\/strong><\/em> and Certbot will fetch the certificates and then modify your Nginx configuration to automatically use the new certifcates. Certbot will also configure <em>Nginx\u00a0<\/em>to automatically redirect all the unecrypted\u00a0 traffic (reaching on port 80) to encrypted traffic (reaching on port 443). If you have not modified the configuration file, the process will still work but you will have to manually enter the FQDN when prompted.<\/p>\n<h2>Final Steps<\/h2>\n<p>The certificates expires after 90 days. To renew them, simply run the command:<\/p>\n<pre>$ certbot renew<\/pre>\n<p>I would recommend, adding the above command to your crontab file. This would allow your server to automatically run the command after a given time interval. For example, adding the below line to your <strong><em>\/etc\/crontab<\/em><\/strong>:<\/p>\n<pre>0 0 * * * root certbot renew<\/pre>\n<p>Would make sure that your VPS tries to renew the certificate everyday at midnight. And when the expiry date draws closer, it will automatically renew it as well!<\/p>\n<h2>Changes in the Configuration<\/h2>\n<p>If you are doing anything more complex than a WordPress blog, chances are you will need to know how to configure TLS\/SSL certificates yourself. So let's look at the configuration file and how it has changed:<\/p>\n<p>Initially, the file <strong><em>\/etc\/nginx\/sites-enabled\/default\u00a0<\/em><\/strong>looked like this:<\/p>\n<pre>server {\n    listen 80 default_server;\n    listen [::]:80 default_server;\n\n    root \/var\/www\/html;\n    index index.html index.htm index.nginx-debian.html;\n    server_name <strong><em>test.example.com<\/em><\/strong>; #Custom change made by us during this tutorial\n\n    location \/ {\n        try_files $uri $uri\/ =404;\n    }\n}<\/pre>\n<p>The same configuration, after issues the <strong><em>certbot --nginx <\/em><\/strong>command, looks like this:<\/p>\n<pre>server {\n\n    root \/var\/www\/html;\n    index index.html index.htm index.nginx-debian.html;\n    server_name test.example.com;\n\n    location \/ {\n        try_files $uri $uri\/ =404;\n    }\n\n    listen [::]:443 ssl ipv6only=on; # managed by Certbot\n    listen 443 ssl; # managed by Certbot\n    ssl_certificate \/etc\/letsencrypt\/live\/test.example.com\/fullchain.pem; # managed by Certbot\n    ssl_certificate_key \/etc\/letsencrypt\/live\/test.example.com\/privkey.pem; # managed by Certbot\n    include \/etc\/letsencrypt\/options-ssl-nginx.conf; # managed by Certbot\n    ssl_dhparam \/etc\/letsencrypt\/ssl-dhparams.pem; # managed by Certbot\n\n}\n\nserver {\n    if ($host = test.example.com) {\n        return 301 https:\/\/$host$request_uri;\n    } # managed by Certbot\n\n    listen 80 default_server;\n    listen [::]:80 default_server;\n\n    server_name test.iranvir.com;\n    return 404; # managed by Certbot\n\n}\n\n<\/pre>\n<p>The comments indicate which parts of the configuration are managed by Certbot. For example, from our initial server block the line <strong><em>listen 80 default_server; <\/em><\/strong>directive got replaced by <strong><em>listen 443 ssl;\u00a0<\/em><\/strong>and a few extra lines were added to indicate SSL(or TLS) specific settings, like the location of fullchain.pem and privkey.pem files which are your certificate and private key, respectively. In addition, a new server block is added that listens on port 80, and if the incoming HTTP traffic is for <strong><em><a href=\"http:\/\/test.example.com\" target=\"_blank\" rel=\"noopener\">http:\/\/test.example.com<\/a> <\/em><\/strong>it redirectly it all to <strong><em><a href=\"https:\/\/test.example.com\" target=\"_blank\" rel=\"noopener\">https:\/\/test.example.com<\/a> <\/em><\/strong>thereby ensuring that all the traffic is encrypted, without the end user of the website having to worry about it.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>TL;DR Version To install Nginx and Certbot on Ubuntu\/Debian systems, you first need to make sure that your FQDN has an A record pointing at your server&#8217;s public IP, and then simply run: $ sudo apt install nginx; $ sudo snap install core; sudo snap refresh core $ sudo snap install &#8211;classic certbot To issue  &#8230;<\/p>\n","protected":false},"author":20,"featured_media":5754,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[18,30],"tags":[202,216,217,201],"class_list":["post-5741","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops","category-tutorials","tag-ca-ssl","tag-certbot","tag-lets-encrypt","tag-self-signed-ssl"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/posts\/5741","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/users\/20"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/comments?post=5741"}],"version-history":[{"count":4,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/posts\/5741\/revisions"}],"predecessor-version":[{"id":13505,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/posts\/5741\/revisions\/13505"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/media\/5754"}],"wp:attachment":[{"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/media?parent=5741"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/categories?post=5741"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ssdnodes.com\/wp-json\/wp\/v2\/tags?post=5741"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}