at 23.11-beta 7.2 kB view raw
1# GeoClue 2 daemon. 2 3{ config, lib, pkgs, ... }: 4 5with lib; 6 7let 8 # the demo agent isn't built by default, but we need it here 9 package = pkgs.geoclue2.override { withDemoAgent = config.services.geoclue2.enableDemoAgent; }; 10 11 cfg = config.services.geoclue2; 12 13 defaultWhitelist = [ "gnome-shell" "io.elementary.desktop.agent-geoclue2" ]; 14 15 appConfigModule = types.submodule ({ name, ... }: { 16 options = { 17 desktopID = mkOption { 18 type = types.str; 19 description = lib.mdDoc "Desktop ID of the application."; 20 }; 21 22 isAllowed = mkOption { 23 type = types.bool; 24 description = lib.mdDoc '' 25 Whether the application will be allowed access to location information. 26 ''; 27 }; 28 29 isSystem = mkOption { 30 type = types.bool; 31 description = lib.mdDoc '' 32 Whether the application is a system component or not. 33 ''; 34 }; 35 36 users = mkOption { 37 type = types.listOf types.str; 38 default = []; 39 description = lib.mdDoc '' 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 }; 45 46 config.desktopID = mkDefault name; 47 }); 48 49 appConfigToINICompatible = _: { desktopID, isAllowed, isSystem, users, ... }: { 50 name = desktopID; 51 value = { 52 allowed = isAllowed; 53 system = isSystem; 54 users = concatStringsSep ";" users; 55 }; 56 }; 57 58in 59{ 60 61 ###### interface 62 63 options = { 64 65 services.geoclue2 = { 66 67 enable = mkOption { 68 type = types.bool; 69 default = false; 70 description = lib.mdDoc '' 71 Whether to enable GeoClue 2 daemon, a DBus service 72 that provides location information for accessing. 73 ''; 74 }; 75 76 enableDemoAgent = mkOption { 77 type = types.bool; 78 default = true; 79 description = lib.mdDoc '' 80 Whether to use the GeoClue demo agent. This should be 81 overridden by desktop environments that provide their own 82 agent. 83 ''; 84 }; 85 86 enableNmea = mkOption { 87 type = types.bool; 88 default = true; 89 description = lib.mdDoc '' 90 Whether to fetch location from NMEA sources on local network. 91 ''; 92 }; 93 94 enable3G = mkOption { 95 type = types.bool; 96 default = true; 97 description = lib.mdDoc '' 98 Whether to enable 3G source. 99 ''; 100 }; 101 102 enableCDMA = mkOption { 103 type = types.bool; 104 default = true; 105 description = lib.mdDoc '' 106 Whether to enable CDMA source. 107 ''; 108 }; 109 110 enableModemGPS = mkOption { 111 type = types.bool; 112 default = true; 113 description = lib.mdDoc '' 114 Whether to enable Modem-GPS source. 115 ''; 116 }; 117 118 enableWifi = mkOption { 119 type = types.bool; 120 default = true; 121 description = lib.mdDoc '' 122 Whether to enable WiFi source. 123 ''; 124 }; 125 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 = lib.mdDoc '' 131 The url to the wifi GeoLocation Service. 132 ''; 133 }; 134 135 submitData = mkOption { 136 type = types.bool; 137 default = false; 138 description = lib.mdDoc '' 139 Whether to submit data to a GeoLocation Service. 140 ''; 141 }; 142 143 submissionUrl = mkOption { 144 type = types.str; 145 default = "https://location.services.mozilla.com/v1/submit?key=geoclue"; 146 description = lib.mdDoc '' 147 The url to submit data to a GeoLocation Service. 148 ''; 149 }; 150 151 submissionNick = mkOption { 152 type = types.str; 153 default = "geoclue"; 154 description = lib.mdDoc '' 155 A nickname to submit network data with. 156 Must be 2-32 characters long. 157 ''; 158 }; 159 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 = lib.mdDoc '' 171 Specify extra settings per application. 172 ''; 173 }; 174 175 }; 176 177 }; 178 179 180 ###### implementation 181 config = mkIf cfg.enable { 182 183 environment.systemPackages = [ package ]; 184 185 services.dbus.packages = [ package ]; 186 187 systemd.packages = [ package ]; 188 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 }; 198 199 groups.geoclue = {}; 200 }; 201 202 systemd.services.geoclue = { 203 after = lib.optionals cfg.enableWifi [ "network-online.target" ]; 204 # restart geoclue service when the configuration changes 205 restartTriggers = [ 206 config.environment.etc."geoclue/geoclue.conf".source 207 ]; 208 serviceConfig.StateDirectory = "geoclue"; 209 }; 210 211 # this needs to run as a user service, since it's associated with the 212 # user who is making the requests 213 systemd.user.services = mkIf cfg.enableDemoAgent { 214 geoclue-agent = { 215 description = "Geoclue agent"; 216 # this should really be `partOf = [ "geoclue.service" ]`, but 217 # we can't be part of a system service, and the agent should 218 # be okay with the main service coming and going 219 wantedBy = [ "default.target" ]; 220 after = lib.optionals cfg.enableWifi [ "network-online.target" ]; 221 unitConfig.ConditionUser = "!@system"; 222 serviceConfig = { 223 Type = "exec"; 224 ExecStart = "${package}/libexec/geoclue-2.0/demos/agent"; 225 Restart = "on-failure"; 226 PrivateTmp = true; 227 }; 228 }; 229 }; 230 231 services.geoclue2.appConfig.epiphany = { 232 isAllowed = true; 233 isSystem = false; 234 }; 235 236 services.geoclue2.appConfig.firefox = { 237 isAllowed = true; 238 isSystem = false; 239 }; 240 241 environment.etc."geoclue/geoclue.conf".text = 242 generators.toINI {} ({ 243 agent = { 244 whitelist = concatStringsSep ";" 245 (optional cfg.enableDemoAgent "geoclue-demo-agent" ++ defaultWhitelist); 246 }; 247 network-nmea = { 248 enable = cfg.enableNmea; 249 }; 250 "3g" = { 251 enable = cfg.enable3G; 252 }; 253 cdma = { 254 enable = cfg.enableCDMA; 255 }; 256 modem-gps = { 257 enable = cfg.enableModemGPS; 258 }; 259 wifi = { 260 enable = cfg.enableWifi; 261 url = cfg.geoProviderUrl; 262 submit-data = boolToString cfg.submitData; 263 submission-url = cfg.submissionUrl; 264 submission-nick = cfg.submissionNick; 265 }; 266 } // mapAttrs' appConfigToINICompatible cfg.appConfig); 267 }; 268 269 meta = with lib; { 270 maintainers = with maintainers; [ ] ++ teams.pantheon.members; 271 }; 272}