On most Linux systems, tzdata is installed at /usr/share/zoneinfo, and glibc looks for it there by default. On NixOS systems, tzdata is installed to the nix store, a series of symlinks /etc/zoneinfo → /etc/static/zoneinfo → ${etc}/zoneinfo → ${tzdata}/share/zoneinfo points to it, glibc looks for it by default in a ${glibc}/share/zoneinfo that never exists, and the TZDIR environment variable is used to point it to /etc/zoneinfo.
FHS prescribes that tzdata should be at /usr/share/zoneinfo, and software that doesn’t implement TZDIR or software that runs in an environment that loses TZDIR will normally expect to find tzdata there and fail on current NixOS. When using buildFHSEnv, the only thing that changes is that the symbolic links become /etc/zoneinfo → /.host-etc/zoneinfo → /etc/static/zoneinfo → ${etc}/zoneinfo → ${tzdata}/share/zoneinfo. /usr/share/zoneinfo does not exist in the created FHS environment. This can be fixed by creating an extra symlink $out/usr/share/zoneinfo → ${tzdata}/share/zoneinfo when building the FHS environment, and adding TZDIR=/usr/share/zoneinfo to the profile. Then software that doesn’t check TZDIR should just work in the FHS environment.
The current system breaks when using foreign filesystem images. When launching a container, it’s possible that TZDIR=/etc/zoneinfo actually creates the problem that it usually solves because /etc/zoneinfo doesn’t exist or cannot be resolved within the container environment but the environment variable gets propagated into the container and tells software in the container to look for tzdata where it isn’t. NixOS has a patch to flatpak to unset TZDIR for this reason.
Things get more complicated with software like Steam which currently starts a container environment where TZDIR is set to /etc/zoneinfo, /etc/zoneinfo can’t be resolved, and a copy of tzdata exists at /usr/share/zoneinfo, but unsetting TZDIR as is done for flatpak doesn’t work because glibc is the NixOS glibc that defaults to the missing ${glibc}/share/zoneinfo path. In this case, TZDIR needs to be set to /usr/share/zoneinfo, which doesn’t actually exist at the last moment NixOS can set it when launching Steam and won’t exist until later on when Steam sets up its environment, by which time some other Steam code may have tried and failed to access tzdata.
Can we make this better by:
- Changing the glibc build so that it defaults to the standard
/usr/share/zoneinfoinstead of${glibc}/share/zoneinfo. Neither path normally exists on NixOS, but/usr/share/zoneinfois more normal and has a better chance of working whenTZDIRis unset. - Ensuring
/usr/share/zoneinfoexists in FHS environments andTZDIRpoints to it (or is unset).
This would fix Steam without making any Steam-specific changes, and improve the chances that other foreign software works as expected when launched in NixOS FHS environments. I don’t think it’s a complicated change, but it seems like a significant enough change that it’d be better to create a discussion first instead of just creating a PR.
See also ValveSoftware/steam-runtime#795.