Self-Host Jitsi Meet: Video Conferencing Server 2026
TL;DR
Jitsi Meet (Apache 2.0, ~20K GitHub stars) is a fully-featured, self-hosted video conferencing platform. No account required to join calls. Works in the browser (WebRTC). Supports hundreds of participants, screensharing, chat, hand-raising, polls, and call recording (via Jibri). Zoom charges $15+/month per host license. Self-hosted Jitsi is free, unlimited meetings, unlimited participants.
Key Takeaways
- Jitsi Meet: Apache 2.0, ~20K stars — browser-based WebRTC video conferencing
- No account needed: Send a link, anyone joins from browser
- Unlimited: No meeting time limit, no participant cap (hardware-bound)
- Recording: Jibri (Jitsi Broadcasting Infrastructure) records to MP4
- JWT auth: Optional — require token to join (prevent random people from joining)
- Server requirements: 2 CPU + 4GB RAM for up to ~30 participants with decent quality
Jitsi Meet vs Zoom vs BigBlueButton
| Feature | Jitsi Meet | Zoom Pro | BigBlueButton |
|---|---|---|---|
| License | Apache 2.0 | Proprietary | LGPL 3.0 |
| Cost | Free (hosting) | $15/host/mo | Free (hosting) |
| Meeting time limit | None | 30h | None |
| Participant limit | Server-bound | 300 (Pro) | Server-bound |
| Recording | Jibri | Yes | Yes |
| Breakout rooms | Yes | Yes | Yes |
| Browser-based | Yes | Yes | Yes |
| Account to join | No | No | No |
| E2EE | Yes (small calls) | Yes (paid) | No |
| GitHub Stars | ~20K | — | ~9K |
Server Requirements
Jitsi is more CPU-intensive than most self-hosted apps:
| Participants | CPU | RAM |
|---|---|---|
| 1–10 | 2 cores | 2GB |
| 10–30 | 4 cores | 4GB |
| 30–100 | 8+ cores | 8GB |
| 100+ | Dedicated server | 16GB+ |
For most homelab/small team use, a 4-core VPS with 4GB RAM handles 30 participants comfortably.
Part 1: Docker Setup (Jitsi Docker Compose)
git clone https://github.com/jitsi/docker-jitsi-meet
cd docker-jitsi-meet
cp env.example .env
Edit .env:
# Public URL (required):
PUBLIC_URL=https://meet.yourdomain.com
# Timezone:
TZ=America/Los_Angeles
# XMPP domain:
XMPP_DOMAIN=meet.yourdomain.com
XMPP_AUTH_DOMAIN=auth.meet.yourdomain.com
XMPP_INTERNAL_MCS_DOMAIN=mcs.meet.yourdomain.com
XMPP_BOSH_URL_BASE=http://xmpp.meet.yourdomain.com:5280
# JVB (video bridge) settings:
JVB_ADVERTISE_IPS=YOUR_PUBLIC_IP # Your server's public IP
JVB_PORT=10000 # UDP port for media
# Optional — JWT authentication:
# ENABLE_AUTH=1
# AUTH_TYPE=jwt
# JWT_APP_ID=my_jitsi_app
# JWT_APP_SECRET=your-jwt-secret
# Generate secrets:
./gen-passwords.sh # Run this to generate random passwords
docker compose up -d
Part 2: HTTPS with Caddy
Jitsi's Docker setup includes a built-in web server on ports 80/443. With Caddy:
# In .env:
HTTP_PORT=8080
HTTPS_PORT=8443
meet.yourdomain.com {
reverse_proxy localhost:8080
}
Or use Jitsi's built-in HTTPS (Let's Encrypt via the web container):
# In .env:
LETSENCRYPT_DOMAIN=meet.yourdomain.com
LETSENCRYPT_EMAIL=admin@yourdomain.com
ENABLE_LETSENCRYPT=1
Part 3: Firewall Rules
Jitsi needs these ports open:
TCP 80 HTTP (redirect to HTTPS)
TCP 443 HTTPS (web and XMPP)
UDP 10000 Media (Jitsi Video Bridge)
TCP 4443 RTP fallback (if UDP blocked)
# Ubuntu UFW:
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow 10000/udp
ufw allow 4443/tcp
Part 4: Start a Meeting
Visit https://meet.yourdomain.com:
- Enter a room name:
team-standup - Click Start meeting
- Share the URL:
https://meet.yourdomain.com/team-standup
Anyone with the link joins from their browser — no account, no app required.
Part 5: Meeting Controls
| Feature | How to Access |
|---|---|
| Screenshare | Monitor icon in toolbar |
| Chat | Message icon → Chat sidebar |
| Raise hand | Hand icon |
| Tile view | Grid icon (top right) |
| Recording | 3-dot menu → Start recording (requires Jibri) |
| Livestream | 3-dot menu → Start livestream (requires Jibri) |
| Breakout rooms | 3-dot menu → Breakout rooms |
| Polls | 3-dot menu → Polls |
| Blur background | ... → Apply background effects |
Part 6: JWT Authentication
Prevent public access — require a token to join meetings:
# .env:
ENABLE_AUTH=1
AUTH_TYPE=jwt
JWT_APP_ID=my_jitsi_server
JWT_APP_SECRET=your-very-secure-jwt-secret
JWT_ACCEPTED_ISSUERS=my_jitsi_server
JWT_ACCEPTED_AUDIENCES=my_jitsi_server
Generate tokens in your app:
import jwt
import time
payload = {
"context": {
"user": {
"name": "John Smith",
"email": "john@example.com"
},
"room": "*" # Access to all rooms, or specify room name
},
"aud": "my_jitsi_server",
"iss": "my_jitsi_server",
"sub": "meet.yourdomain.com",
"room": "*",
"exp": int(time.time()) + 3600 # 1 hour expiry
}
token = jwt.encode(payload, "your-very-secure-jwt-secret", algorithm="HS256")
# Meeting URL: https://meet.yourdomain.com/room-name?jwt=TOKEN
Part 7: Recording with Jibri
Jibri records meetings to MP4 using a headless Chrome browser.
Additional requirements for Jibri:
- Extra RAM: ~2GB per recording instance
- Linux kernel module
snd_alooploaded:sudo modprobe snd_aloop
# Enable in .env:
ENABLE_RECORDING=1
JIBRI_RECORDER_PASSWORD=your-recorder-password
JIBRI_XMPP_PASSWORD=your-jibri-password
# Jibri stores recordings:
JIBRI_RECORDING_DIR=/srv/recordings
# Activate Jibri service in docker-compose.yml:
docker compose --profile jibri up -d
Recordings are saved to /srv/recordings/ on the host.
Part 8: Customize Branding
# .env:
JITSI_WATERMARK_LINK=https://yourdomain.com
DEFAULT_BACKGROUND=#1d1d1d
# Custom interface config:
# Mount custom config.js:
volumes:
- ./config/custom-config.js:/config/custom-config.js
// custom-config.js
config.defaultLanguage = 'en';
config.startWithAudioMuted = true; // Muted by default
config.startWithVideoMuted = true; // Camera off by default
config.requireDisplayName = true; // Force participants to enter a name
config.prejoinPageEnabled = true; // Pre-join lobby
config.disableDeepLinking = true; // No app download prompts
Maintenance
# Update Jitsi:
cd docker-jitsi-meet
git pull
docker compose pull
docker compose up -d
# Check logs:
docker compose logs -f web jvb prosody jicofo
# Check JVB stats (Video Bridge):
curl http://localhost:8080/about/stats
See all open source video conferencing tools at OSSAlt.com/alternatives/zoom.