From c42a7b668c340fb32bc40cf8dfd0214f85dbb0d1 Mon Sep 17 00:00:00 2001 From: lassulus Date: Mon, 22 May 2023 16:56:23 +0200 Subject: Revert "Merge pull request #233377 from ncfavier/revert-226088" This reverts commit 7b28ea6783baaeaebde2b58b13f141b4a6f8e050, reversing changes made to 3009b12817c15e439609aaa794815de40a27564b. --- nixos/modules/services/networking/syncthing.nix | 514 ++++++++++++------------ 1 file changed, 256 insertions(+), 258 deletions(-) (limited to 'nixos/modules/services/networking/syncthing.nix') diff --git a/nixos/modules/services/networking/syncthing.nix b/nixos/modules/services/networking/syncthing.nix index 69b45eb02d1..ca8adcf1357 100644 --- a/nixos/modules/services/networking/syncthing.nix +++ b/nixos/modules/services/networking/syncthing.nix @@ -7,25 +7,26 @@ let opt = options.services.syncthing; defaultUser = "syncthing"; defaultGroup = defaultUser; + settingsFormat = pkgs.formats.json { }; - devices = mapAttrsToList (name: device: { + devices = mapAttrsToList (_: device: device // { deviceID = device.id; - inherit (device) name addresses introducer autoAcceptFolders; - }) cfg.devices; - - folders = mapAttrsToList ( _: folder: { - inherit (folder) path id label type; - devices = map (device: { deviceId = cfg.devices.${device}.id; }) folder.devices; - rescanIntervalS = folder.rescanInterval; - fsWatcherEnabled = folder.watch; - fsWatcherDelayS = folder.watchDelay; - ignorePerms = folder.ignorePerms; - ignoreDelete = folder.ignoreDelete; - versioning = folder.versioning; - }) (filterAttrs ( - _: folder: + }) cfg.settings.devices; + + folders = mapAttrsToList (_: folder: folder // + throwIf (folder?rescanInterval || folder?watch || folder?watchDelay) '' + The options services.syncthing.settings.folders..{rescanInterval,watch,watchDelay} + were removed. Please use, respectively, {rescanIntervalS,fsWatcherEnabled,fsWatcherDelayS} instead. + '' { + devices = map (device: + if builtins.isString device then + { deviceId = cfg.settings.devices.${device}.id; } + else + device + ) folder.devices; + }) (filterAttrs (_: folder: folder.enable - ) cfg.folders); + ) cfg.settings.folders); updateConfig = pkgs.writers.writeDash "merge-syncthing-config" '' set -efu @@ -54,10 +55,10 @@ let old_cfg=$(curl ${cfg.guiAddress}/rest/config) # generate the new config by merging with the NixOS config options - new_cfg=$(printf '%s\n' "$old_cfg" | ${pkgs.jq}/bin/jq -c '. * { - "devices": ('${escapeShellArg (builtins.toJSON devices)}'${optionalString (cfg.devices == {} || ! cfg.overrideDevices) " + .devices"}), - "folders": ('${escapeShellArg (builtins.toJSON folders)}'${optionalString (cfg.folders == {} || ! cfg.overrideFolders) " + .folders"}) - } * '${escapeShellArg (builtins.toJSON cfg.extraOptions)}) + new_cfg=$(printf '%s\n' "$old_cfg" | ${pkgs.jq}/bin/jq -c ${escapeShellArg ''. * ${builtins.toJSON cfg.settings} * { + "devices": ('${escapeShellArg (builtins.toJSON devices)}'${optionalString (cfg.settings.devices == {} || ! cfg.overrideDevices) " + .devices"}), + "folders": ('${escapeShellArg (builtins.toJSON folders)}'${optionalString (cfg.settings.folders == {} || ! cfg.overrideFolders) " + .folders"}) + }''}) # send the new config curl -X PUT -d "$new_cfg" ${cfg.guiAddress}/rest/config @@ -99,287 +100,282 @@ in { default = true; description = mdDoc '' Whether to delete the devices which are not configured via the - [devices](#opt-services.syncthing.devices) option. + [devices](#opt-services.syncthing.settings.devices) option. If set to `false`, devices added via the web interface will persist and will have to be deleted manually. ''; }; - devices = mkOption { - default = {}; - description = mdDoc '' - Peers/devices which Syncthing should communicate with. - - Note that you can still add devices manually, but those changes - will be reverted on restart if [overrideDevices](#opt-services.syncthing.overrideDevices) - is enabled. - ''; - example = { - bigbox = { - id = "7CFNTQM-IMTJBHJ-3UWRDIU-ZGQJFR6-VCXZ3NB-XUH3KZO-N52ITXR-LAIYUAU"; - addresses = [ "tcp://192.168.0.10:51820" ]; - }; - }; - type = types.attrsOf (types.submodule ({ name, ... }: { - options = { - - name = mkOption { - type = types.str; - default = name; - description = lib.mdDoc '' - The name of the device. - ''; - }; - - addresses = mkOption { - type = types.listOf types.str; - default = []; - description = lib.mdDoc '' - The addresses used to connect to the device. - If this is left empty, dynamic configuration is attempted. - ''; - }; - - id = mkOption { - type = types.str; - description = mdDoc '' - The device ID. See . - ''; - }; - - introducer = mkOption { - type = types.bool; - default = false; - description = mdDoc '' - Whether the device should act as an introducer and be allowed - to add folders on this computer. - See . - ''; - }; - - autoAcceptFolders = mkOption { - type = types.bool; - default = false; - description = mdDoc '' - Automatically create or share folders that this device advertises at the default path. - See . - ''; - }; - - }; - })); - }; - overrideFolders = mkOption { type = types.bool; default = true; description = mdDoc '' Whether to delete the folders which are not configured via the - [folders](#opt-services.syncthing.folders) option. + [folders](#opt-services.syncthing.settings.folders) option. If set to `false`, folders added via the web interface will persist and will have to be deleted manually. ''; }; - folders = mkOption { - default = {}; - description = mdDoc '' - Folders which should be shared by Syncthing. - - Note that you can still add folders manually, but those changes - will be reverted on restart if [overrideFolders](#opt-services.syncthing.overrideFolders) - is enabled. - ''; - example = literalExpression '' - { - "/home/user/sync" = { - id = "syncme"; - devices = [ "bigbox" ]; - }; - } - ''; - type = types.attrsOf (types.submodule ({ name, ... }: { + settings = mkOption { + type = types.submodule { + freeformType = settingsFormat.type; options = { - - enable = mkOption { - type = types.bool; - default = true; - description = lib.mdDoc '' - Whether to share this folder. - This option is useful when you want to define all folders - in one place, but not every machine should share all folders. + # global options + options = mkOption { + default = {}; + description = mdDoc '' + The options element contains all other global configuration options ''; - }; + type = types.submodule ({ name, ... }: { + freeformType = settingsFormat.type; + options = { + localAnnounceEnabled = mkOption { + type = types.bool; + default = true; + description = lib.mdDoc '' + Whether to send announcements to the local LAN, also use such announcements to find other devices. + ''; + }; - path = mkOption { - # TODO for release 23.05: allow relative paths again and set - # working directory to cfg.dataDir - type = types.str // { - check = x: types.str.check x && (substring 0 1 x == "/" || substring 0 2 x == "~/"); - description = types.str.description + " starting with / or ~/"; - }; - default = name; - description = lib.mdDoc '' - The path to the folder which should be shared. - Only absolute paths (starting with `/`) and paths relative to - the [user](#opt-services.syncthing.user)'s home directory - (starting with `~/`) are allowed. - ''; - }; + localAnnouncePort = mkOption { + type = types.int; + default = 21027; + description = lib.mdDoc '' + The port on which to listen and send IPv4 broadcast announcements to. + ''; + }; - id = mkOption { - type = types.str; - default = name; - description = lib.mdDoc '' - The ID of the folder. Must be the same on all devices. - ''; - }; + relaysEnabled = mkOption { + type = types.bool; + default = true; + description = lib.mdDoc '' + When true, relays will be connected to and potentially used for device to device connections. + ''; + }; - label = mkOption { - type = types.str; - default = name; - description = lib.mdDoc '' - The label of the folder. - ''; + urAccepted = mkOption { + type = types.int; + default = 0; + description = lib.mdDoc '' + Whether the user has accepted to submit anonymous usage data. + The default, 0, mean the user has not made a choice, and Syncthing will ask at some point in the future. + "-1" means no, a number above zero means that that version of usage reporting has been accepted. + ''; + }; + + limitBandwidthInLan = mkOption { + type = types.bool; + default = false; + description = lib.mdDoc '' + Whether to apply bandwidth limits to devices in the same broadcast domain as the local device. + ''; + }; + + maxFolderConcurrency = mkOption { + type = types.int; + default = 0; + description = lib.mdDoc '' + This option controls how many folders may concurrently be in I/O-intensive operations such as syncing or scanning. + The mechanism is described in detail in a [separate chapter](https://docs.syncthing.net/advanced/option-max-concurrency.html). + ''; + }; + }; + }); }; + # device settings devices = mkOption { - type = types.listOf types.str; - default = []; + default = {}; description = mdDoc '' - The devices this folder should be shared with. Each device must - be defined in the [devices](#opt-services.syncthing.devices) option. - ''; - }; + Peers/devices which Syncthing should communicate with. - versioning = mkOption { - default = null; - description = mdDoc '' - How to keep changed/deleted files with Syncthing. - There are 4 different types of versioning with different parameters. - See . - ''; - example = literalExpression '' - [ - { - versioning = { - type = "simple"; - params.keep = "10"; - }; - } - { - versioning = { - type = "trashcan"; - params.cleanoutDays = "1000"; - }; - } - { - versioning = { - type = "staggered"; - fsPath = "/syncthing/backup"; - params = { - cleanInterval = "3600"; - maxAge = "31536000"; - }; - }; - } - { - versioning = { - type = "external"; - params.versionsPath = pkgs.writers.writeBash "backup" ''' - folderpath="$1" - filepath="$2" - rm -rf "$folderpath/$filepath" - '''; - }; - } - ] + Note that you can still add devices manually, but those changes + will be reverted on restart if [overrideDevices](#opt-services.syncthing.overrideDevices) + is enabled. ''; - type = with types; nullOr (submodule { + example = { + bigbox = { + id = "7CFNTQM-IMTJBHJ-3UWRDIU-ZGQJFR6-VCXZ3NB-XUH3KZO-N52ITXR-LAIYUAU"; + addresses = [ "tcp://192.168.0.10:51820" ]; + }; + }; + type = types.attrsOf (types.submodule ({ name, ... }: { + freeformType = settingsFormat.type; options = { - type = mkOption { - type = enum [ "external" "simple" "staggered" "trashcan" ]; - description = mdDoc '' - The type of versioning. - See . + + name = mkOption { + type = types.str; + default = name; + description = lib.mdDoc '' + The name of the device. ''; }; - fsPath = mkOption { - default = ""; - type = either str path; + + id = mkOption { + type = types.str; description = mdDoc '' - Path to the versioning folder. - See . + The device ID. See . ''; }; - params = mkOption { - type = attrsOf (either str path); + + autoAcceptFolders = mkOption { + type = types.bool; + default = false; description = mdDoc '' - The parameters for versioning. Structure depends on - [versioning.type](#opt-services.syncthing.folders._name_.versioning.type). - See . + Automatically create or share folders that this device advertises at the default path. + See . ''; }; + }; - }); + })); }; - rescanInterval = mkOption { - type = types.int; - default = 3600; - description = lib.mdDoc '' - How often the folder should be rescanned for changes. - ''; - }; + # folder settings + folders = mkOption { + default = {}; + description = mdDoc '' + Folders which should be shared by Syncthing. - type = mkOption { - type = types.enum [ "sendreceive" "sendonly" "receiveonly" "receiveencrypted" ]; - default = "sendreceive"; - description = lib.mdDoc '' - Whether to only send changes for this folder, only receive them - or both. `receiveencrypted` can be used for untrusted devices. See - for reference. + Note that you can still add folders manually, but those changes + will be reverted on restart if [overrideFolders](#opt-services.syncthing.overrideFolders) + is enabled. ''; - }; - - watch = mkOption { - type = types.bool; - default = true; - description = lib.mdDoc '' - Whether the folder should be watched for changes by inotify. + example = literalExpression '' + { + "/home/user/sync" = { + id = "syncme"; + devices = [ "bigbox" ]; + }; + } ''; - }; + type = types.attrsOf (types.submodule ({ name, ... }: { + freeformType = settingsFormat.type; + options = { - watchDelay = mkOption { - type = types.int; - default = 10; - description = lib.mdDoc '' - The delay after an inotify event is triggered. - ''; - }; + enable = mkOption { + type = types.bool; + default = true; + description = lib.mdDoc '' + Whether to share this folder. + This option is useful when you want to define all folders + in one place, but not every machine should share all folders. + ''; + }; - ignorePerms = mkOption { - type = types.bool; - default = true; - description = lib.mdDoc '' - Whether to ignore permission changes. - ''; - }; + path = mkOption { + # TODO for release 23.05: allow relative paths again and set + # working directory to cfg.dataDir + type = types.str // { + check = x: types.str.check x && (substring 0 1 x == "/" || substring 0 2 x == "~/"); + description = types.str.description + " starting with / or ~/"; + }; + default = name; + description = lib.mdDoc '' + The path to the folder which should be shared. + Only absolute paths (starting with `/`) and paths relative to + the [user](#opt-services.syncthing.user)'s home directory + (starting with `~/`) are allowed. + ''; + }; - ignoreDelete = mkOption { - type = types.bool; - default = false; - description = mdDoc '' - Whether to skip deleting files that are deleted by peers. - See . - ''; + id = mkOption { + type = types.str; + default = name; + description = lib.mdDoc '' + The ID of the folder. Must be the same on all devices. + ''; + }; + + label = mkOption { + type = types.str; + default = name; + description = lib.mdDoc '' + The label of the folder. + ''; + }; + + devices = mkOption { + type = types.listOf types.str; + default = []; + description = mdDoc '' + The devices this folder should be shared with. Each device must + be defined in the [devices](#opt-services.syncthing.settings.devices) option. + ''; + }; + + versioning = mkOption { + default = null; + description = mdDoc '' + How to keep changed/deleted files with Syncthing. + There are 4 different types of versioning with different parameters. + See . + ''; + example = literalExpression '' + [ + { + versioning = { + type = "simple"; + params.keep = "10"; + }; + } + { + versioning = { + type = "trashcan"; + params.cleanoutDays = "1000"; + }; + } + { + versioning = { + type = "staggered"; + fsPath = "/syncthing/backup"; + params = { + cleanInterval = "3600"; + maxAge = "31536000"; + }; + }; + } + { + versioning = { + type = "external"; + params.versionsPath = pkgs.writers.writeBash "backup" ''' + folderpath="$1" + filepath="$2" + rm -rf "$folderpath/$filepath" + '''; + }; + } + ] + ''; + type = with types; nullOr (submodule { + freeformType = settingsFormat.type; + options = { + type = mkOption { + type = enum [ "external" "simple" "staggered" "trashcan" ]; + description = mdDoc '' + The type of versioning. + See . + ''; + }; + }; + }); + }; + + copyOwnershipFromParent = mkOption { + type = types.bool; + default = false; + description = mdDoc '' + On Unix systems, tries to copy file/folder ownership from the parent directory (the directory it’s located in). + Requires running Syncthing as a privileged user, or granting it additional capabilities (e.g. CAP_CHOWN on Linux). + ''; + }; + }; + })); }; - }; - })); - }; - extraOptions = mkOption { - type = types.addCheck (pkgs.formats.json {}).type isAttrs; + }; + }; default = {}; description = mdDoc '' Extra configuration options for Syncthing. @@ -530,6 +526,10 @@ in { This option was removed because Syncthing now has the inotify functionality included under the name "fswatcher". It can be enabled on a per-folder basis through the web interface. '') + (mkRenamedOptionModule [ "services" "syncthing" "extraOptions" ] [ "services" "syncthing" "settings" ]) + (mkRenamedOptionModule [ "services" "syncthing" "folders" ] [ "services" "syncthing" "settings" "folders" ]) + (mkRenamedOptionModule [ "services" "syncthing" "devices" ] [ "services" "syncthing" "settings" "devices" ]) + (mkRenamedOptionModule [ "services" "syncthing" "options" ] [ "services" "syncthing" "settings" "options" ]) ] ++ map (o: mkRenamedOptionModule [ "services" "syncthing" "declarative" o ] [ "services" "syncthing" o ] ) [ "cert" "key" "devices" "folders" "overrideDevices" "overrideFolders" "extraOptions"]; @@ -615,9 +615,7 @@ in { ]; }; }; - syncthing-init = mkIf ( - cfg.devices != {} || cfg.folders != {} || cfg.extraOptions != {} - ) { + syncthing-init = mkIf (cfg.settings != {}) { description = "Syncthing configuration updater"; requisite = [ "syncthing.service" ]; after = [ "syncthing.service" ]; -- cgit 1.4.1