Merge pull request #233377 from ncfavier/revert-226088

Revert "nixos/syncthing: use rfc42 style settings"
This commit is contained in:
Naïm Favier 2023-05-22 16:35:04 +02:00 committed by GitHub
commit 7b28ea6783
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 275 additions and 280 deletions

View file

@ -7,26 +7,25 @@ let
opt = options.services.syncthing; opt = options.services.syncthing;
defaultUser = "syncthing"; defaultUser = "syncthing";
defaultGroup = defaultUser; defaultGroup = defaultUser;
settingsFormat = pkgs.formats.json { };
devices = mapAttrsToList (_: device: device // { devices = mapAttrsToList (name: device: {
deviceID = device.id; deviceID = device.id;
}) cfg.settings.devices; inherit (device) name addresses introducer autoAcceptFolders;
}) cfg.devices;
folders = mapAttrsToList (_: folder: folder // folders = mapAttrsToList ( _: folder: {
throwIf (folder?rescanInterval || folder?watch || folder?watchDelay) '' inherit (folder) path id label type;
The options services.syncthing.settings.folders.<name>.{rescanInterval,watch,watchDelay} devices = map (device: { deviceId = cfg.devices.${device}.id; }) folder.devices;
were removed. Please use, respectively, {rescanIntervalS,fsWatcherEnabled,fsWatcherDelayS} instead. rescanIntervalS = folder.rescanInterval;
'' { fsWatcherEnabled = folder.watch;
devices = map (device: fsWatcherDelayS = folder.watchDelay;
if builtins.isString device then ignorePerms = folder.ignorePerms;
{ deviceId = cfg.settings.devices.${device}.id; } ignoreDelete = folder.ignoreDelete;
else versioning = folder.versioning;
device }) (filterAttrs (
) folder.devices; _: folder:
}) (filterAttrs (_: folder:
folder.enable folder.enable
) cfg.settings.folders); ) cfg.folders);
updateConfig = pkgs.writers.writeDash "merge-syncthing-config" '' updateConfig = pkgs.writers.writeDash "merge-syncthing-config" ''
set -efu set -efu
@ -55,10 +54,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 ${escapeShellArg ''. * ${builtins.toJSON cfg.settings} * { new_cfg=$(printf '%s\n' "$old_cfg" | ${pkgs.jq}/bin/jq -c '. * {
"devices": (${builtins.toJSON devices}${optionalString (cfg.settings.devices == {} || ! cfg.overrideDevices) " + .devices"}), "devices": (${builtins.toJSON devices}${optionalString (cfg.devices == {} || ! cfg.overrideDevices) " + .devices"}),
"folders": (${builtins.toJSON folders}${optionalString (cfg.settings.folders == {} || ! cfg.overrideFolders) " + .folders"}) "folders": (${builtins.toJSON folders}${optionalString (cfg.folders == {} || ! cfg.overrideFolders) " + .folders"})
}''}) } * ${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
@ -100,282 +99,287 @@ 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.settings.devices) option. [devices](#opt-services.syncthing.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.settings.folders) option. [folders](#opt-services.syncthing.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.
''; '';
}; };
settings = mkOption { folders = mkOption {
type = types.submodule { default = {};
freeformType = settingsFormat.type; 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, ... }: {
options = { options = {
# global options
options = mkOption { enable = mkOption {
default = {}; type = types.bool;
description = mdDoc '' default = true;
The options element contains all other global configuration options 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.
''; '';
type = types.submodule ({ name, ... }: { };
freeformType = settingsFormat.type;
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.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 {
options = { options = {
localAnnounceEnabled = mkOption { type = mkOption {
type = types.bool; type = enum [ "external" "simple" "staggered" "trashcan" ];
default = true; description = mdDoc ''
description = lib.mdDoc '' The type of versioning.
Whether to send announcements to the local LAN, also use such announcements to find other devices. See <https://docs.syncthing.net/users/versioning.html>.
''; '';
}; };
fsPath = mkOption {
localAnnouncePort = mkOption { default = "";
type = types.int; type = either str path;
default = 21027; description = mdDoc ''
description = lib.mdDoc '' Path to the versioning folder.
The port on which to listen and send IPv4 broadcast announcements to. See <https://docs.syncthing.net/users/versioning.html>.
''; '';
}; };
params = mkOption {
relaysEnabled = mkOption { type = attrsOf (either str path);
type = types.bool; description = mdDoc ''
default = true; The parameters for versioning. Structure depends on
description = lib.mdDoc '' [versioning.type](#opt-services.syncthing.folders._name_.versioning.type).
When true, relays will be connected to and potentially used for device to device connections. See <https://docs.syncthing.net/users/versioning.html>.
'';
};
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 rescanInterval = mkOption {
devices = mkOption { type = types.int;
default = {}; default = 3600;
description = mdDoc '' description = lib.mdDoc ''
Peers/devices which Syncthing should communicate with. How often the folder should be rescanned for changes.
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, ... }: {
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 type = mkOption {
folders = mkOption { type = types.enum [ "sendreceive" "sendonly" "receiveonly" "receiveencrypted" ];
default = {}; default = "sendreceive";
description = mdDoc '' description = lib.mdDoc ''
Folders which should be shared by Syncthing. Whether to only send changes for this folder, only receive them
or both. `receiveencrypted` can be used for untrusted devices. See
Note that you can still add folders manually, but those changes <https://docs.syncthing.net/users/untrusted.html> for reference.
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).
'';
};
};
}));
}; };
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 ''
Whether to skip deleting files that are deleted by peers.
See <https://docs.syncthing.net/advanced/folder-ignoredelete.html>.
'';
};
}; };
}; }));
};
extraOptions = mkOption {
type = types.addCheck (pkgs.formats.json {}).type isAttrs;
default = {}; default = {};
description = mdDoc '' description = mdDoc ''
Extra configuration options for Syncthing. Extra configuration options for Syncthing.
@ -526,10 +530,6 @@ 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,7 +615,9 @@ in {
]; ];
}; };
}; };
syncthing-init = mkIf (cfg.settings != {}) { syncthing-init = mkIf (
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

@ -9,21 +9,14 @@ in {
nodes.machine = { nodes.machine = {
services.syncthing = { services.syncthing = {
enable = true; enable = true;
settings = { devices.testDevice = {
options.crashReportingEnabled = false; id = testId;
devices.testDevice = {
id = testId;
};
folders.testFolder = {
path = "/tmp/test";
devices = [ "testDevice" ];
versioning = {
type = "simple";
params.keep = "10";
};
};
gui.user = "guiUser";
}; };
folders.testFolder = {
path = "/tmp/test";
devices = [ "testDevice" ];
};
extraOptions.gui.user = "guiUser";
}; };
}; };