When attempting to run a Node.js application on port 80, developers often encounter the frustrating EACCES error. This isn't necessarily because the port is occupied - as your netstat
output shows no process listening on port 80 - but rather due to Linux's security measures.
The key error message is:
Error: listen EACCES
at errnoException (net.js:904:11)
In Unix-like systems, ports below 1024 are considered "privileged ports" and require root access. This is a security feature preventing regular users from running services on these standard ports.
1. Running Node as Root (Not Recommended)
While simplest, running Node with root privileges poses security risks:
sudo node app.js
2. Using Port Forwarding with Authbind
A safer alternative is configuring authbind to allow your user account to bind to low ports:
sudo apt-get install authbind
sudo touch /etc/authbind/byport/80
sudo chown youruser:youruser /etc/authbind/byport/80
sudo chmod 755 /etc/authbind/byport/80
Then run your app with:
authbind --deep node app.js
3. Reverse Proxy with Nginx (Recommended)
The most robust solution is using Nginx as a reverse proxy:
server {
listen 80;
server_name yourdomain.com;
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_cache_bypass $http_upgrade;
}
}
To thoroughly check for port conflicts:
sudo lsof -i :80
sudo netstat -tulnp | grep :80
sudo ss -tulnp | grep :80
On cloud instances, check security groups/iptables:
sudo iptables -L -n -v
sudo ufw status
If you must use port 80 temporarily for testing, you can forward it:
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 3000
For production deployments with port 80 access:
[Unit]
Description=Node.js Service
After=network.target
[Service]
ExecStart=/usr/bin/node /path/to/your/app.js
User=root
Group=root
Restart=always
[Install]
WantedBy=multi-user.target
The error Error: listen EACCES
you're encountering is a permission-related issue when trying to bind Node.js to port 80. This is fundamentally a Linux security feature - ports below 1024 are considered privileged ports that require root access.
// Typical error output
events.js:72
throw er; // Unhandled 'error' event
^
Error: listen EACCES
at errnoException (net.js:904:11)
at Server._listen2 (net.js:1023:19)
Your netstat -an
output shows no service listening on port 80, but let's verify thoroughly:
// Check all processes using port 80
sudo lsof -i :80
// Alternative command showing process IDs
sudo ss -tulnp | grep ':80'
If these commands return empty, it confirms port 80 isn't being blocked by another process but rather by system permissions.
Option 1: Run Node as Root (Not Recommended)
While technically possible, running Node.js with root privileges poses security risks:
sudo node app.js // Not recommended for production
Option 2: Port Forwarding with iptables
A safer approach is to run Node on a high port and forward:
// Run your app on port 3000
const port = process.env.PORT || 3000;
app.listen(port);
// Then set up forwarding (run as root)
sudo iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3000
sudo iptables-save > /etc/iptables.rules
Option 3: Use authbind (Recommended)
authbind allows specific users to bind to privileged ports:
// Install authbind
sudo apt-get install authbind
// Configure for port 80
sudo touch /etc/authbind/byport/80
sudo chown youruser:youruser /etc/authbind/byport/80
sudo chmod 755 /etc/authbind/byport/80
// Run your app
authbind --deep node app.js
Option 4: Reverse Proxy with Nginx
The most production-ready solution:
// Sample nginx configuration
server {
listen 80;
server_name yourdomain.com;
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_cache_bypass $http_upgrade;
}
}
After implementing any solution, verify it works:
curl -I http://localhost
netstat -tulnp | grep -E '80|3000'
Remember to:
- Configure your firewall to allow port 80 traffic
- Consider using HTTPS (port 443) for production
- Use process managers like PM2 for Node.js applications