Outgoing connections
MongooseIM can be configured to talk to external service like databases or HTTP servers in order to get or set the required data.
The interface for outgoing connections management was unified and is now available via the outgoing_pools config option for the following type of connections:
cassandra- pool of connections to Cassandra clusterriak- pool of connections to Riak clusterredis- pool of connections to Redis serverhttp- pool of connections to various HTTP(S) servers MongooseIM can talk to, in example HTTP authentication backend or HTTP notificationselastic- pool of connections to ElasticSearch serverrdbms- pool of connections to an RDBMS databasegeneric- pool of generic workers not assosiated directly with a paritcualr connection (SNS, PushNotifications)
All the above pools are managed by inaka/worker_pool library.
Every entry in the outgoing_pools is a 5 element tuple:
{Type, Host, Tag, PoolOptions, ConnectionOptions}
Where:
Typeis one of the types listed aboveHostcan be set to:global- meaning the pool will started once no matter how many XMPP hosts served by MongooseIMhost- the pool will be started for all the XMPP hosts served by MongooseIM- a binary representing a specific XMPP host like
<<"domain1.chat.im">>
Tagis a name to distinguish pools with the sameTypeandHostparameter.PoolOptionsis a list of{key, value}pairs as defined in worker_pool doc with the following exception:strategy- specifies the worker selection strategy for the given pool, default isbest_worker, more details on this can be found in Choosing strategy in worker_pool doccall_timeout- specifies the timeout, in milliseconds, for a call operation to the pool
ConnectionOptions- options list passed to thestartfunction of the pool type
Examples
Provided MongooseIM serves domains <<"a.com">>, <<"b.com">>, <<"c.eu">> and <<"d.eu">>
the following outgoing_pools configuration:
{redis, <<"a.com">>, default, PoolOpts, ConnOptsForDomain1},
{redis, host, default, PoolOpts, ConnOpts},
{redis, <<"c.eu", default, PoolOpts, ConnOptsForDomain2}
will be expanded to the following configuration:
{redis, <<"a.com">>, default, PoolOpts, ConnOptsForDomain1},
{redis, <<"b.com">>, default, PoolOpts, ConnOpts},
{redis, <<"c.eu", default, PoolOpts, ConnOptsForDomain2},
{redis, <<"d.eu">>, default, PoolOpts, ConnOpts}
RDBMS connection setup
An example RDBMS configuration inside outgoing_pools may look like this:
{outgoing_pools, [
{rdbms, global, default, [{workers, 5}],
[{server, {mysql, "localhost", 3306, "mydb", "user", "passwd"}}]}
]}.
This configuration will create a default, global pool of 5 connections to a mysql database. We might also want to add a dedicated pool for a specific host:
{outgoing_pools, [
{rdbms, global, default, [{workers, 5}],
[{server, {mysql, "localhost", 3306, "mydb", "user", "passwd"}}]},
{rdbms, "myhost.com", default, [{workers, 3}],
[{server, {mysql, "localhost", 3306, "mydb", "user", "passwd"}}]}
]}.
Please remember that SQL databases require creating a schema.
See Database backends configuration for more information.
Also see Advanced configuration for additional options that influence RDBMS connections.
Currently all pools must use the same RDBMS type (e.g. mysql, pgsql).
Connection options
-
server
- Description: SQL DB connection configuration. Currently supported DB types are
mysqlandpgsql. - Syntax:
{server, {Type, Host, Port, DBName, Username, Password}}.or{server, "<ODBC connection string>"} - Default:
undefined
- Description: SQL DB connection configuration. Currently supported DB types are
-
keepalive_interval
- Description: When enabled, will send
SELECT 1query through every DB connection at given interval to keep them open. This option should be used to ensure that database connections are restarted after they became broken (e.g. due to a database restart or a load balancer dropping connections). Currently, not every network related error returned from a database driver to a regular query will imply a connection restart. - Syntax:
{keepalive_interval, IntervalSeconds}. - Example:
{keepalive_interval, 30}. - Default:
undefined
- Description: When enabled, will send
MySQL and PostgreSQL SSL connection setup
In order to establish a secure connection with a database, additional options must be passed in the server tuple.
Here is the proper syntax:
{server, {Type, Host, Port, DBName, Username, Password, SSL}}.
MySQL
SSL configuration options for MySQL:
- SSL
- Description: Specifies SSL connection options.
- Syntax:
[Opt] - Supported values: The options are just a list of Erlang
ssl:ssl_option(). More details can be found in official Erlang ssl documentation.
Example configuration
An example configuration can look as follows:
{outgoing_pools, [
{rdbms, global, default, [{workers, 5}],
[{server, {mysql, "localhost", 3306, "mydb", "mim", "mimpass",
[{verify, verify_peer}, {cacertfile, "path/to/cacert.pem"}]}}]}
]}.
PostgreSQL
SSL configuration options for PGSQL:
-
SSL
- Description: Specifies general options for SSL connection.
- Syntax:
[SSLMode, SSLOpts]
-
SSLMode
- Description: Specifies a mode of SSL connection. Mode expresses how much the PostgreSQL driver carries about security of the connections. For more information click here.
- Syntax:
{ssl, Mode} - Supported values:
false,true,required
-
SSLOpts
- Description: Specifies SSL connection options.
- Syntax:
{ssl_opts, [Opt]} - Supported values: The options are just a list of Erlang
ssl:ssl_option(). More details can be found in official Erlang ssl documentation.
Example configuration
An example configuration can look as follows:
{outgoing_pools, [
{rdbms, global, default, [{workers, 5}],
[{server, {pgsql, "localhost", 5432, "mydb", "mim", "mimpass",
[{ssl, required}, {ssl_opts, [{verify, verify_peer}, {cacertfile, "path/to/cacert.pem"}]}]}}]}
]}.
ODBC SSL connection setup
If you've configured MongooseIM to use an ODBC driver, i.e. you've provided an ODBC connection string in the server option, e.g.
{server, "DSN=mydb"}.
then the SSL options, along other connection options, should be present in the ~/.odbc.ini file.
To enable SSL connection the sslmode option needs to be set to verify-full.
Additionally, you can provide the path to the CA certificate using the sslrootcert option.
Example ~/.odbc.ini configuration
[mydb]
Driver = ...
ServerName = ...
Port = ...
...
sslmode = verify-full
sslrootcert = /path/to/ca/cert
HTTP connections setup
Some MongooseIM modules need an HTTP connection to external service. These pools need to be configured and started before the module needs them. Below is a sample configuration:
{outgoing_pools, [
{http, global, default, PoolOptions, ConnectionOptions}
]}.
PoolOptions are described above, below there are the recommended PoolOptions for HTTP pools:
strategy- the recommended value isavailable_workercall_timeout- it should be equal or longer than the value set inrequest_timeoutbelow.
ConnectionOptions can take the following {key, value} pairs:
{server, HostName}- string, default:"http://localhost"- the URL of the destination HTTP server (including a port number if needed).{path_prefix, Prefix}- string, default:"/"- the part of the destination URL that is appended to the host name (hostoption).{request_timeout, TimeoutValue}- non-negative integer, default:2000- maximum number of milliseconds to wait for the HTTP response.
Example configuration
{outgoing_pools, [
{http, global, http_auth,
[{strategy, available_worker}], [{server, "https://my_server:8080"}]}
]}.
Redis connection setup
Session manager backend or mod_global_distrib requires a redis pool defined in the outgoing_pools option.
They can be defined as follows:
{ougtoing_pools, [
{redis, global, Tag, WorkersOptions, ConnectionOptions}
]}.
The Tag parameter can only be set to default for a session backend.
For mod_global_distrib module it can take any value (default is global_distrib) but the name needs to be passed as:
{redis, [{pool, Tag}]}
in the mod_global_distrib options. See mod_global_distrib doc for details and examples.
The ConnectionOptions list can take following parametrs as {key, value} pairs:
- host (default: "localhost") the hostname or IP address of the Redis server
- port (default: 6379) the port of the Redis server
- database (default: 0) number of the database to use by the pool
- password (default: "") the password to the database (if set).
Example
{ougtoing_pools, [
{redis, global, default, [{strategy, random_worker}],
[{host, "198.172.15.12"},
{port, 9923}]}
]}.
Riak connection setup
Currently only one Riak connection pool can exist for each supported XMPP host.
It is configured with the following tuple inside the outgoing_pools config option.
{outgoing_pools, [
{riak, global, default, [{workers, 20}], [{address, "127.0.0.1"}, {port, 8087}]}
]}.
Riak SSL connection setup
Using SSL for Riak connection requires passing extra options in ConnectionOptions to the
aforementioned riak tuple.
Here is the proper syntax:
-
Credentials
- Description: Specifies credentials to use to connect to the database.
- Syntax:
{credentials, User, Password} - Supported values
UserandPasswordare strings with a database username and password respectively.
-
CACert
- Description: Specifies a path to the CA certificate that was used to sign the database certificates.
- Syntax:
{cacertfile, Path} - Supported values
Pathis a string with a path to the CA certificate file.
-
SSL_Opts
- Description: list of SSL options as defined in Erlang SSL module doc
They will be passed verbatim to the
ssl:connectfunction. - Syntax
{ssl_opts, ListOfSSLOpts} - Example:
- Description: list of SSL options as defined in Erlang SSL module doc
They will be passed verbatim to the
{ssl_opts, [{ciphers, ["AES256-SHA", "DHE-RSA-AES128-SHA256"]},
{server_name_indication, disable}]}
Example configuration
An example configuration can look as follows:
{outgoing_pools, [
{riak, global, default, [{workers, 20}, {strategy, next_worker}],
[{address, "127.0.0.1"}, {port, 8087},
{credentials, "username", "pass"},
{cacertfile, "path/to/cacert.pem"}]}
]}.
Cassandra connection setup
The minimum pool definition for cassandra workers looks as follows:
{outgoing_pools, [
{cassandra, global, default, [], []}
]}.
In this case MongooseIM will by default try to connect to Cassandra server on "localhost" and port 9042.
The keyspace used in queries will be mongooseim.
ConnectionOptions
The ConnectionOptions list can take following parameters as {key, Value} pairs:
- servers - A list of servers in Cassandra cluster in
{HostnameOrIP, Port}format. - keyspace - A name of keyspace to use in queries executed in this pool.
- You can find a full list in
cqerldocumentation.
Example
{cassandra, global, default, [],
[
{servers, [{"cassandra_server1.example.com", 9042}, {"cassandra_server2.example.com", 9042}] },
{keyspace, "big_mongooseim"}
]
]}
SSL connection setup
In order to establish a secure connection to Cassandra you must make some changes in the MongooseIM and Cassandra configuration files.
Create server keystore
Follow this guide if you need to create certificate files.
Change the Cassandra configuration file
Find client_encryption_options in cassandra.yaml and make these changes:
client_encryption_options:
enabled: true
keystore: /your_certificate_directory/server.keystore
keystore_password: your_password
Save the changes and restart Cassandra.
Enable MongooseIM to connect with SSL
An SSL connection can be established with both self-signed and CA-signed certificates.
Self-signed certificate
Add the following to ConnectionOptions list:
{ssl, [{verify, verify_none}]}
Save the changes and restart MongooseIM.
CA-signed certificate
Add the following to ConnectionOptions list:
{ssl, [{cacertfile,
"/path/to/rootCA.pem"},
{verify, verify_peer}]}
Save the changes and restart MongooseIM.
Testing the connection
Make sure Cassandra is running and then run MongooseIM in live mode:
$ ./mongooseim live
$ (mongooseim@localhost)1> cqerl:get_client(default).
{ok,{<0.474.0>,#Ref<0.160699839.1270874114.234457>}}
$ (mongooseim@localhost)2> sys:get_state(pid(0,474,0)).
{live,{client_state,cqerl_auth_plain_handler,undefined,
undefined,
{"localhost",9042},
ssl,
{sslsocket,{gen_tcp,#Port<0.8458>,tls_connection,undefined},
<0.475.0>},
undefined,mongooseim,infinity,<<>>,undefined,
[...],
{[],[]},
[0,1,2,3,4,5,6,7,8,9,10,11|...],
[],hash,
{{"localhost",9042},
[...]}}}
If no errors occurred and your output is similar to the one above then your MongooseIM and Cassandra nodes can communicate over SSL.
ElasticSearch connection setup
A connection pool to ElasticSearch can be configured as follows:
{outgoing_pools, [
{elastic, global, default, [], [{host, "localhost"}]}
]}.
Currently only one pool with tag default can be used.
MongooseIM uses inaka/tirerl library to communicate with ElasticSearch.
This library uses worker_pool in a bit different way than MongooseIM does, so the following options are not configurable via WPoolOpts:
call_timeout(inifinity)- worker selection strategy (
available_workeror what's set asdefault_strategyofworker_poolapplication) overrun_warning(infinity)overrun_handler, ({error_logger, warning_report})
Other worker_pool options are possible to set.
In ConnectionOpts you can add (as {key, value} pairs):
host(default:"localhost") - hostname or IP address of ElasticSearch nodeport(default:9200) - port the ElasticSearch node's HTTP API is listening on
Run the following function in the MongooseIM shell to verify that the connection has been established:
1> mongoose_elasticsearch:health().
{ok,#{<<"active_primary_shards">> => 15,<<"active_shards">> => 15,
<<"active_shards_percent_as_number">> => 50.0,
<<"cluster_name">> => <<"docker-cluster">>,
<<"delayed_unassigned_shards">> => 0,
<<"initializing_shards">> => 0,
<<"number_of_data_nodes">> => 1,
<<"number_of_in_flight_fetch">> => 0,
<<"number_of_nodes">> => 1,
<<"number_of_pending_tasks">> => 0,
<<"relocating_shards">> => 0,
<<"status">> => <<"yellow">>,
<<"task_max_waiting_in_queue_millis">> => 0,
<<"timed_out">> => false,
<<"unassigned_shards">> => 15}}
Note that the output might differ based on your ElasticSearch cluster configuration.