Install Nginx and Setup SSL/TLS with Certbot

Hello there, sorry for delay to post almost 2 months. Since covid-19 outbreak have significance impact to my working rhythm. Today I'll continue the journey of initial setup for CentOS 7. After securing our connection into the server (see here), right now the most used application should we install is the Web Server. There are two most known, one is Nginx (read: Engine X) and Apache HTTP Server (also known as Apache WebServer or httpd). Personally I recommend you to use Nginx instead of httpd, because the basic architecture of Nginx is using event-driven approach, instead of creating new thread for each request that doing in httpd. So Nginx could handle more concurrent request within small amount of threads. Also today, the event-driven approach are widely adopted, for example the famous ReactiveX library in the programming side is the leading asynchronous API library for programming languages. So more application are now evolved to use event-driven style instead of blocking in old-fashion.
Back to topic, we gonna install Nginx also setup the free SSL/TLS from Lets Encrypt by using Certbot on CentOS 7. This post scoped only in CentOS 7 and I'm using Alibaba Cloud as my cloud provider. Using other Operating System (OS) or cloud provider may need some adjustment to be matched, but I'll describe in general. If you have a trouble during follow this tutorial, don't hesitate to ask in the comment. Let's rock!

Step 1 Login into Server via SSH

Once we're logged in into our server, change our mode into root by:
$ sudo -s
[sudo] password for h3rucutu:
#

Step 2 Install Necessary Packages using YUM

While in the root mode, we can perform administrative task more easy than typing sudo prefix command for each administrative task. First update the YUM packages list in our server:
# yum check-update
Once the check-update has done, add CentOS 7 EPEL (Extra Packages for Enterprise Linux) repository into our server:
# yum install epel-release -y
If the EPEL repository already configured in our server, in the end of the command above should be appear "Nothing to do". Then we are ready to install Nginx.
# yum install nginx -y
Wait a little minute until YUM is configured Nginx for us.

Step 3 Nginx with systemd

Now, Nginx was installed into our server, but not yet running.
# systemctl status nginx
● nginx.service - The nginx HTTP and reverse proxy server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
   Active: inactive (dead)

Jun 24 13:02:43 caltic-sandbox systemd[1]: Unit nginx.service cannot be reloaded because it is inactive.
We need to manually run Nginx using systemd.
# systemctl start nginx
# systemctl status nginx
● nginx.service - The nginx HTTP and reverse proxy server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
   Active: active (running) since Wed 2020-06-24 12:07:29 WIB; 4min 40s ago
  Process: 11196 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
  Process: 11194 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
  Process: 11193 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
 Main PID: 11198 (nginx)
   CGroup: /system.slice/nginx.service
           ├─11198 nginx: master process /usr/sbin/nginx
           └─11199 nginx: worker process

Jun 24 12:07:29 caltic-sandbox systemd[1]: Starting The nginx HTTP and reverse proxy server...
Jun 24 12:07:29 caltic-sandbox nginx[11194]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
Jun 24 12:07:29 caltic-sandbox nginx[11194]: nginx: configuration file /etc/nginx/nginx.conf test is successful
Jun 24 12:07:29 caltic-sandbox systemd[1]: Failed to parse PID from file /run/nginx.pid: Invalid argument
Jun 24 12:07:29 caltic-sandbox systemd[1]: Started The nginx HTTP and reverse proxy server.
Nginx now running in our server. Verify this by using curl.
# curl -I localhost
HTTP/1.1 200 OK
Server: nginx/1.16.1
Date: Wed, 24 Jun 2020 05:14:26 GMT
Content-Type: text/html
Content-Length: 4833
Last-Modified: Fri, 16 May 2014 15:12:48 GMT
Connection: keep-alive
ETag: "53762af0-12e1"
Accept-Ranges: bytes
We got response 200 (confirm that Nginx running well). Next we need to verify using our IP Public, so anyone on the internet could reach our server. We could use curl again to obtain our IP Public.
# curl icanhazip.com
149.129.227.89
Then from our local machine simply open up your favourite browser and go to the IP Public that you've got from response above, e.g. my IP Public is 149.129.227.89.

Default Homepage Nginx on CentOS
Congratulations, our server are online on the internet! (If you have different experience that your server can't reach on the first time after fresh installed, it's normal due to the firewall in OS or in your Cloud Provider, don't hesitate to drop the comment, I'll help you).
To make our Nginx are available every-time, we should make Nginx auto-start when our server accidentally rebooted.
# systemctl enable nginx

Step 4 Add A Record in DNS

