1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.automatic-timezoned;
7in
8{
9 options = {
10 services.automatic-timezoned = {
11 enable = mkOption {
12 type = types.bool;
13 default = false;
14 description = mdDoc ''
15 Enable `automatic-timezoned`, simple daemon for keeping the system
16 timezone up-to-date based on the current location. It uses geoclue2 to
17 determine the current location and systemd-timedated to actually set
18 the timezone.
19 '';
20 };
21 package = mkOption {
22 type = types.package;
23 default = pkgs.automatic-timezoned;
24 defaultText = literalExpression "pkgs.automatic-timezoned";
25 description = mdDoc ''
26 Which `automatic-timezoned` package to use.
27 '';
28 };
29 };
30 };
31
32 config = mkIf cfg.enable {
33 security.polkit.extraConfig = ''
34 polkit.addRule(function(action, subject) {
35 if (action.id == "org.freedesktop.timedate1.set-timezone"
36 && subject.user == "automatic-timezoned") {
37 return polkit.Result.YES;
38 }
39 });
40 '';
41
42 services.geoclue2 = {
43 enable = true;
44 appConfig.automatic-timezoned = {
45 isAllowed = true;
46 isSystem = true;
47 users = [ (toString config.ids.uids.automatic-timezoned) ];
48 };
49 };
50
51 systemd.services = {
52
53 automatic-timezoned = {
54 description = "Automatically update system timezone based on location";
55 requires = [ "automatic-timezoned-geoclue-agent.service" ];
56 after = [ "automatic-timezoned-geoclue-agent.service" ];
57 serviceConfig = {
58 Type = "exec";
59 User = "automatic-timezoned";
60 ExecStart = "${cfg.package}/bin/automatic-timezoned --zoneinfo-path=${pkgs.tzdata}/share/zoneinfo/zone1970.tab";
61 };
62 wantedBy = [ "default.target" ];
63 };
64
65 automatic-timezoned-geoclue-agent = {
66 description = "Geoclue agent for automatic-timezoned";
67 requires = [ "geoclue.service" ];
68 after = [ "geoclue.service" ];
69 serviceConfig = {
70 Type = "exec";
71 User = "automatic-timezoned";
72 ExecStart = "${pkgs.geoclue2-with-demo-agent}/libexec/geoclue-2.0/demos/agent";
73 Restart = "on-failure";
74 PrivateTmp = true;
75 };
76 wantedBy = [ "default.target" ];
77 };
78
79 };
80
81 users = {
82 users.automatic-timezoned = {
83 description = "automatic-timezoned";
84 uid = config.ids.uids.automatic-timezoned;
85 group = "automatic-timezoned";
86 };
87 groups.automatic-timezoned = {
88 gid = config.ids.gids.automatic-timezoned;
89 };
90 };
91 };
92}