3 { config, lib, pkgs, ... }:
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, ... }: {
17 desktopID = mkOption {
19 description = "Desktop ID of the application.";
22 isAllowed = mkOption {
25 Whether the application will be allowed access to location information.
32 Whether the application is a system component or not.
37 type = types.listOf types.str;
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.
46 config.desktopID = mkDefault name;
49 appConfigToINICompatible = _: { desktopID, isAllowed, isSystem, users, ... }: {
54 users = concatStringsSep ";" users;
71 Whether to enable GeoClue 2 daemon, a DBus service
72 that provides location information for accessing.
76 enableDemoAgent = mkOption {
80 Whether to use the GeoClue demo agent. This should be
81 overridden by desktop environments that provide their own
86 enableNmea = mkOption {
90 Whether to fetch location from NMEA sources on local network.
98 Whether to enable 3G source.
102 enableCDMA = mkOption {
106 Whether to enable CDMA source.
110 enableModemGPS = mkOption {
114 Whether to enable Modem-GPS source.
118 enableWifi = mkOption {
122 Whether to enable WiFi source.
126 geoProviderUrl = mkOption {
128 default = "https://location.services.mozilla.com/v1/geolocate?key=geoclue";
129 example = "https://www.googleapis.com/geolocation/v1/geolocate?key=YOUR_KEY";
131 The url to the wifi GeoLocation Service.
135 submitData = mkOption {
139 Whether to submit data to a GeoLocation Service.
143 submissionUrl = mkOption {
145 default = "https://location.services.mozilla.com/v1/submit?key=geoclue";
147 The url to submit data to a GeoLocation Service.
151 submissionNick = mkOption {
155 A nickname to submit network data with.
156 Must be 2-32 characters long.
160 appConfig = mkOption {
161 type = types.attrsOf appConfigModule;
163 example = literalExpression ''
171 Specify extra settings per application.
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
194 home = "/var/lib/geoclue";
196 description = "Geoinformation service";
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
207 config.environment.etc."geoclue/geoclue.conf".source
209 serviceConfig.StateDirectory = "geoclue";
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 {
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";
226 ExecStart = "${package}/libexec/geoclue-2.0/demos/agent";
227 Restart = "on-failure";
233 services.geoclue2.appConfig.epiphany = {
238 services.geoclue2.appConfig.firefox = {
243 environment.etc."geoclue/geoclue.conf".text =
244 generators.toINI {} ({
246 whitelist = concatStringsSep ";"
247 (optional cfg.enableDemoAgent "geoclue-demo-agent" ++ defaultWhitelist);
250 enable = cfg.enableNmea;
253 enable = cfg.enable3G;
256 enable = cfg.enableCDMA;
259 enable = cfg.enableModemGPS;
262 enable = cfg.enableWifi;
263 url = cfg.geoProviderUrl;
264 submit-data = boolToString cfg.submitData;
265 submission-url = cfg.submissionUrl;
266 submission-nick = cfg.submissionNick;
268 } // mapAttrs' appConfigToINICompatible cfg.appConfig);
272 maintainers = with maintainers; [ ] ++ teams.pantheon.members;