Make sure you have purchase a domain, wherever you buy. Since I didn't have affiliate marketing with the any company that offer to buy domain, so for this step I also focus (like Alibaba Cloud as my cloud provider) on what I've purchased in Hostinger.
Log in into your domain provider, then find DNS Management. Add A Record e.g. we want to add example sub-domain under caltic.tech to be direct into our server that have Nginx running.

Add A Record in DNS Management

Wait for a while (up to 1 x 24 hours) and try to ping the domain, until the IP that appear is reflected into our server. The process during we add record until the our IP is reflected called "propagation".
% ping -c 4 example.caltic.tech
PING example.caltic.tech (149.129.227.89): 56 data bytes
64 bytes from 149.129.227.89: icmp_seq=0 ttl=56 time=9.434 ms
64 bytes from 149.129.227.89: icmp_seq=1 ttl=56 time=7.195 ms
64 bytes from 149.129.227.89: icmp_seq=2 ttl=56 time=7.617 ms
64 bytes from 149.129.227.89: icmp_seq=3 ttl=56 time=6.698 ms

--- example.caltic.tech ping statistics ---
4 packets transmitted, 4 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 6.698/7.736/9.434/1.033 ms
Once the IP is reflected, then change the url in your favourite browser into example.caltic.tech instead of accessing directly using IP Public.

Our server accessible through domain

Great, now our server is accessible through domain.

Step 5 Install Certbot x Nginx

Although our server now is accessible through domain but the communication between our server and the client who visit our domain not yet secure, we need to add SSL/TLS to secure the communication. This would prevent the MITM or anyone could read the communication between server and client.
Let's Encrypt is a non-profit Certificate Authority, providing TLS certificates to website. Let's Encrypt is free, automated, and open certificate authority (CA), run for the public's benefit.
Certbot is a free, open source software tool for automatically using Let's Encrypt certificates on manually-administrated websites to enable HTTPS.
First install the Certbot-Nginx Packages
# yum install certbot python2-certbot-nginx -y
Once installed, we need to backup our nginx configuration first.
# cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
Then obtain new SSL/TLS certificate using Certbot of our domain example.caltic.tech.
# certbot --nginx -d example.caltic.tech
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Starting new HTTPS connection (1): acme-v02.api.letsencrypt.org
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for example.caltic.tech
Waiting for verification...
Cleaning up challenges
Deploying Certificate to VirtualHost /etc/nginx/nginx.conf
Redirecting all traffic on port 80 to ssl in /etc/nginx/nginx.conf

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled https://example.caltic.tech

You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=example.caltic.tech
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/example.caltic.tech/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/example.caltic.tech/privkey.pem
   Your cert will expire on 2020-09-24. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot again
   with the "certonly" option. 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
If you're asked for email, please fill with your email, this would be used by Let's Encrypt to remind you when your certificate will expired soon. Also if you're asked wether redirect or not, please chose to redirect all the request from HTTP to HTTPS during the obtaining certificate using Certbot.
Once the Certbot has been finished, verify that the SSL/TLS has been configured properly by open up your favourite browser and navigate to example.caltic.tech.

Our domain now configured with SSL/TLS

Good job, now the communication on our server to the client has been secured. To make the configuration file of Nginx well organised, rollback our configuration file that we've backup before.
# cd /etc/nginx
cp nginx.conf.bak nginx.conf
Then create new configuration under conf.d.
# vim conf.d/example.caltic.tech.conf
server {
  server_name example.caltic.tech; # managed by Certbot
  root        /usr/share/nginx/html;

  # Load configuration files for the default server block.
  include /etc/nginx/default.d/*.conf;

  location / {
  }

  error_page 404 /404.html;
  location = /40x.html {
  }

  error_page 500 502 503 504 /50x.html;
  location = /50x.html {
  }

  listen [::]:443 ssl ipv6only=on; # managed by Certbot
  listen 443 ssl; # managed by Certbot
  ssl_certificate /etc/letsencrypt/live/example.caltic.tech/fullchain.pem; # managed by Certbot
  ssl_certificate_key /etc/letsencrypt/live/example.caltic.tech/privkey.pem; # managed by Certbot
  include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
  ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

server {
  if ($host = example.caltic.tech) {
      return 301 https://$host$request_uri;
  } # managed by Certbot

  listen       80;
  listen       [::]:80;
  server_name example.caltic.tech;
  return 404; # managed by Certbot
}
Save the file, test Nginx configuration and restart Nginx.
# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
# systemctl restart nginx
Congratulation. We have done to setup Nginx and setup SSL/TLS using Certbot.
Later more on this blog. Stay tune!

Comments

Popular Posts