MongoosePush is simple (seriously) REST service written in Elixir providing ability to send push
notification to FCM
(Firebase Cloud Messaging) and/or
APNS
(Apple Push Notification Service) via their HTTP/2
API.
We provide already builded MongoosePush images. If you just want to use it, then all you need is docker
, FCM
app token and/or APNS
app certificates.
In case of certificates you need setup the following directory structure:
- priv/
- ssl/
- rest_cert.pem - The REST endpoint certificate
- rest_key.pem - private key for the REST endpoint certificate (has to be unencrypted)
- apns/
- prod_cert.pem - Production APNS app certificate
- prod_key.pem - Production APNS app certificate's private key (has to be unencrypted)
- dev_cert.pem - Development APNS app certificate
- dev_key.pem - Development APNS app certificate's private key (has to be unencrypted)
- ssl/
Assuming that your FCM
app token is "MY_FCM_SECRET_TOKEN" and you have the priv
directory with all ceriticates in current directory, then you may start MongoosePush with the following command:
docker run -v `pwd`/priv:/opt/app/priv \
-e PUSH_FCM_APP_KEY="MY_FCM_SECRET_TOKEN" \
-e PUSH_HTTPS_CERTFILE="/opt/app/priv/ssl/rest_cert.pem" \
-e PUSH_HTTPS_KEYFILE="/opt/app/priv/ssl/rest_key.pem" \
-it --rm mongooseim/mongoose-push:latest
Building docker is really easy, just type:
MIX_ENV=prod mix do docker.build, docker.release
As a result of this command you get access to mongoose_push:release
docker image. You may run it by typing:
docker run -it --rm mongoose_push:release foreground
Docker image that you have just builded, exposes the port 8443
for the REST API of
MongoosePush. Also there is a VOLUME
for path /opt/app where the whole MongoosePush release is stored. This volume will be handy for injecting APNS
and REST API certificates.
The docker image of MongoosePush contains common, basic configuration that is generated from config/prod.exs
. All useful options may be overridden via system environmental variables. Below theres a full list of the variables you may set while running docker (via docker -e
switch), but if theres something you feel, you need to change other then that, then you need to prepare your own config/prod.exs
before image build.
Environmental variables to configure production release:
PUSH_HTTPS_BIND_ADDR
- Bind IP address of the REST endpoint. Default value in prod release is "127.0.0.1", but docker overrides this with "0.0.0.0"PUSH_HTTPS_PORT
- The port of the MongoosePush REST endpoint. Please not that docker exposes only8443
port, so changing this setting is not recommendedPUSH_HTTPS_KEYFILE
- Path to PEM keyfile used for REST endpointPUSH_HTTPS_CERTFILE
- Path to PEM certfile used for REST endpointPUSH_HTTPS_ACCEPTORS
- Number of TCP acceptors to start
PUSH_LOGLEVEL
-debug
/info
/warn
/error
- Log level of the application.info
is the default onePUSH_FCM_ENABLED
-true
/false
- Enable or disableFCM
support. Enabled by defaultPUSH_APNS_ENABLED
-true
/false
- Enable or disableAPNS
support. Enabled by default
PUSH_FCM_ENDPOINT
- Hostname ofFCM
service. Set only for local testing. By default this option points to the Google's official hostnamePUSH_FCM_APP_KEY
- App key token to use withFCM
servicePUSH_FCM_POOL_SIZE
- Connection pool size forFCM
service
PUSH_APNS_DEV_ENDPOINT
- Hostname ofAPNS
service. Set only for local testing. By default this option points to the Apple's official hostnamePUSH_APNS_DEV_CERT
- Path Apple's development certfile used to communicate withAPNS
PUSH_APNS_DEV_KEY
- Path Apple's development keyfile used to communicate withAPNS
PUSH_APNS_DEV_USE_2197
-true
/false
- Enable or disable use of alternative2197
port forAPNS
connections in development mode. Disabled by defaultPUSH_APNS_DEV_POOL_SIZE
- Connection pool size forAPNS
service in development modePUSH_APNS_DEV_DEFAULT_TOPIC
- DefaultAPNS
topic to be set if the client app doesn't specify it with the API call. If this option is not set, MongoosePush will try to extract this value from the provided APNS certificate (the first topic will be assumed default). DEV certificates normally don't provide any topics, so this option can be safely left unset
PUSH_APNS_PROD_ENDPOINT
- Hostname ofAPNS
service. Set only for local testing. By default this option points to the Apple's official hostnamePUSH_APNS_PROD_CERT
- Path Apple's production certfile used to communicate withAPNS
PUSH_APNS_PROD_KEY
- Path Apple's production keyfile used to communicate withAPNS
PUSH_APNS_PROD_USE_2197
-true
/false
- Enable or disable use of alternative2197
port forAPNS
connections in production mode. Disabled by defaultPUSH_APNS_PROD_POOL_SIZE
- Connection pool size forAPNS
service in production modePUSH_APNS_PROD_DEFAULT_TOPIC
- DefaultAPNS
topic to be set if the client app doesn't specify it with the API call. If this option is not set, MongoosePush will try to extract this value from the provided APNS certificate (the first topic will be assumed default)
- Elixir 1.4+ (http://elixir-lang.org/install.html)
- Rebar3 (just enter
mix local.rebar
)
Build step is really easy. Just type in root of the repository:
MIX_ENV=prod mix do deps.get, compile, certs.dev, release
After this step you may try to run the service via:
_build/prod/rel/mongoose_push/bin/mongoose_push console
Yeah, I know... It crashed. Running this service is fast and simple but unfortunately you can't have push notifications without properly configured FCM
and/or APNS
service. So, lets configure it!
The whole configuration is contained in file config/{prod|dev|test}.exs
depending on which MIX_ENV
you will be using. You should use MIX_ENV=prod
for production installations and MIX_ENV=dev
for your development. Anyway, lets take a look on config/dev.exs
, part by part.
config :maru, MongoosePush.Router,
versioning: [
using: :path
],
https: [
ip: {127, 0, 0, 1},
port: 8443,
keyfile: "priv/ssl/fake_key.pem",
certfile: "priv/ssl/fake_cert.pem",
otp_app: :mongoose_push
]
This part of configuration relates only to REST
endpoints that MongoosePush
exposes. Here you can set bind IP adress (option: ip
), port and paths to you HTTP
TLS
certificates. You should ignore other options unless you know what you're doing or you're going to get to know by reading maru's documentation.
You may entirely skip the maru
config entry to disable REST
API and just use this project as Elixir
library.
Lets take a look at sample FCM
service configuration:
config :mongoose_push, fcm: [
default: [
key: "fake_app_key",
pool_size: 5,
mode: :prod
]
]
Here we can see definition of a pool. Each pool has a name and its configuration. You may have several named pools of different sizes and with different configurations. Currently the only reason you may want to do this is that, the REST
client may switch between them by specifying matching :mode
in their push request.
Each FCM
pool may be configured by setting the following fields:
- key (required) - you
FCM
Application Key for using Googles API - pool_size (required) - maximum number of used
HTTP/2
connections to google's service - mode (either
:prod
or:dev
) - pool's mode.REST
client may select pool used to push his notification by specifying matching option in his request - endpoint (optional) - URL override for
FCM
service. Useful mainly in tests
You may entirely skip the FCM
config entry to disable FCM
support.
Lets take a look at sample APNS
service configuration:
config :mongoose_push, apns: [
dev: [
cert: "priv/apns/dev_cert.pem",
key: "priv/apns/dev_key.pem",
mode: :dev,
use_2197: false,
pool_size: 5
],
prod: [
cert: "priv/apns/prod_cert.pem",
key: "priv/apns/prod_key.pem",
mode: :prod,
use_2197: false,
pool_size: 5
]
]
Analogically to FCM
configuration, at top level we may specify named pools that have different configurations. For APNS
this is specifically useful since Apple delivers different APS certificated for development and production use. As in FCM
, REST
client may select named pool by providing matching :mode
in his REST
request.
Each APNS
pool may be configured by setting the following fields:
- cert (required) - relative path to
APNS
PEM
certificate issued by Apple. This certificate have to be somewhere inpriv
directory - key (required) - relative path to
PEM
private key forAPNS
certificate issued by Apple. This file have to be somewhere inpriv
directory - pool_size (required) - maximum number of used
HTTP/2
connections to google's service - mode (either
:prod
or:dev
) - pool's mode.REST
client may select pool used to push his notification by specifying matching option in his request - endpoint (optional) - URL override for
APNS
service. Useful mainly in tests - use_2197 (optional
true
orfalse
) - whether use alternative port forAPNS
: 2197
You may entirely skip the APNS
config entry to disable APNS
support.
If for some reason you need Swagger
spec for this REST
service, there is swagger endpoint available at REST
path /swagger.json
There is only one endpoint at this moment:
POST /v2/notification/{device_id}
As you can imagine, {device_id}
should be replaced with device ID/Token generated by your push notification provider (FCM
or APNS
). The notification should be sent as JSON
payload of this request. Minimal JSON
request could be like this:
{
"service": "apns",
"body": "notification's text body",
"title": "notification's title"
}
The full list of options contains the following:
- service (required,
apns
orfcm
) - push notifications provider to be used for this notification - mode (optional,
prod
(default) ordev
) - allows for selecting named pool configured inMongoosePush
- topic (optional,
APNS
specific) - if APNS certificate configured inMongoosePush
allows for multiple applications, this field selects the application. Please refer toAPNS
documentation for more datails - data (optional) - custom JSON structure sent to the target device. For
APNS
, all keys form this stucture are merged into highest level APS message (the one that holds 'aps' key), while forFCM
the wholedata
json stucture is sent as FCM'sdata payload
along withnotification
. - alert (optional) - JSON stucture that if provided will send non-silent notification with the following fields:
- body (required) - text body of notification
- title (required) - short title of notification
- click_action (optional) - for
FCM
itsactivity
to run when notification is clicked. ForAPNS
itscategory
to invoke. Please refer to Android/iOS documentation for more details about this action - tag (optional,
FCM
specific) - notifications aggregation key - badge (optional,
APNS
specific) - unread notifications count
Please note that either alert and data has to be provided (also can be both). If you only specify alert, the request will result in classic, simple notification. If you only specify data, the request will result in "silent" notification, i.e. the client will receive the data and will be able to decide whether notification shall be shown and how should be shown to the user. If you specify both alert and data, target device will receive both notification and the custom data payload to process.
MongoosePush supports metrics based on elixometer
. In order to enable metrics, you need to add an elixometer
configuration in the config file matching your release type (or simply sys.config
when you need this on already released MongoosePush). The following example config will enable simplest reporter - TTY (already enabled in :dev
environment):
config :exometer_core, report: [reporters: [{:exometer_report_tty, []}]]
config :elixometer, reporter: :exometer_report_tty,
env: Mix.env,
metric_prefix: "mongoose_push"
The example below on the other hand will enable graphite
reporter (replace GRAPHITE_OPTIONS with a list of options for graphite
):
config :exometer_core, report: [reporters: [{:exometer_report_graphite, GRAPHITE_OPTIONS}]]
config :elixometer, reporter: :exometer_report_graphite,
env: Mix.env,
metric_prefix: "mongoose_push"