Skip to content

Latest commit

 

History

History
198 lines (161 loc) · 10 KB

File metadata and controls

198 lines (161 loc) · 10 KB

Introduction

Uniqush (\ˈyü-nə-ku̇sh\ "uni" pronounced as in "unified", and "qush" pronounced as in "cushion") is a free and open source software system which provides a unified push service for server side notification to apps on mobile devices. The uniqush-push API abstracts the APIs of the various push services used to send push notifications to those devices. By running uniqush-push on the server side, you can send push notifications to any supported mobile platform.

CI

⚠️ Status: read before deploying

This project was dormant from 2020 to 2026, and in that time some of the upstream APIs it depends on were shut down.

  • APNs — repaired, but not yet verified against Apple's servers. As of the unreleased version it uses the HTTP/2 API by default and sends the apns-push-type header that iOS 13+ requires. Earlier releases defaulted to the binary protocol, which Apple switched off on 31 March 2021, and could not deliver at all.

    These changes are covered by unit tests against a mocked APNs, but nobody has yet run them against real Apple credentials and a real device, because the current maintainer does not have an Apple developer account. If you do, a report either way would be genuinely useful — please open an issue.

  • FCM — migrated to HTTP v1, but not yet verified against Google. The legacy endpoint it used was decommissioned on 20 June 2024. /addpsp now takes projectid and credentialsfile instead of apikey; devices do not need to re-subscribe. Covered by unit tests against a mocked FCM, but nobody has run it against a real Firebase project yet. gcm is now an alias for the same backend.

  • ADM is believed to still work, but has not been re-verified.

  • UnifiedPush / Web Push — new, and the one backend with no vendor dependency. See below.

Building requires Go 1.25 or newer.

Supported Platforms

  • FCM from Google for the Android platform (gcm is an alias)
  • APNS from Apple for the iOS platform
  • ADM from Amazon for Kindle tablets
  • UnifiedPush / Web Push, for de-Googled Android, Linux desktops and browsers

UnifiedPush / Web Push

UnifiedPush is a decentralised push standard: the user picks the push provider rather than the app developer, and it works on devices with no Google services at all. Its application-server side is plain Web Push — RFC 8030 delivery, RFC 8291 aes128gcm payload encryption and RFC 8292 VAPID authentication — so the same backend also drives browser Web Push.

It is registered under two names, webpush and unifiedpush. They behave identically; pick one per service and stay with it, since the name is part of a subscription's identity in the database.

Unlike the other backends, this one needs no vendor account and no certificate.

1. Generate a VAPID key pair. These identify your server to push providers. Some providers reject registrations without them.

$ uniqush-push -generate-vapid-keys
vapidpublickey=BIknD72EXwC1CC5WamGPDn4YbTV7o6yE_zMNNJO2xNMGyy4sz6egSmwFhH8lxllQqvqInrkqyKwnuy1Q1vmkevk
vapidprivatekey=NOHiudJNUw6IEf0SN0jYTascVt68R0sQJxMWSbVRWM4

2. Create the push service provider. subscriber is the VAPID contact — a bare email address or an https:// URL, not a mailto: URI.

curl http://localhost:9898/addpsp \
  -d service=myservice \
  -d pushservicetype=unifiedpush \
  -d vapidpublickey=BIknD72... \
  -d vapidprivatekey=NOHiudJ... \
  -d subscriber=admin@example.org

3. Subscribe a device. The app's UnifiedPush connector library produces all three values; your app just forwards them to your server.

curl http://localhost:9898/subscribe \
  -d service=myservice \
  -d subscriber=alice \
  -d pushservicetype=unifiedpush \
  -d endpoint=https://ntfy.sh/up?id=... \
  -d p256dh=BNcRdreALRFXTkOO... \
  -d auth=tBHItJI5svbpez7KI4CCXg

4. Push. Payload fields are JSON-encoded and delivered encrypted; the app on the device decrypts them. Pass uniqush.payload.webpush instead to send a raw body verbatim.

curl http://localhost:9898/push -d service=myservice -d subscriber=alice -d msg=hello

A note on SSRF

For every other backend the destination host is a constant compiled into uniqush. Here it comes from whoever called /subscribe, so uniqush refuses by default to POST to addresses that are not globally routable — loopback, RFC 1918, link-local (including the 169.254.169.254 cloud metadata endpoint), and the IPv6 equivalents. Redirects are never followed, and the check runs before every push rather than only at subscribe time, so DNS rebinding does not defeat it.

Self-hosted push servers on a private network are a supported UnifiedPush setup, so this can be relaxed per service in uniqush-push.conf with allow_private_addresses, ideally alongside an allowed_hosts list.

FAQ

  • Q: Is this a general push notification platform for all types of devices? How does this differ from services such as Urban Airship?

  • A: Urban Airship is a great service, and there are other similar services available, like OpenPush, Notificare, etc. All of them are wonderful services. However, Uniqush is different from them. Uniqush is not a service. Instead, Uniqush is a system, which runs on your own server. In fact, if you wish, you can use Uniqush to set up a service similar to Urban Airship.

  • Q: OK. Then is it a library? Like java-apns?

  • A: Well.. Not actually. I mean, it is a program, like Apache HTTP Server. You download it, you run it. It does require a Redis server, but, other than that, you don't need to worry about which language to use, package dependencies, etc.

  • Q: But wait, how can I use it anyway? I mean, if my program wants to send a push notification, I need to tell Uniqush about this action. How can I communicate with Uniqush? There must be some library so that I can use it in my program to talk with Uniqush, right?

  • A: We are trying to make it easier. uniqush-push provides RESTful APIs. In other words, you talk with uniqush-push through HTTP protocol. As long as there's an HTTP client library for your language, you can use it and talk with uniqush-push. For details about our RESTful APIs, see our API documentation.

  • Q: Then that's cool. But I noticed that you are using Go programming language. Do I need to install Go compiler and other stuff to run uniqush-push?

  • A: No. There are no installation dependencies. All you need to do is to download the binary file from the download page and install it. But you do need to set up a Redis server running somewhere, preferably with persistence, so that uniqush-push can store the user data in Redis. For more details, see the installation guide

  • Q: This is nice. I want to give it a try. But you are keep talking about uniqush-push, and I'm talking about Uniqush, are they the same thing?

  • A: Thank you for your support! Uniqush is intended to be the name of a system which provides a full stack solution for communication between mobile devices and the app's server. uniqush-push is one piece of the system. However, right now, uniqush-push is the only piece and others are under active development. If you want to know more details about the Uniqush system's plan, you can read the blog post. If you want to find out about the latest progress with Uniqush, please check out our blog. And, if you are really impatient, there's always our our GitHub account which could have brand-new stuff that hasn't been released yet.

Setting Up Redis

Redis persistence describes the details of how Redis saves data on shutdown, as well as how one might back up that data. Make sure that the Redis server you use has persistence enabled - your redis.conf should have contents similar to the section **PERSISTENCE** of redis.conf in the example config files linked in http://redis.io/topics/config

Contributing

You're encouraged to contribute to the uniqush-push project. There are two ways you can contribute.

Issues

If you encounter an issue while using uniqush-push, please report it at the project's issues tracker. Feature suggestions are also welcome.

Pull request

Code contributions to uniqush-push can be made using pull requests. To submit a pull request:

  1. Fork this project.
  2. Make and commit your changes.
  3. Submit your changes as a pull request.

Related Links