Revert "Merge pull request #233377 from ncfavier/revert-226088"

This reverts commit 7b28ea6783, reversing
changes made to 3009b12817.
This commit is contained in:
lassulus 2023-05-22 16:56:23 +02:00 committed by Doron Behar
parent 6b568ce356
commit c42a7b668c
2 changed files with 274 additions and 276 deletions

View file

@ -7,25 +7,26 @@ let
opt = options.services.syncthing; opt = options.services.syncthing;
defaultUser = "syncthing"; defaultUser = "syncthing";
defaultGroup = defaultUser; defaultGroup = defaultUser;
settingsFormat = pkgs.formats.json { };
devices = mapAttrsToList (name: device: { devices = mapAttrsToList (_: device: device // {
deviceID = device.id; deviceID = device.id;
inherit (device) name addresses introducer autoAcceptFolders; }) cfg.settings.devices;
}) cfg.devices;
folders = mapAttrsToList ( _: folder: { folders = mapAttrsToList (_: folder: folder //
inherit (folder) path id label type; throwIf (folder?rescanInterval || folder?watch || folder?watchDelay) ''
devices = map (device: { deviceId = cfg.devices.${device}.id; }) folder.devices; The options services.syncthing.settings.folders.<name>.{rescanInterval,watch,watchDelay}
rescanIntervalS = folder.rescanInterval; were removed. Please use, respectively, {rescanIntervalS,fsWatcherEnabled,fsWatcherDelayS} instead.
fsWatcherEnabled = folder.watch; '' {
fsWatcherDelayS = folder.watchDelay; devices = map (device:
ignorePerms = folder.ignorePerms; if builtins.isString device then
ignoreDelete = folder.ignoreDelete; { deviceId = cfg.settings.devices.${device}.id; }
versioning = folder.versioning; else
}) (filterAttrs ( device
_: folder: ) folder.devices;
}) (filterAttrs (_: folder:
folder.enable folder.enable
) cfg.folders); ) cfg.settings.folders);
updateConfig = pkgs.writers.writeDash "merge-syncthing-config" '' updateConfig = pkgs.writers.writeDash "merge-syncthing-config" ''
set -efu set -efu
@ -54,10 +55,10 @@ let
old_cfg=$(curl ${cfg.guiAddress}/rest/config) old_cfg=$(curl ${cfg.guiAddress}/rest/config)
# generate the new config by merging with the NixOS config options # generate the new config by merging with the NixOS config options
new_cfg=$(printf '%s\n' "$old_cfg" | ${pkgs.jq}/bin/jq -c '. * { new_cfg=$(printf '%s\n' "$old_cfg" | ${pkgs.jq}/bin/jq -c ${escapeShellArg ''. * ${builtins.toJSON cfg.settings} * {
"devices": ('${escapeShellArg (builtins.toJSON devices)}'${optionalString (cfg.devices == {} || ! cfg.overrideDevices) " + .devices"}), "devices": ('${escapeShellArg (builtins.toJSON devices)}'${optionalString (cfg.settings.devices == {} || ! cfg.overrideDevices) " + .devices"}),
"folders": ('${escapeShellArg (builtins.toJSON folders)}'${optionalString (cfg.folders == {} || ! cfg.overrideFolders) " + .folders"}) "folders": ('${escapeShellArg (builtins.toJSON folders)}'${optionalString (cfg.settings.folders == {} || ! cfg.overrideFolders) " + .folders"})
} * '${escapeShellArg (builtins.toJSON cfg.extraOptions)}) }''})
# send the new config # send the new config
curl -X PUT -d "$new_cfg" ${cfg.guiAddress}/rest/config curl -X PUT -d "$new_cfg" ${cfg.guiAddress}/rest/config
@ -99,287 +100,282 @@ in {
default = true; default = true;
description = mdDoc '' description = mdDoc ''
Whether to delete the devices which are not configured via the 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 If set to `false`, devices added via the web
interface will persist and will have to be deleted manually. 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 <https://docs.syncthing.net/dev/device-ids.html>.
'';
};
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 <https://docs.syncthing.net/users/introducer.html>.
'';
};
autoAcceptFolders = mkOption {
type = types.bool;
default = false;
description = mdDoc ''
Automatically create or share folders that this device advertises at the default path.
See <https://docs.syncthing.net/users/config.html?highlight=autoaccept#config-file-format>.
'';
};
};
}));
};
overrideFolders = mkOption { overrideFolders = mkOption {
type = types.bool; type = types.bool;
default = true; default = true;
description = mdDoc '' description = mdDoc ''
Whether to delete the folders which are not configured via the 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 If set to `false`, folders added via the web
interface will persist and will have to be deleted manually. interface will persist and will have to be deleted manually.
''; '';
}; };
folders = mkOption { settings = mkOption {
default = {}; type = types.submodule {
description = mdDoc '' freeformType = settingsFormat.type;
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, ... }: {
options = { options = {
# global options
enable = mkOption { options = mkOption {
type = types.bool; default = {};
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.
'';
};
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.
'';
};
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 '' description = mdDoc ''
The devices this folder should be shared with. Each device must The options element contains all other global configuration options
be defined in the [devices](#opt-services.syncthing.devices) option.
''; '';
}; type = types.submodule ({ name, ... }: {
freeformType = settingsFormat.type;
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 <https://docs.syncthing.net/users/versioning.html>.
'';
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 {
options = { options = {
type = mkOption { localAnnounceEnabled = mkOption {
type = enum [ "external" "simple" "staggered" "trashcan" ]; type = types.bool;
description = mdDoc '' default = true;
The type of versioning. description = lib.mdDoc ''
See <https://docs.syncthing.net/users/versioning.html>. Whether to send announcements to the local LAN, also use such announcements to find other devices.
''; '';
}; };
fsPath = mkOption {
default = ""; localAnnouncePort = mkOption {
type = either str path; type = types.int;
description = mdDoc '' default = 21027;
Path to the versioning folder. description = lib.mdDoc ''
See <https://docs.syncthing.net/users/versioning.html>. The port on which to listen and send IPv4 broadcast announcements to.
''; '';
}; };
params = mkOption {
type = attrsOf (either str path); relaysEnabled = mkOption {
description = mdDoc '' type = types.bool;
The parameters for versioning. Structure depends on default = true;
[versioning.type](#opt-services.syncthing.folders._name_.versioning.type). description = lib.mdDoc ''
See <https://docs.syncthing.net/users/versioning.html>. When true, relays will be connected to and potentially used for device to device connections.
'';
};
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).
''; '';
}; };
}; };
}); });
}; };
rescanInterval = mkOption { # device settings
type = types.int; devices = mkOption {
default = 3600; default = {};
description = lib.mdDoc ''
How often the folder should be rescanned for changes.
'';
};
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
<https://docs.syncthing.net/users/untrusted.html> for reference.
'';
};
watch = mkOption {
type = types.bool;
default = true;
description = lib.mdDoc ''
Whether the folder should be watched for changes by inotify.
'';
};
watchDelay = mkOption {
type = types.int;
default = 10;
description = lib.mdDoc ''
The delay after an inotify event is triggered.
'';
};
ignorePerms = mkOption {
type = types.bool;
default = true;
description = lib.mdDoc ''
Whether to ignore permission changes.
'';
};
ignoreDelete = mkOption {
type = types.bool;
default = false;
description = mdDoc '' description = mdDoc ''
Whether to skip deleting files that are deleted by peers. Peers/devices which Syncthing should communicate with.
See <https://docs.syncthing.net/advanced/folder-ignoredelete.html>.
'';
};
};
}));
};
extraOptions = mkOption { Note that you can still add devices manually, but those changes
type = types.addCheck (pkgs.formats.json {}).type isAttrs; 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, ... }: {
freeformType = settingsFormat.type;
options = {
name = mkOption {
type = types.str;
default = name;
description = lib.mdDoc ''
The name of the device.
'';
};
id = mkOption {
type = types.str;
description = mdDoc ''
The device ID. See <https://docs.syncthing.net/dev/device-ids.html>.
'';
};
autoAcceptFolders = mkOption {
type = types.bool;
default = false;
description = mdDoc ''
Automatically create or share folders that this device advertises at the default path.
See <https://docs.syncthing.net/users/config.html?highlight=autoaccept#config-file-format>.
'';
};
};
}));
};
# folder settings
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, ... }: {
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.
'';
};
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.
'';
};
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 <https://docs.syncthing.net/users/versioning.html>.
'';
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 <https://docs.syncthing.net/users/versioning.html>.
'';
};
};
});
};
copyOwnershipFromParent = mkOption {
type = types.bool;
default = false;
description = mdDoc ''
On Unix systems, tries to copy file/folder ownership from the parent directory (the directory its located in).
Requires running Syncthing as a privileged user, or granting it additional capabilities (e.g. CAP_CHOWN on Linux).
'';
};
};
}));
};
};
};
default = {}; default = {};
description = mdDoc '' description = mdDoc ''
Extra configuration options for Syncthing. 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". 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. 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: ] ++ map (o:
mkRenamedOptionModule [ "services" "syncthing" "declarative" o ] [ "services" "syncthing" o ] mkRenamedOptionModule [ "services" "syncthing" "declarative" o ] [ "services" "syncthing" o ]
) [ "cert" "key" "devices" "folders" "overrideDevices" "overrideFolders" "extraOptions"]; ) [ "cert" "key" "devices" "folders" "overrideDevices" "overrideFolders" "extraOptions"];
@ -615,9 +615,7 @@ in {
]; ];
}; };
}; };
syncthing-init = mkIf ( syncthing-init = mkIf (cfg.settings != {}) {
cfg.devices != {} || cfg.folders != {} || cfg.extraOptions != {}
) {
description = "Syncthing configuration updater"; description = "Syncthing configuration updater";
requisite = [ "syncthing.service" ]; requisite = [ "syncthing.service" ];
after = [ "syncthing.service" ]; after = [ "syncthing.service" ];

View file

@ -10,14 +10,14 @@ in {
nodes.machine = { nodes.machine = {
services.syncthing = { services.syncthing = {
enable = true; enable = true;
devices.${testName} = { settings.devices.testDevice = {
id = testId; id = testId;
}; };
folders.testFolder = { settings.folders.testFolder = {
path = "/tmp/test"; path = "/tmp/test";
devices = [ testName ]; devices = [ "testDevice" ];
}; };
extraOptions.gui.user = "guiUser"; settings.gui.user = "guiUser";
}; };
}; };