🧠 What is a Reverse Proxy?

A reverse proxy is like a smart middleman that sits in front of your app/server, receives requests from clients (like a browser), and then forwards those requests to your backend service (like your Node.js app running on port 5000).


πŸ” Without vs. With Reverse Proxy

❌ Without Reverse Proxy:
User β†’ http://3.7.70.216:5000 β†’ Node.js (direct on port 5000)
You have to expose port 5000, which is non-standard.

βœ… With Reverse Proxy (Nginx):
User β†’ http://3.7.70.216 β†’ Nginx (on port 80) β†’ Node.js (on 5000 internally)
Only port 80 (standard HTTP) is open to the public, but internally Nginx passes traffic to your Node.js app on port 5000.


πŸš€ Why use a Reverse Proxy?

BenefitExplanation
πŸ”’ SecurityHide your backend ports (like 5000, 3000) from the public.
🌐 Clean URLsAccess app via http://example.com instead of :5000.
πŸ” Load BalancingNginx can distribute traffic to multiple app instances.
⚑ CachingIt can cache static assets to improve performance.
πŸ”„ SSL TerminationNginx handles HTTPS so your app can stay HTTP internally.

πŸ› οΈ How to Set Up Nginx as a Reverse Proxy for Node.js

1️⃣ Install Nginx on EC2

sudo yum install nginx -y    # For Amazon Linux
sudo systemctl start nginx
sudo systemctl enable nginx

2️⃣ Edit the Config

sudo nano /etc/nginx/nginx.conf

Add this inside the http {} block (or use a site config file):

server {
    listen 80;
    server_name _;
 
    location / {
        proxy_pass http://localhost:5000;
        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;
    }
}

3️⃣ Restart Nginx

sudo systemctl restart nginx

4️⃣ Access Your App

Open your browser and go to:
πŸ‘‰ http://your-public-ip


πŸ§ͺ Bonus: Add HTTPS with Let’s Encrypt

You can add SSL/TLS with Let’s Encrypt for free β€” so Nginx will serve secure traffic (https://) πŸ”’


πŸ” SSL/TLS with Let’s Encrypt + Nginx

🧠 What is SSL/TLS?

  • SSL/TLS is what makes the https:// in your URL secure.
  • It encrypts data between the browser and your server, preventing eavesdropping.

Example:
http://yourdomain.com ❌ (Not secure)
https://yourdomain.com βœ… (Secure with padlock)


πŸ› οΈ What is Let’s Encrypt?

  • It’s a free, automated, and open certificate authority.
  • It provides an SSL certificate that browsers trust.
  • You can use it with Certbot, a tool that auto-generates and installs the certificate with Nginx.

βœ… Requirements

1️⃣ A domain name (e.g., myapp.omdev.in)
2️⃣ DNS A record pointing to your EC2 public IP
3️⃣ Nginx installed on EC2
4️⃣ Ports 80 and 443 open in EC2 Security Group


πŸš€ Steps to Set Up HTTPS with Let’s Encrypt (Certbot + Nginx)

1️⃣ Install Certbot and Nginx Plugin

For Amazon Linux 2:

sudo yum install -y epel-release
sudo yum install -y certbot python2-certbot-nginx

For Ubuntu/Debian:

sudo apt update
sudo apt install certbot python3-certbot-nginx

2️⃣ Verify Nginx Config

Make sure you have a server block like this:

server {
    listen 80;
    server_name yourdomain.com;
 
    location / {
        proxy_pass http://localhost:5000;
    }
}

3️⃣ Run Certbot

sudo certbot --nginx

It will:

  • Ask for your domain name (e.g., myapp.omdev.in)
  • Generate an SSL certificate
  • Update Nginx config
  • Reload Nginx automatically βœ…

4️⃣ Test HTTPS

Visit: https://yourdomain.com πŸŽ‰
You’ll see the πŸ”’ padlock!


πŸ” Auto-Renewal

Let’s Encrypt certificates expire every 90 days, but Certbot sets up a cron job to auto-renew.

Test renewal manually:

sudo certbot renew --dry-run

πŸ€” What if I Don’t Have a Domain?

Let’s Encrypt won’t work with a public IP (e.g., http://3.7.70.216) β€” it needs a domain name.

You can buy one (e.g., Namecheap, GoDaddy) or get a free one from Freenom.


🌍 Using HTTPS Without a Domain Name

πŸ”’ Can You Use HTTPS with Just a Public IP?

βœ… Yes, but…
❌ Not with Let’s Encrypt


❌ Why Let’s Encrypt Doesn’t Work with IPs

  • It requires a domain for validation.
  • The HTTP-01 challenge checks DNS records β€” which doesn’t work for raw IPs.

βœ… Option 1: Use a Self-Signed Certificate

Good for testing, but browsers will show ⚠️ β€œYour connection is not private”.

# Generate a private key and cert
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout selfsigned.key -out selfsigned.crt

Update your Nginx config:

server {
    listen 443 ssl;
    server_name 3.7.70.216;
 
    ssl_certificate /path/to/selfsigned.crt;
    ssl_certificate_key /path/to/selfsigned.key;
 
    location / {
        proxy_pass http://localhost:5000;
    }
}

Then reload Nginx:

sudo nginx -t
sudo systemctl reload nginx

Access via:
https://3.7.70.216 ⚠️ (browser warning expected)


βœ… Option 2: Buy a Paid IP-Based Certificate

  • Some CAs (like DigiCert) support this.
  • Works for static, dedicated IPs only.
  • Costly β€” not ideal for simple setups.

Use a free/cheap domain and Let’s Encrypt:

Add an A record β†’ point to EC2 IP β†’ get HTTPS for free. βœ…


πŸ’‘ TL;DR

MethodHTTPSBrowser WarningCostBest Use
Let’s Encrypt + IP❌❌FreeNot possible
Self-Signed Certβœ…βš οΈFreeTesting
Paid Cert (IP-based)βœ…βœ…ExpensiveSpecial cases
Domain + Let’s Encryptβœ…βœ…Free / CheapRecommended βœ