+.. role:: since
+
==================
Libvirt NSS module
==================
.. contents::
-When it comes to managing guests and executing commands inside them, logging
-into guest operating system and doing the job is convenient. Users are used to
-ssh in this case. Ideally:
+Effectively managing guests often requires connecting to them via SSH, same as
+you would for any remote machine. Ideally
+
+::
+
+ $ ssh user@mydomain
-``ssh user@virtualMachine``
+would work out of the box, but depending on the network configuration that
+might not be the case. Setting up the libvirt NSS module is a one-time
+operation that makes the process of connecting from the host to the guests
+running on it much more convenient.
-would be nice. But depending on virtual network configuration it might not be
-always possible. For instance, when using libvirt NATed network it's dnsmasq
-(spawned by libvirt) who assigns IP addresses to domains. But by default, the
-dnsmasq process is then not consulted when it comes to host name translation.
-Users work around this problem by configuring their libvirt network to assign
-static IP addresses and maintaining ``/etc/hosts`` file in sync. But this puts
-needless burden onto users. This is where NSS module comes handy.
+Note that this feature only works in certain scenarios. See the
+`limitations`_ section for more information.
Installation
------------
-Installing the module is really easy:
+Installing the module on Fedora or RHEL is really easy:
::
- # yum install libvirt-nss
+ # dnf install libvirt-nss
+
+The package might have a different name on other distributions, but the process
+of installing it will be similar.
Configuration
-------------
-Enabling the module is really easy. Just add **libvirt** into
-``/etc/nsswitch.conf`` file. For instance:
+To enable the module, modify ``/etc/nsswitch.conf`` so that the ``hosts`` line
+looks similar to
::
- $ cat /etc/nsswitch.conf
- # /etc/nsswitch.conf:
- passwd: compat
- shadow: compat
- group: compat
- hosts: files libvirt dns
- # ...
-
-So, in this specific case, whenever ssh program is looking up the host user is
-trying to connect to, **files** module is consulted first (which boils down to
-looking up the host name in ``/etc/hosts`` file), if not found **libvirt**
-module is consulted then. The DNS is the last effort then, if none of the
-previous modules matched the host in question. Therefore users should consider
-the order in which they want the modules to lookup given host name.
-
-Sources of information
-----------------------
+ hosts: files libvirt libvirt_guest dns
-As of ``v3.0.0`` release, libvirt offers two NSS modules implementing two
-different methods of hostname translation. The first and older method is
-implemented by ``libvirt`` plugin and basically looks up the hostname to IP
-address translation in DHCP server records. Therefore this is dependent on
-hostname provided by guests. Thing is, not all the guests out there provide one
-in DHCP transactions, or not every sysadmin out there believes all the guests.
-Hence libvirt implements second method in ``libvirt_guest`` module which does
-libvirt guest name to IP address translation (regardless of hostname set in the
-guest).
+With this configuration, whenever SSH (or any other application)
+tries to contact a guest, the ``files`` module will be consulted first (this
+boils down to searching for a matching line in ``/etc/hosts``); if no IP
+address could be found that way, the ``libvirt`` and ``libvirt_guest`` modules
+(see `below <variants_>`__ for differences between the two) will be used
+instead. Finally, if no previous attempt at resolving the hostname was
+successful, a DNS query will be performed.
-To enable either of the modules put their name into the ``nsswitch.conf`` file.
-For instance, to enable ``libvirt_guest`` module:
+Variants
+--------
-::
+There are two different variants of the module:
- $ cat /etc/nsswitch.conf
- # /etc/nsswitch.conf:
- hosts: files libvirt_guest dns
- # ...
+* ``libvirt`` (:since:`since 1.3.3`) resolves hostnames based on the
+ information that the guest OS itself has reported to the DHCP server when
+ asking for an IP address, so it won't work if the guest OS hasn't been fully
+ configured yet;
-Or users can enable both at the same time:
+* ``libvirt_guest`` (:since:`since 3.0.0`) resolves hostnames by mapping them
+ directly to libvirt domain names, so it will work regardless of how the guest
+ OS is configured and will have more predictable results.
-::
+The recommended configuration seen above enables both of them and gives
+priority to the former but it's also possible to enable only a single one, or
+to alter the precedence by simply changing the order in which they are listed.
- $ cat /etc/nsswitch.conf
- # /etc/nsswitch.conf:
- hosts: files libvirt libvirt_guest dns
- # ...
-
-This configuration will mean that if hostname is not found by the ``libvirt``
-module (e.g. because a guest did not sent hostname during DHCP transaction), the
-``libvirt_guest`` module is consulted (and if the hostname matches libvirt guest
-name it will be resolved).
-
-How does it work?
------------------
-
-Whenever an Unix process wants to do a host name translation
-`gethostbyname() <https://linux.die.net/man/3/gethostbyname>`__ or some variant
-of it is called. This is a glibc function that takes a string containing the
-host name, crunch it and produces a list of IP addresses assigned to that host.
-Now, glibc developers made a really good decision when implementing the
-internals of the function when they decided to make the function pluggable.
-Since there can be several sources for the records (e.g. ``/etc/hosts`` file,
-DNS, LDAP, etc.) it would not make much sense to create one big implementation
-containing all possible cases. What they have done instead is this pluggable
-mechanism. Small plugins implementing nothing but specific technology for lookup
-process are provided and the function then calls those plugins. There is just
-one configuration file that instructs the lookup function in which order should
-the plugins be called and which plugins should be loaded. For more info reading
-`wiki page <https://en.wikipedia.org/wiki/Name_Service_Switch>`__ is
-recommended.
-
-And this is point where libvirt comes in. Libvirt provides plugin for the NSS
-ecosystem. For some time now libvirt keeps a list of assigned IP addresses for
-libvirt networks. The NSS plugin does no more than search the list trying to
-find matching record for given host name. When found, matching IP address is
-returned to the caller. If not found, translation process continues with the
-next plugin configured. At this point it is important to stress the order in
-which plugins are called. Users should be aware that a hostname might match in
-multiple plugins and right after first match, translation process is terminated
-and no other plugin is consulted. Therefore, if there are two different records
-for the same host name users should carefully chose the lookup order.
+Implementation details
+----------------------
-Limitations
------------
+Whenever a Unix process needs to convert a hostname into an IP address, it will
+call the `gethostbyname() <https://linux.die.net/man/3/gethostbyname>`__ libc
+function or one of its variants.
-#. The ``libvirt`` NSS module matches only hostnames provided by guest. If the
- libvirt name and one advertised by guest differs, the latter is matched.
- However, as of ``v3.0.0`` there are two libvirt NSS modules translating both
- hostnames provided by guest and libvirt guest names.
-#. The module works only in that cases where IP addresses are assigned by
- dnsmasq spawned by libvirt. Libvirt NATed networks are typical example.
-
-*The following paragraph describes implementation limitation of the ``libvirt``
-NSS module.* These limitation are result of libvirt's internal implementation.
-While libvirt can report IP addresses regardless of their origin, a public API
-must be used to obtain those. However, for the API a connection object is
-required. Doing that for every name translation request would be too costly.
-Fortunately, libvirt spawns dnsmasq for NATed networks. Not only that, it
-provides small executable that on each IP address space change updates an
-internal list of addresses thus keeping it in sync. The NSS module then merely
-consults the list trying to find the match. Users can view the list themselves:
+Since multiple sources for this information are possible (for example the
+contents of ``/etc/hosts``, DNS, LDAP, etc.) a mechanism called
+`NSS <https://en.wikipedia.org/wiki/Name_Service_Switch>`__ has been created to
+make the name resolution process extensible. This allows each source to be
+implemented as a separate plugin that can be enabled or disabled based on the
+administrator's preferences.
-::
+In the case of libvirt, the lookup is performed by inspecting the DHCP leases
+handed out by ``dnsmasq``, the software used to implement NATed networks. The
+results will be the same that would be reported by
- virsh net-dhcp-leases $network
+::
-where ``$network`` iterates through all running networks. So the module does
-merely the same as
+ $ virsh domifaddr --source lease mydomain
-::
+except that things will work transparently for any application that uses the
+libc resolver, without it needing to link against libvirt or even be aware of
+its existence.
- virsh domifaddr --source lease $domain
+Limitations
+-----------
-If there's no record for either of the aforementioned commands, it's very likely
-that NSS module won't find anything and vice versa. As of ``v3.0.0`` libvirt
-provides ``libvirt_guest`` NSS module that doesn't have this limitation.
-However, the statement is still true for the ``libvirt`` NSS module.
+Since the libvirt NSS module works by looking at ``dnsmasq``, it can only work
+for guests that are connected to a NATed libvirt network. Guests that obtain
+their IP addresses in any other way (usermode networking, assigned network
+devices and so on) will not be able to have their hostnames resolved through
+it.
Alternatives
------------
-As of ``v10.3.0`` libvirt implements an `SSH proxy <ssh-proxy.html>`__ which
-doesn't require any network interface to SSH into the guest as SSH flows
-through a VSOCK device.
+:since:`Since 10.3.0`, libvirt implements an `SSH proxy <ssh-proxy.html>`__.
+This allows the use of SSH even for guests that have no network connectivity,
+by communicating over VSOCK.