-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
optional role for matrix-fluffygate #3677
base: master
Are you sure you want to change the base?
Changes from 3 commits
5b76b66
d628b7f
fc9dac7
934deda
614dc4a
74e7f41
3ca0f42
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,147 @@ | ||||||||||||||||||||||||||
# Setting up Fluffygate (optional) | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
The playbook can install and configure [Fluffygate](https://github.com/krille-chan/fluffygate), a simple Push Gateway for Fluffychat. | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
See the project's documentation to learn what it does and why it might be useful to you. | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
**Note**: most people don't need to install their own gateway. This optional playbook component is only useful to people who develop/build their own Matrix client applications themselves, as you'll need access to your own Firebase/FCM and APNS credentials. | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
## Adjusting the playbook configuration | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
To enable Fluffygate, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file: | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
```yaml | ||||||||||||||||||||||||||
matrix_fluffygate_enabled: true | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
# Basic app information | ||||||||||||||||||||||||||
matrix_fluffygate_app_name: "Your App Name" | ||||||||||||||||||||||||||
matrix_fluffygate_app_website: "https://example.com" | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
# Firebase/FCM configuration (for Android / IOS) | ||||||||||||||||||||||||||
matrix_fluffygate_firebase_project: "your-firebase-project-id" | ||||||||||||||||||||||||||
matrix_fluffygate_firebase_key: | | ||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||
# Your Firebase service account key JSON content | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
# Notification settings | ||||||||||||||||||||||||||
matrix_fluffygate_notification_title: "{count} new messages" | ||||||||||||||||||||||||||
matrix_fluffygate_notification_body: "{body}" | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
# Android specific notification options | ||||||||||||||||||||||||||
matrix_fluffygate_android_notification_options: | ||||||||||||||||||||||||||
priority: high | ||||||||||||||||||||||||||
notification: | ||||||||||||||||||||||||||
sound: "default" | ||||||||||||||||||||||||||
icon: "notifications_icon" | ||||||||||||||||||||||||||
tag: "default_notification" | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
# APNS specific notification options (for iOS) | ||||||||||||||||||||||||||
matrix_fluffygate_apns_notification_options: | ||||||||||||||||||||||||||
headers: | ||||||||||||||||||||||||||
apns-priority: "10" | ||||||||||||||||||||||||||
payload: | ||||||||||||||||||||||||||
aps: | ||||||||||||||||||||||||||
sound: "default" | ||||||||||||||||||||||||||
badge: "{count}" | ||||||||||||||||||||||||||
mutable-content: 1 | ||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
For a complete list of available configuration options, see the `defaults/main.yml` file in the role. | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
### Required Configuration | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
The following settings are required and must be defined: | ||||||||||||||||||||||||||
- `matrix_fluffygate_hostname` | ||||||||||||||||||||||||||
- `matrix_fluffygate_path_prefix` | ||||||||||||||||||||||||||
Comment on lines
+55
to
+56
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we consider automatically configuring This way we'll have a reasonable default. Have you confirmed that hosting it under a path prefix works as expected? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll clean things up bit later - very little time these days, yet wanted to contribute to the upstream. I tried hosting on the same host but that did not work for some reason and I went with a dedicated hostname instead. Can try again later. |
||||||||||||||||||||||||||
- `matrix_fluffygate_container_network` | ||||||||||||||||||||||||||
- `matrix_fluffygate_app_name` | ||||||||||||||||||||||||||
- `matrix_fluffygate_app_website` | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
### Adjusting the Fluffygate URL | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
By default, this playbook installs Fluffygate at the root path (`/`) of the configured hostname. You can customize both the hostname and path prefix using these variables: | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
```yaml | ||||||||||||||||||||||||||
# Configure the hostname where Fluffygate will be served | ||||||||||||||||||||||||||
matrix_fluffygate_hostname: "push.example.com" | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
# Configure a custom path prefix (must either be '/' or not end with a slash) | ||||||||||||||||||||||||||
matrix_fluffygate_path_prefix: /push | ||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
### Traefik Integration | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
Fluffygate includes built-in support for Traefik as a reverse proxy. The following settings control this integration: | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
```yaml | ||||||||||||||||||||||||||
# Enable/disable Traefik labels | ||||||||||||||||||||||||||
matrix_fluffygate_container_labels_traefik_enabled: true | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
# Configure the Traefik network | ||||||||||||||||||||||||||
matrix_fluffygate_container_labels_traefik_docker_network: "{{ matrix_fluffygate_container_network }}" | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
# Additional Traefik configuration | ||||||||||||||||||||||||||
matrix_fluffygate_container_labels_traefik_rule: "Host(`{{ matrix_fluffygate_container_labels_traefik_hostname }}`)" | ||||||||||||||||||||||||||
matrix_fluffygate_container_labels_traefik_priority: 0 | ||||||||||||||||||||||||||
matrix_fluffygate_container_labels_traefik_entrypoints: web-secure | ||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
## Adjusting DNS records | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
You will need to configure your DNS records to point the Fluffygate hostname to your server. This typically involves creating either: | ||||||||||||||||||||||||||
- an A record pointing to your server's IPv4 address | ||||||||||||||||||||||||||
- a CNAME record pointing to your server's hostname | ||||||||||||||||||||||||||
Comment on lines
+90
to
+94
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Per existing lines for Sygnal here. Please update the default CNAME record
Suggested change
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
## Installing | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
After configuring the playbook and adjusting your DNS records, run the installation command: | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
```bash | ||||||||||||||||||||||||||
ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,start | ||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
To install only Fluffygate, you can use: | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
```bash | ||||||||||||||||||||||||||
ansible-playbook -i inventory/hosts setup.yml --tags=setup-fluffygate,start | ||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
## Usage | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
To make use of your Fluffygate installation: | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
1. Configure your Matrix client application to use your Fluffygate URL as the push gateway | ||||||||||||||||||||||||||
2. Ensure your app uses the same Firebase/FCM credentials for Android notifications | ||||||||||||||||||||||||||
3. Ensure your app uses the same APNS certificates/credentials for iOS notifications | ||||||||||||||||||||||||||
4. Configure the notification templates and options as needed through the playbook variables | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
### Debugging | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
If you need to troubleshoot issues: | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
1. Enable debug logs by setting: | ||||||||||||||||||||||||||
```yaml | ||||||||||||||||||||||||||
matrix_fluffygate_debug_logs: true | ||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||
ayushin marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
2. Check the container logs: | ||||||||||||||||||||||||||
```bash | ||||||||||||||||||||||||||
docker logs matrix-fluffygate | ||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||
ayushin marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
## Uninstalling | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
To remove Fluffygate, first disable it in your `inventory/host_vars/matrix.example.com/vars.yml`: | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
```yaml | ||||||||||||||||||||||||||
matrix_fluffygate_enabled: false | ||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
Then run the playbook: | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
```bash | ||||||||||||||||||||||||||
ansible-playbook -i inventory/hosts setup.yml --tags=setup-fluffygate,start | ||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
This will stop the service and remove all associated files. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"active_provider": "claude.ai", | ||
"active_organization_id": "4c1644e0-e630-48f7-bb87-4d8387ef9cd8", | ||
"active_project_id": "1d6c1d5c-5270-439c-9885-aff7168cb24d", | ||
"active_project_name": "matrix-fluffygate", | ||
"local_path": "/Users/alexis/Work/witi/witi-matrix-ansible/roles/custom/matrix-fluffygate" | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't need this. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
--- | ||
|
||
# Fluffygate is a reference Push Gateway for Matrix. | ||
# To make use of it for delivering push notificatins, you'll need to develop/build your own Matrix app. | ||
# Project source code URL: https://github.com/matrix-org/fluffygate | ||
matrix_fluffygate_enabled: true | ||
matrix_fluffygate_identifier: 'matrix-fluffygate' | ||
|
||
# App information | ||
matrix_fluffygate_app_name: "Fluffygate" | ||
matrix_fluffygate_app_website: "https://example.com" | ||
matrix_fluffygate_debug_logs: false | ||
|
||
# Notification settings | ||
matrix_fluffygate_notification_title: "{count} new messages" | ||
matrix_fluffygate_notification_body: "{body}" | ||
|
||
# Android notification options | ||
matrix_fluffygate_android_notification_options: | ||
priority: high | ||
notification: | ||
sound: "default" | ||
icon: "notifications_icon" | ||
tag: "default_notification" | ||
|
||
# APNS notification options | ||
matrix_fluffygate_apns_notification_options: | ||
headers: | ||
apns-priority: "10" | ||
payload: | ||
aps: | ||
sound: "default" | ||
badge: "{count}" | ||
mutable-content: 1 | ||
|
||
matrix_fluffygate_firebase_key: '' # JSON key file contents | ||
matrix_fluffygate_firebase_project: '' # Firebase project ID | ||
|
||
# The hostname at which Fluffygate is served. | ||
matrix_fluffygate_hostname: '' | ||
|
||
# The path at which Fluffygate is exposed. | ||
# This value must either be `/` or not end with a slash (e.g. `/fluffygate`). | ||
matrix_fluffygate_path_prefix: / | ||
|
||
# renovate: datasource=docker depName=matrixdotorg/fluffygate | ||
matrix_fluffygate_version: 1.0.3 | ||
|
||
matrix_fluffygate_base_path: "{{ matrix_base_data_path }}/fluffygate" | ||
matrix_fluffygate_config_path: "{{ matrix_fluffygate_base_path }}/config" | ||
matrix_fluffygate_data_path: "{{ matrix_fluffygate_base_path }}/data" | ||
|
||
# List of systemd services that matrix-fluffygate.service depends on. | ||
matrix_fluffygate_systemd_required_services_list: "{{ [devture_systemd_docker_base_docker_service_name] if devture_systemd_docker_base_docker_service_name else [] }}" | ||
|
||
# List of systemd services that matrix-fluffygate.service wants | ||
matrix_fluffygate_systemd_wanted_services_list: [] | ||
|
||
matrix_fluffygate_docker_image: "{{ matrix_fluffygate_docker_image_registry_prefix }}djangoflow/fluffygate:{{ matrix_fluffygate_docker_image_tag }}" | ||
matrix_fluffygate_docker_image_tag: "{{ matrix_fluffygate_version }}" | ||
matrix_fluffygate_docker_image_registry_prefix: "{{ matrix_container_global_registry_prefix }}" | ||
matrix_fluffygate_docker_image_force_pull: "{{ matrix_fluffygate_docker_image.endswith(':latest') }}" | ||
|
||
# The base container network. It will be auto-created by this role if it doesn't exist already. | ||
matrix_fluffygate_container_network: "{{ traefik_container_network }}" | ||
|
||
# A list of additional container networks that the container would be connected to. | ||
# The role does not create these networks, so make sure they already exist. | ||
# Use this to expose this container to another reverse proxy, which runs in a different container network. | ||
matrix_fluffygate_container_additional_networks: [] | ||
|
||
# Controls whether the matrix-fluffygate container exposes its HTTP port (tcp/6000 in the container). | ||
# | ||
# Takes an "<ip>:<port>" or "<port>" value (e.g. "127.0.0.1:6000"), or empty string to not expose. | ||
matrix_fluffygate_container_http_host_bind_port: '' | ||
|
||
# matrix_fluffygate_container_labels_traefik_enabled controls whether labels to assist a Traefik reverse-proxy will be attached to the container. | ||
# See `../templates/labels.j2` for details. | ||
# | ||
# To inject your own other container labels, see `matrix_fluffygate_container_labels_additional_labels`. | ||
matrix_fluffygate_container_labels_traefik_enabled: true | ||
matrix_fluffygate_container_labels_traefik_docker_network: "{{ matrix_fluffygate_container_network }}" | ||
matrix_fluffygate_container_labels_traefik_hostname: "{{ matrix_fluffygate_hostname }}" | ||
# The path prefix must either be `/` or not end with a slash (e.g. `/fluffygate`). | ||
matrix_fluffygate_container_labels_traefik_path_prefix: "{{ matrix_fluffygate_path_prefix }}" | ||
matrix_fluffygate_container_labels_traefik_rule: "Host(`{{ matrix_fluffygate_container_labels_traefik_hostname }}`){% if matrix_fluffygate_container_labels_traefik_path_prefix != '/' %} && PathPrefix(`{{ matrix_fluffygate_container_labels_traefik_path_prefix }}`){% endif %}" | ||
matrix_fluffygate_container_labels_traefik_priority: 0 | ||
matrix_fluffygate_container_labels_traefik_entrypoints: web-secure | ||
matrix_fluffygate_container_labels_traefik_tls: "{{ matrix_fluffygate_container_labels_traefik_entrypoints != 'web' }}" | ||
matrix_fluffygate_container_labels_traefik_tls_certResolver: default # noqa var-naming | ||
|
||
# Controls which additional headers to attach to all HTTP responses. | ||
# To add your own headers, use `matrix_fluffygate_container_labels_traefik_additional_response_headers_custom` | ||
matrix_fluffygate_container_labels_traefik_additional_response_headers: "{{ matrix_fluffygate_container_labels_traefik_additional_response_headers_auto | combine(matrix_fluffygate_container_labels_traefik_additional_response_headers_custom) }}" | ||
matrix_fluffygate_container_labels_traefik_additional_response_headers_auto: {} | ||
matrix_fluffygate_container_labels_traefik_additional_response_headers_custom: {} | ||
|
||
# matrix_fluffygate_container_labels_additional_labels contains a multiline string with additional labels to add to the container label file. | ||
# See `../templates/labels.j2` for details. | ||
# | ||
# Example: | ||
# matrix_fluffygate_container_labels_additional_labels: | | ||
# my.label=1 | ||
# another.label="here" | ||
matrix_fluffygate_container_labels_additional_labels: '' | ||
|
||
# A list of extra arguments to pass to the container | ||
matrix_fluffygate_container_extra_arguments: [] | ||
|
||
matrix_fluffygate_metrics_prometheus_enabled: false | ||
|
||
# Default Fluffygate configuration template which covers the generic use case. | ||
# You can customize it by controlling the various variables inside it. | ||
# | ||
# For a more advanced customization, you can extend the default (see `matrix_fluffygate_configuration_extension_yaml`) | ||
# or completely replace this variable with your own template. | ||
matrix_fluffygate_configuration_yaml: "{{ lookup('template', 'templates/config.yaml.j2') }}" | ||
|
||
matrix_fluffygate_configuration_extension_yaml: | | ||
# Your custom YAML configuration for Fluffygate goes here. | ||
# This configuration extends the default starting configuration (`matrix_fluffygate_configuration_yaml`). | ||
# | ||
# You can override individual variables from the default configuration, or introduce new ones. | ||
# | ||
# If you need something more special, you can take full control by | ||
# completely redefining `matrix_fluffygate_configuration_yaml`. | ||
# | ||
# Example configuration extension follows: | ||
# metrics: | ||
# opentracing: | ||
# enabled: true | ||
|
||
matrix_fluffygate_configuration_extension: "{{ matrix_fluffygate_configuration_extension_yaml | from_yaml if matrix_fluffygate_configuration_extension_yaml | from_yaml is mapping else {} }}" | ||
|
||
# Holds the final fluffygate configuration (a combination of the default and its extension). | ||
# You most likely don't need to touch this variable. Instead, see `matrix_fluffygate_configuration_yaml`. | ||
matrix_fluffygate_configuration: "{{ matrix_fluffygate_configuration_yaml | from_yaml | combine(matrix_fluffygate_configuration_extension, recursive=True) }}" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
--- | ||
|
||
- name: Ensure Fluffygate paths exists | ||
ansible.builtin.file: | ||
path: "{{ item }}" | ||
state: directory | ||
mode: 0750 | ||
owner: "{{ matrix_user_username }}" | ||
group: "{{ matrix_user_groupname }}" | ||
with_items: | ||
- "{{ matrix_fluffygate_base_path }}" | ||
- "{{ matrix_fluffygate_config_path }}" | ||
- "{{ matrix_fluffygate_data_path }}" | ||
|
||
- name: Ensure Fluffygate config installed | ||
ansible.builtin.copy: | ||
content: "{{ matrix_fluffygate_configuration | to_nice_yaml(indent=2, width=999999) }}" | ||
dest: "{{ matrix_fluffygate_config_path }}/config.yaml" | ||
mode: 0640 | ||
owner: "{{ matrix_user_username }}" | ||
group: "{{ matrix_user_groupname }}" | ||
|
||
- name: Ensure Firebase key file is created when enabled | ||
ansible.builtin.copy: | ||
content: "{{ matrix_fluffygate_firebase_key }}" | ||
dest: "{{ matrix_fluffygate_data_path }}/firebase-key.json" | ||
mode: 0600 | ||
owner: "{{ matrix_user_username }}" | ||
group: "{{ matrix_user_groupname }}" | ||
when: matrix_fluffygate_firebase_key != '' | ||
|
||
- name: Ensure Fluffygate labels installed | ||
ansible.builtin.template: | ||
src: "{{ role_path }}/templates/labels.j2" | ||
dest: "{{ matrix_fluffygate_base_path }}/labels" | ||
mode: 0640 | ||
owner: "{{ matrix_user_username }}" | ||
group: "{{ matrix_user_groupname }}" | ||
|
||
- name: Ensure Fluffygate image is pulled | ||
community.docker.docker_image: | ||
name: "{{ matrix_fluffygate_docker_image }}" | ||
source: "{{ 'pull' if ansible_version.major > 2 or ansible_version.minor > 7 else omit }}" | ||
force_source: "{{ matrix_fluffygate_docker_image_force_pull if ansible_version.major > 2 or ansible_version.minor >= 8 else omit }}" | ||
force: "{{ omit if ansible_version.major > 2 or ansible_version.minor >= 8 else matrix_fluffygate_docker_image_force_pull }}" | ||
register: result | ||
retries: "{{ devture_playbook_help_container_retries_count }}" | ||
delay: "{{ devture_playbook_help_container_retries_delay }}" | ||
until: result is not failed | ||
|
||
- name: Ensure Fluffygate container network is created | ||
community.general.docker_network: | ||
enable_ipv6: "{{ devture_systemd_docker_base_ipv6_enabled }}" | ||
name: "{{ matrix_fluffygate_container_network }}" | ||
driver: bridge | ||
driver_options: "{{ devture_systemd_docker_base_container_networks_driver_options }}" | ||
|
||
- name: Ensure matrix-fluffygate.service installed | ||
ansible.builtin.template: | ||
src: "{{ role_path }}/templates/systemd/matrix-fluffygate.service.j2" | ||
dest: "{{ devture_systemd_docker_base_systemd_path }}/matrix-fluffygate.service" | ||
mode: 0644 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
--- | ||
|
||
- tags: | ||
- setup-all | ||
- setup-fluffygate | ||
- install-all | ||
- install-fluffygate | ||
block: | ||
- when: matrix_fluffygate_enabled | bool | ||
ansible.builtin.include_tasks: "{{ role_path }}/tasks/validate_config.yml" | ||
|
||
- when: matrix_fluffygate_enabled | bool | ||
ansible.builtin.include_tasks: "{{ role_path }}/tasks/install.yml" | ||
|
||
- tags: | ||
- setup-all | ||
- setup-fluffygate | ||
block: | ||
- when: not matrix_fluffygate_enabled | bool | ||
ansible.builtin.include_tasks: "{{ role_path }}/tasks/uninstall.yml" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It may be useful to also mention Sygnal here (
docs/configuring-playbook-sygnal.md
) here and mention Fluffygate on the Sygnal docs page as well.If this "mention" is also a brief comparison as to when one might use one or the other, it'd be even better. It seems like Sygnal is supports direct delivery via APNS , while Fluffygate only supports FCM? Maybe this makes setup easier as all platform-specific setup would happen on the FCM side?