Skip to content

Instantly share code, notes, and snippets.

@dPacc
Last active March 17, 2024 16:55
Show Gist options
  • Save dPacc/5e0ddaeba0a54e18133b6606dcf49682 to your computer and use it in GitHub Desktop.
Save dPacc/5e0ddaeba0a54e18133b6606dcf49682 to your computer and use it in GitHub Desktop.
EC2 - ExpressJS Server Setup with Custom Domain

(PRE) Create a free tier ec2 Ubuntu machine

  • SSH into the server instance

  • Run as super user: sudo su

  • Run: apt-get update

(1) NPM and Nodejs installation: https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-up-node-on-ec2-instance.html

(2) Setting up the server

  • It is conventional to place the code in /var/www/APP_NAME, so mkdir -p /var/www/APP_NAME

  • Go into the dir cd /var/www/APP_NAME and clone the server repo git clone /var/www/APP_NAME

(3) Installing Nginx

  • Install nginx: apt-get install nginx

  • To verify if nginx is running, open the Public IPv4 address of your EC2 server

  • Go to /etc/nginx/sites-available

  • Run nano default and delete everything and paste the following

  • Let us first run it without SSL, paste the following

server {
  listen       80;
  server_name  _;

  location / {
    proxy_pass http://EC2_Private_IPv4:APP_PORT;
    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;
  }
}
  • Run systemctl restart nginx

  • Go to your Domain DNS Settings and create a CNAME with sub-domain with the value to be EC2 Public IPv4 DNS (ec2-2-3...)

  • Go to your /var/www/YOUR_APP, and run your server npm i and npm start

(4) Set up SSL certificate

  • Install snapd package manager: apt-get install snapd

  • Install certbot: snap install --classic certbot

  • sudo ln -s /snap/bin/certbot /usr/bin/certbot

  • Run the following to generate the certs: certbot -d SUB_DOMAIN.DOMAIN.com and go through the questions

  • Reconfigure NGINX to setup the certificates

  • Go to /etc/nginx/sites-available

  • Run nano default and delete everything and paste the following

server {
        listen 80;
        server_name SUB_DOMAIN.YOUR_APP.com;
        return 301 https://$host$request_uri;
}

server {
        listen 443 ssl;

        server_name SUB_DOMAIN.YOUR_APP.com;
        ssl_certificate /etc/letsencrypt/live/SUB_DOMAIN.YOUR_APP.com/fullchain.pem; # managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/SUB_DOMAIN.YOUR_APP.com/privkey.pem; # managed by Certbot

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';

location / {
        proxy_pass http://EC2_Private_IPv4:APP_PORT;
        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;
    }
}
  • Run systemctl restart nginx

  • Go to your /var/www/YOUR_APP, and run your server npm start

  • Open the domain you configured and it should be running the server

(5) Setting up PM2 (Ref: https://www.digitalocean.com/community/tutorials/how-to-set-up-a-node-js-application-for-production-on-ubuntu-20-04)

  • Install build essentials: apt install build-essential

  • Install pm2: npm install pm2@latest -g

  • Start the server: pm2 start server.js

@dPacc
Copy link
Author

dPacc commented Oct 24, 2023

The IP address ::ffff:172.31.80.91 appears to be a private IPv4-mapped IPv6 address. When you see this, it usually indicates that you're running your application in a networked environment, such as a cloud service, behind a load balancer or reverse proxy. The address you're seeing is likely the internal address of the proxy or load balancer forwarding the requests to your application.

Here are some ways to tackle this issue:

X-Forwarded-For Header

You can check if the X-Forwarded-For HTTP header is being set by your reverse proxy. This header contains the original IP address of the client making the request.

To read the first IP from this header in your keyGenerator, you can do:

keyGenerator: (req, res) => {
  const forwarded = req.headers['x-forwarded-for'];
  const ip = forwarded ? forwarded.split(/, /)[0] : req.ip;
  console.log("Client IP:", ip);
  return req.user ? req.user._id : ip;
}

Reverse Proxy Configuration

Ensure that your reverse proxy is configured to pass along the original client IP. Below are some example configurations for popular reverse proxies:

  • For Nginx, you can use:

    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  • For Apache, you can use:

    ProxyPreserveHost On
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/

If you're running in a cloud environment, also check if there's a specific way to capture the client IP for your specific service.

Trust Proxy Setting

You've already set app.set("trust proxy", 1); which is good. This tells Express to trust the first proxy it encounters, which should allow req.ip to correctly reflect the client’s IP address when behind a proxy.

Make sure this setting is before your rate limiter middleware.

Multiple Proxies

If there are multiple proxies involved, you can set 'trust proxy' to the number of proxies in the chain, or to true to trust all proxies. However, be cautious when setting it to true as it could potentially lead to security risks.

app.set("trust proxy", true);  // Be cautious using this

By properly setting one or more of these options, you should be able to capture the original client IP address.

@dPacc
Copy link
Author

dPacc commented Mar 17, 2024

In house use private IP of the server

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment