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