at 17.09-beta 9.7 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 optionalEmptyStr = b: v: optionalString (b != "") v; 13 14 webUIConfig = optionalString cfg.enableWebUI 15 '' 16 "webui": 17 { 18 ${optionalEmptyStr cfg.httpLogin "\"login\": \"${cfg.httpLogin}\","} 19 ${optionalEmptyStr cfg.httpPass "\"password\": \"${cfg.httpPass}\","} 20 ${optionalEmptyStr cfg.apiKey "\"api_key\": \"${cfg.apiKey}\","} 21 ${optionalEmptyStr cfg.directoryRoot "\"directory_root\": \"${cfg.directoryRoot}\","} 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 boolToString entry.attr else boolToString 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": ${boolToString cfg.checkForUpdates}, 68 "use_upnp": ${boolToString cfg.useUpnp}, 69 "download_limit": ${toString cfg.downloadLimit}, 70 "upload_limit": ${toString cfg.uploadLimit}, 71 "lan_encrypt_data": ${boolToString 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, you can 86 interact with the service through the Web UI, or configure it in your 87 NixOS configuration. Enabling the <literal>btsync</literal> service 88 also installs a systemd user unit which can be used to start 89 user-specific copies of the daemon. Once installed, you can use 90 <literal>systemctl --user start btsync</literal> as your user to start 91 the daemon using the configuration file located at 92 <literal>$HOME/.config/btsync.conf</literal>. 93 ''; 94 }; 95 96 deviceName = mkOption { 97 type = types.str; 98 example = "Voltron"; 99 description = '' 100 Name of the Bittorrent Sync device. 101 ''; 102 }; 103 104 listeningPort = mkOption { 105 type = types.int; 106 default = 0; 107 example = 44444; 108 description = '' 109 Listening port. Defaults to 0 which randomizes the port. 110 ''; 111 }; 112 113 checkForUpdates = mkOption { 114 type = types.bool; 115 default = true; 116 description = '' 117 Determines whether to check for updates and alert the user 118 about them in the UI. 119 ''; 120 }; 121 122 useUpnp = mkOption { 123 type = types.bool; 124 default = true; 125 description = '' 126 Use Universal Plug-n-Play (UPnP) 127 ''; 128 }; 129 130 downloadLimit = mkOption { 131 type = types.int; 132 default = 0; 133 example = 1024; 134 description = '' 135 Download speed limit. 0 is unlimited (default). 136 ''; 137 }; 138 139 uploadLimit = mkOption { 140 type = types.int; 141 default = 0; 142 example = 1024; 143 description = '' 144 Upload speed limit. 0 is unlimited (default). 145 ''; 146 }; 147 148 httpListenAddr = mkOption { 149 type = types.str; 150 default = "0.0.0.0"; 151 example = "1.2.3.4"; 152 description = '' 153 HTTP address to bind to. 154 ''; 155 }; 156 157 httpListenPort = mkOption { 158 type = types.int; 159 default = 9000; 160 description = '' 161 HTTP port to bind on. 162 ''; 163 }; 164 165 httpLogin = mkOption { 166 type = types.str; 167 example = "allyourbase"; 168 default = ""; 169 description = '' 170 HTTP web login username. 171 ''; 172 }; 173 174 httpPass = mkOption { 175 type = types.str; 176 example = "arebelongtous"; 177 default = ""; 178 description = '' 179 HTTP web login password. 180 ''; 181 }; 182 183 encryptLAN = mkOption { 184 type = types.bool; 185 default = true; 186 description = "Encrypt LAN data."; 187 }; 188 189 enableWebUI = mkOption { 190 type = types.bool; 191 default = false; 192 description = '' 193 Enable Web UI for administration. Bound to the specified 194 <literal>httpListenAddress</literal> and 195 <literal>httpListenPort</literal>. 196 ''; 197 }; 198 199 package = mkOption { 200 type = types.package; 201 example = literalExample "pkgs.bittorrentSync20"; 202 description = '' 203 Branch of bittorrent sync to use. 204 ''; 205 }; 206 207 storagePath = mkOption { 208 type = types.path; 209 default = "/var/lib/btsync/"; 210 description = '' 211 Where BitTorrent Sync will store it's database files (containing 212 things like username info and licenses). Generally, you should not 213 need to ever change this. 214 ''; 215 }; 216 217 apiKey = mkOption { 218 type = types.str; 219 default = ""; 220 description = "API key, which enables the developer API."; 221 }; 222 223 directoryRoot = mkOption { 224 type = types.str; 225 default = ""; 226 example = "/media"; 227 description = "Default directory to add folders in the web UI."; 228 }; 229 230 sharedFolders = mkOption { 231 default = []; 232 example = 233 [ { secret = "AHMYFPCQAHBM7LQPFXQ7WV6Y42IGUXJ5Y"; 234 directory = "/home/user/sync_test"; 235 useRelayServer = true; 236 useTracker = true; 237 useDHT = false; 238 searchLAN = true; 239 useSyncTrash = true; 240 knownHosts = 241 [ "192.168.1.2:4444" 242 "192.168.1.3:4444" 243 ]; 244 } 245 ]; 246 description = '' 247 Shared folder list. If enabled, web UI must be 248 disabled. Secrets can be generated using <literal>btsync 249 --generate-secret</literal>. Note that this secret will be 250 put inside the Nix store, so it is realistically not very 251 secret. 252 253 If you would like to be able to modify the contents of this 254 directories, it is recommended that you make your user a 255 member of the <literal>btsync</literal> group. 256 257 Directories in this list should be in the 258 <literal>btsync</literal> group, and that group must have 259 write access to the directory. It is also recommended that 260 <literal>chmod g+s</literal> is applied to the directory 261 so that any sub directories created will also belong to 262 the <literal>btsync</literal> group. Also, 263 <literal>setfacl -d -m group:btsync:rwx</literal> and 264 <literal>setfacl -m group:btsync:rwx</literal> should also 265 be applied so that the sub directories are writable by 266 the group. 267 ''; 268 }; 269 }; 270 }; 271 272 config = mkIf cfg.enable { 273 assertions = 274 [ { assertion = cfg.deviceName != ""; 275 message = "Device name cannot be empty."; 276 } 277 { assertion = cfg.enableWebUI -> cfg.sharedFolders == []; 278 message = "If using shared folders, the web UI cannot be enabled."; 279 } 280 { assertion = cfg.apiKey != "" -> cfg.enableWebUI; 281 message = "If you're using an API key, you must enable the web server."; 282 } 283 ]; 284 285 services.btsync.package = mkOptionDefault pkgs.bittorrentSync14; 286 287 users.extraUsers.btsync = { 288 description = "Bittorrent Sync Service user"; 289 home = cfg.storagePath; 290 createHome = true; 291 uid = config.ids.uids.btsync; 292 group = "btsync"; 293 }; 294 295 users.extraGroups = [ 296 { name = "btsync"; 297 }]; 298 299 systemd.services.btsync = with pkgs; { 300 description = "Bittorrent Sync Service"; 301 wantedBy = [ "multi-user.target" ]; 302 after = [ "network.target" "local-fs.target" ]; 303 serviceConfig = { 304 Restart = "on-abort"; 305 UMask = "0002"; 306 User = "btsync"; 307 ExecStart = 308 "${bittorrentSync}/bin/btsync --nodaemon --config ${configFile}"; 309 }; 310 }; 311 312 systemd.user.services.btsync = with pkgs; { 313 description = "Bittorrent Sync user service"; 314 after = [ "network.target" "local-fs.target" ]; 315 serviceConfig = { 316 Restart = "on-abort"; 317 ExecStart = 318 "${bittorrentSync}/bin/btsync --nodaemon --config %h/.config/btsync.conf"; 319 }; 320 }; 321 322 environment.systemPackages = [ cfg.package ]; 323 }; 324}