DEV Community

Madhav Pandey
Madhav Pandey

Posted on

Step-by-Step Guide: Hosting a Node.js App on AWS EC2 with Domain Name and SSL Certificate

Host your nodejs application on AWS EC2 instance with Domain name

blog-pic

This blog post is about hosting your nodejs application on AWS EC2 instance with domain name and secured it with the help of certbot. Let's get started.

  1. Create Ec2 instalce by choosing linux 2s

  2. Leave everything default and click launch instance

  3. Go to instances and click your instace and click on connect.
    Then, you will see option to connect to instance. If you want to access instance terminal from web-browser you can click on Connect button of EC2 Instance Connect. Or, you can connect through SSH client. For that click on SSH client tab to see what steps to take.
    As per instructions provided here, you need to open SSH client such as linux terminal or git bash.
    Go to the folder where private key .pem file is located and run following command which will give read only permision to the file

  chmod 400 prevate-key-name.pem 
Enter fullscreen mode Exit fullscreen mode

Then, you are ready to connect instance using its public DNS or public ip address by following command

 ssh -i "node-server-key.pem" ec2-user@13.54.206.174 
Enter fullscreen mode Exit fullscreen mode

Here, private key name is node-server-key, user is ec2-user and public id address is 13.54.206.174. You can use public DNS as well in place of public address

 ssh -i "node-server-key.pem" ec2-user@ec2-13-54-206-174.ap-southeast-2.compute.amazonaws.com              
Enter fullscreen mode Exit fullscreen mode

After that you can have access to terminal through SSH client. Once you have access to the terminal,type following command

 sudo yum install -y gcc-c++ make 
Enter fullscreen mode Exit fullscreen mode

then, it install nodejs by typing following command
Type following command

 sudo yum install -y nodejs  
Enter fullscreen mode Exit fullscreen mode

To check the version of nodejs run
node -v command

  1. Now you can clone node app from your github. Once the repo is downloaded go to that folder and run npm instal which will install all the dependency. For environmental variables, you can create a new directory and create a .env file there. You can put all environmental variables in that file:
  touch /var/app/env/.env 
Enter fullscreen mode Exit fullscreen mode

Edit the file by running nano /var/app/env/.env
Save the .env file and we need dotenv package to load those environmental variables. For that run following command

  npm install dotenv 
Enter fullscreen mode Exit fullscreen mode

Once it installed, in node.js application, we need config dotenv package on top of main application file.

 require('dotenv').config({path: 'var/app/env/.env'}) 
Enter fullscreen mode Exit fullscreen mode

For the access type your publicIP:portNum. In my case it is http://13.54.206.174:3000/

  1. If you want to run your sever in the background you can use pm2 which is a process manager for node.js application. pm2 can handle to start, restart and stop the server and log managmement. To install pm2 run following command
 npm install pm2 -g 
Enter fullscreen mode Exit fullscreen mode

To start the server use command:

 pm2 start app.js 
Enter fullscreen mode Exit fullscreen mode

pm2-start

To verify your server is running run following command

 pm2 list 
Enter fullscreen mode Exit fullscreen mode

This will display a list of all processes managed by pm2

To stop the server

 pm2 stop app.js 
Enter fullscreen mode Exit fullscreen mode
  1. If you have a domain name and you want to use it, you need to install nginx which is a web server by following command
 sudo yum install nginx 
Enter fullscreen mode Exit fullscreen mode

To run nginx run the command sudo systemctl start nginx and visit EC2 instance public IP address in the browser. You will see Nginx default welcome page.
Once it installed, you need to configure Nginx to act as a reverse proxy for the application. Open the configuration file by following command

 sudo nano /etc/nginx/nginx.conf 
Enter fullscreen mode Exit fullscreen mode

Then, edit the nginx.conf file as following:



 http { 
     listen 80; 
     server_name pblog.online www.pblog.online; 

     location / { 
       proxy_pass http://localhost:8000; 
 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; 
     } 
 } 



Enter fullscreen mode Exit fullscreen mode

