On this page
A single Jitsi Meet server runs out of videobridge capacity long before anything else. The good news is that Jitsi was designed to scale out: you don't need a bigger server, you need more bridges, and eventually more shards. This guide covers both, with the current configuration format. It replaces two older articles of ours that used sip-communicator.properties and HAProxy directives that newer versions no longer accept.
Two levels of load balancing
| More bridges in a shard | More shards | |
|---|---|---|
| What you add | Videobridge servers | Complete Jitsi deployments (nginx, Prosody, Jicofo, bridges) |
| Who balances | Jicofo, automatically | HAProxy, by room name |
| Solves | Bridge CPU and bandwidth | Prosody and Jicofo limits, failure isolation |
| Complexity | Low | Medium |
Start with bridges. Most deployments never need a second shard, and you only find out whether you do by measuring. Load testing Jitsi Meet shows how, and the Jitsi handbook's scalable setup guide is the upstream reference for both levels.
Horizontal scaling: add videobridges to a shard
The main server keeps nginx, Prosody and Jicofo, and its own bridge. The new server runs only a videobridge that logs in to the main server's Prosody and joins the same brewery room. Jicofo notices it and starts using it.
1. Let the bridge reach Prosody
Bridges log in over XMPP on TCP 5222. On the main server, allow that port from the new bridge's private IP only:
sudo ufw allow from 10.0.1.30 to any port 5222 proto tcp Never open 5222 to the internet for this. In a cloud VPC, do the same with a security group rule scoped to the bridge.
While you are on the main server, copy the bridge account password from its own config:
sudo grep -A8 'shard' /etc/jitsi/videobridge/jvb.conf 2. Install the bridge on the new server
Add the Jitsi repository exactly as in step 5 of installing Jitsi Meet on Ubuntu, open UDP 10000, then install only the videobridge:
sudo apt install -y jitsi-videobridge2 When it asks for the hostname, enter the main Jitsi domain, for example meet.example.com.
3. Point it at the main server
Edit /etc/jitsi/videobridge/jvb.conf on the new server:
videobridge {
apis {
xmpp-client {
configs {
shard {
hostname = "10.0.1.10"
domain = "auth.meet.example.com"
username = "jvb"
password = "PASSWORD_FROM_MAIN_SERVER"
muc_jids = "JvbBrewery@internal.auth.meet.example.com"
muc_nickname = "jvb-2"
disable_certificate_verification = true
}
}
}
}
}
ice4j {
harvest {
mapping {
static-mappings = [
{
local-address = "10.0.1.30"
public-address = "203.0.113.30"
}
]
}
}
} hostnameis the main server's private IP.muc_nicknamemust be unique per bridge. Two bridges with the same nickname fight over one slot in the brewery room. For bridges started automatically, generate it at boot, for example from the instance ID.disable_certificate_verificationis acceptable because the bridge reaches Prosody over a private network with a self-signed certificate. If the path crosses the internet, trust the certificate instead.- The
static-mappingsblock gives this bridge its own public IP. Each bridge advertises its own address.
The old sip-communicator.properties names
Older guides, ours included, set these values in /etc/jitsi/videobridge/sip-communicator.properties. Current videobridge releases read jvb.conf instead, and the mapping is direct:
| Old property | Where it lives now |
|---|---|
org.jitsi.videobridge.xmpp.user.shard.MUC_JIDS | muc_jids in the shard block above |
org.jitsi.videobridge.xmpp.user.shard.HOSTNAME | hostname in the shard block |
org.jitsi.videobridge.xmpp.user.shard.MUC_NICKNAME | muc_nickname in the shard block |
org.jitsi.videobridge.ENABLE_STATISTICS | videobridge.stats.enabled |
A properties file left behind on an upgraded server is ignored for these settings, which is why editing it looks like it does nothing. Statistics matter here beyond monitoring: Jicofo places conferences using what the bridges report, so leave them enabled.
sudo systemctl restart jitsi-videobridge2
sudo tail -f /var/log/jitsi/jvb.log On the main server, /var/log/jitsi/jicofo.log should report the new bridge shortly after. If it doesn't, the brewery JID or credentials disagree; fixing Jicofo configuration errors goes through each value.
How Jicofo picks a Jitsi videobridge
Each bridge periodically reports statistics, including a stress level, into the brewery room. Jicofo uses them to place conferences. The strategy is configurable in /etc/jitsi/jicofo/jicofo.conf:
| Strategy | Behaviour |
|---|---|
SingleBridgeSelectionStrategy | Keep each conference on one bridge, choosing the least loaded |
SplitBridgeSelectionStrategy | A separate bridge for each participant; for testing cascading, not production |
RegionBasedBridgeSelectionStrategy | Place participants on bridges in their own region |
IntraRegionBridgeSelectionStrategy | Use additional bridges only when one in the region is overloaded |
VisitorSelectionStrategy | Separate strategies for visitors in very large meetings |
jicofo {
bridge {
brewery-jid = "JvbBrewery@internal.auth.meet.example.com"
selection-strategy = RegionBasedBridgeSelectionStrategy
}
} For bridges in one data center, leave the default. Region-based selection only makes sense when bridges run in several regions and participants connect from far apart; conferences then span bridges that relay media between them, which scaling videobridges with Octo explains.
Multiple shards with HAProxy
A shard is a complete, independent Jitsi deployment. With several shards behind one hostname, the only rule that matters is that everyone in the same room must reach the same shard. Jitsi makes that possible by adding the room name as a room parameter to its XMPP connection URLs, so HAProxy can route on it.
frontend meet
bind *:443 ssl crt /etc/haproxy/certs/meet.example.com.pem
mode http
http-request set-header X-Forwarded-Proto https
default_backend shards
backend shards
mode http
balance url_param room
hash-type consistent
option httpchk GET /about/health
server shard1 10.0.1.10:443 check ssl verify none
server shard2 10.0.2.10:443 check ssl verify none balance url_param room with consistent hashing sends the same room to the same shard every time, and keeps most rooms in place when you add a shard. The HAProxy configuration manual documents both directives.
HAProxy reqadd no longer exists
The older version of this config used reqadd to set the forwarded protocol header. That directive was removed in HAProxy 2.1 along with the rest of the req* family, and a configuration still containing it does not start at all. The replacement is http-request set-header, as in the frontend above. On a Jitsi HAProxy config inherited from a 1.8-era guide, that single line is usually the only thing in the way.
All shards share the public identity
config.js and authentication settings in one place and deploy them identically, or users see different behaviour depending on which room they join.
The health check path above assumes an nginx endpoint that returns 200 when the shard is healthy; point it at whatever health check your shards expose, or drop it and rely on TCP checks.
Automating it
Adding bridges by hand works for a fixed load. When usage swings through the day, you want bridges to appear and disappear on their own, with running conferences drained gracefully before a bridge shuts down. Auto scaling Jitsi Meet on AWS covers that design, and our 1000-user Jitsi test shows what one shard held under real load.
Frequently Asked Questions
Does Jitsi Meet support horizontal scaling?
Yes, at two levels. Inside one shard, you add videobridges and Jicofo spreads conferences across them. Across shards, you run several complete Jitsi deployments behind HAProxy, which sends everyone in the same room to the same shard.
How does Jicofo choose a videobridge?
Bridges report their load to Jicofo through the brewery room. The bridge selection strategy in jicofo.conf decides how that is used: the default keeps a conference on one bridge and picks a lightly loaded one, while region-based and split strategies spread participants differently.
Do I still set MUC_JIDS in sip-communicator.properties?
No, that is the old properties-file format. Current videobridges read /etc/jitsi/videobridge/jvb.conf, where muc_jids, muc_nickname and the XMPP credentials sit in the shard block under apis.xmpp-client.configs.
Which port must the extra videobridge reach on the main server?
TCP 5222 on the Prosody server, which the bridge uses to log in and join the brewery room. Open it only from the bridge's private IP. Participants still reach each bridge directly on UDP 10000.
When do I need shards instead of more bridges?
When Prosody or Jicofo becomes the bottleneck rather than bridge CPU, or when you want failure isolation so one broken deployment doesn't take all meetings down. Load test first; adding bridges is simpler and solves most capacity problems.
Scaling Jitsi Beyond One Server?
Terraform-based Jitsi deployments for 50 to 2000 concurrent users, with load-balanced and auto-scaling videobridges already designed in.
See Jitsi Infrastructure as Code