Ms
Application Infrastructure Azure

MiroTalk SFU on Ubuntu 24.04 on Azure User Guide

| Product: MiroTalk SFU on Ubuntu 24.04 LTS on Azure

Overview

MiroTalk SFU is an open source, self hosted WebRTC video conferencing server. It runs many participant browser meetings with screen sharing, group chat, file transfer, recording and more, all on your own server with no third party cloud in the middle. The cloudimg image installs Node.js 22 LTS, installs the pinned MiroTalk SFU source (version 2.3.09) natively, and runs it as a dedicated mirotalksfu system service that handles signaling on the loopback connector 127.0.0.1:3010. nginx terminates TLS on port 443 with a per-VM self signed certificate and reverse proxies to the signaling server, proxying the Socket.IO WebSocket (wss) upgrade the client requires; port 80 serves an unauthenticated health endpoint and redirects everything else to HTTPS.

Live audio and video travel peer to server over a bounded mediasoup media port range, UDP 40000-40100, exposed directly to the VM's public IP. Because WebRTC needs a routable address, the appliance detects this VM's public IP on first boot and advertises it as the media announcedIp - media will not flow if that address is wrong or if the media ports are closed, so this guide shows how to confirm both. Host protection is enabled, so a host must sign in with the per-VM admin password before a room can start - there is no open to the world conferencing. A unique host password and fresh application secrets are generated on the first boot of every VM. MiroTalk SFU is licensed under the AGPL-3.0; see Licensing below. Backed by 24/7 cloudimg support.

What is included:

  • MiroTalk SFU 2.3.09 (pinned upstream source) installed natively on Node.js 22 LTS and run as the mirotalksfu system service
  • The mediasoup WebRTC media engine advertising this VM's public IP and using the bounded UDP media port range 40000-40100
  • nginx terminating TLS on :443 (per-VM self signed certificate) and reverse proxying to the signaling server on 127.0.0.1:3010 with the Socket.IO WebSocket upgrade
  • Port 80 serving an unauthenticated /healthz endpoint and redirecting all other traffic to HTTPS
  • Host protection enabled with a unique host password generated on first boot, recorded in a root only file (username admin)
  • A dedicated Azure data disk at /var/lib/mirotalksfu holding the per-VM configuration and recordings
  • mirotalksfu.service + nginx.service as systemd units, enabled and active
  • 24/7 cloudimg support

Prerequisites

An active Azure subscription, an SSH key pair, and a VNet + subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a reasonable starting point for small meetings; size up for more participants and rooms. A public IP is required for WebRTC media to reach remote browsers. NSG inbound rules - all four are required for a working meeting:

  • 22/tcp from your management network (SSH)
  • 80/tcp and 443/tcp (the web console and Socket.IO signaling)
  • 40000-40100/udp (mediasoup WebRTC media - audio and video will not connect without this range open)

