resilio service: replaces btsync service, which is no longer supported upstream.

Changed files
+318
nixos
modules
misc
services
networking
+2
nixos/modules/misc/ids.nix
···
jackett = 276;
aria2 = 277;
clickhouse = 278;
+
rslsync = 279;
# When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
···
jackett = 276;
aria2 = 277;
clickhouse = 278;
+
rslsync = 279;
# When adding a gid, make sure it doesn't match an existing
# uid. Users and groups with the same name should have equal
+1
nixos/modules/module-list.nix
···
./services/networking/radvd.nix
./services/networking/rdnssd.nix
./services/networking/redsocks.nix
+
./services/networking/resilio.nix
./services/networking/rpcbind.nix
./services/networking/sabnzbd.nix
./services/networking/searx.nix
+315
nixos/modules/services/networking/resilio.nix
···
+
{ config, lib, pkgs, ... }:
+
+
with lib;
+
+
let
+
cfg = config.services.resilio;
+
+
resilioSync = pkgs.resilio;
+
+
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":
+
{
+
${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}\","}
+
"listen": "${listenAddr}"
+
}
+
'';
+
+
knownHosts = e:
+
optionalString (e ? "knownHosts")
+
(concatStringsSep "," (map (v: "\"${v}\"") e."knownHosts"));
+
+
sharedFoldersRecord =
+
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 "config.json"
+
''
+
{
+
"device_name": "${cfg.deviceName}",
+
"storage_path": "${cfg.storagePath}",
+
"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.resilio = {
+
enable = mkOption {
+
type = types.bool;
+
default = false;
+
description = ''
+
If enabled, start the Resilio Sync daemon. Once enabled, you can
+
interact with the service through the Web UI, or configure it in your
+
NixOS configuration. Enabling the <literal>resilio</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 resilio</literal> as your user to start
+
the daemon using the configuration file located at
+
<literal>$HOME/.config/resilio-sync/config.json</literal>.
+
'';
+
};
+
+
deviceName = mkOption {
+
type = types.str;
+
example = "Voltron";
+
description = ''
+
Name of the Resilio 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";
+
default = "";
+
description = ''
+
HTTP web login username.
+
'';
+
};
+
+
httpPass = mkOption {
+
type = types.str;
+
example = "arebelongtous";
+
default = "";
+
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>.
+
'';
+
};
+
+
storagePath = mkOption {
+
type = types.path;
+
default = "/var/lib/resilio-sync/";
+
description = ''
+
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.
+
'';
+
};
+
+
apiKey = mkOption {
+
type = types.str;
+
default = "";
+
description = "API key, which enables the developer API.";
+
};
+
+
directoryRoot = mkOption {
+
type = types.str;
+
default = "";
+
example = "/media";
+
description = "Default directory to add folders in the web UI.";
+
};
+
+
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>rslsync
+
--generate-secret</literal>. Note that this secret will be
+
put inside the Nix store, so it is realistically not very
+
secret.
+
+
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>resilio</literal> group.
+
+
Directories in this list should be in the
+
<literal>resilio</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>resilio</literal> group. Also,
+
<literal>setfacl -d -m group:resilio:rwx</literal> and
+
<literal>setfacl -m group:resilio:rwx</literal> should also
+
be applied so that the sub directories are writable by
+
the group.
+
'';
+
};
+
};
+
};
+
+
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.";
+
}
+
];
+
+
services.resilio.package = mkOptionDefault pkgs.resilio;
+
+
users.extraUsers.rslsync = {
+
description = "Resilio Sync Service user";
+
home = cfg.storagePath;
+
createHome = true;
+
uid = config.ids.uids.rslsync;
+
group = "rslsync";
+
};
+
+
users.extraGroups = [ { name = "rslsync"; } ];
+
+
systemd.services.resilio = with pkgs; {
+
description = "Resilio Sync Service";
+
wantedBy = [ "multi-user.target" ];
+
after = [ "network.target" "local-fs.target" ];
+
serviceConfig = {
+
Restart = "on-abort";
+
UMask = "0002";
+
User = "rslsync";
+
ExecStart =
+
"${resilioSync}/bin/rslsync --nodaemon --config ${configFile}";
+
};
+
};
+
+
systemd.user.services.resilio = with pkgs; {
+
description = "Resilio Sync user service";
+
after = [ "network.target" "local-fs.target" ];
+
serviceConfig = {
+
Restart = "on-abort";
+
ExecStart =
+
"${resilioSync}/bin/rslsync --nodaemon --config %h/.config/resilio-sync/config.json";
+
};
+
};
+
+
environment.systemPackages = [ cfg.package ];
+
};
+
}