2019-09-25 01:58:20 +02:00
|
|
|
|
# Backups, export and import
|
|
|
|
|
|
|
|
|
|
Zulip has high quality export and import tools that can be used to
|
|
|
|
|
move data from one Zulip server to another, do backups, compliance
|
|
|
|
|
work, or migrate from your own servers to the hosted Zulip Cloud
|
|
|
|
|
service (or back):
|
|
|
|
|
|
2021-08-20 21:45:39 +02:00
|
|
|
|
- The [Backup](#backups) tool is designed for exact restoration of a
|
2019-09-25 01:58:20 +02:00
|
|
|
|
Zulip server's state, for disaster recovery, testing with production
|
2024-02-27 22:51:44 +01:00
|
|
|
|
data, and hardware migrations.
|
|
|
|
|
|
|
|
|
|
We highly recommend this tool in situations where it is applicable,
|
|
|
|
|
because it is fast, robust, and minimizes disruption for your
|
|
|
|
|
users. This tool has a few limitations:
|
2019-09-25 01:58:20 +02:00
|
|
|
|
|
2021-08-20 21:45:39 +02:00
|
|
|
|
- Backups must be restored on a server running the same Zulip
|
2019-09-25 01:58:20 +02:00
|
|
|
|
version (most precisely, one where `manage.py showmigrations` has
|
2024-02-27 22:51:44 +01:00
|
|
|
|
identical output).
|
2021-08-20 21:45:39 +02:00
|
|
|
|
- Backups must be restored on a server running the same PostgreSQL
|
2023-02-24 15:46:28 +01:00
|
|
|
|
version. To install Zulip with the same version of PostgreSQL that
|
|
|
|
|
the backup was taken on, pass the desired version with [the
|
|
|
|
|
`--postgresql-version` argument][installer-options] when
|
2024-02-27 22:51:44 +01:00
|
|
|
|
installing. Note that PostgreSQL is easy to [upgrade
|
|
|
|
|
independently][postgres-upgrade] from the rest of your Zulip
|
|
|
|
|
installation.
|
2021-08-20 21:45:39 +02:00
|
|
|
|
- Backups aren't useful for migrating organizations between
|
2019-12-13 00:56:23 +01:00
|
|
|
|
self-hosting and Zulip Cloud (which may require renumbering all
|
|
|
|
|
the users/messages/etc.).
|
2019-09-25 01:58:20 +02:00
|
|
|
|
|
2024-02-27 22:51:44 +01:00
|
|
|
|
We also document [backup details](#backup-details) for users
|
|
|
|
|
managing backups manually.
|
2019-09-25 01:58:20 +02:00
|
|
|
|
|
2024-02-27 22:51:44 +01:00
|
|
|
|
- The [logical data export](#data-export) tool is designed for
|
2019-09-25 01:58:20 +02:00
|
|
|
|
migrating data between Zulip Cloud and other Zulip servers, as well
|
2024-02-27 22:51:44 +01:00
|
|
|
|
as various auditing purposes.
|
|
|
|
|
|
|
|
|
|
We recommend this tool in cases where the backup tool isn't
|
|
|
|
|
applicable, including situations where an easily machine-parsable
|
|
|
|
|
export format is desired. This tool has a few limitations and
|
|
|
|
|
caveats:
|
|
|
|
|
|
|
|
|
|
- Like the backup tool, logical data exports must be imported on a
|
|
|
|
|
Zulip server running the same Zulip version. However, logical data
|
|
|
|
|
exports can be imported on Zulip servers running a different
|
|
|
|
|
PostgreSQL version or hosting a different set of Zulip
|
|
|
|
|
organizations.
|
|
|
|
|
- Transferring an organization via the data export tool results in
|
|
|
|
|
significant user-facing disruption, such as logging all users out of
|
|
|
|
|
their accounts and requiring them to reset their passwords.
|
|
|
|
|
|
|
|
|
|
The logical export tool produces a `.tar.gz` archive with most of
|
|
|
|
|
the Zulip database data encoded in JSON files–a format shared by our
|
|
|
|
|
[data import](#import-into-a-new-zulip-server) tools for third-party
|
|
|
|
|
services like [Slack](https://zulip.com/help/import-from-slack).
|
2019-09-25 01:58:20 +02:00
|
|
|
|
|
2022-11-17 18:42:02 +01:00
|
|
|
|
- [Compliance exports](#compliance-exports) allow a server
|
|
|
|
|
administrator to export messages matching a search query.
|
|
|
|
|
|
2021-08-20 21:45:39 +02:00
|
|
|
|
- Zulip also has an [HTML archive
|
2019-11-15 12:35:54 +01:00
|
|
|
|
tool](https://github.com/zulip/zulip-archive), which is primarily
|
2019-09-25 01:58:20 +02:00
|
|
|
|
intended for public archives, but can also be useful to
|
|
|
|
|
inexpensively preserve public stream conversations when
|
|
|
|
|
decommissioning a Zulip organization.
|
|
|
|
|
|
2021-08-20 21:45:39 +02:00
|
|
|
|
- It's possible to set up [PostgreSQL streaming
|
2022-02-16 01:39:15 +01:00
|
|
|
|
replication](deployment.md#postgresql-warm-standby)
|
postgresql: Support replication on PostgreSQL >= 11, document.
PostgreSQL 11 and below used a configuration file names
`recovery.conf` to manage replicas and standbys; support for this was
removed in PostgreSQL 12[1], and the configuration parameters were
moved into the main `postgresql.conf`.
Add `zulip.conf` settings for the primary server hostname and
replication username, so that the complete `postgresql.conf`
configuration on PostgreSQL 14 can continue to be managed, even when
replication is enabled. For consistency, also begin writing out the
`recovery.conf` for PostgreSQL 11 and below.
In PostgreSQL 12 configuration and later, the `wal_level =
hot_standby` setting is removed, as `hot_standby` is equivalent to
`replica`, which is the default value[2]. Similarly, the
`hot_standby = on` setting is also the default[3].
Documentation is added for these features, and the commentary on the
"Export and Import" page referencing files under `puppet/zulip_ops/`
is removed, as those files no longer have any replication-specific
configuration.
[1]: https://www.postgresql.org/docs/current/recovery-config.html
[2]: https://www.postgresql.org/docs/12/runtime-config-wal.html#GUC-WAL-LEVEL
[3]: https://www.postgresql.org/docs/12/runtime-config-replication.html#GUC-HOT-STANDBY
2021-11-20 00:33:41 +01:00
|
|
|
|
and the [S3 file upload
|
2022-02-16 01:39:15 +01:00
|
|
|
|
backend](upload-backends.md#s3-backend-configuration)
|
2021-05-11 02:33:21 +02:00
|
|
|
|
as part of a high availability environment.
|
2018-05-25 21:09:02 +02:00
|
|
|
|
|
2023-02-24 15:46:28 +01:00
|
|
|
|
[installer-options]: deployment.md#advanced-installer-options
|
2024-02-27 22:51:44 +01:00
|
|
|
|
[postgres-upgrade]: upgrade.md#upgrading-postgresql
|
2023-02-24 15:46:28 +01:00
|
|
|
|
|
2019-09-25 01:58:20 +02:00
|
|
|
|
## Backups
|
2018-05-25 21:09:02 +02:00
|
|
|
|
|
2019-09-25 01:58:20 +02:00
|
|
|
|
The Zulip server has a built-in backup tool:
|
2018-05-25 21:09:02 +02:00
|
|
|
|
|
2021-08-20 07:09:04 +02:00
|
|
|
|
```bash
|
2019-09-25 01:58:20 +02:00
|
|
|
|
# As the zulip user
|
|
|
|
|
/home/zulip/deployments/current/manage.py backup
|
|
|
|
|
# Or as root
|
|
|
|
|
su zulip -c '/home/zulip/deployments/current/manage.py backup'
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The backup tool provides the following options:
|
2021-08-20 22:54:08 +02:00
|
|
|
|
|
2020-08-10 02:44:12 +02:00
|
|
|
|
- `--output=/tmp/backup.tar.gz`: Filename to write the backup tarball
|
2021-08-20 21:53:28 +02:00
|
|
|
|
to (default: write to a file in `/tmp`). On success, the
|
2020-08-10 02:44:12 +02:00
|
|
|
|
console output will show the path to the output tarball.
|
2021-08-20 21:53:28 +02:00
|
|
|
|
- `--skip-db`: Skip backup of the database. Useful if you're using a
|
2020-10-26 22:27:53 +01:00
|
|
|
|
remote PostgreSQL host with its own backup system and just need to
|
docs: Add missing space to compound verbs “log in”, “set up”, etc.
Noun: backup, checkout, cleanup, login, logout, setup, shutdown, signup,
timeout.
Verb: back up, check out, clean up, log in, log out, set up, shut
down, sign up, time out.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-04-25 23:05:38 +02:00
|
|
|
|
back up non-database state.
|
2019-09-25 01:58:20 +02:00
|
|
|
|
- `--skip-uploads`: If `LOCAL_UPLOADS_DIR` is set, user-uploaded files
|
|
|
|
|
in that directory will be ignored.
|
|
|
|
|
|
|
|
|
|
This will generate a `.tar.gz` archive containing all the data stored
|
|
|
|
|
on your Zulip server that would be needed to restore your Zulip
|
|
|
|
|
server's state on another machine perfectly.
|
|
|
|
|
|
|
|
|
|
### Restoring backups
|
|
|
|
|
|
2023-07-05 16:34:29 +02:00
|
|
|
|
1. Install the same base OS as the backup was taken on. If you want to [upgrade
|
|
|
|
|
the OS][upgrade-os], you should do this after restoring the backup.
|
|
|
|
|
|
|
|
|
|
1. [Install a new Zulip server through Step 3][install-server], with the same
|
|
|
|
|
version of PostgreSQL that the backup was taken on, by passing the desired
|
|
|
|
|
version with [the `--postgresql-version` argument][installer-options]. If
|
|
|
|
|
you want to [upgrade the version of PostgreSQL][upgrade-pg], you should do this after
|
|
|
|
|
restoring the backup.
|
|
|
|
|
|
|
|
|
|
1. As root, import the backup:
|
2019-09-25 01:58:20 +02:00
|
|
|
|
|
2024-03-19 15:18:51 +01:00
|
|
|
|
```bash
|
|
|
|
|
/home/zulip/deployments/current/scripts/setup/restore-backup /path/to/backup
|
|
|
|
|
```
|
2019-09-25 01:58:20 +02:00
|
|
|
|
|
|
|
|
|
When that finishes, your Zulip server should be fully operational again.
|
|
|
|
|
|
2023-07-05 16:34:29 +02:00
|
|
|
|
[upgrade-os]: upgrade.md#upgrading-the-operating-system
|
|
|
|
|
[upgrade-pg]: upgrade.md#upgrading-postgresql
|
|
|
|
|
|
2019-09-25 01:58:20 +02:00
|
|
|
|
#### Changing the hostname
|
2018-08-07 23:49:50 +02:00
|
|
|
|
|
2019-09-25 01:58:20 +02:00
|
|
|
|
It's common, when testing backup restoration, to restore backups with a
|
|
|
|
|
different user-facing hostname than the original server to avoid
|
|
|
|
|
disrupting service (e.g. `zuliptest.example.com` rather than
|
|
|
|
|
`zulip.example.com`).
|
2018-08-07 23:49:50 +02:00
|
|
|
|
|
2019-09-25 01:58:20 +02:00
|
|
|
|
If you do so, just like any other time you change the hostname, you'll
|
2022-02-24 00:17:21 +01:00
|
|
|
|
need to [update `EXTERNAL_HOST`](settings.md) and then
|
2019-09-25 01:58:20 +02:00
|
|
|
|
restart the Zulip server (after backup restoration completes).
|
2018-08-07 23:49:50 +02:00
|
|
|
|
|
2019-09-25 01:58:20 +02:00
|
|
|
|
Until you do, your Zulip server will think its user-facing hostname is
|
|
|
|
|
still `zulip.example.com` and will return HTTP `400 BAD REQUEST`
|
|
|
|
|
errors when trying to access it via `zuliptest.example.com`.
|
2018-08-07 23:49:50 +02:00
|
|
|
|
|
2022-06-09 20:37:41 +02:00
|
|
|
|
#### Changing database settings
|
|
|
|
|
|
|
|
|
|
If you wish to restore onto a very differently configured host (e.g. with
|
|
|
|
|
`REMOTE_POSTGRES_HOST` set to a different value), you can edit
|
|
|
|
|
`/etc/zulip/settings.py` to configure the host to suit the new host's needs,
|
|
|
|
|
then restore with `--keep-settings`:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
/home/zulip/deployments/current/scripts/setup/restore-backup --keep-settings /path/to/backup
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
You can also pass `--keep-zulipconf` if you wish to preserve the local
|
|
|
|
|
`/etc/zulip/zulip.conf`.
|
|
|
|
|
|
2019-09-25 01:58:20 +02:00
|
|
|
|
#### Inspecting a backup tarball
|
|
|
|
|
|
|
|
|
|
If you're not sure what versions were in use when a given backup was
|
|
|
|
|
created, you can get that information via the files in the backup
|
2021-08-20 21:53:28 +02:00
|
|
|
|
tarball: `postgres-version`, `os-version`, and `zulip-version`. The
|
2019-09-25 01:58:20 +02:00
|
|
|
|
following command may be useful for viewing these files without
|
|
|
|
|
extracting the entire archive.
|
|
|
|
|
|
2021-08-20 07:09:04 +02:00
|
|
|
|
```bash
|
2019-09-25 01:58:20 +02:00
|
|
|
|
tar -Oaxf /path/to/archive/zulip-backup-rest.tar.gz zulip-backup/zulip-version
|
|
|
|
|
```
|
|
|
|
|
|
2022-02-24 00:17:21 +01:00
|
|
|
|
[install-server]: install.md
|
2019-09-25 01:58:20 +02:00
|
|
|
|
|
|
|
|
|
### What is included
|
|
|
|
|
|
|
|
|
|
Backups contain everything you need to fully restore your Zulip
|
|
|
|
|
server, including the database, settings, secrets from
|
|
|
|
|
`/etc/zulip`, and user-uploaded files stored on the Zulip server.
|
|
|
|
|
|
|
|
|
|
The following data is not included in these backup archives,
|
docs: Add missing space to compound verbs “log in”, “set up”, etc.
Noun: backup, checkout, cleanup, login, logout, setup, shutdown, signup,
timeout.
Verb: back up, check out, clean up, log in, log out, set up, shut
down, sign up, time out.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-04-25 23:05:38 +02:00
|
|
|
|
and you may want to back up separately:
|
2019-09-25 01:58:20 +02:00
|
|
|
|
|
2021-08-20 21:53:28 +02:00
|
|
|
|
- The server access/error logs from `/var/log/zulip`. The Zulip
|
2019-09-25 01:58:20 +02:00
|
|
|
|
server only appends to logs, and they can be very large compared to
|
|
|
|
|
the rest of the data for a Zulip server.
|
|
|
|
|
|
2021-08-20 21:45:39 +02:00
|
|
|
|
- Files uploaded with the Zulip
|
2022-02-24 00:17:21 +01:00
|
|
|
|
[S3 file upload backend](upload-backends.md). We
|
2019-09-25 01:58:20 +02:00
|
|
|
|
don't include these for two reasons. First, the uploaded file data
|
|
|
|
|
in S3 can easily be many times larger than the rest of the backup,
|
|
|
|
|
and downloading it all to a server doing a backup could easily
|
2021-08-20 21:53:28 +02:00
|
|
|
|
exceed its disk capacity. Additionally, S3 is a reliable persistent
|
2019-09-25 01:58:20 +02:00
|
|
|
|
storage system with its own high-quality tools for doing backups.
|
|
|
|
|
|
2021-08-20 21:53:28 +02:00
|
|
|
|
- SSL certificates. These are not included because they are
|
2019-12-13 00:56:23 +01:00
|
|
|
|
particularly security-sensitive and are either trivially replaced
|
|
|
|
|
(if generated via Certbot) or provided by the system administrator.
|
2019-09-25 01:58:20 +02:00
|
|
|
|
|
2019-12-13 00:56:23 +01:00
|
|
|
|
For completeness, Zulip's backups do not include certain highly
|
2021-08-20 21:53:28 +02:00
|
|
|
|
transient state that Zulip doesn't store in a database. For example,
|
2019-12-13 02:11:45 +01:00
|
|
|
|
typing status data, API rate-limiting counters, and RabbitMQ queues
|
2019-12-13 00:56:23 +01:00
|
|
|
|
that are essentially always empty in a healthy server (like outgoing
|
2021-08-20 21:53:28 +02:00
|
|
|
|
emails to send). You can check whether these queues are empty using
|
2019-12-13 01:06:40 +01:00
|
|
|
|
`rabbitmqctl list_queues`.
|
2019-09-25 01:58:20 +02:00
|
|
|
|
|
|
|
|
|
#### Backup details
|
|
|
|
|
|
|
|
|
|
This section is primarily for users managing backups themselves
|
2020-10-21 03:25:37 +02:00
|
|
|
|
(E.g. if they're using a remote PostgreSQL database with an existing
|
2019-09-25 01:58:20 +02:00
|
|
|
|
backup strategy), and also serves as documentation for what is
|
2021-08-20 21:53:28 +02:00
|
|
|
|
included in the backups generated by Zulip's standard tools. The
|
2019-09-25 01:58:20 +02:00
|
|
|
|
data includes:
|
|
|
|
|
|
2021-08-20 21:53:28 +02:00
|
|
|
|
- The PostgreSQL database. You can back this up with any standard
|
2022-03-17 00:04:22 +01:00
|
|
|
|
database export or backup tool; see
|
|
|
|
|
[below](#database-only-backup-tools) for Zulip's built-in support
|
|
|
|
|
for continuous point-in-time backups.
|
2019-09-25 01:58:20 +02:00
|
|
|
|
|
2021-08-20 21:53:28 +02:00
|
|
|
|
- Any user-uploaded files. If you're using S3 as storage for file
|
2021-08-20 22:54:08 +02:00
|
|
|
|
uploads, this is backed up in S3. But if you have instead set
|
|
|
|
|
`LOCAL_UPLOADS_DIR`, any files uploaded by users (including avatars)
|
|
|
|
|
will be stored in that directory and you'll want to back it up.
|
2019-09-25 01:58:20 +02:00
|
|
|
|
|
2021-08-20 21:45:39 +02:00
|
|
|
|
- Your Zulip configuration including secrets from `/etc/zulip/`.
|
2021-08-20 22:54:08 +02:00
|
|
|
|
E.g. if you lose the value of `secret_key`, all users will need to
|
|
|
|
|
log in again when you set up a replacement server since you won't be
|
|
|
|
|
able to verify their cookies. If you lose `avatar_salt`, any
|
|
|
|
|
user-uploaded avatars will need to be re-uploaded (since avatar
|
|
|
|
|
filenames are computed using a hash of `avatar_salt` and user's
|
|
|
|
|
email), etc.
|
2019-09-25 01:58:20 +02:00
|
|
|
|
|
|
|
|
|
### Restore from manual backups
|
|
|
|
|
|
|
|
|
|
To restore from a manual backup, the process is basically the reverse of the above:
|
|
|
|
|
|
2021-08-20 21:45:39 +02:00
|
|
|
|
- Install new server as normal by downloading a Zulip release tarball
|
2022-03-21 18:06:30 +01:00
|
|
|
|
and then using `scripts/setup/install`. You should pass
|
|
|
|
|
`--no-init-db` because we don't need to create a new database.
|
2019-09-25 01:58:20 +02:00
|
|
|
|
|
2021-08-20 21:45:39 +02:00
|
|
|
|
- Unpack to `/etc/zulip` the `settings.py` and `zulip-secrets.conf` files
|
2019-09-25 01:58:20 +02:00
|
|
|
|
from your backups.
|
|
|
|
|
|
2021-08-20 21:45:39 +02:00
|
|
|
|
- Restore your database from the backup.
|
2020-05-17 13:52:37 +02:00
|
|
|
|
|
2021-08-20 21:45:39 +02:00
|
|
|
|
- Reconfigure rabbitmq to use the password from `secrets.conf`
|
2019-09-25 01:58:20 +02:00
|
|
|
|
by running, as root, `scripts/setup/configure-rabbitmq`.
|
|
|
|
|
|
2021-08-20 21:45:39 +02:00
|
|
|
|
- If you're using local file uploads, restore those files to the path
|
2019-09-25 01:58:20 +02:00
|
|
|
|
specified by `settings.LOCAL_UPLOADS_DIR` and (if appropriate) any
|
|
|
|
|
logs.
|
|
|
|
|
|
2021-08-20 21:45:39 +02:00
|
|
|
|
- Start the server using `scripts/restart-server`.
|
2019-09-25 01:58:20 +02:00
|
|
|
|
|
|
|
|
|
This restoration process can also be used to migrate a Zulip
|
|
|
|
|
installation from one server to another.
|
|
|
|
|
|
2024-02-27 22:51:44 +01:00
|
|
|
|
We recommend running a disaster recovery test after setting up your
|
|
|
|
|
backups to confirm that your backups are working. You may also want to
|
|
|
|
|
monitor that they are up to date using the Nagios plugin at:
|
2020-10-26 22:05:28 +01:00
|
|
|
|
`puppet/zulip/files/nagios_plugins/zulip_postgresql_backups/check_postgresql_backup`.
|
2019-09-25 01:58:20 +02:00
|
|
|
|
|
|
|
|
|
## Data export
|
|
|
|
|
|
|
|
|
|
Zulip's powerful data export tool is designed to handle migration of a
|
2021-02-19 19:05:38 +01:00
|
|
|
|
Zulip organization between different Zulip installations; as a result,
|
2019-09-25 01:58:20 +02:00
|
|
|
|
these exports contain all non-transient data for a Zulip organization,
|
2024-02-27 22:51:44 +01:00
|
|
|
|
with the exception of secrets, like passwords and API keys.
|
2019-09-25 01:58:20 +02:00
|
|
|
|
|
2024-02-27 22:51:44 +01:00
|
|
|
|
We recommend instead using the [backup tool](#backups) in all
|
|
|
|
|
scenarios where it is applicable, because this data export process has
|
|
|
|
|
a few downsides in comparison:
|
2019-09-25 01:58:20 +02:00
|
|
|
|
|
2024-02-27 22:51:44 +01:00
|
|
|
|
- All users will have their passwords randomized and be logged out of
|
|
|
|
|
their accounts, both on web and mobile clients.
|
|
|
|
|
- All bots and integrations will need to be updated with new API keys.
|
|
|
|
|
- Users, streams, and messages are usually renumbered, which will
|
|
|
|
|
break most links from external programs referencing these objects.
|
2023-05-15 20:40:21 +02:00
|
|
|
|
|
2024-02-27 22:51:44 +01:00
|
|
|
|
### Consider upgrading
|
|
|
|
|
|
|
|
|
|
We recommend [upgrading your Zulip server](../production/upgrade.md)
|
|
|
|
|
to the latest release [maintenance
|
|
|
|
|
release](../overview/release-lifecycle.md), or at least the latest
|
|
|
|
|
maintenance release for your major Zulip version.
|
|
|
|
|
|
|
|
|
|
**For Zulip Cloud imports**: If you are exporting data from a
|
|
|
|
|
self-hosted version of Zulip for purposes of importing into Zulip
|
|
|
|
|
Cloud, you should first [upgrade your server to the
|
2023-05-15 20:40:21 +02:00
|
|
|
|
`zulip-cloud-current` branch][upgrade-zulip-from-git]:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
/home/zulip/deployments/current/scripts/upgrade-zulip-from-git zulip-cloud-current
|
|
|
|
|
```
|
|
|
|
|
|
2024-02-27 22:51:44 +01:00
|
|
|
|
It is not sufficient to be on the latest stable release, because Zulip
|
|
|
|
|
Cloud runs pre-release versions of Zulip that are often several months
|
|
|
|
|
of development ahead of the latest release.
|
2023-05-15 20:40:21 +02:00
|
|
|
|
|
2019-09-25 01:58:20 +02:00
|
|
|
|
### Preventing changes during the export
|
2018-05-25 21:09:02 +02:00
|
|
|
|
|
|
|
|
|
For best results, you'll want to shut down access to the organization
|
2021-08-20 21:53:28 +02:00
|
|
|
|
before exporting; so that nobody can send new messages (etc.) while
|
|
|
|
|
you're exporting data. There are two ways to do this:
|
2019-03-04 20:36:09 +01:00
|
|
|
|
|
2021-08-20 21:53:28 +02:00
|
|
|
|
1. `./scripts/stop-server`, which stops the whole server. This is
|
2021-08-20 22:54:08 +02:00
|
|
|
|
preferred if you're not hosting multiple organizations, because it has
|
|
|
|
|
no side effects other than disabling the Zulip server for the
|
|
|
|
|
duration.
|
2020-08-29 00:17:21 +02:00
|
|
|
|
1. Pass `--deactivate` to `./manage export`, which first deactivates
|
2021-08-20 22:54:08 +02:00
|
|
|
|
the target organization, logging out all active login sessions and
|
|
|
|
|
preventing all accounts from logging in or accessing the API. This is
|
|
|
|
|
preferred for environments like Zulip Cloud where you might want to
|
|
|
|
|
export a single organization without disrupting any other users, and
|
|
|
|
|
the intent is to move hosting of the organization (and forcing users
|
|
|
|
|
to re-log in would be required as part of the hosting migration
|
|
|
|
|
anyway).
|
2019-03-04 20:36:09 +01:00
|
|
|
|
|
|
|
|
|
We include both options in the instructions below, commented out so
|
2021-08-20 21:53:28 +02:00
|
|
|
|
that neither runs (using the `# ` at the start of the lines). If
|
2019-03-04 20:36:09 +01:00
|
|
|
|
you'd like to use one of these options, remove the `# ` at the start
|
|
|
|
|
of the lines for the appropriate option.
|
|
|
|
|
|
2019-09-25 01:58:20 +02:00
|
|
|
|
### Export your Zulip data
|
2018-05-25 21:09:02 +02:00
|
|
|
|
|
|
|
|
|
Log in to a shell on your Zulip server as the `zulip` user. Run the
|
|
|
|
|
following commands:
|
|
|
|
|
|
2021-08-20 07:09:04 +02:00
|
|
|
|
```bash
|
2018-05-25 21:09:02 +02:00
|
|
|
|
cd /home/zulip/deployments/current
|
2021-04-16 07:46:05 +02:00
|
|
|
|
# ./scripts/stop-server
|
2020-08-29 00:17:21 +02:00
|
|
|
|
# export DEACTIVATE_FLAG="--deactivate" # Deactivates the organization
|
|
|
|
|
./manage.py export -r '' $DEACTIVATE_FLAG # Exports the data
|
2018-05-25 21:09:02 +02:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
(The `-r` option lets you specify the organization to export; `''` is
|
|
|
|
|
the default organization hosted at the Zulip server's root domain.)
|
|
|
|
|
|
2024-02-27 22:51:44 +01:00
|
|
|
|
This will generate a compressed archive with a name like
|
|
|
|
|
`/tmp/zulip-export-zcmpxfm6.tar.gz`. The archive contains several JSON
|
|
|
|
|
files (containing the Zulip organization's data) as well as an archive
|
|
|
|
|
of all the organization's uploaded files.
|
2018-05-25 21:09:02 +02:00
|
|
|
|
|
2018-07-27 05:52:21 +02:00
|
|
|
|
## Import into a new Zulip server
|
2018-05-25 21:09:02 +02:00
|
|
|
|
|
2022-02-24 00:17:21 +01:00
|
|
|
|
1. [Install a new Zulip server](install.md),
|
2021-08-20 22:54:08 +02:00
|
|
|
|
**skipping Step 3** (you'll create your Zulip organization via the data
|
|
|
|
|
import tool instead).
|
|
|
|
|
|
2021-08-20 21:45:39 +02:00
|
|
|
|
- Ensure that the Zulip server you're importing into is running the same
|
2021-08-20 21:43:11 +02:00
|
|
|
|
version of Zulip as the server you're exporting from.
|
2019-04-29 21:24:10 +02:00
|
|
|
|
|
2023-05-15 20:29:39 +02:00
|
|
|
|
- For exports created from Zulip Cloud (zulip.com), you need to [upgrade to
|
|
|
|
|
`zulip-cloud-current`][upgrade-zulip-from-git], which represents the
|
|
|
|
|
current version that Zulip Cloud is running; this is generally `main`
|
|
|
|
|
delayed by a week or two. To upgrade to that:
|
2019-04-26 03:05:17 +02:00
|
|
|
|
|
2021-08-20 21:43:11 +02:00
|
|
|
|
```bash
|
2023-05-15 20:29:39 +02:00
|
|
|
|
/home/zulip/deployments/current/scripts/upgrade-zulip-from-git zulip-cloud-current
|
2021-08-20 21:43:11 +02:00
|
|
|
|
```
|
2019-04-26 03:05:17 +02:00
|
|
|
|
|
2021-08-20 21:43:11 +02:00
|
|
|
|
It is not sufficient to be on the latest stable release, as
|
|
|
|
|
zulip.com runs pre-release versions of Zulip that are often
|
|
|
|
|
several months of development ahead of the latest release.
|
2019-12-10 02:16:58 +01:00
|
|
|
|
|
2021-08-20 21:45:39 +02:00
|
|
|
|
- Note that if your server has limited free RAM, you'll want to
|
2021-08-20 21:43:11 +02:00
|
|
|
|
shut down the Zulip server with `./scripts/stop-server` while
|
|
|
|
|
you run the import, since our minimal system requirements do not
|
|
|
|
|
budget extra RAM for running the data import tool.
|
2019-04-26 03:05:17 +02:00
|
|
|
|
|
2019-09-25 01:58:20 +02:00
|
|
|
|
2. If your new Zulip server is meant to fully replace a previous Zulip
|
2024-02-27 22:51:44 +01:00
|
|
|
|
server, copying `/etc/zulip/settings.py` and
|
|
|
|
|
`/etc/zulip/zulip.conf` is safe and recommended, to avoid
|
|
|
|
|
unnecessarily repeating configuration work.
|
|
|
|
|
|
|
|
|
|
Copying `/etc/zulip/zulip-secrets.conf` is also safe and
|
|
|
|
|
recommended, with the following important exceptions and notes:
|
|
|
|
|
|
|
|
|
|
- Copying `avatar_salt` is not recommended. Zulip will
|
2019-12-10 02:55:29 +01:00
|
|
|
|
automatically rewrite avatars at URLs appropriate for the new
|
|
|
|
|
user IDs, and using the same avatar salt (and same server URL)
|
2024-02-27 22:51:44 +01:00
|
|
|
|
post import could result in issues with browsers caching and
|
|
|
|
|
displaying avatar images improperly for users whose ID was
|
|
|
|
|
renumbered.
|
|
|
|
|
- Copying `zulip_org_id` and `zulip_org_key` is recommended to
|
|
|
|
|
avoid disconnecting your Zulip server from its registration with
|
|
|
|
|
the [Mobile Push Notifications Service][mobile-push].
|
|
|
|
|
- If you copy the `rabbitmq_password` secret from
|
|
|
|
|
`zulip-secrets.conf`, you'll need to run
|
|
|
|
|
`scripts/setup/configure-rabbitmq` as root to update your local
|
|
|
|
|
RabbitMQ installation to use the password in your Zulip secrets
|
|
|
|
|
file.
|
|
|
|
|
- Copying `camo_key` is required to avoid breaking links from Zulip
|
|
|
|
|
messages to externally hosted images.
|
|
|
|
|
- If your Zulip server is on an old Zulip Server release that
|
|
|
|
|
predates Zulip 5.0, and you use the [Mobile Push Notifications
|
|
|
|
|
Service][mobile-push], you should upgrade before you do the
|
|
|
|
|
export/import process if at all possible, and [ask for support][contact-support] if
|
|
|
|
|
it is not.
|
2019-02-03 08:20:19 +01:00
|
|
|
|
|
2019-09-25 01:58:20 +02:00
|
|
|
|
3. Log in to a shell on your Zulip server as the `zulip` user. Run the
|
2021-08-20 22:54:08 +02:00
|
|
|
|
following commands, replacing the filename with the path to your data
|
|
|
|
|
export tarball:
|
2018-05-25 21:09:02 +02:00
|
|
|
|
|
2024-03-19 15:18:51 +01:00
|
|
|
|
```bash
|
|
|
|
|
cd ~
|
|
|
|
|
tar -xf /path/to/export/file/zulip-export-zcmpxfm6.tar.gz
|
|
|
|
|
cd /home/zulip/deployments/current
|
|
|
|
|
./manage.py import '' ~/zulip-export-zcmpxfm6
|
|
|
|
|
./scripts/start-server
|
|
|
|
|
```
|
2018-05-25 21:09:02 +02:00
|
|
|
|
|
2019-09-25 01:58:20 +02:00
|
|
|
|
This could take several minutes to run depending on how much data you're
|
2018-10-18 22:39:56 +02:00
|
|
|
|
importing.
|
2018-05-25 21:09:02 +02:00
|
|
|
|
|
2024-02-27 22:51:44 +01:00
|
|
|
|
[contact-support]: https://zulip.com/help/contact-support
|
2023-01-17 04:33:42 +01:00
|
|
|
|
[upgrade-zulip-from-git]: upgrade.md#upgrading-from-a-git-repository
|
2019-03-22 17:22:18 +01:00
|
|
|
|
|
2019-09-25 01:58:20 +02:00
|
|
|
|
#### Import options
|
2018-05-25 21:09:02 +02:00
|
|
|
|
|
2018-10-18 22:39:56 +02:00
|
|
|
|
The commands above create an imported organization on the root domain
|
|
|
|
|
(`EXTERNAL_HOST`) of the Zulip installation. You can also import into a
|
|
|
|
|
custom subdomain, e.g. if you already have an existing organization on the
|
2023-04-04 17:27:22 +02:00
|
|
|
|
root domain. Replace the last two lines above with the following, after replacing
|
2018-10-18 22:39:56 +02:00
|
|
|
|
`<subdomain>` with the desired subdomain.
|
2018-05-25 21:09:02 +02:00
|
|
|
|
|
2021-08-20 07:09:04 +02:00
|
|
|
|
```bash
|
2019-01-15 02:56:06 +01:00
|
|
|
|
./manage.py import <subdomain> ~/zulip-export-zcmpxfm6
|
2023-04-04 18:37:16 +02:00
|
|
|
|
./scripts/start-server
|
2018-05-25 21:09:02 +02:00
|
|
|
|
```
|
|
|
|
|
|
2019-09-25 01:58:20 +02:00
|
|
|
|
### Logging in
|
2018-07-27 05:52:21 +02:00
|
|
|
|
|
|
|
|
|
Once the import completes, all your users will have accounts in your
|
|
|
|
|
new Zulip organization, but those accounts won't have passwords yet
|
|
|
|
|
(since for security reasons, passwords are not exported).
|
|
|
|
|
Your users will need to either authenticate using something like
|
2019-09-25 01:58:20 +02:00
|
|
|
|
Google auth or start by resetting their passwords.
|
2018-07-27 05:52:21 +02:00
|
|
|
|
|
|
|
|
|
You can use the `./manage.py send_password_reset_email` command to
|
2021-08-20 21:53:28 +02:00
|
|
|
|
send password reset emails to your users. We
|
2018-07-27 05:52:21 +02:00
|
|
|
|
recommend starting with sending one to yourself for testing:
|
|
|
|
|
|
2021-08-20 07:09:04 +02:00
|
|
|
|
```bash
|
2018-07-27 05:52:21 +02:00
|
|
|
|
./manage.py send_password_reset_email -u username@example.com
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
and then once you're ready, you can email them to everyone using e.g.
|
2021-08-20 22:54:08 +02:00
|
|
|
|
|
2021-08-20 07:09:04 +02:00
|
|
|
|
```bash
|
2018-07-27 05:52:21 +02:00
|
|
|
|
./manage.py send_password_reset_email -r '' --all-users
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
(replace `''` with your subdomain if you're using one).
|
2019-04-11 20:57:25 +02:00
|
|
|
|
|
2019-09-25 01:58:20 +02:00
|
|
|
|
### Deleting and re-importing
|
2019-04-11 20:57:25 +02:00
|
|
|
|
|
|
|
|
|
If you did a test import of a Zulip organization, you may want to
|
|
|
|
|
delete the test import data from your Zulip server before doing a
|
2021-08-20 21:53:28 +02:00
|
|
|
|
final import. You can **permanently delete** all data from a Zulip
|
2023-02-25 03:18:43 +01:00
|
|
|
|
organization by running (replacing `''` with the subdomain if [you are
|
|
|
|
|
hosting the organization on a subdomain](multiple-organizations.md)):
|
2021-08-20 22:54:08 +02:00
|
|
|
|
|
2021-08-20 07:09:04 +02:00
|
|
|
|
```bash
|
2023-02-25 03:18:43 +01:00
|
|
|
|
./manage.py delete_realm -r ''
|
2019-04-11 20:57:25 +02:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Assuming you're using the
|
2022-02-24 00:17:21 +01:00
|
|
|
|
[local file uploads backend](upload-backends.md), you
|
2019-04-11 20:57:25 +02:00
|
|
|
|
can additionally delete all file uploads, avatars, and custom emoji on
|
|
|
|
|
a Zulip server (across **all organizations**) with the following
|
|
|
|
|
command:
|
|
|
|
|
|
2021-08-20 07:09:04 +02:00
|
|
|
|
```bash
|
2019-04-11 20:57:25 +02:00
|
|
|
|
rm -rf /home/zulip/uploads/*/*
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
If you're hosting multiple organizations and would like to remove
|
|
|
|
|
uploads from a single organization, you'll need to access `realm.id`
|
|
|
|
|
in the management shell before deleting the organization from the
|
|
|
|
|
database (this will be `2` for the first organization created on a
|
|
|
|
|
Zulip server, shown in the example below), e.g.:
|
|
|
|
|
|
2021-08-20 07:09:04 +02:00
|
|
|
|
```bash
|
2019-04-11 20:57:25 +02:00
|
|
|
|
rm -rf /home/zulip/uploads/*/2/
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Once that's done, you can simply re-run the import process.
|
2022-03-17 00:04:22 +01:00
|
|
|
|
|
2022-11-17 18:42:02 +01:00
|
|
|
|
## Compliance exports
|
|
|
|
|
|
|
|
|
|
In some circumstances, corporate or legal compliance may require
|
|
|
|
|
performing selective data exports. This can be done with the
|
|
|
|
|
`export_search` command-line tool, which lets you specify the
|
|
|
|
|
following parameters when exporting messages:
|
|
|
|
|
|
|
|
|
|
- Search keywords in the message text.
|
2023-05-11 20:28:24 +02:00
|
|
|
|
- Message sender or recipient.
|
2022-11-17 18:42:02 +01:00
|
|
|
|
- Time range for when messages were sent.
|
|
|
|
|
|
|
|
|
|
For example, to search for messages containing the word "wonderland"
|
|
|
|
|
between November 1st and 6th, from `alice@example.com`:
|
|
|
|
|
|
|
|
|
|
```console
|
|
|
|
|
$ /home/zulip/deployments/current/manage.py export_search --output compliance-export.json
|
|
|
|
|
-r zulip \
|
|
|
|
|
--after '2022-11-01 00:00:00' --before '2022-11-06 14:00:00' \
|
|
|
|
|
--sender alice@example.com \
|
|
|
|
|
wonderland
|
|
|
|
|
```
|
|
|
|
|
|
2023-05-11 20:28:24 +02:00
|
|
|
|
The results are written to a JSON or CSV file. The contents of previous versions
|
|
|
|
|
of edited messages are not searched, nor are deleted messages. Attachments
|
|
|
|
|
associated with the resulting messages can optionally also be exported.
|
2022-11-17 18:42:02 +01:00
|
|
|
|
|
|
|
|
|
See `/home/zulip/deployments/current/manage.py export_search --help`
|
|
|
|
|
for more details on supported options.
|
|
|
|
|
|
2022-03-17 00:04:22 +01:00
|
|
|
|
## Database-only backup tools
|
|
|
|
|
|
2024-03-18 20:27:39 +01:00
|
|
|
|
The [Zulip-specific backup tool documented above](#backups) is perfect for an
|
|
|
|
|
all-in-one backup solution, and can be used for nightly backups. For
|
|
|
|
|
administrators wanting continuous point-in-time backups, Zulip has built-in
|
|
|
|
|
support for taking daily backup snapshots along with [streaming write-ahead log
|
|
|
|
|
(WAL)][wal] backups using [wal-g](https://github.com/wal-g/wal-g). By default,
|
|
|
|
|
these backups are stored for 30 days.
|
2022-03-17 00:04:22 +01:00
|
|
|
|
|
|
|
|
|
Note these database backups, by themselves, do not constitute a full
|
|
|
|
|
backup of the Zulip system! [See above](#backup-details) for other
|
|
|
|
|
pieces which are necessary to back up a Zulip system.
|
|
|
|
|
|
2024-03-18 20:27:39 +01:00
|
|
|
|
Daily full-database backups will be taken at 0200 UTC, and every [WAL][wal]
|
|
|
|
|
archive file will be backed up as it is saved by PostgreSQL; these are written
|
|
|
|
|
every 16KiB of the WAL. This means that if there are periods of slow activity,
|
|
|
|
|
it may be minutes before the backup is saved into S3 -- see
|
|
|
|
|
[`archive_timeout`][archive-timeout] for how to set an upper bound on this.
|
2022-03-17 00:04:22 +01:00
|
|
|
|
|
2024-03-18 20:27:39 +01:00
|
|
|
|
If you need always-current backup availability, Zulip also has
|
|
|
|
|
[built-in database replication support](deployment.md#postgresql-warm-standby).
|
|
|
|
|
|
|
|
|
|
You can (and should) monitor that backups are running regularly via
|
|
|
|
|
the Nagios plugin installed into
|
|
|
|
|
`/usr/lib/nagios/plugins/zulip_postgresql_backups/check_postgresql_backup`.
|
|
|
|
|
|
|
|
|
|
### Streaming backups to S3
|
|
|
|
|
|
|
|
|
|
This provides a durable and reliable off-host database backup, and we suggest
|
|
|
|
|
this configuration for resilience to disk failures. Because backups are written
|
|
|
|
|
to S3 as the WAL logs are written, this means that an active Zulip server will
|
|
|
|
|
be regularly sending PutObject requests to S3, possibly thousands of times per
|
|
|
|
|
day.
|
|
|
|
|
|
|
|
|
|
1. Edit `/etc/zulip/zulip-secrets.conf` on the PostgreSQL server to add:
|
2022-03-17 00:04:22 +01:00
|
|
|
|
|
2024-03-19 15:18:51 +01:00
|
|
|
|
```ini
|
|
|
|
|
s3_region = # region to write to S3; defaults to EC2 host's region
|
|
|
|
|
s3_backups_key = # aws public key; optional, if access not through role
|
|
|
|
|
s3_backups_secret_key = # aws secret key; optional, if access not through role
|
|
|
|
|
s3_backups_bucket = # name of S3 backup bucket
|
|
|
|
|
```
|
2022-03-17 00:04:22 +01:00
|
|
|
|
|
2024-03-18 20:27:39 +01:00
|
|
|
|
1. Run:
|
2022-03-17 00:04:22 +01:00
|
|
|
|
|
2024-03-18 20:27:39 +01:00
|
|
|
|
```shell
|
|
|
|
|
/home/zulip/deployments/current/scripts/zulip-puppet-apply
|
|
|
|
|
```
|
2022-05-07 02:21:44 +02:00
|
|
|
|
|
2024-03-19 15:24:23 +01:00
|
|
|
|
You may also want to adjust the
|
2024-03-18 21:22:31 +01:00
|
|
|
|
[concurrency](system-configuration.md#backups_disk_concurrency), [S3 storage
|
|
|
|
|
class](system-configuration.md#backups_storage_class), or [incremental
|
|
|
|
|
backups][incremental] configuration.
|
2024-03-19 15:24:23 +01:00
|
|
|
|
|
2024-03-18 20:27:39 +01:00
|
|
|
|
### Streaming backups to local disk
|
2022-03-17 00:04:22 +01:00
|
|
|
|
|
2024-03-18 20:27:39 +01:00
|
|
|
|
As an alternative to storing backups to S3, you can also store backups to a
|
|
|
|
|
local disk. This option is not recommended for disaster recovery purposes,
|
|
|
|
|
since unless the directory is on a different disk from the database itself,
|
|
|
|
|
_backups will likely also be lost if the database is lost._ This setting can be
|
|
|
|
|
useful if the path is on a NAS mountpoint, or if some other process copies this
|
|
|
|
|
data off the disk; or if backups are purely for point-in-time historical
|
|
|
|
|
analysis of recent application-level data changes.
|
|
|
|
|
|
|
|
|
|
1. Edit `/etc/zulip/zulip.conf` on the PostgreSQL server, and add to the existing
|
|
|
|
|
`[postgresql]` section:
|
|
|
|
|
|
|
|
|
|
```ini
|
|
|
|
|
# Adjust this path to your desired storage location; this should be on a
|
|
|
|
|
# different disk than /var/lib/postgresql/ which stores the database.
|
|
|
|
|
backups_directory = /srv/zulip-db-backups
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
1. Run:
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
/home/zulip/deployments/current/scripts/zulip-puppet-apply
|
|
|
|
|
```
|
2022-05-07 02:21:44 +02:00
|
|
|
|
|
2024-03-18 21:22:31 +01:00
|
|
|
|
You may also want to adjust the [incremental backups][incremental]
|
|
|
|
|
configuration.
|
|
|
|
|
|
2022-05-07 02:21:44 +02:00
|
|
|
|
[wal]: https://www.postgresql.org/docs/current/wal-intro.html
|
|
|
|
|
[archive-timeout]: https://www.postgresql.org/docs/current/runtime-config-wal.html#GUC-ARCHIVE-TIMEOUT
|
2024-02-27 22:51:44 +01:00
|
|
|
|
[mobile-push]: ../production/mobile-push-notifications.md
|
2024-03-18 21:22:31 +01:00
|
|
|
|
[incremental]: system-configuration.md#backups_incremental
|