2023-08-26
Linux NFS v4 idmapd domain handling and server/client agreement
As mentioned in the nfsidmap(5) manual page, NFS v4 represents UIDs and GIDs as 'id@domain' strings in contexts like stat(2) results and thus, for example, 'ls -l' output (this was explained to me in a comment on this entry). If you want your NFS v4 mounts to look like your NFS v3 mounts and work transparently, the server and the client need to agree on the domain, although the exact domain probably doesn't matter. As I mentioned in my entry on enabling NFS v4, I feel that you might want to set this explicitly rather than count on Linux getting it right (on both the server and all of the clients).
The nfsidmap(5) manual page more or less documents how Linux determines the NFS v4 domain. First, it checks for an explicit setting in /etc/idmapd.conf:
[General] Domain = cs.toronto.edu
If NFS v4 finds no explicit setting, it starts going through a
lookup process, which you can find the code for in
'domain_from_dns()
' in support/nfsidmap/libnfsidmap.c.
We get the system's hostname, look up its IP with gethostbyname(3) (which
doesn't necessarily actually do DNS), take the 'h_name
' field
of the 'struct hostent
' returned by gethostbyname(3) as the
host's fully qualified name, and take the 'domain' to be everything
after the first dot. If gethostbyname(3) failed and the hostname
has a dot in it, everything after that dot is the 'domain' (otherwise
we fail). Having determined the domain, we do a DNS TXT lookup for
'_nfsv4idmapdomain.<domain>
'. If that returns a result, it's
taken as our NFS v4 domain; otherwise, the previously determined
'DNS' domain is our NFS v4 domain.
I'm not quite sure exactly when idmapd or other programs act to determine the NFS v4 domain, but it seems to happen no later than when they first have to do this translation for NFS v4 requests and responses. The current code caches the result, rather than redoing the lookup every time, so I believe the first result obtained will be sticky until the relevant daemon is restarted (I think usually idmapd(8)).
(As far as I can tell, all of this is the same on both the NFS server and all of the NFS clients. As far as I know they all run idmapd and so run this code, although obviously each of them has their own idmapd.conf, their own hostname, and so on.)
Given this, we can make some observations. First, the default (DNS-based) NFS v4 domain determination gives the same result for all hosts under a particular subdomain. if you have two groups separately operating NFS v4 fileservers under a common DNS subdomain, such as 'dev.example.org', they're both going to get the same NFS v4 domain name even if they have different (or even conflicting) Unix login names. Probably you want one or both of them to set an explicit NFS v4 domain name in /etc/idmapd.conf.
If you use the _nfsv4idmapdomain DNS TXT lookup feature to provide your NFS v4 domain name, you're obviously dependent on DNS working. Otherwise it depends on how you have your hostnames set up. If your hostnames are the system's fully qualified domain name (so 'fred.dev.example.org'), then even if DNS isn't working you'll get the same NFS v4 domain name because the current code will fall back to the 'everything after the first dot in the hostname' case. If you have your hostnames set to either the bare hostname (so 'fred') or the hostname with your subdomain only (so 'fred.dev'), the hostname fallback will either fail or generate a different result than normal, and so you're dependent on DNS to get the right NFS v4 domain name.
(If you have NFS v4 clients in different DNS subdomains and they all mount from a NFS v4 server, you definitely need to set the domain explicitly on some or all of them. The same is true if your NFS v4 server(s) are in a different DNS subdomain than all of the clients.)
If the default of your DNS domain is good enough as your NFS v4 domain name, setting an explicit domain in /etc/idmapd.conf is only insurance against odd DNS issues or outright DNS failures. It also insulates you against accidents with /etc/hosts and other nsswitch.conf fun and games (for example, with nss-myhostname).