Host your own Jitsi server via Docker behind an Nginx reverse proxy

Secure your communications by making your data your own

14-10-2021 - 4 minutes, 16 seconds -


This article assumes a fresh apt-based server install and basic knowledge regarding the command line. The rest will be explained to you.

Secure your server:

Create an SSH key pair to use so that you can disable password login and login with your key only. This removes an attack vector from your server.

Create the key pair on the client machine:

ssh-keygen -t rsa -b 4096

Install the public key onto your server:

ssh-copy-id -i $HOME/.ssh/ <username>@<serveraddress>

Now login to your server to make sure your key is recognized:

ssh <username>@<serveraddress>

Disable password and root based logins:

sudo nano /etc/ssh/sshd_config

Find the following lines and change them accordingly:

ChallengeResponseAuthentication no
PasswordAuthentication no
UsePAM no
PermitRootLogin no

Save and close the file then restart the SSH server:

sudo systemctl reload ssh

Install fail2ban. Fail2ban will ban IPs that attempt to repeatedly login to your server without the correct key.

sudo apt update
sudo apt install fail2ban

The default configuration is fine. You can find the fail2ban log within /var/log/fail2ban.log.

Configuring your reverse proxy:

Next you'll want to proxy your connection instead of giving your server a wide open face to the internet. If you don't have a proxy yet and want to get one up and running quickly, I recommend this simple article.

I do not recommend using Jitsi's built-in Let's Encrypt services. Doing so gives you much less flexibility down the line. I do recommend encryption, but via your own proxy. Whether you decide to install Nginx on your host machine or a separate server will not affect your Nginx config except for where you proxy your address from. I will assume in this article you have Nginx installed on the Jitsi host and so will use localhost. Feel free to use the appropriate address if this is not the case.

First you'll need to make a change to your nginx.conf as it will not contain the connection_upgrade variable by default:

sudo nano /etc/nginx/nginx.conf

We need to add the following map block:

map $http_upgrade $connection_upgrade {  
    default upgrade;
    ''      close;

into the http block of your configuration like so:

user www-data;  
worker_processes auto;  
pid /run/;

events {  
        multi_accept       on;
        worker_connections 65535;

http {  
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;

        # Connection header for WebSocket reverse proxy
+       map $http_upgrade $connection_upgrade {
+           default upgrade;
+           ''      close;
+       }

        # further configurations …

Save the file and test nginx:

sudo nginx -t

If everything comes back ok, you're good.

Next create a new conf within /etc/nginx/sites-available/ for your Jitsi domain or subdomain. I'll be using a subdomain in the following example.

sudo nano /etc/nginx/sites-available/

Paste the following into your new configuration file substituting your domain where necessary:

server {

    location / {
    proxy_pass_header Authorization;
    proxy_pass http://localhost:8000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_http_version 1.1;
    proxy_set_header Connection “”;
    proxy_buffering off;
    client_max_body_size 0;
    proxy_read_timeout 36000s;
    proxy_redirect off;

   location /xmpp-websocket {
        proxy_pass http://localhost:8000/xmpp-websocket;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

   location /colibri-ws {
        proxy_pass http://localhost:8000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

Symlink your new conf to /etc/nginx/sites-enabled:

sudo ln -s /etc/nginx/sites-available/ /etc/nginx/sites-enabled/

You'll need to get certbot next to install your certificates for your domain. The snap package is the easiest way to install certbot. I'm using Debian so will install snapd. On Ubuntu snap is installed by default so you can skip the snapd installation steps.

sudo apt install snapd
sudo snap install core

Test to make sure it's valid

sudo snap install hello-world

Install certbot:

sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

Go ahead and forward ports 80 TCP, 443 TCP, 20000-20050 UDP, and 10000 UDP in your router to your server now. Get your certs.

sudo certbot --nginx

Certbot will list your Jitsi nginx conf. Choose it and you should now have SSL for HTTPS.

Restart nginx

sudo systemctl restart nginx

Install Docker and Jitsi Meet:

Follow the instructions here to install docker on your distro of choice. You will also need docker-compose

Download and extract the latest stable release of docker-jitsi-meet to your home folder:

wget ""
tar -xzvf stable-6173.tar.gz
cd docker-jitsi-meet-stable-6173

Copy env.example to .env, automatically generate strong passwords for client connections within the .env file, and then create the required directories:

cp env.example .env
mkdir -p ~/.jitsi-meet-cfg/{web/letsencrypt,transcripts,prosody/config,prosody/prosody-plugins-custom,jicofo,jvb,jigasi,jibri}
nano .env

Adjust the following parameters within your .env:


Save the .env then create your container:

sudo docker-compose up -d

Issue sudo docker ps to list your containers and make sure everything is up and running.

Next create your first user:

sudo docker-compose exec prosody /bin/bash
prosodyctl --config /config/prosody.cfg.lua register <yourusername> meet.jitsi <yourpassword>

To delete a user while in the container:

prosodyctl --config /config/prosody.cfg.lua unregister <username> meet.jitsi

To list all users while in the container:

find /config/data/meet%2ejitsi/accounts -type f -exec basename {} .dat \;

You should now be able to go to your new Jitsi domain and start a meeting. It will ask you to authenticate yourself, enter the username and password you selected and give your browser the mic and camera permissions.