Skip to content

nixos/timezone: stop using mode direct-symlink for linking localtime#284641

Closed
NickCao wants to merge 1 commit intoNixOS:masterfrom
NickCao:direct-symlink
Closed

nixos/timezone: stop using mode direct-symlink for linking localtime#284641
NickCao wants to merge 1 commit intoNixOS:masterfrom
NickCao:direct-symlink

Conversation

@NickCao
Copy link
Member

@NickCao NickCao commented Jan 29, 2024

Description of changes

This surfaces from #270727 (comment).

We are currently having an unnecessary level of indirection, namely
/etc/localtime -> /etc/zoneinfo/<tz> -> /nix/store/<tzdata>/share/zoneinfo/<tz>
Which was introduced in #26608 for no obvious reasons.

It can be reduced to
/etc/localtime -> /nix/store/<tzdata>/share/zoneinfo/<tz>
and the relevant nixos tests still pass.

This also removed the last in-tree user of the undocumented direct-symlink mode of etc files.

Things done

  • Built on platform(s)
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • For non-Linux: Is sandboxing enabled in nix.conf? (See Nix manual)
    • sandbox = relaxed
    • sandbox = true
  • Tested, as applicable:
  • Tested compilation of all packages that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage
  • Tested basic functionality of all binary files (usually in ./result/bin/)
  • 24.05 Release Notes (or backporting 23.05 and 23.11 Release notes)
    • (Package updates) Added a release notes entry if the change is major or breaking
    • (Module updates) Added a release notes entry if the change is significant
    • (Module addition) Added a release notes entry if adding a new NixOS module
  • Fits CONTRIBUTING.md.

Add a 👍 reaction to pull requests you find important.

@github-actions github-actions bot added 6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS 8.has: module (update) This PR changes an existing module in `nixos/` labels Jan 29, 2024
@NickCao NickCao requested a review from lheckemann January 29, 2024 00:18
@ofborg ofborg bot added 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin. 10.rebuild-linux: 1-10 This PR causes between 1 and 10 packages to rebuild on Linux. labels Jan 29, 2024
@lheckemann
Copy link
Member

The indirection wasn't introduced in my PR, it was introduced before in 0762396 -- with justification.

If this turns out to be fine anyway -- given that it's the last use of direct-symlink in nixpkgs, maybe we should remove or at least deprecate the mode as well?

@NickCao
Copy link
Member Author

NickCao commented Jan 29, 2024

The indirection wasn't introduced in my PR, it was introduced before in 0762396 -- with justification.

This indeed breaks systemd:

❯ timedatectl status
                Time zone: n/a (UTC, +0000)

@NickCao NickCao marked this pull request as draft January 29, 2024 21:17
@NickCao
Copy link
Member Author

NickCao commented Jan 29, 2024

So the solution would now be keeping direct-symlink, but make perlless activation compatible with it.

@MinerSebas MinerSebas mentioned this pull request Feb 2, 2024
13 tasks
@Kiskae
Copy link
Contributor

Kiskae commented Feb 2, 2024

Wouldn't the following code work:

lib.optionalAttrs (config.time.timeZone != null) {
  localtime.source = "/etc/zoneinfo/${config.time.timeZone}";
  localtime.mode = "symlink";
};

This keeps the indirection because the systemd requirements, but fixes perlless activation since creating a symlink to a non-existent absolute path is allowed.

It looks like direct-symlink is a hack to get a symlink but gid or uid was set for some reason:

if (-e "$_.mode") {
my $mode = read_file("$_.mode"); chomp $mode;
if ($mode eq "direct-symlink") {
atomicSymlink readlink("$static/$fn"), $target or warn "could not create symlink $target";
} else {
my $uid = read_file("$_.uid"); chomp $uid;
my $gid = read_file("$_.gid"); chomp $gid;
copy "$static/$fn", "$target.tmp" or warn;
$uid = getpwnam $uid unless $uid =~ /^\+/;
$gid = getgrnam $gid unless $gid =~ /^\+/;
chown int($uid), int($gid), "$target.tmp" or warn;
chmod oct($mode), "$target.tmp" or warn;
unless (rename "$target.tmp", $target) {
warn "could not create target $target";
unlink "$target.tmp";
}
}
push @copied, $fn;
print CLEAN "$fn\n";
} elsif (-l "$_") {
atomicSymlink "$static/$fn", $target or warn "could not create symlink $target";
}

