{"id":3204,"date":"2026-04-11T22:13:24","date_gmt":"2026-04-12T02:13:24","guid":{"rendered":"https:\/\/smegnl.medina.oh.us\/?p=3204"},"modified":"2026-04-11T22:22:57","modified_gmt":"2026-04-12T02:22:57","slug":"mattermost-and-jaas","status":"publish","type":"post","link":"https:\/\/smegnl.medina.oh.us\/?p=3204","title":{"rendered":"MatterMost and Jaas"},"content":{"rendered":"\n<p>I set up a MatterMost server and wanted to use Jist as a Service (Jaas) and did not find a lot of info on doing this. So here is what I did, cuz I gotta write crap down.<\/p>\n\n\n\n<p>I used a MatterMost turnkey Linux download from Proxmox. <br>I then signed up for JaaS at this site: <a href=\"https:\/\/jaas.8x8.vc\">https:\/\/jaas.8&#215;8.vc<\/a><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Jaas vs Jist vs Jist meet<br><\/h3>\n\n\n\n<p>There are 3 versions of Jist. Self hosted Jist (here in called Jist), online Jist (here in called Jist Meet), and Jist as a service (here in called JaaS). <br>MatterMost comes with a plugin that can be added that supports Jist. I thought I was going to be using this, but came to find out, that does not entirely work with Jist Meet or JaaS. I wanted to use Jist Meet or JaaS vs Jist as I did not want all that bandwidth running in and out of my network. With Jist, all video come back to my MatterMost\/Jist server and then back out to the end user. With Jist Meet and JaaS, the connections are made in the cloud.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The Plugin <\/h3>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"731\" height=\"878\" src=\"https:\/\/smegnl.medina.oh.us\/wp-content\/uploads\/2026\/04\/matter1.png\" alt=\"\" class=\"wp-image-3206\" srcset=\"https:\/\/smegnl.medina.oh.us\/wp-content\/uploads\/2026\/04\/matter1.png 731w, https:\/\/smegnl.medina.oh.us\/wp-content\/uploads\/2026\/04\/matter1-83x100.png 83w\" sizes=\"auto, (max-width: 731px) 100vw, 731px\" \/><\/figure>\n\n\n\n<p>As I said, this plugin is for Jist, it does work with Jist Meet and does not work well with JaaS. You still need the plugin to set some of the parameters though. The main problem is with the &#8220;Use JWT Authentication for Jitsi&#8221;.  Jist Meet would prompt for a Google Login. With JaaS it would prompt for my JaaS login which would not work as I am the only one with a login. Then by playing around with the App Secret Key and App Secret ID, the Jitsi server URL pointing it to JaaS, and turning off &#8220;Use JWT Authentication for Jitsi&#8221;,  I got it to connect without prompting for login . Problem was, no one was being set as a room manager. That meant no setting lobbies, or muting people, or kicking people. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Jaas \/ 8&#215;8.vc<\/h3>\n\n\n\n<p>Go to 8&#215;8.vc and sign up for the free Jaas.  The free account gets you 25 MAU per month. They define a MAU as<br><em><strong>A Monthly Active User (MAU)<\/strong>&nbsp;is defined as a unique user who attended at least one meeting, with at least one other user, in the same month.&nbsp;A user is defined as a unique endpoint<\/em><br>I believe they count a MAU as any person + any client. So if a user were to use Ffox and Chrome PWA and the desktop client on the same PC, that would be 3 MAU for that user. The MAU resets each month.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"972\" height=\"763\" src=\"https:\/\/smegnl.medina.oh.us\/wp-content\/uploads\/2026\/04\/matter2.png\" alt=\"\" class=\"wp-image-3209\" srcset=\"https:\/\/smegnl.medina.oh.us\/wp-content\/uploads\/2026\/04\/matter2.png 972w, https:\/\/smegnl.medina.oh.us\/wp-content\/uploads\/2026\/04\/matter2-100x78.png 100w, https:\/\/smegnl.medina.oh.us\/wp-content\/uploads\/2026\/04\/matter2-768x603.png 768w\" sizes=\"auto, (max-width: 972px) 100vw, 972px\" \/><\/figure>\n\n\n\n<p>Once you make your account, you will have an AppID.  You can then generate a API key. You MUST download the private key when you generate the API. It is not downloadable after the fact. <br>Back on MatterMost Jisti app:<br>You will put the APP ID in the Jitsi plugin under &#8220;App ID for JWT Authentication&#8221; . <br>You will past the entire, including the ==begin and the ==end, into the &#8220;AP Secret for JWT  Authentication&#8221;<br>In the &#8220;Jitsi Server URL&#8221; you would put in your server url if self hosting Jisti or <a href=\"https:\/\/meet.jit.si\">https:\/\/meet.jit.si<\/a> if using Jitsi Meet, or 8&#215;8.vc if using JaaS. But as previously stated, Jitsi meet or Jaas requires a Google login or Jaas login, respectively.<br>So I was at a dead end.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The app.js (version 1)<\/h3>\n\n\n\n<p>Enter the app.js. I wrote a small js to run and generate the JWT since I could not get the Jist app to work with JaaS. Here is the Code:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>\/\/ ==BLOCK1=====<\/strong>\n\/\/ === set constants===\nconst https = require('https');\nconst fs = require('fs');\nconst express = require('express');\nconst jwt = require('jsonwebtoken');\nconst app = express();\n\n<strong>\/\/ ====BLOCK2===<\/strong>\n\/\/ === 8x8 App credentials ===\nconst APP_ID = \"vpaas-magic-cookie-123456\"; \nconst KID = \"vpaas-magic-cookie-123456\/aabbcc\"; \n\n\/\/ === Load private key for JWT signing ===\nconst PRIVATE_KEY = fs.readFileSync(\".\/private.pk\");\n\n\/\/ === Load Let's Encrypt certificates ===\nconst options = {\n  key: fs.readFileSync(\"\/dir\/letsencrypt-key.pem\"),\n  cert: fs.readFileSync(\"\/dir\/combined-bundle.pem\")\n};\n<strong>\/\/ ===BLOCK 3===<\/strong>\n\/\/ === Jitsi redirect route ===\napp.get(&#91;'\/jitsi', '\/jitsi\/:room'], (req, res) =&gt; {\n    \/\/ This grabs the room name if Mattermost sends it, otherwise generates a random one\n    const room = req.params.room || Math.random().toString(36).substring(2, 10);\n    const username = \"Type Your Name\";\n    const email = \"user@example.com\";\n<strong>\/\/ === Block 4 ===<\/strong>\n    const payload = {\n        aud: \"jitsi\",\n        iss: \"chat\",\n        sub: APP_ID,\n        room: \"*\",\n        exp: Math.floor(Date.now() \/ 1000) + 3600,\n        context: { \n            user: { \n                name: username, \n                email: email, \n                moderator: true \n            } \n        }\n    };\n\n    const token = jwt.sign(payload, PRIVATE_KEY, {\n        algorithm: 'RS256',\n        header: { kid: KID }\n    });\n\n    const url = `https:\/\/8x8.vc\/${APP_ID}\/${room}?jwt=${token}`;\n    res.redirect(url);\n});\n<strong>\/\/ == Block 5 ==<\/strong>\n\/\/ === Start HTTPS server on port 3000 ===\nhttps.createServer(options, app).listen(3000, () =&gt; {\n    console.log(\"Jitsi proxy HTTPS running on port 3000\");\n});<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The first &#8220;block&#8221; sets some constants to be use.<\/li>\n\n\n\n<li>The second &#8220;block&#8221; set the API and keys needed for JaaS and SSL<\/li>\n\n\n\n<li>The third &#8220;block&#8221; sets the room name to be used and name to be used in the room. MatterMost should set a room name. In case it fails, a name is generated. I could not get MatterMost to pass the MatterMost username to JaaS. So I hard coded &#8220;Type Your Name&#8221; to show in the connection box. <\/li>\n\n\n\n<li>The 4th block is what gets packed in the JWT. \n<ul class=\"wp-block-list\">\n<li>aud: tells 8&#215;8 that I am using the jitsi part of my JaaS account<\/li>\n\n\n\n<li>iss: tells JaaS it was issued by chat integration<\/li>\n\n\n\n<li>sub: tells JaaS that the subject is my APP_ID<\/li>\n\n\n\n<li>room: tell JaaS what room this is good for<\/li>\n\n\n\n<li>exp: says how long the JWT is good for<\/li>\n\n\n\n<li>user: adds the user name, email set above. It also sets everyone as a moderator, in my case<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>The 5th block starts the app.js <br><br>The last thing to do is back in the Jist MatterMost app is to point the Jistsi server ULL to the app.js. I am running mine on the MatterMost server on port :3000. Thus it would be something like<br> HTPS:\/\/mattermost.server:3000<br><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Reverse Proxy<\/h3>\n\n\n\n<p>MatterMost runs on port 8065 by default. It does not run on Https. I also already have a webserver using port 443 and I only have 1 IP coming in from the outside. Thus I could not run MatterMost on 443. So I set up a reverse proxy using nginx on 4433 and pointed it to 8065. This worked well, but users had to go to Https:\/\/mattermost.server:4433 and it just looked clunky and I had port 3000 open for the app.js, though at least it was using a cert.  I wanted to close off ports 8065 and 3000 from being open on my firewall\/router to the internet.<\/p>\n\n\n\n<p>I decided to set up my original web server that is running on port 443 as a revers proxy and point it to Matter most. Set up like this pic&#8230;<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"474\" height=\"451\" src=\"https:\/\/smegnl.medina.oh.us\/wp-content\/uploads\/2026\/04\/matter3.png\" alt=\"\" class=\"wp-image-3219\" srcset=\"https:\/\/smegnl.medina.oh.us\/wp-content\/uploads\/2026\/04\/matter3.png 474w, https:\/\/smegnl.medina.oh.us\/wp-content\/uploads\/2026\/04\/matter3-100x95.png 100w\" sizes=\"auto, (max-width: 474px) 100vw, 474px\" \/><\/figure>\n\n\n\n<p> Traffic comes in from the interwebs on port 80 or port 443. All traffic goes to my web server first. If it is for my website, it stays on that web server. If its on https and is for the Mattermost server, it gets proxied over http to the MatterMost server. The MatterMost server also runs a proxy. It takes the http\/port 80 traffic and routes it to either the MatterMost server on port 8065 or the app.js on port 3000.<\/p>\n\n\n\n<p>There are 3 parts to this. The web server is running a reverse proxy using Apache. The MatterMost server is running a reverse proxy running on NGINX. The app.js on the MatterMost server got an updated config file.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Apache Reverse Proxy<\/h3>\n\n\n\n<p>I thought reverse proxy were some hard magical-like-unicorns thing. Its not, its just part of the &lt;VirtualHost&gt; in the Apache config file. The web server run on Ubuntu, so the Apache config file is located in \/etc\/apache2\/sites-available\/. I am using the 000-default.conf. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># ---------------------------------------------------------\n# <strong>1. LOCAL WEBSITE: www.site.com<\/strong>\n# ---------------------------------------------------------\n&lt;VirtualHost *:443&gt;\n    ServerName www.site.com\n    DocumentRoot \/var\/www\/html\n\n    SSLEngine on\n    SSLCertificateFile \/dir\/combined-bundle.pem\n    SSLCertificateKeyFile \/dir\/letsencrypt-key.pem\n\n    &lt;Directory \/var\/www\/html&gt;\n        Options Indexes FollowSymLinks\n        AllowOverride All\n        Require all granted\n    &lt;\/Directory&gt;\n&lt;\/VirtualHost&gt;\n\n# ---------------------------------------------------------\n# 2. <strong>PROXY FOR MATTERMOST: mattermost.site.com<\/strong>\n# ---------------------------------------------------------\n&lt;VirtualHost *:443&gt;\n    ServerName mattermost.site.com\n\n    SSLEngine on\n    SSLCertificateFile \/dir\/combined-bundle.pem\n    SSLCertificateKeyFile \/dir\/letsencrypt-key.pem\n\n    #<em> 1. SSL Proxy Logic (No longer strictly needed for Server B, but fine to leave)<\/em>\n    SSLProxyEngine On\n    SSLProxyVerify none \n    SSLProxyCheckPeerCN off\n    SSLProxyCheckPeerName off\n    SSLProxyCheckPeerExpire off\n\n    # 2. <em>Modern Proxy Logic<\/em>\n    ProxyPreserveHost On\n    ProxyRequests Off\n    \n    #<em> Updated Jitsi Bridge (Point to HTTP)<\/em>\n    ProxyPass \/jitsi http:\/\/192.168.1.156\/jitsi\n    ProxyPassReverse \/jitsi http:\/\/192.168.50.156\/jitsi\n\n    # <em>Updated General Mattermost Proxy (Point to HTTP)<\/em>\n    ProxyPass \/ http:\/\/192.168.1.123\/\n    ProxyPassReverse \/ http:\/\/192.168.1.123\/\n\n    # 3.<em> Secure Headers (CRITICAL: This tells Mattermost it is SECURE even though internal link is HTTP)<\/em>\n    RequestHeader set X-Forwarded-Proto \"https\"\n    RequestHeader set X-Forwarded-Port \"443\"\n\n    # Updated WebSockets for the Mattermost client (Use ws:\/\/ instead of wss:\/\/)\n    RewriteEngine On\n    RewriteCond %{HTTP:Upgrade} =websocket &#91;NC]\n    RewriteRule \/(.*)           ws:\/\/192.168.1.123\/$1 &#91;P,L]\n\n    ErrorLog ${APACHE_LOG_DIR}\/matter_error.log\n&lt;\/VirtualHost&gt;\n\n# ---------------------------------------------------------\n# 3. <strong>HTTP TO HTTPS REDIRECT <\/strong>\n# ---------------------------------------------------------\n&lt;VirtualHost *:80&gt;\n    ServerAdmin webmaster@localhost\n    DocumentRoot \/var\/www\/html\n\n    # This catch-all redirector sends ANY site on this server to its HTTPS version\n    RewriteEngine On\n    RewriteCond %{HTTPS} off\n    RewriteRule ^(.*)$ https:\/\/%{HTTP_HOST}$1 &#91;R=301,L]\n\n    ErrorLog ${APACHE_LOG_DIR}\/error.log\n    CustomLog ${APACHE_LOG_DIR}\/access.log combined\n&lt;\/VirtualHost&gt;<\/code><\/pre>\n\n\n\n<p>This is in 3 parts. <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Part 1 keeps the https traffic meant for my web server on the server.<\/li>\n\n\n\n<li>Part 2 This sets up and proxys over https traffic to the MatterMost server.\n<ul class=\"wp-block-list\">\n<li>top of that section loads up the SSL certs needed. I will talk later about the combined cert.<\/li>\n\n\n\n<li>1- is the old part where I was talking SSL between servers. Not really needed by left.<\/li>\n\n\n\n<li>2- sets up some proxy perimeters:<br><em><strong>ProxyPreserveHost<\/strong> <strong>On<\/strong><\/em>-tells the proxy to leave original full domain name in the proxy. Without this it might send the IP or truncated name. NGINX would get confused<br><em><strong>ProxyRequests Off<\/strong><\/em>-this stops other people form using the proxy and locks it to this specific site, mattermost.site.com<br> <em><strong>ProxyPass<\/strong><\/em> and <strong><em>ProxyPassReverse<\/em> <\/strong>&#8211; tell the web server where to send the data <\/li>\n\n\n\n<li>3- sets up some SSL trickery to pass to MatterMost<br><em><strong>RequestHeader set X-Forwarded-Proto &#8220;https&#8221;<\/strong><\/em>-tells MatterMost that its ok to generate all its links with https even though the incoming request are http<br><em><strong>RequestHeader set X-Forwarded-Port &#8220;443&#8221;<\/strong><\/em>-tells MatterMost to keep working on 443 and not 80<br><strong><em>Rewrite<\/em><\/strong>-This is where the proxy tells MatterMost to stop using HTTP and switch to websocket<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Part 3 This tells the web server to move all port 80 request over to 443. This may become a problem when I go to do a SSL cert renewal.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">NGINX Reverse Proxy<\/h3>\n\n\n\n<p>The MatterMost server runs NGINX on Debian. Here is its reverse proxy located in \/etc\/nginx\/sites-enabled\/<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>server {\n    listen 80;\n    server_name mattermost.site.com;\n\n   <strong> # Logic for Jitsi Proxy<\/strong>\n    location \/jitsi\/ {\n        proxy_pass http:\/\/127.0.0.1:3000\/; \n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto https;\n\n        proxy_http_version 1.1;\n        proxy_set_header Upgrade $http_upgrade;\n        proxy_set_header Connection \"upgrade\";\n        proxy_buffering off;\n    }\n\n  <strong>  # Logic for Mattermost<\/strong>\n    location \/ {\n        client_max_body_size 50M;\n        proxy_read_timeout 600s;\n        proxy_send_timeout 600s;\n        send_timeout       600s;\n\n        proxy_set_header Upgrade $http_upgrade;\n        proxy_set_header Connection \"upgrade\";\n        proxy_set_header Host $http_host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto \"https\"; \n        \n        proxy_pass http:\/\/127.0.0.1:8065;\n    }\n}<\/code><\/pre>\n\n\n\n<p>It has two parts. Jitsi and MatterMost settings for the reverse proxy. It should be noted that they MUST be in this order. <\/p>\n\n\n\n<p><strong>Logic for Jitsi Proxy<\/strong>&#8211; <br><strong><em>location \/jitsi\/<\/em><\/strong>-says apply these setting to request in the format of matter.server.com\/jitsi<br><strong><em>proxy_pass http:\/\/127.0.0.1:3000\/;<\/em><\/strong> &#8211; forward to port 3000, the node.js app<br><strong><em>proxy_set_header Host $host;<\/em><\/strong>-keeps the domain name<br><strong><em>proxy_set_header X-Real-IP $remote_addr;<\/em><\/strong>-passes the IP address of the user<br><strong><em>proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<\/em><\/strong>-like a log to tell how the user got here<br><strong><em>proxy_set_header X-Forwarded-Proto https<\/em><\/strong>;-same as Apache. Use https not http<br><strong><em>proxy_http_version 1.1;<\/em><\/strong>-use this version because it supports websockets<br><strong><em>proxy_set_header Upgrade $http_upgrade<\/em><\/strong>;-move from http to websockets<br><strong><em>proxy_set_header Connection &#8220;upgrade&#8221;;<\/em><\/strong>-move from http to websockets<br><strong><em>proxy_buffering off<\/em><\/strong>-do it, do it now<\/p>\n\n\n\n<p><strong>Logic for Mattermost<\/strong><\/p>\n\n\n\n<p><strong><em>client_max_body_size 50M;<\/em><\/strong>-sets max attachment size, like a pdf<br><strong><em>Timeout<\/em><\/strong>-all of these lines keep the websocket open for 10min. I was seeing some resend errors in chat<br><strong><em>proxy_set_header<\/em><\/strong>&#8211; all of these do the same we explained above and in Apache<br><strong><em>proxy_pass http:\/\/127.0.0.1:8065;<\/em><\/strong>-send the stuff to MatterMost software running on port 8065<br><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The app.js (version 2)<\/h3>\n\n\n\n<p>Now that users were not going directly to the MatterMost server to run JaaS directly, I needed to update the app.js from above.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const http = require('http'); <strong>\/\/ 1. Changed from https to http<\/strong>\nconst fs = require('fs');\nconst express = require('express');\nconst jwt = require('jsonwebtoken');\n\nconst app = express();\n\n<strong>\/**\n * CRITICAL: This tells Express to trust the headers sent by Nginx.\n *\/<\/strong>\napp.set('trust proxy', true);\n\n<strong>\/\/ === 8x8 App credentials ===<\/strong>\nconst APP_ID = \"vpaas-magic-cookie-123456\"; \nconst KID = \"vpaas-magic-cookie-123456\/aabbcc\";  \n\n<strong>\/\/ === Load private key for JWT signing ===<\/strong>\nconst PRIVATE_KEY = fs.readFileSync(\".\/private.pk\");\n\n<strong>\/\/ --- NOTE: Certificate loading removed from here ---<\/strong>\n\n<strong><em>\/\/ === Jitsi redirect route ===<\/em><\/strong>\napp.get(&#91;'\/', '\/:room'], (req, res) =&gt; {\n    const room = req.params.room;\n\n    if (!room || room === 'jitsi') {\n        return res.send('Jitsi Bridge is active. Waiting for a room name from Mattermost...');\n    }\n\n    const username = \"Type Your Name\";\n    const email = \"user@example.com\";\n\n    const payload = {\n        aud: \"jitsi\",\n        iss: \"chat\",\n        sub: APP_ID,\n        room: \"*\",\n        exp: Math.floor(Date.now() \/ 1000) + 3600,\n        context: { \n            user: { \n                name: username, \n                email: email, \n                moderator: true \n            } \n        }\n    };\n\n    const token = jwt.sign(payload, PRIVATE_KEY, {\n        algorithm: 'RS256',\n        header: { kid: KID }\n    });\n\n    const url = `https:\/\/8x8.vc\/${APP_ID}\/${room}?jwt=${token}`;\n    \n   res.send(`\n&lt;!DOCTYPE html&gt;\n&lt;html&gt;\n&lt;head&gt;\n    &lt;title&gt;Meeting Launcher&lt;\/title&gt;\n    &lt;style&gt;\n        body { background-color: #141517; color: white; font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; }\n        .container { text-align: center; padding: 20px; }\n        .loader { border: 4px solid #3d3d3d; border-top: 4px solid #3895ff; border-radius: 50%; width: 30px; height: 30px; animation: spin 1s linear infinite; margin: 20px auto; }\n        @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }\n        .btn { display: inline-block; margin-top: 20px; padding: 12px 24px; background-color: #166de0; color: white; text-decoration: none; border-radius: 4px; font-weight: bold; transition: background 0.2s; }\n        .btn:hover { background-color: #1a7fa0; }\n        .status-text { opacity: 0.8; font-size: 0.95em; line-height: 1.5; }\n    &lt;\/style&gt;\n    &lt;script type=\"text\/javascript\"&gt;\n        window.open(\"${url}\", \"_blank\");\n        setTimeout(function() {\n            const loader = document.querySelector('.loader');\n            const title = document.querySelector('h2');\n            const status = document.querySelector('.status-text');\n            const button = document.querySelector('.btn');\n            if (loader) loader.style.display = 'none';\n            if (title) title.innerText = 'Meeting Launched';\n            if (status) status.innerHTML = 'We attempted to open the meeting in a new window.&lt;br&gt;If you are already in the meeting, you can close this tab.';\n            if (button) button.innerText = 'RE-OPEN MEETING MANUALLY';\n        }, 2000);\n    &lt;\/script&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n    &lt;div class=\"container\"&gt;\n        &lt;div class=\"loader\"&gt;&lt;\/div&gt;\n        &lt;h2&gt;Launching Meeting...&lt;\/h2&gt;\n        &lt;p class=\"status-text\"&gt;Opening your default browser for camera and microphone support.&lt;\/p&gt;\n        &lt;a href=\"${url}\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"btn\"&gt;\n            OPEN MEETING MANUALLY\n        &lt;\/a&gt;\n    &lt;\/div&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;\n`);\n});\n\n<strong>\/\/ === Start HTTP server on port 3000 (options removed) ===<\/strong>\nhttp.createServer(app).listen(3000, () =&gt; {\n    console.log(\"Jitsi proxy HTTP running on port 3000\");\n});<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The first part is basically the same as above.  Also notice the change from httpS to http<\/li>\n\n\n\n<li>The second part loads the API and Key for JaaS. You will note that the SSL certs were removed.<\/li>\n\n\n\n<li>The third part still sets up the room and user names. I did still have to use &#8220;Type Your Name&#8221;<\/li>\n\n\n\n<li>The 4th part does the same as the 4th part in version1. It sets what gets packed into the JWT.<\/li>\n\n\n\n<li>The 5th part, &lt;!DOCTYPE html&gt;, is entirely new. One the windows desktop client it refused to give control to the client for the camera and the mic. I believe because the desktop client was still seeing it as being a port 80 request. Chrome (the &#8220;browser&#8221; inside the client) will not give control unless on an https port. What this whole section does is pops-out JaaS to the default browser when the meeting button is pressed inside MatterMost. It also sets a message and a reconnect button to display on the page that does pop-up in the MatterMost desktop client.<\/li>\n\n\n\n<li>The 6th part starts the app.js running http on port 3000<\/li>\n<\/ul>\n\n\n\n<p><strong>Plugin Change<\/strong><br>The last thing to note, and this is important. Back on the Jist plugin( figure 1 above) you must go back an add \/jist\/ to the end of your url. So it should look like https:\/\/matter.server.com\/jist\/ . If you do not do this it will not know that all that reverse proxy forwarding is for it.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Adroid MatterMost App and Certs<\/h3>\n\n\n\n<p>At the very begining of this journey I had a hard time getting the MatterMost app on android to connect. It would alway say it could not find the server. A web browser on the Andriod phone would work fine. It seems that Android and iOS do not like just the key.pem and the cert.pem like everything else I was using MatterMost on. You must have a combined chain pem. That is why you see me using the combined-bundle.pem in my config files for the web servers. I combined them by hand, but I believe I can get all of this via certbot. I will eventually do another how to on automating certbot and getting the combined pem automated. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>I set up a MatterMost server and wanted to use Jist as a Service (Jaas) and did not find a lot of info on doing this. So here is what I did, cuz I gotta write crap down. I used a MatterMost turnkey Linux download from Proxmox. I then signed up for JaaS at this [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3219,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-3204","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-figured-it-out"],"_links":{"self":[{"href":"https:\/\/smegnl.medina.oh.us\/index.php?rest_route=\/wp\/v2\/posts\/3204","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/smegnl.medina.oh.us\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/smegnl.medina.oh.us\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/smegnl.medina.oh.us\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/smegnl.medina.oh.us\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3204"}],"version-history":[{"count":24,"href":"https:\/\/smegnl.medina.oh.us\/index.php?rest_route=\/wp\/v2\/posts\/3204\/revisions"}],"predecessor-version":[{"id":3231,"href":"https:\/\/smegnl.medina.oh.us\/index.php?rest_route=\/wp\/v2\/posts\/3204\/revisions\/3231"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/smegnl.medina.oh.us\/index.php?rest_route=\/wp\/v2\/media\/3219"}],"wp:attachment":[{"href":"https:\/\/smegnl.medina.oh.us\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3204"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/smegnl.medina.oh.us\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3204"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/smegnl.medina.oh.us\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3204"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}