How to Install Zulip Chat Server on Debian 11

Zulip is an open-source chat server, similar to Microsoft Teams, Rocket Chat or Slack. It is written in Python and uses Django, PostgreSQL, and JavaScript. It integrates with over 90 third-party plugins, including Github, Jira, Stripe, Zendesk, Sentry, etc. You can expand the integrations by connecting them with Zapier and IFTTT. It comes with features like private messaging, group chats, threaded conversations, custom channels, video calls, drag-and-drop file uploads, custom emojis, Giphy integration, Image and Tweets preview and many more. Zulip comes with desktop and mobile apps for every platform, making it platform agnostic.

In this tutorial, you will learn how to install and configure Zulip Chat on a Debian 11 based server.

Prerequisites

  • A server running Debian 11.

  • At least 2GB RAM if you expect less than 100 users. For 100+ users, get a 4GB RAM and 2 CPU server.

  • A non-root user with sudo privileges.

  • A domain name configured to point to the server, zulip.example.com.

  • Everything is updated.

    $ sudo apt update && sudo apt upgrade
    
  • Few packages that your system needs.

    $ sudo apt install wget curl nano ufw software-properties-common apt-transport-https gnupg2 ca-certificates debian-archive-keyring -y
    

    Some of these packages may already be installed on your system.

Step 1 - Configure Firewall

The first step is to configure the firewall. Debian comes with ufw (Uncomplicated Firewall).

Check if the firewall is running.

$ sudo ufw status

You should get the following output.

Status: inactive

Allow SSH port so that the firewall doesn't break the current connection on enabling it.

$ sudo ufw allow OpenSSH

Allow HTTP and HTTPS ports as well.

$ sudo ufw allow 80/tcp
$ sudo ufw allow 443/tcp

Enable the Firewall

$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup

Check the status of the firewall again.

$ sudo ufw status

You should see a similar output.

Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
80/tcp                     ALLOW       Anywhere
443/tcp                    ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
80/tcp (v6)                ALLOW       Anywhere (v6)
443/tcp (v6)               ALLOW       Anywhere (v6)

Step 2 - Install Zulip

Zulip ships with an installer script that does the following:

  1. Creates a user zulip to run the Zulip server.
  2. Creates a home directory using the zulip user which houses all the public code under the directory /home/zulip/deployments.
  3. Installs all the dependencies that Zulip needs.
  4. Installs PostgreSQL database, Nginx web server, RabbitMQ, Redis Cache, and Memcached.
  5. Initializes Zulip's database.

Create a temporary directory using the mktemp command to download the Zulip's installer and switch to it.

$ cd $(mktemp -d)

Download the latest version of Zulip.

$ wget https://download.zulip.com/server/zulip-server-latest.tar.gz

Extract all the files.

$ tar -xf zulip-server-latest.tar.gz

Run the installer script.

$ sudo ./zulip-server-*/scripts/setup/install --certbot \
    --email=YOUR_EMAIL --hostname=YOUR_HOSTNAME

The --certbot flag makes the installer download Certbot and install SSL certificates automatically. Replace YOUR_EMAIL with your email id and YOUR_HOSTNAME with the domain name for Zulip (zulip.example.com).

Step 3 - Accessing Zulip Interface

Once the installer script is finished, you will be given a unique URL. Copy this URL.

.......
zulip-workers:zulip_deliver_scheduled_messages: started
+ set +x
+ su zulip -c '/home/zulip/deployments/current/manage.py generate_realm_creation_link'
Please visit the following secure single-use link to register your

new Zulip organization:


    https://zulip.example.com/new/il5dsewnhugjarbnlxf5nc46

Visit https://zulip.example.com/new/il5dsewnhugjarbnlxf5nc46 in your browser, and the following screen will appear.

Zulip New Organization Page

Enter your email id to start creating your organization. You will be asked to set up an account on the next screen.

Zulip Account Creation

