fpush
is a scalable push server for XMPP implemetingXEP-0357.
fpush
can be connected to any XMPP server as a XMPP component using XEP-0114.
- Features
- Usage
- XMPP API
- Configuration
- Structure
- Clustering
- Compilation
- Compilation Flags
- Expandability
- Systemd
- Supported push platforms
- Apple APNS
- Google FCM
- Multi app / platform support on a single XMPP domain/JID
- Configurable token ratelimiting
./fpush settings.json
This appserver implements XEP-0357 commands for sending actual push notifications.
fpush
does not require devices to register for push before usage like other appserver implementations.
fpush
expects each push IQ to include the push token of the device to be woken up, as well as the info to which push module the token applies.
Hence, push messages can be enabled by a client at their XMPP server as follows:
<iq type='set' id='x43'>
<enable xmlns='urn:xmpp:push:0' jid='###pushServerComponentJid###' node='###DevicePushToken###'>
<x xmlns='jabber:x:data' type='submit'>
<field var='FORM_TYPE'><value>http://jabber.org/protocol/pubsub#publish-options</value></field>
<field var='pushModule'><value>##pushModuleName###</value></field>
</x>
</enable>
</iq>
If the pushModule
identifier is missing in the publish-options, fpush
will instead selected the default push module as configured.
{
"component": {
"componentHostname": "<ComponentJid>",
"componentKey": "ARandomComponentKeySetInsideTheXMPPServer",
"serverHostname": "<XMPP-Server>",
"serverPort": <XMPP-Server Component Port>
},
"pushModules": { // map of configured push modules
"monalProdiOS": { // push module identifier that is later set inside the push iqs as "pushModule"
"type": "apple", // push module type
"is_default_module": true, // Use this push module in case no pushModule was defined in a push iq msg
"apns": {
"certFilePath": "<Path to p12 file>",
"certPassword": "<cert password>",
"topic": "<app bundle id>"
},
"ratelimit": {
"ratelimitTime": "20s", // minimal duration between two pushes
"ratelimitCleanupInterval": "300s", // time how long old and unseen tokens should be keept inside the ratelimit cache before removal
"enabled": true // optionally disable ratelimit. Not advised for apple apns
}
},
"someAndroidApp": {
"type": "google",
"is_default_module": false,
"fcm": {
"fcmSecretPath": "<Path to json from google>"
}
},
},
"timeout": {
"xmppconnectionError": "20s" // time to wait after XMPP component connection failed before reconnecting
}
}
The configuration file consists of three sections.
XMPP component settings (component
) the push module configurations (pushModules
) and a timeout config for the xmpp connection (timeout
).
This section describes all config parameters for the XMPP component connection to the XMPP server handling all S2S connections.
JID of the pushserver. Must match the component JID configured on the XMPP server.
The component handshake element as configured on the XMPP server
Hostname or IP address of the XMPP component endpoint (Usually the XMPP server that handles all S2S connections)
Port of the XMPP component endpoint configured on the XMPP server.
Map of all push modules that should be loaded on start.
Each push module can either be for apple APNS or for googles FCM.
Each push module is identified by the key specified in the map.
This identifier is later used by clients to specifiy which of the configured push modules should be selected when an XMPP IQ is received by fpush
.
Each push module consists of a type
element.
Currently apple
and google
are supported.
If set to true, this push modules is used if an XMPP IQ was received that does not include any push module identifier. Only one push module can be configured as the default module.
Ratelimits for push tokens can be configured per push module.
Enable or disable ratelimiting for tokens It is not advised to disable the ratelimiting
Minimal time between pushes for each push token.
If two push IQs are received for the same token within less time, the latter one is queued.
If more push request arrive for a token, while one push request is already queued, all further requests are ignored and an wait IQ is replied until the configured ratelimitTime
is over.
fpush
caches the last timestamp when an push messages was sent for an token per push module to implement the ratelimit.
This cache is cleaned every 300 seconds.
On each cleaning run, tokens that were send more than ratelimitCleanupInterval
ago are removed to free up memory space.
This section describes all apns related push options.
Path to the p12 certificate that should be used to connect to the APNS API.
Passwort of the p12 certificate.
Bundle ID of the main app.
APNS environment to use. Supports production
and sandbox
. Default: production
This section describes all fcm related push options.
Path to the fcm json file created by google.
Time to wait after XMPP component connection failed before reconnecting
Fpush connects to a single XMPP server, that handles all S2S connections, as a XMPP component using an unencrypted connection.
We thus recommend to either place fpush
on the same system as the XMPP server or securing the connection between the systems using IPsec
or wireguard
.
If the XMPP server is unreachable fpush
will automatically try to reconnect after the configured time.
fpush
can be clustered by simply running multiple servers on the same XMPP domain.
Using SRV records S2S traffic can be steered between the servers.
fpush
currently does not exchange ratelimit information betweeen cluster nodes.
Instead each node manages its own independent ratelimit.
Hence, devices that are registered on more than on XMPP server may, receive push notifications via more than one cluster more frequent than expected.
fpush
is written in Rust. (https://www.rust-lang.org/tools/install)
cargo build
cargo build --release
fpush
supports several features that can be activated while building using the --features <Flag1>,<Flag2>
flag.
Currently the following features are enabled by default.
random_delay_before_push
enable_apns_support
enable_fcm_support
The default features can be disabled using --no-default-features
.
Remove all log messages lower than "WARN" from binary to increase speed.
Remove all log messages lower than "INFO" from binary to increase speed.
Push modules support for different push vendors can be enabled during compilation. For improved performance it is adviced to only enable/compile the needed push modules types (e.g. only apns).
Enable google fcm support for android devices.
Enable apple apns support for iOS, iPadOS and macOS devices.
Enable a simple demo push endpoint used during development.
Improve ratelimit acurracy by waiting a random delay before handling each push message.
For each incomming push event fpush spawns a new tokio thread. Within each thread fpush checks if the supplied token is blocked or if the token is ratelimited. After a push message was sent for a token, fpush ratelimits the token (if configured) for a configured time to reduce the battery consumption of the remote device. Due to the multi thread design, two directly consecutive push events for the same token may not be correctly ratelimited. Hence, adding a random async delay helps to improve the accuracy while keeping memory and cpu consumption low.
Fpush can easily be expanded to support further push platforms by creating a new crate implementing the PushTrait
.
We recommend running fpush
as a seperate user without root permissions.
[Unit]
Description=Fpush
After=network.target
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=always
RestartSec=10
User=fpush
Group=fpush
LimitNOFILE=131072
WorkingDirectory=/opt/fpush/
Environment=RUST_LOG=info
ExecStart=/opt/fpush/fpush settings.json
[Install]
WantedBy=multi-user.target