Última modificacion: 18-04-2026
Quiero empezar a ofrecer cursos (gratuitos y de pago) y me gustaría contar con una plataforma de videoconferencia online que no depende de código privativo ni servidores foráneos. Por eso, me puse manos a la obra para instalar y configurar una instancia de Jitsi en mi propio servidor (donde almaceno, entre otras cosas esta web y el repositorio oficial de Quirinux). Por un tema de seguridad (legalidad y responsabilidades) se me hacía peligroso pensar que cualquiera pudiera ingresar a mi instancia y crear reuniones. Se me ocurrió que tendría que existir alguna manera de crear un único usuario autenticado que pudiera crear y moderar las reuniones, habilitando a cualquier usuario anónimo a asistir a las charlas (pero sin poder crear nuevas ni moderar).
Arquitectura de Jitsi Meet
Jitsi necesita varios servicios para poder funcionar correctamente:
1. Prosody – Servidor XMPP (Jabber)
- Es el corazón de las comunicaciones en Jitsi
- Gestiona la autenticación de usuarios
- Coordina las sesiones y la señalización entre participantes
- Permite que los diferentes componentes de Jitsi se comuniquen entre sí
- En este manual configuramos dos dominios virtuales:
jitsi.quirinux.org: con autenticacióninternal_hashedpara moderadoresguest.jitsi.quirinux.org: con autenticaciónanonymouspara invitados
2. Jicofo (Jitsi Conference Focus)
- Actúa como el «director de orquesta» de las conferencias
- Gestiona la creación y destrucción de salas de reunión
- Asigna participantes a los bridges (JVB) según la carga
- Coordina la negociación de medios entre participantes
- Problema crítico encontrado: Jicofo rechazaba automáticamente la suscripción de presencia del componente
client_proxyde Prosody, impidiendo que las peticiones de conferencia llegaran correctamente. La solución fue añadir manualmentefocus.jitsi.quirinux.orgal roster de Jicofo con suscripción bidireccional (both).
3. JVB (Jitsi Videobridge)
- Es el «puente de video» que enruta los flujos multimedia
- Funciona como SFU (Selective Forwarding Unit)
- Recibe video/audio de cada participante y lo reenvía a los demás
- Optimiza el ancho de banda en conferencias grandes
- Puede escalarse horizontalmente añadiendo más bridges
4. Servidor Web (Apache en nuestro caso)
- Sirve la interfaz web de Jitsi Meet
- Maneja los certificados SSL/TLS
- Hace proxy de las conexiones WebSocket para XMPP
- Gestiona las peticiones HTTP/HTTPS
5. Componentes adicionales de Prosody
client_proxy: Permite que Jicofo no tenga que registrarse como componente completo, sino que actúa como proxy hacia el usuariofocus@auth.jitsi.quirinux.org- Varios componentes MUC (Multi-User Chat) para salas, lobbies y breakout rooms
- Componentes para funcionalidades como estadísticas, grabación, moderación AV, etc.
El desafío de la autenticación
La configuración predeterminada de Jitsi permite que cualquiera cree salas libremente (modo completamente anónimo). Esto es ideal para servicios públicos como meet.jit.si, pero representa un riesgo de seguridad y legal cuando administras tu propia instancia: usuarios maliciosos podrían usar tu servidor para actividades ilegales, consumir recursos sin control, o simplemente crear spam de salas.
La solución implementada en este manual establece un modelo de autenticación selectiva:
- Solo usuarios autenticados (como
charlie@jitsi.quirinux.org) pueden crear nuevas salas - Una vez creada la sala, cualquier persona puede unirse como invitado anónimo
- Los invitados no pueden crear salas nuevas ni moderar las existentes
Este modelo es perfecto para:
- Cursos y formaciones online
- Webinars y conferencias
- Reuniones corporativas con invitados externos
- Cualquier escenario donde quieras controlar quién inicia las sesiones pero permitir participación libre
El problema del roster y su solución
Durante la configuración encontramos un problema técnico crítico no documentado en los manuales oficiales de Jitsi: cuando se habilita la autenticación, el componente client_proxy de Prosody envía una suscripción de presencia a Jicofo para poder enrutar las peticiones de conferencia. Sin embargo, Jicofo (que usa la librería XMPP Smack de Java) rechaza automáticamente esta suscripción con un mensaje unsubscribed, porque por defecto no acepta suscripciones de entidades desconocidas.
El resultado es que aunque Jicofo esté conectado y funcionando, el client_proxy mantiene un array de sesiones vacío (#sessions == 0), y cuando un cliente intenta crear una conferencia, recibe inmediatamente un error service-unavailable porque el proxy cree que no hay ningún Jicofo disponible.
La solución consiste en añadir manualmente focus.jitsi.quirinux.org al roster de Jicofo en la base de datos de Prosody, estableciendo una suscripción bidireccional (subscription = "both"). Esto indica a Jicofo que confíe en el componente y acepte su presencia, permitiendo que el flujo de peticiones funcione correctamente.
Instalación y configuración:
Este manual documenta una instalación funcional de Jitsi Meet con autenticación en Debian 12, usando Apache con mod_md para SSL. La configuración del roster de Jicofo (paso 5.2) es crítica y no está documentada en los manuales oficiales, pero es necesaria para que el componente client_proxy funcione correctamente con autenticación habilitada.
Información del entorno
- Sistema operativo: Debian 12
- Dominio: jitsi.quirinux.org <- Modificar por tu dominio
- Servidor web: Apache con mod_md (Let’s Encrypt)
- Modo de autenticación: internal_hashed (solo usuarios autenticados pueden crear salas)
Versiones probadas:
- Debian 12
- Jitsi Meet 2.0.10741-1
- Jicofo 1.0-1169-1
- jitsi-videobridge2 (última estable)
- Apache 2.4.x con mod_md
1. Preparación del sistema
1.1 Actualizar el sistema
apt update && apt upgrade -y
1.2 Configurar el hostname
hostnamectl set-hostname jitsi.quirinux.org echo "127.0.0.1 jitsi.quirinux.org" >> /etc/hosts
1.3 Instalar dependencias básicas
apt install -y gnupg2 curl apt-transport-https
2. Instalación de Jitsi Meet
2.1 Añadir el repositorio de Jitsi
curl -sS https://download.jitsi.org/jitsi-key.gpg.key | gpg --dearmor > /usr/share/keyrings/jitsi-keyring.gpg echo "deb [signed-by=/usr/share/keyrings/jitsi-keyring.gpg] https://download.jitsi.org stable/" > /etc/apt/sources.list.d/jitsi-stable.list apt update
2.2 Instalar Jitsi Meet
apt install -y jitsi-meet
Durante la instalación:
- Hostname: Introduce tu dominio (jitsi.quirinux.org)
- SSL Certificate: Elige «Generate a new self-signed certificate» (lo cambiaremos después)
3. Configuración de SSL con Apache y mod_md
3.1 Detener Nginx (instalado por Jitsi)
Aunque es una dependencia de Jitsi, podemos prescindir de nginx, ya que no lo vamos a utilizar.
systemctl stop nginx systemctl disable nginx
Nota para Debian 12: Los plugins de Jitsi Meet pueden presentar incompatibilidades con la versión de Prosody incluida en Debian 12 (Lua 5.4). Si al iniciar Prosody aparecen errores del tipo no field package.preload en módulos como speakerstats_component, consultá el apartado 8.5 de este manual para resolverlos. Los módulos afectados suelen ser opcionales y no impiden el funcionamiento de las videoconferencias.
3.2 Instalar y configurar Apache
apt install -y apache2 a2enmod ssl headers rewrite proxy proxy_http proxy_wstunnel
3.3 Habilitar mod_md para Let’s Encrypt
sudo a2enmod md
3.4 Crear VirtualHost para Jitsi
Creamos un archivo /etc/apache2/sites-available/jitsi-quirinux.org.conf con el siguiente contenido:
MDomain jitsi.quirinux.org
MDCertificateAgreement accepted
MDContactEmail admin@quirinux.org
MDRenewWindow 33%
MDStapling on
<VirtualHost *:80>
ServerName jitsi.quirinux.org
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</VirtualHost>
<VirtualHost *:443>
ServerName jitsi.quirinux.org
SSLEngine on
<IfModule pagespeed_module>
ModPagespeed off
ModPagespeedDisallow "*"
</IfModule>
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
DocumentRoot /usr/share/jitsi-meet
<Directory /usr/share/jitsi-meet>
Options -Indexes +FollowSymLinks
AllowOverride None
Require all granted
</Directory>
SSLProxyEngine on
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
ProxyPreserveHost On
<Location /xmpp-websocket>
ProxyPass wss://localhost:5281/xmpp-websocket
ProxyPassReverse wss://localhost:5281/xmpp-websocket
</Location>
<Location /colibri-ws>
ProxyPass ws://localhost:9090/colibri-ws
ProxyPassReverse ws://localhost:9090/colibri-ws
</Location>
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/xmpp-websocket
RewriteCond %{REQUEST_URI} !^/colibri-ws
RewriteCond %{REQUEST_URI} !^/config\.js
RewriteCond %{REQUEST_URI} !^/interface_config\.js
RewriteCond %{REQUEST_URI} !^/libs/
RewriteCond %{REQUEST_URI} !^/css/
RewriteCond %{REQUEST_URI} !^/images/
RewriteCond %{REQUEST_URI} !^/fonts/
RewriteCond %{REQUEST_URI} !^/lang/
RewriteCond %{REQUEST_URI} !^/sounds/
RewriteCond %{REQUEST_URI} !^/static/
RewriteCond %{REQUEST_URI} !^/http-bind
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ /index.html [L]
ErrorLog ${APACHE_LOG_DIR}/jitsi-error.log
CustomLog ${APACHE_LOG_DIR}/jitsi-access.log combined
</VirtualHost>
Habilitamos módulos necesarios, habilitamos el sitio y reiniciamos Apache:
sudo a2enmod ssl headers rewrite proxy proxy_http proxy_wstunnel
sudo a2ensite jitsi.quirinux.org
systemctl restart apache2 3.4.1 Corrección de bug del paquet jitsi-meet de Debian:
El paquete jitsi-meet para Debian omite la declaración en el archivo index.html, lo que hace que Apache lo sirva en modo Quirks y la interfaz aparezca como pantalla negra. Este comando lo corrige manualmente. Si en el futuro actualizás el paquete, es posible que haya que reaplicar este paso:
sed -i '1s/^/\n/' /usr/share/jitsi-meet/index.html Verificar que quedó correctamente
head -3 /usr/share/jitsi-meet/index.html 3.5 Esperar a que mod_md obtenga el certificado
# Monitorear logs journalctl -u apache2 -f # Esperar hasta ver: "MDomain jitsi.quirinux.org has signed-up protocol version ACME/2.0" # Los certificados se guardarán automáticamente en /etc/apache2/md/domains/jitsi.quirinux.org/
4. Configuración de autenticación
4.1 Modificar configuración de Prosody
nano /etc/prosody/conf.avail/jitsi.quirinux.org.cfg.lua
Cambiar:
VirtualHost "jitsi.quirinux.org"
authentication = "jitsi-anonymous"
Por:
VirtualHost "jitsi.quirinux.org" authentication = "internal_hashed"
Añadir después del VirtualHost principal:
VirtualHost "guest.jitsi.quirinux.org"
authentication = "anonymous"
c2s_require_encryption = false
modules_enabled = {
"bosh";
"websocket";
"smacks";
} 4.2 Modificar configuración de Jitsi Meet
Editamos el fichero /etc/jitsi/meet/jitsi.quirinux.org-config.js y buscamos la línea hosts: { para que quede de esta manera:
hosts: {
domain: 'jitsi.quirinux.org',
anonymousdomain: 'guest.jitsi.quirinux.org',
// ... resto de la configuración
} 4.3 Modificar configuración de Jicofo
nano /etc/jitsi/jicofo/jicofo.conf
Añadir dentro del bloque jicofo:
authentication: {
enabled: true
type: XMPP
login-url: "jitsi.quirinux.org"
} 4.4 Crear usuarios autenticados
Verifica las contraseñas de jicofo y videobridge:
grep -i "password" /etc/jitsi/jicofo/jicofo.conf
grep -i "password" /etc/jitsi/videobridge/jvb.conf Luego crea los usuarios con dichas contraseñas, y crea un usuario para tí (con el que te autenticaras como moderador para poder crear salas).
# Usuario para Jicofo (focus) — usar la contraseña de jicofo.conf
prosodyctl register focus auth.jitsi.quirinux.org password-jicofo
# Usuario para JVB — usar la contraseña de jvb.conf
prosodyctl register jvb auth.jitsi.quirinux.org password-jvb
# Usuario moderador (puede crear salas)
prosodyctl register charlie jitsi.quirinux.org password
5. Corrección crítica: Configurar roster de Jicofo
IMPORTANTE: Este paso es crítico y soluciona el error service-unavailable del componente focus.
5.1 Detener servicios
systemctl stop prosody systemctl stop jicofo
5.2 Añadir focus.jitsi.quirinux.org al roster de Jicofo
cat > /var/lib/prosody/auth%2ejitsi%2equirinux%2eorg/roster/focus.dat << 'EOF'
return {
["focus.jitsi.quirinux.org"] = {
["groups"] = {};
["name"] = "focus-proxy";
["subscription"] = "both";
};
[false] = {
["pending"] = {};
["version"] = 12;
};
};
EOF Explicación: El componente client_proxy de Prosody envía una suscripción de presencia a Jicofo, pero Jicofo la rechaza por defecto. Al añadir focus.jitsi.quirinux.org al roster con subscription = "both", Jicofo acepta la presencia y el proxy puede registrar la sesión correctamente.
5.3 Reiniciar servicios
systemctl start prosody
systemctl start jicofo
systemctl start jitsi-videobridge2
6. Verificación de la instalación
6.1 Verificar servicios
systemctl status prosody systemctl status jicofo systemctl status jitsi-videobridge2 systemctl status apache2
6.2 Verificar conexiones XMPP
prosodyctl shell << 'EOF' c2s:show() EOF
Deberías ver:
jvb@auth.jitsi.quirinux.org– onlinefocus@auth.jitsi.quirinux.org– online
6.3 Verificar logs de Jicofo
tail -50 /var/log/jitsi/jicofo.log | grep -i "connected\|error\|warn"
Deberías ver:
Connected.Registered- Sin errores de
unsubscribedoservice-unavailable
6.4 Probar en el navegador
- Accede a
https://jitsi.quirinux.org - Introduce un nombre de sala
- Debe pedir credenciales de autenticación
- Introduce usuario y contraseña (charlie / PASSWORD_CHARLIE)
- La sala debe crearse correctamente
7. Configuraciones adicionales recomendadas
7.1 Desactivar smacks hibernation para auth domain
nano /etc/prosody/conf.avail/jitsi.quirinux.org.cfg.lua
En el bloque VirtualHost "auth.jitsi.quirinux.org" añadir:
smacks_hibernation_time = 0;
7.2 Configurar logging de Jicofo
mkdir -p /usr/share/jicofo/lib cat > /usr/share/jicofo/lib/logging.properties << 'EOF' handlers=java.util.logging.ConsoleHandler, java.util.logging.FileHandler java.util.logging.FileHandler.pattern=/var/log/jitsi/jicofo.log .level=INFO org.jitsi.level=FINE EOF systemctl restart jicofo
7.3 Añadir ruta de plugins de Jitsi en Prosody
nano /etc/prosody/prosody.cfg.lua
Cambiar:
plugin_paths = { «/usr/local/lib/prosody/modules» }
Por:
plugin_paths = { "/usr/local/lib/prosody/modules", "/usr/share/jitsi-meet/prosody-plugins/" } 8. Resolución de problemas comunes
8.1 Error «service-unavailable» del componente focus
Síntoma: Los clientes no pueden conectarse, log muestra:
Strophe error: {"reason":"service-unavailable","targetJid":"focus.jitsi.quirinux.org"} Causa: El roster de Jicofo no incluye focus.jitsi.quirinux.org
Solución: Aplicar el paso 5.2 de este manual
8.2 Error «conflict – Replaced by new connection»
Síntoma: Jicofo se desconecta constantemente con error de conflicto
Causa: Múltiples instancias de Jicofo o sesiones antiguas en Prosody
Solución:
pkill -9 -f jicofo systemctl restart prosody sleep 5 systemctl start jicofo
8.3 Certificados SSL no funcionan
Síntoma: Error SSL en el navegador
Solución:
# Regenerar certificados de Prosody cd /var/lib/prosody prosodyctl cert generate jitsi.quirinux.org prosodyctl cert generate auth.jitsi.quirinux.org # Cambiar propietario chown -R prosody:prosody /var/lib/prosody/*.crt /var/lib/prosody/*.key systemctl restart prosody
8.4 Jicofo no arranca como servicio
Síntoma: systemctl status jicofo muestra «active (exited)» sin proceso java
Solución:
systemctl stop jicofo systemctl reset-failed jicofo pkill -9 -f jicofo rm -f /var/run/jicofo.pid systemctl daemon-reload systemctl start jicofo
8.5 Error «no field package.preload» en módulos de Prosody
Síntoma: Al iniciar Prosody, el log muestra errores como:
modulemanager: Error initializing module ‘speakerstats_component’ on ‘speakerstats.jitsi.quirinux.org’:
/usr/lib/prosody/util/startup.lua:203: in function ‘require’
no field package.preload[‘prosody.util.queue’]
Causa: Incompatibilidad entre los plugins de Jitsi Meet y la versión de Prosody incluida en Debian 12, que usa Lua 5.4 con una estructura de rutas diferente a la esperada por algunos módulos opcionales de Jitsi.
Solución: Deshabilitar el módulo afectado en la configuración de Prosody. El módulo speakerstats es opcional (solo registra estadísticas de quién habla) y no afecta al funcionamiento de las videoconferencias.
Editar el archivo /etc/prosody/conf.avail/jitsi.quirinux.org.cfg.lua y comentar la siguiente línea:
Component "speakerstats.jitsi.quirinux.org" "speakerstats_component" Tiene que quedar así:
--Component "speakerstats.jitsi.quirinux.org" "speakerstats_component" Luego reiniciar Prosody
systemctl restart prosody Nota: Si el mismo error aparece con otros módulos (por ejemplo av_moderation, breakout_rooms, etc.), aplicá el mismo criterio: comentá el componente si no es esencial para tu caso de uso. Los módulos críticos son conference, auth y focus; el resto son funcionalidades adicionales.
9. Mantenimiento
9.1 Actualizar Jitsi
apt update apt upgrade jitsi-meet jicofo jitsi-videobridge2 systemctl restart prosody jicofo jitsi-videobridge2
9.2 Añadir nuevos usuarios moderadores
prosodyctl register USUARIO jitsi.quirinux.org PASSWORD
9.3 Cambiar contraseña de usuario
prosodyctl passwd USUARIO@jitsi.quirinux.org
9.4 Eliminar usuario
prosodyctl deluser USUARIO@jitsi.quirinux.org
9.5 Ver logs en tiempo real
# Jicofo tail -f /var/log/jitsi/jicofo.log # JVB tail -f /var/log/jitsi/jvb.log # Prosody journalctl -u prosody -f
10. Bibliografía
- Documentación oficial de Jitsi: https://jitsi.github.io/handbook/
- Foro de la comunidad: https://community.jitsi.org/
- Repositorio GitHub: https://github.com/jitsi