Enter your organization's name and your name and choose a password for logging in and click the Sign up button to proceed.

Once finished, the Zulip dashboard will open, and you can start using it.

Zulip Dashboard

Step 4 - Configuring Outgoing Email

Zulip server needs to send emails on a regular basis. For this, you should set up outgoing mail for it. For our example, we will be using Amazon's SES service. All the mails are sent from the email id you used to create the organization in step 3.

Zulip stores all of its settings in the /etc/zulip/settings.py file. Open it for editing.

$ sudo nano /etc/zulip/settings.py

Uncomment the following variables by removing # in front of them and entering the corresponding values.

## EMAIL_HOST and EMAIL_HOST_USER are generally required.
EMAIL_HOST = 'email-smtp.us-west-2.amazonaws.com'
EMAIL_HOST_USER = 'yoursmpt_username'

## Passwords and secrets are not stored in this file.  The password
## for user EMAIL_HOST_USER goes in `/etc/zulip/zulip-secrets.conf`.
## In that file, set `email_password`.  For example:
# email_password = abcd1234

## EMAIL_USE_TLS and EMAIL_PORT are required for most SMTP providers.
EMAIL_USE_TLS = True
EMAIL_PORT = 587

Fill in the following additional variables. The first one removes any random token to the no-reply email address, and the second one configures the no-reply email sender for your mails.

ADD_TOKENS_TO_NOREPLY_ADDRESS = False
# TOKENIZED_NOREPLY_EMAIL_ADDRESS = "noreply-{token}@example.com"
## NOREPLY_EMAIL_ADDRESS is the sender for noreply emails that don't
## contain confirmation links (where the security problem fixed by
## ADD_TOKENS_TO_NOREPLY_ADDRESS does not exist), as well as for
## confirmation emails when ADD_TOKENS_TO_NOREPLY_ADDRESS=False.
NOREPLY_EMAIL_ADDRESS = '[email protected]'

Once finished, save the file by pressing Ctrl + X and entering Y when prompted.

Zulip saves the Email password in a different file. Open the file /etc/zulip/zulip-secrets.conf for editing.

$ sudo nano /etc/zulip/zulip-secrets.conf

Paste the following line at the end of the file.

email_password = yoursmtp_password

Save the file by pressing Ctrl + X and entering Y when prompted.

To test your outgoing email configuration, you can send a test mail using the following command.

$ sudo -u zulip /home/zulip/deployments/current/manage.py send_test_email [email protected]
If you run into any trouble, read:

  https://zulip.readthedocs.io/en/latest/production/email.html#troubleshooting

The most common error is not setting `ADD_TOKENS_TO_NOREPLY_ADDRESS=False` when
using an email provider that doesn't support that feature.

Sending 2 test emails from:
  * [email protected]
  * [email protected]

Successfully sent 2 emails to [email protected]

Restart the server.

$ sudo -u zulip /home/zulip/deployments/current/scripts/restart-server

Notice that you can start or stop the Zulip server only as zulip user.

Step 5 - Zulip Server Commands

To stop the Zulip server, use the following command.

$ sudo -u zulip /home/zulip/deployments/current/scripts/stop-server

To start the server again, use the following command.

$ sudo -u zulip /home/zulip/deployments/current/scripts/start-server

Restart the server in a similar manner.

$ sudo -u zulip /home/zulip/deployments/current/scripts/restart-server

There are a lot of management tasks you can achieve using the manage.py script shipped with Zulip.

You can run the script using the following command. We will use the help sub-command to list all the possible operations one can perform.

$ sudo -u zulip /home/zulip/deployments/current/manage.py help
Type 'manage.py help <subcommand>' for help on a specific subcommand.

Available subcommands:

[analytics]
    check_analytics_state
    clear_analytics_tables
    clear_single_stat
    populate_analytics_db
    stream_stats
    update_analytics_counts

[auth]
    changepassword
    createsuperuser

[contenttypes]
    remove_stale_contenttypes

