No description
Find a file
2025-09-09 09:28:48 +02:00
.forgejo/workflows add forgejo actions 2025-08-29 18:02:30 -07:00
LICENSES zulip-prometheus-exporter: init at 0.1.0 2025-08-06 17:16:15 -07:00
nix update zulip-server 10.4 -> 11.0 2025-09-08 00:08:26 +02:00
.envrc pluralize attributes 2025-08-29 16:48:53 -07:00
.gitignore add nixos test for zulip 2025-08-06 21:21:34 -07:00
engage.toml run nixos test in CI 2025-08-29 18:02:30 -07:00
flake.lock update lock 2025-09-07 23:30:53 +02:00
flake.nix docs(README): update descriptions 2025-09-09 09:28:48 +02:00
README.md docs(README): update descriptions 2025-09-09 09:28:48 +02:00
REUSE.toml start the project 2025-08-06 13:35:47 -07:00
treefmt.toml start the project 2025-08-06 13:35:47 -07:00

nix-zulip

This repository packages Zulip for Nix and NixOS.

It is a flake-parts port of https://git.afnix.fr/afnix/nix-zulip and I will maintain incorporating upstream changes.

Usage

An example module usage with

  • OIDC integration (you can probably turn it off by removing all the relevant options), we integrated with kanidm as an IDM
  • mail integration

Note that quiet a few secrets are required. They are mostly free form, but you should use something reasonably safe.

The zulip-oidc should be a JSON of the form:

{
  "kanidm": {
    "name": "kanidm",
    "display_name": "Kanidm",
    "oidc_url": "https://kanidm.example.com/oauth2/openid/zulip",
    "client_id": "zulip",
    "secret": "<your-client-secret>",
    "scopes": ["openid", "zulip_admin", "profile", "email", "groups"],
    "email_key": "email",
    "username_key": "preferred_username",
    "subdomain": "zulip",
    "auto_signup": true
  }
}

Note! This currently only supports one IDM, multiple are not handled by zulip!

services.zulip = {
    enable = true;

    # Normally I would vendor this instead but Zulip requires more configuration
    # than usual; namely, schemas.
    enablePostgresqlLocally = true;

    host = "zulip.example.com";

    zulipSettings = {
        EXTERNAL_HOST = "zulip.example.com";

        AUTHENTICATION_BACKENDS = lib.mkForce [
            "zproject.backends.GenericOpenIdConnectBackend"
            "zproject.backends.EmailAuthBackend"
        ];

        SOCIAL_AUTH_OIDC_ENABLED_IDPS = {
            _get_secret = "social_auth_oidc_enabled_idps";
        };
        SOCIAL_AUTH_OIDC_FULL_NAME_VALIDATED = false;

        WEB_PUBLIC_STREAMS_ENABLED = true;

        ZULIP_SERVICE_PUSH_NOTIFICATIONS = true;

        ZULIP_SERVICE_SUBMIT_USAGE_STATISTICS = false;

        JITSI_SERVER_URL = null;

        # Not really sure why Zulip wants to be able to send from 3 different
        # email addresses by default.
        EMAIL_HOST_USER = "service@example.com";
        NOREPLY_EMAIL_ADDRESS = "noreply@example.com";
        ZULIP_ADMINISTRATOR = "service@example.com";

        # This is safe because we use OIDC for account management/creation.
        ADD_TOKENS_TO_NOREPLY_ADDRESS = false;

        EMAIL_HOST = "mail.example.com";
        EMAIL_PORT = 587;
        EMAIL_USE_TLS = true;
    };

    sharedSecretKeyFile = config.sops.secrets."zulip-shared-secret".path;
    secretKeyFile = config.sops.secrets."zulip-secret-key".path;
    avatarSaltKeyFile = config.sops.secrets."zulip-avatar-salt".path;
    rabbitmqPasswordFile = config.sops.secrets."zulip-rabbitmq-password".path;
    orgKeyFile = config.sops.secrets."zulip-org-key".path;
    orgIdFile = config.sops.secrets."zulip-org-id".path;
    camoKeyFile = config.sops.secrets."zulip-camo-key".path;
    extraSecrets = {
        "email_password" = config.sops.secrets."zulip-email-pw".path;
        "social_auth_oidc_enabled_idps" = config.sops.secrets."zulip-oidc".path;
    };
};

sops.secrets = {
    "zulip-shared-secret".owner = "zulip";
    "zulip-secret-key".owner = "zulip";
    "zulip-avatar-salt".owner = "zulip";
    "zulip-rabbitmq-password".owner = "zulip";
    "zulip-org-key".owner = "zulip";
    "zulip-org-id".owner = "zulip";
    "zulip-camo-key".owner = "zulip";
    "zulip-email-pw".owner = "zulip";
    "zulip-oidc".owner = "zulip";
};

Credits