From 919b39bb7c70a99b090b8e3debde5addc736c469 Mon Sep 17 00:00:00 2001 From: Kjartan Ovmilk Date: Thu, 1 Jun 2017 16:50:17 +0200 Subject: [PATCH] resilio service: replaces btsync service, which is no longer supported upstream. --- nixos/modules/misc/ids.nix | 2 + nixos/modules/module-list.nix | 1 + nixos/modules/services/networking/resilio.nix | 315 ++++++++++++++++++ 3 files changed, 318 insertions(+) create mode 100644 nixos/modules/services/networking/resilio.nix diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index d217b3452fb5..d7459e3fe91c 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -294,6 +294,7 @@ 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! @@ -557,6 +558,7 @@ 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 diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 7afcb9051bd7..47adfa334eed 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -485,6 +485,7 @@ ./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 diff --git a/nixos/modules/services/networking/resilio.nix b/nixos/modules/services/networking/resilio.nix new file mode 100644 index 000000000000..45274991d810 --- /dev/null +++ b/nixos/modules/services/networking/resilio.nix @@ -0,0 +1,315 @@ +{ 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 resilio service + also installs a systemd user unit which can be used to start + user-specific copies of the daemon. Once installed, you can use + systemctl --user start resilio as your user to start + the daemon using the configuration file located at + $HOME/.config/resilio-sync/config.json. + ''; + }; + + 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 + httpListenAddress and + httpListenPort. + ''; + }; + + 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 rslsync + --generate-secret. 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 resilio group. + + Directories in this list should be in the + resilio group, and that group must have + write access to the directory. It is also recommended that + chmod g+s is applied to the directory + so that any sub directories created will also belong to + the resilio group. Also, + setfacl -d -m group:resilio:rwx and + setfacl -m group:resilio:rwx 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 ]; + }; +}