at 23.05-pre 7.8 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.resilio; 7 8 resilioSync = pkgs.resilio-sync; 9 10 sharedFoldersRecord = map (entry: { 11 secret = entry.secret; 12 dir = entry.directory; 13 14 use_relay_server = entry.useRelayServer; 15 use_tracker = entry.useTracker; 16 use_dht = entry.useDHT; 17 18 search_lan = entry.searchLAN; 19 use_sync_trash = entry.useSyncTrash; 20 known_hosts = entry.knownHosts; 21 }) cfg.sharedFolders; 22 23 configFile = pkgs.writeText "config.json" (builtins.toJSON ({ 24 device_name = cfg.deviceName; 25 storage_path = cfg.storagePath; 26 listening_port = cfg.listeningPort; 27 use_gui = false; 28 check_for_updates = cfg.checkForUpdates; 29 use_upnp = cfg.useUpnp; 30 download_limit = cfg.downloadLimit; 31 upload_limit = cfg.uploadLimit; 32 lan_encrypt_data = cfg.encryptLAN; 33 } // optionalAttrs (cfg.directoryRoot != "") { directory_root = cfg.directoryRoot; } 34 // optionalAttrs cfg.enableWebUI { 35 webui = { listen = "${cfg.httpListenAddr}:${toString cfg.httpListenPort}"; } // 36 (optionalAttrs (cfg.httpLogin != "") { login = cfg.httpLogin; }) // 37 (optionalAttrs (cfg.httpPass != "") { password = cfg.httpPass; }) // 38 (optionalAttrs (cfg.apiKey != "") { api_key = cfg.apiKey; }); 39 } // optionalAttrs (sharedFoldersRecord != []) { 40 shared_folders = sharedFoldersRecord; 41 })); 42 43in 44{ 45 options = { 46 services.resilio = { 47 enable = mkOption { 48 type = types.bool; 49 default = false; 50 description = lib.mdDoc '' 51 If enabled, start the Resilio Sync daemon. Once enabled, you can 52 interact with the service through the Web UI, or configure it in your 53 NixOS configuration. 54 ''; 55 }; 56 57 deviceName = mkOption { 58 type = types.str; 59 example = "Voltron"; 60 default = config.networking.hostName; 61 defaultText = literalExpression "config.networking.hostName"; 62 description = lib.mdDoc '' 63 Name of the Resilio Sync device. 64 ''; 65 }; 66 67 listeningPort = mkOption { 68 type = types.int; 69 default = 0; 70 example = 44444; 71 description = lib.mdDoc '' 72 Listening port. Defaults to 0 which randomizes the port. 73 ''; 74 }; 75 76 checkForUpdates = mkOption { 77 type = types.bool; 78 default = true; 79 description = lib.mdDoc '' 80 Determines whether to check for updates and alert the user 81 about them in the UI. 82 ''; 83 }; 84 85 useUpnp = mkOption { 86 type = types.bool; 87 default = true; 88 description = lib.mdDoc '' 89 Use Universal Plug-n-Play (UPnP) 90 ''; 91 }; 92 93 downloadLimit = mkOption { 94 type = types.int; 95 default = 0; 96 example = 1024; 97 description = lib.mdDoc '' 98 Download speed limit. 0 is unlimited (default). 99 ''; 100 }; 101 102 uploadLimit = mkOption { 103 type = types.int; 104 default = 0; 105 example = 1024; 106 description = lib.mdDoc '' 107 Upload speed limit. 0 is unlimited (default). 108 ''; 109 }; 110 111 httpListenAddr = mkOption { 112 type = types.str; 113 default = "[::1]"; 114 example = "0.0.0.0"; 115 description = lib.mdDoc '' 116 HTTP address to bind to. 117 ''; 118 }; 119 120 httpListenPort = mkOption { 121 type = types.int; 122 default = 9000; 123 description = lib.mdDoc '' 124 HTTP port to bind on. 125 ''; 126 }; 127 128 httpLogin = mkOption { 129 type = types.str; 130 example = "allyourbase"; 131 default = ""; 132 description = lib.mdDoc '' 133 HTTP web login username. 134 ''; 135 }; 136 137 httpPass = mkOption { 138 type = types.str; 139 example = "arebelongtous"; 140 default = ""; 141 description = lib.mdDoc '' 142 HTTP web login password. 143 ''; 144 }; 145 146 encryptLAN = mkOption { 147 type = types.bool; 148 default = true; 149 description = lib.mdDoc "Encrypt LAN data."; 150 }; 151 152 enableWebUI = mkOption { 153 type = types.bool; 154 default = false; 155 description = lib.mdDoc '' 156 Enable Web UI for administration. Bound to the specified 157 `httpListenAddress` and 158 `httpListenPort`. 159 ''; 160 }; 161 162 storagePath = mkOption { 163 type = types.path; 164 default = "/var/lib/resilio-sync/"; 165 description = lib.mdDoc '' 166 Where BitTorrent Sync will store it's database files (containing 167 things like username info and licenses). Generally, you should not 168 need to ever change this. 169 ''; 170 }; 171 172 apiKey = mkOption { 173 type = types.str; 174 default = ""; 175 description = lib.mdDoc "API key, which enables the developer API."; 176 }; 177 178 directoryRoot = mkOption { 179 type = types.str; 180 default = ""; 181 example = "/media"; 182 description = lib.mdDoc "Default directory to add folders in the web UI."; 183 }; 184 185 sharedFolders = mkOption { 186 default = []; 187 type = types.listOf (types.attrsOf types.anything); 188 example = 189 [ { secret = "AHMYFPCQAHBM7LQPFXQ7WV6Y42IGUXJ5Y"; 190 directory = "/home/user/sync_test"; 191 useRelayServer = true; 192 useTracker = true; 193 useDHT = false; 194 searchLAN = true; 195 useSyncTrash = true; 196 knownHosts = [ 197 "192.168.1.2:4444" 198 "192.168.1.3:4444" 199 ]; 200 } 201 ]; 202 description = lib.mdDoc '' 203 Shared folder list. If enabled, web UI must be 204 disabled. Secrets can be generated using `rslsync --generate-secret`. 205 Note that this secret will be 206 put inside the Nix store, so it is realistically not very 207 secret. 208 209 If you would like to be able to modify the contents of this 210 directories, it is recommended that you make your user a 211 member of the `rslsync` group. 212 213 Directories in this list should be in the 214 `rslsync` group, and that group must have 215 write access to the directory. It is also recommended that 216 `chmod g+s` is applied to the directory 217 so that any sub directories created will also belong to 218 the `rslsync` group. Also, 219 `setfacl -d -m group:rslsync:rwx` and 220 `setfacl -m group:rslsync:rwx` should also 221 be applied so that the sub directories are writable by 222 the group. 223 ''; 224 }; 225 }; 226 }; 227 228 config = mkIf cfg.enable { 229 assertions = 230 [ { assertion = cfg.deviceName != ""; 231 message = "Device name cannot be empty."; 232 } 233 { assertion = cfg.enableWebUI -> cfg.sharedFolders == []; 234 message = "If using shared folders, the web UI cannot be enabled."; 235 } 236 { assertion = cfg.apiKey != "" -> cfg.enableWebUI; 237 message = "If you're using an API key, you must enable the web server."; 238 } 239 ]; 240 241 users.users.rslsync = { 242 description = "Resilio Sync Service user"; 243 home = cfg.storagePath; 244 createHome = true; 245 uid = config.ids.uids.rslsync; 246 group = "rslsync"; 247 }; 248 249 users.groups.rslsync = {}; 250 251 systemd.services.resilio = with pkgs; { 252 description = "Resilio Sync Service"; 253 wantedBy = [ "multi-user.target" ]; 254 after = [ "network.target" ]; 255 serviceConfig = { 256 Restart = "on-abort"; 257 UMask = "0002"; 258 User = "rslsync"; 259 ExecStart = '' 260 ${resilioSync}/bin/rslsync --nodaemon --config ${configFile} 261 ''; 262 }; 263 }; 264 }; 265}