Logo
  • Zulip homepage
  • Overview
    • Zulip overview
      • Getting started
    • Zulip architectural overview
      • Key codebases
      • Usage assumptions and concepts
      • Components
        • Django and Tornado
        • nginx
        • Supervisor
        • memcached
        • Redis
        • RabbitMQ
        • PostgreSQL
        • Nagios
    • Release lifecycle
      • Server and web app versions
        • Stable releases
        • Git versions
        • What version am I running?
        • Versioned documentation
      • Client apps
        • Mobile app
        • Desktop app
        • Terminal app
      • Server and client app compatibility
        • Upgrade nag
      • Operating system support
      • API bindings
    • Roadmap
      • Server and web app roadmap
      • Mobile app roadmap
    • Version history
      • Zulip Server 13.x series (development)
      • Zulip Server 13.0-dev
        • Upgrade notes for 13.0
      • Zulip Server 12.x series
        • Zulip Server 12.0
        • Upgrade notes for 12.0
      • Zulip Server 11.x series
        • Zulip Server 11.6
        • Zulip Server 11.5
        • Zulip Server 11.4
        • Zulip Server 11.3
        • Zulip Server 11.2
        • Zulip Server 11.1
        • Zulip Server 11.0
      • Zulip Server 10.x series
        • Zulip Server 10.4
        • Zulip Server 10.3
        • Zulip Server 10.2
        • Zulip Server 10.1
        • Zulip Server 10.0
      • Zulip Server 9.x series
        • Zulip Server 9.4
        • Zulip Server 9.3
        • Zulip Server 9.2
        • Zulip Server 9.1
        • Zulip Server 9.0
      • Zulip Server 8.x series
        • Zulip Server 8.5
        • Zulip Server 8.4
        • Zulip Server 8.3
        • Zulip Server 8.2
        • Zulip Server 8.1
        • Zulip Server 8.0
      • Zulip Server 7.x series
        • Zulip Server 7.5
        • Zulip Server 7.4
        • Zulip Server 7.3
        • Zulip Server 7.2
        • Zulip Server 7.1
        • Zulip Server 7.0
      • Zulip Server 6.x series
        • Zulip Server 6.2
        • Zulip Server 6.1
        • Zulip Server 6.0
      • Zulip Server 5.x series
        • Zulip Server 5.7
        • Zulip Server 5.6
        • Zulip Server 5.5
        • Zulip Server 5.4
        • Zulip Server 5.3
        • Zulip Server 5.2
        • Zulip Server 5.1
        • Zulip Server 5.0
      • Zulip Server 4.x series
        • Zulip Server 4.11
        • Zulip Server 4.10
        • Zulip Server 4.9
        • Zulip Server 4.8
        • Zulip Server 4.7
        • Zulip Server 4.6
        • Zulip Server 4.5
        • Zulip Server 4.4
        • Zulip Server 4.3
        • Zulip Server 4.2
        • Zulip Server 4.1
        • Zulip Server 4.0
      • Zulip Server 3.x series
        • Zulip Server 3.4
        • Zulip Server 3.3
        • Zulip Server 3.2
        • Zulip Server 3.1
        • Zulip Server 3.0
      • Zulip Server 2.1.x series
        • Zulip Server 2.1.8
        • Zulip Server 2.1.7
        • Zulip Server 2.1.6
        • Zulip Server 2.1.5
        • Zulip Server 2.1.4
        • Zulip Server 2.1.3
        • Zulip Server 2.1.2
        • Zulip Server 2.1.1
        • Zulip Server 2.1.0
      • Zulip Server 2.0.x series
        • Zulip Server 2.0.8
        • Zulip Server 2.0.7
        • Zulip Server 2.0.6
        • Zulip Server 2.0.5
        • Zulip Server 2.0.4
        • Zulip Server 2.0.3
        • Zulip Server 2.0.2
        • Zulip Server 2.0.1
        • Zulip Server 2.0.0
      • Zulip Server 1.9.x series
        • Zulip Server 1.9.2
        • Zulip Server 1.9.1
        • Zulip Server 1.9.0
      • Zulip Server 1.8.x series
        • Zulip Server 1.8.1
        • Zulip Server 1.8.0
      • Zulip Server 1.7.x series
        • Zulip Server 1.7.2
        • Zulip Server 1.7.1
        • Zulip Server 1.7.0
      • Zulip Server 1.6.x and older
        • Zulip Server 1.6.0
        • Zulip Server 1.5.2
        • Zulip Server 1.5.1
        • Zulip Server 1.5.0
        • Zulip Server 1.4.3
        • Zulip Server 1.4.2
        • Zulip Server 1.4.1
        • Zulip Server 1.4.0
        • Zulip Server 1.3.13
        • Zulip Server 1.3.12
        • Zulip Server 1.3.11
        • Zulip Server 1.3.10
        • Zulip Server 1.3.9
        • Zulip Server 1.3.8
        • Zulip Server 1.3.7
      • Upgrade notes
  • Zulip in production
    • Requirements and scalability
      • Server
        • General
        • Operating system
        • Hardware specifications
        • Network and security specifications
      • Credentials needed
        • SSL certificate
        • Outgoing email
      • Scalability
    • Install a Zulip server
      • Installation process overview
      • Step 0: Set up a base server
      • Step 1: Download the latest release
      • Step 2: Install Zulip
        • Installer options
      • Step 3: Create a Zulip organization, and log in
      • Getting started with Zulip
    • Troubleshooting and monitoring
      • Overview and resources
      • Using supervisorctl
        • Checking status with supervisorctl status
        • Restarting services with supervisorctl restart
        • Stopping services with supervisorctl stop
      • Troubleshooting services
        • Restrict unattended upgrades
      • Monitoring
        • Nagios configuration
      • Memory leak mitigation
      • Troubleshooting the Zulip installer
        • The zulip user’s password.
    • Management commands
      • Running management commands
        • Accessing an organization’s string_id
      • manage.py shell
      • Other useful manage.py commands
      • Custom management commands
    • Server configuration
      • Server settings overview
      • Changing server settings
      • Customizing user onboarding
        • Navigation tour video
        • Terms of Service and Privacy policy
    • System configuration
      • Truthy values
      • [machine]
        • puppet_classes
        • pgroonga
        • timesync
      • [deployment]
        • deploy_options
        • git_repo_url
      • [application_server]
        • http_only
        • nginx_listen_port
        • nginx_worker_processes
        • nginx_worker_connections
        • queue_workers_multiprocess
        • rolling_restart
        • service_file_descriptor_limit
        • s3_memory_cache_size
        • s3_disk_cache_size
        • s3_cache_inactive_time
        • thumbnail_workers
        • email_senders_workers
        • nameserver
        • uwsgi_listen_backlog_limit
        • uwsgi_processes
        • access_log_retention_days
        • katex_server
        • katex_server_port
        • custom_ca_path
      • [postgresql]
        • effective_io_concurrency
        • listen_addresses
        • random_page_cost
        • replication_primary
        • replication_user
        • skip_backups
        • backups_disk_concurrency
        • backups_directory
        • backups_incremental
        • backups_storage_class
        • backups_compression_method
        • missing_dictionaries
        • ssl_ca_file
        • ssl_cert_file
        • ssl_key_file
        • ssl_mode
        • version
      • [memcached]
        • memory
        • max_item_size
        • size_reporting
      • [tornado_sharding]
      • [loadbalancer]
        • ips
        • rejects_http_requests
      • [http_proxy]
        • host
        • port
        • listen_address
        • enable_for_camo
        • allow_addresses, allow_ranges, deny_addresses, deny_ranges
      • [sentry]
        • organization
        • project
    • Mobile push notification service
      • Signing up
      • Plan management
        • Plan management for a Zulip organization
        • Plan management for an entire Zulip server
      • Why a push notification service is necessary
      • Security and privacy
        • What Apple, Google, and the Push Notification Service see
        • What the Push Notification Service stores
        • What the Zulip server sees
        • Limitations
        • Cryptography
        • Uploading basic metadata
        • Uploading usage statistics
      • Rate limits
      • Updating your server’s registration
      • Moving your registration to a new server
        • Transferring your registration if you lost the original credentials
      • Deactivating your server’s registration
        • Pausing use of the Mobile Push Notification Service
        • Legacy protocol
    • Upgrade Zulip
      • Upgrading to a release
        • What to expect during an upgrade
      • Upgrading from a Git repository
        • Upgrading to an unreleased version of Zulip
      • Updating settings.py inline documentation
      • Troubleshooting and rollback
        • Rolling back to a prior version
      • Deployment hooks
      • Preserving local changes to service configuration files
        • nginx configuration changes
      • Upgrading PostgreSQL
      • Upgrading the operating system
        • Upgrading from Ubuntu 22.04 Jammy to 24.04 Noble
        • Upgrading from Ubuntu 20.04 Focal to 22.04 Jammy
        • Upgrading from Ubuntu 18.04 Bionic to 20.04 Focal
        • Upgrading from Ubuntu 16.04 Xenial to 18.04 Bionic
        • Upgrading from Debian 12 to 13
        • Upgrading from Debian 11 to 12
        • Upgrading from Debian 10 to 11
        • Upgrading from Debian 9 to 10
    • Modify Zulip
      • Making changes
        • Upgrading to future releases
        • Making changes with docker-zulip
      • Applying changes from main
        • Applying a small change
        • Upgrading to main
      • Contributing patches
    • Securing your Zulip server
      • 1. Limit shell access to a small set of trusted individuals.
      • 2. Consider requiring authentication with single sign-on (SSO).
      • 3. Teach users how to protect their account.
      • 4. Become familiar with Zulip’s access management model.
      • 5. Understand security for user-uploaded content and user-generated requests.
      • 6. Understand Zulip’s rate-limiting system.
    • Authentication methods
      • Email and password
        • Passwords
      • Social authentication
        • Sign in with Apple
      • LDAP (including Active Directory)
        • Synchronizing data
        • Synchronizing email addresses
        • Multiple LDAP searches
        • Restricting access to an LDAP group
        • Restricting LDAP user access to specific organizations
        • Troubleshooting
      • SAML
        • IdP-initiated SSO
        • Restricting access to specific organizations
        • Synchronizing data during login
        • Synchronizing email addresses with SAML
        • SCIM
        • Using Keycloak as a SAML IdP
        • Using Authentik as a SAML IdP
        • SAML Single Logout
      • Apache-based SSO with REMOTE_USER
        • Setup instructions for Apache-based SSO
        • Troubleshooting Apache-based SSO
        • Life of an Apache-based SSO login attempt
      • OpenID Connect
        • Microsoft Entra ID (OIDC)
      • JSON Web Tokens (JWT)
      • Microsoft Entra ID
      • Custom authentication backends
        • Configuring a custom Python wrapper around the authenticate mechanism
        • Adding more authentication backends
      • Development only
    • Backups, export and import
      • Backups
        • Restoring backups
        • What is included
        • Restore from manual backups
      • Data export
        • Consider upgrading
        • Preventing changes during the export
        • Export your Zulip data
      • Import into a new Zulip server
        • Import options
        • Logging in
        • Deleting and re-importing
      • Compliance exports
      • Database-only backup tools
        • Streaming backups to S3
        • Streaming backups to local disk
        • Restoring from wal-g backups
    • PostgreSQL database details
      • Separate PostgreSQL database
        • Cloud-provider-managed PostgreSQL (e.g., Amazon RDS)
        • Remote PostgreSQL database
      • PostgreSQL warm standby
      • PostgreSQL vacuuming alerts
    • File upload backends
      • S3 backend configuration
        • Google Cloud Platform
      • S3 local caching
      • nginx DNS nameserver configuration
      • S3 bucket policy
      • Migrating from local uploads to Amazon S3 backend
      • S3 data storage class
      • Data export bucket
    • Installing SSL certificates
      • Manual install
        • Testing
      • Certbot (recommended)
        • At initial Zulip install
        • After Zulip is already installed
        • How it works
        • Renewal
      • Self-signed certificate
      • Troubleshooting
        • The Android app can’t connect to the server
        • The iOS app can’t connect to the server
        • The Android app connects to the server on some devices but not others
    • Outgoing email
      • How to configure
      • Email services
        • Free outgoing email services
        • Using system email
        • Using Gmail for outgoing email
        • Logging outgoing email to a file for prototyping
      • Troubleshooting
        • Advanced troubleshooting
    • Deployment options
      • Installing Zulip from Git
      • Zulip in Docker
      • Zulip installer details
        • Advanced installer options
      • Installing on an existing server
      • Deployment hooks
        • Zulip message deploy hook
        • Sentry deploy hook
      • Running Zulip’s service dependencies on different machines
      • Deploying behind a reverse proxy
      • Using an alternate port
      • Customizing the outgoing HTTP proxy
        • IP address rules
        • Using a different outgoing proxy
        • Routing Camo requests through an outgoing proxy
        • Installing Smokescreen on a separate host
        • S3 file storage requests and outgoing proxies
    • Running Zulip in Docker
    • Reverse proxies
      • Installer options
        • Configuring Zulip to allow HTTP
        • Configuring Zulip to trust proxies
      • nginx configuration
      • Apache2 configuration
      • HAProxy configuration
      • Other proxies
    • Hosting multiple organizations
      • Subdomains
        • SSL certificates
        • Other hostnames
        • The root domain
        • Changing subdomains
        • Authentication
        • The system bot realm
        • Migrating / troubleshooting
      • Open realm creation
    • Incoming email integration
      • Local delivery setup
      • Polling setup
    • Video call providers
      • Jitsi
      • Zoom
        • Server to Server OAuth app
        • General OAuth app
        • Configure your Zulip server
      • BigBlueButton
      • Constructor Groups
      • Nextcloud Talk
      • Webex
        • Create a custom Webex integration
        • Configure your Zulip server
    • AI integrations
      • Built-in AI features
        • Data privacy
        • General configurations
        • Topic summarization beta
    • GIF picker integrations
      • GIPHY
        • Apply for API key
      • Tenor
        • Create a Tenor API key
      • KLIPY
        • Create a KLIPY API key
    • SCIM provisioning
      • Server configuration
      • Additional options
  • Incoming webhooks
    • Incoming webhooks overview
      • Quick guide
      • Hello world walkthrough
      • Checklist
        • Files that need to be created
        • Files that need to be updated
      • Common Helpers
      • General advice
      • URL specification
        • api_key (required)
        • stream
        • topic
        • only_events, exclude_events
    • Writing an incoming webhook
      • Step 0: Create fixtures
      • Step 1: Initialize the python package
      • Step 2: Write the main webhook code
        • Decorators
        • Main webhook handler
      • Step 3: Create an API endpoint for the webhook
      • Step 4: Manually test the webhook
        • curl
        • send_webhook_fixture_message management command
        • Integrations dev panel
      • Step 5: Create automated tests
      • Step 6: Document the integration
      • Step 7: Prepare a pull request
      • Advanced topics
        • Handling unexpected webhook event types
    • Incoming webhooks reference
      • Custom HTTP headers
        • Extracting event-type HTTP headers from payloads
        • Recording event-type HTTP headers in fixtures
        • Extracting event-type HTTP headers from fixtures
      • Custom URL query parameters
        • Registering webhooks requiring custom configuration
        • WebhookUrlOption presets
        • Writing tests for custom URL query parameters
      • Negative tests
  • Contributing to Zulip
    • Contributing guide
      • How to use Zulip’s documentation for contributors
      • How to be a successful contributor
      • AI use policy and guidelines
        • Using AI as a coding assistant
        • Using AI for communication
      • Getting started
        • Learning how to use Git (the Zulip way)
        • Setting up your development environment and diving in
      • Finding an issue to work on
        • Where to look for an issue
        • Picking an issue to work on
        • Claiming an issue
      • Getting help
      • Best practices
      • Submitting a pull request
      • Beyond the first issue
      • Common questions
        • Picking up issues
        • Review process
      • Outreach programs
    • Zulip Code of Conduct
      • Expected behavior
      • Unacceptable behavior
      • AI policy
      • Reporting and enforcement
      • Scope
      • License and attribution
      • Moderating the Zulip community
    • How we communicate
      • Providing suggestions and feedback
      • Handling disagreements
      • Expressing your appreciation
    • Asking great questions
      • Where to ask your question
      • How to ask a great question
      • Follow the community guidelines
    • Design discussions
      • Guidelines for all participants
      • Participant roles
      • Guidelines for code contributors
        • When to post
        • Guidelines for requesting design feedback
      • Guidelines for community moderators
        • Improving the quality of discussions
        • Moving threads to the most appropriate channel
      • Guidelines for decision makers
        • Managing the discussion
        • From discussion to decision
    • Commit discipline
      • Each commit must be coherent
      • Commits should generally be minimal
        • When not to be overly minimal
      • Write a clean commit history
      • Commit messages
        • Commit summary, part 1
        • Commit summary, part 2
        • Examples of good commit summaries
        • Commit description
        • Examples of good commit messages
    • Code style and conventions
      • Be consistent with existing code
        • Use the linters
        • Use tests to verify your logic
      • Follow Zulip conventions and practices
        • Observe a reasonable line length
        • Tag user-facing strings for translation
        • Correctly prepare paths destined for state or log files
        • Never include secrets inline with code
        • Familiarize yourself with rules about third-party code
      • Python-specific conventions and practices
      • JavaScript and TypeScript conventions and practices
        • Build DOM elements in Handlebars
        • Attach behaviors to event listeners
        • Declare variables using const and let
        • Manipulate objects and arrays with modern methods
      • HTML and CSS
      • Dangerous constructs in Django
        • Avoid excessive database queries
        • Never do direct database queries (UserProfile.objects.get(), Client.objects.get(), etc.)
        • Don’t use Django model objects as keys in sets/dicts
        • Don’t call user_profile.save() without update_fields
        • Don’t update important model objects with raw saves
        • Don’t use naive datetime objects
      • Dangerous constructs in JavaScript and TypeScript
        • Do not use for...in statements to traverse arrays
    • Presenting visual changes
      • What to capture
      • What are precise Before/After screenshots?
      • Why bother with precise Before/After screenshots?
      • Capturing precise screenshots
        • Using Git to get required states
        • Capturing precise screenshots with your browser
        • Capturing precise screenshots with native OS tools
        • Capturing precise screenshots with other software
        • Freehand versus fixed screenshots
        • Providing sufficient UI context
      • Capturing and presenting short videos
      • Presenting screenshots on your pull request
        • Using tables for Before/After comparisons
        • Making screenshots collapsible
        • Presenting documentation changes
      • Screenshot and GIF software
        • Screenshot tools by platform
        • GIF tools by platform
        • Keypress visualizers by platform
    • Reviewing Zulip code
      • Principles of code review
        • Reviewing your own code
        • Reviewing other contributors’ code
      • How to review code
        • Code review checklist
        • Automated testing
        • Manual testing
      • Review process and communication
        • Asking for a code review
        • Reviewing someone else’s code
        • Responding to review feedback
      • Additional resources
    • Submitting a pull request
      • Write clear code
      • Organize your proposed changes
      • Explain your changes
        • Discussions in the development community
      • Review your own work
      • Submit your pull request for review
      • Draft pull requests
    • Pull request review process
      • Labels for managing the stages of pull request review
      • Stages of a pull request review
      • How to help move the review process forward
      • Follow-ups
    • Continuing unfinished work
      • Find work to be completed
      • Review existing work and feedback
      • Decide how to use prior work
      • Credit prior work in your commit history
      • Present your pull request
    • Using zulipbot
      • Usage
        • Contributing
    • Reporting bugs
      • What to include in a bug report
      • Filing a GitHub issue
      • Starting a conversation about a possible bug
      • Managing bug reports
    • Reporting security vulnerabilities
      • How to report a possible security issue
      • What happens when a security issue is reported
      • Useful resources for security researchers
      • HackerOne disclosure program
        • What’s in scope
        • What’s out of scope
    • Suggesting features and improvements
      • What to include in your proposal
      • Starting a conversation about a suggested feature or improvement
      • Filing a GitHub issue
      • Evaluation and onboarding feedback
    • Counting contributions
      • How the contribution stats are calculated
      • Old email addresses
      • Relevant source code
      • Attribution for non-code contributions
    • Licensing
      • Contributing your own work
      • Contributing someone else’s work
  • Project processes
    • Designing changes to the Zulip API
      • API change process, in short
      • What is an API change?
      • API design approval
      • API compatibility
        • Changes that are automatically compatible
        • Making a change compatible
      • Clean APIs
      • API change process
        • As a PR author
        • As a PR reviewer
        • As an API reviewer
        • As a channel maintainer of #api design
        • As the mobile team lead
    • Zulip server release checklist
      • A week before the release
      • Final release preparation
      • Executing the release
      • Post-release
    • Zulip PyPI packages release checklist
      • Other PyPI packages maintained by Zulip
  • Development environment
    • Development environment installation
      • Requirements
      • Recommended setup
      • Vagrant setup
      • Advanced setup
      • Slow internet connections
      • Installing remotely
      • Next steps
    • Recommended setup
      • Requirements
      • Step 0: Set up Git & GitHub
      • Step 1: Install prerequisites
      • Step 2: Get Zulip code
      • Step 3: Start the development environment
      • Step 4: Developing
        • Where to edit files
        • VSCode setup (optional)
        • Understanding run-dev debugging output
        • Committing and pushing changes with Git
        • Maintaining the development environment
        • Rebuilding the development environment
        • Shutting down the development environment for use later
        • Resuming the development environment
      • Next steps
      • Troubleshooting and common errors
      • Specifying an Ubuntu mirror
      • Specifying a proxy
      • Using a different port for Vagrant
      • Customizing CPU and RAM allocation
    • Advanced setup
      • Installing directly on Ubuntu, Debian, CentOS, or Fedora
      • Installing using Vagrant with VirtualBox on Windows 10
        • Running Git BASH as an administrator
      • Using the Vagrant Hyper-V provider on Windows (beta)
        • Problems you may encounter
      • Newer versions of supported platforms
    • Using the development environment
      • Common
      • Server
      • Web
      • Mobile
    • Developing remotely
      • Connecting to the remote environment
      • Setting up user accounts
      • Setting up the development environment
      • Running the development server
      • Making changes to code on your remote development server
        • Editing locally
        • Editing remotely
        • Next steps
      • Using an nginx reverse proxy
    • Authentication in the development environment
      • Email and password
      • Google
      • GitHub
      • GitLab
      • Apple
      • Discord
      • SAML
      • When SSL is required
      • Testing LDAP in development
        • Testing avatar and custom profile field synchronization
        • Automated testing
      • Two factor authentication
      • Password form implementation
    • Testing the installer
      • Configuring
      • Running a test install
        • Build and unpack a release tarball
        • Test an install
        • See running containers after installation
        • Connect to a running container
        • Stopping and destroying containers
        • Iterating on the installer
  • Developer tutorials
    • Writing a new application feature
      • General process
        • Files impacted
        • Adding a field to the database
        • Backend changes
        • Frontend changes
        • Documentation changes
      • Example feature
        • Update the model
        • Create the migration
        • Test your migration changes
        • Handle database interactions
        • Update application state
        • Add a new view
        • Backend tests
        • What is my fantastic feature?
        • Update the frontend
        • Manually test
        • Frontend tests
        • Update documentation
        • Share your fantastic feature
    • Writing views in Zulip
      • What this covers
      • What is a view?
      • Modifying urls.py
      • Writing human-readable views
        • Decorators used for webpage views
        • Writing a template
      • Writing API REST endpoints
        • Request variables
        • Deciding which HTTP verb to use
        • Idempotency
        • Making changes to the database
        • Calling from the web application
        • Calling from an API client
      • Legacy endpoints used by the web client
      • Incoming webhook integrations
    • Life of a request
      • A request is sent to the server, and handled by nginx
      • Static files are served directly by nginx
      • nginx routes other requests between Django and Tornado
      • Django routes the request to a view in urls.py files
      • Views serving HTML are internationalized by server path
      • API endpoints use REST
        • PUT is only for creating new things
        • OPTIONS
        • Incoming webhook integrations may not be RESTful
      • Django calls rest_dispatch for REST endpoints, and authenticates
      • The view will authorize the user, extract request variables, and validate them
      • Results are given as JSON
    • Reading list
      • General programming/IT
      • Python
      • Java/Android
      • JavaScript/ECMAScript
      • TypeScript
      • Git/version control systems (VCS)
      • Computer science/algorithms
      • Community experience
      • Competitions/camps
      • Massive open online courses (MOOC) platforms
    • Shell tips
      • The prompt ($)
      • Tilde character (~)
      • Change directory (cd)
      • Running commands as root (sudo)
      • Escaping characters
      • Sequencing commands
      • Splitting commands into multiple lines
      • Arguments
      • Shebang
      • Understanding commands
      • Cheatsheet
      • Git
  • Git guide
    • Quick start
    • Set up Git
      • Install and configure Git, join GitHub
      • Get a graphical client
    • Zulip-specific tools
      • Set up Git repo script
      • Configure continuous integration for your Zulip fork
      • Reset to pull request
      • Fetch a pull request and rebase
      • Fetch a pull request without rebasing
      • Push to a pull request
      • Delete unimportant branches
      • Merge conflict on pnpm-lock.yaml file
    • How Git is different
    • Important Git terms
      • branch
      • cache
      • checkout
      • commit
      • fast-forward
      • fetch
      • hash
      • head
      • HEAD
      • index
      • pull
      • push
      • rebase
    • Get Zulip code
      • Step 1a: Create your fork
      • Step 1b: Clone to your machine
      • Step 1c: Connect your fork to Zulip upstream
      • Step 2: Set up the Zulip development environment
      • Step 3: Configure continuous integration for your fork
    • Working copies
      • Workflows
      • Relevant Git commands
    • Using Git as you work
      • Know what branch you’re working on
      • Keep your fork up to date
      • Work on a feature branch
      • Run linters and tests locally
      • Stage changes
        • Get status of working directory
        • Stage additions with git add
        • Stage deletions with git rm
      • Commit changes
      • Push your commits to GitHub
      • Examine and tidy your commit history
      • Force-push changes to GitHub after you’ve altered your history
    • Pull requests
      • Draft pull requests
      • Create a pull request
        • Step 0: Make sure you’re on a feature branch (not main)
        • Step 1: Update your branch with git rebase
        • Step 2: Push your updated branch to your remote fork
        • Step 3: Open the pull request
      • Update a pull request
    • Collaborate
      • Fetch another contributor’s branch
      • Check out a pull request locally
    • Fixing commits
      • Fixing the last commit
        • Changing the last commit message
        • Changing the last commit
      • Fixing older commits
        • Changing commit messages
        • Deleting old commits
      • Squashing commits
      • Reordering commits
      • Pushing commits after tidying them
    • Reviewing changes
      • Changes on (local) working tree
      • Changes within branches
      • Changes between branches
    • Reading history
      • Use a graphical client
      • The “secret” to using git log -p
      • Filter git log down to relevant commits
      • Filter in your graphical client
      • Git a summary, with git log --oneline
    • Get and stay out of trouble
      • Undo a merge commit
      • Restore a lost commit
      • Recover from a git rebase failure
      • Working from multiple computers
    • Git cheat sheet
      • Common commands
      • Detailed cheat sheet
  • Code testing
    • Testing overview
      • Running tests
      • Major test suites
      • Other test suites
      • Internet access inside test suites
        • Documentation tests
    • Linters
      • Overview
      • Running the linters
      • General considerations
      • Lint checks
      • lint
        • Special options
        • Lint checks
      • Philosophy
        • Speed
        • Accuracy
        • Completeness
    • Backend Django tests
      • Overview
      • Running tests
      • Writing tests
        • Setting up data for tests
        • Testing code that accesses the filesystem
        • Testing with mocks
      • Zulip testing philosophy
        • Endpoint tests
        • Library tests
        • Fixture-driven tests
        • Mocks and stubs
        • Template tests
        • SQL performance tests
        • Event-based tests
        • Negative tests
      • Testing considerations
    • JavaScript/TypeScript unit tests
      • How the node tests work
      • Handling dependencies in unit tests
      • Creating new test modules
      • Verifying HTML templates with mock_template
      • Coverage reports
      • Editor debugger integration
      • Webstorm integration setup
      • Running tests with the debugger
    • Web frontend black-box Puppeteer tests
      • Running tests
      • How Puppeteer tests work
      • Debugging Puppeteer tests
      • Writing Puppeteer tests
    • Python static type checker (mypy)
      • Installing mypy
      • Running mypy on Zulip’s code locally
      • Mypy is there to find bugs in Zulip before they impact users
      • Mypy stubs for third-party modules
      • Working with types from django-stubs
      • Using @overload to accurately describe variations
      • Best practices
        • When is a type annotation justified?
        • Avoid the Any type
        • Avoid cast()
        • Avoid # type: ignore comments
        • Avoid other unchecked constructs
        • Use Optional and None correctly
        • Read-only types
        • Typing decorators
      • Troubleshooting advice
    • TypeScript static types
      • Type checking
      • Linting and style
      • Migration strategy
    • Continuous integration (CI)
      • Goals
      • GitHub Actions
        • Useful debugging tips and tools
        • Suites
        • Configuration
        • Images
        • Performance optimizations
    • Manual testing
      • Basic stuff
        • Message view
        • Messagebox
        • Message editing
        • Narrowing
        • Composing messages
        • Popover menus
        • Sidebar filtering
        • Channel permissions
        • Search
        • Channel settings
        • User settings
        • Keyboard shortcuts
        • Miscellaneous menu options
        • Inviting users/tutorial
        • To be continued…
    • Testing philosophy
      • Effective testing allows us to move quickly
      • Test suite performance and reliability are critical
      • Integration testing or unit testing?
      • Avoid duplicating code with security impact
      • Share test setup code
      • What isn’t tested probably doesn’t work
  • Subsystems documentation
    • Directory structure
      • Core Python files
      • HTML templates
      • JavaScript, TypeScript, and other frontend assets
      • Tests
      • Management commands
      • Scripts
      • API and bots
      • Production Puppet configuration
      • Additional Django apps
      • Jinja2 compatibility files
      • Translation files
      • Documentation
    • Provisioning and third-party dependencies
      • Provisioning
        • PROVISION_VERSION
      • Philosophy on adding third-party dependencies
      • System packages
      • Python packages
      • JavaScript and other frontend packages
      • Node.js and pnpm
      • ShellCheck and shfmt
      • Puppet packages
      • Other third-party and generated files
        • Emoji
        • Translations data
        • Pygments data
      • Modifying provisioning
    • Settings system
      • Server settings
        • Testing non-default settings
      • Realm settings
    • HTML and CSS
      • Zulip CSS organization
      • Editing Zulip CSS
      • CSS style guidelines
        • Avoid duplicated code
        • Be consistent with existing similar UI
        • Use clear, unique names for classes and object IDs
      • Validating CSS
      • HTML templates
        • Behavior
        • Backend templates
        • Frontend templates
        • Toolchain
        • Translation
        • Tooltips
      • Static asset pipeline
        • Primary build process
        • Adding static files
        • How it works in production
        • ES6/TypeScript modules
    • Icons
      • Using icons
      • Adding a new icon
      • Preparing icons for use with Zulip
        • Correcting icons that include strokes
        • Correcting icons with an evenodd fill rule
        • Cleaning up the SVG code
      • Updating UI icons in the help center
    • Accessibility
      • Guidelines
      • Tools
      • GitHub issues
      • Additional resources
    • Real-time push and events
      • Generation system
      • Delivery system
      • The initial data fetch
        • Testing
        • Messages
      • Schema changes
    • Sending messages
      • Message lists
      • Compose area
      • Backend implementation
      • Local echo
        • Local echo in message editing
      • Putting it all together
      • Message editing
        • Inline URL previews
      • Soft deactivation
    • Notifications in Zulip
      • Important corner cases
      • The mobile/email notifications flow
    • Queue processors
      • Adding a new queue processor
      • Publishing events into a queue
      • Clearing a RabbitMQ queue
    • Unread counts and the pointer
      • Pointer logic
        • Recipient bar: message you clicked
        • Search, sidebar click, or new tab: unread/recent matching narrow
        • Unnarrow: previous sequence
        • Forced reload: state preservation
      • Unread count logic
      • Testing and development
    • Markdown implementation
      • Testing
      • Changing Zulip’s Markdown processor
      • Per-realm features
      • Zulip’s Markdown philosophy
      • Zulip’s changes to Markdown
        • Basic syntax
        • Lists
        • Links
        • Code
        • Headings
        • Other
    • Caching in Zulip
      • Backend caching with memcached
        • The core implementation
        • Cautions
        • Cache invalidation after writes
        • Production deployments and database migrations
        • Automated testing and memcached
        • Manual testing and memcached
        • Performance
      • In-process caching in Django
      • Browser caching of state
    • Performance and scalability
      • Load profiles
      • Major Zulip endpoints
        • Tornado
        • Presence
        • Fetching page_params
        • Fetching message history
        • User uploads
        • Sending and editing messages
        • Other endpoints
      • Queue processors and cron jobs
      • Service scalability
    • Realms in Zulip
      • Creating realms
        • Using unique link generator
      • Subdomains
        • Working with subdomains in development environment
    • Management commands
      • Writing management commands
    • Schema migrations
      • Automated testing for migrations
      • Schema and initial data changes
    • Database concurrency
      • select_for_update()
        • What select_for_update() does
        • Lock strengths (no_key)
        • Choosing no_key=True vs no_key=False
        • Example patterns
    • URL hashes and deep linking
      • Hashchange
      • Server-initiated reloads
      • All reloads
    • Emoji
      • Emoji codes
        • Custom emoji
      • Tooling
      • Picking emoji names
    • Onboarding Steps
      • Configuring a New Onboarding Step
        • Step 1: Add the Onboarding Step Name
        • Step 2: Display the Onboarding Step
        • Step 3: Mark the Onboarding Step as Read
    • Full-text search
      • The default full-text search implementation
      • Multi-language full-text search
        • Enabling PGroonga
        • Disabling PGroonga
    • Email
      • Development and testing
        • Testing in a real email client
        • Notes
      • Email templates
    • Analytics
      • Analytics backend overview
      • The *Count database tables
      • CountStats
      • The FillState table
      • Performance strategy
      • Backend testing
      • LoggingCountStats
      • Analytics UI development and testing
        • Setup and testing
        • Adding or editing /stats graphs
        • /activity page
    • Clients in Zulip
      • Analytics
      • Integrations
    • Logging and error reporting
      • Backend error reporting
        • Sentry error logging
        • Backend logging
      • Blueslip frontend error reporting
        • Sentry JavaScript error logging
      • Frontend performance reporting
    • Typing indicators
      • Privacy settings
      • Writing user
      • Server
      • Receiving user
      • Ecosystem
      • Roadmap
    • Upgrading Django
    • UI: input pills
      • Setup
      • Basic usage
      • Typeahead
        • onPillCreate and onPillRemove methods
    • Unread message synchronization
    • Billing (Development)
      • Common setup
      • Manual testing
        • Setup
        • Test card numbers
        • Flows to test
      • Upgrading Stripe API versions
      • Writing tests
    • Widgets
      • What is a widget?
      • /me messages
      • Polls, todo lists, and games
        • Data flow
        • Backward compatibility
        • Adding widgets
      • zform (trivia quiz bot)
      • Data flow
    • Slash commands
      • Data flow
      • Typeahead
    • Thumbnailing
      • libvips
      • Avatars
      • Emoji
      • Realm logos
      • Realm icons
      • File uploads
        • Images
        • Migrations
        • Videos and PDFs
  • Writing documentation
    • Documentation systems
      • Developer and sysadmin documentation
      • Core website documentation
      • User-facing documentation
        • Help center documentation
        • Integrations documentation
        • API documentation
      • Automated testing
    • Writing help center articles
      • Getting started
      • Structure of a feature article
        • Introduction
        • Instructions section
        • Related articles
      • What the help center isn’t for
      • Adding and updating articles
        • Updating an existing article
        • Adding a new article
      • Writing style
        • User interface
        • Voice
        • Keyboard shortcuts
        • Images
      • Viewing and updating help center articles
      • MDX features and custom Zulip components
        • Icons
        • Include files
        • Asides
        • Tabs
      • Redirecting an existing article
    • Documenting an integration
      • Markdown macros
      • Writing guidelines
        • General writing guidelines
        • Guidelines for specific steps
        • Screenshots
      • Markdown features
        • Icons
        • Tips and warnings
        • Tab switcher
    • Documenting REST API endpoints
      • How it works
        • Title and description
        • Usage examples
        • Parameters
        • Response with examples
      • Step by step guide
      • Redirecting an existing article
      • Why a custom system?
      • Debugging schema validation errors
        • Deconstructing the error output
        • Adding a realm setting
    • OpenAPI configuration
      • Working with the zulip.yaml file
        • Configuration
        • Endpoint definitions
        • Schemas
      • Zulip Swagger YAML style:
      • Tips for working with YAML:
        • Formatting help:
        • Examples:
  • Translating Zulip
    • Translation guidelines
      • Translators’ workflow
        • Testing translations
        • Machine translation
        • Translation style guides
        • Capitalization
    • Internationalization for developers
      • How internationalization impacts Zulip’s UI
      • What should be marked for translation
      • How to mark a string for translation
      • Translation syntax in Zulip
        • Web application translations
        • Server translations
      • Translation process
      • Translation resource files
      • Additional resources
    • Chinese translation style guide(中文翻译指南)
      • Note(题记)
      • Terms(术语)
      • Phrases(习惯用语)
      • Others(其它)
    • Finnish translation style guide
      • Guidelines
        • Word order
        • Grammatical case (Sijamuodot)
        • Loan word (Lainasanat)
        • Please, in error messages
        • Zulip word inflection
        • Your -expression
        • Comma
      • Terms
      • Other
    • French translation style guide
      • Community
      • Rules
      • Terms
    • German translation style guide (Richtlinien für die deutsche Übersetzung)
      • Rules
        • Formal or informal?
        • Gender-inclusive language
        • Form of address
        • Form of instruction
        • Rules for labels
        • Concatenation of words
        • Anglicisms
        • Special characters
        • False friends
        • Other
      • Terms (Begriffe)
      • Phrases (Ausdrücke)
      • Other (Verschiedenes)
    • Hindi translation style guide (हिन्दी अनुवाद शैली मार्गदर्शक)
      • Terms (शर्तें)
      • Phrases (वाक्यांश)
      • Others (अन्य)
    • Japanese translation style guide
      • Rules
      • Terms
    • Polish translation style guide
      • Special terms used in Zulip
    • Russian translation style guide
      • Перевод некоторых терминов
    • Spanish translation style guide
      • Términos
      • Frases
      • Otros
    • Urdu translation style guide(انداذِ ترجمہ کا رہنما)
      • Terms(اصطلاحات)
      • Phrases (فِقْرے)
      • Others(مختلف دیگر)
  • Outreach programs
    • Outreach programs overview
      • About Zulip
      • Outreach program experience
    • How to apply
      • Application criteria
      • Applicant eligibility
      • Getting started
      • Putting together your application
        • What to include
        • Project proposals
        • Circulating your application for feedback
    • How to have an amazing experience
      • Your goals
      • You and your mentor
      • Communication and check-ins
        • Getting feedback and advice
        • How to post your check-ins
      • Peer reviews
      • How do I figure out what to work on?
        • Prioritization
        • What about my proposal?
        • Tips for finding issues to pick up
        • Staying productive
      • How else can I contribute?
      • Timeline extensions for GSoC
    • GSoC project ideas
      • Project size
      • Focus areas
      • Project ideas by area
        • Full stack and web frontend focused projects
        • Terminal app
        • Desktop app
        • Mobile app
    • Mentoring
      • Who can mentor
      • Supporting your mentee
        • Establishing communication patterns
      • Managing challenges
  • Index
