I've seen various config examples for handling dual-stack IPv4 and IPv6 virtual hosts on nginx. Many suggest this pattern:
listen 80;
listen [::]:80 ipv6only=on;
As far as I can see, this achieves exactly the same thing as:
listen [::]:80 ipv6only=off;
Why would you use the former? The only reason I can think of is if you need additional params that are specific to each protocol, for example if you only wanted to set deferred
on IPv4.
If you host multiple vhost domains with a single Nginx instance, you can't use the single combined listen directive
for each of them. Nginx has a weird quirk where you can only specify the
ipv6only
parameter once for each port, or it will fail to start. That means you can't specify it for each vhost domain server block.As Michael mentioned, starting with Nginx 1.3.4, the
ipv6only
parameter defaults toon
.Therefore, if you want to host multiple domains on both IPv4 and IPv6 with a single Nginx server, you are forced to use two listen directives for each domain server block:
Additionally, as Sander mentioned, using
ipv6only=off
has the drawback that IPv4 addresses are translated to IPv6. This can cause problems if your app does IP checking against blacklists like Akismet or StopForumSpam because unless you build in a reverse translation layer, your app will check the IPv6 translation of the spammer's IPv4 address, which won't match any of the IPv4 addresses in the blacklist.That probably is about the only reason you would use the former construct, these days.
The reason you're seeing this is probably that the default of
ipv6only
changed in nginx 1.3.4. Prior to that, it defaulted tooff
; in newer versions it defaults toon
.This happens to interact with the IPV6_V6ONLY socket option on Linux, and similar options on other operating systems, whose defaults aren't necessarily predictable. Thus the former construct was required pre-1.3.4 to ensure that you were actually listening for connections on both IPv4 and IPv6.
The change to the nginx default for
ipv6only
ensures that the operating system default for dual stack sockets is irrelevant. Now, nginx either explicitly binds to IPv4, IPv6, or both, never depending on the OS to create a dual stack socket by default.Indeed, my standard nginx configs for pre-1.3.4 have the first configuration, and post-1.3.4 all have the second configuration.
Though, since binding a dual stack socket is a Linux-only thing, my current configurations now look more like the first example, but without
ipv6only
set, to wit:With the
ipv6only=off
configuration style the IPv4 addresses might be shown as IPv6 addresses using the (software-only) IPv4-mapped IPv6 addresses in for example log files, environment variables (REMOTE_ADDR) etc.To my understanding (and according to the docs at http://nginx.org/en/docs/http/ngx_http_core_module.html#listen), using justlisten 80;
is sufficient if you wish to channel both IPv4 & IPv6 traffic at the same port.Revised answer as of Nov. 2021
As of Nov. 2021 with Nginx latest (from the official repo) e.g. on Ubuntu 18.04 or 20.04 I can confirm that for regular (=not the default) Nginx vhosts this is what works for both IPv4 & IPv6 traffic:
listen [::]:80;
...and if you use a separate block for HTTPS traffic:
listen [::]:443 ssl http2;
The
ipv6only=off
flag should ONLY be referenced once and in the "default" vhost in Nginx (the one used by Nginx when no domain can be mapped to a vhost).E.g.:
Obviously, if your Nginx setup uses a single vhost then you need the latter config only.
One pesky problem I have encountered while adding IPv6 support to a site with the
listen [::]:80 ipv6only=off;
snippet, was when I added it to a vhost and the default_server was already configured to listen for both80
and[::]:80
.nginx
refused to start, complaining that the address was already in use!Replacing the magic
listen [::]:80 ipv6only=off;
with the two traditionallisten
lines allowsnginx
to start just fine.As much as
listen [::]:80 ipv6only=off;
may be convenient in manual configuration, it may cause nasty troubles when used in automated configuration systems.