| 
									
										
										
										
											2014-04-14 16:26:48 +02:00
										 |  |  | { config, lib, pkgs, ... }: | 
					
						
							| 
									
										
										
										
											2014-02-21 13:05:12 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-14 16:26:48 +02:00
										 |  |  | with lib; | 
					
						
							| 
									
										
										
										
											2014-02-21 13:05:12 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | let | 
					
						
							|  |  |  |   cfg = config.services.btsync; | 
					
						
							| 
									
										
										
										
											2015-04-06 15:31:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   bittorrentSync = cfg.package; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-21 13:05:12 -06:00
										 |  |  |   listenAddr = cfg.httpListenAddr + ":" + (toString cfg.httpListenPort); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   boolStr = x: if x then "true" else "false"; | 
					
						
							|  |  |  |   optionalEmptyStr = b: v: optionalString (b != "") v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   webUIConfig = optionalString cfg.enableWebUI | 
					
						
							|  |  |  |     ''
 | 
					
						
							|  |  |  |       "webui": | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2016-01-04 04:00:18 -06:00
										 |  |  |         ${optionalEmptyStr cfg.httpLogin     "\"login\":          \"${cfg.httpLogin}\","} | 
					
						
							|  |  |  |         ${optionalEmptyStr cfg.httpPass      "\"password\":       \"${cfg.httpPass}\","} | 
					
						
							|  |  |  |         ${optionalEmptyStr cfg.apiKey        "\"api_key\":        \"${cfg.apiKey}\","} | 
					
						
							|  |  |  |         ${optionalEmptyStr cfg.directoryRoot "\"directory_root\": \"${cfg.directoryRoot}\","} | 
					
						
							| 
									
										
										
										
											2014-02-21 13:05:12 -06:00
										 |  |  |         "listen": "${listenAddr}" | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     '';
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   knownHosts = e: | 
					
						
							|  |  |  |     optionalString (e ? "knownHosts") | 
					
						
							|  |  |  |       (concatStringsSep "," (map (v: "\"${v}\"") e."knownHosts")); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-14 16:26:48 +02:00
										 |  |  |   sharedFoldersRecord = | 
					
						
							| 
									
										
										
										
											2014-02-21 13:05:12 -06:00
										 |  |  |     concatStringsSep "," (map (entry: | 
					
						
							|  |  |  |       let helper = attr: v: | 
					
						
							|  |  |  |         if (entry ? attr) then boolStr entry.attr else boolStr v; | 
					
						
							|  |  |  |       in | 
					
						
							|  |  |  |       ''
 | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           "secret": "${entry.secret}", | 
					
						
							|  |  |  |           "dir":    "${entry.directory}", | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           "use_relay_server": ${helper "useRelayServer" true}, | 
					
						
							|  |  |  |           "use_tracker":      ${helper "useTracker"     true}, | 
					
						
							|  |  |  |           "use_dht":          ${helper "useDHT"        false}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           "search_lan":       ${helper "searchLAN"      true}, | 
					
						
							|  |  |  |           "use_sync_trash":   ${helper "useSyncTrash"   true}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           "known_hosts": [${knownHosts entry}] | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       '') cfg.sharedFolders);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   sharedFoldersConfig = optionalString (cfg.sharedFolders != []) | 
					
						
							|  |  |  |     ''
 | 
					
						
							|  |  |  |       "shared_folders": | 
					
						
							|  |  |  |         [ | 
					
						
							|  |  |  |         ${sharedFoldersRecord} | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |     '';
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   configFile = pkgs.writeText "btsync.config" | 
					
						
							|  |  |  |     ''
 | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         "device_name":     "${cfg.deviceName}", | 
					
						
							| 
									
										
										
										
											2015-04-06 15:31:40 +00:00
										 |  |  |         "storage_path":    "${cfg.storagePath}", | 
					
						
							| 
									
										
										
										
											2014-02-21 13:05:12 -06:00
										 |  |  |         "listening_port":  ${toString cfg.listeningPort}, | 
					
						
							|  |  |  |         "use_gui":         false, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         "check_for_updates": ${boolStr cfg.checkForUpdates}, | 
					
						
							|  |  |  |         "use_upnp":          ${boolStr cfg.useUpnp}, | 
					
						
							|  |  |  |         "download_limit":    ${toString cfg.downloadLimit}, | 
					
						
							|  |  |  |         "upload_limit":      ${toString cfg.uploadLimit}, | 
					
						
							|  |  |  |         "lan_encrypt_data":  ${boolStr cfg.encryptLAN}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ${webUIConfig} | 
					
						
							|  |  |  |         ${sharedFoldersConfig} | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     '';
 | 
					
						
							|  |  |  | in | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   options = { | 
					
						
							|  |  |  |     services.btsync = { | 
					
						
							|  |  |  |       enable = mkOption { | 
					
						
							|  |  |  |         type = types.bool; | 
					
						
							|  |  |  |         default = false; | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							| 
									
										
										
										
											2016-01-07 00:10:05 -06:00
										 |  |  |           If enabled, start the Bittorrent Sync daemon. Once enabled, you can | 
					
						
							|  |  |  |           interact with the service through the Web UI, or configure it in your | 
					
						
							|  |  |  |           NixOS configuration. Enabling the <literal>btsync</literal> service | 
					
						
							|  |  |  |           also installs a systemd user unit which can be used to start | 
					
						
							|  |  |  |           user-specific copies of the daemon. Once installed, you can use | 
					
						
							|  |  |  |           <literal>systemctl --user start btsync</literal> as your user to start | 
					
						
							|  |  |  |           the daemon using the configuration file located at | 
					
						
							| 
									
										
										
										
											2014-12-28 17:26:59 +08:00
										 |  |  |           <literal>$HOME/.config/btsync.conf</literal>. | 
					
						
							| 
									
										
										
										
											2014-02-21 13:05:12 -06:00
										 |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       deviceName = mkOption { | 
					
						
							|  |  |  |         type = types.str; | 
					
						
							|  |  |  |         example = "Voltron"; | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							|  |  |  |           Name of the Bittorrent Sync device. | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       listeningPort = mkOption { | 
					
						
							|  |  |  |         type = types.int; | 
					
						
							|  |  |  |         default = 0; | 
					
						
							|  |  |  |         example = 44444; | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							|  |  |  |           Listening port. Defaults to 0 which randomizes the port. | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       checkForUpdates = mkOption { | 
					
						
							|  |  |  |         type = types.bool; | 
					
						
							|  |  |  |         default = true; | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							|  |  |  |           Determines whether to check for updates and alert the user | 
					
						
							|  |  |  |           about them in the UI. | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       useUpnp = mkOption { | 
					
						
							|  |  |  |         type = types.bool; | 
					
						
							|  |  |  |         default = true; | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							|  |  |  |           Use Universal Plug-n-Play (UPnP) | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       downloadLimit = mkOption { | 
					
						
							|  |  |  |         type = types.int; | 
					
						
							|  |  |  |         default = 0; | 
					
						
							|  |  |  |         example = 1024; | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							|  |  |  |           Download speed limit. 0 is unlimited (default). | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       uploadLimit = mkOption { | 
					
						
							|  |  |  |         type = types.int; | 
					
						
							|  |  |  |         default = 0; | 
					
						
							|  |  |  |         example = 1024; | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							|  |  |  |           Upload speed limit. 0 is unlimited (default). | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       httpListenAddr = mkOption { | 
					
						
							|  |  |  |         type = types.str; | 
					
						
							|  |  |  |         default = "0.0.0.0"; | 
					
						
							|  |  |  |         example = "1.2.3.4"; | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							|  |  |  |           HTTP address to bind to. | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       httpListenPort = mkOption { | 
					
						
							|  |  |  |         type = types.int; | 
					
						
							|  |  |  |         default = 9000; | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							|  |  |  |           HTTP port to bind on. | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       httpLogin = mkOption { | 
					
						
							|  |  |  |         type = types.str; | 
					
						
							|  |  |  |         example = "allyourbase"; | 
					
						
							| 
									
										
										
										
											2014-05-02 00:41:47 -05:00
										 |  |  |         default = ""; | 
					
						
							| 
									
										
										
										
											2014-02-21 13:05:12 -06:00
										 |  |  |         description = ''
 | 
					
						
							|  |  |  |           HTTP web login username. | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       httpPass = mkOption { | 
					
						
							|  |  |  |         type = types.str; | 
					
						
							|  |  |  |         example = "arebelongtous"; | 
					
						
							| 
									
										
										
										
											2014-05-02 00:41:47 -05:00
										 |  |  |         default = ""; | 
					
						
							| 
									
										
										
										
											2014-02-21 13:05:12 -06:00
										 |  |  |         description = ''
 | 
					
						
							|  |  |  |           HTTP web login password. | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       encryptLAN = mkOption { | 
					
						
							|  |  |  |         type = types.bool; | 
					
						
							|  |  |  |         default = true; | 
					
						
							|  |  |  |         description = "Encrypt LAN data."; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       enableWebUI = mkOption { | 
					
						
							|  |  |  |         type = types.bool; | 
					
						
							|  |  |  |         default = false; | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							|  |  |  |           Enable Web UI for administration. Bound to the specified | 
					
						
							|  |  |  |           <literal>httpListenAddress</literal> and | 
					
						
							|  |  |  |           <literal>httpListenPort</literal>. | 
					
						
							|  |  |  |           '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-06 15:31:40 +00:00
										 |  |  |       package = mkOption { | 
					
						
							|  |  |  |         type = types.package; | 
					
						
							|  |  |  |         example = literalExample "pkgs.bittorrentSync20"; | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							|  |  |  |           Branch of bittorrent sync to use. | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       storagePath = mkOption { | 
					
						
							|  |  |  |         type = types.path; | 
					
						
							| 
									
										
										
										
											2015-06-05 18:39:01 +03:00
										 |  |  |         default = "/var/lib/btsync/"; | 
					
						
							|  |  |  |         example = "/var/lib/btsync/"; | 
					
						
							| 
									
										
										
										
											2015-04-06 15:31:40 +00:00
										 |  |  |         description = ''
 | 
					
						
							| 
									
										
										
										
											2016-01-07 00:10:05 -06:00
										 |  |  |           Where BitTorrent Sync will store it's database files (containing | 
					
						
							|  |  |  |           things like username info and licenses). Generally, you should not | 
					
						
							|  |  |  |           need to ever change this. | 
					
						
							| 
									
										
										
										
											2015-04-06 15:31:40 +00:00
										 |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-21 13:05:12 -06:00
										 |  |  |       apiKey = mkOption { | 
					
						
							|  |  |  |         type = types.str; | 
					
						
							|  |  |  |         default = ""; | 
					
						
							|  |  |  |         description = "API key, which enables the developer API."; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-04 04:00:18 -06:00
										 |  |  |       directoryRoot = mkOption { | 
					
						
							|  |  |  |         type = types.str; | 
					
						
							|  |  |  |         default = ""; | 
					
						
							|  |  |  |         example = "/media"; | 
					
						
							|  |  |  |         description = "Default directory to add folders in the web UI."; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-21 13:05:12 -06:00
										 |  |  |       sharedFolders = mkOption { | 
					
						
							|  |  |  |         default = []; | 
					
						
							|  |  |  |         example = | 
					
						
							|  |  |  |           [ { secret         = "AHMYFPCQAHBM7LQPFXQ7WV6Y42IGUXJ5Y"; | 
					
						
							|  |  |  |               directory      = "/home/user/sync_test"; | 
					
						
							|  |  |  |               useRelayServer = true; | 
					
						
							|  |  |  |               useTracker     = true; | 
					
						
							|  |  |  |               useDHT         = false; | 
					
						
							|  |  |  |               searchLAN      = true; | 
					
						
							|  |  |  |               useSyncTrash   = true; | 
					
						
							|  |  |  |               knownHosts     = | 
					
						
							|  |  |  |                 [ "192.168.1.2:4444" | 
					
						
							|  |  |  |                   "192.168.1.3:4444" | 
					
						
							|  |  |  |                 ]; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           ]; | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							|  |  |  |           Shared folder list. If enabled, web UI must be | 
					
						
							|  |  |  |           disabled. Secrets can be generated using <literal>btsync | 
					
						
							|  |  |  |           --generate-secret</literal>. Note that this secret will be | 
					
						
							|  |  |  |           put inside the Nix store, so it is realistically not very | 
					
						
							|  |  |  |           secret. | 
					
						
							| 
									
										
										
										
											2014-12-28 17:26:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |           If you would like to be able to modify the contents of this | 
					
						
							|  |  |  |           directories, it is recommended that you make your user a | 
					
						
							|  |  |  |           member of the <literal>btsync</literal> group. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           Directories in this list should be in the | 
					
						
							|  |  |  |           <literal>btsync</literal> group, and that group must have | 
					
						
							|  |  |  |           write access to the directory. It is also recommended that | 
					
						
							|  |  |  |           <literal>chmod g+s</literal> is applied to the directory | 
					
						
							|  |  |  |           so that any sub directories created will also belong to | 
					
						
							|  |  |  |           the <literal>btsync</literal> group. Also, | 
					
						
							|  |  |  |           <literal>setfacl -d -m group:btsync:rwx</literal> and | 
					
						
							|  |  |  |           <literal>setfacl -m group:btsync:rwx</literal> should also | 
					
						
							|  |  |  |           be applied so that the sub directories are writable by | 
					
						
							|  |  |  |           the group. | 
					
						
							| 
									
										
										
										
											2014-02-21 13:05:12 -06:00
										 |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   config = mkIf cfg.enable { | 
					
						
							|  |  |  |     assertions = | 
					
						
							|  |  |  |       [ { assertion = cfg.deviceName != ""; | 
					
						
							|  |  |  |           message   = "Device name cannot be empty."; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         { assertion = cfg.enableWebUI -> cfg.sharedFolders == []; | 
					
						
							|  |  |  |           message   = "If using shared folders, the web UI cannot be enabled."; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         { assertion = cfg.apiKey != "" -> cfg.enableWebUI; | 
					
						
							|  |  |  |           message   = "If you're using an API key, you must enable the web server."; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       ]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-08 23:10:42 +02:00
										 |  |  |     services.btsync.package = mkOptionDefault pkgs.bittorrentSync14; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-21 13:05:12 -06:00
										 |  |  |     users.extraUsers.btsync = { | 
					
						
							|  |  |  |       description     = "Bittorrent Sync Service user"; | 
					
						
							| 
									
										
										
										
											2015-04-06 15:31:40 +00:00
										 |  |  |       home            = cfg.storagePath; | 
					
						
							| 
									
										
										
										
											2014-02-21 13:05:12 -06:00
										 |  |  |       createHome      = true; | 
					
						
							|  |  |  |       uid             = config.ids.uids.btsync; | 
					
						
							| 
									
										
										
										
											2014-12-28 13:17:37 +08:00
										 |  |  |       group           = "btsync"; | 
					
						
							| 
									
										
										
										
											2014-02-21 13:05:12 -06:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-28 13:23:10 +08:00
										 |  |  |     users.extraGroups = [ | 
					
						
							|  |  |  |       { name = "btsync"; | 
					
						
							|  |  |  |       }]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-21 13:05:12 -06:00
										 |  |  |     systemd.services.btsync = with pkgs; { | 
					
						
							|  |  |  |       description = "Bittorrent Sync Service"; | 
					
						
							|  |  |  |       wantedBy    = [ "multi-user.target" ]; | 
					
						
							| 
									
										
										
										
											2015-04-23 12:52:54 +00:00
										 |  |  |       after       = [ "network.target" "local-fs.target" ]; | 
					
						
							| 
									
										
										
										
											2014-02-21 13:05:12 -06:00
										 |  |  |       serviceConfig = { | 
					
						
							|  |  |  |         Restart   = "on-abort"; | 
					
						
							| 
									
										
										
										
											2014-12-28 16:44:27 +08:00
										 |  |  |         UMask     = "0002"; | 
					
						
							| 
									
										
										
										
											2014-02-21 13:05:12 -06:00
										 |  |  |         User      = "btsync"; | 
					
						
							|  |  |  |         ExecStart = | 
					
						
							|  |  |  |           "${bittorrentSync}/bin/btsync --nodaemon --config ${configFile}"; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-07 00:10:05 -06:00
										 |  |  |     systemd.user.services.btsync = with pkgs; { | 
					
						
							|  |  |  |       description = "Bittorrent Sync user service"; | 
					
						
							| 
									
										
										
										
											2015-04-23 12:52:54 +00:00
										 |  |  |       after       = [ "network.target" "local-fs.target" ]; | 
					
						
							| 
									
										
										
										
											2014-02-21 13:05:12 -06:00
										 |  |  |       serviceConfig = { | 
					
						
							|  |  |  |         Restart   = "on-abort"; | 
					
						
							|  |  |  |         ExecStart = | 
					
						
							|  |  |  |           "${bittorrentSync}/bin/btsync --nodaemon --config %h/.config/btsync.conf"; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-06 15:31:40 +00:00
										 |  |  |     environment.systemPackages = [ cfg.package ]; | 
					
						
							| 
									
										
										
										
											2014-02-21 13:05:12 -06:00
										 |  |  |   }; | 
					
						
							|  |  |  | } |