Self-hosting Jitsi Meet with Digital Ocean

Video conferencing usage is increasing exponentially. Google Hangouts has been my preferred tool however Google’s plans to phase it out in favor of their paid product Google Meet. Meanwhile Zoom is quickly becoming a household name. I don’t mind paying for a good solution, but neither Google or Zoom have a great reputation for respecting data privacy. I also don’t like that Google is officially abandoning Google Hangouts, which I currently use. So when I heard about Jitsi Meet, an open source alternative to Google Hangouts and Zoom, I was quite interested.

Hosted version of Jitsi Meet is ready to use however the self-hosted option grants complete control.

Most people would be fine to use Jitsi Meet’s online version. That said nothing compares to self-hosting. You are in control and you own the data. After watching this fantastic installation guide on YouTube I had Jitsi Meet running on my own Digital Ocean droplet. Here is a quick summary of what that looks like.

  • Spin up a new Digital Ocean droplet. I went with the $10/month server.
  • Point the DNS record over to Digital Ocean droplet. I configured this on a subdomain of anchor.host.
  • SSH to the Digital Ocean droplet and follow the official quick install guide and activate Let’s Encrypt for HTTPS.
  • And that’s it! After the installation is completed the new self-hosted Jitsi Meet server is ready to use from any browser. Simply share the URL with others and begin your video conference.

Customizing and upgrading Jitsi Meet

There doesn’t appear to be a built-in tool to configure Jitsi Meet. I bundled my own customization into a single bash script upgrade-jitsi.sh as shown below. This script upgrades Jitsi Meet to the latest version and then applies a few customization thereafter.

# Run Jitsi Meet updates
apt-get -y upgrade jigasi

# Apply customization to interface_config.js
cd /usr/share/jitsi-meet
sed -i "/    DEFAULT_BACKGROUND:/c\    DEFAULT_BACKGROUND: '#27c3f3'," interface_config.js
sed -i "/    SHOW_JITSI_WATERMARK:/c\    SHOW_JITSI_WATERMARK: false," interface_config.js
sed -i "/    SHOW_WATERMARK_FOR_GUESTS:/c\    SHOW_WATERMARK_FOR_GUESTS: false," interface_config.js
sed -i "/    APP_NAME:/c\    APP_NAME: 'Meet'," interface_config.js
sed -i "/    NATIVE_APP_NAME:/c\    NATIVE_APP_NAME: 'Meet'," interface_config.js
sed -i "/    RECENT_LIST_ENABLED:/c\    RECENT_LIST_ENABLED: false," interface_config.js

# Hide website from search engines
sed -i '/Allow:/d' robots.txt

Toggling Nginx maintenance mode instead of configuring Jitsi Meet authentication.

Out of the box Jitsi Meet is wide open. While the video calls are fully encrypted, anyone can create a video conference with anyone else if they know the self-hosted url. Fully open is not ideal. Locking down the robots.txt file, as shown above, is a good start.

Jitsi Meet has the ability of implementing an authentication system however that gets fairly complex. It also makes it more difficult to use with others participants. Instead, why not just turn off the entire Jitsi Meet instance when it’s not being used. That can be accomplished by enabling NGINX maintenance mode.

Start by creating the following maintenance-enabled.html and placing under /usr/share/jitsi-meet.

<html itemscope="" itemtype="http://schema.org/Product" prefix="og: http://ogp.me/ns#" xmlns="http://www.w3.org/1999/html">
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="css/all.css">
    <title>Meet</title>
</head>
<body class="welcome-page">
    <div class="welcome without-content" id="welcome_page">
        <div class="header">
        <div class="header-text">
            <h1 class="header-text-title">Conference Hangouts Offline</h1>
            <p class="header-text-description" style="text-align:center;display:block;">Waiting for organizer. Check back later.</p>
        </div>
        </div>
    </div>
</body>
</html>

Next we tell NGNIX to display this file for all requests when the file exists. Make the following customization to the /etc/nginx/sites-available/<domain>.conf file. Below the line error_page 404 /static/404.html; add the following:

    error_page 503 /maintenance-enabled.html;
    location = /maintenance-enabled.html {
    }

Next find the line that starts with location ~ ^/([^/?&:'"]+)$ { and add the following if statement to return HTTP 503 errors for all requests:

    location ~ ^/([^/?&:'"]+)$ {
        if (-f /usr/share/jitsi-meet/maintenance-enabled.html) {
            return 503;
        }
        try_files $uri @root_path;
    }

Restart NGINX /etc/init.d/nginx restart and you should see maintenance mode is enabled.

NGINX maintenance mode enabled
NGINX maintenance mode disabled

Now Jitsi Meet can be turned off by simply renaming maintenance-enabled.html to anything else. Here is a simple toggle-jitsi.sh script.

if [ -f /usr/share/jitsi-meet/maintenance-enabled.html ]; then
        echo "Enabling Jitsi Meet"
        mv /usr/share/jitsi-meet/maintenance-enabled.html /usr/share/jitsi-meet/maintenance-disabled.html
else
        echo "Disabling Jitsi Meet"
        /usr/share/jitsi-meet/maintenance-disabled.html /usr/share/jitsi-meet/maintenance.html
fi

Disposable video conferences powered by open source.

One the main advantages with this approach is the ability to spin up a video conference on your own private VPS whenever you wish. Participants simply click on a special link and then they’re in. Super simple to use. If anything breaks, the VPS can easily be deleted and recreated. No need to worry about losing any data.

While I haven’t tested it out yet, Jitsi Meet recommends keeping the participant number to less then 35. There is no hard cap, just a recommendation from them. Need to handle more participants? Then simply upgrade to a larger Digital Ocean droplet. I suspect that amount of participants you can get into a single conference call will vary greatly depending on the server resources and each participant’s bandwidth capacities. I don’t plan to push the limits or even come close. Three people in a group chat is plenty enough for me.