Replace pblog.online with you domain name.
Once the file edited, we need to check if it is validate or not. For that run the following command:

 sudo nginx -t 

 nginx: the configuration file /etc/nginx/nginx.conf syntax is ok 
 nginx: configuration file /etc/nginx/nginx.conf test is successful 

Enter fullscreen mode Exit fullscreen mode

If the test is successful, you can reload the nginx by the command sudo nginx -s reload.
You can check the nginx status by following command as well

 sudo systemctl status nginx 

 ● nginx.service - The nginx HTTP and reverse proxy server 
      Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; preset: disabled) 
      Active: active (running) since Tue 2023-05-16 03:29:05 UTC; 43min ago 


Enter fullscreen mode Exit fullscreen mode

## Add Domain Name
To add a custom domain name, first you need to assign Elastic IP address for you EC2 instance. You can do that from EC2 Dashbord, there you will elastic ip under Network & Security. Once you have assigned elastic ip address go to your domain name provider account and find DNS Records section. There we need to add new record. So, click on Add new record option. Select record type A, in Name section type www and value will be your elastic IP address and save it.

DNS record

Now, hit your domain URL in the browser. It will take some time but you can visit your application running on EC2 instance by entering your domain name.
url

But the connection is not secured. To make it secured we need to add SSL certificate. We can do it for free with the help of Certbot. Run following commands to install certbot:

 sudo yum install python3 python3-venv libaugeas0 
Enter fullscreen mode Exit fullscreen mode
    sudo /opt/certbot/bin/pip install --upgrade pip 
    ```





    ``` 
    sudo /opt/certbot/bin/pip install certbot certbot-nginx 
    ```





    ``` 
    sudo ln -s /opt/certbot/bin/certbot /usr/bin/certbot 
    ```





    ``` 
    sudo python3 -m venv /opt/certbot/ 
    ```



    Once it's done run the following command to get `ssl` certificate for you domain



    ``` 
    sudo certbot --nginx -d pblog.online -d www.pblog.online 
    ```


 Here, replace `pblog.online` with your own domain name. 

 `certbot` will ask you to confirm your domain name and add `ssl` certificate to your domain name. It will change configuration of `nginx.conf` file as well. Once the certificated is added `nginx.conf` file looks like this:


Enter fullscreen mode Exit fullscreen mode
 server { 
 server_name pblog.online www.pblog.online; 

     root         /usr/share/nginx/html; 

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

     error_page 404 /404.html; 
     location / { 
Enter fullscreen mode Exit fullscreen mode

proxy_pass http://localhost:8000;
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;
}

     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/pblog.online/fullchain.pem; # managed by Certbot 
 ssl_certificate_key /etc/letsencrypt/live/pblog.online/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 
Enter fullscreen mode Exit fullscreen mode

}

 server { 
 if ($host = www.pblog.online) { 
     return 301 https://$host$request_uri; 
 } # managed by Certbot 


 if ($host = pblog.online) { 
     return 301 https://$host$request_uri; 
 } # managed by Certbot 

     listen 80; 
     listen [::]:80; 

    server_name pblog.online www.pblog.online; 
 return 404; # managed by Certbot 
Enter fullscreen mode Exit fullscreen mode

}



 If you look at it closely, now our app is running on port 443 which is `https` connection. So, we have to make sure that port 443 is allowed in our `ec2` instance security groups. If your `ec2` instance security groups does not have `https` port enabled you can add new rule by clicking `add rule` button and select type `HTTPS`. 

 ![security-groups](https://images2.imgbox.com/d2/e0/4FjSUpJB_o.png) 

 Now, visit your site by entering `https://www.YOUR_DOMAIN_NAME`.You will be able to see your site which is now secure with ssl certificate. 

 ![ssl-certifite](https://images2.imgbox.com/5c/20/vBhFpNkr_o.png) 

 This way, you can run your `nodejs` app on `ec2` instance with custom domain name.  
 #### Thank you for reading :)
Enter fullscreen mode Exit fullscreen mode

Top comments (0)