7

Is there an equivalent of net.ipv4.ip_nonlocal_bind for ipv6 ? Need to start my nginx on boot on such an IP...

My Ubuntu doesn't have this IPv6 assigned on eth0 quickly enough despite this /etc/network/interface :

iface eth0 inet6 static
    address 1:2:3:4::5
    netmask 64

During boot :

Starting nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
[emerg]: bind() to [1:2:3:4::5]:80 failed (99: Cannot assign requested address)

I need to run /etc/init.d/nginx restart a few seconds after boot to make things work :-/

NB : 1:2:3:4::5 is used here only for demo, i have a valid IPv6 address on my server.

Jenny D
  • 27,358
  • 21
  • 74
  • 110
Valentin
  • 71
  • 1
  • 2
  • Why not get the boot order fixed so that nginx can't be started until after the network interfaces have been started? – Flexo Feb 17 '11 at 08:45
  • 3
    This does raise an interesting point - net.ipv4.ip_nonlocal_bind is often used in HA setups with floating IPs. What happens when IPv6 becomes commonplace? – Coops Feb 17 '11 at 09:16

5 Answers5

5

The net.ipv6.ip_nonlocal_bind sysctl was added in kernel 4.3, so if you're running a more bleeding-edge system, you can now solve this problem directly with the sysctl, rather than working around the problem with init script hacks.

womble
  • 95,029
  • 29
  • 173
  • 228
3

The delay is most likely due to IPv6 Duplicate Address Detection. Turning this off would (of course) break the standard, but you might try setting net.ipv6.conf.eth0.dad_transmits to 0 (defaults to 1 on my Ubuntu system):

sysctl -w net.ipv6.conf.eth0.dad_transmits=0

To make permanent:

sudo /bin/bash -c 'echo "net.ipv6.conf.eth0.dad_transmits=0" > /etc/sysctl.d/99-disable-dad-eth0.conf'

Of course, the other option is to just bind to :: (IPv6 all-zeroes, or any IPv6 address) and firewall off the service on interfaces that should not expose it.

mpontillo
  • 924
  • 6
  • 23
1

You can simply configure a static IPv6 address entry on the loopback interface. This will allow nginx to listen on the IP/PORT even if the address it not yet available on eth0.

Manual:

/sbin/ip -6 addr add 2001:db8::ffff:1/64 dev lo

Config file:

# File: '/etc/network/interfaces'

auto lo
iface lo inet loopback

iface lo inet6 static
    address 2001:db8::ffff:1
    netmask 64
0

As it seems that there is no such kernel parameter for ipv6, you could hack the init script of nginx and add :

grep -q eth0 /etc/network/run/ifstate || ifup eth0

somewhere before the command launching nginx ?

Or, as you seem to use a debian or a derivatice, you could try to reorder your init scripts by dependancy with the help of the package insserv and switch to parallel init script lauchning by setting the variable CONCURENCY=makefile in /etc/default/rcS (if you are using Debian Squeeze this is the default configuration).

jon_d
  • 693
  • 4
  • 7
  • Currently my nginx already starts after networking setup. If I set only an IPv4 address without net.ipv4.ip_nonlocal_bind, it works perfectly. It just seems that IPv6 set up takes longer to complete. I'm going to test a small sleep in nginx rc.d script just to validate that. – Valentin Feb 19 '11 at 14:16
0

I'm sure you've solved your issue at some point in the past four years since this post was begun, but I ended up here trying to find a solution to starting nginx on a systemd-enabled CentOS 7 system with similar issues, so perhaps this will help others.

My nginx would come up before networking for both IPv4 and IPv6 was up, causing it to fail to start and remain down. RedHat has a bug where the systemd 'After' network-online.target is set prior to IPv6 being up, so nginx is executed before it can bind to the IPv6 addresses in its config.

Unfortunately since it's a bug, my only option was to introduce a sleep call into the systemd service definition for nginx so it would sleep long enough at boot that IPv6 would be up.