Logo
stable
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
      • Glossary
    • Directory structure
      • Core Python files
      • HTML templates
      • JavaScript, TypeScript, and other static assets
      • Tests
      • Management commands
      • Scripts
      • API and bots
      • Production Puppet configuration
      • Additional Django apps
      • Jinja2 compatibility files
      • Translation files
      • Documentation
    • Release lifecycle
      • Server and web app
        • Stable releases
        • Git versions
        • Compatibility and upgrading
        • Security releases
        • Upgrade nag
        • Operating system support
        • Server roadmap
      • Client apps
      • API bindings
    • Version history
      • Zulip 6.x series
        • 6.1 – 2023-01-23
        • 6.0 – 2022-11-17
      • Zulip 5.x series
        • 5.7 – 2022-11-16
        • 5.6 – 2022-08-24
        • 5.5 – 2022-07-21
        • 5.4 – 2022-07-11
        • 5.3 – 2022-06-21
        • 5.2 – 2022-05-03
        • 5.1 – 2022-04-01
        • 5.0 – 2022-03-29
      • Zulip 4.x series
        • 4.11 – 2022-03-15
        • 4.10 – 2022-02-25
        • 4.9 – 2022-01-24
        • 4.8 – 2021-12-01
        • 4.7 – 2021-10-04
        • 4.6 – 2021-09-23
        • 4.5 – 2021-07-25
        • 4.4 – 2021-07-22
        • 4.3 – 2021-06-02
        • 4.2 – 2021-05-13
        • 4.1 – 2021-05-13
        • 4.0 – 2021-05-13
      • Zulip 3.x series
        • 3.4 – 2021-04-14
        • 3.3 – 2020-12-01
        • 3.2 – 2020-09-15
        • 3.1 – 2020-07-30
        • 3.0 – 2020-07-16
      • Zulip 2.1.x series
        • 2.1.8 – 2021-08-11
        • 2.1.7 – 2020-06-25
        • 2.1.6 – 2020-06-17
        • 2.1.5 – 2020-06-16
        • 2.1.4 – 2020-04-16
        • 2.1.3 – 2020-04-01
        • 2.1.2 – 2020-01-16
        • 2.1.1 – 2019-12-13
        • 2.1.0 – 2019-12-12
      • Zulip 2.0.x series
        • 2.0.8 – 2019-12-12
        • 2.0.7 – 2019-11-21
        • 2.0.6 – 2019-09-23
        • 2.0.5 – 2019-09-11
        • 2.0.4 – 2019-06-29
        • 2.0.3 – 2019-04-23
        • 2.0.2 – 2019-03-15
        • 2.0.1 – 2019-03-04
        • 2.0.0 – 2019-03-01
      • Zulip 1.9.x series
        • 1.9.2 – 2019-01-29
        • 1.9.1 – 2018-11-30
        • 1.9.0 – 2018-11-07
      • Zulip 1.8.x series
        • 1.8.1 – 2018-05-07
        • 1.8.0 – 2018-04-17
      • Zulip 1.7.x series
        • 1.7.2 – 2018-04-12
        • 1.7.1 – 2017-11-21
        • 1.7.0 – 2017-10-25
      • Zulip 1.6.x and older
        • 1.6.0 – 2017-06-06
        • 1.5.2 – 2017-06-01
        • 1.5.1 – 2017-02-07
        • 1.5.0 – 2017-02-06
        • 1.4.3 - 2017-01-29
        • 1.4.2 - 2016-09-27
        • 1.4.1 - 2016-09-03
        • 1.4.0 - 2016-08-25
        • 1.3.13 - 2016-06-21
        • 1.3.12 - 2016-05-10
        • 1.3.11 - 2016-05-02
        • 1.3.10 - 2016-01-21
        • 1.3.9 - 2015-11-16
        • 1.3.8 - 2015-11-15
        • 1.3.7 - 2015-10-19
      • 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
      • Before you begin
        • Should I follow this installation guide?
      • Step 1: Download the latest release
      • Step 2: Install Zulip
        • Installer options
      • Step 3: Create a Zulip organization, and log in
      • Step 4: Configure and use
      • Details: What the installer does
      • Troubleshooting
    • Troubleshooting and monitoring
      • 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
    • Management commands
      • Running management commands
        • Accessing an organization’s string_id
      • manage.py shell
      • Other useful manage.py commands
      • Custom management commands
    • Customize Zulip
      • Making changes
      • Specific settings
        • Domain and email settings
        • Authentication backends
        • Mobile and desktop apps
        • Terms of Service and Privacy policy
        • Miscellaneous server settings
      • Zulip announcement list
      • Enjoy your Zulip installation!
    • Mobile push notification service
      • How to sign up
      • Updating your server’s registration
      • Why this is necessary
      • Security and privacy
      • Submitting statistics
      • Rate limits
      • Sending push notifications directly from your server
    • Upgrade or modify Zulip
      • Upgrading to a release
      • Upgrading from a Git repository
      • Updating settings.py inline documentation
      • Troubleshooting and rollback
        • Rolling back to a prior version
      • Preserving local changes to service configuration files
        • nginx configuration changes
      • Upgrading the operating system
        • 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 Ubuntu 14.04 Trusty to 16.04 Xenial
        • Upgrading from Debian 10 to 11
        • Upgrading from Debian 9 to 10
      • Upgrading PostgreSQL
      • Modifying 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
    • Security model
      • Secure your Zulip server like your email server
      • Encryption and authentication
        • Passwords
      • Messages and history
      • Users and bots
      • User-uploaded content and user-generated requests
      • Rate limiting
      • Final notes and security response
    • Authentication methods
      • Email and password
      • Plug-and-play SSO (Google, GitHub, GitLab)
      • LDAP (including Active Directory)
        • Synchronizing data
        • 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
        • Using Keycloak as a SAML IdP
        • IdP-initiated SAML 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
      • Sign in with Apple
      • OpenID Connect
      • Adding more authentication backends
      • Development only
    • Backups, export and import
      • Backups
        • Restoring backups
        • What is included
        • Restore from manual backups
      • Data export
        • 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
    • PostgreSQL database details
      • Remote PostgreSQL database
      • Debugging PostgreSQL database issues
      • Stopping the Zulip PostgreSQL database
      • Debugging issues starting PostgreSQL
      • PostgreSQL vacuuming alerts
    • File upload backends
      • S3 backend configuration
      • S3 bucket policy
      • Migrating from local uploads to Amazon S3 backend
    • 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
      • Advanced installer options
      • Installing on an existing server
      • Running Zulip’s service dependencies on different machines
        • Using Zulip with Amazon RDS as the database
      • Using an alternate port
      • Customizing the outgoing HTTP proxy
        • S3 file storage requests and outgoing proxies
      • Putting the Zulip application behind a reverse proxy
        • Installer options
        • nginx configuration
        • Apache2 configuration
        • HAProxy configuration
        • Other proxies
      • PostgreSQL warm standby
      • System and deployment configuration
        • [machine]
        • [deployment]
        • [application_server]
        • [postfix]
        • [postgresql]
        • [memcached]
        • [loadbalancer]
        • [http_proxy]
    • Incoming email integration
      • Local delivery setup
      • Polling setup
    • Video call providers
      • Zoom
      • BigBlueButton
    • GIPHY GIF integration
      • Apply for API key
  • Contributing to Zulip
    • Contributing guide
      • Zulip development community
      • Ways to contribute
      • Your first codebase contribution
        • Where to look for an issue
        • Picking an issue to work on
        • Claiming an issue
        • Working on an issue
        • Submitting a pull request
        • Stages of a pull request
        • Beyond the first issue
        • Common questions
      • What makes a great Zulip contributor?
      • Reporting issues
      • User feedback
      • Outreach programs
      • Stay connected
      • Help others find Zulip
    • Zulip Code of Conduct
      • Expected behavior
      • Unacceptable behavior
      • Reporting and enforcement
      • Scope
      • License and attribution
    • 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 stream
      • Guidelines for decision makers
        • Managing the discussion
        • From discussion to decision
    • Version control
      • Commit discipline
      • Commit messages
        • Good summaries:
        • Message body:
    • Code style and conventions
      • Be consistent!
      • Lint tools
      • Secrets
      • Dangerous constructs
        • Too many database queries
        • UserProfile.objects.get() / Client.objects.get() / etc.
        • Using Django model objects as keys in sets/dicts
        • user_profile.save()
        • Using raw saves to update important model objects
        • Naive datetime objects
        • x.attr('zid') vs. rows.id(x)
        • JavaScript const and let
        • JavaScript and TypeScript for (i in myArray)
        • Translation tags
        • Paths to state or log files
      • JS array/object manipulation
      • More arbitrary style things
        • Line length
        • JavaScript and TypeScript
        • HTML / CSS
        • Python
        • Tests
        • Third party code
    • Reviewable pull requests
      • Posting a pull request
      • Addressing feedback
      • Working on larger projects
    • 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
    • Using zulipbot
      • Usage
        • Contributing
    • Bug report guidelines
    • Licensing
      • Contributing your own work
      • Contributing someone else’s work
  • 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
        • macOS
        • Ubuntu
        • Debian
        • Fedora
        • Windows 10
      • Step 2: Get Zulip code
      • Step 3: Start the development environment
      • Step 4: Developing
        • Where to edit files
        • Understanding run-dev.py 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
        • Vagrant guest doesn’t show (zulip-py3-venv) at start of prompt
        • Vagrant was unable to mount VirtualBox shared folders
        • ssl read error
        • Unmet dependencies error
        • ssh connection closed by remote host
        • os.symlink error
        • Hyper-V error messages
        • Connection timeout on vagrant up
        • Vagrant was unable to communicate with the guest machine
        • Vagrant up fails with subprocess.CalledProcessError
        • VBoxManage errors related to VT-x or WHvSetupPartition
        • OSError: [Errno 26] Text file busy
      • 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
      • 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
        • Update the frontend
        • Frontend tests
        • Update documentation
    • 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
        • Legacy endpoints are used by the web client
        • 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
    • Screenshot and GIF software
      • Screenshot tools by platform
        • Browser
        • macOS
        • Windows
        • Linux
      • GIF tools by platform
        • Browser
        • macOS
        • Windows
        • Linux
    • 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 yarn.lock 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
    • 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
      • 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
        • Stream permissions
        • Search
        • Stream 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
    • Provisioning and third-party dependencies
      • Provisioning
        • PROVISION_VERSION
      • Philosophy on adding third-party dependencies
      • System packages
      • Python packages
        • Upgrading packages
      • JavaScript and other frontend packages
      • Node.js and Yarn
      • 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
    • 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
        • 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
    • URL hashes and deep linking
      • Hashchange
      • Server-initiated reloads
      • All reloads
    • Emoji
      • Emoji codes
        • Custom emoji
      • Tooling
      • Picking emoji names
    • Hotspots
      • Adding a new hotspot
        • Step 1: Create hotspot content
        • Step 2: Configure hotspot placement
        • Step 3: Test manually
        • Step 4 (if necessary): Tweak hotspot icon z-index
    • 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
        • Backend logging
      • Blueslip frontend error reporting
      • Frontend performance reporting
    • Typing indicators
      • Writing user
      • Server
      • Receiving user
      • Ecosystem
      • Roadmap
    • Upgrading Django
    • 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
    • UI: input pills
      • Setup
      • Basic usage
      • Typeahead
        • onPillCreate and onPillRemove methods
    • Presence
    • Unread message synchronization
    • Billing (Development)
      • Common setup
      • Manual testing
        • Setup
        • Test card numbers
        • Flows to test
      • Upgrading Stripe API versions
    • 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
  • 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
      • Guide to writing help center articles
        • Getting started
        • Updating an existing article
        • Adding a new article
        • Redirecting an existing article
      • Writing style
        • User interface
        • Voice
        • Keyboard shortcuts
      • Markdown features
        • Images
        • Icons
        • Macros
        • Tips and warnings
        • Tab switcher
    • Documenting an integration
      • Markdown macros
      • Writing guidelines
        • General writing guidelines
        • Guidelines for specific steps
        • Screenshots
    • Documenting REST API endpoints
      • How it works
        • Title and description
        • Usage examples
        • Parameters
        • Displaying example payloads/responses
      • Step by step guide
      • Why a custom system?
    • 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
        • Translation style guides
        • Capitalization
    • Internationalization for developers
      • Key details about human language
      • Translation process
      • Translation resource files
      • HTML Templates
      • Backend translations
        • Jinja2 templates
        • Python
      • Frontend translations
        • Handlebars templates
      • Transifex config
      • Transifex CLI setup
    • 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
      • Rules
      • Terms
    • German translation style guide (Richtlinien für die deutsche Übersetzung)
      • Rules
        • Formal or informal?
        • 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(अन्य)
    • Polish translation style guide
      • Special terms used in Zulip
    • Russian translation style guide
      • Перевод некоторых терминов
    • Spanish translation style guide
      • Términos
      • Frases
      • Otros
  • Outreach programs
    • Outreach programs overview
      • About Zulip
      • Outreach program experience
    • How to apply
      • Application criteria
      • 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 and difficulty
      • Focus areas
      • Project ideas by area
        • Full stack and web frontend focused projects
        • React Native mobile app
        • Electron desktop app
        • Terminal app
        • Archive tool
    • Mentoring
      • Who can mentor
      • Supporting your mentee
      • Managing challenges
  • Index
