1
0
Fork 1
mirror of https://github.com/NixOS/nixpkgs.git synced 2025-01-22 14:45:27 +00:00

nixos/syncthing: move declarative options to the top level

This commit is contained in:
Naïm Favier 2021-07-28 11:14:09 +02:00
parent a66d9f9b00
commit e9b01c5c8e
No known key found for this signature in database
GPG key ID: 49B07322580B7EE2
2 changed files with 279 additions and 281 deletions

View file

@ -9,11 +9,11 @@ let
devices = mapAttrsToList (name: device: { devices = mapAttrsToList (name: device: {
deviceID = device.id; deviceID = device.id;
inherit (device) name addresses introducer; inherit (device) name addresses introducer;
}) cfg.declarative.devices; }) cfg.devices;
folders = mapAttrsToList ( _: folder: { folders = mapAttrsToList ( _: folder: {
inherit (folder) path id label type; inherit (folder) path id label type;
devices = map (device: { deviceId = cfg.declarative.devices.${device}.id; }) folder.devices; devices = map (device: { deviceId = cfg.devices.${device}.id; }) folder.devices;
rescanIntervalS = folder.rescanInterval; rescanIntervalS = folder.rescanInterval;
fsWatcherEnabled = folder.watch; fsWatcherEnabled = folder.watch;
fsWatcherDelayS = folder.watchDelay; fsWatcherDelayS = folder.watchDelay;
@ -23,7 +23,7 @@ let
}) (filterAttrs ( }) (filterAttrs (
_: folder: _: folder:
folder.enable folder.enable
) cfg.declarative.folders); ) cfg.folders);
updateConfig = pkgs.writers.writeDash "merge-syncthing-config" '' updateConfig = pkgs.writers.writeDash "merge-syncthing-config" ''
set -efu set -efu
@ -50,9 +50,9 @@ let
# generate the new config by merging with the NixOS config options # generate the new config by merging with the NixOS config options
new_cfg=$(echo "$old_cfg" | ${pkgs.jq}/bin/jq -c '. * { new_cfg=$(echo "$old_cfg" | ${pkgs.jq}/bin/jq -c '. * {
"devices": (${builtins.toJSON devices}${optionalString (! cfg.declarative.overrideDevices) " + .devices"}), "devices": (${builtins.toJSON devices}${optionalString (! cfg.overrideDevices) " + .devices"}),
"folders": (${builtins.toJSON folders}${optionalString (! cfg.declarative.overrideFolders) " + .folders"}) "folders": (${builtins.toJSON folders}${optionalString (! cfg.overrideFolders) " + .folders"})
} * ${builtins.toJSON cfg.declarative.extraOptions}') } * ${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
@ -74,283 +74,281 @@ in {
available on http://127.0.0.1:8384/. available on http://127.0.0.1:8384/.
''; '';
declarative = { cert = mkOption {
cert = mkOption { type = types.nullOr types.str;
type = types.nullOr types.str; default = null;
default = null; description = ''
description = '' Path to users cert.pem file, will be copied into Syncthing's
Path to users cert.pem file, will be copied into Syncthing's <literal>configDir</literal>
<literal>configDir</literal> '';
''; };
};
key = mkOption { key = mkOption {
type = types.nullOr types.str; type = types.nullOr types.str;
default = null; default = null;
description = '' description = ''
Path to users key.pem file, will be copied into Syncthing's Path to users key.pem file, will be copied into Syncthing's
<literal>configDir</literal> <literal>configDir</literal>
''; '';
}; };
overrideDevices = mkOption { overrideDevices = mkOption {
type = types.bool; type = types.bool;
default = true; default = true;
description = '' description = ''
Whether to delete the devices which are not configured via the Whether to delete the devices which are not configured via the
<literal>declarative.devices</literal> option. <literal>devices</literal> option.
If set to false, devices added via the webinterface will If set to false, devices added via the webinterface will
persist but will have to be deleted manually. persist but will have to be deleted manually.
''; '';
}; };
devices = mkOption { devices = mkOption {
default = {}; default = {};
description = '' description = ''
Peers/devices which Syncthing should communicate with. Peers/devices which Syncthing should communicate with.
''; '';
example = { example = {
bigbox = { bigbox = {
id = "7CFNTQM-IMTJBHJ-3UWRDIU-ZGQJFR6-VCXZ3NB-XUH3KZO-N52ITXR-LAIYUAU"; id = "7CFNTQM-IMTJBHJ-3UWRDIU-ZGQJFR6-VCXZ3NB-XUH3KZO-N52ITXR-LAIYUAU";
addresses = [ "tcp://192.168.0.10:51820" ]; addresses = [ "tcp://192.168.0.10:51820" ];
};
}; };
type = types.attrsOf (types.submodule ({ name, ... }: { };
options = { type = types.attrsOf (types.submodule ({ name, ... }: {
options = {
name = mkOption {
type = types.str;
default = name;
description = ''
Name of the device
'';
};
addresses = mkOption {
type = types.listOf types.str;
default = [];
description = ''
The addresses used to connect to the device.
If this is let empty, dynamic configuration is attempted
'';
};
id = mkOption {
type = types.str;
description = ''
The id of the other peer, this is mandatory. It's documented at
https://docs.syncthing.net/dev/device-ids.html
'';
};
introducer = mkOption {
type = types.bool;
default = false;
description = ''
If the device should act as an introducer and be allowed
to add folders on this computer.
'';
};
name = mkOption {
type = types.str;
default = name;
description = ''
Name of the device
'';
}; };
}));
};
overrideFolders = mkOption { addresses = mkOption {
type = types.bool; type = types.listOf types.str;
default = true; default = [];
description = '' description = ''
Whether to delete the folders which are not configured via the The addresses used to connect to the device.
<literal>declarative.folders</literal> option. If this is let empty, dynamic configuration is attempted
If set to false, folders added via the webinterface will persist '';
but will have to be deleted manually. };
'';
};
folders = mkOption { id = mkOption {
default = {}; type = types.str;
description = '' description = ''
Folders which should be shared by Syncthing. The id of the other peer, this is mandatory. It's documented at
''; https://docs.syncthing.net/dev/device-ids.html
example = literalExample '' '';
{ };
"/home/user/sync" = {
id = "syncme";
devices = [ "bigbox" ];
};
}
'';
type = types.attrsOf (types.submodule ({ name, ... }: {
options = {
enable = mkOption { introducer = mkOption {
type = types.bool; type = types.bool;
default = true; default = false;
description = '' description = ''
share this folder. If the device should act as an introducer and be allowed
This option is useful when you want to define all folders to add folders on this computer.
in one place, but not every machine should share all folders. '';
''; };
};
path = mkOption { };
type = types.str; }));
default = name; };
description = ''
The path to the folder which should be shared.
'';
};
id = mkOption { overrideFolders = mkOption {
type = types.str; type = types.bool;
default = name; default = true;
description = '' description = ''
The id of the folder. Must be the same on all devices. Whether to delete the folders which are not configured via the
''; <literal>folders</literal> option.
}; If set to false, folders added via the webinterface will persist
but will have to be deleted manually.
'';
};
label = mkOption { folders = mkOption {
type = types.str; default = {};
default = name; description = ''
description = '' Folders which should be shared by Syncthing.
The label of the folder. '';
''; example = literalExample ''
}; {
"/home/user/sync" = {
id = "syncme";
devices = [ "bigbox" ];
};
}
'';
type = types.attrsOf (types.submodule ({ name, ... }: {
options = {
devices = mkOption { enable = mkOption {
type = types.listOf types.str; type = types.bool;
default = []; default = true;
description = '' description = ''
The devices this folder should be shared with. Must be defined share this folder.
in the <literal>declarative.devices</literal> attribute. This option is useful when you want to define all folders
''; in one place, but not every machine should share all folders.
}; '';
};
versioning = mkOption { path = mkOption {
default = null; type = types.str;
description = '' default = name;
How to keep changed/deleted files with Syncthing. description = ''
There are 4 different types of versioning with different parameters. The path to the folder which should be shared.
See https://docs.syncthing.net/users/versioning.html '';
''; };
example = [
{ id = mkOption {
versioning = { type = types.str;
type = "simple"; default = name;
params.keep = "10"; description = ''
}; The id of the folder. Must be the same on all devices.
} '';
{ };
versioning = {
type = "trashcan"; label = mkOption {
params.cleanoutDays = "1000"; type = types.str;
}; default = name;
} description = ''
{ The label of the folder.
versioning = { '';
type = "staggered"; };
params = {
cleanInterval = "3600"; devices = mkOption {
maxAge = "31536000"; type = types.listOf types.str;
versionsPath = "/syncthing/backup"; default = [];
}; description = ''
}; The devices this folder should be shared with. Must be defined
} in the <literal>devices</literal> attribute.
{ '';
versioning = { };
type = "external";
params.versionsPath = pkgs.writers.writeBash "backup" '' versioning = mkOption {
folderpath="$1" default = null;
filepath="$2" description = ''
rm -rf "$folderpath/$filepath" 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 = [
type = with types; nullOr (submodule { {
options = { versioning = {
type = mkOption { type = "simple";
type = enum [ "external" "simple" "staggered" "trashcan" ]; params.keep = "10";
description = '' };
Type of versioning. }
See https://docs.syncthing.net/users/versioning.html {
''; versioning = {
}; type = "trashcan";
params = mkOption { params.cleanoutDays = "1000";
type = attrsOf (either str path); };
description = '' }
Parameters for versioning. Structure depends on versioning.type. {
See https://docs.syncthing.net/users/versioning.html versioning = {
''; type = "staggered";
params = {
cleanInterval = "3600";
maxAge = "31536000";
versionsPath = "/syncthing/backup";
}; };
}; };
}); }
}; {
versioning = {
rescanInterval = mkOption { type = "external";
type = types.int; params.versionsPath = pkgs.writers.writeBash "backup" ''
default = 3600; folderpath="$1"
description = '' filepath="$2"
How often the folders should be rescaned for changes. rm -rf "$folderpath/$filepath"
''; '';
}; };
}
type = mkOption { ];
type = types.enum [ "sendreceive" "sendonly" "receiveonly" ]; type = with types; nullOr (submodule {
default = "sendreceive"; options = {
description = '' type = mkOption {
Whether to send only changes from this folder, only receive them type = enum [ "external" "simple" "staggered" "trashcan" ];
or propagate both. description = ''
''; Type of versioning.
}; See https://docs.syncthing.net/users/versioning.html
'';
watch = mkOption { };
type = types.bool; params = mkOption {
default = true; type = attrsOf (either str path);
description = '' description = ''
Whether the folder should be watched for changes by inotify. Parameters for versioning. Structure depends on versioning.type.
''; See https://docs.syncthing.net/users/versioning.html
}; '';
};
watchDelay = mkOption { };
type = types.int; });
default = 10;
description = ''
The delay after an inotify event is triggered.
'';
};
ignorePerms = mkOption {
type = types.bool;
default = true;
description = ''
Whether to propagate permission changes.
'';
};
ignoreDelete = mkOption {
type = types.bool;
default = false;
description = ''
Whether to delete files in destination. See <link
xlink:href="https://docs.syncthing.net/advanced/folder-ignoredelete.html">
upstream's docs</link>.
'';
};
}; };
}));
};
extraOptions = mkOption { rescanInterval = mkOption {
type = types.addCheck (pkgs.formats.json {}).type isAttrs; type = types.int;
default = {}; default = 3600;
description = '' description = ''
Extra configuration options for Syncthing. How often the folders should be rescaned for changes.
''; '';
example = { };
options.localAnnounceEnabled = false;
gui.theme = "black"; type = mkOption {
type = types.enum [ "sendreceive" "sendonly" "receiveonly" ];
default = "sendreceive";
description = ''
Whether to send only changes from this folder, only receive them
or propagate both.
'';
};
watch = mkOption {
type = types.bool;
default = true;
description = ''
Whether the folder should be watched for changes by inotify.
'';
};
watchDelay = mkOption {
type = types.int;
default = 10;
description = ''
The delay after an inotify event is triggered.
'';
};
ignorePerms = mkOption {
type = types.bool;
default = true;
description = ''
Whether to propagate permission changes.
'';
};
ignoreDelete = mkOption {
type = types.bool;
default = false;
description = ''
Whether to delete files in destination. See <link
xlink:href="https://docs.syncthing.net/advanced/folder-ignoredelete.html">
upstream's docs</link>.
'';
};
}; };
}));
};
extraOptions = mkOption {
type = types.addCheck (pkgs.formats.json {}).type isAttrs;
default = {};
description = ''
Extra configuration options for Syncthing.
'';
example = {
options.localAnnounceEnabled = false;
gui.theme = "black";
}; };
}; };
@ -443,11 +441,13 @@ in {
}; };
imports = [ imports = [
(mkRemovedOptionModule ["services" "syncthing" "useInotify"] '' (mkRemovedOptionModule [ "services" "syncthing" "useInotify" ] ''
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 webinterface. It can be enabled on a per-folder basis through the webinterface.
'') '')
]; ] ++ map (o:
mkRenamedOptionModule [ "services" "syncthing" "declarative" o ] [ "services" "syncthing" o ]
) [ "cert" "key" "devices" "folders" "overrideDevices" "overrideFolders" "extraOptions"];
###### implementation ###### implementation
@ -491,14 +491,14 @@ in {
RestartForceExitStatus="3 4"; RestartForceExitStatus="3 4";
User = cfg.user; User = cfg.user;
Group = cfg.group; Group = cfg.group;
ExecStartPre = mkIf (cfg.declarative.cert != null || cfg.declarative.key != null) ExecStartPre = mkIf (cfg.cert != null || cfg.key != null)
"+${pkgs.writers.writeBash "syncthing-copy-keys" '' "+${pkgs.writers.writeBash "syncthing-copy-keys" ''
install -dm700 -o ${cfg.user} -g ${cfg.group} ${cfg.configDir} install -dm700 -o ${cfg.user} -g ${cfg.group} ${cfg.configDir}
${optionalString (cfg.declarative.cert != null) '' ${optionalString (cfg.cert != null) ''
install -Dm400 -o ${cfg.user} -g ${cfg.group} ${toString cfg.declarative.cert} ${cfg.configDir}/cert.pem install -Dm400 -o ${cfg.user} -g ${cfg.group} ${toString cfg.cert} ${cfg.configDir}/cert.pem
''} ''}
${optionalString (cfg.declarative.key != null) '' ${optionalString (cfg.key != null) ''
install -Dm400 -o ${cfg.user} -g ${cfg.group} ${toString cfg.declarative.key} ${cfg.configDir}/key.pem install -Dm400 -o ${cfg.user} -g ${cfg.group} ${toString cfg.key} ${cfg.configDir}/key.pem
''} ''}
''}" ''}"
; ;
@ -529,7 +529,7 @@ in {
}; };
}; };
syncthing-init = mkIf ( syncthing-init = mkIf (
cfg.declarative.devices != {} || cfg.declarative.folders != {} || cfg.declarative.extraOptions != {} cfg.devices != {} || cfg.folders != {} || cfg.extraOptions != {}
) { ) {
description = "Syncthing configuration updater"; description = "Syncthing configuration updater";
after = [ "syncthing.service" ]; after = [ "syncthing.service" ];

View file

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