nixos/timezone: support imperative timezone configuration (#26608)

Fixes #26469.

authored by

Linus Heckemann and committed by
Joachim F
a0d46403 449946ef

+57 -8
+12 -8
nixos/modules/config/timezone.nix
··· 14 14 time = { 15 15 16 16 timeZone = mkOption { 17 - default = "UTC"; 18 - type = types.str; 17 + default = null; 18 + type = types.nullOr types.str; 19 19 example = "America/New_York"; 20 20 description = '' 21 21 The time zone used when displaying times and dates. See <link 22 22 xlink:href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones"/> 23 23 for a comprehensive list of possible values for this setting. 24 + 25 + If null, the timezone will default to UTC and can be set imperatively 26 + using timedatectl. 24 27 ''; 25 28 }; 26 29 ··· 40 43 # This way services are restarted when tzdata changes. 41 44 systemd.globalEnvironment.TZDIR = tzdir; 42 45 43 - environment.etc.localtime = 44 - { source = "/etc/zoneinfo/${config.time.timeZone}"; 45 - mode = "direct-symlink"; 46 + systemd.services.systemd-timedated.environment = lib.optionalAttrs (config.time.timeZone != null) { NIXOS_STATIC_TIMEZONE = "1"; }; 47 + 48 + environment.etc = { 49 + zoneinfo.source = tzdir; 50 + } // lib.optionalAttrs (config.time.timeZone == null) { 51 + localtime.source = "/etc/zoneinfo/${config.time.timeZone}"; 52 + localtime.mode = "direct-symlink"; 46 53 }; 47 - 48 - environment.etc.zoneinfo.source = tzdir; 49 - 50 54 }; 51 55 52 56 }
+45
nixos/tests/timezone.nix
··· 1 + { 2 + timezone-static = import ./make-test.nix ({ pkgs, ... }: { 3 + name = "timezone-static"; 4 + meta.maintainers = with pkgs.lib.maintainers; [ lheckemann ]; 5 + 6 + machine.time.timeZone = "Europe/Amsterdam"; 7 + 8 + testScript = '' 9 + $machine->waitForUnit("dbus.socket"); 10 + $machine->fail("timedatectl set-timezone Asia/Tokyo"); 11 + my @dateResult = $machine->execute('date -d @0 "+%Y-%m-%d %H:%M:%S"'); 12 + $dateResult[1] eq "1970-01-01 01:00:00\n" or die "Timezone seems to be wrong"; 13 + ''; 14 + }); 15 + 16 + timezone-imperative = import ./make-test.nix ({ pkgs, ... }: { 17 + name = "timezone-imperative"; 18 + meta.maintainers = with pkgs.lib.maintainers; [ lheckemann ]; 19 + 20 + machine.time.timeZone = null; 21 + 22 + testScript = '' 23 + $machine->waitForUnit("dbus.socket"); 24 + 25 + # Should default to UTC 26 + my @dateResult = $machine->execute('date -d @0 "+%Y-%m-%d %H:%M:%S"'); 27 + print $dateResult[1]; 28 + $dateResult[1] eq "1970-01-01 00:00:00\n" or die "Timezone seems to be wrong"; 29 + 30 + $machine->succeed("timedatectl set-timezone Asia/Tokyo"); 31 + 32 + # Adjustment should be taken into account 33 + my @dateResult = $machine->execute('date -d @0 "+%Y-%m-%d %H:%M:%S"'); 34 + print $dateResult[1]; 35 + $dateResult[1] eq "1970-01-01 09:00:00\n" or die "Timezone was not adjusted"; 36 + 37 + # Adjustment should persist across a reboot 38 + $machine->shutdown; 39 + $machine->waitForUnit("dbus.socket"); 40 + my @dateResult = $machine->execute('date -d @0 "+%Y-%m-%d %H:%M:%S"'); 41 + print $dateResult[1]; 42 + $dateResult[1] eq "1970-01-01 09:00:00\n" or die "Timezone adjustment was not persisted"; 43 + ''; 44 + }); 45 + }