Zulip
  • Development environment
  • Recommended environment setup tutorial
  • Edit on GitHub

Recommended environment setup tutorial

This section guides first-time contributors through installing the Zulip development environment on Windows, macOS, and Linux.

The recommended method for installing the Zulip development environment is to use WSL 2 on Windows, and Vagrant with Docker on macOS and Linux. This methoduses the Windows Subsystem for Linux or creates a Linux container (for macOS and Linux) inside which the Zulip server and all related services will run.

Contents:

  • 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

  • Troubleshooting and common errors

  • Specifying an Ubuntu mirror

  • Specifying a proxy

  • Customizing CPU and RAM allocation

If you encounter errors installing the Zulip development environment, check troubleshooting and common errors. If that doesn’t help, please visit #provision help in the Zulip development community server for real-time help or file an issue.

When reporting your issue, please include the following information:

  • host operating system

  • installation method (Vagrant or direct)

  • whether or not you are using a proxy

  • a copy of Zulip’s vagrant provisioning logs, available in /var/log/provision.log on your virtual machine

Requirements

Installing the Zulip development environment with Vagrant requires downloading several hundred megabytes of dependencies. You will need an active internet connection throughout the entire installation processes. (See Specifying a proxy if you need a proxy to access the internet.)

  • All: 2GB available RAM, Active broadband internet connection, GitHub account.

  • macOS: macOS (10.11 El Capitan or newer recommended)

  • Ubuntu LTS: 20.04 or 22.04

  • Debian: 11

  • Fedora: tested for 36

  • Windows: Windows 64-bit (Win 10 recommended), hardware virtualization enabled (VT-x or AMD-V), administrator access.

