Keywords: nginx | IPv6 Configuration | Port Binding Error
Abstract: This paper provides an in-depth analysis of the nginx [emerg] bind() to [::]:80 failed error, focusing on IPv6 configuration conflicts. Through detailed configuration examples and system diagnostic methods, it presents two effective solutions: using the ipv6only=on parameter to separate IPv4/IPv6 bindings, or unifying listen directives in IPv6 format. Combining Q&A data and reference materials, the article systematically explains port binding mechanisms, configuration syntax evolution, and best practices, offering comprehensive troubleshooting guidance for system administrators.
Problem Phenomenon and Diagnosis
When attempting to restart the nginx service, the system reports nginx: [emerg] bind() to [::]:80 failed (98: Address already in use) error. This indicates that port 80 is already occupied, but using lsof -i :80 and sudo fuser -k 80/tcp commands reveals no processes occupying the port. This contradiction typically stems from IPv6 configuration issues.
Root Cause Analysis
The [::]:80 in the error message represents IPv6 address format. In Linux systems, binding to an IPv6 TCP port automatically binds to the corresponding IPv4 port as well. When both listen 80; and listen [::]:80; directives exist in the nginx configuration file, the system attempts to bind to the same port twice, causing conflicts.
From a historical evolution perspective, early nginx versions allowed listen :80; syntax, but modern versions no longer support this format. Reference articles indicate that outdated configuration syntax is a common cause of binding failures.
Solution 1: Using ipv6only Parameter
The most recommended solution is to add the ipv6only=on parameter to the IPv6 listen directive:
server {
listen 80;
listen [::]:80 ipv6only=on;
server_name 127.0.0.1;
location / {
include uwsgi_params;
uwsgi_buffering off;
uwsgi_pass 127.0.0.1:8070;
}
}
The ipv6only=on parameter ensures that the IPv6 listen directive only binds to IPv6 ports and does not automatically bind to IPv4 ports, thus avoiding port conflicts. This method provides maximum configuration flexibility, especially suitable for complex server environments.
Solution 2: Unifying IPv6 Format
Another approach is to unify all listen directives in IPv6 format:
server {
listen [::]:80;
server_name 127.0.0.1;
location / {
include uwsgi_params;
uwsgi_buffering off;
uwsgi_pass 127.0.0.1:8070;
}
}
A single listen [::]:80; directive automatically binds to both IPv4 and IPv6 ports. This method results in cleaner code but requires ensuring all server blocks are modified accordingly to avoid configuration inconsistencies.
Other Potential Causes and Solutions
Beyond IPv6 configuration issues, other factors may cause port binding failures:
Apache Conflict: In some Ubuntu systems, Apache might be running in the background and occupying the port. Use sudo apachectl stop or sudo /etc/init.d/apache2 stop commands to stop Apache service.
Zombie nginx Processes: If nginx processes are not completely terminated, forced termination might be necessary:
sudo pkill -f nginx & wait $!
sudo systemctl start nginx
Configuration Verification and Testing
After modifying the configuration, use the sudo nginx -t command to test configuration file syntax. Once confirmed correct, restart the service using sudo systemctl restart nginx.
Verify port binding status:
sudo netstat -tulpn | grep :80
You should see the nginx process correctly bound to both IPv4 and IPv6 port 80.
Best Practice Recommendations
For production environments, Solution 1 (ipv6only=on) is recommended because:
- Provides explicit IPv4/IPv6 separation control
- Facilitates maintenance of complex multi-site configurations
- Supports address-specific listen directives
- Avoids risks associated with global configuration changes
On older systems like Ubuntu 12.04, ensure compatible nginx versions and configuration syntax. Regular system and package updates can prevent issues caused by version incompatibility.
Conclusion
The nginx: [emerg] bind() to [::]:80 failed error typically originates from IPv6 configuration conflicts. By correctly using the ipv6only=on parameter or unifying IPv6 listen formats, port binding issues can be effectively resolved. System administrators should deeply understand Linux network stack port binding mechanisms and establish standardized configuration management processes.