[django]
    check
    createcachetable
    dbshell
    diffsettings
    dumpdata
    flush
    inspectdb
    loaddata
    makemigrations
    migrate
    sendtestemail
    shell
    showmigrations
    sqlflush
    sqlmigrate
    sqlsequencereset
    squashmigrations
    startapp
    startproject
    test
    testserver

[otp_static]
    addstatictoken

[sessions]
    clearsessions

[social_django]
    clearsocial

[staticfiles]
    collectstatic
    findstatic
    runserver

[two_factor]
    two_factor_disable
    two_factor_status

[zerver]
    add_users_to_streams
    archive_messages
    audit_fts_indexes
    backup
    bulk_change_user_name
    change_password
    change_realm_subdomain
    change_user_email
    change_user_role
    check_redis
    checkconfig
    compilemessages
    convert_gitter_data
    convert_mattermost_data
    convert_slack_data
    create_default_stream_groups
    create_large_indexes
    create_realm_internal_bots
    create_stream
    create_user
    deactivate_realm
    deactivate_user
    delete_old_unclaimed_attachments
    delete_realm
    delete_user
    deliver_scheduled_emails
    deliver_scheduled_messages
    dump_messages
    edit_linkifiers
    email_mirror
    enqueue_digest_emails
    enqueue_file
    export
    export_single_user
    export_usermessage_batch
    fill_memcached_caches
    fix_unreads
    generate_invite_links
    generate_multiuse_invite_link
    generate_realm_creation_link
    get_migration_status
    import
    list_realms
    logout_all_users
    makemessages
    merge_streams
    print_email_delivery_backlog
    process_queue
    purge_queue
    query_ldap
    rate_limit
    reactivate_realm
    realm_domain
    register_server
    remove_users_from_stream
    rename_stream
    reset_authentication_attempt_count
    restore_messages
    runtornado
    scrub_realm
    send_custom_email
    send_password_reset_email
    send_realm_reactivation_email
    send_stats
    send_test_email
    send_to_email_mirror
    send_webhook_fixture_message
    set_message_flags
    show_admins
    soft_deactivate_users
    sync_ldap_user_data
    transfer_uploads_to_s3
    turn_off_digests

Step 6 - Upgrading Zulip

To upgrade Zulip, download the latest release from the server.

$ curl -fLO https://download.zulip.com/server/zulip-server-latest.tar.gz

Run the following command to perform the upgrade.

$ sudo /home/zulip/deployments/current/scripts/upgrade-zulip ~/zulip-server-latest.tar.gz

The script will perform the following functions.

  1. Run apt upgrade to upgrade the system.
  2. Install the new version of Zulip's dependencies.
  3. Shuts down the Zulip server.
  4. Runs the puppet apply command.
  5. Perform database migrations if required.
  6. Restarts Zulip server.

Step 7 - Backup and Restore Zulip

Backing and Restoring Zulip is easy, thanks to the in-built scripts that take care of everything.

To take a complete backup of Zulip, run the following command.

$ sudo -u zulip /home/zulip/deployments/current/manage.py backup --output=~/backups/zulip-backup.tar.gz

The above command will create a zulip-backup.tar.gz file in the ~/backups directory. This contains everything that you will need to transfer or restore Zulip.

To restore an existing backup, install Zulip by going through step 2.

Once finished, run the following command to finish restoring.

$ sudo -u zulip /home/zulip/deployments/current/scripts/setup/restore-backup ~/backups/zulip-backup.tar.gz

If you want to change the domain, you can change the variable EXTERNAL_HOST in the file /etc/zulip/settings.py and then restart the server using the following command.

$ sudo -u zulip /home/zulip/deployments/current/scripts/restart-server

Conclusion

This concludes our tutorial on installing and configuring the Zulip Chat server on a Debian 11 based system. You can follow Zulip's official documentation to explore in detail. If you have any questions, post them in the comments below.

Share this page:

0 Comment(s)