Other Linux distributions work great too, but we don’t maintain documentation for installing Vagrant and Docker on those systems, so you’ll need to find a separate guide and crib from these docs.

Step 0: Set up Git & GitHub

You can skip this step if you already have Git, GitHub, and SSH access to GitHub working on your machine.

Follow our Git guide in order to install Git, set up a GitHub account, create an SSH key to access code on GitHub efficiently, etc. Be sure to create an SSH key and add it to your GitHub account using these instructions.

Step 1: Install prerequisites

Jump to:

  • macOS

  • Ubuntu

  • Debian

  • Fedora

  • Windows

macOS

  1. Install Vagrant (latest).

  2. Install Docker Desktop (latest).

Now you are ready for Step 2: Get Zulip code.

Ubuntu

1. Install Vagrant, Docker, and Git

christie@ubuntu-desktop:~
$ sudo apt install vagrant docker.io git

2. Add yourself to the docker group:

christie@ubuntu-desktop:~
$ sudo adduser $USER docker
Adding user `christie' to group `docker' ...
Adding user christie to group docker
Done.

You will need to reboot for this change to take effect. If it worked, you will see docker in your list of groups:

christie@ubuntu-desktop:~
$ groups | grep docker
christie adm cdrom sudo dip plugdev lpadmin sambashare docker

3. Make sure the Docker daemon is running:

If you had previously installed and removed an older version of Docker, an Ubuntu bug may prevent Docker from being automatically enabled and started after installation. You can check using the following:

$ systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
   Active: active (running) since Mon 2019-07-15 23:20:46 IST; 18min ago

