diff --git a/clanModules/flake-module.nix b/clanModules/flake-module.nix index 27c9ebd7b..7e1b46e54 100644 --- a/clanModules/flake-module.nix +++ b/clanModules/flake-module.nix @@ -17,6 +17,7 @@ sunshine = ./sunshine; static-hosts = ./static-hosts; syncthing = ./syncthing; + syncthing-static-peers = ./syncthing-static-peers; thelounge = ./thelounge; trusted-nix-caches = ./trusted-nix-caches; user-password = ./user-password; diff --git a/clanModules/syncthing-static-peers/README.md b/clanModules/syncthing-static-peers/README.md new file mode 100644 index 000000000..6d79cf603 --- /dev/null +++ b/clanModules/syncthing-static-peers/README.md @@ -0,0 +1,2 @@ +Statically configure syncthing peers through clan +--- diff --git a/clanModules/syncthing-static-peers/default.nix b/clanModules/syncthing-static-peers/default.nix new file mode 100644 index 000000000..89d2a5e1d --- /dev/null +++ b/clanModules/syncthing-static-peers/default.nix @@ -0,0 +1,91 @@ +{ + lib, + config, + pkgs, + ... +}: +let + clanDir = config.clanCore.clanDir; + machineDir = clanDir + "/machines/"; + syncthingPublicKeyPath = machines: machineDir + machines + "/facts/syncthing.pub"; + machinesFileSet = builtins.readDir machineDir; + machines = lib.mapAttrsToList (name: _: name) machinesFileSet; + syncthingPublicKeysUnchecked = builtins.map ( + machine: + let + fullPath = syncthingPublicKeyPath machine; + in + if builtins.pathExists fullPath then machine else null + ) machines; + syncthingPublicKeyMachines = lib.filter (machine: machine != null) syncthingPublicKeysUnchecked; + devices = builtins.map (machine: { + name = machine; + value = { + name = machine; + id = (builtins.readFile (syncthingPublicKeyPath machine)); + }; + }) syncthingPublicKeyMachines; +in +{ + options.clan.static-syncthing-peers = { + excludeMachines = lib.mkOption { + type = lib.types.listOf lib.types.str; + example = [ config.clanCore.machineName ]; + default = [ ]; + description = '' + Machines that should not be added. + ''; + }; + }; + + config.services.syncthing.settings.devices = (builtins.listToAttrs devices); + + imports = [ + { + # Syncthing ports: 8384 for remote access to GUI + # 22000 TCP and/or UDP for sync traffic + # 21027/UDP for discovery + # source: https://docs.syncthing.net/users/firewall.html + networking.firewall.interfaces."zt+".allowedTCPPorts = [ + 8384 + 22000 + ]; + networking.firewall.allowedTCPPorts = [ 8384 ]; + networking.firewall.interfaces."zt+".allowedUDPPorts = [ + 22000 + 21027 + ]; + + # Activates inotify compatibility on syncthing + # use mkOverride 900 here as it otherwise would collide with the default of the + # upstream nixos xserver.nix + boot.kernel.sysctl."fs.inotify.max_user_watches" = lib.mkOverride 900 524288; + + services.syncthing = { + enable = true; + configDir = "/var/lib/syncthing"; + group = "syncthing"; + + key = lib.mkDefault config.clan.secrets.syncthing.secrets."syncthing.key".path or null; + cert = lib.mkDefault config.clan.secrets.syncthing.secrets."syncthing.cert".path or null; + }; + + clanCore.facts.services.syncthing = { + secret."syncthing.key" = { }; + secret."syncthing.cert" = { }; + public."syncthing.pub" = { }; + generator.path = [ + pkgs.coreutils + pkgs.gnugrep + pkgs.syncthing + ]; + generator.script = '' + syncthing generate --config "$secrets" + mv "$secrets"/key.pem "$secrets"/syncthing.key + mv "$secrets"/cert.pem "$secrets"/syncthing.cert + cat "$secrets"/config.xml | grep -oP '(?<= "$facts"/syncthing.pub + ''; + }; + } + ]; +} diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index d545db165..56bae1f56 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -64,6 +64,7 @@ nav: - reference/clanModules/sshd.md - reference/clanModules/static-hosts.md - reference/clanModules/sunshine.md + - reference/clanModules/syncthing-static-peers.md - reference/clanModules/syncthing.md - reference/clanModules/thelounge.md - reference/clanModules/trusted-nix-caches.md