Workload · Running your team's Zulip

Zulip self-hosted: run your team's chat on your own server

To host Zulip yourself, you need a server that runs nothing else, with a current Ubuntu or Debian, at least 2 GB of memory, about 10 GB of free disk space, a web address and an email account Zulip can send from. You download one release file, run its installer, and open the link it prints to create your organization. Below, you'll find how big a server your team needs according to Zulip's own docs, every step of the install, and the chores that keep it healthy: email, backups, upgrades and notifications on phones.

The short version
  1. Under 100 people: 1 CPU and 2 GB of memory, plus swap
  2. 100 people or more: 2 CPUs and 4 GB
  3. Our advice: open the one-time organization link as soon as the install ends
  4. Set up email before the first invitation
  5. Open source under Apache 2.0

How big a server does your team need?

Less than you might think. Zulip's documentation says a team of fewer than 100 people gets by on 1 processor and 2 GB of memory, as long as you add 2 GB of swap (disk space the system borrows as overflow memory). Once you pass 100 people, it asks for 2 processors and 4 GB.

Your teamMemory the docs suggestNote
Fewer than 100 people2 GB with 2 GB of swap1 CPU is enough
100 people or more4 GBWith 2 CPUs
100+ active every day8 GBFrom the docs' advice for larger organizations
400+ active every day16 GB for Zulip, 16 GB for the databaseDatabase on its own machine is suggested, not required

For disk, the docs want at least 10 GB free for a server with dozens of people, which works out to a disk of about 25 GB once the operating system is on it, and they recommend an SSD because the database does most of the reading and writing. Zulip runs on Ubuntu 22.04, 24.04 and 26.04 and on Debian 12 and 13, on ordinary Intel/AMD processors or on 64-bit ARM. The docs suggest the newest of those you are comfortable with, to save yourself an upgrade later.

Why Zulip wants a machine of its own

Zulip's installer sets up its own web server, database and cache on the machine and expects nothing else to be there. The docs are blunt about it: if you put Zulip on a server that already hosts other things, they can't support you. So the simplest home for it is a dedicated server, one physical computer that runs your work and nobody else's.

  • You log in as root, so you can run the installer exactly as the docs describe.
  • If the first try goes wrong, reinstall the operating system yourself from the control panel and start clean, as often as you like.
  • Nobody meters your port, so a busy month of file sharing doesn't come with a bandwidth bill.
  • On rack servers and blades you get the console screen and power button yourself, a lifesaver if you shut yourself out with a firewall mistake.
  • A ready server is handed over within 30 minutes of approval, and you can cancel when any month ends.

One thing to know up front: you look after the software. We keep the hardware and the network running; Zulip, its updates and its backups are yours.

Installing Zulip in one sitting

Set aside an hour or so. You'll close the firewall first, then fetch Zulip and run its installer.

  1. Choose the address your team will type, for example zulip.example.com, and point it at your server's IP in your DNS settings. The free certificate only works once that name reaches your server from the internet.
  2. Turn on the firewall, which decides what traffic may reach the server. Zulip needs port 443 for its secure website. We also open port 80: Zulip only uses it to send visitors on to the secure address, but Let's Encrypt checks your domain through it when issuing the certificate. Everything else stays shut, which matters because the docs say port 4369, used by one of Zulip's background services, should be protected by a firewall. Your IPv6 address costs nothing, so the first line makes the firewall cover it, before any rule is added.
  3. If you picked Ubuntu, switch on its universe package collection. On Debian there is nothing to do here.
  4. Fetch the latest release file into an empty temporary folder and unpack it, exactly as below. There is nothing to pipe into a shell.
  5. Run the installer as root. Give it a real email address that you read, and your chosen address. The extra option asks it to fetch a free Let's Encrypt certificate and renew it automatically.
sudo sed -i 's/^IPV6=.*/IPV6=yes/' /etc/default/ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw --force enable
# Ubuntu only (skip on Debian):
sudo add-apt-repository universe
sudo apt update
cd $(mktemp -d)
curl -fLO https://download.zulip.com/server/zulip-server-latest.tar.gz
tar -xf zulip-server-latest.tar.gz
sudo ./zulip-server-*/scripts/setup/install --certbot \
  --email=you@example.com --hostname=zulip.example.com

The email you pass with --email is shown to your users as the contact for the server, on help pages and in automatic messages. The --hostname value becomes the server's public name. If you would like phone notifications from day one, add --push-notifications too; the installer will then ask you to accept the terms of that service. The install takes a few minutes. If it stops with an error, fix what it complains about and run the same command again: it is built to be repeated safely. Keep outgoing web traffic allowed afterwards, since Zulip reaches out to the internet to build link previews and to deliver phone notifications.

Claim your organization

At the very end, the installer prints a link. Open it in your browser and follow the prompts: you name your organization and create your own account inside it.

The docs call it a one-time-use link: whoever opens it first sets up the organization. Our advice, not a rule from the docs: your server is already on the internet at this point, so use the link straight away and don't paste it anywhere others can see it. Lost it? The generate_realm_creation_link command makes a new one; it is in the box in the next section.

