syncthing: Declarative

I could split this commit in more but I won't.
The first commit in this repository said it would be the last legible
one, and I haven't followed that, so YOLO.
This commit is contained in:
Geoffrey Frogeye 2024-06-23 23:57:03 +02:00
parent b7d56a3118
commit 8edb670486
Signed by: geoffrey
GPG key ID: C72403E7F82E6AD8
20 changed files with 222 additions and 45 deletions

View file

@ -1,6 +1,9 @@
{ pkgs, lib, ... }:
{ pkgs, lib, config, ... }:
{
networking.domain = "geoffrey.frogeye.fr";
networking = {
hostName = config.frogeye.name;
domain = "geoffrey.frogeye.fr";
};
time.timeZone = "Europe/Amsterdam";

View file

@ -32,6 +32,7 @@ do
done <<< "$(ls /nix/var/nix/profiles/system/specialisation)"
# Apply
confirm="n"
if [ "$verb" = "confirm" ]
then
echo "Apply configuration? [y/N]"

View file

@ -4,16 +4,28 @@ let
service = "syncthing";
secretsDir = "/etc/secrets/${service}";
password = {
path = "syncthing/${config.networking.hostName}";
path = "syncthing/${config.frogeye.name}";
selector = "@";
generator = ''(t="$(mktemp -d)" && ${lib.getExe pkgs.syncthing} generate --home="$t" &> /dev/null && cat "$t"/{cert,key}.pem && rm -rf "$t")'';
};
capitalizeFirstLetter = str: (lib.strings.toUpper (builtins.substring 0 1 str)) + (builtins.substring 1 (builtins.stringLength str) str);
nixosDevices = builtins.map (system: system.config.frogeye) (builtins.attrValues config.frogeye.toplevel.nixosConfigurations);
allDevices = nixosDevices;
syncingDevices = builtins.filter (device: device.syncthing.id != null) allDevices;
peerDevices = builtins.filter (device: device.name != config.frogeye.name) syncingDevices;
# Can't use the module's folders enable option, as it still requests things somehow
allFolders = builtins.attrValues config.frogeye.folders;
syncedFolders = builtins.filter (folder: folder.syncthing.enable) allFolders;
folderShouldSyncWith = folder: device: (lib.hasAttrByPath [ folder.name ] device.folders) && device.folders.${folder.name}.syncthing.enable;
folderDeviceEntry = folder: device: { deviceID = device.syncthing.id; };
in
{
config = lib.mkIf cfg.enable {
services.${service} = {
guiAddress = "127.0.0.1:8385"; # DEBUG
services.${service} = {
openDefaultPorts = true;
configDir = "/var/lib/${service}";
databaseDir = "/var/cache/${service}";
@ -21,14 +33,46 @@ in
key = "${secretsDir}/key.pem";
cert = "${secretsDir}/cert.pem";
settings = {
devices = builtins.listToAttrs (builtins.map (device: { inherit (device) name; value = device.syncthing; }) syncingDevices);
folders = builtins.listToAttrs (builtins.map
(folder: {
inherit (folder) name;
value =
{
label = "${capitalizeFirstLetter folder.user} ${folder.label}";
path = "${config.users.users.${folder.user}.home}/${folder.path}";
# Despite further in the code indicating this is possible, it is, actually not
# devices = builtins.map (folderDeviceEntry folder) (builtins.filter (folderShouldSyncWith folder) peerDevices);
devices = builtins.map (device: device.name) (builtins.filter (folderShouldSyncWith folder) peerDevices);
versioning =
if (config.frogeye.storageSize == "big" && folder.versionsMaxDays != null) then {
type = "staggered";
params.maxAge = builtins.toString (folder.versionsMaxDays * 24 * 3600);
# TODO Increase cleanupIntervalS to 1 day or so
} else null;
rescanIntervalS = 10 * 3600; # Using watcher, should be good enough
copyRangeMethod = "all"; # Prevents duplication
copyOwnershipFromParent = true;
} // folder.syncthing;
})
syncedFolders);
options = rec {
urAccepted = 3;
urSeen = urAccepted;
};
};
};
systemd.services.${service} = {
serviceConfig.ExecStartPre = [
systemd.services.${service}.serviceConfig = {
ExecStartPre = [
"+${pkgs.writeShellScript "syncthing-create-folders" ''
install -Dm700 -o ${cfg.user} -g ${cfg.group} -d ${cfg.configDir}
install -Dm700 -o ${cfg.user} -g ${cfg.group} -d ${cfg.databaseDir}
''}"
install -Dm700 -o ${cfg.user} -g ${cfg.group} -d ${cfg.configDir}
install -Dm700 -o ${cfg.user} -g ${cfg.group} -d ${cfg.databaseDir}
''}"
];
PrivateUsers = lib.mkForce false;
AmbientCapabilities = ["CAP_CHOWN" "CAP_DAC_OVERRIDE" "CAP_FOWNER"];
};
vivarium.passwordFiles = {
${cfg.key}.password = password // {