2018-01-23 20:36:07 +01:00
|
|
|
```eval_rst
|
|
|
|
:orphan:
|
|
|
|
```
|
|
|
|
|
2017-08-25 03:56:20 +02:00
|
|
|
# Hosting multiple organizations
|
|
|
|
|
2017-10-20 18:53:33 +02:00
|
|
|
The vast majority of Zulip servers host just a single organization (or
|
|
|
|
"realm", as the Zulip code calls organizations). This article
|
|
|
|
documents what's involved in hosting multiple Zulip organizations on a
|
|
|
|
single server.
|
2017-08-25 03:56:20 +02:00
|
|
|
|
|
|
|
Throughout this article, we'll assume you're working on a zulip server
|
2017-10-20 18:53:33 +02:00
|
|
|
with hostname `zulip.example.com`. You may also find the more
|
2019-09-30 19:37:56 +02:00
|
|
|
[technically focused article on realms](../subsystems/realms.md) to be useful
|
2017-10-20 18:53:33 +02:00
|
|
|
reading.
|
2017-08-25 03:56:20 +02:00
|
|
|
|
|
|
|
## Subdomains
|
|
|
|
|
|
|
|
Zulip's approach for supporting multiple organizations on a single
|
|
|
|
Zulip server is for each organization to be hosted on its own
|
|
|
|
subdomain. E.g. you'd have `org1.zulip.example.com` and
|
|
|
|
`org2.zulip.example.com`.
|
|
|
|
|
|
|
|
Web security standards mean that one subdomain per organization is
|
2017-12-31 02:11:24 +01:00
|
|
|
required to support a user logging into multiple organizations on a
|
2017-08-25 03:56:20 +02:00
|
|
|
server at the same time.
|
|
|
|
|
|
|
|
When you want to create a new organization, you need to do a few
|
|
|
|
things:
|
|
|
|
|
|
|
|
* If you're using Zulip older than 1.7, you'll need to set
|
|
|
|
`REALMS_HAVE_SUBDOMAINS=True` in your `/etc/zulip/settings.py`
|
|
|
|
file. That setting is the default in 1.7 and later.
|
|
|
|
* Make sure you have SSL certificates for all of the subdomains you're
|
|
|
|
going to use. If you're using
|
2019-09-30 19:37:56 +02:00
|
|
|
[our LetsEncrypt instructions](ssl-certificates.md), it's easy to
|
2017-08-25 03:56:20 +02:00
|
|
|
just specify multiple subdomains in your certificate request.
|
|
|
|
* If necessary, modify your `nginx` configuration to use your new
|
|
|
|
certificates.
|
|
|
|
* Use `./manage.py generate_realm_creation_link` again to create your
|
|
|
|
new organization. Review
|
2019-09-30 19:37:56 +02:00
|
|
|
[the install instructions](install.md) if you need a
|
2017-08-25 03:56:20 +02:00
|
|
|
refresher on how this works.
|
2018-07-10 08:07:23 +02:00
|
|
|
* If you're planning on using GitHub auth or another social
|
|
|
|
authentication method, review
|
2019-12-11 02:33:53 +01:00
|
|
|
[the notes on `SOCIAL_AUTH_SUBDOMAIN` below](#authentication).
|
2017-08-25 03:56:20 +02:00
|
|
|
|
|
|
|
For servers hosting a large number of organizations, like
|
2020-06-08 23:04:39 +02:00
|
|
|
[zulip.com](https://zulip.com), one can set `ROOT_DOMAIN_LANDING_PAGE
|
|
|
|
= True` in `/etc/zulip/settings.py` so that the homepage for the
|
|
|
|
server is a copy of the Zulip homepage.
|
2017-08-25 03:56:20 +02:00
|
|
|
|
2018-11-13 21:53:12 +01:00
|
|
|
### SSL Certificates
|
|
|
|
|
|
|
|
You'll need to install an SSL certificate valid for all the
|
|
|
|
(sub)domains you're using your Zulip server with. You can get an SSL
|
|
|
|
certificate covering several domains for free by using
|
2019-04-06 02:58:44 +02:00
|
|
|
[our Certbot wrapper tool](../production/ssl-certificates.html#after-zulip-is-already-installed),
|
2018-11-13 21:53:12 +01:00
|
|
|
though if you're going to host a large number of organizations, you
|
|
|
|
may want to get a wildcard certificate. You can also get a wildcard
|
|
|
|
certificate for
|
|
|
|
[free using Certbot](https://community.letsencrypt.org/t/getting-wildcard-certificates-with-certbot/56285),
|
|
|
|
but because of the stricter security checks for acquiring a wildcard
|
|
|
|
cert, it isn't possible for a generic script like `setup-certbot` to
|
|
|
|
create it for you; you'll have to do some manual steps with your DNS
|
|
|
|
provider.
|
|
|
|
|
2018-05-16 16:02:13 +02:00
|
|
|
### Other hostnames
|
|
|
|
|
|
|
|
If you'd like to use hostnames that are not subdomains of each other,
|
|
|
|
you can set the `REALM_HOSTS` setting in `/etc/zulip/settings.py` to a
|
|
|
|
Python dictionary, like this:
|
|
|
|
|
|
|
|
```
|
|
|
|
REALM_HOSTS = {
|
|
|
|
'mysubdomain': 'hostname.example.com',
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
What this will do is map the hostname `hostname.example.com` to the
|
|
|
|
realm whose `subdomain` in the Zulip database is `mysubdomain`.
|
|
|
|
|
|
|
|
In a future version of Zulip, we expect to move this configuration
|
|
|
|
into the database.
|
|
|
|
|
2017-08-25 03:56:20 +02:00
|
|
|
### The root domain
|
|
|
|
|
|
|
|
Most Zulip servers host a single Zulip organization on the root domain
|
2020-06-08 21:15:53 +02:00
|
|
|
(e.g. `zulip.example.com`). The way this is implemented internally
|
2017-08-25 03:56:20 +02:00
|
|
|
involves the organization having the empty string (`''`) as its
|
2018-05-31 21:17:16 +02:00
|
|
|
"subdomain".
|
|
|
|
|
|
|
|
You can mix having an organization on the root domain and some others
|
|
|
|
on subdomains (e.g. `subdivision.zulip.example.com`), but this only
|
|
|
|
works well if there are no users in common between the two
|
|
|
|
organizations, because the auth cookies for the root domain are
|
|
|
|
visible to the subdomain (so it's not possible for a single
|
|
|
|
browser/client to be logged into both). So we don't recommend that
|
|
|
|
configuration.
|
2017-10-20 18:53:33 +02:00
|
|
|
|
2019-12-11 01:10:24 +01:00
|
|
|
### Authentication
|
|
|
|
|
|
|
|
Many of Zulip's supported authentication methods (Google, GitHub,
|
|
|
|
SAML, etc.) can require providing the third-party authentication
|
|
|
|
provider with a whitelist of callback URLs to your Zulip server (or
|
|
|
|
even a single URL). For those vendors that support a whitelist, you
|
|
|
|
can provide the callback URLs for each of your Zulip organizations.
|
|
|
|
|
|
|
|
The cleaner solution is to register a special subdomain, e.g.
|
|
|
|
`auth.zulip.example.com` with the third-party provider, and then set
|
|
|
|
`SOCIAL_AUTH_SUBDOMAIN = 'auth'` in `/etc/zulip/settings.py`, so that
|
|
|
|
Zulip knows to use that subdomain for these authentication callbacks.
|
2018-07-10 08:07:23 +02:00
|
|
|
|
2017-10-20 18:53:33 +02:00
|
|
|
### The system bot realm
|
|
|
|
|
|
|
|
This is very much an implementation detail, but worth documenting to
|
|
|
|
avoid confusion as to why there's an extra realm when inspecting the
|
|
|
|
Zulip database.
|
|
|
|
|
|
|
|
Every Zulip server comes with 1 realm that isn't created by users: the
|
2019-07-24 08:37:13 +02:00
|
|
|
`zulipinternal` realm. By default, this realm only contains the Zulip "system
|
2017-10-20 18:53:33 +02:00
|
|
|
bots". You can get a list of these on your system via
|
|
|
|
`./scripts/get-django-setting INTERNAL_BOTS`, but this is where bots
|
|
|
|
like "Notification Bot", "Welcome Bot", etc. exist. In the future,
|
|
|
|
we're considering moving these bots to exist in every realm, so that
|
|
|
|
we wouldn't need the system realm anymore.
|
2018-12-12 21:08:25 +01:00
|
|
|
|
|
|
|
### Migrating / Troubleshooting
|
|
|
|
|
|
|
|
If you're migrating from a configuration using the root domain to one
|
|
|
|
with realms hosted on subdomains, be sure to clear cookies in any
|
|
|
|
browsers that were logged in on the root domain; otherwise, those
|
|
|
|
browsers will experience weird/confusing redirects.
|