Prerequisites
Before you begin, make sure you have the following ready:
- A computer running macOS, Linux, or Windows
- Terminal or command-line access
- Administrator or sudo privileges (for system-level changes)
- A stable internet connection for downloading tools
Step 1 - Option 1: Jitsi Meet
Jitsi Meet is the most widely deployed self-hosted video conferencing platform.
- Browser-based: no account required for participants, and supports E2EE for small meetings.
- CPU and memory monitoring for Jitsi - The Jitsi Video Bridge (JVB) process is the most CPU-intensive component.
- Choose Jitsi Meet when: You need quick meeting links you can share with external participants who have no accounts.
- Choose Matrix + Element when: Your team needs persistent rooms, asynchronous chat alongside video, and the ability to federate with other Matrix servers.
Step 2 - Option 1: Jitsi Meet
Jitsi Meet is the most widely deployed self-hosted video conferencing platform. Browser-based, no account required for participants, and supports E2EE for small meetings.
Server Requirements
- 2+ CPU cores, 4GB RAM (for up to 50 concurrent users)
- Ubuntu 22.04 LTS recommended
- Domain with DNS pointing to the server
Install Jitsi Meet
Add Jitsi repository
curl https://download.jitsi.org/jitsi-key.gpg.key | \
sudo gpg --dearmor -o /usr/share/keyrings/jitsi-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/jitsi-keyring.gpg] \
https://download.jitsi.org stable/" | \
sudo tee /etc/apt/sources.list.d/jitsi-stable.list
sudo apt update
Install (this installs Jitsi + Nginx + Let's Encrypt)
sudo apt install jitsi-meet
When prompted:
- Enter your domain: meet.yourdomain.com
- Choose SSL certificate: Let's Encrypt (automated)
- Enter email for Let's Encrypt
That's it. Jitsi is running at https://meet.yourdomain.com
Harden Jitsi (Require Authentication)
By default, anyone can create rooms. Restrict room creation to authenticated users:
Edit Prosody authentication config
sudo nano /etc/prosody/conf.d/meet.yourdomain.com.cfg.lua
-- Change authentication from "anonymous" to "internal_hashed"
VirtualHost "meet.yourdomain.com"
authentication = "internal_hashed"
-- Keep guest access for participants (they can JOIN but not create)
VirtualHost "guest.meet.yourdomain.com"
authentication = "anonymous"
c2s_require_encryption = false
Create user accounts for hosts
sudo prosodyctl register alice meet.yourdomain.com SecurePass123
sudo prosodyctl register bob meet.yourdomain.com AnotherPass456
Edit Jicofo config to require auth for room creation
sudo nano /etc/jitsi/jicofo/jicofo.conf
jicofo {
authentication {
enabled = true
type = XMPP
login-url = meet.yourdomain.com
}
}
sudo systemctl restart prosody jicofo jitsi-videobridge2
Enable End-to-End Encryption
Jitsi supports E2EE for meetings with fewer than ~15 participants (requires browser’s Insertable Streams API):
/etc/jitsi/meet/meet.yourdomain.com-config.js
config.e2eping = { enabled: false };
config.e2ee = { labels: { } };
In the interface config:
interfaceConfig.DISABLE_FOCUS_INDICATOR = true;
Participants enable E2EE via the security icon (shield) in the bottom toolbar. All participants must enable it.
Step 3 - Option 2: Matrix + Element
Matrix is a federated, open protocol for real-time communication including video calls. Element is the primary client. Self-hosting Synapse (Matrix homeserver) gives you persistent rooms, team communication, and video via Jitsi integration or native WebRTC.
Install Synapse
Add Matrix repository
sudo apt install -y lsb-release wget apt-transport-https
wget -qO /usr/share/keyrings/matrix-org-archive-keyring.gpg \
https://packages.matrix.org/debian/matrix-org-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/matrix-org-archive-keyring.gpg] \
https://packages.matrix.org/debian/ $(lsb_release -cs) main" | \
sudo tee /etc/apt/sources.list.d/matrix-org.list
sudo apt update && sudo apt install matrix-synapse-py3
Configure
sudo nano /etc/matrix-synapse/homeserver.yaml
/etc/matrix-synapse/homeserver.yaml (key settings)
server_name: "yourdomain.com"
database:
name: psycopg2
args:
user: synapse
password: strong_db_password
database: synapse
host: localhost
Disable public registration (invite-only)
enable_registration: false
enable_registration_without_verification: false
Rate limiting
rc_messages_per_second: 0.2
rc_message_burst_count: 10
Logging
log_config: "/etc/matrix-synapse/log.yaml"
Create PostgreSQL database for Synapse
sudo -u postgres psql << 'SQL'
CREATE DATABASE synapse ENCODING 'UTF8' LC_COLLATE='C' LC_CTYPE='C' template=template0;
CREATE USER synapse WITH PASSWORD 'strong_db_password';
GRANT ALL PRIVILEGES ON DATABASE synapse TO synapse;
SQL
sudo systemctl enable --now matrix-synapse
Create admin user
register_new_matrix_user -c /etc/matrix-synapse/homeserver.yaml \
-u admin -p SecureAdminPassword -a http://localhost:8008
Set Up Nginx for Matrix
server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
# Matrix federation
location /_matrix {
proxy_pass http://127.0.0.1:8008;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 50M;
}
}
Federation port (Matrix server-to-server)
server {
listen 8448 ssl;
server_name yourdomain.com;
location / {
proxy_pass http://127.0.0.1:8008;
}
}
Video Calls in Matrix
Element uses WebRTC for 1:1 calls (peer-to-peer, no server involvement for the media). For group calls, integrate Jitsi:
In homeserver.yaml:
Point Jitsi to your self-hosted Jitsi Meet server
jitsi:
preferred_jitsi_domain: meet.yourdomain.com
In Element - Settings → Preferences → Jitsi → Use your own server
Enter - https://meet.yourdomain.com
Step 4 - Option 3: Galene (Minimal, for Small Groups)
Galene is a small, dependency-free video conferencing server written in Go. No WebRTC SFU complexity. runs as a single binary with minimal configuration. Suitable for small team calls (up to ~20 participants).
Download Galene
wget https://github.com/jech/galene/releases/latest/download/galene-linux-amd64.tar.gz
tar xzf galene-linux-amd64.tar.gz
cd galene
Generate TLS certificate (or use existing)
openssl req -newkey rsa:4096 -x509 -sha256 -days 3650 \
-nodes -out data/cert.pem -keyout data/key.pem \
-subj "/CN=your.domain.com"
Create a group (room)
mkdir -p groups
cat > groups/team.json << 'EOF'
{
"op": [{"password": "OperatorPassword123"}],
"presenter": [{"password": "PresenterPass"}],
"other": [{"password": "JoinPassword"}]
}
EOF
Start Galene
./galene -data data -groups groups
Default - listens on port 8443
Access - https://your.server.ip:8443/group/team
Operator/presenter/viewer have different permissions
Step 5 - Firewall Rules for Video Calling
Video calling requires additional ports:
Jitsi Meet required ports:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 4443/tcp # JVB (Jitsi Video Bridge) fallback
sudo ufw allow 10000/udp # JVB media traffic (primary)
Matrix:
sudo ufw allow 8448/tcp # Federation
Galene:
sudo ufw allow 8443/tcp # Web
sudo ufw allow 49152:65535/udp # WebRTC media (STUN/TURN)
Step 6 - TURN Server (Required Behind NAT)
Without a TURN server, participants behind strict NAT can’t connect (corporate firewalls, some ISPs):
Install coturn
sudo apt install coturn
/etc/turnserver.conf
listening-port=3478
tls-listening-port=5349
realm=turn.yourdomain.com
server-name=turn.yourdomain.com
cert=/etc/letsencrypt/live/yourdomain.com/fullchain.pem
pkey=/etc/letsencrypt/live/yourdomain.com/privkey.pem
lt-cred-mech
user=turnuser:TurnPassword
log-file=/var/log/turnserver.log
no-stdout-log
Start coturn
sudo systemctl enable --now coturn
Configure Jitsi to use your TURN server
/etc/jitsi/meet/meet.yourdomain.com-config.js:
config.p2p.stunServers = [
{ urls: "turn:turn.yourdomain.com:443?transport=tcp",
username: "turnuser",
credential: "TurnPassword" }
];
Step 7 - Monitor Server Health and Call Quality
After deploying a self-hosted video calling server, ongoing monitoring ensures call quality stays acceptable and the server doesn’t silently degrade. Video traffic is resource-intensive, and a server that looked adequate at setup may struggle under concurrent meetings.
CPU and memory monitoring for Jitsi - The Jitsi Video Bridge (JVB) process is the most CPU-intensive component. Set up a simple monitoring script that alerts you when resources are constrained:
#!/bin/bash
/usr/local/bin/jitsi-health.sh. run via cron every 5 minutes
JVB_CPU=$(ps aux | awk '/jitsi-videobridge/ && !/awk/ {print $3}')
JVB_MEM=$(ps aux | awk '/jitsi-videobridge/ && !/awk/ {print $4}')
LOAD=$(uptime | awk -F'load average:' '{print $2}' | cut -d, -f1 | tr -d ' ')
LOG="/var/log/jitsi-health.log"
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
echo "$TIMESTAMP CPU=${JVB_CPU}% MEM=${JVB_MEM}% LOAD=${LOAD}" >> "$LOG"
Alert if CPU exceeds 80%
if [ "$(echo "$JVB_CPU > 80" | bc -l)" -eq 1 ]; then
curl -s -d "Jitsi JVB CPU at ${JVB_CPU}%. check active meetings" \
https://ntfy.sh/your-jitsi-alerts
fi
Call quality testing - Use mtr to check the path quality to your server from clients’ locations before hosting important meetings:
Test UDP packet loss to your Jitsi server (port 10000 is JVB media)
sudo mtr --udp --port 10000 meet.yourdomain.com --report --report-cycles 20
More than 1-2% packet loss consistently will cause visible video artifacts. If you see packet loss, check whether your VPS provider has network issues, or whether a TURN relay is needed for specific clients.
Log rotation - Jitsi produces significant log output. Without rotation, logs fill disk over weeks:
/etc/logrotate.d/jitsi
/var/log/jitsi/*.log {
daily
rotate 7
compress
missingok
notifempty
sharedscripts
postrotate
systemctl reload jitsi-videobridge2 >/dev/null 2>&1 || true
endscript
}
Step 8 - Choose Between Jitsi, Matrix, and Galene
Each option in this guide serves different use cases. Choosing the wrong tool for your situation creates maintenance overhead without proportional privacy benefit.
Choose Jitsi Meet when - You need quick meeting links you can share with external participants who have no accounts. Jitsi is the closest drop-in replacement for Zoom, send a URL, participants join from the browser, meetings end and leave no persistent state.
Choose Matrix + Element when - Your team needs persistent rooms, asynchronous chat alongside video, and the ability to federate with other Matrix servers. Matrix has significantly higher setup complexity than Jitsi, but the result is a complete communication platform rather than just a video solution. If your team currently uses Slack and Zoom together, Matrix + Element can replace both.
Choose Galene when - You need a minimal, low-overhead solution for small trusted groups (your immediate team, family, or close collaborators). Galene requires almost no maintenance after setup, the binary has no external dependencies and uses minimal server resources. It is not suitable for meetings with external participants unfamiliar with the URL format.
Resource requirements comparison:
| Platform | Min RAM | CPU | Concurrent Users | Maintenance Load |
|---|---|---|---|---|
| Jitsi Meet | 4GB | 2 cores | 50+ | Medium |
| Matrix Synapse | 2GB | 1 core | Team-sized | High |
| Galene | 512MB | 1 core | ~20 | Low |
For most privacy-focused individuals or small teams, Jitsi on a $20/month VPS handles needs well. Teams with ongoing communication requirements that currently pay for Slack will find Matrix’s total cost of ownership competitive after the initial setup investment.
Troubleshooting
Configuration changes not taking effect
Restart the relevant service or application after making changes. Some settings require a full system reboot. Verify the configuration file path is correct and the syntax is valid.
Permission denied errors
Run the command with sudo for system-level operations, or check that your user account has the necessary permissions. On macOS, you may need to grant terminal access in System Settings > Privacy & Security.
Connection or network-related failures
Check your internet connection and firewall settings. If using a VPN, try disconnecting temporarily to isolate the issue. Verify that the target server or service is accessible from your network.
Related Articles
- How To Set Up Jitsi Meet Self Hosted Encrypted Video
- Jitsi Meet Self Hosted Setup Guide
- Best Secure Video Calling App 2026: A Technical Guide
- Nextcloud Talk Video Calls Setup Guide
- Youtube Alternative Private Video Platforms 2026
- Best Self-Hosted AI Model for JavaScript TypeScript Code Built by theluckystrike. More at zovo.one