Skip to content

Deploying all in one XMPP STUN TURN server with containers

Renato Figueiredo edited this page Sep 2, 2020 · 5 revisions

Introduction

This document describes how to setup a server hosting XMPP, STUN/TURN services - essentially, all the services needed to bootstrap Evio overlays - using Docker containers on a cloud-hosted image.

These steps have been tested with in Amazon EC2, using the standard Ubuntu 18.04 AMI.

Overview and pre-requisites

The setup comprises of three containers:

  • evio-mysql: holds databases for the XMPP and TURN containers
  • evio-openfire: runs the Openfire XMPP server
  • evio-coturn: runs the coturn STUN/TURN server

These are all containers available on Dockerhub. It is assumed you have Docker installed in your system.

Ideally, you should run these on a VM that has a public IP address and a DNS name. Nonetheless, it does work with an Amazon instance without a static public IP address - we've tested it.

The firewall/security group settings of the VM hosting these services needs to be setup so the following inbound ports are open:

Custom UDP  UDP  3478           0.0.0.0/0  STUN
Custom UDP  UDP  49160 - 59200  0.0.0.0/0  TURN
Custom TCP  TCP  5223           0.0.0.0/0  XMPP
Custom TCP  TCP  9090           0.0.0.0/0  OpenFire admin
Custom TCP  TCP  5222           0.0.0.0/0  XMPP

The instructions assume you are running in an EC2 instance with username ubuntu, with home directory /home/ubuntu, and its public-facing external IP address is SERVER_IP.

We'll use the convention below to denote running commands on the host vs. container, and queries within mysql:

$ a_host_command
# a_container_command
mysql> a_mysql_query
  • Note: the instructions below are meant to serve as a guideline, and we do not go into best practices for setting up security, certificates, database backups, etc. The example uses a single MySQL user, and we use your_mysql_root_password to refer to a password you setup for the MySQL server.

Deploy MySQL container and create databases

Create a directory for your MySQL database on the host, and run the MySQL container mounting this volume:

$ mkdir mysql
$ docker run --name evio-mysql -e MYSQL_ROOT_PASSWORD=your_mysql_root_password -v /home/ubuntu/mysql:/var/lib/mysql -d mysql

Now log in to the container to create databases for openfire and turnserver:

$ docker exec -it evio-mysql bash
# mysql -u root --password=your_mysql_root_password
mysql> CREATE DATABASE openfire;
mysql> CREATE DATABASE turnserver;
mysql> \q
# exit
$

Deploy Openfire container linked to MySQL

This command runs the Openfire container, and create an alias (db) to connect to the database container:

$ docker run -d -p 9090:9090 -p 5222:5222 -p 5269:5269 -p 5223:5223 -p 7443:7443 -p 7777:7777 -p 7070:7070 -p 5229:5229 -p 5275:5275 --link evio-mysql:db --name evio-openfire quantumobject/docker-openfire

Now you must manually copy the MySQL schema from the evio-openfire to your host, then copy from your host to the evio-mysql container, and load to MySQL to create the proper tables Openfire needs:

$ docker cp evio-openfire:/usr/share/openfire/resources/database/openfire_mysql.sql openfire_mysql.sql 
$ docker cp openfire_mysql.sql evio-mysql:/openfire_mysql.sql
$ docker exec -it evio-mysql bash
# mysql -u root --password=your_mysql_root_password openfire < /openfire_mysql.sql

You can verify the tables have been created as follows:

# mysql -u root --password=your_mysql_root_password openfire
mysql> SHOW TABLES;
+----------------------+
| Tables_in_openfire   |
+----------------------+
| ofExtComponentConf   |
| ofGroup              |
| ofGroupProp          |
| ofGroupUser          |
| ofID                 |
... and so on

Perform initial Openfire setup

This sequence of steps is done via page forms exposed through the Openfire admin web interface:

  • Point your Web browser to: http://SERVER_IP:9090
  • Select your language
  • change XMPP Domain Name, Server Host Name to your server's FQDN - or, if you don't have one, use "local"
  • select "Standard database connection" (which is not the default option)
  • In "Pick Database": pick MySQL
  • replace Database URL with the following string to connect to your other container: jdbc:mysql://db:3306/openfire
  • set username: root
  • set password: your_mysql_root_password
  • Profile settings: Default
  • Set your admin email and password for Openfire - you will use this password you need to login back again as "admin" to http://SERVER_IP:9090

Optional: set plain password for user in Openfire

If you'd like to set up Openfire to store plain passwords for users in the MySQL database (not a best practice for production deployments, but makes the process easier for testing), log into the evio-mysql container and set this property:

