- Published on
Nginx with IPv6/Dual stack
The new virtual host serving you this website is now capable of IPv6, which is great. In the days where IPv4 addresses are rare and also not very cheap (>15€ per month for more than 4 addresses), it's good to have a /64 IPv6 subnet. 2^64
addresses is way to much but well.. it is for free.
Nginx is my webserver of choice right now and I want to enable IPv6 in dual stack mode. My first naive approach was to just uncomment the listen [::]:80
directive for all servers and that's it. I was wrong, this is the result:
Starting nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
configuration file /etc/nginx/nginx.conf test is successful
[emerg]: bind() to [::]:80 failed (98: Address already in use)
[emerg]: bind() to [::]:80 failed (98: Address already in use)
[emerg]: bind() to [::]:80 failed (98: Address already in use)
[emerg]: bind() to [::]:80 failed (98: Address already in use)
[emerg]: bind() to [::]:80 failed (98: Address already in use)
[emerg]: still could not bind()
The point here is, that if net.ipv6.bindv6only
(in /etc/sysctl.conf
) is disabled - which it is by default - nginx listens in dual stack mode. And as we have the directive listen 80
in our configuration as well, it crashes.
There are two solutions to this: Disable listen 80
for every server or change ipv6only
to 1
.
listen 80
with listen [::]:80
Replace all server {
# listen 80; ## listen for ipv4
listen [::]:80; ## listen for ipv6
}
$> netstat -nlp | grep nginx
tcp6 0 0 :::80 :::* LISTEN 8960/nginx
tcp6 0 0 :::443 :::* LISTEN 8960/nginx
No tcp (IPv4) listen directives for nginx. Despite that, the sockets are configured to accept both IPv4 and IPv6 connections via in6addr_any
.
ipv6only
Enable To explicitly create to sockets for each protocol, you'd have to to configure nginx the following way:
server {
listen 80;
listen [::]:80 ipv6only=on;
}
The default on Linux is disabled ipv6only. So you have to enable it manually with sysctl -w net.ipv6.bindv6only="1"
or put the following into /etc/sysctl.conf
and reboot.
net.ipv6.bindv6only = 1