{ name, povSelf, hostConfig, config, pkgs, lib, ... }: let inherit (lib) types; cfg = lib.getAttrFromPath povSelf config; cfgWebsites = lib.getAttrFromPath (lib.remove name povSelf) config; in { options = { enable = { type = types.bool; default = false; }; domain = { type = types.str; default = "zaphyra.eu"; }; subdomain = { type = types.str; default = "grapevine"; }; }; config = lib.mkIf cfg.enable { assertions = [ { assertion = cfgWebsites."zaphyra.eu".enable == true; message = "The option 'modules.websites.\"zaphyra.eu\"' must be enabled in order to use this module."; } ]; dns.zones."${cfg.domain}".subdomains."${cfg.subdomain}".CNAME = [ "${config.networking.fqdn}." ]; sops.secrets."resticPasswords/grapevine" = { }; modules.filesystem.impermanence.system.dirs = [ "/var/lib/private/grapevine" ]; modules.services.resticBackup.paths = { grapevine = { enable = true; passwordFile = config.sops.secrets."resticPasswords/grapevine".path; paths = [ "/tmp/grapevine/media" "/tmp/grapevine/database" ]; runBeforeBackup = '' ${pkgs.systemd}/bin/systemctl stop grapevine.service ${pkgs.coreutils}/bin/cp -r /var/lib/grapevine /tmp/grapevine ${pkgs.systemd}/bin/systemctl start grapevine.service ''; }; }; systemd.services.grapevine = { serviceConfig.ExecStartPre = pkgs.writeShellScript "createDirs" '' mkdir -p /var/lib/grapevine/media; mkdir -p /var/lib/grapevine/database; ''; }; services.grapevine = { enable = true; settings = { server_name = cfg.domain; max_request_size = 52428800; media.allow_unauthenticated_access = true; allow_registration = false; registration_token = "foobar123"; database.backend = "rocksdb"; database.cache_capacity_mb = 128; federation.max_concurrent_requests = 10000; federation.self_test = false; # somehow this fails to unexpected server version server_discovery.server.authority = "${cfg.domain}:443"; server_discovery.client.base_url = "https://${cfg.domain}"; observability.logs.format = "pretty"; listen = [ { type = "tcp"; address = "::1"; port = 6167; } ]; }; }; services.nginx = { enable = true; virtualHosts = let grapevineListen = lib.last config.services.grapevine.settings.listen; matrixServerConfig = { "m.server" = "${cfg.subdomain}.${cfg.domain}:443"; }; matrixClientConfig = { "m.homeserver".base_url = "https://${cfg.subdomain}.${cfg.domain}/"; }; in { "${config.services.grapevine.settings.server_name}" = { locations = { "= /.well-known/matrix/server".extraConfig = '' add_header Content-Type application/json; return 200 '${builtins.toJSON matrixServerConfig}'; ''; "= /.well-known/matrix/client".extraConfig = '' add_header Content-Type application/json; return 200 '${builtins.toJSON matrixClientConfig}'; ''; }; }; "${cfg.subdomain}.${cfg.domain}" = { useACMEHost = "${config.networking.fqdn}"; forceSSL = true; kTLS = true; locations = { "/_matrix" = { proxyPass = "http://[${grapevineListen.address}]:${toString (grapevineListen.port)}"; proxyWebsockets = true; }; "/".root = pkgs.cinny.override { conf = { defaultHomeserver = 0; homeserverList = [ "${cfg.subdomain}.${cfg.domain}" ]; hashRouter.enabled = true; allowCustomHomesevrers = false; }; }; }; }; }; }; }; }