Describe the bug
I was happy to learn that in NixOS 24.05 the virtualization module gained NSS module support for libvirtd.
However, I found it not working: getent hosts <hostname> does not resolve to an IP address, even though the VM host name and IP is present in libvirt.
Steps To Reproduce
With the following NixOS configuration:
virtualisation = {
libvirtd = {
enable = true;
nss = {
enable = true;
enableGuest = true;
};
};
};
The following entry in /etc/nsswitch.conf is correctly created:
hosts: mymachines resolve [!UNAVAIL=return] files myhostname libvirt libvirt_guest dns
The path to libnss_libvirt.so.2 and libnss_libvirt_guest.so.2 is also correctly added to the LD_LIBRARY_PATH environment variable of the nscd.service, as evidenced by systemctl show nscd:
Environment=LD_LIBRARY_PATH=/nix/store/gzvzqc3lyya4xwjrplmfk3x6l160rr62-libvirt-10.0.0/lib:/nix/store/xjiifrz7ha6s29gp0p0j3w0155phxmia-systemd-255.6/lib
The data source of libnss_libvirt* are plain text files in /var/lib/libvirt/dnsmasq, which makes it a lot easier to reproduce the issue because no actual VMs have to be created using libvirt. Here are two files that can be used for reproduction (Note: The expiry-time below is significant, and should lie in your future, otherwise the name lookups will not work.)
/var/lib/libvirt/dnsmasq/virbr0.macs:
[
{
"domain": "debian11",
"macs": [
"52:54:00:60:dc:fe"
]
}
]
/var/lib/libvirt/dnsmasq/virbr0.status:
[
{
"ip-address": "192.168.122.8",
"mac-address": "52:54:00:60:dc:fe",
"hostname": "debian11",
"expiry-time": 1819155914
}
]
The actual querying of the name can now be done with getent hosts debian11. This does not return a result (exit code 2).
Expected behavior
getent hosts debian11 should return the IP address 192.168.122.8.
Additional context
Having more than one directory in LD_LIBRARY_PATH does not work.
Having just one directory in LD_LIBRARY_PATH, the libvirt one, does work.
To verify those two statements, do the following steps as root.
Please take extra care below to distinguish between nscd and nsncd.
systemctl stop nscd
nix-shell -p nsncd
LD_LIBRARY_PATH="/nix/store/gzvzqc3lyya4xwjrplmfk3x6l160rr62-libvirt-10.0.0/lib" NSNCD_WORKER_COUNT=1 NSNCD_HANDOFF_TIMOUT=10 strace -f nsncd 2>&1 | grep dnsmasq # adapt the libvirt path to your Nix store
In a different terminal, the name resolution is successful:
getent hosts debian11
# ->192.168.122.8 debian11
strace in the first terminal shows that the data source /var/lib/libvirt/ndsmasq is actually consulted:
[pid 9358] openat(AT_FDCWD, "/var/lib/libvirt/dnsmasq/", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 8
[pid 9358] openat(AT_FDCWD, "/var/lib/libvirt/dnsmasq//virbr0.status", O_RDONLY) = 8
[pid 9358] openat(AT_FDCWD, "/var/lib/libvirt/dnsmasq/", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 8
[pid 9358] openat(AT_FDCWD, "/var/lib/libvirt/dnsmasq//virbr0.macs", O_RDONLY) = 9
[pid 9358] openat(AT_FDCWD, "/var/lib/libvirt/dnsmasq//virbr0.status", O_RDONLY) = 8
[pid 9358] openat(AT_FDCWD, "/var/lib/libvirt/dnsmasq/", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 8
[pid 9358] openat(AT_FDCWD, "/var/lib/libvirt/dnsmasq//virbr0.status", O_RDONLY) = 8
Now, repeat the same experiment, but add the second path to LD_LIBRARY_PATH (the actual value from systemd show nscd), e.g.
LD_LIBRARY_PATH="/nix/store/gzvzqc3lyya4xwjrplmfk3x6l160rr62-libvirt-10.0.0/lib:/nix/store/xjiifrz7ha6s29gp0p0j3w0155phxmia-systemd-255.6/lib" to the nsncd invocation.
This time, grep does not match any lines and getent hosts debian11 does not return a result.
Note: If you pass --service libvirt (or similar) to getent, this will bypass the call to nscd and attempt to go to the libnss libraries directly, so this will always fail on NixOS (unless the needed shared libraries are in scope).
I do not know enough about the actual NSS mechanism inside glibc to understand why libnss_libvirt.so.2 and libnss_libvirt_guest.so.2 are not consulted.
Since nsncd does not do actual lookups, and only calls into glibc (gethostbyname() or such), this looks to me like a glibc issue, but this is currently out of my depth to analyze.
In any case, the NixOS feature as I think it was intended to work, does not, hence I think that this is a bug.
I'm happy to provide more details if needed.
Notify maintainers
Sorry for notifying so many of you but this issue looks like it could be interconnected between several parts.
nixos/modules/virtualization/libvirtd.nix: @jchv
nixos/modules/config/nsswitch.nix: @dasJ
nsncd: @flokli @picnoir
libvirt: @fpletz @globin @lovesegfault
Metadata
[user@system:~]$ nix-shell -p nix-info --run "nix-info -m"
- system: `"x86_64-linux"`
- host os: `Linux 6.6.33, NixOS, 24.05 (Uakari), 24.05.20240615.752c634`
- multi-user?: `yes`
- sandbox: `yes`
- version: `nix-env (Nix) 2.18.2`
- nixpkgs: `/nix/store/mcwr2j04fikfsrsaq76f4bviinvl6zql-source`
Add a 👍 reaction to issues you find important.
Describe the bug
I was happy to learn that in NixOS 24.05 the virtualization module gained NSS module support for libvirtd.
However, I found it not working:
getent hosts <hostname>does not resolve to an IP address, even though the VM host name and IP is present in libvirt.Steps To Reproduce
With the following NixOS configuration:
The following entry in
/etc/nsswitch.confis correctly created:The path to
libnss_libvirt.so.2andlibnss_libvirt_guest.so.2is also correctly added to theLD_LIBRARY_PATHenvironment variable of thenscd.service, as evidenced bysystemctl show nscd:The data source of
libnss_libvirt*are plain text files in/var/lib/libvirt/dnsmasq, which makes it a lot easier to reproduce the issue because no actual VMs have to be created using libvirt. Here are two files that can be used for reproduction (Note: Theexpiry-timebelow is significant, and should lie in your future, otherwise the name lookups will not work.)/var/lib/libvirt/dnsmasq/virbr0.macs:/var/lib/libvirt/dnsmasq/virbr0.status:The actual querying of the name can now be done with
getent hosts debian11. This does not return a result (exit code 2).Expected behavior
getent hosts debian11should return the IP address192.168.122.8.Additional context
Having more than one directory in
LD_LIBRARY_PATHdoes not work.Having just one directory in
LD_LIBRARY_PATH, the libvirt one, does work.To verify those two statements, do the following steps as
root.Please take extra care below to distinguish between
nscdandnsncd.In a different terminal, the name resolution is successful:
stracein the first terminal shows that the data source/var/lib/libvirt/ndsmasqis actually consulted:Now, repeat the same experiment, but add the second path to
LD_LIBRARY_PATH(the actual value fromsystemd show nscd), e.g.LD_LIBRARY_PATH="/nix/store/gzvzqc3lyya4xwjrplmfk3x6l160rr62-libvirt-10.0.0/lib:/nix/store/xjiifrz7ha6s29gp0p0j3w0155phxmia-systemd-255.6/lib"to thensncdinvocation.This time,
grepdoes not match any lines andgetent hosts debian11does not return a result.Note: If you pass
--service libvirt(or similar) togetent, this will bypass the call to nscd and attempt to go to the libnss libraries directly, so this will always fail on NixOS (unless the needed shared libraries are in scope).I do not know enough about the actual NSS mechanism inside glibc to understand why
libnss_libvirt.so.2andlibnss_libvirt_guest.so.2are not consulted.Since
nsncddoes not do actual lookups, and only calls into glibc (gethostbyname()or such), this looks to me like a glibc issue, but this is currently out of my depth to analyze.In any case, the NixOS feature as I think it was intended to work, does not, hence I think that this is a bug.
I'm happy to provide more details if needed.
Notify maintainers
Sorry for notifying so many of you but this issue looks like it could be interconnected between several parts.
nixos/modules/virtualization/libvirtd.nix: @jchv
nixos/modules/config/nsswitch.nix: @dasJ
nsncd: @flokli @picnoir
libvirt: @fpletz @globin @lovesegfault
Metadata
Add a 👍 reaction to issues you find important.