{ config, inputs, lib, libNginx, this, ... }: with lib; let cfg = config.nixfiles.modules.syncthing; in { options.nixfiles.modules.syncthing = { enable = mkEnableOption "Syncthing"; port = mkOption { description = "Port."; type = with types; port; default = 8384; }; domain = mkOption { description = "Domain name sans protocol scheme."; type = with types; str; default = "syncthing.${config.networking.fqdn}"; }; }; config = mkIf cfg.enable (mkMerge [ { secrets = { "syncthing-cert-${this.hostname}" = with config.services.syncthing; { file = "${inputs.self}/secrets/syncthing-cert-${this.hostname}"; owner = user; inherit group; }; "syncthing-key-${this.hostname}" = with config.services.syncthing; { file = "${inputs.self}/secrets/syncthing-key-${this.hostname}"; owner = user; inherit group; }; }; services.syncthing = { enable = true; user = my.username; inherit (config.my) group; dataDir = "${config.dirs.config}/syncthing"; configDir = config.services.syncthing.dataDir; guiAddress = "127.0.0.1:${toString cfg.port}"; cert = config.secrets."syncthing-cert-${this.hostname}".path; key = config.secrets."syncthing-key-${this.hostname}".path; overrideDevices = false; overrideFolders = false; settings = { options = { announceLANAddresses = false; autoUpgradeIntervalH = 0; crashReportingEnabled = false; globalAnnounceEnabled = false; relaysEnabled = false; setLowPriority = this.isHeadful; stunKeepaliveStartS = 0; urAccepted = -1; }; gui = { insecureAdminAccess = this.isHeadless; insecureSkipHostcheck = this.isHeadless; }; devices = mapAttrs ( name: attr: mkIf (attr.syncthing.id != null && hasAttr "wireguard" attr) { inherit (attr.syncthing) id; compression = "always"; introducer = false; addresses = [ "quic://${name}.${config.networking.domain}:22000" "tcp://${name}.${config.networking.domain}:22000" ]; autoAcceptFolders = true; untrusted = false; } ) my.configurations; folders = let filterDevices = f: attrNames ( filterAttrs ( _: attr: (attr.hostname != this.hostname) && (attr.syncthing.id != null) && f attr ) my.configurations ); all = filterDevices (_: true); notHeadless = filterDevices (attr: !attr.isHeadless); notOther = filterDevices (attr: !attr.isOther); simple = { type = "simple"; params.keep = "5"; }; trashcan = { type = "trashcan"; params.cleanoutDays = "7"; }; in with config.hm.xdg.userDirs; { share = { path = publicShare; devices = notHeadless; versioning = trashcan; }; pass = { path = config.hm.programs.password-store.settings.PASSWORD_STORE_DIR; devices = notOther; versioning = trashcan; }; org = { path = "${documents}/org"; devices = all; versioning = simple; }; roam = { path = "${documents}/roam"; devices = notOther; versioning = simple; }; elfeed = { path = "${config.my.home}/.elfeed"; devices = notOther; versioning = trashcan; }; books = { path = "${documents}/books"; devices = notOther; versioning = trashcan; }; }; }; }; systemd.services.syncthing.environment.STNODEFAULTFOLDER = "yes"; } (mkIf this.isHeadless { nixfiles.modules.nginx = { enable = true; upstreams.syncthing.servers.${config.services.syncthing.guiAddress} = { }; virtualHosts.${cfg.domain} = { locations."/".proxyPass = "http://syncthing"; extraConfig = libNginx.config.internalOnly; }; }; }) ]); }