# Comprehensive Guide: Hosting and Deploying Multiple Node Applications on AWS EC2 with Step-by-Step Instructions

**Introduction:**  
Setting up and hosting a Node server on AWS EC2 can be a powerful and flexible solution for deploying your web applications. In this step-by-step guide, we will cover the entire process, from creating an EC2 instance to configuring Nginx with SSL certification for your domain. Let's dive into the details.

**Creating an EC2 Instance:**

* Log in to your AWS Management Console.
    
* Navigate to the EC2 dashboard and click on "Launch Instance."
    
* Choose an Amazon Machine Image (AMI), select an instance type, configure instance details, add storage, configure security groups, and review your instance details.
    
* Click "Launch," and select an existing key pair or create a new one. Download the .pem file, as you'll need it to connect to the EC2 instance later.
    

**Connecting EC2 Instance with Elastic IP:**

* Allocate an Elastic IP from the AWS console.
    
* Associate the Elastic IP with your EC2 instance to ensure a static IP address for your server. This is beneficial for maintaining a consistent connection, especially in a production environment.
    

**Connecting to EC2 Instance using .pem file:**

* Open your terminal and navigate to the directory where the .pem file is located.
    
* Use the following command to connect to your EC2 instance:  
    `ssh -i "your-key.pem" ec2-user@your-elastic-ip`
    

**Installing Git, NVM, and Setting Up Your Node.js Application:**

* Now that you're connected, it's time to prepare your environment:  
    `sudo yum update -y`  
    `sudo yum install git -y`  
    `curl -o-` [`https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh`](https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh) `| bash source ~/.bashrc`
    
    `nvm install node`
    
* Clone your Node.js server repository, install dependencies, set up the `.env` file, and start your application using PM2:  
    `git clone cd your-app-directory   npm install   cp .env.example .env   pm2 start your-app.js`
    

**Creating an Nginx Server:**

* Install Nginx:  
    `sudo amazon-linux-extras install nginx1.12   sudo service nginx start`
    

**Nginx Configuration for HTTP:**

* Edit the Nginx configuration file:  
    `sudo nano /etc/nginx/nginx.conf`
    
* Add server block:  
    `server {`  
    `listen 80;`  
    `server_name` [`your-domain.com`](http://your-domain.com) [`www.your-domain.com`](http://www.your-domain.com)`;`
    
    `location / {`  
    `proxy_pass` [`http://127.0.0.1:8000`](http://127.0.0.1:8000)`;`  
    `# Additional proxy configurations }`  
    `}`
    

**Configuring SSL with Let's Encrypt:**

* Install Certbot and get SSL certificate:  
    `sudo amazon-linux-extras install epel`  
    `sudo yum install certbot-nginx -y`
    
    `sudo certbot --nginx -d` [`your-domain.com`](http://your-domain.com) `-d` [`www.your-domain.com`](http://www.your-domain.com)
    
* Update Nginx configuration to include SSL:  
    `listen [::]:443 ssl ipv6only=on; # managed by Certbot`  
    `listen 443 ssl; # managed by Certbot`  
    `ssl_certificate /etc/letsencrypt/live/`[`dev.usampac.org/fullchain.pem`](http://dev.usampac.org/fullchain.pem)`; # managed by Certbot`  
    `ssl_certificate_key /etc/letsencrypt/live/`[`dev.usampac.org/privkey.pem`](http://dev.usampac.org/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 =` [`dev.usampac.org`](http://dev.usampac.org)`) {`  
    `return 301` [`https://$host$request_uri`](https://$host$request_uri)`;`  
    `} # managed by Certbot`
    
    `listen 80;`  
    `listen [::]:80;`  
    `listen 443;`  
    `listen [::]:443;`  
    `server_name` [`dev.usampac.org`](http://dev.usampac.org)`;`  
    `return 404; # managed by Certbot`
    
    `}`
    

**Setting Up Nginx Routes for Multiple Servers:**

* Add location blocks for different routes:  
    `location /api {`  
    `rewrite ^/api(/.*)$ $1 break;`  
    `proxy_pass` [`http://127.0.0.1:8000`](http://127.0.0.1:8000)`;`  
    `# Additional proxy configurations`  
    `}`
    
    `location /production/api {`  
    `rewrite ^/production/api(/.*)$ $1 break;`  
    `proxy_pass` [`http://127.0.0.1:8020`](http://127.0.0.1:8020)`;`  
    `# Additional proxy configurations`  
    `}`  
    Putting it all together, if a request comes in with a URL path like `/api/some/endpoint`, the `rewrite` directive will modify it to `/some/endpoint` using the captured part after `/api/`. This adjusted URL is then passed to the proxied server specified in `proxy_pass`.
    

**Enabling Ports in AWS Security Group:**  
In your EC2 dashboard, navigate to the security group associated with your instance and add inbound rules for ports 80 and 443.

<mark>Congratulations! You've successfully hosted your Node.js server on AWS EC2, secured it with SSL, and configured Nginx for optimal performance. This guide provides a solid foundation for deploying and maintaining web applications in a scalable and secure environment. Happy coding!</mark>

Sample Nginx.conf file, with ssl certificate.

```nginx
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /run/nginx.pid;

include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    keepalive_timeout   65;
    types_hash_max_size 4096;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    include /etc/nginx/conf.d/*.conf;

    server {
        server_name  example.com; 
        index   index.html;

        include /etc/nginx/default.d/*.conf;

        location /api {
            rewrite ^/api(/.*)$ $1 break;
            proxy_pass http://127.0.0.1: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;
        }

        location /production/api {
            rewrite ^/production/api(/.*)$ $1 break;
            proxy_pass http://127.0.0.1:8020;
            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;
        }

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

    server {
        if ($host = example.com) {
            return 301 https://$host$request_uri;
        }

        listen       80;
        listen       [::]:80;
        listen       443;
        listen       [::]:443;
        server_name  example.com;
        return 404;
    }
}
```
