Relays WebPush messages through firebase to allow them to be received by mobile applications. This was built for my Mastodon client but is pretty general.
- Supports both rfc8291 and the draft rfc encryption standards.
- Supports multiple client applications.
- Includes a client android library for easy setup.
Your first step should be to figure out you are authenticating with Firebase. If you aren't familiar with the process
you can follow along here. For the rest of this section we'll assume you have a service
account key json saved in ./credentials/firebase-key.json
You can download the jar and run directly. This requires java 21+.
java -jar webpush-fcm-relay.jar -port=8080 -P:firebase.auth.credentialsDir=./credentials
Images are published to dockerhub.
docker run -p 8080:8080 -v ./credentials:/credentials:ro docker.io/etatarka/webpush-fcm-relay:latest -port=8080 -P:firebase.auth.credentialsDir=./credentials
There's a docker-compose.yaml file in this repo that you can use as an example.
docker-compose up
All methods take the same arguments:
-port=
(required) sets the port the server is run on-host=0.0.0.0
sets the host address the server is run on-P:firebase.auth.credentialsDir=
sets the directory to looks for firebase credentials, multiple credentials with different project-id's are allowed in that directory.
In addition, the following jvm arguments can be set:
-Dlog.level=INFO
set the level of logging. The default is very conservative, setting this to at least DEBUG will cause requests to be logged.
Note: As the server will require https to handle web pushes properly, you'll want to set up a reverse proxy and ssl certificate. There's a lot of ways to do this, and I'd recommend starting with Let's Encrypt's clients.
Start by setting up Firebase Cloud Messaging in your
project. Note: I recommend skipping the com.google.gms.google-services
plugin as it's not well maintained. Instead you
can create a resources file with the following values that can be found in your Firebase project's console or in the
google-services.json file you can download.
<resources>
<string name="google_app_id">1:0000000000000:android:0000000000000000000000</string>
<string name="project_id">projectid</string>
<string name="google_api_key">000000000000000000000000000000000000000</string>
</resources>
Then add the client-android
dependency to your build.gradke(.kts)
dependencies {
implementation("me.tatarka.webpush.relay:client-android:1.0.0")
}
Make your push service extend me.tatarka.webpush.relay.WebPushRelayService
instead of
com.google.firebase.messaging.FirebaseMessagingService.FirebaseMessagingService
and implement the required methods.
class MyWebPushService : WebPushRelayService() {
override suspend fun register(path: String, publicKey: ByteString, authSecret: ByteString) {
// This is where you'd register with the service that's sending the web pushes. The url should be the domain of
// your relay server + the path given here. Ex: https://relay.example.com/ + path
}
override suspend fun onWebPushReceived(body: Source) {
// This is where you decode the body and optionally show a notification to the user.
}
}
Pros:
- Written in Go
- Low memory usage
- Very simple implementation
Cons:
- Unclear licencing
- Non-standard message encoding
- Only supports pre-standard WebPush encryption
- Only supports a single client application
Pros:
- Written in Rust
- Designed to handle millions of push messages
- Supports all WebPush encryption standards
- Supports multiple client applications
Cons:
- Not well documented
- Existing storage backends are propitiatory