From 5f80bfc5c8b9077d7670cf6cee7e1fb824a5183d Mon Sep 17 00:00:00 2001 From: Madeleine Sydney Date: Mon, 10 Mar 2025 15:16:47 -0600 Subject: [PATCH] refactor(syncthing): Refactor syncthing modules --- hosts/deertopia/configuration.nix | 55 +---------------- modules/home/syncthing.nix | 85 +++++++++++++++++++++++++++ modules/nixos/deertopia/syncthing.nix | 47 +++++++++++++++ modules/nixos/syncthing.nix | 71 ++++++++++++---------- users/crumb/files.nix | 50 ++++------------ 5 files changed, 187 insertions(+), 121 deletions(-) create mode 100644 modules/home/syncthing.nix create mode 100644 modules/nixos/deertopia/syncthing.nix diff --git a/hosts/deertopia/configuration.nix b/hosts/deertopia/configuration.nix index bc6e791..9cf4188 100755 --- a/hosts/deertopia/configuration.nix +++ b/hosts/deertopia/configuration.nix @@ -37,60 +37,6 @@ keyFile = "/persist/private-keys/age/deertopia"; }; - # git-annex = { - # enable = true; - # user.name = "annex"; - # user.email = "annex@deertopia.net"; - # keyFiles = [ - # ../../public-keys/crumb-at-guix-rebound.pub - # ../../public-keys/crumble-at-fruitbook.pub - # ../../public-keys/lain-at-deertopia.pub - # ]; - # repos = { - # "/persist/vault/jellyfin/Documents" = { - # managed = true; - # symlinkToAnnexHome = "documents"; - # remotes = { - # "guix-rebound" = "crumb@guix-rebound:Documents"; - # }; - # }; - # "/persist/vault/jellyfin/Music" = { - # managed = true; - # symlinkToAnnexHome = "music"; - # remotes = { - # "guix-rebound" = "crumb@guix-rebound:Music"; - # }; - # }; - # "/persist/deertopia.net/dav/org" = { - # managed = true; - # symlinkToAnnexHome = "org"; - # remotes = { - # "guix-rebound" = "crumb@guix-rebound:org"; - # }; - # }; - # }; - # }; - - syncthing = { - enable = true; - devices = { - "guix-rebound".id = - "Q5B6LIV-5HQMWWV-XFQL5IT-PHP7PVE-XFWUVHK-F6WJ42C-OPMR4M7-GFNK3AG"; - }; - folders = { - "Music" = { - path = "/persist/vault/jellyfin/Music"; - devices = [ "guix-rebound" ]; - ignorePerms = true; - }; - "org" = { - path = "/persist/deertopia.net/dav/org"; - devices = [ "guix-rebound" ]; - ignorePerms = true; - }; - }; - }; - deertopia = { authelia.enable = true; bepasty.enable = true; @@ -100,6 +46,7 @@ slskd.enable = true; webdav.enable = true; copyparty.enable = true; + syncthing.enable = true; # A simple default webpage. This should probably live somewhere else. nginx.vhosts."www" = { diff --git a/modules/home/syncthing.nix b/modules/home/syncthing.nix new file mode 100644 index 0000000..df23ee5 --- /dev/null +++ b/modules/home/syncthing.nix @@ -0,0 +1,85 @@ +{ config, lib, pkgs, ... }: + +let cfg = config.sydnix.syncthing; +in { + options.sydnix.syncthing = { + enable = lib.mkEnableOption "Syncthing"; + includeDevices = lib.mkOption { + type = + lib.types.listOf + (lib.types.enum (builtins.attrNames cfg.devices)); + default = []; + description = '' + A list of device names to sync with. See the read-only option + `sydnix.syncthing.devices` for the concrete details. + ''; + }; + devices = lib.mkOption { + # This should generally be in sync with modules/home/syncthing.nix. + default = { + "guix-rebound".id = + "Q5B6LIV-5HQMWWV-XFQL5IT-PHP7PVE-XFWUVHK-F6WJ42C-OPMR4M7-GFNK3AG"; + "deertopia".id = + "OO6XGGQ-SORH6XW-YEMN3T3-CSW5QOO-2IRB2QE-NZOL6JE-RAV36GS-WZXXLQV"; + }; + readOnly = true; + description = '' + The read-only 'universe' of devices available. A subset of these + devices — those named by `sydnix.syncthing.includeDevices` — will be + handed to Syncthing's module. This should generally match the option of + the same name in the NixOS module, `sydnix.syncthing.devices`. + ''; + }; + directories = lib.mkOption { + type = lib.types.anything; + default = {}; + description = '' + Directly handed to `services.syncthing.settings.folders`. + ''; + }; + }; + + config = lib.mkIf cfg.enable { + # TODO: sydnix.syncthing module + sydnix.impermanence.directories = + let xdg-state-dir = + config.home.statehome + or "${config.home.homeDirectory}/.local/state"; + in [ + # HACK: This relies on behaviour that is not explicitly defined by the + # Syncthing Home-manager module. We have to trust that $XDG_STATE_DIR, + # at the time of syncthing.service's start, does not differ from this + # value defined in Nix. Perhaps a PR to home-manager adding an option + # `services.syncthing.stateDir` would be good. + # + # If Syncthing ever breaks, make sure they didn't start using a different path: + # https://github.com/nix-community/home-manager/blob/master/modules/services/syncthing.nix + # + # Evidence for using this path is found at: (permalink) + # https://github.com/nix-community/home-manager/blob/6d3163aea47fdb1fe19744e91306a2ea4f602292/modules/services/syncthing.nix#L624 + + # Hack aside, this directory must be persisted to, at least + # 1. Preserve the device ID. + (lib.removePrefix config.home.homeDirectory "${xdg-state-dir}/syncthing") + ]; + + services.syncthing = { + enable = true; + settings = { + gui = { + # TODO: Figure out how to read credentials from a file. + # tls = true; + user = "lain"; + password = "my-awesome-password"; + }; + overrideDevices = true; + overrideFolders = true; + devices = + lib.filterAttrs + (k: _v: builtins.elem k cfg.includeDevices) + cfg.devices; + folders = cfg.directories; + }; + }; + }; +} diff --git a/modules/nixos/deertopia/syncthing.nix b/modules/nixos/deertopia/syncthing.nix new file mode 100644 index 0000000..749c4bc --- /dev/null +++ b/modules/nixos/deertopia/syncthing.nix @@ -0,0 +1,47 @@ +{ config, lib, pkgs, ... }: + +let cfg = config.sydnix.deertopia.syncthing; +in { + options.sydnix.deertopia.syncthing.enable = + lib.mkEnableOption "Syncthing, à la Deertopia"; + config = lib.mkIf cfg.enable { + sydnix.syncthing = { + enable = true; + includeDevices = [ + "guix-rebound" + "nixos-testbed" + ]; + directories = { + "Music" = { + path = "/persist/vault/jellyfin/Music"; + devices = [ "guix-rebound" ]; + ignorePerms = true; + }; + "org" = { + path = "/persist/deertopia.net/dav/org"; + devices = [ + "guix-rebound" + "nixos-testbed" + ]; + ignorePerms = true; + }; + }; + }; + + # HACK: I don't understand the idioms of Unix file permissions. + # TODO: Consult molly for this shit TwT. + users.users.${config.services.syncthing.user}.extraGroups = [ + "jellyfin" + "nginx" + ]; + + sydnix.deertopia.nginx.vhosts."syncthing".vhost = { + forceSSL = true; + enableACME = true; + locations."/" = { + # TODO: This should work if guiAddress already specifies a protocol. + proxyPass = "http://" + config.services.syncthing.guiAddress; + }; + }; + }; +} diff --git a/modules/nixos/syncthing.nix b/modules/nixos/syncthing.nix index 4fe2d98..11e070f 100644 --- a/modules/nixos/syncthing.nix +++ b/modules/nixos/syncthing.nix @@ -1,44 +1,52 @@ { config, lib, pkgs, ... }: -# TODO: This is a Deertopia module. Move to nixos/deertopia/syncthing.nix. - let cfg = config.sydnix.syncthing; in { - options = { - sydnix.syncthing = { - enable = lib.mkEnableOption "Syncthing"; - devices = lib.mkOption { - type = lib.types.anything; - default = {}; - }; - folders = lib.mkOption { - type = lib.types.anything; - default = {}; + options.sydnix.syncthing = { + enable = lib.mkEnableOption "Syncthing"; + includeDevices = lib.mkOption { + type = + lib.types.listOf + (lib.types.enum (builtins.attrNames cfg.devices)); + default = []; + description = '' + A list of device names to sync with. See the read-only option + `sydnix.syncthing.devices` for the concrete details. + ''; + }; + devices = lib.mkOption { + # This should generally be in sync with modules/home/syncthing.nix. + default = { + "guix-rebound".id = + "Q5B6LIV-5HQMWWV-XFQL5IT-PHP7PVE-XFWUVHK-F6WJ42C-OPMR4M7-GFNK3AG"; + "deertopia".id = + "OO6XGGQ-SORH6XW-YEMN3T3-CSW5QOO-2IRB2QE-NZOL6JE-RAV36GS-WZXXLQV"; + "nixos-testbed".id = + "BO3AESA-LBKMZW7-QFE7NTT-GF62DOA-PYUACYU-HNTNYI5-EMF6PAN-TR6YHAL"; }; + readOnly = true; + description = '' + The read-only 'universe' of devices available. A subset of these + devices — those named by `sydnix.syncthing.includeDevices` — will be + handed to Syncthing's module. This should generally match the option of + the same name in the Home-manager module, `sydnix.syncthing.devices`. + ''; + }; + directories = lib.mkOption { + type = lib.types.anything; + default = {}; + description = '' + Directly handed to `services.syncthing.settings.folders`. + ''; }; }; config = lib.mkIf cfg.enable { - # HACK: I don't understand the idioms of Unix file permissions. - # TODO: Consult molly for this shit TwT. - users.users.${config.services.syncthing.user}.extraGroups = [ - "jellyfin" - "nginx" - ]; - sydnix.impermanence.directories = [ + # Most notably, preserves the device ID. "/var/lib/syncthing" ]; - sydnix.deertopia.nginx.vhosts."syncthing".vhost = { - forceSSL = true; - enableACME = true; - locations."/" = { - # TODO: This should work if guiAddress already specifies a protocol. - proxyPass = "http://" + config.services.syncthing.guiAddress; - }; - }; - services.syncthing = { enable = true; openDefaultPorts = true; @@ -51,8 +59,11 @@ in { }; overrideDevices = true; overrideFolders = true; - devices = cfg.devices; - folders = cfg.folders; + devices = + lib.filterAttrs + (k: _v: builtins.elem k cfg.includeDevices) + cfg.devices; + folders = cfg.directories; }; }; }; diff --git a/users/crumb/files.nix b/users/crumb/files.nix index c41f23b..7f9789a 100755 --- a/users/crumb/files.nix +++ b/users/crumb/files.nix @@ -64,44 +64,20 @@ in lib.mkMerge [ { ### Syncthing - # TODO: sydnix.syncthing module - sydnix.impermanence.directories = - let xdg-state-dir = - config.home.statehome - or "${config.home.homeDirectory}/.local/state"; - in [ - # HACK: This relies on behaviour that is not explicitly defined by the - # Syncthing Home-manager module. We have to trust that $XDG_STATE_DIR, - # at the time of syncthing.service's start, does not differ from this - # value defined in Nix. Perhaps a PR to home-manager adding an option - # `services.syncthing.stateDir` would be good. - # - # If Syncthing ever breaks, make sure they didn't start using a different path: - # https://github.com/nix-community/home-manager/blob/master/modules/services/syncthing.nix - # - # Evidence for using this path is found at: (permalink) - # https://github.com/nix-community/home-manager/blob/6d3163aea47fdb1fe19744e91306a2ea4f602292/modules/services/syncthing.nix#L624 - - # Hack aside, this directory must be persisted to, at least - # 1. Preserve the device ID. - (lib.removePrefix config.home.homeDirectory "${xdg-state-dir}/syncthing") - ]; - - services.syncthing = { + sydnix.syncthing = { enable = true; - settings = { - overrideDevices = true; - overrideFolders = true; - devices = { - "guix-rebound".id = - "Q5B6LIV-5HQMWWV-XFQL5IT-PHP7PVE-XFWUVHK-F6WJ42C-OPMR4M7-GFNK3AG"; - }; - folders = { - "org" = { - path = "~/org"; - devices = [ "guix-rebound" ]; - ignorePerms = true; - }; + includeDevices = [ + "guix-rebound" + "deertopia" + ]; + directories = { + "org" = { + path = "~/org"; + devices = [ + "guix-rebound" + "deertopia" + ]; + ignorePerms = true; }; }; };