pkg: { config, lib, ... }: let cfg = config.services.noisebell-zulip; bin = "${pkg}/bin/noisebell-zulip"; in { options.services.noisebell-zulip = { enable = lib.mkEnableOption "noisebell Zulip bridge"; domain = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; description = "Optional domain for the Caddy virtual host."; }; port = lib.mkOption { type = lib.types.port; default = 3003; }; zulipUrl = lib.mkOption { type = lib.types.str; description = "Base URL of the Zulip server (for example https://chat.example.com)."; }; botEmail = lib.mkOption { type = lib.types.str; description = "Email address for the Zulip bot user."; }; apiKeyFile = lib.mkOption { type = lib.types.path; description = "Path to file containing the Zulip bot API key."; }; stream = lib.mkOption { type = lib.types.str; description = "Zulip stream that receives Noisebell updates."; }; topic = lib.mkOption { type = lib.types.str; default = "noisebell"; description = "Zulip topic used for Noisebell updates."; }; imageBaseUrl = lib.mkOption { type = lib.types.str; default = "https://noisebell.extremist.software/image"; description = "Base URL for status images linked in Zulip messages."; }; webhookSecretFile = lib.mkOption { type = lib.types.path; description = "Path to file containing the inbound webhook bearer token."; }; }; config = lib.mkIf cfg.enable ( { users.users.noisebell-zulip = { isSystemUser = true; group = "noisebell-zulip"; }; users.groups.noisebell-zulip = { }; systemd.services.noisebell-zulip = { description = "Noisebell Zulip bridge"; wantedBy = [ "multi-user.target" ]; after = [ "network-online.target" ]; wants = [ "network-online.target" ]; environment = { NOISEBELL_ZULIP_PORT = toString cfg.port; NOISEBELL_ZULIP_SITE_URL = cfg.zulipUrl; NOISEBELL_ZULIP_BOT_EMAIL = cfg.botEmail; NOISEBELL_ZULIP_STREAM = cfg.stream; NOISEBELL_ZULIP_TOPIC = cfg.topic; NOISEBELL_ZULIP_IMAGE_BASE_URL = cfg.imageBaseUrl; RUST_LOG = "info"; }; script = '' export NOISEBELL_ZULIP_API_KEY="$(cat ${cfg.apiKeyFile})" export NOISEBELL_ZULIP_WEBHOOK_SECRET="$(cat ${cfg.webhookSecretFile})" exec ${bin} ''; serviceConfig = { Type = "simple"; Restart = "on-failure"; RestartSec = 5; User = "noisebell-zulip"; Group = "noisebell-zulip"; NoNewPrivileges = true; ProtectSystem = "strict"; ProtectHome = true; PrivateTmp = true; ProtectKernelTunables = true; ProtectKernelModules = true; ProtectControlGroups = true; RestrictSUIDSGID = true; }; }; } // lib.mkIf (cfg.domain != null) { services.caddy.virtualHosts.${cfg.domain}.extraConfig = '' reverse_proxy localhost:${toString cfg.port} ''; } ); }