If the service is not running, you’ll see Active: inactive (dead) on the second line, and will need to enable and start the Docker service using the following:

sudo systemctl unmask docker
sudo systemctl enable docker
sudo systemctl start docker

Now you are ready for Step 2: Get Zulip code.

Debian

The setup for Debian is the same as that for Ubuntu above.

Fedora

The setup for Fedora is mostly equivalent to the setup for Ubuntu. The only difference is the installation of Docker. Fedora does not include the official docker-ce package (named docker.io in the setup for Ubuntu) in their repositories. They provide the package moby-engine which you can choose instead. In case you prefer the official docker distribution, you can follow their documentation to install Docker on Fedora.

Windows 10

Zulip’s development environment is most easily set up on Windows using the Windows Subsystem for Linux (WSL 2) installation method described here.

  1. Enable virtualization through your BIOS settings. This sequence depends on your specific hardware and brand, but here are some basic instructions.

  2. Install WSL 2.

  3. Launch the Ubuntu shell as an administrator and run the following command:

    sudo apt update && sudo apt upgrade
    
  4. Install dependencies with the following command:

    sudo apt install rabbitmq-server memcached redis-server postgresql
    
  5. Open /etc/rabbitmq/rabbitmq-env.conf using e.g.:

    sudo nano /etc/rabbitmq/rabbitmq-env.conf
    

    Confirm the following lines are at the end of your file, and add them if not present. Then save your changes (Ctrl+O, then Enter to confirm the path), and exit nano (Ctrl+X).

    NODE_IP_ADDRESS=127.0.0.1
    NODE_PORT=5672
    
  6. Run the command below to make sure you are inside the WSL disk and not in a Windows mounted disk. You will run into permission issues if you run provision from zulip in a Windows mounted disk.

    cd ~  # or cd /home/USERNAME
    
  7. Create your fork of the Zulip server repository.

  8. Create a new SSH key for the WSL-2 Virtual Machine and add it to your GitHub account. Note that SSH keys linked to your Windows computer will not work within the virtual machine.

  9. Clone and connect to the Zulip upstream repository:

    git clone --config pull.rebase git@github.com:YOURUSERNAME/zulip.git ~/zulip
    cd zulip
    git remote add -f upstream https://github.com/zulip/zulip.git
    
  10. Run the following to install the Zulip development environment and start it. (If Windows Firewall creates popups to block services, simply click Allow Access.)

    # Start database, cache, and other services
    ./tools/wsl/start_services
    # Install/update the Zulip development environment
    ./tools/provision
    # Enter the Zulip Python environment
    source /srv/zulip-py3-venv/bin/activate
    # Start the development server
    ./tools/run-dev.py
    

    Note

    If you shut down WSL, after starting it again, you will have to manually start the services using ./tools/wsl/start_services.

  11. If you are facing problems or you see error messages after running ./tools/run-dev.py, you can try running ./tools/provision again.

  12. The Visual Studio Code Remote - WSL extension is recommended for editing files when developing with WSL. When you have it installed, you can run:

    code .
    

    to open VSCode connected to your WSL environment.

  13. You’re done! Now you’re ready for Step 4: Developing, ignoring the parts about vagrant (since you’re not using it).

WSL 2 can be uninstalled by following Microsoft’s documentation

Step 2: Get Zulip code

  1. In your browser, visit https://github.com/zulip/zulip and click the fork button. You will need to be logged in to GitHub to do this.

  2. Open Terminal (macOS/Linux) or Git BASH (Windows; must run as an Administrator).

  3. In Terminal/Git BASH, clone your fork of the Zulip repository and connect the Zulip upstream repository:

git clone --config pull.rebase git@github.com:YOURUSERNAME/zulip.git
cd zulip
git remote add -f upstream https://github.com/zulip/zulip.git

This will create a ‘zulip’ directory and download the Zulip code into it.

Don’t forget to replace YOURUSERNAME with your Git username. You will see something like:

