at 15.09-beta 9.4 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.btsync; 7 8 bittorrentSync = cfg.package; 9 10 listenAddr = cfg.httpListenAddr + ":" + (toString cfg.httpListenPort); 11 12 boolStr = x: if x then "true" else "false"; 13 optionalEmptyStr = b: v: optionalString (b != "") v; 14 15 webUIConfig = optionalString cfg.enableWebUI 16 '' 17 "webui": 18 { 19 ${optionalEmptyStr cfg.httpLogin "\"login\": \"${cfg.httpLogin}\","} 20 ${optionalEmptyStr cfg.httpPass "\"password\": \"${cfg.httpPass}\","} 21 ${optionalEmptyStr cfg.apiKey "\"api_key\": \"${cfg.apiKey}\","} 22 "listen": "${listenAddr}" 23 } 24 ''; 25 26 knownHosts = e: 27 optionalString (e ? "knownHosts") 28 (concatStringsSep "," (map (v: "\"${v}\"") e."knownHosts")); 29 30 sharedFoldersRecord = 31 concatStringsSep "," (map (entry: 32 let helper = attr: v: 33 if (entry ? attr) then boolStr entry.attr else boolStr v; 34 in 35 '' 36 { 37 "secret": "${entry.secret}", 38 "dir": "${entry.directory}", 39 40 "use_relay_server": ${helper "useRelayServer" true}, 41 "use_tracker": ${helper "useTracker" true}, 42 "use_dht": ${helper "useDHT" false}, 43 44 "search_lan": ${helper "searchLAN" true}, 45 "use_sync_trash": ${helper "useSyncTrash" true}, 46 47 "known_hosts": [${knownHosts entry}] 48 } 49 '') cfg.sharedFolders); 50 51 sharedFoldersConfig = optionalString (cfg.sharedFolders != []) 52 '' 53 "shared_folders": 54 [ 55 ${sharedFoldersRecord} 56 ] 57 ''; 58 59 configFile = pkgs.writeText "btsync.config" 60 '' 61 { 62 "device_name": "${cfg.deviceName}", 63 "storage_path": "${cfg.storagePath}", 64 "listening_port": ${toString cfg.listeningPort}, 65 "use_gui": false, 66 67 "check_for_updates": ${boolStr cfg.checkForUpdates}, 68 "use_upnp": ${boolStr cfg.useUpnp}, 69 "download_limit": ${toString cfg.downloadLimit}, 70 "upload_limit": ${toString cfg.uploadLimit}, 71 "lan_encrypt_data": ${boolStr cfg.encryptLAN}, 72 73 ${webUIConfig} 74 ${sharedFoldersConfig} 75 } 76 ''; 77in 78{ 79 options = { 80 services.btsync = { 81 enable = mkOption { 82 type = types.bool; 83 default = false; 84 description = '' 85 If enabled, start the Bittorrent Sync daemon. Once enabled, 86 you can interact with the service through the Web UI, or 87 configure it in your NixOS configuration. Enabling the 88 <literal>btsync</literal> service also installs a 89 multi-instance systemd unit which can be used to start 90 user-specific copies of the daemon. Once installed, you can 91 use <literal>systemctl start btsync@user</literal> to start 92 the daemon only for user <literal>user</literal>, using the 93 configuration file located at 94 <literal>$HOME/.config/btsync.conf</literal>. 95 ''; 96 }; 97 98 deviceName = mkOption { 99 type = types.str; 100 example = "Voltron"; 101 description = '' 102 Name of the Bittorrent Sync device. 103 ''; 104 }; 105 106 listeningPort = mkOption { 107 type = types.int; 108 default = 0; 109 example = 44444; 110 description = '' 111 Listening port. Defaults to 0 which randomizes the port. 112 ''; 113 }; 114 115 checkForUpdates = mkOption { 116 type = types.bool; 117 default = true; 118 description = '' 119 Determines whether to check for updates and alert the user 120 about them in the UI. 121 ''; 122 }; 123 124 useUpnp = mkOption { 125 type = types.bool; 126 default = true; 127 description = '' 128 Use Universal Plug-n-Play (UPnP) 129 ''; 130 }; 131 132 downloadLimit = mkOption { 133 type = types.int; 134 default = 0; 135 example = 1024; 136 description = '' 137 Download speed limit. 0 is unlimited (default). 138 ''; 139 }; 140 141 uploadLimit = mkOption { 142 type = types.int; 143 default = 0; 144 example = 1024; 145 description = '' 146 Upload speed limit. 0 is unlimited (default). 147 ''; 148 }; 149 150 httpListenAddr = mkOption { 151 type = types.str; 152 default = "0.0.0.0"; 153 example = "1.2.3.4"; 154 description = '' 155 HTTP address to bind to. 156 ''; 157 }; 158 159 httpListenPort = mkOption { 160 type = types.int; 161 default = 9000; 162 description = '' 163 HTTP port to bind on. 164 ''; 165 }; 166 167 httpLogin = mkOption { 168 type = types.str; 169 example = "allyourbase"; 170 default = ""; 171 description = '' 172 HTTP web login username. 173 ''; 174 }; 175 176 httpPass = mkOption { 177 type = types.str; 178 example = "arebelongtous"; 179 default = ""; 180 description = '' 181 HTTP web login password. 182 ''; 183 }; 184 185 encryptLAN = mkOption { 186 type = types.bool; 187 default = true; 188 description = "Encrypt LAN data."; 189 }; 190 191 enableWebUI = mkOption { 192 type = types.bool; 193 default = false; 194 description = '' 195 Enable Web UI for administration. Bound to the specified 196 <literal>httpListenAddress</literal> and 197 <literal>httpListenPort</literal>. 198 ''; 199 }; 200 201 package = mkOption { 202 type = types.package; 203 example = literalExample "pkgs.bittorrentSync20"; 204 description = '' 205 Branch of bittorrent sync to use. 206 ''; 207 }; 208 209 storagePath = mkOption { 210 type = types.path; 211 default = "/var/lib/btsync/"; 212 example = "/var/lib/btsync/"; 213 description = '' 214 Where to store the bittorrent sync files. 215 ''; 216 }; 217 218 apiKey = mkOption { 219 type = types.str; 220 default = ""; 221 description = "API key, which enables the developer API."; 222 }; 223 224 sharedFolders = mkOption { 225 default = []; 226 example = 227 [ { secret = "AHMYFPCQAHBM7LQPFXQ7WV6Y42IGUXJ5Y"; 228 directory = "/home/user/sync_test"; 229 useRelayServer = true; 230 useTracker = true; 231 useDHT = false; 232 searchLAN = true; 233 useSyncTrash = true; 234 knownHosts = 235 [ "192.168.1.2:4444" 236 "192.168.1.3:4444" 237 ]; 238 } 239 ]; 240 description = '' 241 Shared folder list. If enabled, web UI must be 242 disabled. Secrets can be generated using <literal>btsync 243 --generate-secret</literal>. Note that this secret will be 244 put inside the Nix store, so it is realistically not very 245 secret. 246 247 If you would like to be able to modify the contents of this 248 directories, it is recommended that you make your user a 249 member of the <literal>btsync</literal> group. 250 251 Directories in this list should be in the 252 <literal>btsync</literal> group, and that group must have 253 write access to the directory. It is also recommended that 254 <literal>chmod g+s</literal> is applied to the directory 255 so that any sub directories created will also belong to 256 the <literal>btsync</literal> group. Also, 257 <literal>setfacl -d -m group:btsync:rwx</literal> and 258 <literal>setfacl -m group:btsync:rwx</literal> should also 259 be applied so that the sub directories are writable by 260 the group. 261 ''; 262 }; 263 }; 264 }; 265 266 config = mkIf cfg.enable { 267 assertions = 268 [ { assertion = cfg.deviceName != ""; 269 message = "Device name cannot be empty."; 270 } 271 { assertion = cfg.enableWebUI -> cfg.sharedFolders == []; 272 message = "If using shared folders, the web UI cannot be enabled."; 273 } 274 { assertion = cfg.apiKey != "" -> cfg.enableWebUI; 275 message = "If you're using an API key, you must enable the web server."; 276 } 277 ]; 278 279 services.btsync.package = mkOptionDefault pkgs.bittorrentSync14; 280 281 users.extraUsers.btsync = { 282 description = "Bittorrent Sync Service user"; 283 home = cfg.storagePath; 284 createHome = true; 285 uid = config.ids.uids.btsync; 286 group = "btsync"; 287 }; 288 289 users.extraGroups = [ 290 { name = "btsync"; 291 }]; 292 293 systemd.services.btsync = with pkgs; { 294 description = "Bittorrent Sync Service"; 295 wantedBy = [ "multi-user.target" ]; 296 after = [ "network.target" "local-fs.target" ]; 297 serviceConfig = { 298 Restart = "on-abort"; 299 UMask = "0002"; 300 User = "btsync"; 301 ExecStart = 302 "${bittorrentSync}/bin/btsync --nodaemon --config ${configFile}"; 303 }; 304 }; 305 306 systemd.services."btsync@" = with pkgs; { 307 description = "Bittorrent Sync Service for %i"; 308 after = [ "network.target" "local-fs.target" ]; 309 serviceConfig = { 310 Restart = "on-abort"; 311 User = "%i"; 312 ExecStart = 313 "${bittorrentSync}/bin/btsync --nodaemon --config %h/.config/btsync.conf"; 314 }; 315 }; 316 317 environment.systemPackages = [ cfg.package ]; 318 }; 319}