mirror of https://github.com/zulip/zulip.git
392 lines
17 KiB
Markdown
392 lines
17 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 let users know when new messages have
|
|
arrived. This is an important feature for having a great mobile app experience.
|
|
|
|
To set up mobile push notifications, you will need to register your Zulip server
|
|
with the Zulip mobile push notification service. This service will forward push
|
|
notifications generated by your server to users' mobile apps.
|
|
|
|
## How to sign up
|
|
|
|
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. Decide whether to share usage statistics with the Zulip team.
|
|
|
|
By default, Zulip installations using the Mobile Push Notifications
|
|
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
|
|
`SUBMIT_USAGE_STATISTICS=False` in `/etc/zulip/settings.py`.
|
|
|
|
Note that all systems using the service upload [basic
|
|
metadata](#uploading-basic-metadata) about the organizations hosted
|
|
by the installation.
|
|
|
|
1. Uncomment the
|
|
`PUSH_NOTIFICATION_BOUNCER_URL = 'https://push.zulipchat.com'` line
|
|
in your `/etc/zulip/settings.py` file (i.e., remove the `#` at the
|
|
start of the line), and [restart your Zulip
|
|
server](settings.md#making-changes).
|
|
|
|
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 notifications 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. 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 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 (stream 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
|
|
`***REDACTED***`). 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).
|
|
- 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 Notifications 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 Notifications Service itself.
|
|
|
|
### Uploading usage statistics
|
|
|
|
By default, Zulip installations that register for the Mobile Push
|
|
Notifications Service upload the following usage statistics. You can
|
|
disable these uploads any time by setting
|
|
`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` 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 Notifications Service itself.
|
|
|
|
## Rate limits
|
|
|
|
The Mobile Push Notifications 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
|
|
`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).
|
|
|
|
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
|