MiroTalk SFU - Self Hosting
Requirements
- Server Selection:
- Hetzner (CPX11) - Use this link to receive
€20 in cloud credits
- Hostinger (KVM 2 or KVM 4)
- Contabo (VPS-1)
- OS: Ubuntu 22.04 LTS.
- Node.js (LTS) and npm
- FFmpeg for optional RTMP streaming support.
- Domain or Subdomain Name (e.g.,
YOUR.DOMAIN.NAME
) with a DNS A record pointing to your server's IPv4 address.
Installation
Note
Many of the installation steps require root
or sudo
access
# Gcc g++ make
$ apt-get update
$ apt-get install -y build-essential
# Python 3.8 and pip
$ DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata
$ apt install -y software-properties-common
$ add-apt-repository -y ppa:deadsnakes/ppa
$ apt update
$ apt install -y python3.8 python3-pip
# FFmpeg
$ apt install -y ffmpeg
Install NodeJS 18.X
and npm
using Node Version Manager
Quick start
# Clone this repo
$ git clone https://github.com/miroslavpejic85/mirotalksfu.git
# Go to to dir mirotalksfu
$ cd mirotalksfu
# Copy app/src/config.template.js in app/src/config.js
$ cp app/src/config.template.js app/src/config.js
# Copy .env.template to .env and edit it if needed
$ cp .env.template .env
Config.js
Change the ENVIRONMENT
and the PUBLIC_IP
in the app/src/config.js
Set the port range for WebRTC communication. This range is used for the dynamic allocation of UDP ports for media streams.
/*
About:
- Each participant requires 2 ports: one for audio and one for video.
- The default configuration supports up to 50 participants (50 * 2 ports = 100 ports).
- To support more participants, simply increase the port range.
Note:
- When running in Docker, use 'network mode: host' for improved performance.
- Alternatively, enable 'webRtcServerActive: true' mode for better scalability.
- Make sure these port ranges are not blocked by the firewall, if they are, add the necessary rules
*/
const RTC_MIN_PORT = 40000;
const RTC_MAX_PORT = 40100;
{
protocol: 'udp',
ip: LISTEN_IP,
announcedAddress: IPv4,
portRange: { min: RTC_MIN_PORT, max: RTC_MAX_PORT } },
{
protocol: 'tcp',
ip: LISTEN_IP,
announcedAddress: IPv4,
portRange: { min: RTC_MIN_PORT, max: RTC_MAX_PORT }
},
// If you are not behind a NAT
{
protocol: 'udp',
ip: IPv4,
portRange: { min: RTC_MIN_PORT, max: RTC_MAX_PORT }
},
{
protocol: 'tcp',
ip: IPv4,
portRange: { min: RTC_MIN_PORT, max: RTC_MAX_PORT }
},
FireWall
Set the inbound rules
if needed
Port range | Protocol | Source | Description |
---|---|---|---|
3010 | TCP | 0.0.0.0/0 | APP listen on TCP |
40000-40100 | TCP | 0.0.0.0/0 | RTC port ranges TCP |
40000-40100 | UDP | 0.0.0.0/0 | RTC port ranges UDP |
# Check the firewall Status: (active/inactive)
ufw status
# If active then allow traffic
ufw allow 3010/tcp
ufw allow 40000:40100/tcp
ufw allow 40000:40100/udp
# ssh, http, https, nginx...
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
WebRTCServer (optional)
You can activate the WebRTCServer
option by setting webRtcServerActive: true
in the app/src/config.js
.
Here's how it works:
- MiroTalk instantiates a
Worker
for eachCPU
. - Each
Worker
has its ownWebRTCServer
, which listens on a single port starting from40000
. - This setup simplifies port management because you only need to open ports for the number of
Workers
you have.
{
protocol: 'udp',
ip: LISTEN_IP,
announcedAddress: IPv4,
portRange: { min: RTC_MIN_PORT, max: RTC_MIN_PORT + NUM_WORKERS }
},
{
protocol: 'tcp',
ip: LISTEN_IP,
announcedAddress: IPv4,
portRange: { min: RTC_MIN_PORT, max: RTC_MIN_PORT + NUM_WORKERS }
},
Install dependencies and start the server
# Install dependencies - be patient, the first time will take a few minutes, in the meantime have a good coffee ;)
$ npm install
# Start the server
$ npm start
Check if is correctly installed: http://YOUR.DOMAIN.NAME:3010
Using PM2 (Process Manager)
# Install pm2
$ npm install -g pm2
# Start the server
$ pm2 start app/src/Server.js
# Takes a snapshot
$ pm2 save
# Add it on startup
$ pm2 startup
Using Docker
# Install docker
$ sudo apt install -y docker.io
# Instal docker-compose
$ sudo apt install -y docker-compose
# Clone this repo
$ git clone https://github.com/miroslavpejic85/mirotalksfu.git
# Go to to dir mirotalksfu
$ cd mirotalksfu
# Copy app/src/config.template.js in app/src/config.js IMPORTANT (edit it according to your needs)
$ cp app/src/config.template.js app/src/config.js
# Copy .env.template to .env and edit it if needed
$ cp .env.template .env
# Copy docker-compose.template.yml in docker-compose.yml and customize it according to your needs if needed
$ cp docker-compose.template.yml docker-compose.yml
# Pull the official Docker image
$ docker pull mirotalk/sfu:latest
# Create and start containers (-d as daemon)
$ docker-compose up
Check if is correctly installed: http://YOUR.DOMAIN.NAME:3010
Configuring Nginx & Certbot
In order to use it without the port number and to have encrypted communications (mandatory to make it work correctly
), we going to install nginx and certbot
# Install Nginx
$ sudo apt-get install -y nginx
# Install Certbot (SSL certificates)
$ sudo apt install -y snapd
$ sudo snap install core; sudo snap refresh core
$ sudo snap install --classic certbot
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
# Configure Nginx
$ sudo vim /etc/nginx/sites-enabled/default
Add the following:
# HTTP — redirect all traffic to HTTPS
server {
listen 80;
listen [::]:80;
server_name YOUR.DOMAIN.NAME;
return 301 https://$host$request_uri;
}
# Test Nginx configuration
$ sudo nginx -t
# Enable HTTPS with Certbot (follow the instruction)
$ sudo certbot certonly --nginx
# Add Let's Encrypt configuration to Nginx
$ sudo vim /etc/nginx/sites-enabled/default
Paste this:
# MiroTalk SFU - HTTPS — proxy all requests to the Node app
server {
# Enable HTTP/2
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name YOUR.DOMAIN.NAME;
# Use the Let’s Encrypt certificates
ssl_certificate /etc/letsencrypt/live/YOUR.DOMAIN.NAME/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/YOUR.DOMAIN.NAME/privkey.pem;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://localhost:3010/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
# Test Nginx configuration again
$ sudo nginx -t
# Restart nginx
$ service nginx restart
$ service nginx status
# Set up auto-renewal for SSL certificates
$ sudo certbot renew --dry-run
# Show certificates
$ sudo certbot certificates
Check Your MiroTalk SFU instance: http://YOUR.DOMAIN.NAME
Apache Virtual Host (Alternative to Nginx)
If you prefer Apache
, configure it with the equivalent settings provided in this guide.
# Install apache with certbot
$ apt install python3-certbot-apache -y
# Setting up ssl
$ certbot --apache --non-interactive --agree-tos -d YOUR.DOMAIN.NAME -m your.email.address
# Edit the apache sites
$ sudo vim /etc/apache2/sites-enabled/YOUR.DOMAIN.NAME.conf
Add the following:
# HTTP — redirect all traffic to HTTPS
<VirtualHost *:80>
ServerName YOUR.DOMAIN.NAME
Redirect permanent / https://YOUR.DOMAIN.NAME
</VirtualHost>
# MiroTalk SFU - HTTPS — proxy all requests to the Node app
<VirtualHost *:443>
ServerName YOUR.DOMAIN.NAME
# SSL Configuration
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/YOUR.DOMAIN.NAME/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/YOUR.DOMAIN.NAME/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
# Enable HTTP/2 support
Protocols h2 http/1.1
<Location />
# Proxy Configuration for Node.js App
ProxyPass http://localhost:3010/
ProxyPassReverse http://localhost:3010/
ProxyPreserveHost On
RequestHeader set X-Forwarded-For "%{REMOTE_ADDR}s"
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set Host "%{HTTP_HOST}s"
# Enable WebSocket proxy support for Socket.IO
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /(.*) ws://localhost:3010/socket.io/$1 [P,L]
# Adjust the WebSocket path according to your Socket.IO configuration
# For Socket.IO 3.x or higher, use /socket.io/?EIO=4&transport=websocket
</Location>
</VirtualHost>
# Check configuration
sudo apache2ctl configtest
sudo a2enmod proxy # Enables the `mod_proxy` module, which is essential for proxying HTTP and WebSocket connections.
sudo a2enmod proxy_http # Enables the `mod_proxy_http` module, which adds support for proxying HTTP connections.
sudo a2enmod proxy_wstunnel # Enables the `mod_proxy_wstunnel` module, which provides support for tunneling WebSocket connections
# Restart apache
sudo systemctl restart apache2
Updating Your Instance
To keep your MiroTalk SFU instance up to date, create an update script:
For PM2
:
For Docker
:
#!/bin/bash
cd mirotalksfu
git pull
docker-compose pull
docker image prune -f
docker-compose up -d
Make the script executable
To update your MiroTalk SFU instance to the latest version, run the script:
Changelogs
Stay informed about project updates by following the commits of the MiroTalk SFU project here