jitsi changed

This commit is contained in:
2026-05-14 16:42:42 +05:30
commit e35fd60cc5
9 changed files with 4709 additions and 0 deletions

85
README.md Normal file
View File

@@ -0,0 +1,85 @@
# PoliticTalk Jitsi Setup
This folder is the local source of truth for the PoliticTalk Jitsi setup used by:
```text
https://politictalk.parallelglobe.io
```
The VPS still runs the actual Jitsi services. Changes should be made here first, committed to Git, pulled on the VPS, then deployed into the system Jitsi paths with the deploy script.
## Structure
```text
jitsi/
config/
politictalk.parallelglobe.io-config.js
assets/
public/politictalk/
branding.json
pgLogo.svg
nginx/
politictalk.parallelglobe.io.conf
scripts/
deploy-vps.sh
templates/
```
## Current Meeting Policy
- Meetings start in audio-only mode.
- Participants join with microphone muted.
- Participants join with camera off.
- Camera/prejoin camera controls are hidden.
- Toolbar is limited to microphone, chat, raise hand, fullscreen, noise suppression, participants pane, and hangup.
- Chat and polls are enabled.
- Invite/share controls are disabled.
- Room names are not stored in recent rooms.
- E2EE support is enabled in the Jitsi config.
- The logo and dynamic branding point to PoliticTalk public assets.
## VPS Paths
The deploy script copies local files into these VPS paths:
```text
jitsi/config/politictalk.parallelglobe.io-config.js
-> /etc/jitsi/meet/politictalk.parallelglobe.io-config.js
jitsi/assets/public/politictalk/*
-> /etc/jitsi/meet/public/politictalk/
jitsi/nginx/politictalk.parallelglobe.io.conf
-> /etc/nginx/sites-available/politictalk.parallelglobe.io.conf
```
By default, the deploy script does not replace nginx config unless `DEPLOY_NGINX=1` is set.
## Deploy On VPS
After pulling the latest repo changes on the VPS:
```bash
cd /path/to/pg/jitsi
sudo ./scripts/deploy-vps.sh
```
To also deploy the nginx vhost:
```bash
cd /path/to/pg/jitsi
sudo DEPLOY_NGINX=1 ./scripts/deploy-vps.sh
```
For current `config.js`, branding, and asset changes, an nginx reload is enough. Future JWT/auth changes may require restarting Prosody and Jicofo.
## Future Auth Work
The future authenticated flow should be:
```text
PgPlatform -> PgApi verifies event/user -> PgApi creates short-lived Jitsi JWT
-> PgPlatform prejoin/iframe -> Jitsi validates JWT on VPS
```
Do not commit real secrets here. JWT secrets, Prosody passwords, and private keys should stay in VPS-only environment/config files.

View File