Neither are the case here, so it is likely safe to remove this entirely.

@nyabinary
Copy link
Contributor

Wouldn't the following code work:

lib.optionalAttrs (config.time.timeZone != null) {
  localtime.source = "/etc/zoneinfo/${config.time.timeZone}";
  localtime.mode = "symlink";
};

This keeps the indirection because the systemd requirements, but fixes perlless activation since creating a symlink to a non-existent absolute path is allowed.

It looks like direct-symlink is a hack to get a symlink but gid or uid was set for some reason:

if (-e "$_.mode") {
my $mode = read_file("$_.mode"); chomp $mode;
if ($mode eq "direct-symlink") {
atomicSymlink readlink("$static/$fn"), $target or warn "could not create symlink $target";
} else {
my $uid = read_file("$_.uid"); chomp $uid;
my $gid = read_file("$_.gid"); chomp $gid;
copy "$static/$fn", "$target.tmp" or warn;
$uid = getpwnam $uid unless $uid =~ /^\+/;
$gid = getgrnam $gid unless $gid =~ /^\+/;
chown int($uid), int($gid), "$target.tmp" or warn;
chmod oct($mode), "$target.tmp" or warn;
unless (rename "$target.tmp", $target) {
warn "could not create target $target";
unlink "$target.tmp";
}
}
push @copied, $fn;
print CLEAN "$fn\n";
} elsif (-l "$_") {
atomicSymlink "$static/$fn", $target or warn "could not create symlink $target";
}

Neither are the case here, so it is likely safe to remove this entirely.

I believe the systemd patch will need to be updated too:

+ e = PATH_STARTSWITH_SET(t, "/etc/zoneinfo/", "../etc/zoneinfo/");

@nyabinary
Copy link
Contributor

Any status update on this?

@devurandom
Copy link
Contributor

devurandom commented Mar 6, 2024

I just ran into the same issue:

error: builder for '/nix/store/596cj5v942ms8dbfsmsz5fm69a7yghmr-etc-lowerdir.drv' failed with exit code 1;
       last 1 log lines:
       > cp: cannot stat '/etc/zoneinfo/Europe/Berlin': No such file or directory
       For full logs, run 'nix log /nix/store/596cj5v942ms8dbfsmsz5fm69a7yghmr-etc-lowerdir.drv'.

Is there a workaround? (Apart from unsetting time.timeZone.)

@nyabinary
Copy link
Contributor

I just ran into the same issue:

error: builder for '/nix/store/596cj5v942ms8dbfsmsz5fm69a7yghmr-etc-lowerdir.drv' failed with exit code 1;
       last 1 log lines:
       > cp: cannot stat '/etc/zoneinfo/Europe/Berlin': No such file or directory
       For full logs, run 'nix log /nix/store/596cj5v942ms8dbfsmsz5fm69a7yghmr-etc-lowerdir.drv'.

Is there a workaround? (Apart from unsetting time.timeZone.)

I don't think so, sadly.

@jcfj
Copy link

jcfj commented May 23, 2024

Is there a workaround?

Setting environment.etc.localtime = lib.mkForce { source = "${pkgs.tzdata}/share/zoneinfo/${config.time.timeZone}"; }; works for that build failure, but I'm not sure the resulting system is usable.

@NickCao
Copy link
Member Author

NickCao commented May 26, 2024

Closing in favor of #314579

@NickCao NickCao closed this May 26, 2024
@NickCao NickCao deleted the direct-symlink branch May 26, 2024 14:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS 8.has: module (update) This PR changes an existing module in `nixos/` 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin. 10.rebuild-linux: 1-10 This PR causes between 1 and 10 packages to rebuild on Linux.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants