at 16.09-beta 5.8 kB view raw
1{ config, lib, pkgs, ...}: 2 3with lib; 4 5let 6 cfg = config.services.mosquitto; 7 8 listenerConf = optionalString cfg.ssl.enable '' 9 listener ${toString cfg.ssl.port} ${cfg.ssl.host} 10 cafile ${cfg.ssl.cafile} 11 certfile ${cfg.ssl.certfile} 12 keyfile ${cfg.ssl.keyfile} 13 ''; 14 15 mosquittoConf = pkgs.writeText "mosquitto.conf" '' 16 pid_file /run/mosquitto/pid 17 acl_file ${aclFile} 18 persistence true 19 allow_anonymous ${if cfg.allowAnonymous then "true" else "false"} 20 bind_address ${cfg.host} 21 port ${toString cfg.port} 22 ${listenerConf} 23 ${cfg.extraConf} 24 ''; 25 26 userAcl = (concatStringsSep "\n\n" (mapAttrsToList (n: c: 27 "user ${n}\n" + (concatStringsSep "\n" c.acl)) cfg.users 28 )); 29 30 aclFile = pkgs.writeText "mosquitto.acl" '' 31 ${cfg.aclExtraConf} 32 ${userAcl} 33 ''; 34 35in 36 37{ 38 39 ###### Interface 40 41 options = { 42 services.mosquitto = { 43 enable = mkEnableOption "Enable the MQTT Mosquitto broker."; 44 45 host = mkOption { 46 default = "127.0.0.1"; 47 example = "0.0.0.0"; 48 type = types.string; 49 description = '' 50 Host to listen on without SSL. 51 ''; 52 }; 53 54 port = mkOption { 55 default = 1883; 56 example = 1883; 57 type = types.int; 58 description = '' 59 Port on which to listen without SSL. 60 ''; 61 }; 62 63 ssl = { 64 enable = mkEnableOption "Enable SSL listener."; 65 66 cafile = mkOption { 67 type = types.nullOr types.path; 68 default = null; 69 description = "Path to PEM encoded CA certificates."; 70 }; 71 72 certfile = mkOption { 73 type = types.nullOr types.path; 74 default = null; 75 description = "Path to PEM encoded server certificate."; 76 }; 77 78 keyfile = mkOption { 79 type = types.nullOr types.path; 80 default = null; 81 description = "Path to PEM encoded server key."; 82 }; 83 84 host = mkOption { 85 default = "0.0.0.0"; 86 example = "localhost"; 87 type = types.string; 88 description = '' 89 Host to listen on with SSL. 90 ''; 91 }; 92 93 port = mkOption { 94 default = 8883; 95 example = 8883; 96 type = types.int; 97 description = '' 98 Port on which to listen with SSL. 99 ''; 100 }; 101 }; 102 103 dataDir = mkOption { 104 default = "/var/lib/mosquitto"; 105 type = types.path; 106 description = '' 107 The data directory. 108 ''; 109 }; 110 111 users = mkOption { 112 type = types.attrsOf (types.submodule { 113 options = { 114 password = mkOption { 115 type = with types; uniq (nullOr str); 116 default = null; 117 description = '' 118 Specifies the (clear text) password for the MQTT User. 119 ''; 120 }; 121 122 hashedPassword = mkOption { 123 type = with types; uniq (nullOr str); 124 default = null; 125 description = '' 126 Specifies the hashed password for the MQTT User. 127 <option>hashedPassword</option> overrides <option>password</option>. 128 To generate hashed password install <literal>mkpasswd</literal> 129 package and run <literal>mkpasswd -m sha-512</literal>. 130 ''; 131 }; 132 133 acl = mkOption { 134 type = types.listOf types.string; 135 example = [ "topic read A/B" "topic A/#" ]; 136 description = '' 137 Control client access to topics on the broker. 138 ''; 139 }; 140 }; 141 }); 142 example = { john = { password = "123456"; acl = [ "topic readwrite john/#" ]; }; }; 143 description = '' 144 A set of users and their passwords and ACLs. 145 ''; 146 }; 147 148 allowAnonymous = mkOption { 149 default = false; 150 example = true; 151 type = types.bool; 152 description = '' 153 Allow clients to connect without authentication. 154 ''; 155 }; 156 157 extraConf = mkOption { 158 default = ""; 159 type = types.lines; 160 description = '' 161 Extra config to append to `mosquitto.conf` file. 162 ''; 163 }; 164 165 aclExtraConf = mkOption { 166 default = ""; 167 type = types.lines; 168 description = '' 169 Extra config to prepend to the ACL file. 170 ''; 171 }; 172 173 }; 174 }; 175 176 177 ###### Implementation 178 179 config = mkIf cfg.enable { 180 181 systemd.services.mosquitto = { 182 description = "Mosquitto MQTT Broker Daemon"; 183 wantedBy = [ "multi-user.target" ]; 184 after = [ "network.target" ]; 185 serviceConfig = { 186 Type = "forking"; 187 User = "mosquitto"; 188 Group = "mosquitto"; 189 RuntimeDirectory = "mosquitto"; 190 WorkingDirectory = cfg.dataDir; 191 Restart = "on-failure"; 192 ExecStart = "${pkgs.mosquitto}/bin/mosquitto -c ${mosquittoConf} -d"; 193 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; 194 PIDFile = "/run/mosquitto/pid"; 195 }; 196 preStart = '' 197 rm -f ${cfg.dataDir}/passwd 198 touch ${cfg.dataDir}/passwd 199 '' + concatStringsSep "\n" ( 200 mapAttrsToList (n: c: 201 if c.hashedPassword != null then 202 "echo '${n}:${c.hashedPassword}' > ${cfg.dataDir}/passwd" 203 else optionalString (c.password != null) 204 "${pkgs.mosquitto}/bin/mosquitto_passwd -b ${cfg.dataDir}/passwd ${n} ${c.password}" 205 ) cfg.users); 206 }; 207 208 users.extraUsers.mosquitto = { 209 description = "Mosquitto MQTT Broker Daemon owner"; 210 group = "mosquitto"; 211 uid = config.ids.uids.mosquitto; 212 home = cfg.dataDir; 213 createHome = true; 214 }; 215 216 users.extraGroups.mosquitto.gid = config.ids.gids.mosquitto; 217 218 }; 219}