@@ -0,0 +1,16 @@
{
"inviteDomain": "politictalk.parallelglobe.io",
"backgroundColor": "#101820",
"logoClickUrl": "https://parallelglobe.io/",
"logoImageUrl": "/_api/public/politictalk/pgLogo.svg",
"premeetingBackground": "url(/_api/public/politictalk/pg_bg.png)",
"customTheme": {
"palette": {
"ui01": "#101820",
"ui02": "#172432",
"surface02": "#1D2C3A",
"action01": "#2F80ED",
"action01Hover": "#1C6DD0"
}
}
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 641 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,244 @@
server_names_hash_bucket_size 64;
types {
# nginx's default mime.types doesn't include a mapping for wasm or wav.
application/wasm wasm;
audio/wav wav;
}
upstream prosody {
zone upstreams 64K;
server 127.0.0.1:5280;
keepalive 2;
}
upstream jvb1 {
zone upstreams 64K;
server 127.0.0.1:9090;
keepalive 2;
}
map $arg_vnode $prosody_node {
default prosody;
v1 v1;
v2 v2;
v3 v3;
v4 v4;
v5 v5;
v6 v6;
v7 v7;
v8 v8;
}
# Matches any URI or Referer with some matches and redacts the whole
# query string. log_format and map must be at the http context level.
map $request_uri $loggable_uri {
~^(?P<path>[^?]*)\?.*(?:jwt|token)= "${path}?[params_redacted]";
default $request_uri;
}
map $http_referer $loggable_referer {
~^(?P<url>[^?]*)\?.*(?:jwt|token)= "${url}?[params_redacted]";
default $http_referer;
}
log_format jitsi_log '$remote_addr - $remote_user [$time_local] '
'"$request_method $loggable_uri $server_protocol" '
'$status $body_bytes_sent "$loggable_referer" "$http_user_agent"';
server {
listen 80;
listen [::]:80;
server_name politictalk.parallelglobe.io;
location ^~ /.well-known/acme-challenge/ {
default_type "text/plain";
root /usr/share/jitsi-meet;
}
location = /.well-known/acme-challenge/ {
return 404;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name politictalk.parallelglobe.io;
# Mozilla Guideline v5.4, nginx 1.17.7, OpenSSL 1.1.1d, intermediate configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
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 "";
set $custom_index "";
set $config_js_location /etc/jitsi/meet/politictalk.parallelglobe.io-config.js;
ssl_certificate /etc/jitsi/meet/politictalk.parallelglobe.io.crt;
ssl_certificate_key /etc/jitsi/meet/politictalk.parallelglobe.io.key;
root /usr/share/jitsi-meet;
access_log /var/log/nginx/access.log jitsi_log;
# ssi on with javascript for multidomain variables in config.js
ssi on;
ssi_types application/x-javascript application/javascript;
index index.html index.htm;
error_page 404 /static/404.html;
gzip on;
gzip_types text/plain text/css application/javascript application/json image/x-icon application/octet-stream application/wasm;
gzip_vary on;
gzip_proxied no-cache no-store private expired auth;
gzip_min_length 512;
include /etc/jitsi/meet/jaas/*.conf;
location = /config.js {
alias $config_js_location;
}
location = /external_api.js {
alias /usr/share/jitsi-meet/libs/external_api.min.js;
}
location = /_api/room-info {
proxy_pass http://prosody/room-info?prefix=$prefix&$args;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
}
location ~ ^/_api/public/(.*)$ {
autoindex off;
alias /etc/jitsi/meet/public/$1;
}
# ensure all static content can always be found first
location ~ ^/(libs|css|static|images|fonts|lang|sounds|.well-known)/(.*)$
{
add_header 'Access-Control-Allow-Origin' '*';
alias /usr/share/jitsi-meet/$1/$2;
# cache all versioned files
if ($arg_v) {
expires 1y;
}
}
# BOSH
location = /http-bind {
proxy_pass http://$prosody_node/http-bind?prefix=$prefix&$args;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header Connection "";
}
# xmpp websockets
location = /xmpp-websocket {
proxy_pass http://$prosody_node/xmpp-websocket?prefix=$prefix&$args;
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;
}
# colibri (JVB) websockets for jvb1
location ~ ^/colibri-ws/default-id/(.*) {
proxy_pass http://jvb1/colibri-ws/default-id/$1$is_args$args;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
tcp_nodelay on;
}
# load test minimal client, uncomment when used
#location ~ ^/_load-test/([^/?&:'"]+)$ {
# rewrite ^/_load-test/(.*)$ /load-test/index.html break;
#}
#location ~ ^/_load-test/libs/(.*)$ {
# add_header 'Access-Control-Allow-Origin' '*';
# alias /usr/share/jitsi-meet/load-test/libs/$1;
#}
location = /_unlock {
add_header 'Access-Control-Allow-Origin' '*';
add_header Strict-Transport-Security 'max-age=63072000; includeSubDomains';
add_header "Cache-Control" "no-cache, no-store";
}
location ~ ^/conference-request/v1(\/.*)?$ {
proxy_pass http://127.0.0.1:8888/conference-request/v1$1;
add_header "Cache-Control" "no-cache, no-store";
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Content-Type';
}
location ~ ^/([^/?&:'"]+)/conference-request/v1(\/.*)?$ {
rewrite ^/([^/?&:'"]+)/conference-request/v1(\/.*)?$ /conference-request/v1$2;
}
location ~ ^/([^/?&:'"]+)$ {
set $roomname "$1";
try_files $uri @root_path;
}
location @root_path {
rewrite ^/(.*)$ /$custom_index break;
}
location ~ ^/([^/?&:'"]+)/config.js$
{
set $subdomain "$1.";
set $subdir "$1/";
alias $config_js_location;
}
# Matches /(TENANT)/pwa-worker.js or /(TENANT)/manifest.json to rewrite to / and look for file
location ~ ^/([^/?&:'"]+)/(pwa-worker.js|manifest.json)$ {
set $subdomain "$1.";
set $subdir "$1/";
rewrite ^/([^/?&:'"]+)/(pwa-worker.js|manifest.json)$ /$2;
}
# BOSH for subdomains
location ~ ^/([^/?&:'"]+)/http-bind {
set $subdomain "$1.";
set $subdir "$1/";
set $prefix "$1";
rewrite ^/(.*)$ /http-bind;
}
# websockets for subdomains
location ~ ^/([^/?&:'"]+)/xmpp-websocket {
set $subdomain "$1.";
set $subdir "$1/";
set $prefix "$1";
rewrite ^/(.*)$ /xmpp-websocket;
}
location ~ ^/([^/?&:'"]+)/_api/room-info {
set $subdomain "$1.";
set $subdir "$1/";
set $prefix "$1";
rewrite ^/(.*)$ /_api/room-info;
}
# Anything that didn't match above, and isn't a real file, assume it's a room name and redirect to /
location ~ ^/([^/?&:'"]+)/(.*)$ {
set $subdomain "$1.";
set $subdir "$1/";
rewrite ^/([^/?&:'"]+)/(.*)$ /$2;
}
}

67
scripts/deploy-vps.sh Executable file
View File

@@ -0,0 +1,67 @@
#!/usr/bin/env bash
set -euo pipefail
DOMAIN="${DOMAIN:-politictalk.parallelglobe.io}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
JITSI_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
BACKUP_ROOT="${BACKUP_ROOT:-/root/jitsi-backups}"
STAMP="$(date +%Y%m%d-%H%M%S)"
BACKUP_DIR="$BACKUP_ROOT/$STAMP"
CONFIG_SRC="$JITSI_DIR/config/$DOMAIN-config.js"
ASSETS_SRC="$JITSI_DIR/assets/public/politictalk"
NGINX_SRC="$JITSI_DIR/nginx/$DOMAIN.conf"
CONFIG_DEST="/etc/jitsi/meet/$DOMAIN-config.js"
ASSETS_DEST="/etc/jitsi/meet/public/politictalk"
NGINX_DEST="/etc/nginx/sites-available/$DOMAIN.conf"
if [[ "$(id -u)" -ne 0 ]]; then
echo "Run this script with sudo on the VPS."
exit 1
fi
if [[ ! -f "$CONFIG_SRC" ]]; then
echo "Missing config source: $CONFIG_SRC"
exit 1
fi
if [[ ! -d "$ASSETS_SRC" ]]; then
echo "Missing assets source: $ASSETS_SRC"
exit 1
fi
install -d -m 0755 "$BACKUP_DIR"
if [[ -f "$CONFIG_DEST" ]]; then
cp -a "$CONFIG_DEST" "$BACKUP_DIR/"
fi
if [[ -d "$ASSETS_DEST" ]]; then
install -d -m 0755 "$BACKUP_DIR/public"
cp -a "$ASSETS_DEST" "$BACKUP_DIR/public/"
fi
if [[ "${DEPLOY_NGINX:-0}" == "1" && -f "$NGINX_DEST" ]]; then
cp -a "$NGINX_DEST" "$BACKUP_DIR/"
fi
install -d -m 0755 "$ASSETS_DEST"
install -m 0644 "$CONFIG_SRC" "$CONFIG_DEST"
find "$ASSETS_SRC" -maxdepth 1 -type f -print0 | while IFS= read -r -d '' file; do
install -m 0644 "$file" "$ASSETS_DEST/"
done
if [[ "${DEPLOY_NGINX:-0}" == "1" ]]; then
if [[ ! -f "$NGINX_SRC" ]]; then
echo "Missing nginx source: $NGINX_SRC"
exit 1
fi
install -m 0644 "$NGINX_SRC" "$NGINX_DEST"
nginx -t
fi
systemctl reload nginx
echo "Deployed PoliticTalk Jitsi files."
echo "Backup: $BACKUP_DIR"

33
templates/auth-roadmap.md Normal file
View File

@@ -0,0 +1,33 @@
# PoliticTalk Jitsi Auth Roadmap
These notes are intentionally not deployed yet. They describe the local files and app changes we should add when we connect PgApi authentication to Jitsi.
## Target Flow
```text
PgPlatform calendar event
-> PgPlatform PoliticTalk prejoin page
-> PgApi verifies logged-in user, event ownership/invite/access, and event time window
-> PgApi returns a short-lived Jitsi JWT
-> PgPlatform embeds or opens Jitsi with that JWT
-> Jitsi VPS validates JWT through Prosody token auth
```
## Local Files To Add Later
```text
jitsi/templates/prosody-token-auth.cfg.lua.example
jitsi/templates/jicofo-token-auth.conf.example
jitsi/templates/jitsi-token-auth.env.example
```
Only templates should be committed. Real JWT secrets must stay in VPS-only files.
## Platform Changes To Add Later
- PgApi endpoint to issue Jitsi JWTs for valid PoliticTalk event access.
- JWT claims for room, user display name, email/id, moderator flag, expiry, and feature permissions.
- PgPlatform prejoin route that shows event title and immutable platform user name.
- PgPlatform embedded Jitsi room using the IFrame API.
- Moderator-only controls for audio moderation and poll permissions.
- Event end-time enforcement through JWT expiry and/or iframe hangup.

View File

@@ -0,0 +1,8 @@
# Optional variables for jitsi/scripts/deploy-vps.sh.
# Copy this to a VPS-only location if needed. Do not commit real secrets.
DOMAIN=politictalk.parallelglobe.io
BACKUP_ROOT=/root/jitsi-backups
# Set to 1 only when intentionally replacing the nginx vhost config.
DEPLOY_NGINX=0