apt-get upgrade nginx adds ipv6 by default

and what happens when a merge goes bad

Thomas V.

2 minute read

I discovered this when I ran the latest server update for the NGINX PPA on Ubuntu, which includes a new default configuration file.

Instead of choosing to overwrite or discard the new config, I merged the new one with my old and when I restarted NGINX I got an address already in use error:

nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)
nginx: [emerg] still could not bind()

This is because the latest NGINX update adds IPv6 support by default

When I opened up the server’s configuration file, I had:

server {
  listen 80; # listen for ipv4 connections
  listen [::]:80 default_server; # listen for ipv4 and ipv6 connections

I did that for a few hours but the fact that IPv6 has already been rolled out bothered me enough that I had to revisit the problem. Someone in #nginx on freenode pointed me to the manual page where I came across this:

In Linux by default any IPv6 TCP socket also accepts IPv4 traffic using the IPv4 to IPv6 mapped address format, i.e., ::ffff:. E.g., ::ffff: maps the IPv4 address to an IPv6 address.

When you enable the address [::]:80, binding port 80 using IPv6, in the listen directive, in Linux, by default, the IPv4 port 80 is also enabled. Meaning that nginx listens for both IPv4 and IPv6 incoming traffic. Therefore if you erroneously specify also a IPv4 address you’ll get an already bind address error when reloading nginx configuration.

In Linux the separation of the IPv6 and IPv4 stacks is controlled through the runtime parameter: net.ipv6.bindv6only which has the value 0 by default.

If you want to use separate sockets for IPv4 and IPv6 you should set this parameter to 1 using sysctl.

Note that any nginx instance that was running before you made the change will continue to accept IPv4 traffic. Therefore you should edit your nginx configuration to reflect the new setup for IPv6 and IPv4 packet handling and do a restart.

comments powered by Disqus