Semaphor blog
Blog: Semaphor

Whiteboard on self-hosted Jitsi Meet server

The functionality of Jitsi Meet has been expanded with the new whiteboard feature which allows for collaborative drawing during a meeting. This is very helpful for conveying ideas - at times much more efficiently than words, making it a great (and fun) addition to the software. While these news are great, the handbook is - at the time of writing - unfortunately lacking some steps for self-hosted Jitsi instances. This post aims to be a short step-by-step to setting up this feature for your own Jitsi server. To keep the guide focused, it is assumed that you have basic knowledge of Jitsi, Prosody, Nginx and Linux services. This blog post would not be possible without this community post as well as this one.

Fig. 1. Brainstorming in a meeting

The first step is to clone the git repository, which can be found here. You can either host the backend on your Jitsi server or on a seperate machine. I recommend placing the git repo in the /opt/ directory under /opt/excalidraw-backend and creating a system user called "excali" by running
 $ sudo useradd -r excali 
remember to assign ownership of the excalidraw-backend directory to the newly created excali user, by running
 $ sudo chown -R excali:excali /opt/excalidraw-backend
Do not switch to the excali user, we merely need it for running the service after it is set up. Now hop in to the excalidraw-backend directory and build from souce by following the commands in the README. When this is done, make sure that you can start the service without issue, by running either
 $ sudo npm run start:dev 
which will launch the debug server, accompanied by verbose messages, or
 $ sudo npm run start
which will launch a production server. Note, that depending on whether you start the development or production server, the port that will be used is specified in the .env.development and .env.production files. The production file is not included in the git repo, so make a copy of the devolpment environment and name it ".env.production" (make sure this file is also owned by the excali user). These files should contain a single line
If you wish for the backend to listen on another port, change this value in both files. Now create a linux service that will run the backend using the excali user (credit to this community post):

ExecStart=/usr/bin/npm start

Remember to enable and start the service. Once the backend server is up and running, it is time to setup the reverse-proxy. Configure a site that will proxy-pass to the Excalidraw backend (credit to this community post) like this:
server {    
    listen 80;

    location / {
        return 301 https://$host$request_uri;

server {  
    listen 443 ssl;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;

    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:10m;  # about 40000 sessions
    ssl_session_tickets off;

    add_header Strict-Transport-Security "max-age=63072000" always;
    set $prefix "";

    ssl_certificate ...;
    ssl_certificate_key ...;

    location = / {
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $http_host;
        tcp_nodelay on;
Remember to replace the example domain with your Excalidraw server name and provide valid paths for for the SSL .key and .crt files. If you chose another port than 3002 ealier, be sure to replace the port in the / location as well. Alternatively, if you are hosting the backend on your Jitsi server, simply add the / location to your existing jitsi web-config. Once the site is configured remember to reload Nginx.

You should now have a reverse proxy setup that will handle and upgrade traffic from http(s) to a websocket, which is required for Excalidraw to work. In order for the whiteboard to work, your Prosody server must have the "room_metadata" prosody plugin enabled on your main virtual host (credit to this post). This may not be enabled by default. A guide on how to enable this component can be found in the very top of the .lua file found here, specifically your prosody must have the following inclusions:
VirtualHost ""
     modules_enabled = {
     room_metadata_component = ""
     main_muc = ""

Component "" "room_metadata_component"
     muc_component = ""
     breakout_rooms_component = ""
Remember to restart your Prosody service. Optionally, tail the /var/log/prosody/prosody.err file for any potential errors when restarting. Your Excalidraw should now be running as a system service, it should be reachable through Nginx and it should be supported by Prosody. Finally add the whiteboard button to your Jitsi meet instance by adding the following to your config.js:
whiteboard: {
    enabled: true,
    collabServerBaseUrl: ''
Moderators should now be able to show the whiteboard from the "More actions" tab. Typical pitfalls when setting up the whiteboard could be:
  • The connection fails to upgrade from HTTP to WebSocket - You can use your web browser's devtools and inspect the network tab's websocket section to see if the websocket is successfully established.
  • The Prosody metadata component setup is incorrect
  • The Node package manager version might be outdated, for building and running the backend. We use npm v.9.5.0
04-05-2023 16:10


Add comment

It may take a moment until your comment is published.