Add SSL to your AWS EC2 Node.js backend giving it a subdomain

Hosting is one of thran ine most haunting task for a developer. With all the expertie in development, you never know the kind of errors you might ran into by not properly deploying your code. Hosting can be tough especially with the lack of resources or the knowledge of it. We will try to get behind the hosting steps to figure out a way to secure your hosted EC2 backend along with giving it a subdomain. Let's start with it.

Problem Statement

Suppose that you have deployed your backend on an AWS instance at an IP xx.xx.xx.xx, port pp and the URL to access your backend is xx.xx.xx.xx:pp (Notice the http and not https in the URL, eg - http://192.168.0.0:2000 ). You have hosted your frontend at any other service with a URL example.com. Now, by convention http and https requests can't communicate in modern browsers until you accept your browser to go in insecure mode. So the problem is to convert xx.xx.xx.xx:pp into api.example.com because you want a more meaningful endpoint while coding ahead.

Assumptions and Pre-requisites

  1. Your backend and frontend is working perfectly on insecure channels like localhost.

  2. You have example.com domain bought from any of the service provider, we will use GoDaddy for this article, but any other domain provider will work just fine.

  3. Your backend is hosted on AWS EC2 instance. We are scoping it for EC2 in this article.

Solution Steps

  1. Install Nginx

    To get the SSL working, we need to first setup Nginx server. To do that open the terminal of aws, enter into ssh instance (ssh ubuntu@xx.xx.xx.xx) and install Nginx package

     sudo apt-get install nginx
    

    As Nginx registers itself under firewalls, you can check its installation by

     sudo ufw app list
    

    Output:

  2. Enable Nginx

    Allow the permissions to nginx full and openssh to act as firewalls. You can do this by writing

     sudo ufw allow 22/tcp
     sudo ufw allow 'nginx full'
    

    After installing Nginx, you must enable it. First of all, check if the firewall is enabled by typing

     sudo ufw status
    

    There are two cases - active/inactive.

    If ufw is inactive, enable the ufw by using

     sudo ufw enable
    

    If ufw is active, reload the ufw

     sudo ufw reload
    

    After this Check the status of ufw by

     sudo ufw status
    

    and it should output something like

  3. Install certbot

    After allowing nginx the access for your backend application, install certbot to generate a free SSL certifcate on your system.

     sudo apt install certbot python3-certbot-nginx
    
  4. Get the subdomain

    Now, go to the domain provider (GoDaddy in this case) and go to Manage DNS -> Add an A record -> Type your subdomain (Here, api) in Name column and Your Ip (i.e. xx.xx.xx.xx) without http in the value. As soon as the A record is created, you will have a subdomain api.example.com accessible to you.

  5. Generate Certificate

    Generate the SSL certificate using certbot on EC2 instance by typing the command

     sudo certbot --nginx -d api.example.com
    

    You will get an option of whether you want to redirect http calls or not, select 2 (i.e. to redirect http calls to https) and move ahead. You will have your certificate generated.

  6. Create Reverse Proxy

    After generating the certificate, the only thing left is to create a reverse proxy because nginx works at port 80 and your application might be working at any other port, say 8080 for example. So inside your ssh session go to the default sites-available file in nginx by typing

     sudo nano /etc/nginx/sites-available/default
    

    It opens the editor with the default file. Add the following piece of code in the file

     server{ 
     server_name api.example.com;
    
     location / {
                     # First attempt to serve request as file, then
                     # as directory, then fall back to displaying a 404.
                     proxy_pass http://xx.xx.xx.xx:8080;
             proxy_http_version 1.1;
             proxy_set_header Upgrade $http_upgrade;
             proxy_set_header Connection 'upgrade';
             proxy_set_header Host $host;
             proxy_cache_bypass $http_upgrade;
             }
     }
    

    Leave all other parts as it is. That's it, api.example.com should now be up and running.

    Note - There are multiple ways to achieve the SSL with subdomain and every method works just fine. I ahve explained something that I tried and worked.

    Thank you for reading through, looking forward to hear your feedback.