# Mattermost Push Proxy Router A small, stateless Go service that routes Mattermost push notifications by mobile client platform prefix. It lets a single `PushNotificationServer` URL serve both a custom mobile app (e.g. Bubbles) and the official Mattermost mobile apps on the same server. ## Why Mattermost allows only **one** push notification server URL per instance. The stock push proxy routes by platform prefix (`apple_rn`, `android_rn`, …) and drops anything it cannot handle. A custom client registers under its own prefix (e.g. `apple_bubbles:`) and needs its own APNs key/topic — but official app users on the same server still need HPNS. This router sits in front of unmodified backends: ``` Mattermost server └─ PushNotificationServer └─ [router :8066] ├─ apple_bubbles:* → your mattermost-push-proxy (custom APNs key) └─ apple_rn:* / android_rn:* → HPNS relay ``` ## Features - Implements the Mattermost push proxy API (`/api/v1/send_push`, `/api/v1/ack`) - Routes by `platform` prefix extracted from the JSON payload - Relays official app traffic to HPNS unchanged - Forwards custom app traffic to a stock `mattermost-push-proxy` instance - Single static binary with TOML-based configuration - Docker and GoReleaser ready - Prometheus metrics at `/metrics` ## Quick Start ### Prerequisites - Go 1.26+ - A running [mattermost-push-proxy](https://github.com/mattermost/mattermost-push-proxy) for your custom app (with your APNs `.p8` key) ### Run locally ```bash cp config/router.toml.example config/router.toml # Edit config/router.toml with your route prefixes and backend URLs make build CONFIG_FILE=config/router.toml ./mattermost-push-proxy-router ``` Point your Mattermost server's `EmailSettings.PushNotificationServer` at `http://:8066`. ### Docker Compose The included `docker-compose.yml` runs the router plus a placeholder push-proxy backend: ```bash cp config/router.toml.example config/router.toml cp config/mattermost-push-proxy.json.example config/mattermost-push-proxy.json # Edit both config files for your deployment docker compose up -d ``` ## Configuration Routes are defined in a TOML config file — there are no built-in prefix defaults. Set `CONFIG_FILE` to a TOML file: ```toml listen = ":8066" request_timeout_sec = 60 [[routes]] prefixes = ["apple_bubbles"] url = "http://bubbles-proxy:8067" [[routes]] prefixes = ["apple_rn", "android_rn"] url = "https://push.mattermost.com" ``` See `config/router.toml.example`. | Variable | Description | | --- | --- | | `CONFIG_FILE` | Path to router TOML config (required) | | `PORT` | Overrides `listen` from the config file | | `REQUEST_TIMEOUT_SEC` | Overrides upstream timeout | ## API Compatible with the [Mattermost push notification service](https://developers.mattermost.com/contribute/more-info/mobile/push-notifications/service/) protocol: | Endpoint | Method | Description | | --- | --- | --- | | `/api/v1/send_push` | POST | Route a push notification to the correct backend | | `/api/v1/ack` | POST | Route a delivery acknowledgement | | `/version` | GET | Service version | | `/health` | GET | Health check | | `/metrics` | GET | Prometheus metrics | ### Example ```bash curl http://127.0.0.1:8066/api/v1/send_push \ -X POST \ -H "Content-Type: application/json" \ -d '{ "type": "message", "platform": "apple_bubbles", "server_id": "YOUR_DIAGNOSTIC_ID", "device_id": "YOUR_APNS_TOKEN", "channel_id": "CHANNEL_ID", "post_id": "POST_ID", "is_id_loaded": true }' ``` ## Building ```bash make help # Show all targets make build # Production binary make test # Unit tests make format # Format Go source make lint # Run linter make build-snapshot # Cross-platform builds via goreleaser ``` ## Mattermost Server Setup ```bash MM_EMAILSETTINGS_SENDPUSHNOTIFICATIONS=true MM_EMAILSETTINGS_PUSHNOTIFICATIONCONTENTS=id_loaded MM_EMAILSETTINGS_PUSHNOTIFICATIONSERVER=http://router-host:8066 ``` ## License MIT