No description
  • Go 92.2%
  • Makefile 5.5%
  • Dockerfile 2.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Felipe M. 79b1005bdf
All checks were successful
CI / format (push) Successful in 43s
CI / goreleaser-lint (push) Successful in 23s
CI / test (push) Successful in 2m47s
CI / build (push) Successful in 1m39s
CI / lint (push) Successful in 5m19s
Authenticate the setup actions against the GitHub API
setup-go, setup-node and setup-bun resolve versions through
api.github.com. Anonymously that is sixty requests an hour for the
whole runner host, and the jobs started failing on it. GH_API_TOKEN is
a read-only GitHub token held as a Forgejo secret.

Where the secret is absent the input is empty and the action falls back
to an anonymous request, exactly as before.
2026-09-22 12:54:19 +02:00
.github/workflows Authenticate the setup actions against the GitHub API 2026-09-22 12:54:19 +02:00
config feat: add Mattermost push proxy prefix router 2026-07-26 10:03:43 +02:00
.gitignore feat: add Mattermost push proxy prefix router 2026-07-26 10:03:43 +02:00
.goreleaser.yml feat: add Mattermost push proxy prefix router 2026-07-26 10:03:43 +02:00
AGENTS.md feat: include Go runtime and process metrics on /metrics 2026-07-27 08:39:11 +02:00
config.go feat: add Sentry observability 2026-07-28 18:16:24 +02:00
Containerfile feat: add Mattermost push proxy prefix router 2026-07-26 10:03:43 +02:00
Containerfile.dev feat: add Mattermost push proxy prefix router 2026-07-26 10:03:43 +02:00
docker-compose.yml feat: add Mattermost push proxy prefix router 2026-07-26 10:03:43 +02:00
go.mod feat: add Sentry observability 2026-07-28 18:16:24 +02:00
go.sum feat: add Sentry observability 2026-07-28 18:16:24 +02:00
logger.go feat: add Sentry observability 2026-07-28 18:16:24 +02:00
main.go fix: report startup and listen panics to Sentry 2026-07-30 11:33:12 +02:00
main_test.go fix: report startup and listen panics to Sentry 2026-07-30 11:33:12 +02:00
Makefile Give golangci-lint five minutes 2026-09-22 12:48:50 +02:00
metrics.go fix: avoid duplicate Prometheus collector registration on startup 2026-07-30 12:01:02 +02:00
metrics_test.go fix: avoid duplicate Prometheus collector registration on startup 2026-07-30 12:01:02 +02:00
proxy.go feat: add Sentry observability 2026-07-28 18:16:24 +02:00
README.md feat: add Sentry observability 2026-07-28 18:16:24 +02:00
router.go feat: add Mattermost push proxy prefix router 2026-07-26 10:03:43 +02:00
router_test.go feat: add Mattermost push proxy prefix router 2026-07-26 10:03:43 +02:00
sentry.go fix: report startup and listen panics to Sentry 2026-07-30 11:33:12 +02:00
sentry_test.go feat: add Sentry observability 2026-07-28 18:16:24 +02:00
server.go fix: report startup and listen panics to Sentry 2026-07-30 11:33:12 +02:00
server_test.go fix: report startup and listen panics to Sentry 2026-07-30 11:33:12 +02:00
spec.md feat: add Mattermost push proxy prefix router 2026-07-26 10:03:43 +02:00

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:<token>) 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

Run locally

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://<router-host>:8066.

Docker Compose

The included docker-compose.yml runs the router plus a placeholder push-proxy backend:

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:

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
SENTRY_DSN Enables Sentry error reporting and tracing
SENTRY_ENVIRONMENT Sentry environment name
SENTRY_RELEASE Sentry release identifier (defaults to the build version)
SENTRY_TRACES_SAMPLE_RATE Performance trace sampling rate (default: 0.1; set to 0 to disable)
SENTRY_ATTACH_STACKTRACE Attach stack traces to Sentry events (default: true)
SENTRY_DEBUG Enable Sentry SDK debug output (default: false)

API

Compatible with the Mattermost push notification 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

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

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

MM_EMAILSETTINGS_SENDPUSHNOTIFICATIONS=true
MM_EMAILSETTINGS_PUSHNOTIFICATIONCONTENTS=id_loaded
MM_EMAILSETTINGS_PUSHNOTIFICATIONSERVER=http://router-host:8066

License

MIT