at 23.11-pre 3.5 kB view raw
1{ config, lib, pkgs, utils, ... }: 2 3with lib; 4 5let 6 7 uid = config.ids.uids.gpsd; 8 gid = config.ids.gids.gpsd; 9 cfg = config.services.gpsd; 10 11in { 12 13 ###### interface 14 15 imports = [ 16 (lib.mkRemovedOptionModule [ "services" "gpsd" "device" ] 17 "Use `services.gpsd.devices` instead.") 18 ]; 19 20 options = { 21 22 services.gpsd = { 23 24 enable = mkOption { 25 type = types.bool; 26 default = false; 27 description = lib.mdDoc '' 28 Whether to enable `gpsd`, a GPS service daemon. 29 ''; 30 }; 31 32 devices = mkOption { 33 type = types.listOf types.str; 34 default = [ "/dev/ttyUSB0" ]; 35 description = lib.mdDoc '' 36 List of devices that `gpsd` should subscribe to. 37 38 A device may be a local serial device for GPS input, or a 39 URL of the form: 40 `[{dgpsip|ntrip}://][user:passwd@]host[:port][/stream]` in 41 which case it specifies an input source for DGPS or ntrip 42 data. 43 ''; 44 }; 45 46 readonly = mkOption { 47 type = types.bool; 48 default = true; 49 description = lib.mdDoc '' 50 Whether to enable the broken-device-safety, otherwise 51 known as read-only mode. Some popular bluetooth and USB 52 receivers lock up or become totally inaccessible when 53 probed or reconfigured. This switch prevents gpsd from 54 writing to a receiver. This means that gpsd cannot 55 configure the receiver for optimal performance, but it 56 also means that gpsd cannot break the receiver. A better 57 solution would be for Bluetooth to not be so fragile. A 58 platform independent method to identify 59 serial-over-Bluetooth devices would also be nice. 60 ''; 61 }; 62 63 nowait = mkOption { 64 type = types.bool; 65 default = false; 66 description = lib.mdDoc '' 67 don't wait for client connects to poll GPS 68 ''; 69 }; 70 71 port = mkOption { 72 type = types.port; 73 default = 2947; 74 description = lib.mdDoc '' 75 The port where to listen for TCP connections. 76 ''; 77 }; 78 79 debugLevel = mkOption { 80 type = types.int; 81 default = 0; 82 description = lib.mdDoc '' 83 The debugging level. 84 ''; 85 }; 86 87 listenany = mkOption { 88 type = types.bool; 89 default = false; 90 description = lib.mdDoc '' 91 Listen on all addresses rather than just loopback. 92 ''; 93 }; 94 95 }; 96 97 }; 98 99 ###### implementation 100 101 config = mkIf cfg.enable { 102 103 users.users.gpsd = { 104 inherit uid; 105 group = "gpsd"; 106 description = "gpsd daemon user"; 107 home = "/var/empty"; 108 }; 109 110 users.groups.gpsd = { inherit gid; }; 111 112 systemd.services.gpsd = { 113 description = "GPSD daemon"; 114 wantedBy = [ "multi-user.target" ]; 115 after = [ "network.target" ]; 116 serviceConfig = { 117 Type = "forking"; 118 ExecStart = let 119 devices = utils.escapeSystemdExecArgs cfg.devices; 120 in '' 121 ${pkgs.gpsd}/sbin/gpsd -D "${toString cfg.debugLevel}" \ 122 -S "${toString cfg.port}" \ 123 ${optionalString cfg.readonly "-b"} \ 124 ${optionalString cfg.nowait "-n"} \ 125 ${optionalString cfg.listenany "-G"} \ 126 ${devices} 127 ''; 128 }; 129 }; 130 131 }; 132 133}