zulip/docs/production/mobile-push-notifications.md

422 lines
18 KiB
Markdown

# Mobile push notification service
Zulip's iOS and Android [mobile apps](https://zulip.com/apps/) support
receiving push notifications from Zulip servers to notify users when
new messages have arrived. This is an important feature for having a
great mobile app experience.
Google's and Apple's security model for mobile push notifications does not allow
self-hosted Zulip servers to directly send mobile notifications to the Zulip
mobile apps. The Zulip Mobile Push Notification Service solves this problem by
forwarding mobile push notifications generated by your server to the Zulip
mobile apps.
## Signing up
:::{important}
These instructions are for Zulip Server 9.0+. If you are running an older
version of Zulip ([check](https://zulip.com/help/view-zulip-version) if you are
unsure), see the [Zulip 8.x
documentation](https://zulip.readthedocs.io/en/8.4/production/mobile-push-notifications.html).
:::
You can enable the mobile push notification service for your Zulip server as
follows:
1. Make sure your server has outgoing HTTPS access to the public Internet. If
that is restricted by a proxy, you will need to [configure Zulip to use your
outgoing HTTP proxy](deployment.md#customizing-the-outgoing-http-proxy)
first.
1. Set `ZULIP_SERVICE_PUSH_NOTIFICATIONS = True` in your
`/etc/zulip/settings.py` file. Simply uncomment the appropriate line [in
settings.py][update-settings-docs] by deleting the initial `# `.
1. Decide whether to share usage statistics with the Zulip team.
By default, Zulip installations using the Mobile Push Notification Service
submit additional usage statistics that help Zulip's maintainers allocate
resources towards supporting self-hosted installations
([details](#uploading-usage-statistics)). You can disable submitting usage
statistics now or at any time by setting
`ZULIP_SERVICE_SUBMIT_USAGE_STATISTICS=False` in `/etc/zulip/settings.py`
(uncomment the appropriate line).
Note that all systems using the service upload [basic
metadata](#uploading-basic-metadata) about the organizations hosted
by the installation.
[update-settings-docs]: ../production/upgrade.md#updating-settingspy-inline-documentation
1. [Restart your Zulip server](settings.md#making-changes) so that
your configuration changes take effect.
1. Run the registration command. If you installed Zulip directly on the server
(without Docker), run as root:
```
su zulip -c '/home/zulip/deployments/current/manage.py register_server'
```
Or if you're using Docker, run:
```
docker exec -it -u zulip <container_name> /home/zulip/deployments/current/manage.py register_server
```
This command will print the registration data it would send to the Mobile
Push Notification Service, ask you to accept the terms of service, and if
you accept, register your server. If you have trouble, [contact Zulip
support](https://zulip.com/help/contact-support) with the output of this
command.
1. Organizations with more than 10 users must upgrade their
[plan](https://zulip.com/plans/) in order to access the Mobile Push
Notification Service. See [plan management](#plan-management) for details.
1. If you or your users have already set up the Zulip mobile app, you'll each
need to log out of the mobile app, and log back in again in order to start
getting push notifications.
Congratulations! You've successfully set up the service. You can now test mobile
push notifications by following [these
instructions](https://zulip.com/help/mobile-notifications#testing-mobile-notifications).
## Plan management
To access the Mobile Push Notification Service, organizations with more than 10
users must upgrade to a paid [plan](https://zulip.com/plans/#self-hosted), or
the free Community plan (if
[eligible](https://zulip.com/help/self-hosted-billing#free-community-plan)).
While upgrading your Zulip server to version 8.0+ makes it more convenient to
manage your plan, the same plans are offered for all Zulip versions.
### Plan management for a Zulip organization
On a self-hosted Zulip server running Zulip 8.0+, [organization
owners](https://zulip.com/help/roles-and-permissions) and billing administrators
can conveniently access plan management from the Zulip app. See [help center
documentation](https://zulip.com/help/self-hosted-billing) for detailed
instructions.
You can add billing administrators using the `change_user_role` [management
command][management-commands], passing [the organization's
`string_id`][accessing-string-id], and the email address of the Zulip user who
should be added as a billing administrator.
```
/home/zulip/deployments/current/manage.py change_user_role -r '' username@example.com is_billing_admin
```
You can remove a user's billing administrator permissions with the `--revoke`
option:
```
/home/zulip/deployments/current/manage.py change_user_role --revoke -r '' username@example.com is_billing_admin
```
[management-commands]: ../production/management-commands.md
[accessing-string-id]: https://zulip.readthedocs.io/en/stable/production/management-commands.html#accessing-an-organization-s-string-id
### Plan management for an entire Zulip server
Servers running Zulip releases older than Zulip 8.0 can start the plan
management log in process at
<https://selfhosting.zulip.com/serverlogin/>. This option is also
available for Zulip 8.0+ servers, and makes it possible to use a
single plan for multiple organizations on one installation. See [help
center documentation](https://zulip.com/help/self-hosted-billing) for
detailed log in instructions.
You will use your server's `zulip_org_id` and `zulip_org_key` as the username
and password to access plan management. You can obtain these from
`/etc/zulip/zulip-secrets.conf` on your Zulip server, or via the following
commands:
```
/home/zulip/deployments/current/scripts/get-django-setting ZULIP_ORG_ID
/home/zulip/deployments/current/scripts/get-django-setting ZULIP_ORG_KEY
```
## Why a push notification service is necessary
Both Google's and Apple's push notification services have a security
model that does not support mutually untrusted self-hosted servers
sending push notifications to the same app. In particular, when an
app is published to their respective app stores, one must compile into
the app a secret corresponding to the server that will be able to
publish push notifications for the app. This means that it is
impossible for a single app in their stores to receive push
notifications from multiple, mutually untrusted, servers.
Zulip's solution to this problem is to provide a central push
notification forwarding service, which allows registered Zulip servers
to send push notifications to the Zulip app indirectly (through the
forwarding service).
## Security and privacy
Use of the push notification bouncer is subject to the Zulip Cloud [Terms of
Service](https://zulip.com/policies/terms), [Privacy
Policy](https://zulip.com/policies/privacy) and [Rules of
Use](https://zulip.com/policies/rules). By using push notifications, you agree
to these terms.
We've designed this push notification bouncer service with security
and privacy in mind:
- A central design goal of the Push Notification Service is to
avoid any message content being stored or logged by the service,
even in error cases.
- The Push Notification Service only stores the necessary metadata for
delivering the notifications to the appropriate devices and
otherwise operating the service:
- The APNS/FCM tokens needed to securely send mobile push
notifications to iOS and Android devices, one per device
registered to be notified by your Zulip server.
- User ID numbers generated by your Zulip server, needed to route
a given notification to the appropriate set of mobile devices.
These user ID numbers are opaque to the Push Notification
Service and Kandra Labs.
- [Basic organization metadata](#uploading-basic-metadata),
[optional usage statistics](#uploading-usage-statistics), and
aggregate statistics about how many push notifications are sent by
each customer.
- The Push Notification Service receives (but does not store) the
contents of individual mobile push notifications:
- The numeric message ID generated by your Zulip server.
- Metadata on the message's sender (name and avatar URL).
- Metadata on the message's recipient (channel name + ID, topic,
direct message recipients, etc.).
- A timestamp.
- The message's content.
There's a `PUSH_NOTIFICATION_REDACT_CONTENT` setting available to
disable any message content being sent via the push notification
bouncer (i.e., message content will be replaced with
`New message`). Note that this setting makes push notifications
significantly less usable.
We plan to
[replace that setting with end-to-end encryption](https://github.com/zulip/zulip/issues/6954)
which would eliminate that usability tradeoff and additionally allow
us to not have any access to the other details mentioned in this
section.
- All of the network requests (both from Zulip servers to the Push
Notification Service and from the Push Notification Service to the
relevant Google and Apple services) are encrypted over the wire with
SSL/TLS.
- The code for the push notification forwarding service is 100% open
source and available as part of the
[Zulip server project on GitHub](https://github.com/zulip/zulip)
(specifically, [here](https://github.com/zulip/zulip/tree/main/zilencer)).
- The push notification forwarding servers are professionally managed
by a small team of security-sensitive engineers.
If you have any questions about the security model, [contact Zulip
support](https://zulip.com/help/contact-support).
### Uploading basic metadata
All Zulip installations running Zulip 8.0 or greater that are
registered for the Mobile Push Notification Service regularly upload
to the service basic metadata about the organizations hosted by the
installation. (Older Zulip servers upload these metadata only if
[uploading usage statistics](#uploading-usage-statistics) is enabled).
Uploaded metadata consists of, for each organization hosted by the
installation:
- A subset of the basic metadata returned by the unauthenticated [`GET
/server_settings` API
endpoint](https://zulip.com/api/get-server-settings).
The purpose of that API endpoint is to serve the minimal data
needed by the Zulip mobile apps in order to:
- Verify that a given URL is indeed a valid Zulip server URL
- Present a correct login form, offering only the supported features
and authentication methods for that organization and Zulip server
version.
Most of the metadata it returns is necessarily displayed to anyone
with network access to the Zulip server on the login and signup
pages for your Zulip organization as well.
(Some fields returned by this endpoint, like the organization icon
and description, are not included in uploaded metadata.)
- The [organization type](https://zulip.com/help/organization-type)
and creation date.
- The number of user accounts with each role.
Our use of uploaded metadata is governed by the same [Terms of
Service](https://zulip.com/policies/terms) and [Privacy
Policy](https://zulip.com/policies/privacy) that covers the Mobile
Push Notification Service itself.
### Uploading usage statistics
By default, Zulip installations that register for the Mobile Push
Notification Service upload the following usage statistics. You can
disable these uploads any time by setting
`ZULIP_SERVICE_SUBMIT_USAGE_STATISTICS=False` in `/etc/zulip/settings.py`.
- Totals for messages sent and read with subtotals for various
combinations of clients and integrations.
- Totals for active users under a few definitions (1day, 7day, 15day)
and related statistics.
Some of the graphs on your server's [usage statistics
page](https://zulip.com/help/analytics) can be generated from these
statistics.
When enabled, usage statistics are submitted via an hourly cron
job. If you'd like to access plan management immediately after
enabling `SUBMIT_USAGE_STATISTICS=True` (the legacy form of this setting)
on a pre-8.0 Zulip server, you can run the analytics job manually via:
```
/home/zulip/deployments/current/manage.py update_analytics_counts
```
Our use of uploaded usage statistics is governed by the same [Terms of
Service](https://zulip.com/policies/terms) and [Privacy
Policy](https://zulip.com/policies/privacy) that covers the Mobile
Push Notification Service itself.
## Rate limits
The Mobile Push Notification Service API has a very high default rate
limit of 1000 requests per minute. A Zulip server makes requests to
this API every time it sends a push notification, which is fairly
frequent, but we believe it to be unlikely that a self-hosted
installation will hit this limit.
This limit is primarily intended to protect the service against DoS
attacks (intentional or otherwise). If you hit this limit or you
anticipate that your server will require sending more push
notifications than the limit permits, please [contact
support](https://zulip.com/help/contact-support).
## Updating your server's registration
Your server's registration includes the server's hostname and contact
email address (from `EXTERNAL_HOST` and `ZULIP_ADMINISTRATOR` in
`/etc/zulip/settings.py`, aka the `--hostname` and `--email` options
in the installer). You can update your server's registration data by
running `manage.py register_server` again.
If you'd like to rotate your server's API key for this service
(`zulip_org_key`), you need to use
`manage.py register_server --rotate-key` option; it will automatically
generate a new `zulip_org_key` and store that new key in
`/etc/zulip/zulip-secrets.conf`.
## Deactivating your server's registration
If you are deleting your Zulip server or otherwise no longer want to
use the Mobile Push Notification Service, you can deactivate your server's
registration.
1. [Cancel any paid
plans](https://zulip.com/help/self-hosted-billing#cancel-paid-plan)
associated with your server.
1. Run the deregistration command. If you installed Zulip directly on
the server (without Docker), run as root:
```
su zulip -c '/home/zulip/deployments/current/manage.py register_server --deactivate'
```
Or if you're using Docker, run:
```
docker exec -it -u zulip <container_name> /home/zulip/deployments/current/manage.py register_server --deactivate
```
1. Comment out the
`ZULIP_SERVICE_PUSH_NOTIFICATIONS = True` line
in your `/etc/zulip/settings.py` file (i.e., add `# ` at the
start of the line), and [restart your Zulip
server](settings.md#making-changes).
If you ever need to reactivate your server's registration, [contact Zulip
support](https://zulip.com/help/contact-support).
### Pausing use of the Mobile Push Notification Service
You can temporarily stop using the Mobile Push Notification Service. Comment out
the `PUSH_NOTIFICATION_BOUNCER_URL = 'https://push.zulipchat.com'` line in your
`/etc/zulip/settings.py` file (i.e., add `# ` at the start of the line), and
[restart your Zulip server](settings.md#making-changes). This approach makes it
easy to start using the service again by uncommenting the same line.
## Sending push notifications directly from your server
This section documents an alternative way to send push notifications
that does not involve using the Mobile Push Notification Service at
the cost of needing to compile and distribute modified versions of the
Zulip mobile apps.
We don't recommend this path -- patching and shipping a production
mobile app can take dozens of hours to set up even for an experienced
developer, and even more time to maintain. And it doesn't provide
material privacy benefits -- your organization's push notification
data would still go through Apple/Google's servers, just not Kandra
Labs'. But in the interest of transparency, we document in this
section roughly what's involved in doing so.
As [discussed above](#why-a-push-notification-service-is-necessary),
it is impossible for a single app in the Google or Apple
store to receive push notifications from multiple, mutually
untrusted, servers. The Mobile Push Notification Service is one of
the possible solutions to this problem.
The other possible solution is for an individual Zulip server's administrators
to build and distribute their own copy of the Zulip mobile apps, hardcoding a
key that they possess. This solution is possible with Zulip, but it requires the
server administrators to publish their own copies of the Zulip mobile apps.
There's nothing the Zulip team can do to eliminate this onerous requirement.
The main work is thus distributing your own copies of the Zulip mobile apps
configured to use APNS/FCM keys that you generate. This is not for
the faint of heart! If you haven't done this before, be warned that
one can easily spend hundreds of dollars (on things like a DUNS number
registration) and a week struggling through the hoops Apple requires
to build and distribute an app through the Apple app store, even if
you're making no code modifications to an app already present in the
store (as would be the case here). The Zulip mobile app also gets
frequent updates that you will have to either forgo or republish to
the app stores yourself.
If you've done that work, the Zulip server configuration for sending
push notifications through the new app is quite straightforward:
- Create an
[FCM push notifications](https://firebase.google.com/docs/cloud-messaging)
key in the Google Developer console and set `android_gcm_api_key` in
`/etc/zulip/zulip-secrets.conf` to that key.
- In Apple's developer console, register a [token][apple-doc-token] or
[certificate][apple-doc-cert] for sending push notifications.
Then in `/etc/zulip/settings.py`, set `APNS_SANDBOX=False`, and:
- If using APNs [certificate-based authentication][apple-doc-cert],
set `APNS_CERT_FILE` to the path of your APNs certificate file.
- If using APNs [token-based authentication][apple-doc-token],
set `APNS_TOKEN_KEY_FILE` to the path of your APNs token key file,
`APNS_TOKEN_KEY_ID` to the corresponding 10-character key ID, and
`APNS_TEAM_ID` to your 10-character Apple team ID.
- Restart the Zulip server.
[apple-doc-cert]: https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/establishing_a_certificate-based_connection_to_apns
[apple-doc-token]: https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/establishing_a_token-based_connection_to_apns