Setting up MongooseIM with Pleroma
So you run pleroma and you want to set up an XMPP server so your comfy friends can talk in real-time
How exactly do you go about doing that?
Well, that's rather the point of this post. Rather in the name, eh?
Setting up your server
Assuming your infrastructure looks sorta like mine (as described in this post), we'll need to do some setting up before we can actually install anything.
First, spin up a tiny little server to be your XMPP host. It can be very small and cute, AWS t3.micro or similar should suffice unless you run some behemoth server in which case feel free to allocate some more resources.
I advise putting ubuntu on it, since we only really care for stability and compatibility here.
As per usual, we're going to lock the server down to our bastion host (skip this if you don't have a bastion host)
sudo apt-get update && sudo apt-get upgrade
sudo apt-get install ufw
# OPTIONAL
# use sudo ufw allow 22 if you don't have a bastion
sudo ufw allow from BASTION_IP to any port 22
sudo ufw allow 5222
sudo ufw allow 5269
Now we want postgres to hold some data
sudo apt-get install postgresql
Setting up DNS
If you're not running on your root server, you'll need to point a few records at your XMPP server.
SRV _xmpp-client._tcp.MYDOMAIN -> your xmpp server ip 5222
SRV _xmpp-server._tcp.MYDOMAIN -> your xmpp server ip 5269
Installing MongooseIM
From https://www.erlang-solutions.com/resources/download.html pick "MongooseIM" and
download the latest .deb
file to your server.
Then you can sudo dpkg -i the_deb_file.deb
to install
This will shove a load of files on your server, naturally. The stuff we care about
is in /etc/mongooseim
Installing the database
This is exceptionally badly documented by the mongooseim project, so it falls to me to explain how we get the initial DB all... working.
Having installed the mongooseim
user, we now need to set up the corresponding
postgres user.
sudo -Hu postgres psql
postgres=# create user mongooseim with login password 'SOME_GOOD_PASSWORD';
postgres=# create database mongooseim with owner mongooseim;
cool now we just need to actually find the initial tables
sudo -Hu mongooseim psql mongooseim < /usr/lib/mongooseim/lib/mongooseim-?.?.?/priv/pg.sql
If for whatever reason the file isn't there, find it with find / -iname "pg.sql" -type f
Configuration
Configuration of mongooseim is done in erlang. It's like the trenches of the somme in there so good luck.
The standard config isn't going to be doing much for you, so just take my config and alter it
VERY IMPORTANT NOTE - fullcert.pem
MUST be a concatenated file of both public and
private key. If you're using letsencrypt make sure you cat
the two pem files together.
If you want to be running multi-user rooms you'll want your SSL cert to also cover muc.mydomain
,
but i don't do that so don't come asking me for how it works.
%% 1: Critical
%% 2: Error
%% 3: Warning
%% 4: Info
%% 5: Debug
%%
{loglevel, 5}.
%%%. ================
%%%' SERVED HOSTNAMES
{hosts, ["YOUR_FEDIVERSE_SERVER"] }.
%%%. ===============
%%%' LISTENING PORTS
{listen,
[
%% MongooseIM HTTP API it's important to start it on localhost
%% or some private interface only (not accessible from the outside)
%% At least start it on different port which will be hidden behind firewall
{ {8088, "127.0.0.1"} , ejabberd_cowboy, [
{num_acceptors, 10},
{transport_options, [{max_connections, 1024}]},
{modules, [
{"localhost", "/api", mongoose_api_admin, []}
]}
]},
{ 5222, ejabberd_c2s, [
{certfile, "/etc/mongooseim/ssl/fullcert.pem"}, starttls,
{access, c2s},
{shaper, c2s_shaper},
{max_stanza_size, 65536},
{protocol_options, ["no_sslv3"]}
]},
{ 5269, ejabberd_s2s_in, [
{shaper, s2s_shaper},
{max_stanza_size, 131072},
{protocol_options, ["no_sslv3"]}
]},
{ 8888, ejabberd_service, [
{access, all},
{shaper_rule, fast},
{ip, {127, 0, 0, 1}},
{password, "secret"}
]}
]}.
{s2s_use_starttls, required}.
{s2s_certfile, "/etc/mongooseim/ssl/fullcert.pem"}.
{s2s_default_policy, allow }.
{outgoing_s2s_port, 5269 }.
{sm_backend, {mnesia, []} }.
{sasl_mechanisms, [cyrsasl_plain]}.
{auth_method, http}.
{auth_opts, [
{password_format, plain}
]}.
{outgoing_pools, [
{http, global, auth, [{workers, 50}], [{server, "https://YOUR_FEDIVERSE_SERVER,.com"}]},
{rdbms, global, default, [{workers, 10}], [{server, {pgsql, "127.0.0.1", 5432, "mongooseim", "mongooseim", "YOUR_GOOD_PASSWORD"}}]}
]}.
%% == Extra options ==
%%
%% If you use PostgreSQL, have a large database, and need a
%% faster but inexact replacement for "select count(*) from users"
%%
%%{pgsql_users_number_estimate, true}.
%%
%% rdbms_server_type specifies what database is used over the RDBMS layer
%% Can take values mssql, pgsql, mysql
%% In some cases (for example for MAM with pgsql) it is required to set proper value.
%%
{rdbms_server_type, pgsql}.
%%%. ===============
%%%' TRAFFIC SHAPERS
%%
%% The "normal" shaper limits traffic speed to 1000 B/s
%%
{shaper, normal, {maxrate, 1000}}.
%%
%% The "fast" shaper limits traffic speed to 50000 B/s
%%
{shaper, fast, {maxrate, 50000}}.
%%
%% This option specifies the maximum number of elements in the queue
%% of the FSM. Refer to the documentation for details.
%%
{max_fsm_queue, 1000}.
%%%. ====================
%%%' ACCESS CONTROL LISTS
%%
%% The 'admin' ACL grants administrative privileges to XMPP accounts.
%% You can put here as many accounts as you want.
%%
{acl, admin, {user, "myusername", "YOUR_FEDIVERSE_SERVER"}}.
%%
%% Local users: don't modify this line.
%%
{acl, local, {user_regexp, ""}}.
%%%. ============
%%%' ACCESS RULES
%% Maximum number of simultaneous sessions allowed for a single user:
{access, max_user_sessions, [{10, all}]}.
%% Maximum number of offline messages that users can have:
{access, max_user_offline_messages, [{5000, admin}, {100, all}]}.
%% This rule allows access only for local users:
{access, local, [{allow, local}]}.
%% Only non-blocked users can use c2s connections:
{access, c2s, [{deny, blocked},
{allow, all}]}.
%% For C2S connections, all users except admins use the "normal" shaper
{access, c2s_shaper, [{none, admin},
{normal, all}]}.
%% All S2S connections use the "fast" shaper
{access, s2s_shaper, [{fast, all}]}.
%% Admins of this server are also admins of the MUC service:
{access, muc_admin, [{allow, admin}]}.
%% Only accounts of the local ejabberd server can create rooms:
{access, muc_create, [{allow, local}]}.
%% All users are allowed to use the MUC service:
{access, muc, [{allow, all}]}.
%% In-band registration allows registration of any possible username.
%% To disable in-band registration, replace 'allow' with 'deny'.
{access, register, [{allow, all}]}.
%% By default the frequency of account registrations from the same IP
%% is limited to 1 account every 10 minutes. To disable, specify: infinity
{registration_timeout, infinity}.
%% Default settings for MAM.
%% To set non-standard value, replace 'default' with 'allow' or 'deny'.
%% Only user can access his/her archive by default.
%% An online user can read room's archive by default.
%% Only an owner can change settings and purge messages by default.
%% Empty list (i.e. `[]`) means `[{deny, all}]`.
{access, mam_set_prefs, [{default, all}]}.
{access, mam_get_prefs, [{default, all}]}.
{access, mam_lookup_messages, [{default, all}]}.
{access, mam_purge_single_message, [{default, all}]}.
{access, mam_purge_multiple_messages, [{default, all}]}.
%% 1 command of the specified type per second.
{shaper, mam_shaper, {maxrate, 1}}.
%% This shaper is primeraly for Mnesia overload protection during stress testing.
%% The limit is 1000 operations of each type per second.
{shaper, mam_global_shaper, {maxrate, 1000}}.
{access, mam_set_prefs_shaper, [{mam_shaper, all}]}.
{access, mam_get_prefs_shaper, [{mam_shaper, all}]}.
{access, mam_lookup_messages_shaper, [{mam_shaper, all}]}.
{access, mam_purge_single_message_shaper, [{mam_shaper, all}]}.
{access, mam_purge_multiple_messages_shaper, [{mam_shaper, all}]}.
{access, mam_set_prefs_global_shaper, [{mam_global_shaper, all}]}.
{access, mam_get_prefs_global_shaper, [{mam_global_shaper, all}]}.
{access, mam_lookup_messages_global_shaper, [{mam_global_shaper, all}]}.
{access, mam_purge_single_message_global_shaper, [{mam_global_shaper, all}]}.
{access, mam_purge_multiple_messages_global_shaper, [{mam_global_shaper, all}]}.
{language, "en"}.
{all_metrics_are_global, false }.
{services,
[
{service_admin_extra, [{submods, [node, accounts, sessions, vcard,
roster, last, private, stanza, stats]}]},
{service_cache, []}
]
}.
{modules,
[
{mod_adhoc, []},
{mod_disco, [{users_can_see_hidden_services, false}]},
{mod_commands, []},
{mod_muc_light_commands, []},
{mod_last, []},
{mod_stream_management, [
]},
{mod_offline, [{access_max_user_messages, max_user_offline_messages}, {backend, rdbms}]},
{mod_privacy, [{backend, rdbms}]},
{mod_blocking, []},
{mod_muc_light, [
{host, "muclight.@HOST@"},
{backend, rdbms},
{access_create, none},
{all_can_invite, true},
{all_can_configure, false},
{blocking, false},
{max_occupants, 500},
{rooms_per_page, 50},
{rooms_in_rosters, true}
]},
{mod_event_pusher, [
{backends, [
{push, [
{backend, mnesia},
{wpool, [{workers, 200}]},
{plugin_module, mod_event_pusher_push_plugin_defaults}
]}
]}
]},
{mod_private, [{backend, rdbms}]},
{mod_inbox, [
{backend, rdbms},
{reset_markers, [displayed, received, acknowledged]},
{aff_changes, true},
{remove_on_kicked, true},
{groupchat, [muclight]}
]},
{mod_roster, [{backend, rdbms}, {versioning, true}]},
{mod_sic, []},
{mod_pubsub, [
{access_createnode, pubsub_createnode},
{ignore_pep_from_offline, false},
{last_item_cache, mnesia},
{max_items_node, 1000},
{plugins, [<<"flat">>, <<"pep">>]},
{backend, rdbms}
]},
{mod_vcard, [
{host, "vjud.@HOST@"}
]},
{mod_bosh, []},
{mod_carboncopy, []},
{mod_caps, []},
{mod_mam_meta, [
{backend, rdbms},
{async_writer, true },
{archive_groupchats, true },
{user_prefs_store, mnesia},
{rdbms_message_format, simple},
{pm, [
{archive_groupchats, true}
]},
{muc, [
{host, "muclight.@HOST@"}
]}
]},
{mod_csi, [{buffer_max, 40}]}
]}.
%%%.
%%%'
%%% $Id$
%%% Local Variables:
%%% mode: erlang
%%% End:
%%% vim: set filetype=erlang tabstop=8 foldmarker=%%%',%%%. foldmethod=marker:
%%%.
Starting the server
Ok cool i hope your PTSD isn't that bad right now but i wouldn't blame you if you had to go to therapy after seeing that.
start by running mongooseimctl foreground
and making sure it starts all ok.
if it does, feel free to just mongooseimctl start
it and you'll be good to go.