Jicofo is the component that breaks quietest. Prosody starts, nginx serves the page, the videobridge process is alive, and then everyone who joins a room sits watching their own video tile with nobody else in it. No error on screen. Nothing obviously red in systemctl status.
I have lost more hours to this than to any other part of a self-hosted Jitsi install. And almost every time, it came down to four values spread across two config files. Not a bug, not a version problem. A domain with the wrong prefix, or a JID that differs by one word between jicofo.conf and jvb.conf.
Quick answer
Jump to a section
What a jicofo configuration error actually looks like
The frustrating part is that a jicofo configuration error rarely announces itself as one. It shows up as a symptom in the browser, three layers away from the file you need to edit. Here is the mapping I use to skip straight to the right config:
| What you see | What is usually wrong | File to open |
|---|---|---|
| Room loads, participants never see each other | Bridge never joined the brewery MUC | jvb.conf |
| "Something went wrong" on joining | Jicofo is not connected to Prosody at all | jicofo.conf |
| Stuck on "waiting for the host" | Auth domain or focus user misconfigured | jicofo.conf + Prosody |
| Jicofo restarts in a loop | HOCON syntax error or missing password | jicofo.conf |
| Everything works, second bridge ignored | Duplicate muc_nickname | jvb.conf |
If you want the background on what each of these services actually does before you start editing, our breakdown of the Jitsi architecture covers the roles of Nginx, Jicofo, Prosody, and the videobridge. This article assumes you already know roughly what they are and just need the thing fixed.
Read the logs before you touch a config file
I mean it. The temptation is to start editing domains and restarting things, and that is how a 20 minute fix becomes an evening. Jicofo tells you what it is unhappy about, in plain language, in the first 40 lines after a restart.
# Restart, then immediately watch what it says
sudo systemctl restart jicofo
sudo journalctl -u jicofo -n 60 -f
# The log files, if you prefer tailing those
sudo tail -f /var/log/jitsi/jicofo.log
sudo tail -f /var/log/jitsi/jvb.log
sudo tail -f /var/log/prosody/prosody.log /var/log/prosody/prosody.err Three greps answer most questions. The first tells you whether Jicofo ever reached Prosody, the second whether a bridge ever showed up, and the third whether Jicofo has given up on finding one:
grep -i "not-authorized\|SASLError\|Failed to connect" /var/log/jitsi/jicofo.log
grep -i "Added new videobridge" /var/log/jitsi/jicofo.log
grep -i "no operational bridges\|no bridge available" /var/log/jitsi/jicofo.log That middle one is the diagnostic I reach for most. If Added new videobridge never appears in the log after a JVB restart, then no amount of poking at Jicofo will help you. The bridge is the thing that failed to arrive, and your problem is in jvb.conf.
xmpp-domain in jicofo.conf is not your auth domain
This is the one. If you searched for xmpp-domain jicofo and landed here, it is almost certainly because these two keys look interchangeable and are not.
domainis the domain Jicofo logs in against. It takes the auth prefix:auth.meet.example.com.xmpp-domainis your main Jitsi domain, with no prefix:meet.example.com. Jicofo uses it to discover components and send pings.
Swap them and Jicofo tries to authenticate the focus user against a virtual host that has no accounts on it. Prosody correctly refuses, and you get a SASL failure that reads like a password problem even though your password is fine.
A working /etc/jitsi/jicofo/jicofo.conf for the domain meet.example.com:
jicofo {
xmpp {
client {
enabled = true
hostname = "localhost"
port = 5222
domain = "auth.meet.example.com"
xmpp-domain = "meet.example.com"
username = "focus"
password = "YOUR_FOCUS_PASSWORD"
conference-muc-jid = "conference.meet.example.com"
client-proxy = "focus.meet.example.com"
disable-certificate-verification = false
}
}
bridge {
brewery-jid = "JvbBrewery@internal.auth.meet.example.com"
}
} Five values, five different prefixes. It is genuinely easy to get wrong, so here they are side by side:
| Key | Prefix | Example |
|---|---|---|
| domain | auth. | auth.meet.example.com |
| xmpp-domain | none | meet.example.com |
| conference-muc-jid | conference. | conference.meet.example.com |
| client-proxy | focus. | focus.meet.example.com |
| brewery-jid | internal.auth. | JvbBrewery@internal.auth.meet.example.com |
grep -E "domain|muc|proxy" /etc/jitsi/jicofo/jicofo.conf and check each prefix against the table above. Restart Jicofo and watch the log. If the SASL error is gone, that was it.
Jicofo not starting: password, syntax, or a missing user
When Jicofo will not stay up at all, it is one of three things, and the log distinguishes them clearly.
A HOCON parse error. Shows up within a second of the restart, before any network activity. Usually an unbalanced brace or a value with an unquoted special character. Passwords generated with a dollar sign in them are a classic: quote them, always.
Bad credentials. You get this:
Failed to connect/login: SASLError using SCRAM-SHA-1: not-authorized Assuming your domain is correct after the previous section, the focus user either does not exist in Prosody or has a different password than the one in jicofo.conf. Re-register it, then paste the same password into the config:
sudo prosodyctl register focus auth.meet.example.com YOUR_FOCUS_PASSWORD
sudo prosodyctl register jvb auth.meet.example.com YOUR_JVB_PASSWORD
sudo systemctl restart prosody jicofo jitsi-videobridge2 Prosody cannot store the account. If registration appears to succeed but the login still fails, check the Prosody log for a permission denied on its data directory. This happens when files under /var/lib/prosody end up owned by root:
sudo chown -R prosody:prosody /var/lib/prosody
sudo systemctl restart prosody Restart order matters
journalctl -u jicofo -n 50 straight after a restart. A parse error appears instantly, a SASL error appears after a short pause. That timing alone tells you which of the three you are dealing with.
The brewery MUC: where Jicofo and the bridge shake hands
Jicofo does not talk to the videobridge directly. Both of them join a hidden XMPP chat room, the JvbBrewery, and that room is how Jicofo discovers which bridges exist and how loaded they are. If they join different rooms, both services look perfectly healthy and no call ever works.
The symptom is distinctive: the conference UI loads normally, the participant list fills up, and there is no media. In the log:
There are no operational bridges
Can not invite participant, no bridge available Which means the JID in jicofo.conf and the JID in jvb.conf must be identical. Same room name, same domain, same capitalisation:
# These two must print the same JID
grep brewery-jid /etc/jitsi/jicofo/jicofo.conf
grep muc_jids /etc/jitsi/videobridge/jvb.conf Watch for the domain in particular. It is internal.auth.meet.example.com, not auth.meet.example.com and not internal.meet.example.com. Docker deployments use different defaults again (internal-muc.meet.jitsi), which is why copying a snippet from a Docker tutorial into a package install breaks in exactly this way.
Added new videobridge in jicofo.log. If that line appears, the handshake worked and your call will connect.
jvb.conf and org.jitsi.videobridge.xmpp.user.shard.muc_jids
Here is a thing that wastes a lot of people's time. Search for org.jitsi.videobridge.xmpp.user.shard.muc_jids and you will land in load balancing tutorials written for a config format the current packages no longer use.
That key is the old sip-communicator.properties form. Modern builds read /etc/jitsi/videobridge/jvb.conf, which is HOCON, and the same setting lives at videobridge.apis.xmpp-client.configs.shard.muc_jids. The word shard is not a reserved keyword, by the way. It is just the name of your connection block, and you can call it anything.
The old properties and their current equivalents:
| Old sip-communicator.properties key | Current jvb.conf path |
|---|---|
| org.jitsi.videobridge.xmpp.user.shard.MUC_JIDS | apis.xmpp-client.configs.shard.muc_jids |
| org.jitsi.videobridge.xmpp.user.shard.MUC_NICKNAME | apis.xmpp-client.configs.shard.muc_nickname |
| org.jitsi.videobridge.xmpp.user.shard.HOSTNAME | apis.xmpp-client.configs.shard.hostname |
| org.jitsi.videobridge.xmpp.user.shard.DOMAIN | apis.xmpp-client.configs.shard.domain |
A working jvb.conf, single bridge:
videobridge {
apis {
xmpp-client {
configs {
shard {
hostname = "localhost"
domain = "auth.meet.example.com"
username = "jvb"
password = "YOUR_JVB_PASSWORD"
muc_jids = "JvbBrewery@internal.auth.meet.example.com"
muc_nickname = "jvb-1"
}
}
}
}
stats {
enabled = true
transports = [
{ type = "muc" }
]
}
} Two details in there that bite people. First, stats must be enabled with the muc transport, because that is how the bridge reports its load into the brewery room. Turn it off and Jicofo sees a bridge with no health data and refuses to use it.
Second, muc_nickname has to be unique across every bridge pointing at the same Prosody. If you built your second bridge by copying the first one's config, you now have two bridges with the nickname jvb-1, and the second one quietly takes the first one's place in the room instead of joining alongside it. You end up with one bridge and a puzzling capacity ceiling. Use the hostname, or generate one with uuidgen.
Prosody jitsi error patterns worth recognising
Prosody is usually the innocent party, but it is where the evidence lives. A standard package install gives you two virtual hosts and two MUC components, and every JID above has to line up with one of them:
# What a working setup looks like in /etc/prosody/conf.d/meet.example.com.cfg.lua
VirtualHost "meet.example.com" -- your main domain, anonymous or token auth
VirtualHost "auth.meet.example.com" -- internal_hashed, holds the focus and jvb accounts
Component "conference.meet.example.com" "muc" -- where actual meetings live
Component "internal.auth.meet.example.com" "muc" -- where JvbBrewery lives Two Prosody-side failures come up often enough to name. Certificate errors, where jicofo.log shows a TLS alert against localhost: on a self-signed setup, either add the certificate to the Java truststore or set disable-certificate-verification = true in jicofo.conf. On a loopback connection to your own Prosody that second option is a reasonable trade, and it is what the Docker images do by default. Storage errors, covered above, where Prosody cannot write to /var/lib/prosody and no account you register actually persists.
One thing worth ruling out early: media problems that look like config problems. If Jicofo logs Added new videobridge, both participants appear, and there is still no audio or video, your XMPP layer is fine and you have a network path issue instead. That is a TURN question, and our guide on setting up a TURN server for Jitsi Meet covers it. Do not go back to editing jicofo.conf.
The 10-minute checklist
When someone hands me a broken Jitsi box, this is the order I work in. It finds the problem most of the time before I have opened an editor:
- Restart in order: Prosody, Jicofo, videobridge. Some "errors" are just startup races.
journalctl -u jicofo -n 60. A parse error shows instantly, a SASL error after a beat.- Check the five domain prefixes in jicofo.conf against the table above.
- Diff
brewery-jidagainstmuc_jids. They must match exactly. - Grep jicofo.log for
Added new videobridge. No line means the bridge never arrived. - Confirm the focus and jvb accounts exist in Prosody, and that
/var/lib/prosodyis owned by prosody. - Confirm
muc_nicknameis unique if you run more than one bridge. - Only then start looking at the network, ports, and TURN.
If you are setting a server up from scratch rather than repairing one, the config comes out right the first time by following the platform guides: Jitsi Meet on AWS or Jitsi Meet on GCP. Adding recording later introduces a second brewery room with the same class of JID mismatch, and the Jibri setup guide covers that one. And if you fixed a config but the browser still serves the old behaviour, that is a caching artefact, not a config error: see resolving Jitsi cache issues after an upgrade.
The pattern behind all of this is that Jitsi's components fail politely. They log the problem once, at startup, and then sit there looking healthy. Get in the habit of restarting and reading the first 60 lines, and most of these stop being mysteries.
Frequently Asked Questions
What is the difference between domain and xmpp-domain in jicofo.conf?
domain is the login domain, so it takes the auth prefix (auth.meet.example.com). xmpp-domain is your main Jitsi domain (meet.example.com), used for component discovery and pings. Swapping the two is the most common jicofo configuration error.
Why is jicofo not starting after I edited jicofo.conf?
Usually a HOCON syntax error or a bad password. Run journalctl -u jicofo -n 50 right after the restart. An unbalanced brace prints a parse error on startup, while a wrong password shows SASLError using SCRAM-SHA-1: not-authorized once it reaches Prosody.
Where do I set org.jitsi.videobridge.xmpp.user.shard.muc_jids?
That is the old sip-communicator.properties key. Current builds use jvb.conf, where the same value lives at videobridge.apis.xmpp-client.configs.shard.muc_jids. The word shard is just the name of your config block, not a reserved keyword.
Jicofo says there are no operational bridges. What is wrong?
The bridge never joined the brewery MUC. Check that brewery-jid in jicofo.conf and muc_jids in jvb.conf are the exact same JID, character for character, and that the jvb user is registered in Prosody.
Do I still need the jitsi-videobridge component in Prosody?
No. That is the deprecated component mode on port 5347. Current deployments use MUC mode, where the bridge logs in as a normal XMPP user and joins the JvbBrewery room. If your config still has a component secret, you are following an outdated tutorial.
Why does Prosody log a permission denied error for auth.meet.example.com?
Prosody cannot write its account storage. Run chown -R prosody:prosody /var/lib/prosody and restart. This usually happens after registering the focus or jvb user with sudo prosodyctl as root instead of as the prosody user.
Can I run two videobridges against one Jicofo?
Yes, that is the point of MUC mode. Both bridges use the same muc_jids value but must have a different muc_nickname. Duplicate nicknames make the second bridge silently replace the first in the brewery room.
Skip the Config Debugging: Jitsi Meet for 500 Users on AWS
Launch a pre-configured Jitsi Meet server sized for 500 participants, with the Jicofo, Prosody, and videobridge domains and brewery JIDs already wired together correctly.
Get Jitsi Meet on AWS Marketplace