Configuring Nginx as a Reverse Proxy on EC2 Routing Traffic to Node.js
Learn how to configure Nginx as a reverse proxy on AWS EC2 to route incoming traffic to your Node.js application, including WebSocket support for Socket.io.
Configuring Nginx as a Reverse Proxy on EC2
Nginx sits in front of your Node.js app and handles incoming HTTP requests. It routes traffic to the Node.js process running on port 3000, provides SSL termination, and supports WebSockets for Socket.io.
Why Use Nginx as a Reverse Proxy?
- Port management Nginx on port 80/443, Node.js on port 3000 (no need to run Node as root)
- SSL termination Nginx handles HTTPS, Node.js handles plain HTTP
- Static files Nginx serves static files faster than Node.js
- Load balancing Distribute traffic across multiple Node.js instances
- WebSocket support Proxy WebSocket connections for Socket.io
- Gzip compression Compress responses before sending to client
Step 1: Create the Nginx Configuration
sudo nano /etc/nginx/sites-available/devtinder
Add this configuration:
server { listen 80; server_name yourdomain.com; # or your EC2 public IP # API routes location / { proxy_pass http://localhost:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_cache_bypass $http_upgrade; } # Socket.io WebSocket support location /socket.io/ { proxy_pass http://localhost:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
Step 2: Enable the Configuration
# Create a symbolic link to sites-enabled sudo ln -s /etc/nginx/sites-available/devtinder /etc/nginx/sites-enabled/ # Remove the default site sudo rm /etc/nginx/sites-enabled/default # Test the configuration sudo nginx -t
You should see:
nginx: configuration file /etc/nginx/nginx.conf test is successful
Step 3: Restart Nginx
sudo systemctl restart nginx
Step 4: Verify
From your local machine:
curl http://your-ec2-public-ip/api/health
This should return your API response. Nginx is now proxying traffic to the Node.js app on port 3000.
Key Configuration Explained
proxy_pass Tells Nginx where to forward requests (the Node.js app on port 3000).
proxy_http_version 1.1 Uses HTTP/1.1 for the proxy connection, required for WebSockets.
Upgrade and Connection headers These are critical for WebSocket support. Without them, Socket.io won't work.
X-Real-IP and X-Forwarded-For Pass the client's real IP to Node.js. Without these, Node.js sees Nginx's IP (127.0.0.1) instead of the client's IP.
X-Forwarded-Proto Passes the original protocol (http or https) to Node.js. Useful for generating correct redirect URLs.
Gzip Compression
Add gzip compression to reduce response sizes:
server { # ... existing config ... gzip on; gzip_types text/plain application/json application/javascript text/css; gzip_min_length 1000; }
Rate Limiting (Optional)
Protect your API from abuse:
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s; server { location / { limit_req zone=api burst=20 nodelay; proxy_pass http://localhost:3000; # ... other settings ... } }
This allows 10 requests per second with a burst of 20.
The Takeaway
Configuring Nginx as a reverse proxy involves creating a server block that listens on port 80, proxies requests to localhost:3000 (Node.js), and includes the Upgrade and Connection headers for WebSocket support. Enable the configuration with a symbolic link, test with nginx -t, and restart. The key headers (X-Real-IP, X-Forwarded-For, X-Forwarded-Proto) pass client information to the Node.js app.
Nginx handles port management (80/443 while Node.js uses 3000), SSL termination, static file serving, load balancing, WebSocket proxying for Socket.io, and gzip compression. Node.js doesn't need to run as root or handle SSL directly.
Add a location /socket.io/ block with proxy_pass, proxy_http_version 1.1, and the Upgrade and Connection headers set to 'upgrade'. These headers are critical without them, WebSocket connections will fail.
They pass the client's real IP address to the Node.js app. Without them, Node.js sees Nginx's IP (127.0.0.1) instead of the actual client IP, which breaks IP-based features like rate limiting and logging.
Create a file in /etc/nginx/sites-available/, create a symbolic link to /etc/nginx/sites-enabled/, remove the default site, test with sudo nginx -t, and restart with sudo systemctl restart nginx.
Define a limit_req_zone in the http block (limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s), then add limit_req zone=api burst=20 nodelay inside the location block. This allows 10 requests per second with a burst of 20.
Ready to master Node.js completely?
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.
Master Node.js
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course.