$ docker exec -it evio-mysql bash
# mysql -u root --password=your_mysql_root_password openfire
mysql> INSERT INTO ofProperty (name, propValue) VALUES ('user.usePlainPassword','true');
mysql> \q
# exit
$

Deploy coturn container

First, create a directory on your host to hold the configuration file for the coturn container, and create the configuration file turnserver.conf:

$ cd
$ mkdir coturn
$ cd coturn
$ vi turnserver.conf

There are many configuration options for coturn, but the template turnserver.conf below will get you started. You must replace three items in this template

realm=local
fingerprint
external-ip=SERVER_IP
listening-port=3478
min-port=49160
max-port=59200
lt-cred-mech
mysql-userdb="host=MYSQL_CONTAINER_IP dbname=turnserver user=root password=your_mysql_root_password connect_timeout=30 read_timeout=30”
  • Make sure you replace SERVER_IP with the address of your server!!
  • Make sure you replace your_mysql_root_password!!
  • Replace MYSQL_CONTAINER_IP with the IP address of your evio-mysql container. This is a private address, and you can determine it as follows:
$ docker inspect evio-mysql | grep IPAddress

Now you're run the evio-coturn container - note that it binds to the host network, since it uses many ports for relaying:

$ docker run -d --network=host --name evio-coturn -v /home/ubuntu/coturn/turnserver.conf:/etc/coturn/turnserver.conf       instrumentisto/coturn -c /etc/coturn/turnserver.conf

Now you must manually copy the MySQL schema from the evio-coturn container to your host, then copy from your host to the evio-mysql container, and load to MySQL to create the proper tables the coturn TURN server needs:

$ docker cp evio-coturn:/usr/share/turnserver/schema.sql turnserver.sql 
$ docker cp turnserver.sql evio-mysql:/turnserver.sql
$ docker exec -it evio-coturn sh
# mysql -u root --password=your_mysql_root_password turnserver < /turnserver.sql

Adding users

You're done with the basic installation steps! Now you're ready to add users.

The Evio team is developing scripts that will help in the creation of users in XMPP, TURN, as well as Evio configuration files. We'll add to this page as we progress.

If you want to manually create XMPP users/groups, the SQL commands you need to use follow this template (assuming you are using plain passwords):

INSERT INTO ofUser (username, email, iterations, plainPassword, creationDate, modificationDate) VALUES ('node1', 'someone@email.com', 4096, 'some_password_1'
, 1599071130973, 1599071130973);
INSERT INTO ofUser (username, email, iterations, plainPassword, creationDate, modificationDate) VALUES ('node2', 'someone@email.com', 4096, 'some_password_2'
, 1599071130973, 1599071130973);
INSERT INTO ofUser (username, email, iterations, plainPassword, creationDate, modificationDate) VALUES ('node3', 'someone@email.com', 4096, 'some_password_3'
, 1599071130973, 1599071130973);
INSERT INTO ofGroup (groupName) VALUES ('mygroup');
INSERT INTO ofGroupUser (groupName, username, administrator) VALUES ('mygroup', 'node1', 0);
INSERT INTO ofGroupUser (groupName, username, administrator) VALUES ('mygroup', 'node2', 0);
INSERT INTO ofGroupUser (groupName, username, administrator) VALUES ('mygroup', 'node3', 0);
INSERT INTO ofGroupProp (groupName, name, propValue) VALUES ('mygroup', 'sharedRoster.displayName', 'mygroup');
INSERT INTO ofGroupProp (groupName, name, propValue) VALUES ('mygroup', 'sharedRoster.groupList', '');
INSERT INTO ofGroupProp (groupName, name, propValue) VALUES ('mygroup', 'sharedRoster.showInRoster', 'onlyGroup');

And for TURN users, you can use the turnadmin program that's available within evio-coturn (replace 172.17.0.2 with the evio-mysql container's IP):

$ docker exec -it evio-coturn sh
# turnadmin --mysql-userdb "host=172.17.0.2 dbname=turnserver user=root password=your_mysql_root_password connect_timeout=30 read_timeout=30" -a -r local -u node1 -p some_password_1
# turnadmin --mysql-userdb "host=172.17.0.2 dbname=turnserver user=root password=your_mysql_root_password connect_timeout=30 read_timeout=30" -a -r local -u node2 -p some_password_2
# turnadmin --mysql-userdb "host=172.17.0.2 dbname=turnserver user=root password=your_mysql_root_password connect_timeout=30 read_timeout=30" -a -r local -u node3 -p some_password_3