The appliance ships a self signed certificate, so for production put your own domain and a trusted certificate (for example Let's Encrypt) in front of it (see Maintenance).

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for MiroTalk SFU by cloudimg, and select Create. On Basics pick your subscription, resource group, region and size; under Administrator account choose SSH public key and paste your key; under Inbound port rules allow SSH (22), HTTP (80) and HTTPS (443). After creation, add an inbound NSG rule for UDP 40000-40100 (see Step 3) so media can flow. Review the dedicated data disk on the Disks tab, then Review + create -> Create.

Step 2 - Deploy from the Azure CLI

az vm create \
  --resource-group <your-rg> \
  --name mirotalksfu \
  --image <marketplace-image-urn> \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_ed25519.pub \
  --vnet-name <your-vnet> --subnet <your-subnet> \
  --public-ip-sku Standard

az vm open-port --resource-group <your-rg> --name mirotalksfu --port 80  --priority 1010
az vm open-port --resource-group <your-rg> --name mirotalksfu --port 443 --priority 1020

Step 3 - Open the mediasoup media ports (required)

WebRTC media uses a bounded UDP range that must be reachable from participants' browsers. Open 40000-40100/udp on the VM's network security group:

az network nsg rule create \
  --resource-group <your-rg> \
  --nsg-name <your-nsg> \
  --name Allow-MiroTalk-Media \
  --priority 1030 \
  --direction Inbound --access Allow --protocol Udp \
  --destination-port-ranges 40000-40100 \
  --source-address-prefixes '*'

Without this rule the web console still loads and hosts can sign in, but audio and video will fail to connect.

Step 4 - Connect to your VM

ssh azureuser@<vm-public-ip>

Step 5 - Confirm the services and media ports

systemctl is-active mirotalksfu.service nginx.service

Both report active. MiroTalk SFU handles signaling on the loopback port 3010, nginx fronts it with TLS on port 443 (including the Socket.IO WebSocket upgrade), and the mediasoup media engine binds a set of UDP ports inside 40000-40100. The per-VM configuration and recordings live on the dedicated Azure data disk mounted at /var/lib/mirotalksfu.

mirotalksfu.service and nginx.service active, the signaling, nginx and mediasoup media port listeners, and the dedicated data disk mount

Step 6 - Confirm the announced public IP

WebRTC needs a routable address. On first boot the appliance detects this VM's public IP and writes it into the media configuration as announcedIp. Confirm it matches the VM's live public IP:

sudo grep -E '^(SFU_SERVER|SFU_ANNOUNCED_IP|SFU_MIN_PORT|SFU_MAX_PORT|HOST_PROTECTED)=' /var/lib/mirotalksfu/.env

SFU_ANNOUNCED_IP should equal your VM's public IP address, SFU_MIN_PORT/SFU_MAX_PORT bound the media range to 40000-40100, and HOST_PROTECTED=true shows host login is enforced. If you later reassign the VM's public IP, restart the first boot service to re-detect it: sudo rm -f /var/lib/cloudimg/mirotalksfu-firstboot.done && sudo systemctl restart mirotalksfu-firstboot.service.

The MiroTalk SFU version, the WebRTC media configuration from the per-VM environment file, and the announced IP cross checked against the live public IP showing a match

Step 7 - Confirm the health endpoints

nginx serves an unauthenticated health endpoint for load balancers and probes:

curl -s http://localhost/healthz
curl -sk https://localhost/healthz

Both return ok. Port 80 returns HTTP 301 and redirects to HTTPS; because host protection is enabled, the root of the site over HTTPS returns HTTP 302 and redirects to the /login page. The /healthz endpoint never requires authentication, so it is safe for an Azure Load Balancer health probe.

Step 8 - Retrieve your host password

The MiroTalk SFU host password is generated uniquely on the first boot of your VM and written to a root only file:

sudo cat /root/mirotalksfu-credentials.txt

This file contains MIROTALK_USERNAME (always admin), MIROTALK_PASSWORD and the URL to open. Store the password somewhere safe. The file is mode 0600 and owned by root, so only an administrator can read it.

The per-VM credentials file with the host password masked, the host user defined in the environment file, and the reminder that the NSG must open UDP 40000-40100 for media

Step 9 - Verify the host login from the command line

MiroTalk SFU's login is a JSON request over the TLS edge that returns a host token on success. The check below authenticates with the correct per-VM password; a wrong password returns HTTP 401. Because the command embeds your unique password, run it interactively rather than from a script - substitute the value of MIROTALK_PASSWORD from Step 8 for <MIROTALK_PASSWORD>:

curl -sk -o /dev/null -w 'host login -> HTTP %{http_code}\n' \
  -H 'Content-Type: application/json' \
  --data '{"username":"admin","password":"<MIROTALK_PASSWORD>"}' \
  https://127.0.0.1/login

The correct per-VM password prints host login -> HTTP 200 and the server returns a host token; a wrong password returns HTTP 401. The Socket.IO signaling endpoint upgrades to a WebSocket through nginx, so real time messaging works over the same TLS edge.

The host protected login round trip over TLS: the root path redirects to the login page, a wrong password returns 401, the per-VM password returns 200 with a host token, and the Socket.IO endpoint responds

Step 10 - Sign in as the host

Browse to https://<vm-public-ip>/. The appliance uses a self signed certificate, so accept the browser warning (or, for production, put your own domain and certificate in front - see Maintenance). Because host protection is enabled, you are taken to the sign-in page; enter the username admin and the password from Step 8.

The MiroTalk SFU host protected sign-in page in the browser

Step 11 - Start a room

After signing in you can name a room and start a conference. Type a room name (or generate a random one) and select Join Room. Share the room URL with participants - they join straight from their browser with no app to install.

The MiroTalk SFU start a conference screen where the signed in host names a room and joins

Step 12 - Choose your camera and microphone

Before entering the room MiroTalk SFU shows a preview with your camera and a device picker for camera, microphone and speakers, plus the in-call controls for video, audio and screen sharing. Confirm your devices and select Join meeting.

The MiroTalk SFU pre join preview showing the local video tile, the camera microphone and speaker device pickers, and the media control toolbar

Step 13 - In the meeting

Inside the room you see the participant video grid and the control bar for muting audio and video, sharing your screen, opening the group chat, raising a hand, recording and inviting others. Use Share the room to invite people by link or QR code.

The MiroTalk SFU meeting room with the host video and the share the room invite panel showing the join link and QR code

Step 14 - Confirm data lives on the dedicated disk

MiroTalk SFU's per-VM state - the environment file holding the host password, the announced IP and the application secrets, plus any recordings - is stored under /var/lib/mirotalksfu on the dedicated Azure data disk, so it survives OS changes and can be resized independently:

findmnt /var/lib/mirotalksfu

The mount is backed by a separate Azure data disk captured into the image and re-provisioned on every VM.

Maintenance

  • Host password: the host password is set on first boot and stored in /root/mirotalksfu-credentials.txt. To rotate it, edit HOST_USERS in /var/lib/mirotalksfu/.env (format admin:<password>:Admin:*) and restart mirotalksfu.service.
  • Media / announced IP: WebRTC media needs the VM's public IP reachable on UDP 40000-40100. If you reassign the public IP, clear the first boot marker and restart the first boot service so the new address is re-detected: sudo rm -f /var/lib/cloudimg/mirotalksfu-firstboot.done && sudo systemctl restart mirotalksfu-firstboot.service.
  • TLS and your own domain: the appliance ships a per-VM self signed certificate on port 443. For production, point a DNS name at the VM and install a trusted certificate (for example with certbot / Let's Encrypt) in the nginx site at /etc/nginx/sites-available/cloudimg-mirotalksfu, then reload nginx.
  • Configuration: all settings are environment variables in /var/lib/mirotalksfu/.env (documented in /opt/mirotalksfu/app/src/config.js); change a value and restart mirotalksfu.service.
  • Recording: server side recording is off by default; enable it by setting RECORDING_ENABLED=true in the environment file. Recordings are written under the data disk.
  • Storage: all per-VM state lives under /var/lib/mirotalksfu on the data disk; back up that volume to protect your configuration and recordings.
  • Security patches: unattended-upgrades remains enabled so the OS continues to receive security updates automatically.

Licensing

MiroTalk SFU is distributed under the GNU Affero General Public License v3.0 (AGPL-3.0). The AGPL includes a network use clause: if you modify the MiroTalk SFU source and offer it to users over a network, you must make your modified source available to those users. cloudimg ships the pinned upstream MiroTalk SFU source unmodified together with appliance packaging (systemd units, the nginx front end and the first boot configuration). Review the AGPL-3.0 terms before modifying the application for a public service.

Support

cloudimg provides 24/7 expert support for this image. Contact support@cloudimg.co.uk.