Skip to content

TutorialsCommunication

How to install Jitsi Meet with Docker and Let's Encrypt

Run your own Jitsi Meet video conferencing server with the official Docker setup, a Let's Encrypt certificate and logins so only your users can open rooms.

  • Intermediate
  • 40 min read
  • Updated

Tested on: Ubuntu 24.04 LTS, Ubuntu 26.04 LTS, Debian 12, Debian 13

This guide is not available in your language yet, so it is shown in English.

On this page
  1. Prerequisites
  2. Step 1 — Open the firewall ports
  3. Step 2 — Download the latest release
  4. Step 3 — Create the .env file and generate passwords
  5. Step 4 — Set the domain, HTTPS and logins
  6. Step 5 — Create the configuration folders and start Jitsi
  7. Step 6 — Create user accounts
  8. Step 7 — Test a meeting
  9. Back up and restore
  10. Update Jitsi Meet
  11. Troubleshooting
  12. Calls work with two people but there is no audio or video with three
  13. The certificate is not issued
  14. A container keeps restarting after an update
  15. Anyone can still create rooms without logging in
  16. Ports 80 or 443 are already in use
  17. Next steps

Jitsi Meet is an open-source video conferencing platform that runs in the browser and in the Jitsi mobile apps. Running your own server keeps meeting traffic on infrastructure you control and lets you decide who may create rooms. This guide installs Jitsi Meet with the project's official docker-jitsi-meet release on Ubuntu or Debian, gets a certificate from Let's Encrypt, requires a login to start meetings, and shows how to back up, update and troubleshoot the server.

Prerequisites

  • A server running Ubuntu 24.04 or 26.04 LTS, or Debian 12 or 13, with Docker Engine and the Compose plugin installed: see Install Docker on Ubuntu or Install Docker on Debian.
  • A non-root user with sudo rights (Secure a new Linux server).
  • A domain name such as meet.example.com with an A record (and AAAA record if you use IPv6) pointing to the server's public IP address.
  • Ports 80 and 443 free on the server. The Jitsi web container serves HTTPS itself in this guide, so do not run another web server on the same machine.

Sizing guidance from the Jitsi handbook:

ResourceMinimum (official)Suggested starting point
CPU4 dedicated cores for a basic server4 or more dedicated cores; avoid shared CPU
RAM2 GB for tests or very small meetings, 4 GB for small meetings8 GB, the handbook's general suggestion
DiskAbout 20 GB20 GB plus room for logs
NetworkAbout 1 Gbit/s is often enough for friends or a small organisationMeasure real throughput and latency before you rely on it

Video bandwidth adds up quickly: the handbook lists about 500 kbit/s per stream at 360p and about 2.5 Mbit/s at 720p.

Step 1 — Open the firewall ports

Jitsi needs HTTPS for the web app and UDP port 10000 for audio and video. Port 80 is used for the Let's Encrypt challenge.

Bash
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 10000/udp
sudo ufw enable
sudo ufw status verbose

Docker publishes these container ports itself and does not depend on ufw for them, but keeping the rules explicit documents what the server is meant to expose.

Step 2 — Download the latest release

The handbook asks you to use a release download rather than cloning the repository, because the release pins matching image versions. Create a working folder and download the latest release archive from GitHub:

