ipa-server-upgrade: IPv6 stack is enabled in the kernel but there is no interface that has ::1 address assigned

I applied the latest CentOS updates, as usual. It included a kernel update, so I rebooted the system:

$ sudo yum update -y
$ sudo reboot

After reboot, ipactl showed that FreeIPA was not running:

$ sudo ipactl status
Directory Service: STOPPED
Directory Service must be running in order to obtain status of other services
ipa: INFO: The ipactl command was successful

I tried to start it:

$ sudo ipactl start
Upgrade required: please run ipa-server-upgrade command
Aborting ipactl

I tried running ipa-server-upgrade:

$ sudo ipa-server-upgrade
IPv6 stack is enabled in the kernel but there is no interface that has ::1 address assigned. Add ::1 address resolution to 'lo' interface. You might need to enable IPv6 on the interface 'lo' in sysctl.conf.
The ipa-server-upgrade command failed. See /var/log/ipaupgrade.log for more information

I had previously disabled IPv6 in /etc/sysctl.conf and removed the ::1 entry from /etc/hosts.

I added the localhost entry back to /etc/hosts:

::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

I removed the statements disabling IPv6 from /etc/sysctl.conf:

net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1

I rebooted for good measure, but even after reboot ipa-server-upgrade produced the same error. Indeed, IPv6 is not enabled:

$ ping6 ::1
connect: No route to host
$ ping6 localhost
connect: No route to host
$ sysctl net.ipv6.conf.all.disable_ipv6
net.ipv6.conf.all.disable_ipv6 = 1

That makes sense. Merely removing the lines setting IPv6 to disabled didn’t actually do anything to re-enable it.

$ sudo sysctl net.ipv6.conf.all.disable_ipv6=0
net.ipv6.conf.all.disable_ipv6 = 0
$ sudo sysctl net.ipv6.conf.lo.disable_ipv6=0
net.ipv6.conf.lo.disable_ipv6 = 0

After that change, ping6 ::1 and ping6 localhost worked as expected. I left IPv6 disabled on the default interface, but noticed in ifconfig that eth0 had picked up an IPv6 address, so I disabled that:

$ sudo sysctl net.ipv6.conf.eth0.disable_ipv6=1

I also added that same line to /etc/sysctl.conf.

I ran the upgrade again:

$ sudo ipa-server-upgrade
Upgrading IPA:. Estimated time: 1 minute 30 seconds
...
...
...
The IPA services were upgraded
The ipa-server-upgrade command was successful

And started FreeIPA:

$ sudo ipactl start
Starting Directory Service
Starting krb5kdc Service
Starting kadmin Service
Starting httpd Service
Starting ipa-custodia Service
Starting ntpd Service
Starting pki-tomcatd Service
Starting ipa-otpd Service
ipa: INFO: The ipactl command was successful

Success! And apparently disabling IPv6 is not the best idea.

FreeIPA 4.5.0 upgrade fails

I recently ran the usual sudo yum update, which included an upgrade of FreeIPA from version 4.4 to version 4.5. However, the upgrade reported that it failed, so I tried to run it manually afterwards:

$ sudo ipa-server-upgrade

The command above timed out, so I ran it again in verbose mode:

$ sudo ipa-server-upgrade --verbose

With the extra output, I saw it was getting stuck on the following before timing out:

ipa: DEBUG: wait_for_open_ports: localhost [8080, 8443] timeout 300

Neither 8080 nor 8443 are on the list of FreeIPA protocols/ports:

TCP 80, 443: HTTP/HTTPS
TCP 389, 636: LDAP/LDAPS
TCP 88, 464: kerberos
TCP 53: DNS
UDP 88, 464: kerberos
UDP 53: DNS
UDP 123: NTP

So what was going on?

I checked to see if those ports were listening:

$ sudo lsof -i TCP -P
...
TCP *:8080 (LISTEN)
TCP *:8443 (LISTEN)
...

$ sudo lsof -i TCP
...
TCP *:webcache (LISTEN)
TCP *:pcsync-https (LISTEN)
...

The ports were listening, so why the timeout? Fortunately I found someone else describing a similar problem on the FreeIPA mailing list, with this reply from Alexander Bokovoy, one of the FreeIPA developers:

I’m a bit tired to repeat this multiple times but FreeIPA does require IPv6 stack to be enabled in the kernel. We absolutely do. If you don’t use IPv6 stack, disable it on specific interfaces. However, there is a practical problem with the way how glibc DNS resolver works: in default configuration it always prefers IPv6 answers to IPv4 because this is actually a policy of RFC3484. As result, if you have ::1 in /etc/hosts, it will be returned first. If you don’t have ::1 on any of your interfaces (‘lo’ is a typical one), then apps cannot contact ::1 (localhost) even if those apps that use IPv6 bind to all interfaces.

FreeIPA uses modern APIs provided by glibc to listen on both IPv6 and IPv4. It simply means that FreeIPA servers bind to IPv6 addresses (on all interfaces or on a specific one, if needed) and treat IPv4 as mapped ones because IPv6 and IPv4 share the same port space on the same machine. This works transparently thanks to glibc and is a recommended way to write networking applications. See man ipv6(7) for details.

(Source)

Following that suggestion, I deleted the following line from /etc/hosts:

::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

Sure enough, that solved the problem! This seems like a good idea for anyone who has disabled IPv6, even if you’re not running FreeIPA. Why include an entry in your hosts file that you know doesn’t work?

I had another FreeIPA server, this one running on an underpowered VM (1GB RAM, 1 CPU). Even after removing the IPv6 entry from /etc/hosts, the FreeIPA upgrade seemed to fail. The certmonger/dogtag processes would consume all of the system resources and it would freeze. All memory was in use and nearly all of the swap space as well. The CPU was running at 5000%. I gave up on it and ignored it for a while, and it turned out that letting it sit and process for a while helped. It seem to have worked itself out: FreeIPA is at the latest version and system resource utilization is very low.