lint-staged: 15.2.10 -> 15.2.11 (#364089)
[NixPkgs.git] / nixos / modules / services / desktops / geoclue2.nix
blob16d1cb17ca066d8e63478a42e80d61de0b9b45c7
1 # GeoClue 2 daemon.
3   config,
4   lib,
5   pkgs,
6   ...
7 }:
8 let
9   cfg = config.services.geoclue2;
11   defaultWhitelist = [
12     "gnome-shell"
13     "io.elementary.desktop.agent-geoclue2"
14   ];
16   appConfigModule = lib.types.submodule (
17     { name, ... }:
18     {
19       options = {
20         desktopID = lib.mkOption {
21           type = lib.types.str;
22           description = "Desktop ID of the application.";
23         };
25         isAllowed = lib.mkOption {
26           type = lib.types.bool;
27           description = ''
28             Whether the application will be allowed access to location information.
29           '';
30         };
32         isSystem = lib.mkOption {
33           type = lib.types.bool;
34           description = ''
35             Whether the application is a system component or not.
36           '';
37         };
39         users = lib.mkOption {
40           type = lib.types.listOf lib.types.str;
41           default = [ ];
42           description = ''
43             List of UIDs of all users for which this application is allowed location
44             info access, Defaults to an empty string to allow it for all users.
45           '';
46         };
47       };
49       config.desktopID = lib.mkDefault name;
50     }
51   );
53   appConfigToINICompatible =
54     _:
55     {
56       desktopID,
57       isAllowed,
58       isSystem,
59       users,
60       ...
61     }:
62     {
63       name = desktopID;
64       value = {
65         allowed = isAllowed;
66         system = isSystem;
67         users = lib.concatStringsSep ";" users;
68       };
69     };
74   ###### interface
76   options = {
78     services.geoclue2 = {
80       enable = lib.mkOption {
81         type = lib.types.bool;
82         default = false;
83         description = ''
84           Whether to enable GeoClue 2 daemon, a DBus service
85           that provides location information for accessing.
86         '';
87       };
89       enableDemoAgent = lib.mkOption {
90         type = lib.types.bool;
91         default = true;
92         description = ''
93           Whether to use the GeoClue demo agent. This should be
94           overridden by desktop environments that provide their own
95           agent.
96         '';
97       };
99       enableNmea = lib.mkOption {
100         type = lib.types.bool;
101         default = true;
102         description = ''
103           Whether to fetch location from NMEA sources on local network.
104         '';
105       };
107       enable3G = lib.mkOption {
108         type = lib.types.bool;
109         default = true;
110         description = ''
111           Whether to enable 3G source.
112         '';
113       };
115       enableCDMA = lib.mkOption {
116         type = lib.types.bool;
117         default = true;
118         description = ''
119           Whether to enable CDMA source.
120         '';
121       };
123       enableModemGPS = lib.mkOption {
124         type = lib.types.bool;
125         default = true;
126         description = ''
127           Whether to enable Modem-GPS source.
128         '';
129       };
131       enableWifi = lib.mkOption {
132         type = lib.types.bool;
133         default = true;
134         description = ''
135           Whether to enable WiFi source.
136         '';
137       };
139       geoProviderUrl = lib.mkOption {
140         type = lib.types.str;
141         default = "https://location.services.mozilla.com/v1/geolocate?key=geoclue";
142         example = "https://www.googleapis.com/geolocation/v1/geolocate?key=YOUR_KEY";
143         description = ''
144           The url to the wifi GeoLocation Service.
145         '';
146       };
148       package = lib.mkOption {
149         type = lib.types.package;
150         default = pkgs.geoclue2;
151         defaultText = lib.literalExpression "pkgs.geoclue2";
152         apply =
153           pkg:
154           pkg.override {
155             # the demo agent isn't built by default, but we need it here
156             withDemoAgent = cfg.enableDemoAgent;
157           };
158         description = "The geoclue2 package to use";
159       };
161       submitData = lib.mkOption {
162         type = lib.types.bool;
163         default = false;
164         description = ''
165           Whether to submit data to a GeoLocation Service.
166         '';
167       };
169       submissionUrl = lib.mkOption {
170         type = lib.types.str;
171         default = "https://location.services.mozilla.com/v1/submit?key=geoclue";
172         description = ''
173           The url to submit data to a GeoLocation Service.
174         '';
175       };
177       submissionNick = lib.mkOption {
178         type = lib.types.str;
179         default = "geoclue";
180         description = ''
181           A nickname to submit network data with.
182           Must be 2-32 characters long.
183         '';
184       };
186       appConfig = lib.mkOption {
187         type = lib.types.attrsOf appConfigModule;
188         default = { };
189         example = lib.literalExpression ''
190           "com.github.app" = {
191             isAllowed = true;
192             isSystem = true;
193             users = [ "300" ];
194           };
195         '';
196         description = ''
197           Specify extra settings per application.
198         '';
199       };
201     };
203   };
205   ###### implementation
206   config = lib.mkIf cfg.enable {
208     environment.systemPackages = [ cfg.package ];
210     services.dbus.packages = [ cfg.package ];
212     systemd.packages = [ cfg.package ];
214     # we cannot use DynamicUser as we need the the geoclue user to exist for the
215     # dbus policy to work
216     users = {
217       users.geoclue = {
218         isSystemUser = true;
219         home = "/var/lib/geoclue";
220         group = "geoclue";
221         description = "Geoinformation service";
222       };
224       groups.geoclue = { };
225     };
227     systemd.services.geoclue = {
228       wants = lib.optionals cfg.enableWifi [ "network-online.target" ];
229       after = lib.optionals cfg.enableWifi [ "network-online.target" ];
230       # restart geoclue service when the configuration changes
231       restartTriggers = [
232         config.environment.etc."geoclue/geoclue.conf".source
233       ];
234       serviceConfig.StateDirectory = "geoclue";
235     };
237     # this needs to run as a user service, since it's associated with the
238     # user who is making the requests
239     systemd.user.services = lib.mkIf cfg.enableDemoAgent {
240       geoclue-agent = {
241         description = "Geoclue agent";
242         # this should really be `partOf = [ "geoclue.service" ]`, but
243         # we can't be part of a system service, and the agent should
244         # be okay with the main service coming and going
245         wantedBy = [ "default.target" ];
246         wants = lib.optionals cfg.enableWifi [ "network-online.target" ];
247         after = lib.optionals cfg.enableWifi [ "network-online.target" ];
248         unitConfig.ConditionUser = "!@system";
249         serviceConfig = {
250           Type = "exec";
251           ExecStart = "${cfg.package}/libexec/geoclue-2.0/demos/agent";
252           Restart = "on-failure";
253           PrivateTmp = true;
254         };
255       };
256     };
258     services.geoclue2.appConfig.epiphany = {
259       isAllowed = true;
260       isSystem = false;
261     };
263     services.geoclue2.appConfig.firefox = {
264       isAllowed = true;
265       isSystem = false;
266     };
268     environment.etc."geoclue/geoclue.conf".text = lib.generators.toINI { } (
269       {
270         agent = {
271           whitelist = lib.concatStringsSep ";" (
272             lib.optional cfg.enableDemoAgent "geoclue-demo-agent" ++ defaultWhitelist
273           );
274         };
275         network-nmea = {
276           enable = cfg.enableNmea;
277         };
278         "3g" = {
279           enable = cfg.enable3G;
280         };
281         cdma = {
282           enable = cfg.enableCDMA;
283         };
284         modem-gps = {
285           enable = cfg.enableModemGPS;
286         };
287         wifi = {
288           enable = cfg.enableWifi;
289           url = cfg.geoProviderUrl;
290           submit-data = lib.boolToString cfg.submitData;
291           submission-url = cfg.submissionUrl;
292           submission-nick = cfg.submissionNick;
293         };
294       }
295       // lib.mapAttrs' appConfigToINICompatible cfg.appConfig
296     );
297   };
299   meta = with lib; {
300     maintainers = with maintainers; [ ] ++ teams.pantheon.members;
301   };