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 databaserabbit- pool of connections to a RabbitMQ serverldap- pool of connections to an LDAP servergeneric- pool of generic workers not associated directly with a particular 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 doc WARNING:redisandriakbackends are not compatible withavailable_workerstrategy.call_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",
[{versions, ['tlsv1.2']},
{verify, verify_peer},
{cacertfile, "path/to/cacert.pem"},
{server_name_indication, disable}]}}]}
]}.
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.{http_opts, HTTPOptions}- list, default:[]- can be used to pass extra parameters which are passed to fusco, the library used for making the HTTP calls. More details about the possiblehttp_optscan be found in fusco's documentation.
Example configuration
{outgoing_pools, [
{http, global, http_auth,
[{strategy, available_worker}], [{server, "https://my_server:8080"}]}
]}.
If peer certificate verification is required, the pool can be configured in the following way:
{outgoing_pools, [
{http, global, mongoose_push_http,
[{workers, 50}],
[{server, "https://localhost:8443"},
{http_opts, [
{connect_options, [{verify, verify_peer}]}
]}
]}
]}.
Please note the connect_options passed to fusco via the pool's http_opts parameter.
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}
]}.
WARNING: redis backend is not compatible with available_worker strategy.
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}]}
]}.
WARNING: riak backend is not compatible with available_worker strategy.
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.
RabbitMQ connection setup
RabbitMQ backend for mod_event_pusher
requires a rabbit pool defined in the outgoing_pools option.
They can be defined as follows:
{ougtoing_pools, [
{rabbit, host, Tag, WorkersOptions, ConnectionOptions}
]}.
Notice that Host parameter is set to atom host. This basically means that
MongooseIM will start as many rabbit pools as XMPP hosts are served by
the server.
The Tag parameter must be set to event_pusher in order to be able to use
the pool for mod_event_pusher_rabbit.
Any other Tag can be used for any other RabbitMQ connection pool.
The ConnectionOptions list can take following parameters as {key, value} pairs:
- amqp_host (default:
"localhost") - Defines RabbitMQ server host (domain or IP address; both as a string); - amqp_port (default:
5672) - Defines RabbitMQ server AMQP port; - amqp_username (default:
"guest") - Defines RabbitMQ server username; - amqp_password (default:
"guest") - Defines RabbitMQ server password; - confirms_enabled (default:
false) - Enables/disables one-to-one publishers confirms; - max_worker_queue_len (default:
1000; useinfinityto disable it) - Sets a limit of messages in a worker's mailbox above which the worker starts dropping the messages. If a worker message queue length reaches the limit, messages from the head of the queue are dropped until the queue length is again below the limit.
Example
{ougtoing_pools, [
{rabbit, host, event_pusher, [{workers, 20}],
[{amqp_host, "localhost"},
{amqp_port, 5672},
{amqp_username, "guest"},
{amqp_password, "guest"},
{confirms_enabled, true},
{max_worker_queue_len, 100}]}
]}.
LDAP connection setup
To configure a pool of connections to an LDAP server, use the following syntax:
{ldap, Host, Tag, PoolOptions, ConnectionOptions}
Connection options
The following options can be specified in the ConnectionOptions list:
-
servers
- Description: List of IP addresses or DNS names of your LDAP servers. They are tried sequentially until the connection succeeds.
- Value: A list of strings
- Default:
["localhost"] - Example:
["primary-ldap-server.example.com", "secondary-ldap-server.example.com"]
-
encrypt
- Description: Enable connection encryption with your LDAP server.
The value
tlsenables encryption by using LDAP over SSL. Note that STARTTLS encryption is not supported. - Values:
none,tls - Default:
none
- Description: Enable connection encryption with your LDAP server.
The value
-
tls_options
- Description: Specifies TLS connection options. Requires
{encrypt, tls}(see above). - Value: List of
ssl:tls_client_option(). More details can be found in the official Erlang ssl documentation. - Default: no options
- Example:
[{verify, verify_peer}, {cacertfile, "path/to/cacert.pem"}]
- Description: Specifies TLS connection options. Requires
-
port
- Description: Port to connect to your LDAP server.
- Values: Integer
- Default: 389 if encryption is disabled. 636 if encryption is enabled.
-
rootdn
- Description: Bind DN
- Values: String
- Default: empty string which is
anonymous connection
-
password
- Description: Bind password
- Values: String
- Default: empty string
-
connect_interval
- Description: Interval between consecutive connection attempts in case of connection failure
- Value: Integer (milliseconds)
- Default: 10000
Example
A pool started for each host with the default tag and 5 workers. The LDAP server is at ldap-server.example.com:389. MongooseIM will authenticate as cn=admin,dc=example,dc=com with the provided password.
{outgoing_pools, [
{ldap, host, default, [{workers, 5}],
[{servers, ["ldap-server.example.com"]},
{rootdn, "cn=admin,dc=example,dc=com"},
{password, "ldap-admin-password"}]
}
]}.