The Docker setup is the most reliable way to run Jitsi Meet today. Every component (web, Prosody, Jicofo, the videobridge) runs in its own container, upgrades are a tag change, and the whole stack is described by two files you can keep in version control.
This is the same layout our platform deploys on customer servers, pinned to stable-11031.
Before you start
- A Linux server with 2 vCPU and 4 GB of RAM or more. See server requirements.
- A public IP address.
- A domain such as
meet.example.comwith anArecord pointing at that IP. Create it first; Let’s Encrypt validates it on the first start. - SSH access with sudo.
1. Install Docker
On Ubuntu or Debian, Docker’s convenience script installs Docker Engine and the Compose plugin:
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker $USER # log out and back in afterwards
docker compose version
2. Download one pinned release
Pin a release instead of tracking latest. The compose file references image tags, and mixing a compose file from one release with images from another is a common cause of containers that refuse to start.
sudo mkdir -p /opt/jitsi-meet && sudo chown $USER /opt/jitsi-meet
cd /opt/jitsi-meet
RELEASE=stable-11031
BASE=https://raw.githubusercontent.com/jitsi/docker-jitsi-meet/$RELEASE
curl -fsSLO $BASE/docker-compose.yml
curl -fsSL -o .env $BASE/env.example
curl -fsSLO $BASE/gen-passwords.sh
chmod +x gen-passwords.sh
./gen-passwords.sh
gen-passwords.sh fills in the internal component passwords (JICOFO_AUTH_PASSWORD, JVB_AUTH_PASSWORD and the rest) in .env. Never reuse the example values.
3. Edit .env
Open .env and set at least these values:
CONFIG=/opt/jitsi-meet/config
HTTP_PORT=80
HTTPS_PORT=443
PUBLIC_URL=https://meet.example.com
TZ=UTC
# Always send http:// to https://. Camera and microphone only work on HTTPS.
ENABLE_HTTP_REDIRECT=1
ENABLE_LETSENCRYPT=1
LETSENCRYPT_DOMAIN=meet.example.com
LETSENCRYPT_EMAIL=you@example.com
# Keep images on the same release as the compose file.
JITSI_IMAGE_VERSION=stable-11031
If your server is behind NAT and calls with three people fail later, also set:
JVB_ADVERTISE_IPS=203.0.113.10 # your public IP
4. Create the config folders
The containers write their generated configuration under CONFIG:
mkdir -p /opt/jitsi-meet/config/{web,transcripts,prosody/config,prosody/prosody-plugins-custom,jicofo,jvb,jigasi,jibri}
5. Open the firewall
On the server (ufw) and in your cloud provider’s firewall or security group:
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 10000/udp
sudo ufw enable
Forgetting 10000/udp in the cloud security group, while opening it in ufw, is the classic mistake. Both layers have to allow it.
6. Start the stack
cd /opt/jitsi-meet
docker compose up -d
docker compose ps
docker compose logs -f web
On the first start the web container requests the Let’s Encrypt certificate. When the log settles, open https://meet.example.com.
7. Test it properly
Open a room in three browsers or devices, not two. Two participants connect peer to peer and never touch the videobridge, so a broken 10000/udp path only shows up when the third person joins.
Check that:
- All three see and hear each other.
- The padlock shows a valid certificate.
- Screen sharing works.
Customizing without losing changes
The containers regenerate config.js and interface_config.js on every restart. Put your changes in these files instead, and they are appended on start:
config/web/custom-config.jsfor behavior, for exampleconfig.disableInviteFunctions = true;config/web/custom-interface_config.jsfor branding, for exampleinterfaceConfig.APP_NAME = "Acme Meet";
See white-label branding for a full example.
Next steps
- Lock down who can create rooms: password authentication or JWT tokens.
- Add recording with Jibri or transcription with Vosk.
- Plan upgrades: upgrading Docker Jitsi safely.