Zulip
  • Subsystems documentation
  • Full-text search
  • View page source

Full-text search

Zulip supports full-text search, which can be combined arbitrarily with Zulip’s full suite of narrowing operators. By default, it only supports English text, but there is an experimental PGroonga integration that provides full-text search for all languages.

The user interface and feature set for Zulip’s full-text search is documented in the in-app “Search filters” reference which can be accessed from the Zulip app’s gear menu.

The default full-text search implementation

Zulip uses PostgreSQL’s built-in full-text search feature, with a custom set of English stop words to improve the quality of the search results.

In order to optimize the performance of delivering messages, the full-text search index is updated for newly sent messages in the background, after the message has been delivered. This background updating is done by puppet/zulip/files/postgresql/process_fts_updates, which is usually deployed on the database server, but could be deployed on an application server instead.

Multi-language full-text search

Zulip also supports using PGroonga for full-text search. While PostgreSQL’s built-in full-text search feature supports only one language at a time (in Zulip’s case, English), the PGroonga full-text search engine supports all languages simultaneously, including Japanese and Chinese. Once we have tested this new backend sufficiently, we expect to switch Zulip deployments to always use PGroonga.

Enabling PGroonga

All steps in this section should be run as the root user; on most installs, this can be done by running sudo -i.

  1. Alter the deployment setting:

    crudini --set /etc/zulip/zulip.conf machine pgroonga enabled
    
  2. Update the deployment to respect that new setting:

    /home/zulip/deployments/current/scripts/zulip-puppet-apply
    
  3. Edit /etc/zulip/settings.py, to add:

    USING_PGROONGA = True
    
  4. Apply the PGroonga migrations:

    su zulip -c '/home/zulip/deployments/current/manage.py migrate pgroonga'
    

    Note that the migration may take a long time, and users will be unable to send new messages until the migration finishes.

  5. Once the migrations are complete, restart Zulip:

    su zulip -c '/home/zulip/deployments/current/scripts/restart-server'
    

Disabling PGroonga

  1. Remove the PGroonga migration:

    su zulip -c '/home/zulip/deployments/current/manage.py migrate pgroonga zero'
    

    If you intend to re-enable PGroonga later, you can skip this step, at the cost of your Message table being slightly larger than it would be otherwise.

  2. Edit /etc/zulip/settings.py, editing the line containing USING_PGROONGA to read:

    USING_PGROONGA = False
    
  3. Restart Zulip:

    su zulip -c '/home/zulip/deployments/current/scripts/restart-server'
    
  4. Finally, remove the deployment setting:

    crudini --del /etc/zulip/zulip.conf machine pgroonga
    
Previous Next

© Copyright 2012–2015 Dropbox, Inc., 2015–2021 Kandra Labs, Inc., and contributors.

Built with Sphinx using a theme provided by Read the Docs.