Bash
sudo apt install wget unzip
sudo mkdir -p /opt/jitsi
sudo chown $USER:$USER /opt/jitsi
cd /opt/jitsi
wget $(wget -q -O - https://api.github.com/repos/jitsi/docker-jitsi-meet/releases/latest | grep zip | cut -d\" -f4)
ls

The file is named after the release tag, for example stable- followed by a number. Unpack it and give the folder a fixed name so the Compose project name stays the same across updates:

Bash
unzip -q stable-*
mv jitsi-docker-jitsi-meet-* meet
cd meet

Step 3 — Create the .env file and generate passwords

Copy the example configuration and let the included script fill in random passwords for the internal service accounts:

Bash
cp env.example .env
./gen-passwords.sh
chmod 600 .env
grep -c "PASSWORD=." .env

The last command counts the password lines that now have a value; it should be greater than zero.

Step 4 — Set the domain, HTTPS and logins

Open .env with an editor (nano .env) and set the following values. Some lines exist already, others are commented out with # and must be uncommented:

.env
HTTP_PORT=80
HTTPS_PORT=443
TZ=UTC
PUBLIC_URL=https://meet.example.com
JVB_ADVERTISE_IPS=203.0.113.10
ENABLE_LETSENCRYPT=1
LETSENCRYPT_DOMAIN=meet.example.com
LETSENCRYPT_EMAIL[email protected]
ENABLE_AUTH=1
ENABLE_GUESTS=1
AUTH_TYPE=internal

What these do:

  • HTTP_PORT and HTTPS_PORT publish the web container on the standard ports, which Let's Encrypt requires.
  • PUBLIC_URL must be the real address users open.
  • JVB_ADVERTISE_IPS tells the videobridge which public IP to give to clients. Inside Docker the bridge sits behind NAT, and without this setting calls with three or more people often have no audio or video. Use your server's public IPv4 address.
  • ENABLE_AUTH=1 with AUTH_TYPE=internal makes Jitsi ask for a username and password before a room is created; ENABLE_GUESTS=1 still lets invited people join without an account.
  • TZ sets the time zone for logs; replace UTC with your own zone, for example Europe/Istanbul.

Step 5 — Create the configuration folders and start Jitsi

The containers run as UID/GID 1000 and refuse to start if their configuration folders are missing or not writable. Create them exactly as the handbook shows:

Bash
mkdir -p ~/.jitsi-meet-cfg/{web,prosody/config,prosody/prosody-plugins-custom,jicofo,jvb,jigasi,jibri,transcriber}
mkdir -p ~/.jitsi-meet-cfg/storage/{jibri,prosody,transcripts,web}
mkdir -p ~/.jitsi-meet-cfg/tmp/{web-crontabs,web-load-test}
chmod 777 ~/.jitsi-meet-cfg/storage/{jibri,prosody,transcripts,web}
chmod 777 ~/.jitsi-meet-cfg/tmp/{web-crontabs,web-load-test}

Start the stack and watch the web container request the certificate:

Bash
docker compose up -d
docker compose ps
docker compose logs -f web

All four core services (web, prosody, jicofo, jvb) should show as running. Press Ctrl+C to stop following the log once the certificate has been issued.

Step 6 — Create user accounts

Users are stored in the Prosody container. Create one account for each person who may start meetings; meet.jitsi is the internal XMPP domain of the Docker setup, not your public domain:

Bash
docker compose exec prosody prosodyctl --config /run/prosody/config/prosody.cfg.lua register alice meet.jitsi 'a-long-unique-password'

The command prints nothing when it succeeds. To remove an account, run the same command with unregister alice meet.jitsi instead of register.

Step 7 — Test a meeting

Open https://meet.example.com in a browser. The certificate should be valid (a padlock with no warning). Enter a room name and click Start meeting; Jitsi asks you to log in as the host. Use the account from Step 6.

Then join the same room from a phone on mobile data and from a third device. A call with three participants is the real test, because it is the first case where all media goes through the videobridge on UDP port 10000.

Back up and restore

Everything that is not in the images lives in two places:

  • the .env file in /opt/jitsi/meet (domain settings and the generated service passwords),
  • the configuration folder ~/.jitsi-meet-cfg (generated config, certificates and the Prosody user database).

Create a dated archive of both while the stack is stopped:

Bash
cd /opt/jitsi/meet
docker compose down
sudo mkdir -p /opt/backups
sudo tar czf /opt/backups/jitsi-$(date +%F).tar.gz -C / opt/jitsi/meet/.env -C $HOME .jitsi-meet-cfg
docker compose up -d

To restore on a new server, install Docker, download the same release (Step 2), extract the archive so that .env returns to /opt/jitsi/meet and .jitsi-meet-cfg to the admin user's home, and run docker compose up -d. Copy backups off the server as well.

Update Jitsi Meet

Each docker-jitsi-meet release pins a tested set of image versions, so updating means switching to the new release folder. Read the release notes on GitHub first and take a backup.

Bash
cd /opt/jitsi
wget $(wget -q -O - https://api.github.com/repos/jitsi/docker-jitsi-meet/releases/latest | grep zip | cut -d\" -f4)
unzip -q -o stable-NEW_NUMBER
cp meet/.env jitsi-docker-jitsi-meet-*/.env
cd meet
docker compose down
cd ..
mv meet meet-previous
mv jitsi-docker-jitsi-meet-* meet
cd meet
docker compose pull
docker compose up -d

Replace stable-NEW_NUMBER with the file name you just downloaded. Compare the new env.example with your .env and copy over any new settings you want. The handbook notes that when you come from a release older than stable-11146, you keep your configuration folder but must create the new storage and tmp folders from Step 5 before starting. Delete meet-previous once the new version works.

Troubleshooting

Calls work with two people but there is no audio or video with three

Two-person calls can run peer to peer; three or more always go through the videobridge. Check that UDP port 10000 is open in every firewall on the path, and that JVB_ADVERTISE_IPS contains the server's public IP. After changing .env, run docker compose up -d to recreate the containers.

The certificate is not issued

Run docker compose logs web and read the Let's Encrypt messages. The usual causes are a DNS record that does not point to this server yet, port 80 blocked or used by another program, or the Let's Encrypt rate limit after repeated attempts. Fix the cause and restart with docker compose restart web.

A container keeps restarting after an update

Since release stable-11146 the containers are hardened and need the storage and tmp folders from Step 5 with the permissions shown there. Create them, then run docker compose up -d again and check docker compose logs.

Anyone can still create rooms without logging in

The authentication settings are applied when the containers are created. Make sure ENABLE_AUTH=1 and AUTH_TYPE=internal are uncommented in .env, then run docker compose up -d --force-recreate.

Ports 80 or 443 are already in use

Another web server is running on the host. Stop it (sudo systemctl disable --now nginx or caddy), or run Jitsi behind that proxy: keep the web container on local ports, set ENABLE_LETSENCRYPT=0 and proxy the domain to the container's HTTPS port with WebSocket support.

Next steps

Frequently asked questions

How many participants can one Jitsi server handle?

The Jitsi project gives no fixed number. It depends on CPU, bandwidth and video quality: the handbook lists roughly 200 kbit/s per stream at 180p, 500 kbit/s at 360p and 2.5 Mbit/s at 720p. For large meetings Jitsi recommends adding more videobridges rather than one very large server.

Can guests join without an account?

Yes. With ENABLE_AUTH=1 and ENABLE_GUESTS=1 only registered users can start a room, and anyone with the link can join once the host is there.

Why does this guide use Docker instead of the Debian packages?

Both are official. With the packages, the simple secure-domain login is marked deprecated in the Jitsi handbook and the documented replacement is token authentication with Keycloak. The Docker setup has built-in user logins (AUTH_TYPE=internal) and keeps updates to a single release download.

Can I record meetings?

Recording uses a separate component, Jibri. Each simultaneous recording needs its own Jibri instance with at least 8 GB of RAM at 1280x720, and the handbook advises against running Jibri on the same server as Jitsi Meet.

Can I run Jitsi Meet behind my existing Caddy or Nginx?

Yes, but then the web container must not take ports 80 and 443. Keep HTTP_PORT and HTTPS_PORT on local ports, turn off ENABLE_LETSENCRYPT and proxy the domain to the HTTPS port with WebSocket support. Port 10000/udp must still reach the videobridge directly.

Sources

產生密碼

Please confirm