{ config, lib, pkgs, ... }: let cfg = config.services.conduwuit; format = pkgs.formats.toml { }; configFile = format.generate "conduwuit.toml" cfg.settings; defaultUser = "conduwuit"; defaultGroup = "conduwuit"; in { options.services.conduwuit = { enable = lib.mkEnableOption "conduwuit"; user = lib.mkOption { type = lib.types.nonEmptyStr; default = defaultUser; }; group = lib.mkOption { type = lib.types.nonEmptyStr; default = defaultGroup; }; extraEnvironment = lib.mkOption { type = lib.types.attrsOf lib.types.str; default = { }; }; package = lib.mkPackageOption pkgs "conduwuit" { }; settings = lib.mkOption { default = { }; apply = lib.filterAttrsRecursive (_: v: v != null); type = lib.types.submodule { freeformType = format.type; options = { global.allow_check_for_updates = lib.mkOption { type = lib.types.bool; default = false; }; global.database_path = lib.mkOption { type = lib.types.path; default = "/var/lib/conduwuit/"; readOnly = true; }; global.trusted_servers = lib.mkOption { type = lib.types.listOf lib.types.nonEmptyStr; default = [ "matrix.org" ]; }; global.server_name = lib.mkOption { type = lib.types.nonEmptyStr; }; global.address = lib.mkOption { type = lib.types.nullOr (lib.types.listOf lib.types.nonEmptyStr); default = null; }; global.port = lib.mkOption { type = lib.types.listOf lib.types.port; default = [ 6167 ]; }; global.unix_socket_path = lib.mkOption { type = lib.types.nullOr lib.types.path; default = null; }; global.unix_socket_perms = lib.mkOption { type = lib.types.ints.positive; default = 660; }; global.max_request_size = lib.mkOption { type = lib.types.ints.positive; default = 20000000; }; global.allow_registration = lib.mkOption { type = lib.types.bool; default = false; }; global.allow_encryption = lib.mkOption { type = lib.types.bool; default = true; }; global.allow_federation = lib.mkOption { type = lib.types.bool; default = true; }; }; }; }; }; config = lib.mkIf cfg.enable { assertions = [{ assertion = !(cfg.settings ? global.unix_socket_path) || !(cfg.settings ? global.address); message = '' In `services.conduwuit.settings.global`, `unix_socket_path` and `address` cannot be set at the same time. Leave one of the two options unset or explicitly set them to `null`. ''; } { assertion = cfg.user != defaultUser -> config ? users.users.${cfg.user}; message = "If `services.conduwuit.user` is changed, the configured user must already exist."; } { assertion = cfg.group != defaultGroup -> config ? users.groups.${cfg.group}; message = "If `services.conduwuit.group` is changed, the configured group must already exist."; }]; users.users = lib.mkIf (cfg.user == defaultUser) { ${defaultUser} = { group = cfg.group; home = cfg.settings.global.database_path; isSystemUser = true; }; }; users.groups = lib.mkIf (cfg.group == defaultGroup) { ${defaultGroup} = { }; }; systemd.services.conduwuit = { description = "Conduwuit Matrix Server"; documentation = [ "https://conduwuit.puppyirl.gay/" ]; wantedBy = [ "multi-user.target" ]; wants = [ "network-online.target" ]; after = [ "network-online.target" ]; environment = lib.mkMerge ([ { CONDUWUIT_CONFIG = configFile; } cfg.extraEnvironment ]); startLimitBurst = 5; startLimitIntervalSec = 60; serviceConfig = { DynamicUser = true; User = cfg.user; Group = cfg.group; Type = "notify-reload"; ReloadSignal = "SIGUSR1"; ExecStart = lib.getExe cfg.package; Restart = "on-failure"; RestartSec = 10; StateDirectory = "conduwuit"; StateDirectoryMode = "0700"; RuntimeDirectory = "conduwuit"; RuntimeDirectoryMode = "0750"; DevicePolicy = "closed"; LockPersonality = true; MemoryDenyWriteExecute = true; NoNewPrivileges = true; ProtectClock = true; ProtectControlGroups = true; ProtectHome = true; ProtectHostname = true; ProtectKernelLogs = true; ProtectKernelModules = true; ProtectKernelTunables = true; PrivateDevices = true; PrivateMounts = true; PrivateTmp = true; PrivateUsers = true; PrivateIPC = true; RemoveIPC = true; RestrictNamespaces = true; RestrictRealtime = true; RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ]; SystemCallArchitectures = "native"; SystemCallErrorNumber = "EPERM"; SystemCallFilter = [ "@system-service @resources" "~@clock @debug @module @mount @reboot @swap @cpu-emulation @obsolete @timer @chown @setuid @privileged @keyring @ipc" ]; }; }; }; }