The error message bind() to 0.0.0.0:80 failed (48: Address already in use)
indicates that Nginx cannot bind to port 80 because another process has already claimed it. This commonly occurs when:
- Another web server (Apache, httpd) is running
- Previous Nginx instances weren't properly terminated
- MacOS system services are using the port
Use these terminal commands to identify the offending process:
sudo lsof -i :80
sudo lsof -iTCP:80 -sTCP:LISTEN
Sample output might reveal:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
httpd 1234 root 4u IPv6 0xffff800123456789 0t0 TCP *:http (LISTEN)
MacOS has several native services that might interfere:
# Check for Apple-specific services
sudo launchctl list | grep -i apache
sudo launchctl list | grep -i http
First try gracefully stopping the service:
sudo apachectl stop # For Apache
sudo nginx -s stop # For Nginx
If that fails, terminate the process forcefully:
sudo kill -9 [PID] # Replace [PID] with actual process ID
sudo killall httpd # Alternative approach
Modify Nginx configuration to avoid conflicts:
# /usr/local/etc/nginx/nginx.conf
server {
listen 80 reuseport; # Added reuseprot option
# ... rest of config
}
For development environments, consider using higher ports:
server {
listen 8080; # Alternative port
server_name localhost;
# ... rest of config
}
Create a bash script to handle port conflicts:
#!/bin/bash
PORT=80
PID=$(lsof -ti :$PORT)
if [ ! -z "$PID" ]; then
echo "Killing process $PID using port $PORT"
kill -9 $PID
fi
nginx
Use these diagnostic commands:
sudo nginx -t # Test configuration
sudo nginx -T # Show full configuration
sudo nginx -s reload # Reload configuration
journalctl -u nginx -f # View logs (systemd systems)
When Nginx fails to bind to port 80, it's typically because another process has already claimed that privileged port. On macOS, this could be caused by:
- Apache running in the background
- Other web servers like Microsoft IIS
- Docker containers using port 80
- macOS built-in services
First, let's definitively check what's using port 80:
sudo lsof -i :80
sudo netstat -anp tcp | grep LISTEN
For more detailed process information:
sudo lsof -i :80 -sTCP:LISTEN -nP
If the offender is Apache (common in macOS):
sudo apachectl stop
sudo launchctl unload -w /System/Library/LaunchDaemons/org.apache.httpd.plist
For lingering Nginx processes:
sudo pkill -f nginx
sudo nginx -s stop
If you can't free port 80, consider running Nginx on a different port temporarily:
# In nginx.conf
server {
listen 8080;
server_name localhost;
...
}
For production setups, create a proper launchd plist to prevent conflicts:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>nginx</string>
<key>ProgramArguments</key>
<array>
<string>/opt/local/sbin/nginx</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
Save to /Library/LaunchDaemons/nginx.plist
and load with:
sudo launchctl load -w /Library/LaunchDaemons/nginx.plist
After making changes, verify Nginx is running properly:
sudo nginx -t
sudo nginx
ps aux | grep nginx
curl -I http://localhost