2018-05-22 20:29:33 +02:00
|
|
|
# Deployment options
|
|
|
|
|
|
|
|
The default Zulip installation instructions will install a complete
|
|
|
|
Zulip server, with all of the services it needs, on a single machine.
|
|
|
|
|
|
|
|
For production deployment, however, it's common to want to do
|
2021-08-20 21:53:28 +02:00
|
|
|
something more complicated. This page documents the options for doing so.
|
2018-05-22 20:29:33 +02:00
|
|
|
|
2018-10-17 00:19:51 +02:00
|
|
|
## Installing Zulip from Git
|
|
|
|
|
|
|
|
To install a development version of Zulip from Git, just clone the Git
|
|
|
|
repository from GitHub:
|
|
|
|
|
2021-08-20 07:09:04 +02:00
|
|
|
```bash
|
2018-10-17 00:19:51 +02:00
|
|
|
# First, install Git if you don't have it installed already
|
|
|
|
sudo apt install git
|
|
|
|
git clone https://github.com/zulip/zulip.git zulip-server-git
|
|
|
|
```
|
|
|
|
|
|
|
|
and then
|
2019-04-06 02:58:44 +02:00
|
|
|
[continue the normal installation instructions](../production/install.html#step-2-install-zulip).
|
2019-10-14 21:40:48 +02:00
|
|
|
You can also [upgrade Zulip from Git](../production/upgrade-or-modify.html#upgrading-from-a-git-repository).
|
2018-10-17 00:19:51 +02:00
|
|
|
|
2021-09-01 00:15:31 +02:00
|
|
|
The most common use case for this is upgrading to `main` to get a
|
2020-07-08 21:14:51 +02:00
|
|
|
feature that hasn't made it into an official release yet (often
|
2021-08-20 21:53:28 +02:00
|
|
|
support for a new base OS release). See [upgrading to
|
2021-09-01 00:15:31 +02:00
|
|
|
main][upgrade-to-main] for notes on how `main` works and the
|
2020-07-08 21:14:51 +02:00
|
|
|
support story for it, and [upgrading to future
|
|
|
|
releases][upgrade-to-future-release] for notes on upgrading Zulip
|
|
|
|
afterwards.
|
|
|
|
|
|
|
|
In particular, we are always very glad to investigate problems with
|
2021-09-01 00:15:31 +02:00
|
|
|
installing Zulip from `main`; they are rare and help us ensure that
|
2020-07-08 21:14:51 +02:00
|
|
|
our next major release has a reliable install experience.
|
|
|
|
|
2021-09-01 00:15:31 +02:00
|
|
|
[upgrade-to-main]: ../production/upgrade-or-modify.html#upgrading-to-main
|
2020-07-08 21:14:51 +02:00
|
|
|
[upgrade-to-future-release]: ../production/upgrade-or-modify.html#upgrading-to-future-releases
|
|
|
|
|
2018-10-17 00:27:03 +02:00
|
|
|
## Zulip in Docker
|
|
|
|
|
|
|
|
Zulip has an officially supported, experimental
|
2021-08-20 21:53:28 +02:00
|
|
|
[docker image](https://github.com/zulip/docker-zulip). Please note
|
2019-09-30 19:37:56 +02:00
|
|
|
that Zulip's [normal installer](../production/install.md) has been
|
2018-10-17 00:27:03 +02:00
|
|
|
extremely reliable for years, whereas the Docker image is new and has
|
|
|
|
rough edges, so we recommend the normal installer unless you have a
|
|
|
|
specific reason to prefer Docker.
|
|
|
|
|
2021-05-10 07:02:14 +02:00
|
|
|
## Advanced installer options
|
2021-04-18 04:01:20 +02:00
|
|
|
|
|
|
|
The Zulip installer supports the following advanced installer options
|
|
|
|
as well as those mentioned in the
|
|
|
|
[install](../production/install.html#installer-options) documentation:
|
|
|
|
|
2021-08-20 21:45:39 +02:00
|
|
|
- `--postgresql-version`: Sets the version of PostgreSQL that will be
|
2021-11-06 03:10:55 +01:00
|
|
|
installed. We currently support PostgreSQL 10, 11, 12, 13, and 14.
|
2021-04-18 04:01:20 +02:00
|
|
|
|
2021-08-20 21:45:39 +02:00
|
|
|
- `--postgresql-database-name=exampledbname`: With this option, you
|
2021-03-28 05:41:50 +02:00
|
|
|
can customize the default database name. If you do not set this. The
|
|
|
|
default database name will be `zulip`. This setting can only be set
|
|
|
|
on the first install.
|
|
|
|
|
2021-08-20 21:45:39 +02:00
|
|
|
- `--postgresql-database-user=exampledbuser`: With this option, you
|
2021-03-28 05:41:50 +02:00
|
|
|
can customize the default database user. If you do not set this. The
|
|
|
|
default database user will be `zulip`. This setting can only be set
|
|
|
|
on the first install.
|
|
|
|
|
2021-08-20 21:45:39 +02:00
|
|
|
- `--postgresql-missing-dictionaries`: Set
|
2021-04-18 04:01:20 +02:00
|
|
|
`postgresql.missing_dictionaries` ([docs][doc-settings]) in the
|
|
|
|
Zulip settings, which omits some configuration needed for full-text
|
|
|
|
indexing. This should be used with [cloud managed databases like
|
|
|
|
RDS](#using-zulip-with-amazon-rds-as-the-database). This option
|
|
|
|
conflicts with `--no-overwrite-settings`.
|
|
|
|
|
2021-08-20 21:45:39 +02:00
|
|
|
- `--no-init-db`: This option instructs the installer to not do any
|
2021-04-18 04:01:20 +02:00
|
|
|
database initialization. This should be used when you already have a
|
|
|
|
Zulip database.
|
|
|
|
|
2021-08-20 21:45:39 +02:00
|
|
|
- `--no-overwrite-settings`: This option preserves existing
|
2021-04-18 04:01:20 +02:00
|
|
|
`/etc/zulip` configuration files.
|
|
|
|
|
2021-06-03 01:42:15 +02:00
|
|
|
## Installing on an existing server
|
|
|
|
|
|
|
|
Zulip's installation process assumes it is the only application
|
|
|
|
running on the server; though installing alongside other applications
|
|
|
|
is not recommended, we do have [some notes on the
|
|
|
|
process](../production/install-existing-server.md).
|
|
|
|
|
2018-05-22 20:29:33 +02:00
|
|
|
## Running Zulip's service dependencies on different machines
|
|
|
|
|
|
|
|
Zulip has full support for each top-level service living on its own
|
|
|
|
machine.
|
|
|
|
|
2020-10-26 22:27:53 +01:00
|
|
|
You can configure remote servers for PostgreSQL, RabbitMQ, Redis,
|
2018-05-22 20:29:33 +02:00
|
|
|
in `/etc/zulip/settings.py`; just search for the service name in that
|
|
|
|
file and you'll find inline documentation in comments for how to
|
|
|
|
configure it.
|
|
|
|
|
|
|
|
Since some of these services require some configuration on the node
|
2020-10-26 22:27:53 +01:00
|
|
|
itself (e.g. installing our PostgreSQL extensions), we have designed
|
2020-10-23 02:43:28 +02:00
|
|
|
the Puppet configuration that Zulip uses for installing and upgrading
|
2018-05-22 20:29:33 +02:00
|
|
|
configuration to be completely modular.
|
|
|
|
|
2020-10-20 02:49:54 +02:00
|
|
|
For example, to install a Zulip Redis server on a machine, you can run
|
|
|
|
the following after unpacking a Zulip production release tarball:
|
2018-05-22 20:29:33 +02:00
|
|
|
|
2021-08-20 07:09:04 +02:00
|
|
|
```bash
|
2020-10-20 02:49:54 +02:00
|
|
|
env PUPPET_CLASSES=zulip::profile::redis ./scripts/setup/install
|
2018-05-22 20:29:33 +02:00
|
|
|
```
|
|
|
|
|
2020-10-20 02:49:54 +02:00
|
|
|
All puppet modules under `zulip::profile` are allowed to be configured
|
2021-08-20 21:53:28 +02:00
|
|
|
stand-alone on a host. You can see most likely manifests you might
|
2020-10-20 02:49:54 +02:00
|
|
|
want to choose in the list of includes in [the main manifest for the
|
2020-10-20 03:49:23 +02:00
|
|
|
default all-in-one Zulip server][standalone.pp], though it's also
|
2020-10-20 02:49:54 +02:00
|
|
|
possible to subclass some of the lower-level manifests defined in that
|
2021-08-20 21:53:28 +02:00
|
|
|
directory if you want to customize. A good example of doing this is
|
2020-10-20 02:49:54 +02:00
|
|
|
in the [zulip_ops Puppet configuration][zulipchat-puppet] that we use
|
|
|
|
as part of managing chat.zulip.org and zulip.com.
|
2018-05-22 20:29:33 +02:00
|
|
|
|
|
|
|
### Using Zulip with Amazon RDS as the database
|
|
|
|
|
2019-12-12 10:50:04 +01:00
|
|
|
You can use DBaaS services like Amazon RDS for the Zulip database.
|
|
|
|
The experience is slightly degraded, in that most DBaaS provides don't
|
|
|
|
include useful dictionary files in their installations and don't
|
|
|
|
provide a way to provide them yourself, resulting in a degraded
|
|
|
|
[full-text search](../subsystems/full-text-search.md) experience
|
|
|
|
around issues dictionary files are relevant (e.g. stemming).
|
|
|
|
|
|
|
|
You also need to pass some extra options to the Zulip installer in
|
|
|
|
order to avoid it throwing an error when Zulip attempts to configure
|
|
|
|
the database's dictionary files for full-text search; the details are
|
|
|
|
below.
|
|
|
|
|
2020-08-11 01:47:54 +02:00
|
|
|
#### Step 1: Set up Zulip
|
2019-12-12 10:50:04 +01:00
|
|
|
|
|
|
|
Follow the [standard instructions](../production/install.md), with one
|
2021-08-20 21:53:28 +02:00
|
|
|
change. When running the installer, pass the `--no-init-db`
|
2019-12-12 10:50:04 +01:00
|
|
|
flag, e.g.:
|
|
|
|
|
2021-08-20 07:09:04 +02:00
|
|
|
```bash
|
2019-12-12 10:50:04 +01:00
|
|
|
sudo -s # If not already root
|
|
|
|
./zulip-server-*/scripts/setup/install --certbot \
|
|
|
|
--email=YOUR_EMAIL --hostname=YOUR_HOSTNAME \
|
2020-10-26 22:35:47 +01:00
|
|
|
--no-init-db --postgresql-missing-dictionaries
|
2019-12-12 10:50:04 +01:00
|
|
|
```
|
|
|
|
|
2020-10-26 22:27:53 +01:00
|
|
|
The script also installs and starts PostgreSQL on the server by
|
2019-12-12 10:50:04 +01:00
|
|
|
default. We don't need it, so run the following command to
|
2020-10-26 22:27:53 +01:00
|
|
|
stop and disable the local PostgreSQL server.
|
2019-12-12 10:50:04 +01:00
|
|
|
|
2021-08-20 07:09:04 +02:00
|
|
|
```bash
|
2019-12-12 10:50:04 +01:00
|
|
|
sudo service postgresql stop
|
|
|
|
sudo update-rc.d postgresql disable
|
|
|
|
```
|
|
|
|
|
|
|
|
This complication will be removed in a future version.
|
|
|
|
|
2020-10-26 22:27:53 +01:00
|
|
|
#### Step 2: Create the PostgreSQL database
|
2019-12-12 10:50:04 +01:00
|
|
|
|
2020-10-26 22:27:53 +01:00
|
|
|
Access an administrative `psql` shell on your PostgreSQL database, and
|
2019-12-12 10:50:04 +01:00
|
|
|
run the commands in `scripts/setup/create-db.sql` to:
|
|
|
|
|
2021-08-20 21:45:39 +02:00
|
|
|
- Create a database called `zulip`.
|
|
|
|
- Create a user called `zulip`.
|
|
|
|
- Now log in with the `zulip` user to create a schema called
|
2019-12-12 10:50:04 +01:00
|
|
|
`zulip` in the `zulip` database. You might have to grant `create`
|
|
|
|
privileges first for the `zulip` user to do this.
|
|
|
|
|
2020-10-26 22:27:53 +01:00
|
|
|
Depending on how authentication works for your PostgreSQL installation,
|
2019-12-12 10:50:04 +01:00
|
|
|
you may also need to set a password for the Zulip user, generate a
|
|
|
|
client certificate, or similar; consult the documentation for your
|
|
|
|
database provider for the available options.
|
|
|
|
|
2020-10-26 22:27:53 +01:00
|
|
|
#### Step 3: Configure Zulip to use the PostgreSQL database
|
2019-12-12 10:50:04 +01:00
|
|
|
|
|
|
|
In `/etc/zulip/settings.py` on your Zulip server, configure the
|
2020-10-26 22:27:53 +01:00
|
|
|
following settings with details for how to connect to your PostgreSQL
|
2021-08-20 21:53:28 +02:00
|
|
|
server. Your database provider should provide these details.
|
2019-12-12 10:50:04 +01:00
|
|
|
|
2021-08-20 21:45:39 +02:00
|
|
|
- `REMOTE_POSTGRES_HOST`: Name or IP address of the PostgreSQL server.
|
|
|
|
- `REMOTE_POSTGRES_PORT`: Port on the PostgreSQL server.
|
|
|
|
- `REMOTE_POSTGRES_SSLMODE`: SSL Mode used to connect to the server.
|
2019-12-12 10:50:04 +01:00
|
|
|
|
|
|
|
If you're using password authentication, you should specify the
|
|
|
|
password of the `zulip` user in /etc/zulip/zulip-secrets.conf as
|
|
|
|
follows:
|
|
|
|
|
2021-08-20 07:09:04 +02:00
|
|
|
```ini
|
2019-12-12 10:50:04 +01:00
|
|
|
postgres_password = abcd1234
|
|
|
|
```
|
|
|
|
|
2019-12-13 08:16:55 +01:00
|
|
|
Now complete the installation by running the following commands.
|
2019-12-12 10:50:04 +01:00
|
|
|
|
2021-08-20 07:09:04 +02:00
|
|
|
```bash
|
2020-10-26 22:27:53 +01:00
|
|
|
# Ask Zulip installer to initialize the PostgreSQL database.
|
2019-12-13 08:16:55 +01:00
|
|
|
su zulip -c '/home/zulip/deployments/current/scripts/setup/initialize-database'
|
2019-12-12 10:50:04 +01:00
|
|
|
|
|
|
|
# And then generate a realm creation link:
|
|
|
|
su zulip -c '/home/zulip/deployments/current/manage.py generate_realm_creation_link'
|
|
|
|
```
|
2018-05-22 20:29:33 +02:00
|
|
|
|
2019-06-17 21:16:34 +02:00
|
|
|
## Using an alternate port
|
|
|
|
|
|
|
|
If you'd like your Zulip server to use an HTTPS port other than 443, you can
|
|
|
|
configure that as follows:
|
|
|
|
|
|
|
|
1. Edit `EXTERNAL_HOST` in `/etc/zulip/settings.py`, which controls how
|
|
|
|
the Zulip server reports its own URL, and restart the Zulip server
|
|
|
|
with `/home/zulip/deployments/current/scripts/restart-server`.
|
|
|
|
1. Add the following block to `/etc/zulip/zulip.conf`:
|
|
|
|
|
2021-08-20 22:54:08 +02:00
|
|
|
```ini
|
|
|
|
[application_server]
|
|
|
|
nginx_listen_port = 12345
|
|
|
|
```
|
2019-06-17 21:16:34 +02:00
|
|
|
|
|
|
|
1. As root, run
|
2021-08-20 22:54:08 +02:00
|
|
|
`/home/zulip/deployments/current/scripts/zulip-puppet-apply`. This
|
|
|
|
will convert Zulip's main `nginx` configuration file to use your new
|
|
|
|
port.
|
2019-06-17 21:16:34 +02:00
|
|
|
|
|
|
|
We also have documentation for a Zulip server [using HTTP][using-http] for use
|
|
|
|
behind reverse proxies.
|
|
|
|
|
|
|
|
[using-http]: ../production/deployment.html#configuring-zulip-to-allow-http
|
|
|
|
|
2021-11-17 22:17:56 +01:00
|
|
|
## Customizing the outgoing HTTP proxy
|
2020-10-15 11:43:44 +02:00
|
|
|
|
2021-11-17 22:17:56 +01:00
|
|
|
To protect against [SSRF][ssrf], Zulip 4.8 and above default to
|
|
|
|
routing all outgoing HTTP and HTTPS traffic through
|
|
|
|
[Smokescreen][smokescreen], an HTTP `CONNECT` proxy; this includes
|
|
|
|
outgoing webhooks, website previews, and mobile push notifications.
|
2020-10-15 11:43:44 +02:00
|
|
|
|
2021-11-17 22:17:56 +01:00
|
|
|
To use a custom outgoing proxy:
|
2021-05-13 20:03:57 +02:00
|
|
|
|
2020-10-15 11:43:44 +02:00
|
|
|
1. Add the following block to `/etc/zulip/zulip.conf`, substituting in
|
|
|
|
your proxy's hostname/IP and port:
|
|
|
|
|
2021-08-20 22:54:08 +02:00
|
|
|
```ini
|
|
|
|
[http_proxy]
|
|
|
|
host = 127.0.0.1
|
|
|
|
port = 4750
|
|
|
|
```
|
2020-10-15 11:43:44 +02:00
|
|
|
|
|
|
|
1. As root, run
|
2021-08-20 21:53:28 +02:00
|
|
|
`/home/zulip/deployments/current/scripts/zulip-puppet-apply`. This
|
2021-11-17 22:17:56 +01:00
|
|
|
will reconfigure and restart Zulip.
|
|
|
|
|
|
|
|
If you have a deployment with multiple frontend servers, or wish to
|
|
|
|
install Smokescreen on a separate host, you can apply the
|
|
|
|
`zulip::profile::smokescreen` Puppet class on that host, and follow
|
|
|
|
the above steps, setting the `[http_proxy]` block to point to that
|
|
|
|
host.
|
|
|
|
|
|
|
|
If you wish to disable the outgoing proxy entirely, follow the above
|
|
|
|
steps, configuring an empty `host` value.
|
|
|
|
|
|
|
|
Optionally, you can also configure the [Smokescreen ACL
|
|
|
|
list][smokescreen-acls]. By default, Smokescreen denies access to all
|
|
|
|
[non-public IP
|
|
|
|
addresses](https://en.wikipedia.org/wiki/Private_network), including
|
|
|
|
127.0.0.1, but allows traffic to all public Internet hosts.
|
2021-02-26 23:40:18 +01:00
|
|
|
|
2021-11-17 22:17:56 +01:00
|
|
|
In Zulip 4.7 and older, to enable SSRF protection via Smokescreen, you
|
|
|
|
will need to explicitly add the `zulip::profile::smokescreen` Puppet
|
|
|
|
class, and configure the `[http_proxy]` block as above.
|
2020-10-15 11:43:44 +02:00
|
|
|
|
|
|
|
[smokescreen]: https://github.com/stripe/smokescreen
|
2021-05-13 20:03:57 +02:00
|
|
|
[smokescreen-acls]: https://github.com/stripe/smokescreen#acls
|
2021-02-26 23:40:18 +01:00
|
|
|
[ssrf]: https://owasp.org/www-community/attacks/Server_Side_Request_Forgery
|
2020-10-15 11:43:44 +02:00
|
|
|
|
2018-05-22 20:29:33 +02:00
|
|
|
## Putting the Zulip application behind a reverse proxy
|
|
|
|
|
2018-08-02 17:35:45 +02:00
|
|
|
Zulip is designed to support being run behind a reverse proxy server.
|
2018-11-16 07:26:59 +01:00
|
|
|
This section contains notes on the configuration required with
|
|
|
|
variable reverse proxy implementations.
|
|
|
|
|
|
|
|
### Installer options
|
|
|
|
|
|
|
|
If your Zulip server will not be on the public Internet, we recommend,
|
|
|
|
installing with the `--self-signed-cert` option (rather than the
|
|
|
|
`--certbot` option), since CertBot requires the server to be on the
|
|
|
|
public Internet.
|
|
|
|
|
|
|
|
#### Configuring Zulip to allow HTTP
|
|
|
|
|
|
|
|
Depending on your environment, you may want the reverse proxy to talk
|
|
|
|
to the Zulip server over HTTP; this can be secure when the Zulip
|
|
|
|
server is not directly exposed to the public Internet.
|
|
|
|
|
|
|
|
After installing the Zulip server as
|
|
|
|
[described above](#installer-options), you can configure Zulip to talk
|
|
|
|
HTTP as follows:
|
|
|
|
|
|
|
|
1. Add the following block to `/etc/zulip/zulip.conf`:
|
|
|
|
|
2021-08-20 22:54:08 +02:00
|
|
|
```ini
|
|
|
|
[application_server]
|
|
|
|
http_only = true
|
|
|
|
```
|
2018-11-16 07:26:59 +01:00
|
|
|
|
|
|
|
1. As root, run
|
2021-08-20 22:54:08 +02:00
|
|
|
`/home/zulip/deployments/current/scripts/zulip-puppet-apply`. This
|
|
|
|
will convert Zulip's main `nginx` configuration file to allow HTTP
|
|
|
|
instead of HTTPS.
|
2018-11-16 07:26:59 +01:00
|
|
|
|
|
|
|
1. Finally, restart the Zulip server, using
|
2021-08-20 22:54:08 +02:00
|
|
|
`/home/zulip/deployments/current/scripts/restart-server`.
|
2018-11-16 07:26:59 +01:00
|
|
|
|
2021-11-18 02:31:09 +01:00
|
|
|
#### Configuring Zulip to trust proxies
|
|
|
|
|
|
|
|
Before placing Zulip behind a reverse proxy, it needs to be configured to trust
|
|
|
|
the client IP addresses that the proxy reports. This is important to have
|
|
|
|
accurate IP addresses in server logs, as well as in notification emails which
|
|
|
|
are sent to end users.
|
|
|
|
|
|
|
|
1. Determine the IP addresses of all reverse proxies you are setting up, as seen
|
|
|
|
from the Zulip host. Depending on your network setup, these may not be the
|
|
|
|
same as the public IP addresses of the reverse proxies.
|
|
|
|
|
|
|
|
1. Add the following block to `/etc/zulip/zulip.conf`.
|
|
|
|
|
|
|
|
```ini
|
|
|
|
[loadbalancer]
|
|
|
|
# Use the IP addresses you determined above, separated by commas.
|
|
|
|
ips = 192.168.0.100
|
|
|
|
```
|
|
|
|
|
|
|
|
1. Reconfigure Zulip with these settings. As root, run
|
|
|
|
`/home/zulip/deployments/current/scripts/zulip-puppet-apply`. This will
|
|
|
|
adjust Zulip's `nginx` configuration file to accept the `X-Forwarded-For`
|
|
|
|
header when it is sent from one of the reverse proxy IPs.
|
|
|
|
|
|
|
|
1. Finally, restart the Zulip server, using
|
|
|
|
`/home/zulip/deployments/current/scripts/restart-server`.
|
|
|
|
|
2018-11-16 07:26:59 +01:00
|
|
|
### nginx configuration
|
|
|
|
|
2020-08-11 01:47:54 +02:00
|
|
|
For `nginx` configuration, there's two things you need to set up:
|
2021-08-20 22:54:08 +02:00
|
|
|
|
2021-08-20 21:53:28 +02:00
|
|
|
- The root `nginx.conf` file. We recommend using
|
2020-04-26 19:51:39 +02:00
|
|
|
`/etc/nginx/nginx.conf` from your Zulip server for our recommended
|
2021-08-20 21:53:28 +02:00
|
|
|
settings. E.g. if you don't set `client_max_body_size`, it won't be
|
2020-04-26 19:51:39 +02:00
|
|
|
possible to upload large files to your Zulip server.
|
2021-08-20 21:45:39 +02:00
|
|
|
- The `nginx` site-specific configuration (in
|
2021-08-20 21:53:28 +02:00
|
|
|
`/etc/nginx/sites-available`) for the Zulip app. The following
|
2021-02-19 23:49:25 +01:00
|
|
|
example is a good starting point:
|
2018-05-23 11:31:01 +02:00
|
|
|
|
2021-08-20 07:09:04 +02:00
|
|
|
```nginx
|
2018-05-23 11:31:01 +02:00
|
|
|
server {
|
2020-10-14 01:53:28 +02:00
|
|
|
listen 443 ssl http2;
|
|
|
|
listen [::]:443 ssl http2;
|
2018-05-23 11:31:01 +02:00
|
|
|
server_name zulip.example.net;
|
|
|
|
|
|
|
|
ssl_certificate /path/to/fullchain-cert.pem;
|
|
|
|
ssl_certificate_key /path/to/private-key.pem;
|
|
|
|
|
|
|
|
location / {
|
|
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
|
|
proxy_set_header Host $http_host;
|
|
|
|
proxy_http_version 1.1;
|
|
|
|
proxy_buffering off;
|
|
|
|
proxy_read_timeout 20m;
|
|
|
|
proxy_pass https://zulip-upstream-host;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Don't forget to update `server_name`, `ssl_certificate`,
|
2020-04-26 19:51:39 +02:00
|
|
|
`ssl_certificate_key` and `proxy_pass` with the appropriate values for
|
|
|
|
your installation.
|
2018-05-22 20:29:33 +02:00
|
|
|
|
2021-11-18 02:31:09 +01:00
|
|
|
On the Zulip side, you will need to add the `nginx` server IP as a trusted
|
|
|
|
reverse proxy. Follow the instructions to [configure Zulip to trust
|
|
|
|
proxies](#configuring-zulip-to-trust-proxies).
|
|
|
|
|
2021-09-01 00:15:31 +02:00
|
|
|
[nginx-proxy-longpolling-config]: https://github.com/zulip/zulip/blob/main/puppet/zulip/files/nginx/zulip-include-common/proxy_longpolling
|
|
|
|
[standalone.pp]: https://github.com/zulip/zulip/blob/main/puppet/zulip/manifests/profile/standalone.pp
|
|
|
|
[zulipchat-puppet]: https://github.com/zulip/zulip/tree/main/puppet/zulip_ops/manifests
|
2018-05-22 20:29:33 +02:00
|
|
|
|
2020-06-14 04:18:07 +02:00
|
|
|
### Apache2 configuration
|
|
|
|
|
|
|
|
Below is a working example of a full Apache2 configuration. It assumes
|
|
|
|
that your Zulip sits at `http://localhost:5080`. You first need to
|
|
|
|
make the following changes in two configuration files.
|
|
|
|
|
|
|
|
1. Follow the instructions for [Configure Zulip to allow HTTP](#configuring-zulip-to-allow-http).
|
|
|
|
|
|
|
|
2. Add the following to `/etc/zulip/settings.py`:
|
|
|
|
|
2021-08-20 22:54:08 +02:00
|
|
|
```python
|
|
|
|
EXTERNAL_HOST = 'zulip.example.com'
|
|
|
|
ALLOWED_HOSTS = ['zulip.example.com', '127.0.0.1']
|
|
|
|
USE_X_FORWARDED_HOST = True
|
|
|
|
```
|
2020-06-14 04:18:07 +02:00
|
|
|
|
2020-08-01 01:09:00 +02:00
|
|
|
3. Restart your Zulip server with `/home/zulip/deployments/current/scripts/restart-server`.
|
2020-06-14 04:18:07 +02:00
|
|
|
|
2021-11-18 02:31:09 +01:00
|
|
|
4. Follow the instructions to [configure Zulip to trust
|
|
|
|
proxies](#configuring-zulip-to-trust-proxies). For this example, the reverse
|
|
|
|
proxy IP would be `127.0.0.1`.
|
|
|
|
|
|
|
|
5. Create an Apache2 virtual host configuration file, similar to the
|
2021-08-20 21:53:28 +02:00
|
|
|
following. Place it the appropriate path for your Apache2
|
2020-06-14 04:18:07 +02:00
|
|
|
installation and enable it (E.g. if you use Debian or Ubuntu, then
|
|
|
|
place it in `/etc/apache2/sites-available/zulip.example.com.conf`
|
2021-09-08 00:23:24 +02:00
|
|
|
and then run
|
|
|
|
`a2ensite zulip.example.com && systemctl reload apache2`):
|
2020-06-14 04:18:07 +02:00
|
|
|
|
2021-08-20 22:54:08 +02:00
|
|
|
```apache
|
|
|
|
<VirtualHost *:80>
|
|
|
|
ServerName zulip.example.com
|
|
|
|
RewriteEngine On
|
|
|
|
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
|
|
|
|
</VirtualHost>
|
|
|
|
|
|
|
|
<VirtualHost *:443>
|
|
|
|
ServerName zulip.example.com
|
|
|
|
|
|
|
|
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
|
|
|
|
RequestHeader set "X-Forwarded-SSL" expr=%{HTTPS}
|
|
|
|
|
|
|
|
RewriteEngine On
|
|
|
|
RewriteRule /(.*) http://localhost:5080/$1 [P,L]
|
|
|
|
|
|
|
|
<Location />
|
|
|
|
Require all granted
|
|
|
|
ProxyPass http://localhost:5080/ timeout=300
|
|
|
|
ProxyPassReverse http://localhost:5080/
|
|
|
|
ProxyPassReverseCookieDomain 127.0.0.1 zulip.example.com
|
|
|
|
</Location>
|
|
|
|
|
|
|
|
SSLEngine on
|
|
|
|
SSLProxyEngine on
|
|
|
|
SSLCertificateFile /etc/letsencrypt/live/zulip.example.com/fullchain.pem
|
|
|
|
SSLCertificateKeyFile /etc/letsencrypt/live/zulip.example.com/privkey.pem
|
|
|
|
SSLOpenSSLConfCmd DHParameters "/etc/nginx/dhparam.pem"
|
|
|
|
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
|
|
|
|
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
|
|
|
|
SSLHonorCipherOrder off
|
|
|
|
SSLSessionTickets off
|
|
|
|
Header set Strict-Transport-Security "max-age=31536000"
|
|
|
|
</VirtualHost>
|
|
|
|
```
|
2020-06-14 04:18:07 +02:00
|
|
|
|
2018-11-16 07:26:59 +01:00
|
|
|
### HAProxy configuration
|
|
|
|
|
|
|
|
If you want to use HAProxy with Zulip, this `backend` config is a good
|
|
|
|
place to start.
|
|
|
|
|
2021-08-20 07:09:04 +02:00
|
|
|
```text
|
2018-11-16 07:26:59 +01:00
|
|
|
backend zulip
|
|
|
|
mode http
|
|
|
|
balance leastconn
|
|
|
|
reqadd X-Forwarded-Proto:\ https
|
|
|
|
server zulip 10.10.10.10:80 check
|
|
|
|
```
|
|
|
|
|
|
|
|
Since this configuration uses the `http` mode, you will also need to
|
|
|
|
[configure Zulip to allow HTTP](#configuring-zulip-to-allow-http) as
|
2021-11-18 02:31:09 +01:00
|
|
|
described above. Additionally, you will need to [add the the HAProxy server IP
|
|
|
|
address as a trusted load balancer](#configuring-zulip-to-trust-proxies)
|
|
|
|
to have Zulip respect the addresses in `X-Forwarded-For` headers.
|
2018-11-29 00:53:54 +01:00
|
|
|
|
|
|
|
### Other proxies
|
|
|
|
|
|
|
|
If you're using another reverse proxy implementation, there are few
|
|
|
|
things you need to be careful about when configuring it:
|
|
|
|
|
|
|
|
1. Configure your reverse proxy (or proxies) to correctly maintain the
|
2021-08-20 22:54:08 +02:00
|
|
|
`X-Forwarded-For` HTTP header, which is supposed to contain the series
|
2021-11-18 02:31:09 +01:00
|
|
|
of IP addresses the request was forwarded through. Additionally,
|
|
|
|
[configure Zulip to respect the addresses sent by your reverse
|
|
|
|
proxies](#configuring-zulip-to-trust-proxies). You can verify
|
2021-08-20 22:54:08 +02:00
|
|
|
your work by looking at `/var/log/zulip/server.log` and checking it
|
|
|
|
has the actual IP addresses of clients, not the IP address of the
|
|
|
|
proxy server.
|
2018-11-29 00:53:54 +01:00
|
|
|
|
|
|
|
2. Ensure your proxy doesn't interfere with Zulip's use of
|
2021-08-20 22:54:08 +02:00
|
|
|
long-polling for real-time push from the server to your users'
|
|
|
|
browsers. This [nginx code snippet][nginx-proxy-longpolling-config]
|
|
|
|
does this.
|
2018-11-29 00:53:54 +01:00
|
|
|
|
|
|
|
The key configuration options are, for the `/json/events` and
|
|
|
|
`/api/1/events` endpoints:
|
|
|
|
|
2021-08-20 21:53:28 +02:00
|
|
|
- `proxy_read_timeout 1200;`. It's critical that this be
|
2018-11-29 00:53:54 +01:00
|
|
|
significantly above 60s, but the precise value isn't important.
|
2021-08-20 21:53:28 +02:00
|
|
|
- `proxy_buffering off`. If you don't do this, your `nginx` proxy may
|
2018-11-29 00:53:54 +01:00
|
|
|
return occasional 502 errors to clients using Zulip's events API.
|
|
|
|
|
|
|
|
3. The other tricky failure mode we've seen with `nginx` reverse
|
2021-08-20 22:54:08 +02:00
|
|
|
proxies is that they can load-balance between the IPv4 and IPv6
|
|
|
|
addresses for a given hostname. This can result in mysterious errors
|
|
|
|
that can be quite difficult to debug. Be sure to declare your
|
|
|
|
`upstreams` equivalent in a way that won't do load-balancing
|
|
|
|
unexpectedly (e.g. pointing to a DNS name that you haven't configured
|
|
|
|
with multiple IPs for your Zulip machine; sometimes this happens with
|
|
|
|
IPv6 configuration).
|
2020-10-20 01:53:08 +02:00
|
|
|
|
|
|
|
## System and deployment configuration
|
|
|
|
|
|
|
|
The file `/etc/zulip/zulip.conf` is used to configure properties of
|
|
|
|
the system and deployment; `/etc/zulip/settings.py` is used to
|
2021-08-20 21:53:28 +02:00
|
|
|
configure the application itself. The `zulip.conf` sections and
|
2020-10-20 01:53:08 +02:00
|
|
|
settings are described below.
|
|
|
|
|
|
|
|
### `[machine]`
|
|
|
|
|
|
|
|
#### `puppet_classes`
|
|
|
|
|
|
|
|
A comma-separated list of the Puppet classes to install on the server.
|
|
|
|
The most common is **`zulip::profile::standalone`**, used for a
|
|
|
|
stand-alone single-host deployment.
|
|
|
|
[Components](../overview/architecture-overview.html#components) of
|
|
|
|
that include:
|
2021-08-20 22:54:08 +02:00
|
|
|
|
|
|
|
- **`zulip::profile::app_frontend`**
|
|
|
|
- **`zulip::profile::memcached`**
|
|
|
|
- **`zulip::profile::postgresql`**
|
|
|
|
- **`zulip::profile::redis`**
|
|
|
|
- **`zulip::profile::rabbitmq`**
|
2020-10-20 01:53:08 +02:00
|
|
|
|
|
|
|
If you are using a [Apache as a single-sign-on
|
|
|
|
authenticator](../production/authentication-methods.html#apache-based-sso-with-remote-user),
|
|
|
|
you will need to add **`zulip::apache_sso`** to the list.
|
|
|
|
|
|
|
|
#### `pgroonga`
|
|
|
|
|
|
|
|
Set to the string `enabled` if enabling the [multi-language PGroonga
|
|
|
|
search
|
|
|
|
extension](../subsystems/full-text-search.html#multi-language-full-text-search).
|
|
|
|
|
|
|
|
### `[deployment]`
|
|
|
|
|
|
|
|
#### `deploy_options`
|
|
|
|
|
|
|
|
Options passed by `upgrade-zulip` and `upgrade-zulip-from-git` into
|
2021-08-20 21:53:28 +02:00
|
|
|
`upgrade-zulip-stage-2`. These might be any of:
|
2020-10-20 01:53:08 +02:00
|
|
|
|
2021-08-20 22:54:08 +02:00
|
|
|
- **`--skip-puppet`** skips doing Puppet/apt upgrades. The user will need
|
|
|
|
to run `zulip-puppet-apply` manually after the upgrade.
|
|
|
|
- **`--skip-migrations`** skips running database migrations. The
|
|
|
|
user will need to run `./manage.py migrate` manually after the upgrade.
|
|
|
|
- **`--skip-purge-old-deployments`** skips purging old deployments;
|
|
|
|
without it, only deployments with the last two weeks are kept.
|
2020-10-20 01:53:08 +02:00
|
|
|
|
|
|
|
Generally installations will not want to set any of these options; the
|
|
|
|
`--skip-*` options are primarily useful for reducing upgrade downtime
|
|
|
|
for servers that are upgraded frequently by core Zulip developers.
|
|
|
|
|
|
|
|
#### `git_repo_url`
|
|
|
|
|
|
|
|
Default repository URL used when [upgrading from a Git
|
|
|
|
repository](../production/upgrade-or-modify.html#upgrading-from-a-git-repository).
|
|
|
|
|
|
|
|
### `[application_server]`
|
|
|
|
|
|
|
|
#### `http_only`
|
|
|
|
|
|
|
|
If set to non-empty, [configures Zulip to allow HTTP
|
|
|
|
access][using-http]; use if Zulip is deployed behind a reverse proxy
|
|
|
|
that is handling SSL/TLS termination.
|
|
|
|
|
|
|
|
#### `nginx_listen_port`
|
|
|
|
|
|
|
|
Set to the port number if you [prefer to listen on a port other than
|
|
|
|
443](#using-an-alternate-port).
|
|
|
|
|
|
|
|
#### `no_serve_uploads`
|
|
|
|
|
2020-10-27 21:39:06 +01:00
|
|
|
To enable the [the S3 uploads backend][s3-uploads], one needs to both
|
|
|
|
configure `settings.py` and set this to 'true' to configure
|
|
|
|
`nginx`. Remove this field to return to the local uploads backend (any
|
|
|
|
non-empty value is currently equivalent to true).
|
|
|
|
|
|
|
|
[s3-uploads]: ../production/upload-backends.html#s3-backend-configuration
|
2020-10-20 01:53:08 +02:00
|
|
|
|
2021-04-20 00:11:07 +02:00
|
|
|
#### `queue_workers_multiprocess`
|
|
|
|
|
|
|
|
By default, Zulip automatically detects whether the system has enough
|
|
|
|
memory to run Zulip queue processors in the higher-throughput but more
|
|
|
|
multiprocess mode (or to save 1.5GiB of RAM with the multithreaded
|
|
|
|
mode). The calculation is based on whether the system has enough
|
|
|
|
memory (currently 3.5GiB) to run a single-server Zulip installation in
|
|
|
|
the multiprocess mode.
|
|
|
|
|
2021-08-20 21:53:28 +02:00
|
|
|
Set to `true` or `false` to override the automatic calculation. This
|
2021-04-20 00:11:07 +02:00
|
|
|
override is useful both Docker systems (where the above algorithm
|
|
|
|
might see the host's memory, not the container's) and/or when using
|
|
|
|
remote servers for postgres, memcached, redis, and RabbitMQ.
|
|
|
|
|
2020-10-20 01:53:08 +02:00
|
|
|
#### `uwsgi_buffer_size`
|
|
|
|
|
|
|
|
Override the default uwsgi buffer size of 8192.
|
|
|
|
|
|
|
|
#### `uwsgi_listen_backlog_limit`
|
|
|
|
|
|
|
|
Override the default uwsgi backlog of 128 connections.
|
|
|
|
|
|
|
|
#### `uwsgi_processes`
|
|
|
|
|
|
|
|
Override the default `uwsgi` (Django) process count of 6 on hosts with
|
|
|
|
more than 3.5GiB of RAM, 4 on hosts with less.
|
|
|
|
|
|
|
|
### `[certbot]`
|
|
|
|
|
|
|
|
#### `auto_renew`
|
|
|
|
|
|
|
|
If set to the string `yes`, [Certbot will attempt to automatically
|
2021-08-20 21:53:28 +02:00
|
|
|
renew its certificate](../production/ssl-certificates.html#certbot-recommended). Do
|
2020-10-20 01:53:08 +02:00
|
|
|
no set by hand; use `scripts/setup/setup-certbot` to configure this.
|
|
|
|
|
|
|
|
### `[postfix]`
|
|
|
|
|
|
|
|
#### `mailname`
|
|
|
|
|
|
|
|
The hostname that [Postfix should be configured to receive mail
|
|
|
|
at](../production/email-gateway.html#local-delivery-setup).
|
|
|
|
|
|
|
|
### `[postgresql]`
|
|
|
|
|
|
|
|
#### `effective_io_concurrency`
|
|
|
|
|
|
|
|
Override PostgreSQL's [`effective_io_concurrency`
|
|
|
|
setting](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-EFFECTIVE-IO-CONCURRENCY).
|
|
|
|
|
|
|
|
#### `listen_addresses`
|
|
|
|
|
|
|
|
Override PostgreSQL's [`listen_addresses`
|
|
|
|
setting](https://www.postgresql.org/docs/current/runtime-config-connection.html#GUC-LISTEN-ADDRESSES).
|
|
|
|
|
|
|
|
#### `random_page_cost`
|
|
|
|
|
|
|
|
Override PostgreSQL's [`random_page_cost`
|
|
|
|
setting](https://www.postgresql.org/docs/current/runtime-config-query.html#GUC-RANDOM-PAGE-COST)
|
|
|
|
|
|
|
|
#### `replication`
|
|
|
|
|
|
|
|
Set to non-empty to enable replication to enable [streaming
|
|
|
|
replication between PostgreSQL
|
2020-10-26 22:27:53 +01:00
|
|
|
servers](../production/export-and-import.html#postgresql-streaming-replication).
|
2020-10-20 01:53:08 +02:00
|
|
|
|
|
|
|
#### `ssl_ca_file`
|
|
|
|
|
|
|
|
Set to the path to the PEM-encoded certificate authority used to
|
|
|
|
authenticate client connections.
|
|
|
|
|
|
|
|
#### `ssl_cert_file`
|
|
|
|
|
|
|
|
Set to the path to the PEM-encoded public certificate used to secure
|
|
|
|
client connections.
|
|
|
|
|
|
|
|
#### `ssl_key_file`
|
|
|
|
|
|
|
|
Set to the path to the PEM-encoded private key used to secure client
|
|
|
|
connections.
|
|
|
|
|
|
|
|
#### `version`
|
|
|
|
|
2021-08-20 21:53:28 +02:00
|
|
|
The version of PostgreSQL that is in use. Do not set by hand; use the
|
2020-10-20 01:53:08 +02:00
|
|
|
[PostgreSQL upgrade tool](../production/upgrade-or-modify.html#upgrading-postgresql).
|
|
|
|
|
|
|
|
### `[rabbitmq]`
|
|
|
|
|
|
|
|
#### `nodename`
|
|
|
|
|
|
|
|
The name used to identify the local RabbitMQ server; do not modify.
|
|
|
|
|
|
|
|
### `[memcached]`
|
|
|
|
|
|
|
|
#### `memory`
|
|
|
|
|
|
|
|
Override the number of megabytes of memory that memcached should be
|
|
|
|
configured to consume; defaults to 1/8th of the total server memory.
|
|
|
|
|
|
|
|
### `[loadbalancer]`
|
|
|
|
|
|
|
|
#### `ips`
|
|
|
|
|
|
|
|
Comma-separated list of IP addresses or netmasks of external
|
|
|
|
load balancers whose `X-Forwarded-For` should be respected.
|
2020-10-15 11:43:44 +02:00
|
|
|
|
|
|
|
### `[http_proxy]`
|
|
|
|
|
|
|
|
#### `host`
|
|
|
|
|
|
|
|
The hostname or IP address of an [outgoing HTTP `CONNECT`
|
2021-11-17 22:17:56 +01:00
|
|
|
proxy](#customizing-the-outgoing-http-proxy). Defaults to `localhost`
|
|
|
|
if unspecified.
|
2020-10-15 11:43:44 +02:00
|
|
|
|
|
|
|
#### `port`
|
|
|
|
|
|
|
|
The TCP port of the HTTP `CONNECT` proxy on the host specified above.
|
2021-11-17 22:17:56 +01:00
|
|
|
Defaults to `4750` if unspecified.
|
2021-07-14 23:54:15 +02:00
|
|
|
|
|
|
|
#### `listen_address`
|
|
|
|
|
|
|
|
The IP address that Smokescreen should bind to and listen on.
|
|
|
|
Defaults to `127.0.0.1`.
|