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

In jicofo.conf, domain is the login domain and takes the auth prefix (auth.meet.example.com). xmpp-domain is your plain domain (meet.example.com). If those two are swapped, Jicofo will not authenticate. If the room loads but nobody connects, your brewery JID does not match between jicofo.conf and jvb.conf.
domain ≠ xmpp-domain The single most common mix-up. One takes the auth prefix, one does not.
JvbBrewery@... The same JID has to appear in both jicofo.conf and jvb.conf, exactly.
muc_nickname Must be unique per bridge. Duplicates make bridges vanish silently.

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 otherBridge never joined the brewery MUCjvb.conf
"Something went wrong" on joiningJicofo is not connected to Prosody at alljicofo.conf
Stuck on "waiting for the host"Auth domain or focus user misconfiguredjicofo.conf + Prosody
Jicofo restarts in a loopHOCON syntax error or missing passwordjicofo.conf
Everything works, second bridge ignoredDuplicate muc_nicknamejvb.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.

Error 1

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.

  • domain is the domain Jicofo logs in against. It takes the auth prefix: auth.meet.example.com.
  • xmpp-domain is 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:

KeyPrefixExample
domainauth.auth.meet.example.com
xmpp-domainnonemeet.example.com
conference-muc-jidconference.conference.meet.example.com
client-proxyfocus.focus.meet.example.com
brewery-jidinternal.auth.JvbBrewery@internal.auth.meet.example.com
The fix: print those five lines with 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.
Error 2

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

Prosody first, then Jicofo, then the videobridge. Jicofo does retry its connection, but restarting it against a Prosody that is still coming up produces a scary looking failure in the log that has nothing to do with your config, and sends people editing files that were already correct.
The fix: run 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.
Error 3

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.

The fix: after correcting the JID, restart the bridge and grep for Added new videobridge in jicofo.log. If that line appears, the handshake worked and your call will connect.
Error 4

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 keyCurrent jvb.conf path
org.jitsi.videobridge.xmpp.user.shard.MUC_JIDSapis.xmpp-client.configs.shard.muc_jids
org.jitsi.videobridge.xmpp.user.shard.MUC_NICKNAMEapis.xmpp-client.configs.shard.muc_nickname
org.jitsi.videobridge.xmpp.user.shard.HOSTNAMEapis.xmpp-client.configs.shard.hostname
org.jitsi.videobridge.xmpp.user.shard.DOMAINapis.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.

The fix: if your config still mentions a component secret on port 5347, you are on the deprecated component mode. Move to MUC mode using the block above. Component mode is gone from current builds.

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:

  1. Restart in order: Prosody, Jicofo, videobridge. Some "errors" are just startup races.
  2. journalctl -u jicofo -n 60. A parse error shows instantly, a SASL error after a beat.
  3. Check the five domain prefixes in jicofo.conf against the table above.
  4. Diff brewery-jid against muc_jids. They must match exactly.
  5. Grep jicofo.log for Added new videobridge. No line means the bridge never arrived.
  6. Confirm the focus and jvb accounts exist in Prosody, and that /var/lib/prosody is owned by prosody.
  7. Confirm muc_nickname is unique if you run more than one bridge.
  8. 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