christie@win10 ~
$ git clone --config pull.rebase git@github.com:YOURUSERNAME/zulip.git
Cloning into 'zulip'...
remote: Counting objects: 73571, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 73571 (delta 1), reused 0 (delta 0), pack-reused 73569
Receiving objects: 100% (73571/73571), 105.30 MiB | 6.46 MiB/s, done.
Resolving deltas: 100% (51448/51448), done.
Checking connectivity... done.
Checking out files: 100% (1912/1912), done.`

Now you are ready for Step 3: Start the development environment.

Step 3: Start the development environment

Change into the zulip directory and tell vagrant to start the Zulip development environment with vagrant up:

# On Windows:
cd zulip
vagrant plugin install vagrant-vbguest
vagrant up --provider=virtualbox

# On macOS or Linux:
cd zulip
vagrant up --provider=docker

The first time you run this command it will take some time because vagrant does the following:

  • downloads the base Ubuntu 20.04 virtual machine image (for macOS and Windows) or container (for Linux)

  • configures this virtual machine/container for use with Zulip,

  • creates a shared directory mapping your clone of the Zulip code inside the virtual machine/container at ~/zulip

  • runs the tools/provision script inside the virtual machine/container, which downloads all required dependencies, sets up the python environment for the Zulip development server, and initializes a default test database. We call this process “provisioning”, and it is documented in some detail in our dependencies documentation.

You will need an active internet connection during the entire process. (See Specifying a proxy if you need a proxy to access the internet.) vagrant up can fail while provisioning if your Internet connection is unreliable. To retry, you can use vagrant provision (vagrant up will just boot the guest without provisioning after the first time). Other common issues are documented in the Troubleshooting and common errors section. If that doesn’t help, please visit #provision help in the Zulip development community server for real-time help.

On Windows, you will see the message The system cannot find the path specified. several times. This is normal and is not a problem.

Once vagrant up has completed, connect to the development environment with vagrant ssh:

christie@win10 ~/zulip
$ vagrant ssh

You should see output that starts like this:

Welcome to Ubuntu 20.04.4 LTS (GNU/Linux 5.4.0-107-generic x86_64)

Congrats, you’re now inside the Zulip development environment!

You can confirm this by looking at the command prompt, which starts with (zulip-py3-venv)vagrant@. If it just starts with vagrant@, your provisioning failed and you should look at the troubleshooting section.

Next, start the Zulip server:

(zulip-py3-venv) vagrant@vagrant:/srv/zulip
$ ./tools/run-dev.py

You will see several lines of output starting with something like:

2016-05-04 22:20:33,895 INFO: process_fts_updates starting
Recompiling templates
2016-05-04 18:20:34,804 INFO: Not in recovery; listening for FTS updates
done
Validating Django models.py...
System check identified no issues (0 silenced).

Django version 1.8
Tornado server is running at http://localhost:9993/
Quit the server with CTRL-C.
2016-05-04 18:20:40,716 INFO     Tornado loaded 0 event queues in 0.001s
2016-05-04 18:20:40,722 INFO     Tornado  95.5% busy over the past  0.0 seconds
Performing system checks...

And ending with something similar to:

http://localhost:9994/webpack-dev-server/
webpack result is served from http://localhost:9991/webpack/
content is served from /srv/zulip

webpack: bundle is now VALID.
2016-05-06 21:43:29,553 INFO     Tornado  31.6% busy over the past 10.6 seconds
2016-05-06 21:43:35,007 INFO     Tornado  23.9% busy over the past 16.0 seconds

Now the Zulip server should be running and accessible. Verify this by navigating to http://localhost:9991/ in the browser on your main machine.

You should see something like this:

Image of Zulip development environment

The Zulip server will continue to run and send output to the terminal window. When you navigate to Zulip in your browser, check your terminal and you should see something like:

2016-05-04 18:21:57,547 INFO     127.0.0.1       GET     302 582ms (+start: 417ms) / (unauth@zulip via ?)
[04/May/2016 18:21:57]"GET / HTTP/1.0" 302 0
2016-05-04 18:21:57,568 INFO     127.0.0.1       GET     301   4ms /login (unauth@zulip via ?)
[04/May/2016 18:21:57]"GET /login HTTP/1.0" 301 0
2016-05-04 18:21:57,819 INFO     127.0.0.1       GET     200 209ms (db: 7ms/2q) /login/ (unauth@zulip via ?)

Now you’re ready for Step 4: Developing.

Step 4: Developing

Where to edit files

You’ll work by editing files on your host machine, in the directory where you cloned Zulip. Use your favorite editor (Sublime, Atom, Vim, Emacs, Notepad++, etc.).

When you save changes they will be synced automatically to the Zulip development environment on the virtual machine/container.

Each component of the Zulip development server will automatically restart itself or reload data appropriately when you make changes. So, to see your changes, all you usually have to do is reload your browser. More details on how this works are available below.

Zulip’s whitespace rules are all enforced by linters, so be sure to run tools/lint often to make sure you’re following our coding style (or use tools/setup-git-repo to run it on just the changed files automatically whenever you commit).

Understanding run-dev.py debugging output

It’s good to have the terminal running run-dev.py up as you work since error messages including tracebacks along with every backend request will be printed there.

See Logging for further details on the run-dev.py console output.

Committing and pushing changes with Git

When you’re ready to commit or push changes via Git, you will do this by running Git commands in Terminal (macOS/Linux) or Git BASH (Windows) in the directory where you cloned Zulip on your main machine.

If you’re new to working with Git/GitHub, check out our Git & GitHub guide.

Maintaining the development environment

If after rebasing onto a new version of the Zulip server, you receive new errors while starting the Zulip server or running tests, this is probably not because Zulip’s main branch is broken. Instead, this is likely because we’ve recently merged changes to the development environment provisioning process that you need to apply to your development environment. To update your environment, you’ll need to re-provision your vagrant machine using vagrant provision (this just runs tools/provision from your Zulip checkout inside the Vagrant guest); this should complete in about a minute.

After provisioning, you’ll want to (re)start the Zulip development server.

If you run into any trouble, #provision help in the Zulip development community server is a great place to ask for help.

Rebuilding the development environment

If you ever want to recreate your development environment again from scratch (e.g. to test a change you’ve made to the provisioning process, or because you think something is broken), you can do so using vagrant destroy and then vagrant up. This will usually be much faster than the original vagrant up since the base image is already cached on your machine (it takes about 5 minutes to run with a fast Internet connection).

Any additional programs (e.g. Zsh, emacs, etc.) or configuration that you may have installed in the development environment will be lost when you recreate it. To address this, you can create a script called tools/custom_provision in your Zulip Git checkout; and place any extra setup commands there. Vagrant will run tools/custom_provision every time you run vagrant provision (or create a Vagrant guest via vagrant up).

Shutting down the development environment for use later

To shut down but preserve the development environment so you can use it again later use vagrant halt or vagrant suspend.

You can do this from the same Terminal/Git BASH window that is running run-dev.py by pressing ^C to halt the server and then typing exit. Or you can halt vagrant from another Terminal/Git BASH window.

From the window where run-dev.py is running:

2016-05-04 18:33:13,330 INFO     127.0.0.1       GET     200  92ms /register/ (unauth@zulip via ?)
^C
KeyboardInterrupt
(zulip-py3-venv) vagrant@vagrant:/srv/zulip$ exit
logout
Connection to 127.0.0.1 closed.
christie@win10 ~/zulip

Now you can suspend the development environment:

christie@win10 ~/zulip
$ vagrant suspend
==> default: Saving VM state and suspending execution...

If vagrant suspend doesn’t work, try vagrant halt:

christie@win10 ~/zulip
$ vagrant halt
==> default: Attempting graceful shutdown of VM...

Check out the Vagrant documentation to learn more about suspend and halt.

Resuming the development environment

When you’re ready to work on Zulip again, run vagrant up (no need to pass the --provider option required above). You will also need to connect to the virtual machine with vagrant ssh and re-start the Zulip server:

christie@win10 ~/zulip
$ vagrant up
$ vagrant ssh

(zulip-py3-venv) vagrant@vagrant:/srv/zulip
$ ./tools/run-dev.py

Next steps

Next, read the following to learn more about developing for Zulip:

  • Git & GitHub guide

  • Using the development environment

  • Testing (and Configuring CI to run the full test suite against any branches you push to your fork, which can help you optimize your development workflow).

Troubleshooting and common errors

Below you’ll find a list of common errors and their solutions. Most issues are resolved by just provisioning again (by running ./tools/provision (from /srv/zulip) inside the Vagrant guest or equivalently vagrant provision from outside).

If these solutions aren’t working for you or you encounter an issue not documented below, there are a few ways to get further help:

  • Ask in #provision help in the Zulip development community server.

  • File an issue.

When reporting your issue, please include the following information:

  • host operating system

  • installation method (Vagrant or direct)

  • whether or not you are using a proxy

  • a copy of Zulip’s vagrant provisioning logs, available in /var/log/provision.log on your virtual machine. If you choose to post just the error output, please include the beginning of the error output, not just the last few lines.

The output of tools/diagnose run inside the Vagrant guest is also usually helpful.

Vagrant guest doesn’t show (zulip-py3-venv) at start of prompt

This is caused by provisioning failing to complete successfully. You can see the errors in var/log/provision.log; it should end with something like this:

ESC[94mZulip development environment setup succeeded!ESC[0m

The ESC stuff are the terminal color codes that make it show as a nice blue in the terminal, which unfortunately looks ugly in the logs.

If you encounter an incomplete /var/log/provision.log file, you need to update your environment. Re-provision your vagrant machine; if the problem persists, please come chat with us (see instructions above) for help.

After you provision successfully, you’ll need to exit your vagrant ssh shell and run vagrant ssh again to get the virtualenv setup properly.

Vagrant was unable to mount VirtualBox shared folders

For the following error:

Vagrant was unable to mount VirtualBox shared folders. This is usually
because the filesystem "vboxsf" is not available. This filesystem is
made available via the VirtualBox Guest Additions and kernel
module. Please verify that these guest additions are properly
installed in the guest. This is not a bug in Vagrant and is usually
caused by a faulty Vagrant box. For context, the command attempted
was:

 mount -t vboxsf -o uid=1000,gid=1000 keys /keys

If this error starts happening unexpectedly, then just run:

vagrant halt
vagrant up

to reboot the guest. After this, you can do vagrant provision and vagrant ssh.

ssl read error

If you receive the following error while running vagrant up:

SSL read: error:00000000:lib(0):func(0):reason(0), errno 104

It means that either your network connection is unstable and/or very slow. To resolve it, run vagrant up until it works (possibly on a better network connection).

Unmet dependencies error

When running vagrant up or provision, if you see the following error:

==> default: E:unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution).

It means that your local apt repository has been corrupted, which can usually be resolved by executing the command:

apt-get -f install

ssh connection closed by remote host

On running vagrant ssh, if you see the following error:

ssh_exchange_identification: Connection closed by remote host

It usually means the Vagrant guest is not running, which is usually solved by rebooting the Vagrant guest via vagrant halt; vagrant up. See Vagrant was unable to communicate with the guest machine for more details.

os.symlink error

If you receive the following error while running vagrant up:

==> default: Traceback (most recent call last):
==> default: File "./emoji_dump.py", line 75, in <module>
==> default:
==> default: os.symlink('unicode/{}.png'.format(code_point), 'out/{}.png'.format(name))
==> default: OSError
==> default: :
==> default: [Errno 71] Protocol error

Then Vagrant was not able to create a symbolic link.

First, if you are using Windows, make sure you have run Git BASH (or Cygwin) as an administrator. By default, only administrators can create symbolic links on Windows. Additionally UAC, a Windows feature intended to limit the impact of malware, can prevent even administrator accounts from creating symlinks. Turning off UAC will allow you to create symlinks. You can also try some of the solutions mentioned here.

If you ran Git BASH as administrator but you already had VirtualBox running, you might still get this error because VirtualBox is not running as administrator. In that case: close the Zulip VM with vagrant halt; close any other VirtualBox VMs that may be running; exit VirtualBox; and try again with vagrant up --provision from a Git BASH running as administrator.

Second, VirtualBox does not enable symbolic links by default. Vagrant starting with version 1.6.0 enables symbolic links for VirtualBox shared folder.

You can check to see that this is enabled for your virtual machine with vboxmanage command.

Get the name of your virtual machine by running vboxmanage list vms and then print out the custom settings for this virtual machine with vboxmanage getextradata YOURVMNAME enumerate:

christie@win10 ~/zulip
$ vboxmanage list vms
"zulip_default_1462498139595_55484" {5a65199d-8afa-4265-b2f6-6b1f162f157d}

christie@win10 ~/zulip
$ vboxmanage getextradata zulip_default_1462498139595_55484 enumerate
Key: VBoxInternal2/SharedFoldersEnableSymlinksCreate/srv_zulip, Value: 1
Key: supported, Value: false

If you see “command not found” when you try to run VBoxManage, you need to add the VirtualBox directory to your path. On Windows this is mostly likely C:\Program Files\Oracle\VirtualBox\.

If vboxmanage enumerate prints nothing, or shows a value of 0 for VBoxInternal2/SharedFoldersEnableSymlinksCreate/srv_zulip, then enable symbolic links by running this command in Terminal/Git BASH/Cygwin:

vboxmanage setextradata YOURVMNAME VBoxInternal2/SharedFoldersEnableSymlinksCreate/srv_zulip 1

The virtual machine needs to be shut down when you run this command.

Hyper-V error messages

If you get an error message on Windows about lack of Windows Home support for Hyper-V when running vagrant up, the problem is that Windows is incorrectly attempting to use Hyper-V rather than Virtualbox as the virtualization provider. You can fix this by explicitly passing the virtualbox provider to vagrant up:

christie@win10 ~/zulip
$ vagrant up --provide=virtualbox

Connection timeout on vagrant up

If you see the following error after running vagrant up:

default: SSH address: 127.0.0.1:2222
default: SSH username: vagrant
default: SSH auth method: private key
default: Error: Connection timeout. Retrying...
default: Error: Connection timeout. Retrying...
default: Error: Connection timeout. Retrying...

A likely cause is that hardware virtualization is not enabled for your computer. This must be done via your computer’s BIOS settings. Look for a setting called VT-x (Intel) or (AMD-V).

If this is already enabled in your BIOS, double-check that you are running a 64-bit operating system.

For further information about troubleshooting vagrant timeout errors see this post.

Vagrant was unable to communicate with the guest machine

If you see the following error when you run vagrant up:

Timed out while waiting for the machine to boot. This means that
Vagrant was unable to communicate with the guest machine within
the configured ("config.vm.boot_timeout" value) time period.

If you look above, you should be able to see the error(s) that
Vagrant had when attempting to connect to the machine. These errors
are usually good hints as to what may be wrong.

If you're using a custom box, make sure that networking is properly
working and you're able to connect to the machine. It is a common
problem that networking isn't setup properly in these boxes.
Verify that authentication configurations are also setup properly,
as well.

If the box appears to be booting properly, you may want to increase
the timeout ("config.vm.boot_timeout") value.

This has a range of possible causes, that usually amount to a bug in Virtualbox or Vagrant. If you see this error, you usually can fix it by rebooting the guest via vagrant halt; vagrant up.

Vagrant up fails with subprocess.CalledProcessError

The vagrant up command basically does the following:

  • Downloads an Ubuntu image and starts it using a Vagrant provider.

  • Uses vagrant ssh to connect to that Ubuntu guest, and then runs tools/provision, which has a lot of subcommands that are executed via Python’s subprocess module. These errors mean that one of those subcommands failed.

To debug such errors, you can log in to the Vagrant guest machine by running vagrant ssh, which should present you with a standard shell prompt. You can debug interactively by using e.g. cd zulip && ./tools/provision, and then running the individual subcommands that failed. Once you’ve resolved the problem, you can rerun tools/provision to proceed; the provisioning system is designed to recover well from failures.

The Zulip provisioning system is generally highly reliable; the most common cause of issues here is a poor network connection (or one where you need a proxy to access the Internet and haven’t configured the development environment to use it.

Once you’ve provisioned successfully, you’ll get output like this:

Zulip development environment setup succeeded!
(zulip-py3-venv) vagrant@vagrant-base-trusty-amd64:~/zulip$

If the (zulip-py3-venv) part is missing, this is because your installation failed the first time before the Zulip virtualenv was created. You can fix this by just closing the shell and running vagrant ssh again, or using source /srv/zulip-py3-venv/bin/activate.

Finally, if you encounter any issues that weren’t caused by your Internet connection, please report them! We try hard to keep Zulip development environment provisioning free of bugs.

pip install fails during vagrant up on Linux

Likely causes are:

  1. Networking issues

  2. Insufficient RAM. Check whether you’ve allotted at least two gigabytes of RAM, which is the minimum Zulip requires. If not, go to your VM settings and increase the RAM, then restart the VM.

yarn install warnings

$ yarn install
yarn install v0.24.5
[1/4] Resolving packages...
[2/4] Fetching packages...
warning fsevents@1.1.1: The platform "linux" is incompatible with this module.
info "fsevents@1.1.1" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
[4/4] Building fresh packages...
Done in 23.50s.

These are warnings produced by spammy third party JavaScript packages. It is okay to proceed and start the Zulip server.

VBoxManage errors related to VT-x or WHvSetupPartition

There was an error while executing `VBoxManage`, a CLI used by Vagrant
for controlling VirtualBox. The command and stderr is shown below.

Command: ["startvm", "8924a681-b4e4-4b7a-96f2-4cb11619f123", "--type", "headless"]

Stderr: VBoxManage.exe: error: (VERR_NEM_MISSING_KERNEL_API).
VBoxManage.exe: error: VT-x is not available (VERR_VMX_NO_VMX)
VBoxManage.exe: error: Details: code E_FAIL (0x80004005), component ConsoleWrap, interface IConsole

or

Stderr: VBoxManage.exe: error: Call to WHvSetupPartition failed: ERROR_SUCCESS (Last=0xc000000d/87) (VERR_NEM_VM_CREATE_FAILED)
VBoxManage.exe: error: Details: code E_FAIL (0x80004005), component ConsoleWrap, interface IConsole

First, ensure that hardware virtualization support (VT-x or AMD-V) is enabled in your BIOS.

If the error persists, you may have run into an incompatibility between VirtualBox and Hyper-V on Windows. To disable Hyper-V, open command prompt as administrator, run bcdedit /set hypervisorlaunchtype off, and reboot. If you need to enable it later, run bcdedit /deletevalue hypervisorlaunchtype, and reboot.

OSError: [Errno 26] Text file busy

default: Traceback (most recent call last):
…
default:   File "/srv/zulip-py3-venv/lib/python3.6/shutil.py", line 426, in _rmtree_safe_fd
default:     os.rmdir(name, dir_fd=topfd)
default: OSError: [Errno 26] Text file busy: 'baremetrics'

This error is caused by a bug in recent versions of the VirtualBox Guest Additions for Linux on Windows hosts. You can check the running version of VirtualBox Guest Additions with this command:

vagrant ssh -- 'sudo modinfo -F version vboxsf'

The bug has not been fixed upstream as of this writing, but you may be able to work around it by downgrading VirtualBox Guest Additions to 5.2.44. To do this, create a ~/.zulip-vagrant-config file and add this line:

VBOXADD_VERSION 5.2.44

Then run these commands (yes, reload is needed twice):

vagrant plugin install vagrant-vbguest
vagrant reload
vagrant reload --provision

Specifying an Ubuntu mirror

Bringing up a development environment for the first time involves downloading many packages from the Ubuntu archive. The Ubuntu cloud images use the global mirror http://archive.ubuntu.com/ubuntu/ by default, but you may find that you can speed up the download by using a local mirror closer to your location. To do this, create ~/.zulip-vagrant-config and add a line like this, replacing the URL as appropriate:

UBUNTU_MIRROR http://us.archive.ubuntu.com/ubuntu/

Specifying a proxy

If you need to use a proxy server to access the Internet, you will need to specify the proxy settings before running Vagrant up. First, install the Vagrant plugin vagrant-proxyconf:

vagrant plugin install vagrant-proxyconf

Then create ~/.zulip-vagrant-config and add the following lines to it (with the appropriate values in it for your proxy):

HTTP_PROXY http://proxy_host:port
HTTPS_PROXY http://proxy_host:port
NO_PROXY localhost,127.0.0.1,.example.com,.zulipdev.com

For proxies that require authentication, the config will be a bit more complex, e.g.:

HTTP_PROXY http://userName:userPassword@192.168.1.1:8080
HTTPS_PROXY http://userName:userPassword@192.168.1.1:8080
NO_PROXY localhost,127.0.0.1,.example.com,.zulipdev.com

You’ll want to double-check your work for mistakes (a common one is using https:// when your proxy expects http://). Invalid proxy configuration can cause confusing/weird exceptions; if you’re using a proxy and get an error, the first thing you should investigate is whether you entered your proxy configuration correctly.

Now run vagrant up in your terminal to install the development server. If you ran vagrant up before and failed, you’ll need to run vagrant destroy first to clean up the failed installation.

If you no longer want to use proxy with Vagrant, you can remove the HTTP_PROXY and HTTPS_PROXY lines in ~/.zulip-vagrant-config and then do a vagrant reload.

Using a different port for Vagrant

You can also change the port on the host machine that Vagrant uses by adding to your ~/.zulip-vagrant-config file. E.g. if you set:

HOST_PORT 9971

(and vagrant reload to apply the new configuration), then you would visit http://localhost:9971/ to connect to your development server.

If you’d like to be able to connect to your development environment from other machines than the VM host, you can manually set the host IP address in the ‘~/.zulip-vagrant-config’ file as well. For example, if you set:

HOST_IP_ADDR 0.0.0.0

(and restart the Vagrant guest with vagrant reload), your host IP would be 0.0.0.0, a special value for the IP address that means any IP address can connect to your development server.

Customizing CPU and RAM allocation

When running Vagrant using a VM-based provider such as VirtualBox or VMware Fusion, CPU and RAM resources must be explicitly allocated to the guest system (with Docker and other container-based Vagrant providers, explicit allocation is unnecessary and the settings described here are ignored).

Our default Vagrant settings allocate 2 cpus with 2GiB of memory for the guest, which is sufficient to run everything in the development environment. If your host system has more CPUs, or you have enough RAM that you’d like to allocate more than 2GiB to the guest, you can improve performance of the Zulip development environment by allocating more resources.

To do so, create a ~/.zulip-vagrant-config file containing the following lines:

GUEST_CPUS <number of cpus>
GUEST_MEMORY_MB <system memory (in MB)>

For example:

GUEST_CPUS 4
GUEST_MEMORY_MB 8192

would result in an allocation of 4 cpus and 8 GiB of memory to the guest VM.

After changing the configuration, run vagrant reload to reboot the guest VM with your new configuration.

If at any time you wish to revert back to the default settings, simply remove the GUEST_CPUS and GUEST_MEMORY_MB lines from ~/.zulip-vagrant-config.

Previous Next

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

Built with Sphinx using a theme provided by Read the Docs.
Read the Docs v: stable
Versions
latest
stable
6.1
6.0
5.7
5.6
5.5
5.4
5.3
5.2
5.1
5.0
4.11
4.10
4.9
4.8
4.7
4.6
4.5
4.4
4.3
4.2
4.1
4.0
3.4
3.3
3.2
3.1
3.0
Downloads
html
On Read the Docs
Project Home
Builds