Get email working before inviting anyone

Zulip can't welcome new people without email: it uses it to confirm their addresses, to send notifications and to reset forgotten passwords. The docs recommend a transactional email service built for sending from servers, rather than an ordinary mailbox, and several have free tiers.

  1. Open /etc/zulip/settings.py and fill in the outgoing email section: your provider's server name, your login name, and for most providers port 587 with TLS switched on.
  2. Put the password in a different file, /etc/zulip/zulip-secrets.conf, as a line reading email_password = followed by the password. Zulip deliberately keeps secrets out of settings.py. Use a text editor for this; typing the password into a command would leave it in your shell history.
  3. Send yourself a test with the first command below. Two messages should arrive.
  4. Restart Zulip so it picks up the change, with the second.
sudo su zulip -c '/home/zulip/deployments/current/manage.py send_test_email you@example.com'
sudo su zulip -c '/home/zulip/deployments/current/scripts/restart-server'
# only if you need a new organization link:
sudo su zulip -c '/home/zulip/deployments/current/manage.py generate_realm_creation_link'

Keep a copy of everything, somewhere else

Zulip has its own backup command, and the nightly job below runs it for you as the zulip user. Each run produces a single archive with your messages and database, your settings and secrets from /etc/zulip, and any uploaded files stored on the server. Left to its defaults, the command saves that archive in /tmp, which is why the job gives it a folder of its own. Logs and the SSL certificate are not in it. The docs say to back the certificate up separately; if you installed with --certbot, a new server whose DNS name points at it can simply be issued a fresh one.

Since the archive contains your passwords and keys, keep it somewhere only the zulip user can open, and copy it off the server regularly. Your data is yours to back up: we keep the hardware and the network running, not your software, so a nightly job like the one below is how you make sure a copy always exists. It also writes a short log each night so you can check it worked. Old archives pile up, so clear them out from time to time.

sudo install -d -m 700 -o zulip -g zulip /var/backups/zulip
echo '15 2 * * * zulip /home/zulip/deployments/current/manage.py backup --output=/var/backups/zulip/zulip-$(date +\%F).tar.gz > /var/backups/zulip/backup-$(date +\%F).log 2>&1' | sudo tee /etc/cron.d/zulip-backup

To restore, your new server has to match the old one on three counts: operating system, Zulip release and PostgreSQL release. Then you run the restore-backup script. Trying it once on a spare server is the best way to know your backups really work, and the docs recommend exactly that.

Staying up to date

Zulip's maintainers recommend always running the latest release. Upgrading is short: read the release notes for each version you are skipping, and download the new release file the same way as at install. Then, as root, change to /home/zulip/deployments/current and run ./scripts/upgrade-zulip followed by the path of the new file. Your team will see a brief interruption, under 30 seconds according to the docs, unless the release notes warn of a long database change. If something misbehaves, /var/log/zulip/upgrade.log tells you why, and a minor release can be rolled back.

Moving to a newer Ubuntu or Debian is a bigger job with extra steps for your exact versions, so follow that part of the upgrade guide closely and take a backup before you start.

Phone notifications, plans and the licence

Apple and Google don't let a server you host send alerts straight to the Zulip apps, so Zulip runs a forwarding service in between. With Zulip Server 12.0 or newer and an up-to-date app, the notifications are encrypted end to end, so the forwarding service can't read them. If you skipped --push-notifications at install, switch on the push setting in settings.py, restart, and register by running the register_server management command as the zulip user. Once registered, your server shares some basic details with Zulip, plus usage statistics unless you turn those off.

Here is the one plan rule the docs state: once an organization has more than 10 users, it either pays for a plan or qualifies for the free Community plan before it can use that notification service. Zulip itself is open source under the Apache 2.0 licence.

Questions people ask

Can I run Zulip alongside my website on the same server?
Zulip's docs advise against it, and they won't support that setup. The installer takes over the web server and database on the machine for its own use. Give Zulip a server of its own and keep the website elsewhere.
Which operating system should I choose?
Any of Debian 12 and 13 or Ubuntu 22.04, 24.04 and 26.04 is supported. The docs suggest picking the newest one you're comfortable with, so your next operating system upgrade is further away.
Do my team's phones need anything special?
They need the Zulip app, and your server needs to be registered with Zulip's notification service. Past 10 users, your organization also needs to be on a paid plan or, if eligible, the no-cost Community plan before those alerts flow.
We already use another chat tool. Can we bring our history over?
Yes, in many cases. Zulip can import from Mattermost, Rocket.Chat, Slack and more; its install guide links the steps. You stop after the install and follow those steps instead of opening the organization link. Still comparing? Read our pages on Mattermost, Rocket.Chat and running a Matrix server.
I lost the setup link. Now what?
Nothing is lost. Run the generate_realm_creation_link command from the email section on the server and you get a fresh one. Our advice is the same as for the first: use it straight away.

Ready to give your team its own Zulip?

Choose a server with the memory your team needs. Root access is yours, nobody meters the traffic, and you can stop at the end of any month.

Get a server for your team chat

Read next