When setting up a Node.js web server on an Ubuntu EC2 instance, you might encounter the frustrating "Connection refused" error despite your server appearing to run correctly. This typically indicates a networking issue between your client and server.
First, confirm your Node.js server is actually running and listening on the correct port. SSH into your EC2 instance and run:
netstat -tulnp | grep node
# or alternatively:
ss -tulnp | grep node
You should see output similar to:
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 1234/node
Amazon EC2 uses security groups as virtual firewalls. Ensure you've:
- Opened port 80 (HTTP) and 8080 in your security group
- Allowed traffic from 0.0.0.0/0 (or your specific IP range)
You can verify this in the AWS Console under EC2 > Security Groups.
From within your EC2 instance, test if the server responds locally:
curl http://localhost:8080
If this works but external connections fail, the issue is definitely network-related.
Your iptables port forwarding command needs adjustment. Try this instead:
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
sudo iptables -A INPUT -p tcp --dport 8080 -j ACCEPT
To make these changes persistent:
sudo apt-get install iptables-persistent
sudo netfilter-persistent save
Modify your Node.js server to listen on all network interfaces:
const http = require('http');
const server = http.createServer((req, res) => {
res.end('Hello World');
});
server.listen(8080, '0.0.0.0', () => {
console.log('Server running on port 8080');
});
Ubuntu might be using UFW (Uncomplicated Firewall). Check its status:
sudo ufw status
If active, allow the necessary ports:
sudo ufw allow 80/tcp
sudo ufw allow 8080/tcp
After making these changes:
- Restart your Node.js server
- Check all firewall rules are properly configured
- Test from both local and external networks
Remember that AWS EC2 instances might take a few minutes for network changes to propagate completely.
When setting up a Node.js server on an EC2 Ubuntu instance, the "Connection refused" error typically indicates one of these fundamental issues:
- Node.js server isn't bound to the correct network interface
- Port forwarding rules aren't properly configured
- Security groups or local firewall are blocking traffic
- The application isn't actually listening on the expected port
First, ensure your Node.js application is properly configured to listen on all network interfaces (0.0.0.0) rather than just localhost:
const http = require('http');
const port = 8080;
const server = http.createServer((req, res) => {
res.end('Hello from Node.js!');
});
// Critical: Bind to 0.0.0.0 instead of 127.0.0.1
server.listen(port, '0.0.0.0', () => {
console.log(Server running at http://0.0.0.0:${port}/);
});
Check your AWS security group settings:
1. Inbound rules should allow:
- HTTP (port 80) from 0.0.0.0/0
- Custom TCP (port 8080) from 0.0.0.0/0
2. Outbound rules should allow all traffic
The current iptables rules might need adjustment. Here's a more comprehensive setup:
# Flush existing rules
iptables -F
iptables -t nat -F
# Allow established connections
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow loopback
iptables -A INPUT -i lo -j ACCEPT
# Port forwarding from 80 to 8080
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
# Allow HTTP/HTTPS
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 8080 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# Default policies
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Save rules (Ubuntu specific)
iptables-save > /etc/iptables.rules
Run these commands to verify your setup:
# Check listening ports
sudo netstat -tulnp | grep node
# Check iptables rules
sudo iptables -L -n -v
sudo iptables -t nat -L -n -v
# Test connectivity from another machine
telnet your-ec2-ip 80
telnet your-ec2-ip 8080
# Check AWS security groups
aws ec2 describe-security-groups --group-ids your-group-id
For production environments, consider using nginx:
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://localhost:8080;
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;
}
}
After making these changes, test with:
curl -v http://localhost:8080
curl -v http://your-ec2-ip:8080
curl -v http://your-ec2-ip
Each command should return your Node.js server response without connection refused errors.