<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="es">
	<id>https://vivait-wiki.mdnova.local/wiki/vivait/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Alfredo.rodriguez</id>
	<title>VIVAitwiki - Contribuciones del usuario [es]</title>
	<link rel="self" type="application/atom+xml" href="https://vivait-wiki.mdnova.local/wiki/vivait/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Alfredo.rodriguez"/>
	<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php/Especial:Contribuciones/Alfredo.rodriguez"/>
	<updated>2026-07-14T02:35:32Z</updated>
	<subtitle>Contribuciones del usuario</subtitle>
	<generator>MediaWiki 1.33.0</generator>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19195</id>
		<title>Instalacion cartelia 10</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19195"/>
		<updated>2026-07-13T10:26:50Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* Configuración desde el portal de administración de Cartelia */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[:Media:cartelia-despliegue-vm-documentacion-tecnica.pdf|Instalación de Cartelia 1.0]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
= Introducción =&lt;br /&gt;
&lt;br /&gt;
'''Cartelia''' es el producto de cartelería digital (digital signage) de la compañía.&lt;br /&gt;
&lt;br /&gt;
El presente documento describe el procedimiento de despliegue de una nueva instancia de Cartelia partiendo de una '''máquina virtual base''' con las siguientes características:&lt;br /&gt;
&lt;br /&gt;
* Sistema operativo: '''Debian 13 (trixie)'''.&lt;br /&gt;
* Hipervisor: '''KVM/QEMU''' (gestionado mediante &amp;lt;code&amp;gt;libvirt&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;virt-manager&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Software preinstalado: '''Cartelia 1.0''', instalado en &amp;lt;code&amp;gt;/var/www/html/cartelia&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Punto de partida''': la máquina base se entrega totalmente operativa, con Cartelia instalado de forma nativa sobre Apache + PHP y la base de datos MariaDB local ya creada e inicializada.&lt;br /&gt;
&lt;br /&gt;
'''Restricciones conocidas''':&lt;br /&gt;
&lt;br /&gt;
* La plantilla base '''no debe arrancarse nunca en producción sin personalizar''': contiene identidad de máquina, claves SSH y secretos del CMS compartidos con cualquier otra copia de la plantilla.&lt;br /&gt;
* Los players (pantallas) se autentican contra el CMS mediante la clave del servidor (''CMS Key'') y la URL del CMS; cualquier cambio posterior de IP/FQDN o de claves obliga a volver a autorizar los displays.&lt;br /&gt;
&lt;br /&gt;
= Arquitectura =&lt;br /&gt;
&lt;br /&gt;
== Esquema general del despliegue ==&lt;br /&gt;
&lt;br /&gt;
[[File:Cartelia-arquitectura.png|thumb|center|900px|Esquema general del despliegue de Cartelia sobre KVM/QEMU]]&lt;br /&gt;
&lt;br /&gt;
El CMS está instalado de forma nativa sobre el sistema operativo: Apache 2 con PHP como servidor web del portal, MariaDB local como base de datos y el servicio XMR ejecutándose como unidad de systemd.&lt;br /&gt;
&lt;br /&gt;
== Flujo del proceso de despliegue ==&lt;br /&gt;
&lt;br /&gt;
# El técnico de sistemas clona la plantilla base en el host KVM/QEMU (disco &amp;lt;code&amp;gt;qcow2&amp;lt;/code&amp;gt; + definición de dominio libvirt).&lt;br /&gt;
# En el primer arranque del clon, se personaliza la identidad del sistema operativo: &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt;, hostname, claves SSH de host, red, zona horaria y credenciales locales.&lt;br /&gt;
# Se personaliza el producto Cartelia: URL pública del CMS, secretos y contraseñas de base de datos, clave del servidor (''CMS Key''), dirección pública de XMR y personalización de marca.&lt;br /&gt;
# Se verifican los servicios, la conectividad de los players y el acceso al portal de administración.&lt;br /&gt;
# La máquina queda registrada en inventario/monitorización y se entrega.&lt;br /&gt;
&lt;br /&gt;
== Componentes principales ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Componente !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Portal Cartelia''' || Interfaz de administración de contenidos, layouts, programaciones y pantallas. Servida por Apache 2 + PHP.&lt;br /&gt;
|-&lt;br /&gt;
| '''MariaDB (local)''' || Almacena la configuración, usuarios, programaciones y metadatos de medios del CMS. Servicio nativo del sistema.&lt;br /&gt;
|-&lt;br /&gt;
| '''XMR (Cartelia Message Relay)''' || Canal push que permite al CMS enviar órdenes inmediatas a los players (recarga de contenido, capturas, reinicio). Servicio &amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;. Los players se conectan por WebSocket a la ruta &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, que reenvía a &amp;lt;code&amp;gt;ws://127.0.0.1:8080&amp;lt;/code&amp;gt;; el puerto 9505/TCP queda además permitido en el firewall para el modo de publicación directa.&lt;br /&gt;
|-&lt;br /&gt;
| '''Biblioteca de medios''' || &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;: directorio donde el CMS guarda los ficheros multimedia subidos (configurado en ''Administración &amp;gt; Configuración &amp;gt; Ubicación de la biblioteca'' y alineado con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts).&lt;br /&gt;
|-&lt;br /&gt;
| '''libvirt / KVM-QEMU''' || Capa de virtualización que aloja la VM.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Dependencias e integraciones externas ==&lt;br /&gt;
&lt;br /&gt;
* '''DNS''': registro A/AAAA del FQDN del CMS (imprescindible si los players usan nombre en lugar de IP).&lt;br /&gt;
* '''NTP''': sincronización horaria; las programaciones de contenido dependen de la hora del sistema.&lt;br /&gt;
* '''SMTP''' (opcional): relay de correo para notificaciones del CMS, si el cliente lo requiere. Se configura en el portal (''Administración &amp;gt; Configuración'', pestaña '''Mantenimiento''').&lt;br /&gt;
* '''Certificados TLS''': siempre certificados válidos, nunca autofirmados. Si el cliente dispone de certificado propio para el FQDN, lo aporta él; en caso contrario se emite con Let's Encrypt.&lt;br /&gt;
&lt;br /&gt;
= Personalización del sistema operativo (dentro de la VM) =&lt;br /&gt;
&lt;br /&gt;
== Personalización de identidad y red ==&lt;br /&gt;
&lt;br /&gt;
Todos los comandos se ejecutan como &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; desde la consola de &amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; en el primer arranque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Paso 1: regenerar las claves SSH de host (las de la plantilla son comunes a todos los clones)&lt;br /&gt;
rm -f /etc/ssh/ssh_host_*&lt;br /&gt;
dpkg-reconfigure openssh-server&lt;br /&gt;
systemctl restart ssh&lt;br /&gt;
&lt;br /&gt;
# Paso 2: hostname y resolución local&lt;br /&gt;
hostnamectl set-hostname &amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
sed -i &amp;quot;s/127.0.1.1.*/127.0.1.1\t&amp;lt;nombre-del-entorno&amp;gt; &amp;lt;FQDN-del-CMS&amp;gt;/&amp;quot; /etc/hosts&lt;br /&gt;
&lt;br /&gt;
# Paso 3: configuración de red (ifupdown, /etc/network/interfaces)&lt;br /&gt;
&lt;br /&gt;
# Paso 4: zona horaria y hora (NTP)&lt;br /&gt;
vi /etc/systemd/timesyncd.conf.d/local.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Paso 5: actualización de paquetes del SO&lt;br /&gt;
apt update &amp;amp;&amp;amp; apt upgrade -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Arranque del producto Cartelia ==&lt;br /&gt;
&lt;br /&gt;
El CMS ya viene instalado y operativo en la máquina base; en esta fase únicamente debe verificarse el arranque de los servicios nativos tras la personalización de red:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
&lt;br /&gt;
# Si algún servicio no arranca tras el cambio de red/hostname:&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
journalctl -u apache2 -n 50 --no-pager&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Verificación de la instalación ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# El portal responde en local (la máquina base publica en HTTP; ver 4.3 para HTTPS)&lt;br /&gt;
curl -Is http://localhost/ | head -1          # esperado: HTTP/1.1 200 OK (o 302 a /login)&lt;br /&gt;
&lt;br /&gt;
# Puertos de servicio a la escucha&lt;br /&gt;
ss -tlnp | grep -E ':(80|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Resolución del FQDN desde un puesto cliente&lt;br /&gt;
getent hosts &amp;lt;FQDN-del-CMS&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Acceso final: abrir &amp;lt;code&amp;gt;http://&amp;lt;FQDN-del-CMS&amp;gt;/&amp;lt;/code&amp;gt; en el navegador y validar la pantalla de login de Cartelia (o &amp;lt;code&amp;gt;https://&amp;lt;/code&amp;gt; si se ha habilitado el vhost TLS, ver 4.3).&lt;br /&gt;
&lt;br /&gt;
= Configuración =&lt;br /&gt;
&lt;br /&gt;
== Ficheros de configuración del producto ==&lt;br /&gt;
&lt;br /&gt;
La instalación es nativa (Apache + PHP + MariaDB local); estos son los ficheros que el SAT debe revisar/personalizar en cada clon:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; del CMS''' (&amp;lt;code&amp;gt;/var/www/html/cartelia/web/settings.php&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Descripción !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbhost&amp;lt;/code&amp;gt; || Host de MariaDB (normalmente &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt;) || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$dbuser&amp;lt;/code&amp;gt; || Base de datos y usuario del CMS || No cambiar salvo política del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbpass&amp;lt;/code&amp;gt; || Contraseña del usuario del CMS en MariaDB || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SECRET_KEY&amp;lt;/code&amp;gt; || Clave secreta de la instalación (cifrado interno) || Actualmente no se regenera: se mantiene el valor de la máquina base en todos los despliegues&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''XMR''' (&amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;, unidad en &amp;lt;code&amp;gt;/etc/systemd/system/xibo-xmr.service&amp;lt;/code&amp;gt;): ejecuta &amp;lt;code&amp;gt;/var/www/html/cartelia/vendor/bin/xmr.phar&amp;lt;/code&amp;gt; con PHP como usuario &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;, con reinicio automático (&amp;lt;code&amp;gt;Restart=always&amp;lt;/code&amp;gt;).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Sockets por defecto: WebSocket para players en &amp;lt;code&amp;gt;127.0.0.1:8080&amp;lt;/code&amp;gt;, expuesto a través del proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, y publicación interna del CMS en &amp;lt;code&amp;gt;tcp://127.0.0.1:50001&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Tras cualquier cambio: &amp;lt;code&amp;gt;systemctl restart xibo-xmr.service&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Apache''': la máquina base incluye dos vhosts en &amp;lt;code&amp;gt;/etc/apache2/sites-available/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; (habilitado por defecto): sirve el portal en el puerto 80. En la máquina base el &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt; es la IP de la propia máquina; en cada cliente debe actualizarse al FQDN definitivo. Incluye el proxy WebSocket de XMR (&amp;lt;code&amp;gt;ProxyPass /xmr ws://127.0.0.1:8080&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;XSendFile&amp;lt;/code&amp;gt; para la entrega de medios y una exclusión de mod_security (&amp;lt;code&amp;gt;SecRuleRemoveById 920350&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; (deshabilitado por defecto): vhost TLS preparado para clientes con FQDN y certificado. Su activación se describe en la sección 4.3.&lt;br /&gt;
&lt;br /&gt;
Validar siempre con &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; antes de &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Configuración desde el portal de administración de Cartelia ==&lt;br /&gt;
&lt;br /&gt;
Acceder con el usuario '''&amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt;''' y la contraseña estándar de la máquina base (conocida por el SAT; no se documenta aquí) y cambiar dicha contraseña de inmediato, ya que es común a todos los clones. A continuación:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;''Administración &amp;gt; Configuración &amp;gt; Red''&amp;lt;/code&amp;gt;: establecer la dirección del CMS (&amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt;) con el FQDN definitivo. Los players usan este valor para conectarse.&lt;br /&gt;
* &amp;lt;code&amp;gt;''Administración &amp;gt; Configuración''&amp;lt;/code&amp;gt;, pestaña &amp;lt;code&amp;gt;'''Configuración'''&amp;lt;/code&amp;gt;, campo &amp;lt;code&amp;gt;'''&amp;quot;Clave secreta de CMS&amp;quot;'''&amp;lt;/code&amp;gt;: es la clave que debe introducirse en cada player para autenticarlo contra el CMS. En un clon es idéntica a la de la máquina base (y, por tanto, conocida por cualquier otro despliegue), así que debe sustituirse por una clave nueva y única en cada cliente.&lt;br /&gt;
* &amp;lt;code&amp;gt;''Administración &amp;gt; Configuración''&amp;lt;/code&amp;gt;, pestaña &amp;lt;code&amp;gt;'''Configuración'''&amp;lt;/code&amp;gt;, campo &amp;lt;code&amp;gt;'''&amp;quot;Ubicación de la biblioteca&amp;quot;'''&amp;lt;/code&amp;gt;: verificar que mantiene el valor &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;; no cambiarlo, ya que debe coincidir con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts de Apache.&lt;br /&gt;
* &amp;lt;code&amp;gt;''Administración &amp;gt; Configuración''&amp;lt;/code&amp;gt;, pestaña &amp;lt;code&amp;gt;'''Red'''&amp;lt;/code&amp;gt; (sección XMR): establecer la dirección pública de XMR como &amp;lt;code&amp;gt;ws://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; (o &amp;lt;code&amp;gt;wss://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; si está activo el vhost HTTPS). Los players se conectan por WebSocket a través del proxy de Apache; el puerto 9505 permanece abierto en el firewall únicamente como vía alternativa de publicación directa.&lt;br /&gt;
&lt;br /&gt;
Los cambios de claves y direcciones obligan a volver a autorizar los displays que estuvieran dados de alta en la máquina base (en un despliegue nuevo no debería haber ninguno; si los hubiera, eliminarlos).&lt;br /&gt;
&lt;br /&gt;
== Configuración a nivel de sistema operativo ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elemento !! Fichero / mecanismo !! Acción&lt;br /&gt;
|-&lt;br /&gt;
| Firewall || &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt; → ejecuta &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;, parametrizado por &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Editar &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; en cada despliegue (ver 4.4): la IP local está fijada a la de la máquina base y debe cambiarse junto con la red del cliente&lt;br /&gt;
|-&lt;br /&gt;
| fail2ban || &amp;lt;code&amp;gt;/etc/fail2ban/jail.d/&amp;lt;/code&amp;gt; || Verificar jail de &amp;lt;code&amp;gt;sshd&amp;lt;/code&amp;gt; activo tras el cambio de IP&lt;br /&gt;
|-&lt;br /&gt;
| Certificado TLS / HTTPS || Vhost &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; incluido de serie (deshabilitado) || Certificado siempre válido, nunca autofirmado: lo aporta el cliente si dispone de él o se emite con Let's Encrypt (&amp;lt;code&amp;gt;certbot certonly&amp;lt;/code&amp;gt; para el FQDN; requiere el puerto 80 alcanzable desde internet y renovación automática vía timer de certbot). Instalar certificado y clave en &amp;lt;code&amp;gt;/etc/ssl/cartelia/&amp;lt;/code&amp;gt; (o apuntar las directivas &amp;lt;code&amp;gt;SSL*&amp;lt;/code&amp;gt; a &amp;lt;code&amp;gt;/etc/letsencrypt/live/&amp;lt;FQDN&amp;gt;/&amp;lt;/code&amp;gt;), ajustar &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2enmod ssl proxy_wstunnel headers&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2ensite cartelia_https&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;. Activar después la redirección HTTP→HTTPS en &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; y actualizar en el portal la CMS Address (&amp;lt;code&amp;gt;https://&amp;lt;FQDN&amp;gt;&amp;lt;/code&amp;gt;) y la dirección de XMR (&amp;lt;code&amp;gt;wss://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Rotación de logs || &amp;lt;code&amp;gt;logrotate&amp;lt;/code&amp;gt; || Verificar&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Firewall (&amp;lt;code&amp;gt;/etc/firewall/&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
El firewall se implementa con nftables mediante dos ficheros, ejecutados en el arranque por &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero !! Función&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt; || Reglas nftables: acepta 80, 443 y 9505 (XMR) hacia la IP local/flotante, 22 solo desde &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt;, checks pasivos de Zabbix (10050) desde el servidor Zabbix, ICMP y tráfico establecido; el resto de entrada se descarta (&amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Variables de entorno que parametrizan las reglas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Variables de &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; a ajustar en cada despliegue:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Valor en la máquina base !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ETH&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;ens3&amp;lt;/code&amp;gt; || Cambiar solo si la interfaz del clon tiene otro nombre (&amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; || IP de la máquina base || Cambiar siempre a la IP del cliente (debe coincidir con la configurada en la sección 3.1, paso 3)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_FLO&amp;lt;/code&amp;gt; || Igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; (sin IP flotante) || Mantener igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; salvo despliegue con alta disponibilidad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_DATOS&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar al direccionamiento del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar a la red desde la que se accede por SSH; es la única red con acceso al puerto 22&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Aplicación y verificación de cambios:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Aplicar (corta y recrea todas las reglas; las conexiones establecidas se mantienen)&lt;br /&gt;
/etc/init.d/firewall start&lt;br /&gt;
&lt;br /&gt;
# Verificar reglas cargadas y contadores&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Verificación remota mínima tras el cambio (desde RED_GESTION)&lt;br /&gt;
ssh &amp;lt;usuario&amp;gt;@&amp;lt;IP-del-servidor&amp;gt;          # el 22 debe seguir accesible&lt;br /&gt;
curl -Is http://&amp;lt;IP-del-servidor&amp;gt;/ | head -1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #fef6e7; border: 1px solid #fbd68a; padding: 1em; border-radius: 4px;width: fit-content; margin-left: 0px&amp;quot;&amp;gt;&lt;br /&gt;
	'''⚠️ ATENCION !!'''&lt;br /&gt;
	'''Riesgo operativo''': editar &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; con valores erróneos y ejecutar el script '''puede dejar la máquina inaccesible por SSH''' (la política final es &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&amp;lt;br&amp;gt; Realizar siempre el cambio con una consola de &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt; abierta como vía de recuperación.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19194</id>
		<title>Instalacion cartelia 10</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19194"/>
		<updated>2026-07-13T10:25:10Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* Configuración desde el portal de administración de Cartelia */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[:Media:cartelia-despliegue-vm-documentacion-tecnica.pdf|Instalación de Cartelia 1.0]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
= Introducción =&lt;br /&gt;
&lt;br /&gt;
'''Cartelia''' es el producto de cartelería digital (digital signage) de la compañía.&lt;br /&gt;
&lt;br /&gt;
El presente documento describe el procedimiento de despliegue de una nueva instancia de Cartelia partiendo de una '''máquina virtual base''' con las siguientes características:&lt;br /&gt;
&lt;br /&gt;
* Sistema operativo: '''Debian 13 (trixie)'''.&lt;br /&gt;
* Hipervisor: '''KVM/QEMU''' (gestionado mediante &amp;lt;code&amp;gt;libvirt&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;virt-manager&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Software preinstalado: '''Cartelia 1.0''', instalado en &amp;lt;code&amp;gt;/var/www/html/cartelia&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Punto de partida''': la máquina base se entrega totalmente operativa, con Cartelia instalado de forma nativa sobre Apache + PHP y la base de datos MariaDB local ya creada e inicializada.&lt;br /&gt;
&lt;br /&gt;
'''Restricciones conocidas''':&lt;br /&gt;
&lt;br /&gt;
* La plantilla base '''no debe arrancarse nunca en producción sin personalizar''': contiene identidad de máquina, claves SSH y secretos del CMS compartidos con cualquier otra copia de la plantilla.&lt;br /&gt;
* Los players (pantallas) se autentican contra el CMS mediante la clave del servidor (''CMS Key'') y la URL del CMS; cualquier cambio posterior de IP/FQDN o de claves obliga a volver a autorizar los displays.&lt;br /&gt;
&lt;br /&gt;
= Arquitectura =&lt;br /&gt;
&lt;br /&gt;
== Esquema general del despliegue ==&lt;br /&gt;
&lt;br /&gt;
[[File:Cartelia-arquitectura.png|thumb|center|900px|Esquema general del despliegue de Cartelia sobre KVM/QEMU]]&lt;br /&gt;
&lt;br /&gt;
El CMS está instalado de forma nativa sobre el sistema operativo: Apache 2 con PHP como servidor web del portal, MariaDB local como base de datos y el servicio XMR ejecutándose como unidad de systemd.&lt;br /&gt;
&lt;br /&gt;
== Flujo del proceso de despliegue ==&lt;br /&gt;
&lt;br /&gt;
# El técnico de sistemas clona la plantilla base en el host KVM/QEMU (disco &amp;lt;code&amp;gt;qcow2&amp;lt;/code&amp;gt; + definición de dominio libvirt).&lt;br /&gt;
# En el primer arranque del clon, se personaliza la identidad del sistema operativo: &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt;, hostname, claves SSH de host, red, zona horaria y credenciales locales.&lt;br /&gt;
# Se personaliza el producto Cartelia: URL pública del CMS, secretos y contraseñas de base de datos, clave del servidor (''CMS Key''), dirección pública de XMR y personalización de marca.&lt;br /&gt;
# Se verifican los servicios, la conectividad de los players y el acceso al portal de administración.&lt;br /&gt;
# La máquina queda registrada en inventario/monitorización y se entrega.&lt;br /&gt;
&lt;br /&gt;
== Componentes principales ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Componente !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Portal Cartelia''' || Interfaz de administración de contenidos, layouts, programaciones y pantallas. Servida por Apache 2 + PHP.&lt;br /&gt;
|-&lt;br /&gt;
| '''MariaDB (local)''' || Almacena la configuración, usuarios, programaciones y metadatos de medios del CMS. Servicio nativo del sistema.&lt;br /&gt;
|-&lt;br /&gt;
| '''XMR (Cartelia Message Relay)''' || Canal push que permite al CMS enviar órdenes inmediatas a los players (recarga de contenido, capturas, reinicio). Servicio &amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;. Los players se conectan por WebSocket a la ruta &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, que reenvía a &amp;lt;code&amp;gt;ws://127.0.0.1:8080&amp;lt;/code&amp;gt;; el puerto 9505/TCP queda además permitido en el firewall para el modo de publicación directa.&lt;br /&gt;
|-&lt;br /&gt;
| '''Biblioteca de medios''' || &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;: directorio donde el CMS guarda los ficheros multimedia subidos (configurado en ''Administración &amp;gt; Configuración &amp;gt; Ubicación de la biblioteca'' y alineado con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts).&lt;br /&gt;
|-&lt;br /&gt;
| '''libvirt / KVM-QEMU''' || Capa de virtualización que aloja la VM.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Dependencias e integraciones externas ==&lt;br /&gt;
&lt;br /&gt;
* '''DNS''': registro A/AAAA del FQDN del CMS (imprescindible si los players usan nombre en lugar de IP).&lt;br /&gt;
* '''NTP''': sincronización horaria; las programaciones de contenido dependen de la hora del sistema.&lt;br /&gt;
* '''SMTP''' (opcional): relay de correo para notificaciones del CMS, si el cliente lo requiere. Se configura en el portal (''Administración &amp;gt; Configuración'', pestaña '''Mantenimiento''').&lt;br /&gt;
* '''Certificados TLS''': siempre certificados válidos, nunca autofirmados. Si el cliente dispone de certificado propio para el FQDN, lo aporta él; en caso contrario se emite con Let's Encrypt.&lt;br /&gt;
&lt;br /&gt;
= Personalización del sistema operativo (dentro de la VM) =&lt;br /&gt;
&lt;br /&gt;
== Personalización de identidad y red ==&lt;br /&gt;
&lt;br /&gt;
Todos los comandos se ejecutan como &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; desde la consola de &amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; en el primer arranque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Paso 1: regenerar las claves SSH de host (las de la plantilla son comunes a todos los clones)&lt;br /&gt;
rm -f /etc/ssh/ssh_host_*&lt;br /&gt;
dpkg-reconfigure openssh-server&lt;br /&gt;
systemctl restart ssh&lt;br /&gt;
&lt;br /&gt;
# Paso 2: hostname y resolución local&lt;br /&gt;
hostnamectl set-hostname &amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
sed -i &amp;quot;s/127.0.1.1.*/127.0.1.1\t&amp;lt;nombre-del-entorno&amp;gt; &amp;lt;FQDN-del-CMS&amp;gt;/&amp;quot; /etc/hosts&lt;br /&gt;
&lt;br /&gt;
# Paso 3: configuración de red (ifupdown, /etc/network/interfaces)&lt;br /&gt;
&lt;br /&gt;
# Paso 4: zona horaria y hora (NTP)&lt;br /&gt;
vi /etc/systemd/timesyncd.conf.d/local.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Paso 5: actualización de paquetes del SO&lt;br /&gt;
apt update &amp;amp;&amp;amp; apt upgrade -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Arranque del producto Cartelia ==&lt;br /&gt;
&lt;br /&gt;
El CMS ya viene instalado y operativo en la máquina base; en esta fase únicamente debe verificarse el arranque de los servicios nativos tras la personalización de red:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
&lt;br /&gt;
# Si algún servicio no arranca tras el cambio de red/hostname:&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
journalctl -u apache2 -n 50 --no-pager&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Verificación de la instalación ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# El portal responde en local (la máquina base publica en HTTP; ver 4.3 para HTTPS)&lt;br /&gt;
curl -Is http://localhost/ | head -1          # esperado: HTTP/1.1 200 OK (o 302 a /login)&lt;br /&gt;
&lt;br /&gt;
# Puertos de servicio a la escucha&lt;br /&gt;
ss -tlnp | grep -E ':(80|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Resolución del FQDN desde un puesto cliente&lt;br /&gt;
getent hosts &amp;lt;FQDN-del-CMS&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Acceso final: abrir &amp;lt;code&amp;gt;http://&amp;lt;FQDN-del-CMS&amp;gt;/&amp;lt;/code&amp;gt; en el navegador y validar la pantalla de login de Cartelia (o &amp;lt;code&amp;gt;https://&amp;lt;/code&amp;gt; si se ha habilitado el vhost TLS, ver 4.3).&lt;br /&gt;
&lt;br /&gt;
= Configuración =&lt;br /&gt;
&lt;br /&gt;
== Ficheros de configuración del producto ==&lt;br /&gt;
&lt;br /&gt;
La instalación es nativa (Apache + PHP + MariaDB local); estos son los ficheros que el SAT debe revisar/personalizar en cada clon:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; del CMS''' (&amp;lt;code&amp;gt;/var/www/html/cartelia/web/settings.php&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Descripción !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbhost&amp;lt;/code&amp;gt; || Host de MariaDB (normalmente &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt;) || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$dbuser&amp;lt;/code&amp;gt; || Base de datos y usuario del CMS || No cambiar salvo política del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbpass&amp;lt;/code&amp;gt; || Contraseña del usuario del CMS en MariaDB || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SECRET_KEY&amp;lt;/code&amp;gt; || Clave secreta de la instalación (cifrado interno) || Actualmente no se regenera: se mantiene el valor de la máquina base en todos los despliegues&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''XMR''' (&amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;, unidad en &amp;lt;code&amp;gt;/etc/systemd/system/xibo-xmr.service&amp;lt;/code&amp;gt;): ejecuta &amp;lt;code&amp;gt;/var/www/html/cartelia/vendor/bin/xmr.phar&amp;lt;/code&amp;gt; con PHP como usuario &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;, con reinicio automático (&amp;lt;code&amp;gt;Restart=always&amp;lt;/code&amp;gt;).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Sockets por defecto: WebSocket para players en &amp;lt;code&amp;gt;127.0.0.1:8080&amp;lt;/code&amp;gt;, expuesto a través del proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, y publicación interna del CMS en &amp;lt;code&amp;gt;tcp://127.0.0.1:50001&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Tras cualquier cambio: &amp;lt;code&amp;gt;systemctl restart xibo-xmr.service&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Apache''': la máquina base incluye dos vhosts en &amp;lt;code&amp;gt;/etc/apache2/sites-available/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; (habilitado por defecto): sirve el portal en el puerto 80. En la máquina base el &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt; es la IP de la propia máquina; en cada cliente debe actualizarse al FQDN definitivo. Incluye el proxy WebSocket de XMR (&amp;lt;code&amp;gt;ProxyPass /xmr ws://127.0.0.1:8080&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;XSendFile&amp;lt;/code&amp;gt; para la entrega de medios y una exclusión de mod_security (&amp;lt;code&amp;gt;SecRuleRemoveById 920350&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; (deshabilitado por defecto): vhost TLS preparado para clientes con FQDN y certificado. Su activación se describe en la sección 4.3.&lt;br /&gt;
&lt;br /&gt;
Validar siempre con &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; antes de &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Configuración desde el portal de administración de Cartelia ==&lt;br /&gt;
&lt;br /&gt;
Acceder con el usuario '''&amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt;''' y la contraseña estándar de la máquina base (conocida por el SAT; no se documenta aquí) y cambiar dicha contraseña de inmediato, ya que es común a todos los clones. A continuación:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;''Administración &amp;gt; Configuración &amp;gt; Red''&amp;lt;/code&amp;gt;: establecer la dirección del CMS (&amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt;) con el FQDN definitivo. Los players usan este valor para conectarse.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Clave secreta de CMS&amp;quot;''': es la clave que debe introducirse en cada player para autenticarlo contra el CMS. En un clon es idéntica a la de la máquina base (y, por tanto, conocida por cualquier otro despliegue), así que debe sustituirse por una clave nueva y única en cada cliente.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Ubicación de la biblioteca&amp;quot;''': verificar que mantiene el valor &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;; no cambiarlo, ya que debe coincidir con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts de Apache.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Red''' (sección XMR): establecer la dirección pública de XMR como &amp;lt;code&amp;gt;ws://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; (o &amp;lt;code&amp;gt;wss://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; si está activo el vhost HTTPS). Los players se conectan por WebSocket a través del proxy de Apache; el puerto 9505 permanece abierto en el firewall únicamente como vía alternativa de publicación directa.&lt;br /&gt;
&lt;br /&gt;
Los cambios de claves y direcciones obligan a volver a autorizar los displays que estuvieran dados de alta en la máquina base (en un despliegue nuevo no debería haber ninguno; si los hubiera, eliminarlos).&lt;br /&gt;
&lt;br /&gt;
== Configuración a nivel de sistema operativo ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elemento !! Fichero / mecanismo !! Acción&lt;br /&gt;
|-&lt;br /&gt;
| Firewall || &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt; → ejecuta &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;, parametrizado por &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Editar &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; en cada despliegue (ver 4.4): la IP local está fijada a la de la máquina base y debe cambiarse junto con la red del cliente&lt;br /&gt;
|-&lt;br /&gt;
| fail2ban || &amp;lt;code&amp;gt;/etc/fail2ban/jail.d/&amp;lt;/code&amp;gt; || Verificar jail de &amp;lt;code&amp;gt;sshd&amp;lt;/code&amp;gt; activo tras el cambio de IP&lt;br /&gt;
|-&lt;br /&gt;
| Certificado TLS / HTTPS || Vhost &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; incluido de serie (deshabilitado) || Certificado siempre válido, nunca autofirmado: lo aporta el cliente si dispone de él o se emite con Let's Encrypt (&amp;lt;code&amp;gt;certbot certonly&amp;lt;/code&amp;gt; para el FQDN; requiere el puerto 80 alcanzable desde internet y renovación automática vía timer de certbot). Instalar certificado y clave en &amp;lt;code&amp;gt;/etc/ssl/cartelia/&amp;lt;/code&amp;gt; (o apuntar las directivas &amp;lt;code&amp;gt;SSL*&amp;lt;/code&amp;gt; a &amp;lt;code&amp;gt;/etc/letsencrypt/live/&amp;lt;FQDN&amp;gt;/&amp;lt;/code&amp;gt;), ajustar &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2enmod ssl proxy_wstunnel headers&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2ensite cartelia_https&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;. Activar después la redirección HTTP→HTTPS en &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; y actualizar en el portal la CMS Address (&amp;lt;code&amp;gt;https://&amp;lt;FQDN&amp;gt;&amp;lt;/code&amp;gt;) y la dirección de XMR (&amp;lt;code&amp;gt;wss://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Rotación de logs || &amp;lt;code&amp;gt;logrotate&amp;lt;/code&amp;gt; || Verificar&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Firewall (&amp;lt;code&amp;gt;/etc/firewall/&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
El firewall se implementa con nftables mediante dos ficheros, ejecutados en el arranque por &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero !! Función&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt; || Reglas nftables: acepta 80, 443 y 9505 (XMR) hacia la IP local/flotante, 22 solo desde &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt;, checks pasivos de Zabbix (10050) desde el servidor Zabbix, ICMP y tráfico establecido; el resto de entrada se descarta (&amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Variables de entorno que parametrizan las reglas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Variables de &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; a ajustar en cada despliegue:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Valor en la máquina base !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ETH&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;ens3&amp;lt;/code&amp;gt; || Cambiar solo si la interfaz del clon tiene otro nombre (&amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; || IP de la máquina base || Cambiar siempre a la IP del cliente (debe coincidir con la configurada en la sección 3.1, paso 3)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_FLO&amp;lt;/code&amp;gt; || Igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; (sin IP flotante) || Mantener igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; salvo despliegue con alta disponibilidad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_DATOS&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar al direccionamiento del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar a la red desde la que se accede por SSH; es la única red con acceso al puerto 22&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Aplicación y verificación de cambios:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Aplicar (corta y recrea todas las reglas; las conexiones establecidas se mantienen)&lt;br /&gt;
/etc/init.d/firewall start&lt;br /&gt;
&lt;br /&gt;
# Verificar reglas cargadas y contadores&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Verificación remota mínima tras el cambio (desde RED_GESTION)&lt;br /&gt;
ssh &amp;lt;usuario&amp;gt;@&amp;lt;IP-del-servidor&amp;gt;          # el 22 debe seguir accesible&lt;br /&gt;
curl -Is http://&amp;lt;IP-del-servidor&amp;gt;/ | head -1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #fef6e7; border: 1px solid #fbd68a; padding: 1em; border-radius: 4px;width: fit-content; margin-left: 0px&amp;quot;&amp;gt;&lt;br /&gt;
	'''⚠️ ATENCION !!'''&lt;br /&gt;
	'''Riesgo operativo''': editar &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; con valores erróneos y ejecutar el script '''puede dejar la máquina inaccesible por SSH''' (la política final es &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&amp;lt;br&amp;gt; Realizar siempre el cambio con una consola de &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt; abierta como vía de recuperación.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19193</id>
		<title>Instalacion cartelia 10</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19193"/>
		<updated>2026-07-13T10:19:14Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* Ficheros de configuración del producto */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[:Media:cartelia-despliegue-vm-documentacion-tecnica.pdf|Instalación de Cartelia 1.0]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
= Introducción =&lt;br /&gt;
&lt;br /&gt;
'''Cartelia''' es el producto de cartelería digital (digital signage) de la compañía.&lt;br /&gt;
&lt;br /&gt;
El presente documento describe el procedimiento de despliegue de una nueva instancia de Cartelia partiendo de una '''máquina virtual base''' con las siguientes características:&lt;br /&gt;
&lt;br /&gt;
* Sistema operativo: '''Debian 13 (trixie)'''.&lt;br /&gt;
* Hipervisor: '''KVM/QEMU''' (gestionado mediante &amp;lt;code&amp;gt;libvirt&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;virt-manager&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Software preinstalado: '''Cartelia 1.0''', instalado en &amp;lt;code&amp;gt;/var/www/html/cartelia&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Punto de partida''': la máquina base se entrega totalmente operativa, con Cartelia instalado de forma nativa sobre Apache + PHP y la base de datos MariaDB local ya creada e inicializada.&lt;br /&gt;
&lt;br /&gt;
'''Restricciones conocidas''':&lt;br /&gt;
&lt;br /&gt;
* La plantilla base '''no debe arrancarse nunca en producción sin personalizar''': contiene identidad de máquina, claves SSH y secretos del CMS compartidos con cualquier otra copia de la plantilla.&lt;br /&gt;
* Los players (pantallas) se autentican contra el CMS mediante la clave del servidor (''CMS Key'') y la URL del CMS; cualquier cambio posterior de IP/FQDN o de claves obliga a volver a autorizar los displays.&lt;br /&gt;
&lt;br /&gt;
= Arquitectura =&lt;br /&gt;
&lt;br /&gt;
== Esquema general del despliegue ==&lt;br /&gt;
&lt;br /&gt;
[[File:Cartelia-arquitectura.png|thumb|center|900px|Esquema general del despliegue de Cartelia sobre KVM/QEMU]]&lt;br /&gt;
&lt;br /&gt;
El CMS está instalado de forma nativa sobre el sistema operativo: Apache 2 con PHP como servidor web del portal, MariaDB local como base de datos y el servicio XMR ejecutándose como unidad de systemd.&lt;br /&gt;
&lt;br /&gt;
== Flujo del proceso de despliegue ==&lt;br /&gt;
&lt;br /&gt;
# El técnico de sistemas clona la plantilla base en el host KVM/QEMU (disco &amp;lt;code&amp;gt;qcow2&amp;lt;/code&amp;gt; + definición de dominio libvirt).&lt;br /&gt;
# En el primer arranque del clon, se personaliza la identidad del sistema operativo: &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt;, hostname, claves SSH de host, red, zona horaria y credenciales locales.&lt;br /&gt;
# Se personaliza el producto Cartelia: URL pública del CMS, secretos y contraseñas de base de datos, clave del servidor (''CMS Key''), dirección pública de XMR y personalización de marca.&lt;br /&gt;
# Se verifican los servicios, la conectividad de los players y el acceso al portal de administración.&lt;br /&gt;
# La máquina queda registrada en inventario/monitorización y se entrega.&lt;br /&gt;
&lt;br /&gt;
== Componentes principales ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Componente !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Portal Cartelia''' || Interfaz de administración de contenidos, layouts, programaciones y pantallas. Servida por Apache 2 + PHP.&lt;br /&gt;
|-&lt;br /&gt;
| '''MariaDB (local)''' || Almacena la configuración, usuarios, programaciones y metadatos de medios del CMS. Servicio nativo del sistema.&lt;br /&gt;
|-&lt;br /&gt;
| '''XMR (Cartelia Message Relay)''' || Canal push que permite al CMS enviar órdenes inmediatas a los players (recarga de contenido, capturas, reinicio). Servicio &amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;. Los players se conectan por WebSocket a la ruta &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, que reenvía a &amp;lt;code&amp;gt;ws://127.0.0.1:8080&amp;lt;/code&amp;gt;; el puerto 9505/TCP queda además permitido en el firewall para el modo de publicación directa.&lt;br /&gt;
|-&lt;br /&gt;
| '''Biblioteca de medios''' || &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;: directorio donde el CMS guarda los ficheros multimedia subidos (configurado en ''Administración &amp;gt; Configuración &amp;gt; Ubicación de la biblioteca'' y alineado con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts).&lt;br /&gt;
|-&lt;br /&gt;
| '''libvirt / KVM-QEMU''' || Capa de virtualización que aloja la VM.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Dependencias e integraciones externas ==&lt;br /&gt;
&lt;br /&gt;
* '''DNS''': registro A/AAAA del FQDN del CMS (imprescindible si los players usan nombre en lugar de IP).&lt;br /&gt;
* '''NTP''': sincronización horaria; las programaciones de contenido dependen de la hora del sistema.&lt;br /&gt;
* '''SMTP''' (opcional): relay de correo para notificaciones del CMS, si el cliente lo requiere. Se configura en el portal (''Administración &amp;gt; Configuración'', pestaña '''Mantenimiento''').&lt;br /&gt;
* '''Certificados TLS''': siempre certificados válidos, nunca autofirmados. Si el cliente dispone de certificado propio para el FQDN, lo aporta él; en caso contrario se emite con Let's Encrypt.&lt;br /&gt;
&lt;br /&gt;
= Personalización del sistema operativo (dentro de la VM) =&lt;br /&gt;
&lt;br /&gt;
== Personalización de identidad y red ==&lt;br /&gt;
&lt;br /&gt;
Todos los comandos se ejecutan como &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; desde la consola de &amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; en el primer arranque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Paso 1: regenerar las claves SSH de host (las de la plantilla son comunes a todos los clones)&lt;br /&gt;
rm -f /etc/ssh/ssh_host_*&lt;br /&gt;
dpkg-reconfigure openssh-server&lt;br /&gt;
systemctl restart ssh&lt;br /&gt;
&lt;br /&gt;
# Paso 2: hostname y resolución local&lt;br /&gt;
hostnamectl set-hostname &amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
sed -i &amp;quot;s/127.0.1.1.*/127.0.1.1\t&amp;lt;nombre-del-entorno&amp;gt; &amp;lt;FQDN-del-CMS&amp;gt;/&amp;quot; /etc/hosts&lt;br /&gt;
&lt;br /&gt;
# Paso 3: configuración de red (ifupdown, /etc/network/interfaces)&lt;br /&gt;
&lt;br /&gt;
# Paso 4: zona horaria y hora (NTP)&lt;br /&gt;
vi /etc/systemd/timesyncd.conf.d/local.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Paso 5: actualización de paquetes del SO&lt;br /&gt;
apt update &amp;amp;&amp;amp; apt upgrade -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Arranque del producto Cartelia ==&lt;br /&gt;
&lt;br /&gt;
El CMS ya viene instalado y operativo en la máquina base; en esta fase únicamente debe verificarse el arranque de los servicios nativos tras la personalización de red:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
&lt;br /&gt;
# Si algún servicio no arranca tras el cambio de red/hostname:&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
journalctl -u apache2 -n 50 --no-pager&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Verificación de la instalación ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# El portal responde en local (la máquina base publica en HTTP; ver 4.3 para HTTPS)&lt;br /&gt;
curl -Is http://localhost/ | head -1          # esperado: HTTP/1.1 200 OK (o 302 a /login)&lt;br /&gt;
&lt;br /&gt;
# Puertos de servicio a la escucha&lt;br /&gt;
ss -tlnp | grep -E ':(80|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Resolución del FQDN desde un puesto cliente&lt;br /&gt;
getent hosts &amp;lt;FQDN-del-CMS&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Acceso final: abrir &amp;lt;code&amp;gt;http://&amp;lt;FQDN-del-CMS&amp;gt;/&amp;lt;/code&amp;gt; en el navegador y validar la pantalla de login de Cartelia (o &amp;lt;code&amp;gt;https://&amp;lt;/code&amp;gt; si se ha habilitado el vhost TLS, ver 4.3).&lt;br /&gt;
&lt;br /&gt;
= Configuración =&lt;br /&gt;
&lt;br /&gt;
== Ficheros de configuración del producto ==&lt;br /&gt;
&lt;br /&gt;
La instalación es nativa (Apache + PHP + MariaDB local); estos son los ficheros que el SAT debe revisar/personalizar en cada clon:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; del CMS''' (&amp;lt;code&amp;gt;/var/www/html/cartelia/web/settings.php&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Descripción !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbhost&amp;lt;/code&amp;gt; || Host de MariaDB (normalmente &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt;) || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$dbuser&amp;lt;/code&amp;gt; || Base de datos y usuario del CMS || No cambiar salvo política del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbpass&amp;lt;/code&amp;gt; || Contraseña del usuario del CMS en MariaDB || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SECRET_KEY&amp;lt;/code&amp;gt; || Clave secreta de la instalación (cifrado interno) || Actualmente no se regenera: se mantiene el valor de la máquina base en todos los despliegues&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''XMR''' (&amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;, unidad en &amp;lt;code&amp;gt;/etc/systemd/system/xibo-xmr.service&amp;lt;/code&amp;gt;): ejecuta &amp;lt;code&amp;gt;/var/www/html/cartelia/vendor/bin/xmr.phar&amp;lt;/code&amp;gt; con PHP como usuario &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;, con reinicio automático (&amp;lt;code&amp;gt;Restart=always&amp;lt;/code&amp;gt;).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Sockets por defecto: WebSocket para players en &amp;lt;code&amp;gt;127.0.0.1:8080&amp;lt;/code&amp;gt;, expuesto a través del proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, y publicación interna del CMS en &amp;lt;code&amp;gt;tcp://127.0.0.1:50001&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Tras cualquier cambio: &amp;lt;code&amp;gt;systemctl restart xibo-xmr.service&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Apache''': la máquina base incluye dos vhosts en &amp;lt;code&amp;gt;/etc/apache2/sites-available/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; (habilitado por defecto): sirve el portal en el puerto 80. En la máquina base el &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt; es la IP de la propia máquina; en cada cliente debe actualizarse al FQDN definitivo. Incluye el proxy WebSocket de XMR (&amp;lt;code&amp;gt;ProxyPass /xmr ws://127.0.0.1:8080&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;XSendFile&amp;lt;/code&amp;gt; para la entrega de medios y una exclusión de mod_security (&amp;lt;code&amp;gt;SecRuleRemoveById 920350&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; (deshabilitado por defecto): vhost TLS preparado para clientes con FQDN y certificado. Su activación se describe en la sección 4.3.&lt;br /&gt;
&lt;br /&gt;
Validar siempre con &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; antes de &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Configuración desde el portal de administración de Cartelia ==&lt;br /&gt;
&lt;br /&gt;
Acceder con el usuario '''&amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt;''' y la contraseña estándar de la máquina base (conocida por el SAT; no se documenta aquí) y cambiar dicha contraseña de inmediato, ya que es común a todos los clones. A continuación:&lt;br /&gt;
&lt;br /&gt;
* ''Administración &amp;gt; Configuración &amp;gt; Red'': establecer la dirección del CMS (&amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt;) con el FQDN definitivo. Los players usan este valor para conectarse.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Clave secreta de CMS&amp;quot;''': es la clave que debe introducirse en cada player para autenticarlo contra el CMS. En un clon es idéntica a la de la máquina base (y, por tanto, conocida por cualquier otro despliegue), así que debe sustituirse por una clave nueva y única en cada cliente.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Ubicación de la biblioteca&amp;quot;''': verificar que mantiene el valor &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;; no cambiarlo, ya que debe coincidir con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts de Apache.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Red''' (sección XMR): establecer la dirección pública de XMR como &amp;lt;code&amp;gt;ws://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; (o &amp;lt;code&amp;gt;wss://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; si está activo el vhost HTTPS). Los players se conectan por WebSocket a través del proxy de Apache; el puerto 9505 permanece abierto en el firewall únicamente como vía alternativa de publicación directa.&lt;br /&gt;
&lt;br /&gt;
Los cambios de claves y direcciones obligan a volver a autorizar los displays que estuvieran dados de alta en la máquina base (en un despliegue nuevo no debería haber ninguno; si los hubiera, eliminarlos).&lt;br /&gt;
&lt;br /&gt;
== Configuración a nivel de sistema operativo ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elemento !! Fichero / mecanismo !! Acción&lt;br /&gt;
|-&lt;br /&gt;
| Firewall || &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt; → ejecuta &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;, parametrizado por &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Editar &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; en cada despliegue (ver 4.4): la IP local está fijada a la de la máquina base y debe cambiarse junto con la red del cliente&lt;br /&gt;
|-&lt;br /&gt;
| fail2ban || &amp;lt;code&amp;gt;/etc/fail2ban/jail.d/&amp;lt;/code&amp;gt; || Verificar jail de &amp;lt;code&amp;gt;sshd&amp;lt;/code&amp;gt; activo tras el cambio de IP&lt;br /&gt;
|-&lt;br /&gt;
| Certificado TLS / HTTPS || Vhost &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; incluido de serie (deshabilitado) || Certificado siempre válido, nunca autofirmado: lo aporta el cliente si dispone de él o se emite con Let's Encrypt (&amp;lt;code&amp;gt;certbot certonly&amp;lt;/code&amp;gt; para el FQDN; requiere el puerto 80 alcanzable desde internet y renovación automática vía timer de certbot). Instalar certificado y clave en &amp;lt;code&amp;gt;/etc/ssl/cartelia/&amp;lt;/code&amp;gt; (o apuntar las directivas &amp;lt;code&amp;gt;SSL*&amp;lt;/code&amp;gt; a &amp;lt;code&amp;gt;/etc/letsencrypt/live/&amp;lt;FQDN&amp;gt;/&amp;lt;/code&amp;gt;), ajustar &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2enmod ssl proxy_wstunnel headers&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2ensite cartelia_https&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;. Activar después la redirección HTTP→HTTPS en &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; y actualizar en el portal la CMS Address (&amp;lt;code&amp;gt;https://&amp;lt;FQDN&amp;gt;&amp;lt;/code&amp;gt;) y la dirección de XMR (&amp;lt;code&amp;gt;wss://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Rotación de logs || &amp;lt;code&amp;gt;logrotate&amp;lt;/code&amp;gt; || Verificar&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Firewall (&amp;lt;code&amp;gt;/etc/firewall/&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
El firewall se implementa con nftables mediante dos ficheros, ejecutados en el arranque por &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero !! Función&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt; || Reglas nftables: acepta 80, 443 y 9505 (XMR) hacia la IP local/flotante, 22 solo desde &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt;, checks pasivos de Zabbix (10050) desde el servidor Zabbix, ICMP y tráfico establecido; el resto de entrada se descarta (&amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Variables de entorno que parametrizan las reglas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Variables de &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; a ajustar en cada despliegue:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Valor en la máquina base !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ETH&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;ens3&amp;lt;/code&amp;gt; || Cambiar solo si la interfaz del clon tiene otro nombre (&amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; || IP de la máquina base || Cambiar siempre a la IP del cliente (debe coincidir con la configurada en la sección 3.1, paso 3)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_FLO&amp;lt;/code&amp;gt; || Igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; (sin IP flotante) || Mantener igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; salvo despliegue con alta disponibilidad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_DATOS&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar al direccionamiento del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar a la red desde la que se accede por SSH; es la única red con acceso al puerto 22&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Aplicación y verificación de cambios:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Aplicar (corta y recrea todas las reglas; las conexiones establecidas se mantienen)&lt;br /&gt;
/etc/init.d/firewall start&lt;br /&gt;
&lt;br /&gt;
# Verificar reglas cargadas y contadores&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Verificación remota mínima tras el cambio (desde RED_GESTION)&lt;br /&gt;
ssh &amp;lt;usuario&amp;gt;@&amp;lt;IP-del-servidor&amp;gt;          # el 22 debe seguir accesible&lt;br /&gt;
curl -Is http://&amp;lt;IP-del-servidor&amp;gt;/ | head -1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #fef6e7; border: 1px solid #fbd68a; padding: 1em; border-radius: 4px;width: fit-content; margin-left: 0px&amp;quot;&amp;gt;&lt;br /&gt;
	'''⚠️ ATENCION !!'''&lt;br /&gt;
	'''Riesgo operativo''': editar &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; con valores erróneos y ejecutar el script '''puede dejar la máquina inaccesible por SSH''' (la política final es &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&amp;lt;br&amp;gt; Realizar siempre el cambio con una consola de &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt; abierta como vía de recuperación.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19192</id>
		<title>Instalacion cartelia 10</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19192"/>
		<updated>2026-07-13T10:18:59Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* Ficheros de configuración del producto */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[:Media:cartelia-despliegue-vm-documentacion-tecnica.pdf|Instalación de Cartelia 1.0]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
= Introducción =&lt;br /&gt;
&lt;br /&gt;
'''Cartelia''' es el producto de cartelería digital (digital signage) de la compañía.&lt;br /&gt;
&lt;br /&gt;
El presente documento describe el procedimiento de despliegue de una nueva instancia de Cartelia partiendo de una '''máquina virtual base''' con las siguientes características:&lt;br /&gt;
&lt;br /&gt;
* Sistema operativo: '''Debian 13 (trixie)'''.&lt;br /&gt;
* Hipervisor: '''KVM/QEMU''' (gestionado mediante &amp;lt;code&amp;gt;libvirt&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;virt-manager&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Software preinstalado: '''Cartelia 1.0''', instalado en &amp;lt;code&amp;gt;/var/www/html/cartelia&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Punto de partida''': la máquina base se entrega totalmente operativa, con Cartelia instalado de forma nativa sobre Apache + PHP y la base de datos MariaDB local ya creada e inicializada.&lt;br /&gt;
&lt;br /&gt;
'''Restricciones conocidas''':&lt;br /&gt;
&lt;br /&gt;
* La plantilla base '''no debe arrancarse nunca en producción sin personalizar''': contiene identidad de máquina, claves SSH y secretos del CMS compartidos con cualquier otra copia de la plantilla.&lt;br /&gt;
* Los players (pantallas) se autentican contra el CMS mediante la clave del servidor (''CMS Key'') y la URL del CMS; cualquier cambio posterior de IP/FQDN o de claves obliga a volver a autorizar los displays.&lt;br /&gt;
&lt;br /&gt;
= Arquitectura =&lt;br /&gt;
&lt;br /&gt;
== Esquema general del despliegue ==&lt;br /&gt;
&lt;br /&gt;
[[File:Cartelia-arquitectura.png|thumb|center|900px|Esquema general del despliegue de Cartelia sobre KVM/QEMU]]&lt;br /&gt;
&lt;br /&gt;
El CMS está instalado de forma nativa sobre el sistema operativo: Apache 2 con PHP como servidor web del portal, MariaDB local como base de datos y el servicio XMR ejecutándose como unidad de systemd.&lt;br /&gt;
&lt;br /&gt;
== Flujo del proceso de despliegue ==&lt;br /&gt;
&lt;br /&gt;
# El técnico de sistemas clona la plantilla base en el host KVM/QEMU (disco &amp;lt;code&amp;gt;qcow2&amp;lt;/code&amp;gt; + definición de dominio libvirt).&lt;br /&gt;
# En el primer arranque del clon, se personaliza la identidad del sistema operativo: &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt;, hostname, claves SSH de host, red, zona horaria y credenciales locales.&lt;br /&gt;
# Se personaliza el producto Cartelia: URL pública del CMS, secretos y contraseñas de base de datos, clave del servidor (''CMS Key''), dirección pública de XMR y personalización de marca.&lt;br /&gt;
# Se verifican los servicios, la conectividad de los players y el acceso al portal de administración.&lt;br /&gt;
# La máquina queda registrada en inventario/monitorización y se entrega.&lt;br /&gt;
&lt;br /&gt;
== Componentes principales ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Componente !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Portal Cartelia''' || Interfaz de administración de contenidos, layouts, programaciones y pantallas. Servida por Apache 2 + PHP.&lt;br /&gt;
|-&lt;br /&gt;
| '''MariaDB (local)''' || Almacena la configuración, usuarios, programaciones y metadatos de medios del CMS. Servicio nativo del sistema.&lt;br /&gt;
|-&lt;br /&gt;
| '''XMR (Cartelia Message Relay)''' || Canal push que permite al CMS enviar órdenes inmediatas a los players (recarga de contenido, capturas, reinicio). Servicio &amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;. Los players se conectan por WebSocket a la ruta &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, que reenvía a &amp;lt;code&amp;gt;ws://127.0.0.1:8080&amp;lt;/code&amp;gt;; el puerto 9505/TCP queda además permitido en el firewall para el modo de publicación directa.&lt;br /&gt;
|-&lt;br /&gt;
| '''Biblioteca de medios''' || &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;: directorio donde el CMS guarda los ficheros multimedia subidos (configurado en ''Administración &amp;gt; Configuración &amp;gt; Ubicación de la biblioteca'' y alineado con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts).&lt;br /&gt;
|-&lt;br /&gt;
| '''libvirt / KVM-QEMU''' || Capa de virtualización que aloja la VM.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Dependencias e integraciones externas ==&lt;br /&gt;
&lt;br /&gt;
* '''DNS''': registro A/AAAA del FQDN del CMS (imprescindible si los players usan nombre en lugar de IP).&lt;br /&gt;
* '''NTP''': sincronización horaria; las programaciones de contenido dependen de la hora del sistema.&lt;br /&gt;
* '''SMTP''' (opcional): relay de correo para notificaciones del CMS, si el cliente lo requiere. Se configura en el portal (''Administración &amp;gt; Configuración'', pestaña '''Mantenimiento''').&lt;br /&gt;
* '''Certificados TLS''': siempre certificados válidos, nunca autofirmados. Si el cliente dispone de certificado propio para el FQDN, lo aporta él; en caso contrario se emite con Let's Encrypt.&lt;br /&gt;
&lt;br /&gt;
= Personalización del sistema operativo (dentro de la VM) =&lt;br /&gt;
&lt;br /&gt;
== Personalización de identidad y red ==&lt;br /&gt;
&lt;br /&gt;
Todos los comandos se ejecutan como &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; desde la consola de &amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; en el primer arranque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Paso 1: regenerar las claves SSH de host (las de la plantilla son comunes a todos los clones)&lt;br /&gt;
rm -f /etc/ssh/ssh_host_*&lt;br /&gt;
dpkg-reconfigure openssh-server&lt;br /&gt;
systemctl restart ssh&lt;br /&gt;
&lt;br /&gt;
# Paso 2: hostname y resolución local&lt;br /&gt;
hostnamectl set-hostname &amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
sed -i &amp;quot;s/127.0.1.1.*/127.0.1.1\t&amp;lt;nombre-del-entorno&amp;gt; &amp;lt;FQDN-del-CMS&amp;gt;/&amp;quot; /etc/hosts&lt;br /&gt;
&lt;br /&gt;
# Paso 3: configuración de red (ifupdown, /etc/network/interfaces)&lt;br /&gt;
&lt;br /&gt;
# Paso 4: zona horaria y hora (NTP)&lt;br /&gt;
vi /etc/systemd/timesyncd.conf.d/local.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Paso 5: actualización de paquetes del SO&lt;br /&gt;
apt update &amp;amp;&amp;amp; apt upgrade -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Arranque del producto Cartelia ==&lt;br /&gt;
&lt;br /&gt;
El CMS ya viene instalado y operativo en la máquina base; en esta fase únicamente debe verificarse el arranque de los servicios nativos tras la personalización de red:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
&lt;br /&gt;
# Si algún servicio no arranca tras el cambio de red/hostname:&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
journalctl -u apache2 -n 50 --no-pager&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Verificación de la instalación ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# El portal responde en local (la máquina base publica en HTTP; ver 4.3 para HTTPS)&lt;br /&gt;
curl -Is http://localhost/ | head -1          # esperado: HTTP/1.1 200 OK (o 302 a /login)&lt;br /&gt;
&lt;br /&gt;
# Puertos de servicio a la escucha&lt;br /&gt;
ss -tlnp | grep -E ':(80|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Resolución del FQDN desde un puesto cliente&lt;br /&gt;
getent hosts &amp;lt;FQDN-del-CMS&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Acceso final: abrir &amp;lt;code&amp;gt;http://&amp;lt;FQDN-del-CMS&amp;gt;/&amp;lt;/code&amp;gt; en el navegador y validar la pantalla de login de Cartelia (o &amp;lt;code&amp;gt;https://&amp;lt;/code&amp;gt; si se ha habilitado el vhost TLS, ver 4.3).&lt;br /&gt;
&lt;br /&gt;
= Configuración =&lt;br /&gt;
&lt;br /&gt;
== Ficheros de configuración del producto ==&lt;br /&gt;
&lt;br /&gt;
La instalación es nativa (Apache + PHP + MariaDB local); estos son los ficheros que el SAT debe revisar/personalizar en cada clon:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; del CMS''' (&amp;lt;code&amp;gt;/var/www/html/cartelia/web/settings.php&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Descripción !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbhost&amp;lt;/code&amp;gt; || Host de MariaDB (normalmente &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt;) || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$dbuser&amp;lt;/code&amp;gt; || Base de datos y usuario del CMS || No cambiar salvo política del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbpass&amp;lt;/code&amp;gt; || Contraseña del usuario del CMS en MariaDB || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SECRET_KEY&amp;lt;/code&amp;gt; || Clave secreta de la instalación (cifrado interno) || Actualmente no se regenera: se mantiene el valor de la máquina base en todos los despliegues&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''XMR''' (&amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;, unidad en &amp;lt;code&amp;gt;/etc/systemd/system/xibo-xmr.service&amp;lt;/code&amp;gt;): ejecuta &amp;lt;code&amp;gt;/var/www/html/cartelia/vendor/bin/xmr.phar&amp;lt;/code&amp;gt; con PHP como usuario &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;, con reinicio automático (&amp;lt;code&amp;gt;Restart=always&amp;lt;/code&amp;gt;).&lt;br /&gt;
Sockets por defecto: WebSocket para players en &amp;lt;code&amp;gt;127.0.0.1:8080&amp;lt;/code&amp;gt;, expuesto a través del proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, y publicación interna del CMS en &amp;lt;code&amp;gt;tcp://127.0.0.1:50001&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Tras cualquier cambio: &amp;lt;code&amp;gt;systemctl restart xibo-xmr.service&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Apache''': la máquina base incluye dos vhosts en &amp;lt;code&amp;gt;/etc/apache2/sites-available/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; (habilitado por defecto): sirve el portal en el puerto 80. En la máquina base el &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt; es la IP de la propia máquina; en cada cliente debe actualizarse al FQDN definitivo. Incluye el proxy WebSocket de XMR (&amp;lt;code&amp;gt;ProxyPass /xmr ws://127.0.0.1:8080&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;XSendFile&amp;lt;/code&amp;gt; para la entrega de medios y una exclusión de mod_security (&amp;lt;code&amp;gt;SecRuleRemoveById 920350&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; (deshabilitado por defecto): vhost TLS preparado para clientes con FQDN y certificado. Su activación se describe en la sección 4.3.&lt;br /&gt;
&lt;br /&gt;
Validar siempre con &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; antes de &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Configuración desde el portal de administración de Cartelia ==&lt;br /&gt;
&lt;br /&gt;
Acceder con el usuario '''&amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt;''' y la contraseña estándar de la máquina base (conocida por el SAT; no se documenta aquí) y cambiar dicha contraseña de inmediato, ya que es común a todos los clones. A continuación:&lt;br /&gt;
&lt;br /&gt;
* ''Administración &amp;gt; Configuración &amp;gt; Red'': establecer la dirección del CMS (&amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt;) con el FQDN definitivo. Los players usan este valor para conectarse.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Clave secreta de CMS&amp;quot;''': es la clave que debe introducirse en cada player para autenticarlo contra el CMS. En un clon es idéntica a la de la máquina base (y, por tanto, conocida por cualquier otro despliegue), así que debe sustituirse por una clave nueva y única en cada cliente.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Ubicación de la biblioteca&amp;quot;''': verificar que mantiene el valor &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;; no cambiarlo, ya que debe coincidir con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts de Apache.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Red''' (sección XMR): establecer la dirección pública de XMR como &amp;lt;code&amp;gt;ws://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; (o &amp;lt;code&amp;gt;wss://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; si está activo el vhost HTTPS). Los players se conectan por WebSocket a través del proxy de Apache; el puerto 9505 permanece abierto en el firewall únicamente como vía alternativa de publicación directa.&lt;br /&gt;
&lt;br /&gt;
Los cambios de claves y direcciones obligan a volver a autorizar los displays que estuvieran dados de alta en la máquina base (en un despliegue nuevo no debería haber ninguno; si los hubiera, eliminarlos).&lt;br /&gt;
&lt;br /&gt;
== Configuración a nivel de sistema operativo ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elemento !! Fichero / mecanismo !! Acción&lt;br /&gt;
|-&lt;br /&gt;
| Firewall || &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt; → ejecuta &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;, parametrizado por &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Editar &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; en cada despliegue (ver 4.4): la IP local está fijada a la de la máquina base y debe cambiarse junto con la red del cliente&lt;br /&gt;
|-&lt;br /&gt;
| fail2ban || &amp;lt;code&amp;gt;/etc/fail2ban/jail.d/&amp;lt;/code&amp;gt; || Verificar jail de &amp;lt;code&amp;gt;sshd&amp;lt;/code&amp;gt; activo tras el cambio de IP&lt;br /&gt;
|-&lt;br /&gt;
| Certificado TLS / HTTPS || Vhost &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; incluido de serie (deshabilitado) || Certificado siempre válido, nunca autofirmado: lo aporta el cliente si dispone de él o se emite con Let's Encrypt (&amp;lt;code&amp;gt;certbot certonly&amp;lt;/code&amp;gt; para el FQDN; requiere el puerto 80 alcanzable desde internet y renovación automática vía timer de certbot). Instalar certificado y clave en &amp;lt;code&amp;gt;/etc/ssl/cartelia/&amp;lt;/code&amp;gt; (o apuntar las directivas &amp;lt;code&amp;gt;SSL*&amp;lt;/code&amp;gt; a &amp;lt;code&amp;gt;/etc/letsencrypt/live/&amp;lt;FQDN&amp;gt;/&amp;lt;/code&amp;gt;), ajustar &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2enmod ssl proxy_wstunnel headers&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2ensite cartelia_https&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;. Activar después la redirección HTTP→HTTPS en &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; y actualizar en el portal la CMS Address (&amp;lt;code&amp;gt;https://&amp;lt;FQDN&amp;gt;&amp;lt;/code&amp;gt;) y la dirección de XMR (&amp;lt;code&amp;gt;wss://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Rotación de logs || &amp;lt;code&amp;gt;logrotate&amp;lt;/code&amp;gt; || Verificar&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Firewall (&amp;lt;code&amp;gt;/etc/firewall/&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
El firewall se implementa con nftables mediante dos ficheros, ejecutados en el arranque por &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero !! Función&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt; || Reglas nftables: acepta 80, 443 y 9505 (XMR) hacia la IP local/flotante, 22 solo desde &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt;, checks pasivos de Zabbix (10050) desde el servidor Zabbix, ICMP y tráfico establecido; el resto de entrada se descarta (&amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Variables de entorno que parametrizan las reglas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Variables de &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; a ajustar en cada despliegue:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Valor en la máquina base !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ETH&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;ens3&amp;lt;/code&amp;gt; || Cambiar solo si la interfaz del clon tiene otro nombre (&amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; || IP de la máquina base || Cambiar siempre a la IP del cliente (debe coincidir con la configurada en la sección 3.1, paso 3)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_FLO&amp;lt;/code&amp;gt; || Igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; (sin IP flotante) || Mantener igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; salvo despliegue con alta disponibilidad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_DATOS&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar al direccionamiento del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar a la red desde la que se accede por SSH; es la única red con acceso al puerto 22&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Aplicación y verificación de cambios:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Aplicar (corta y recrea todas las reglas; las conexiones establecidas se mantienen)&lt;br /&gt;
/etc/init.d/firewall start&lt;br /&gt;
&lt;br /&gt;
# Verificar reglas cargadas y contadores&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Verificación remota mínima tras el cambio (desde RED_GESTION)&lt;br /&gt;
ssh &amp;lt;usuario&amp;gt;@&amp;lt;IP-del-servidor&amp;gt;          # el 22 debe seguir accesible&lt;br /&gt;
curl -Is http://&amp;lt;IP-del-servidor&amp;gt;/ | head -1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #fef6e7; border: 1px solid #fbd68a; padding: 1em; border-radius: 4px;width: fit-content; margin-left: 0px&amp;quot;&amp;gt;&lt;br /&gt;
	'''⚠️ ATENCION !!'''&lt;br /&gt;
	'''Riesgo operativo''': editar &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; con valores erróneos y ejecutar el script '''puede dejar la máquina inaccesible por SSH''' (la política final es &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&amp;lt;br&amp;gt; Realizar siempre el cambio con una consola de &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt; abierta como vía de recuperación.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19191</id>
		<title>Instalacion cartelia 10</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19191"/>
		<updated>2026-07-13T10:05:49Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* Firewall (/etc/firewall/) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[:Media:cartelia-despliegue-vm-documentacion-tecnica.pdf|Instalación de Cartelia 1.0]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
= Introducción =&lt;br /&gt;
&lt;br /&gt;
'''Cartelia''' es el producto de cartelería digital (digital signage) de la compañía.&lt;br /&gt;
&lt;br /&gt;
El presente documento describe el procedimiento de despliegue de una nueva instancia de Cartelia partiendo de una '''máquina virtual base''' con las siguientes características:&lt;br /&gt;
&lt;br /&gt;
* Sistema operativo: '''Debian 13 (trixie)'''.&lt;br /&gt;
* Hipervisor: '''KVM/QEMU''' (gestionado mediante &amp;lt;code&amp;gt;libvirt&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;virt-manager&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Software preinstalado: '''Cartelia 1.0''', instalado en &amp;lt;code&amp;gt;/var/www/html/cartelia&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Punto de partida''': la máquina base se entrega totalmente operativa, con Cartelia instalado de forma nativa sobre Apache + PHP y la base de datos MariaDB local ya creada e inicializada.&lt;br /&gt;
&lt;br /&gt;
'''Restricciones conocidas''':&lt;br /&gt;
&lt;br /&gt;
* La plantilla base '''no debe arrancarse nunca en producción sin personalizar''': contiene identidad de máquina, claves SSH y secretos del CMS compartidos con cualquier otra copia de la plantilla.&lt;br /&gt;
* Los players (pantallas) se autentican contra el CMS mediante la clave del servidor (''CMS Key'') y la URL del CMS; cualquier cambio posterior de IP/FQDN o de claves obliga a volver a autorizar los displays.&lt;br /&gt;
&lt;br /&gt;
= Arquitectura =&lt;br /&gt;
&lt;br /&gt;
== Esquema general del despliegue ==&lt;br /&gt;
&lt;br /&gt;
[[File:Cartelia-arquitectura.png|thumb|center|900px|Esquema general del despliegue de Cartelia sobre KVM/QEMU]]&lt;br /&gt;
&lt;br /&gt;
El CMS está instalado de forma nativa sobre el sistema operativo: Apache 2 con PHP como servidor web del portal, MariaDB local como base de datos y el servicio XMR ejecutándose como unidad de systemd.&lt;br /&gt;
&lt;br /&gt;
== Flujo del proceso de despliegue ==&lt;br /&gt;
&lt;br /&gt;
# El técnico de sistemas clona la plantilla base en el host KVM/QEMU (disco &amp;lt;code&amp;gt;qcow2&amp;lt;/code&amp;gt; + definición de dominio libvirt).&lt;br /&gt;
# En el primer arranque del clon, se personaliza la identidad del sistema operativo: &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt;, hostname, claves SSH de host, red, zona horaria y credenciales locales.&lt;br /&gt;
# Se personaliza el producto Cartelia: URL pública del CMS, secretos y contraseñas de base de datos, clave del servidor (''CMS Key''), dirección pública de XMR y personalización de marca.&lt;br /&gt;
# Se verifican los servicios, la conectividad de los players y el acceso al portal de administración.&lt;br /&gt;
# La máquina queda registrada en inventario/monitorización y se entrega.&lt;br /&gt;
&lt;br /&gt;
== Componentes principales ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Componente !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Portal Cartelia''' || Interfaz de administración de contenidos, layouts, programaciones y pantallas. Servida por Apache 2 + PHP.&lt;br /&gt;
|-&lt;br /&gt;
| '''MariaDB (local)''' || Almacena la configuración, usuarios, programaciones y metadatos de medios del CMS. Servicio nativo del sistema.&lt;br /&gt;
|-&lt;br /&gt;
| '''XMR (Cartelia Message Relay)''' || Canal push que permite al CMS enviar órdenes inmediatas a los players (recarga de contenido, capturas, reinicio). Servicio &amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;. Los players se conectan por WebSocket a la ruta &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, que reenvía a &amp;lt;code&amp;gt;ws://127.0.0.1:8080&amp;lt;/code&amp;gt;; el puerto 9505/TCP queda además permitido en el firewall para el modo de publicación directa.&lt;br /&gt;
|-&lt;br /&gt;
| '''Biblioteca de medios''' || &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;: directorio donde el CMS guarda los ficheros multimedia subidos (configurado en ''Administración &amp;gt; Configuración &amp;gt; Ubicación de la biblioteca'' y alineado con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts).&lt;br /&gt;
|-&lt;br /&gt;
| '''libvirt / KVM-QEMU''' || Capa de virtualización que aloja la VM.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Dependencias e integraciones externas ==&lt;br /&gt;
&lt;br /&gt;
* '''DNS''': registro A/AAAA del FQDN del CMS (imprescindible si los players usan nombre en lugar de IP).&lt;br /&gt;
* '''NTP''': sincronización horaria; las programaciones de contenido dependen de la hora del sistema.&lt;br /&gt;
* '''SMTP''' (opcional): relay de correo para notificaciones del CMS, si el cliente lo requiere. Se configura en el portal (''Administración &amp;gt; Configuración'', pestaña '''Mantenimiento''').&lt;br /&gt;
* '''Certificados TLS''': siempre certificados válidos, nunca autofirmados. Si el cliente dispone de certificado propio para el FQDN, lo aporta él; en caso contrario se emite con Let's Encrypt.&lt;br /&gt;
&lt;br /&gt;
= Personalización del sistema operativo (dentro de la VM) =&lt;br /&gt;
&lt;br /&gt;
== Personalización de identidad y red ==&lt;br /&gt;
&lt;br /&gt;
Todos los comandos se ejecutan como &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; desde la consola de &amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; en el primer arranque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Paso 1: regenerar las claves SSH de host (las de la plantilla son comunes a todos los clones)&lt;br /&gt;
rm -f /etc/ssh/ssh_host_*&lt;br /&gt;
dpkg-reconfigure openssh-server&lt;br /&gt;
systemctl restart ssh&lt;br /&gt;
&lt;br /&gt;
# Paso 2: hostname y resolución local&lt;br /&gt;
hostnamectl set-hostname &amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
sed -i &amp;quot;s/127.0.1.1.*/127.0.1.1\t&amp;lt;nombre-del-entorno&amp;gt; &amp;lt;FQDN-del-CMS&amp;gt;/&amp;quot; /etc/hosts&lt;br /&gt;
&lt;br /&gt;
# Paso 3: configuración de red (ifupdown, /etc/network/interfaces)&lt;br /&gt;
&lt;br /&gt;
# Paso 4: zona horaria y hora (NTP)&lt;br /&gt;
vi /etc/systemd/timesyncd.conf.d/local.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Paso 5: actualización de paquetes del SO&lt;br /&gt;
apt update &amp;amp;&amp;amp; apt upgrade -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Arranque del producto Cartelia ==&lt;br /&gt;
&lt;br /&gt;
El CMS ya viene instalado y operativo en la máquina base; en esta fase únicamente debe verificarse el arranque de los servicios nativos tras la personalización de red:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
&lt;br /&gt;
# Si algún servicio no arranca tras el cambio de red/hostname:&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
journalctl -u apache2 -n 50 --no-pager&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Verificación de la instalación ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# El portal responde en local (la máquina base publica en HTTP; ver 4.3 para HTTPS)&lt;br /&gt;
curl -Is http://localhost/ | head -1          # esperado: HTTP/1.1 200 OK (o 302 a /login)&lt;br /&gt;
&lt;br /&gt;
# Puertos de servicio a la escucha&lt;br /&gt;
ss -tlnp | grep -E ':(80|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Resolución del FQDN desde un puesto cliente&lt;br /&gt;
getent hosts &amp;lt;FQDN-del-CMS&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Acceso final: abrir &amp;lt;code&amp;gt;http://&amp;lt;FQDN-del-CMS&amp;gt;/&amp;lt;/code&amp;gt; en el navegador y validar la pantalla de login de Cartelia (o &amp;lt;code&amp;gt;https://&amp;lt;/code&amp;gt; si se ha habilitado el vhost TLS, ver 4.3).&lt;br /&gt;
&lt;br /&gt;
= Configuración =&lt;br /&gt;
&lt;br /&gt;
== Ficheros de configuración del producto ==&lt;br /&gt;
&lt;br /&gt;
La instalación es nativa (Apache + PHP + MariaDB local); estos son los ficheros que el SAT debe revisar/personalizar en cada clon:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; del CMS''' (&amp;lt;code&amp;gt;/var/www/html/cartelia/web/settings.php&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Descripción !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbhost&amp;lt;/code&amp;gt; || Host de MariaDB (normalmente &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt;) || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$dbuser&amp;lt;/code&amp;gt; || Base de datos y usuario del CMS || No cambiar salvo política del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbpass&amp;lt;/code&amp;gt; || Contraseña del usuario del CMS en MariaDB || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SECRET_KEY&amp;lt;/code&amp;gt; || Clave secreta de la instalación (cifrado interno) || Actualmente no se regenera: se mantiene el valor de la máquina base en todos los despliegues&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''XMR''' (&amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;, unidad en &amp;lt;code&amp;gt;/etc/systemd/system/xibo-xmr.service&amp;lt;/code&amp;gt;): ejecuta &amp;lt;code&amp;gt;/var/www/html/cartelia/vendor/bin/xmr.phar&amp;lt;/code&amp;gt; con PHP como usuario &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;, con reinicio automático (&amp;lt;code&amp;gt;Restart=always&amp;lt;/code&amp;gt;). Sockets por defecto: WebSocket para players en &amp;lt;code&amp;gt;127.0.0.1:8080&amp;lt;/code&amp;gt;, expuesto a través del proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, y publicación interna del CMS en &amp;lt;code&amp;gt;tcp://127.0.0.1:50001&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Tras cualquier cambio: &amp;lt;code&amp;gt;systemctl restart xibo-xmr.service&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Apache''': la máquina base incluye dos vhosts en &amp;lt;code&amp;gt;/etc/apache2/sites-available/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; (habilitado por defecto): sirve el portal en el puerto 80. En la máquina base el &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt; es la IP de la propia máquina; en cada cliente debe actualizarse al FQDN definitivo. Incluye el proxy WebSocket de XMR (&amp;lt;code&amp;gt;ProxyPass /xmr ws://127.0.0.1:8080&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;XSendFile&amp;lt;/code&amp;gt; para la entrega de medios y una exclusión de mod_security (&amp;lt;code&amp;gt;SecRuleRemoveById 920350&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; (deshabilitado por defecto): vhost TLS preparado para clientes con FQDN y certificado. Su activación se describe en la sección 4.3.&lt;br /&gt;
&lt;br /&gt;
Validar siempre con &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; antes de &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Configuración desde el portal de administración de Cartelia ==&lt;br /&gt;
&lt;br /&gt;
Acceder con el usuario '''&amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt;''' y la contraseña estándar de la máquina base (conocida por el SAT; no se documenta aquí) y cambiar dicha contraseña de inmediato, ya que es común a todos los clones. A continuación:&lt;br /&gt;
&lt;br /&gt;
* ''Administración &amp;gt; Configuración &amp;gt; Red'': establecer la dirección del CMS (&amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt;) con el FQDN definitivo. Los players usan este valor para conectarse.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Clave secreta de CMS&amp;quot;''': es la clave que debe introducirse en cada player para autenticarlo contra el CMS. En un clon es idéntica a la de la máquina base (y, por tanto, conocida por cualquier otro despliegue), así que debe sustituirse por una clave nueva y única en cada cliente.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Ubicación de la biblioteca&amp;quot;''': verificar que mantiene el valor &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;; no cambiarlo, ya que debe coincidir con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts de Apache.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Red''' (sección XMR): establecer la dirección pública de XMR como &amp;lt;code&amp;gt;ws://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; (o &amp;lt;code&amp;gt;wss://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; si está activo el vhost HTTPS). Los players se conectan por WebSocket a través del proxy de Apache; el puerto 9505 permanece abierto en el firewall únicamente como vía alternativa de publicación directa.&lt;br /&gt;
&lt;br /&gt;
Los cambios de claves y direcciones obligan a volver a autorizar los displays que estuvieran dados de alta en la máquina base (en un despliegue nuevo no debería haber ninguno; si los hubiera, eliminarlos).&lt;br /&gt;
&lt;br /&gt;
== Configuración a nivel de sistema operativo ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elemento !! Fichero / mecanismo !! Acción&lt;br /&gt;
|-&lt;br /&gt;
| Firewall || &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt; → ejecuta &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;, parametrizado por &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Editar &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; en cada despliegue (ver 4.4): la IP local está fijada a la de la máquina base y debe cambiarse junto con la red del cliente&lt;br /&gt;
|-&lt;br /&gt;
| fail2ban || &amp;lt;code&amp;gt;/etc/fail2ban/jail.d/&amp;lt;/code&amp;gt; || Verificar jail de &amp;lt;code&amp;gt;sshd&amp;lt;/code&amp;gt; activo tras el cambio de IP&lt;br /&gt;
|-&lt;br /&gt;
| Certificado TLS / HTTPS || Vhost &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; incluido de serie (deshabilitado) || Certificado siempre válido, nunca autofirmado: lo aporta el cliente si dispone de él o se emite con Let's Encrypt (&amp;lt;code&amp;gt;certbot certonly&amp;lt;/code&amp;gt; para el FQDN; requiere el puerto 80 alcanzable desde internet y renovación automática vía timer de certbot). Instalar certificado y clave en &amp;lt;code&amp;gt;/etc/ssl/cartelia/&amp;lt;/code&amp;gt; (o apuntar las directivas &amp;lt;code&amp;gt;SSL*&amp;lt;/code&amp;gt; a &amp;lt;code&amp;gt;/etc/letsencrypt/live/&amp;lt;FQDN&amp;gt;/&amp;lt;/code&amp;gt;), ajustar &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2enmod ssl proxy_wstunnel headers&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2ensite cartelia_https&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;. Activar después la redirección HTTP→HTTPS en &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; y actualizar en el portal la CMS Address (&amp;lt;code&amp;gt;https://&amp;lt;FQDN&amp;gt;&amp;lt;/code&amp;gt;) y la dirección de XMR (&amp;lt;code&amp;gt;wss://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Rotación de logs || &amp;lt;code&amp;gt;logrotate&amp;lt;/code&amp;gt; || Verificar&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Firewall (&amp;lt;code&amp;gt;/etc/firewall/&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
El firewall se implementa con nftables mediante dos ficheros, ejecutados en el arranque por &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero !! Función&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt; || Reglas nftables: acepta 80, 443 y 9505 (XMR) hacia la IP local/flotante, 22 solo desde &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt;, checks pasivos de Zabbix (10050) desde el servidor Zabbix, ICMP y tráfico establecido; el resto de entrada se descarta (&amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Variables de entorno que parametrizan las reglas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Variables de &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; a ajustar en cada despliegue:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Valor en la máquina base !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ETH&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;ens3&amp;lt;/code&amp;gt; || Cambiar solo si la interfaz del clon tiene otro nombre (&amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; || IP de la máquina base || Cambiar siempre a la IP del cliente (debe coincidir con la configurada en la sección 3.1, paso 3)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_FLO&amp;lt;/code&amp;gt; || Igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; (sin IP flotante) || Mantener igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; salvo despliegue con alta disponibilidad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_DATOS&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar al direccionamiento del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar a la red desde la que se accede por SSH; es la única red con acceso al puerto 22&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Aplicación y verificación de cambios:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Aplicar (corta y recrea todas las reglas; las conexiones establecidas se mantienen)&lt;br /&gt;
/etc/init.d/firewall start&lt;br /&gt;
&lt;br /&gt;
# Verificar reglas cargadas y contadores&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Verificación remota mínima tras el cambio (desde RED_GESTION)&lt;br /&gt;
ssh &amp;lt;usuario&amp;gt;@&amp;lt;IP-del-servidor&amp;gt;          # el 22 debe seguir accesible&lt;br /&gt;
curl -Is http://&amp;lt;IP-del-servidor&amp;gt;/ | head -1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #fef6e7; border: 1px solid #fbd68a; padding: 1em; border-radius: 4px;width: fit-content; margin-left: 0px&amp;quot;&amp;gt;&lt;br /&gt;
	'''⚠️ ATENCION !!'''&lt;br /&gt;
	'''Riesgo operativo''': editar &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; con valores erróneos y ejecutar el script '''puede dejar la máquina inaccesible por SSH''' (la política final es &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&amp;lt;br&amp;gt; Realizar siempre el cambio con una consola de &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt; abierta como vía de recuperación.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19190</id>
		<title>Instalacion cartelia 10</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19190"/>
		<updated>2026-07-13T10:05:28Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* Firewall (/etc/firewall/) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[:Media:cartelia-despliegue-vm-documentacion-tecnica.pdf|Instalación de Cartelia 1.0]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
= Introducción =&lt;br /&gt;
&lt;br /&gt;
'''Cartelia''' es el producto de cartelería digital (digital signage) de la compañía.&lt;br /&gt;
&lt;br /&gt;
El presente documento describe el procedimiento de despliegue de una nueva instancia de Cartelia partiendo de una '''máquina virtual base''' con las siguientes características:&lt;br /&gt;
&lt;br /&gt;
* Sistema operativo: '''Debian 13 (trixie)'''.&lt;br /&gt;
* Hipervisor: '''KVM/QEMU''' (gestionado mediante &amp;lt;code&amp;gt;libvirt&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;virt-manager&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Software preinstalado: '''Cartelia 1.0''', instalado en &amp;lt;code&amp;gt;/var/www/html/cartelia&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Punto de partida''': la máquina base se entrega totalmente operativa, con Cartelia instalado de forma nativa sobre Apache + PHP y la base de datos MariaDB local ya creada e inicializada.&lt;br /&gt;
&lt;br /&gt;
'''Restricciones conocidas''':&lt;br /&gt;
&lt;br /&gt;
* La plantilla base '''no debe arrancarse nunca en producción sin personalizar''': contiene identidad de máquina, claves SSH y secretos del CMS compartidos con cualquier otra copia de la plantilla.&lt;br /&gt;
* Los players (pantallas) se autentican contra el CMS mediante la clave del servidor (''CMS Key'') y la URL del CMS; cualquier cambio posterior de IP/FQDN o de claves obliga a volver a autorizar los displays.&lt;br /&gt;
&lt;br /&gt;
= Arquitectura =&lt;br /&gt;
&lt;br /&gt;
== Esquema general del despliegue ==&lt;br /&gt;
&lt;br /&gt;
[[File:Cartelia-arquitectura.png|thumb|center|900px|Esquema general del despliegue de Cartelia sobre KVM/QEMU]]&lt;br /&gt;
&lt;br /&gt;
El CMS está instalado de forma nativa sobre el sistema operativo: Apache 2 con PHP como servidor web del portal, MariaDB local como base de datos y el servicio XMR ejecutándose como unidad de systemd.&lt;br /&gt;
&lt;br /&gt;
== Flujo del proceso de despliegue ==&lt;br /&gt;
&lt;br /&gt;
# El técnico de sistemas clona la plantilla base en el host KVM/QEMU (disco &amp;lt;code&amp;gt;qcow2&amp;lt;/code&amp;gt; + definición de dominio libvirt).&lt;br /&gt;
# En el primer arranque del clon, se personaliza la identidad del sistema operativo: &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt;, hostname, claves SSH de host, red, zona horaria y credenciales locales.&lt;br /&gt;
# Se personaliza el producto Cartelia: URL pública del CMS, secretos y contraseñas de base de datos, clave del servidor (''CMS Key''), dirección pública de XMR y personalización de marca.&lt;br /&gt;
# Se verifican los servicios, la conectividad de los players y el acceso al portal de administración.&lt;br /&gt;
# La máquina queda registrada en inventario/monitorización y se entrega.&lt;br /&gt;
&lt;br /&gt;
== Componentes principales ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Componente !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Portal Cartelia''' || Interfaz de administración de contenidos, layouts, programaciones y pantallas. Servida por Apache 2 + PHP.&lt;br /&gt;
|-&lt;br /&gt;
| '''MariaDB (local)''' || Almacena la configuración, usuarios, programaciones y metadatos de medios del CMS. Servicio nativo del sistema.&lt;br /&gt;
|-&lt;br /&gt;
| '''XMR (Cartelia Message Relay)''' || Canal push que permite al CMS enviar órdenes inmediatas a los players (recarga de contenido, capturas, reinicio). Servicio &amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;. Los players se conectan por WebSocket a la ruta &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, que reenvía a &amp;lt;code&amp;gt;ws://127.0.0.1:8080&amp;lt;/code&amp;gt;; el puerto 9505/TCP queda además permitido en el firewall para el modo de publicación directa.&lt;br /&gt;
|-&lt;br /&gt;
| '''Biblioteca de medios''' || &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;: directorio donde el CMS guarda los ficheros multimedia subidos (configurado en ''Administración &amp;gt; Configuración &amp;gt; Ubicación de la biblioteca'' y alineado con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts).&lt;br /&gt;
|-&lt;br /&gt;
| '''libvirt / KVM-QEMU''' || Capa de virtualización que aloja la VM.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Dependencias e integraciones externas ==&lt;br /&gt;
&lt;br /&gt;
* '''DNS''': registro A/AAAA del FQDN del CMS (imprescindible si los players usan nombre en lugar de IP).&lt;br /&gt;
* '''NTP''': sincronización horaria; las programaciones de contenido dependen de la hora del sistema.&lt;br /&gt;
* '''SMTP''' (opcional): relay de correo para notificaciones del CMS, si el cliente lo requiere. Se configura en el portal (''Administración &amp;gt; Configuración'', pestaña '''Mantenimiento''').&lt;br /&gt;
* '''Certificados TLS''': siempre certificados válidos, nunca autofirmados. Si el cliente dispone de certificado propio para el FQDN, lo aporta él; en caso contrario se emite con Let's Encrypt.&lt;br /&gt;
&lt;br /&gt;
= Personalización del sistema operativo (dentro de la VM) =&lt;br /&gt;
&lt;br /&gt;
== Personalización de identidad y red ==&lt;br /&gt;
&lt;br /&gt;
Todos los comandos se ejecutan como &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; desde la consola de &amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; en el primer arranque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Paso 1: regenerar las claves SSH de host (las de la plantilla son comunes a todos los clones)&lt;br /&gt;
rm -f /etc/ssh/ssh_host_*&lt;br /&gt;
dpkg-reconfigure openssh-server&lt;br /&gt;
systemctl restart ssh&lt;br /&gt;
&lt;br /&gt;
# Paso 2: hostname y resolución local&lt;br /&gt;
hostnamectl set-hostname &amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
sed -i &amp;quot;s/127.0.1.1.*/127.0.1.1\t&amp;lt;nombre-del-entorno&amp;gt; &amp;lt;FQDN-del-CMS&amp;gt;/&amp;quot; /etc/hosts&lt;br /&gt;
&lt;br /&gt;
# Paso 3: configuración de red (ifupdown, /etc/network/interfaces)&lt;br /&gt;
&lt;br /&gt;
# Paso 4: zona horaria y hora (NTP)&lt;br /&gt;
vi /etc/systemd/timesyncd.conf.d/local.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Paso 5: actualización de paquetes del SO&lt;br /&gt;
apt update &amp;amp;&amp;amp; apt upgrade -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Arranque del producto Cartelia ==&lt;br /&gt;
&lt;br /&gt;
El CMS ya viene instalado y operativo en la máquina base; en esta fase únicamente debe verificarse el arranque de los servicios nativos tras la personalización de red:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
&lt;br /&gt;
# Si algún servicio no arranca tras el cambio de red/hostname:&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
journalctl -u apache2 -n 50 --no-pager&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Verificación de la instalación ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# El portal responde en local (la máquina base publica en HTTP; ver 4.3 para HTTPS)&lt;br /&gt;
curl -Is http://localhost/ | head -1          # esperado: HTTP/1.1 200 OK (o 302 a /login)&lt;br /&gt;
&lt;br /&gt;
# Puertos de servicio a la escucha&lt;br /&gt;
ss -tlnp | grep -E ':(80|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Resolución del FQDN desde un puesto cliente&lt;br /&gt;
getent hosts &amp;lt;FQDN-del-CMS&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Acceso final: abrir &amp;lt;code&amp;gt;http://&amp;lt;FQDN-del-CMS&amp;gt;/&amp;lt;/code&amp;gt; en el navegador y validar la pantalla de login de Cartelia (o &amp;lt;code&amp;gt;https://&amp;lt;/code&amp;gt; si se ha habilitado el vhost TLS, ver 4.3).&lt;br /&gt;
&lt;br /&gt;
= Configuración =&lt;br /&gt;
&lt;br /&gt;
== Ficheros de configuración del producto ==&lt;br /&gt;
&lt;br /&gt;
La instalación es nativa (Apache + PHP + MariaDB local); estos son los ficheros que el SAT debe revisar/personalizar en cada clon:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; del CMS''' (&amp;lt;code&amp;gt;/var/www/html/cartelia/web/settings.php&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Descripción !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbhost&amp;lt;/code&amp;gt; || Host de MariaDB (normalmente &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt;) || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$dbuser&amp;lt;/code&amp;gt; || Base de datos y usuario del CMS || No cambiar salvo política del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbpass&amp;lt;/code&amp;gt; || Contraseña del usuario del CMS en MariaDB || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SECRET_KEY&amp;lt;/code&amp;gt; || Clave secreta de la instalación (cifrado interno) || Actualmente no se regenera: se mantiene el valor de la máquina base en todos los despliegues&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''XMR''' (&amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;, unidad en &amp;lt;code&amp;gt;/etc/systemd/system/xibo-xmr.service&amp;lt;/code&amp;gt;): ejecuta &amp;lt;code&amp;gt;/var/www/html/cartelia/vendor/bin/xmr.phar&amp;lt;/code&amp;gt; con PHP como usuario &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;, con reinicio automático (&amp;lt;code&amp;gt;Restart=always&amp;lt;/code&amp;gt;). Sockets por defecto: WebSocket para players en &amp;lt;code&amp;gt;127.0.0.1:8080&amp;lt;/code&amp;gt;, expuesto a través del proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, y publicación interna del CMS en &amp;lt;code&amp;gt;tcp://127.0.0.1:50001&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Tras cualquier cambio: &amp;lt;code&amp;gt;systemctl restart xibo-xmr.service&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Apache''': la máquina base incluye dos vhosts en &amp;lt;code&amp;gt;/etc/apache2/sites-available/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; (habilitado por defecto): sirve el portal en el puerto 80. En la máquina base el &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt; es la IP de la propia máquina; en cada cliente debe actualizarse al FQDN definitivo. Incluye el proxy WebSocket de XMR (&amp;lt;code&amp;gt;ProxyPass /xmr ws://127.0.0.1:8080&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;XSendFile&amp;lt;/code&amp;gt; para la entrega de medios y una exclusión de mod_security (&amp;lt;code&amp;gt;SecRuleRemoveById 920350&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; (deshabilitado por defecto): vhost TLS preparado para clientes con FQDN y certificado. Su activación se describe en la sección 4.3.&lt;br /&gt;
&lt;br /&gt;
Validar siempre con &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; antes de &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Configuración desde el portal de administración de Cartelia ==&lt;br /&gt;
&lt;br /&gt;
Acceder con el usuario '''&amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt;''' y la contraseña estándar de la máquina base (conocida por el SAT; no se documenta aquí) y cambiar dicha contraseña de inmediato, ya que es común a todos los clones. A continuación:&lt;br /&gt;
&lt;br /&gt;
* ''Administración &amp;gt; Configuración &amp;gt; Red'': establecer la dirección del CMS (&amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt;) con el FQDN definitivo. Los players usan este valor para conectarse.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Clave secreta de CMS&amp;quot;''': es la clave que debe introducirse en cada player para autenticarlo contra el CMS. En un clon es idéntica a la de la máquina base (y, por tanto, conocida por cualquier otro despliegue), así que debe sustituirse por una clave nueva y única en cada cliente.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Ubicación de la biblioteca&amp;quot;''': verificar que mantiene el valor &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;; no cambiarlo, ya que debe coincidir con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts de Apache.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Red''' (sección XMR): establecer la dirección pública de XMR como &amp;lt;code&amp;gt;ws://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; (o &amp;lt;code&amp;gt;wss://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; si está activo el vhost HTTPS). Los players se conectan por WebSocket a través del proxy de Apache; el puerto 9505 permanece abierto en el firewall únicamente como vía alternativa de publicación directa.&lt;br /&gt;
&lt;br /&gt;
Los cambios de claves y direcciones obligan a volver a autorizar los displays que estuvieran dados de alta en la máquina base (en un despliegue nuevo no debería haber ninguno; si los hubiera, eliminarlos).&lt;br /&gt;
&lt;br /&gt;
== Configuración a nivel de sistema operativo ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elemento !! Fichero / mecanismo !! Acción&lt;br /&gt;
|-&lt;br /&gt;
| Firewall || &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt; → ejecuta &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;, parametrizado por &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Editar &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; en cada despliegue (ver 4.4): la IP local está fijada a la de la máquina base y debe cambiarse junto con la red del cliente&lt;br /&gt;
|-&lt;br /&gt;
| fail2ban || &amp;lt;code&amp;gt;/etc/fail2ban/jail.d/&amp;lt;/code&amp;gt; || Verificar jail de &amp;lt;code&amp;gt;sshd&amp;lt;/code&amp;gt; activo tras el cambio de IP&lt;br /&gt;
|-&lt;br /&gt;
| Certificado TLS / HTTPS || Vhost &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; incluido de serie (deshabilitado) || Certificado siempre válido, nunca autofirmado: lo aporta el cliente si dispone de él o se emite con Let's Encrypt (&amp;lt;code&amp;gt;certbot certonly&amp;lt;/code&amp;gt; para el FQDN; requiere el puerto 80 alcanzable desde internet y renovación automática vía timer de certbot). Instalar certificado y clave en &amp;lt;code&amp;gt;/etc/ssl/cartelia/&amp;lt;/code&amp;gt; (o apuntar las directivas &amp;lt;code&amp;gt;SSL*&amp;lt;/code&amp;gt; a &amp;lt;code&amp;gt;/etc/letsencrypt/live/&amp;lt;FQDN&amp;gt;/&amp;lt;/code&amp;gt;), ajustar &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2enmod ssl proxy_wstunnel headers&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2ensite cartelia_https&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;. Activar después la redirección HTTP→HTTPS en &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; y actualizar en el portal la CMS Address (&amp;lt;code&amp;gt;https://&amp;lt;FQDN&amp;gt;&amp;lt;/code&amp;gt;) y la dirección de XMR (&amp;lt;code&amp;gt;wss://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Rotación de logs || &amp;lt;code&amp;gt;logrotate&amp;lt;/code&amp;gt; || Verificar&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Firewall (&amp;lt;code&amp;gt;/etc/firewall/&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
El firewall se implementa con nftables mediante dos ficheros, ejecutados en el arranque por &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero !! Función&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt; || Reglas nftables: acepta 80, 443 y 9505 (XMR) hacia la IP local/flotante, 22 solo desde &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt;, checks pasivos de Zabbix (10050) desde el servidor Zabbix, ICMP y tráfico establecido; el resto de entrada se descarta (&amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Variables de entorno que parametrizan las reglas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Variables de &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; a ajustar en cada despliegue:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Valor en la máquina base !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ETH&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;ens3&amp;lt;/code&amp;gt; || Cambiar solo si la interfaz del clon tiene otro nombre (&amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; || IP de la máquina base || Cambiar siempre a la IP del cliente (debe coincidir con la configurada en la sección 3.1, paso 3)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_FLO&amp;lt;/code&amp;gt; || Igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; (sin IP flotante) || Mantener igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; salvo despliegue con alta disponibilidad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_DATOS&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar al direccionamiento del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar a la red desde la que se accede por SSH; es la única red con acceso al puerto 22&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Aplicación y verificación de cambios:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Aplicar (corta y recrea todas las reglas; las conexiones establecidas se mantienen)&lt;br /&gt;
/etc/init.d/firewall start&lt;br /&gt;
&lt;br /&gt;
# Verificar reglas cargadas y contadores&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Verificación remota mínima tras el cambio (desde RED_GESTION)&lt;br /&gt;
ssh &amp;lt;usuario&amp;gt;@&amp;lt;IP-del-servidor&amp;gt;          # el 22 debe seguir accesible&lt;br /&gt;
curl -Is http://&amp;lt;IP-del-servidor&amp;gt;/ | head -1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #fef6e7; border: 1px solid #fbd68a; padding: 1em; border-radius: 4px;width: fit-content; margin-left: 0px&amp;quot;&amp;gt;&lt;br /&gt;
	'''⚠️ ATENCION !!'''&lt;br /&gt;
	'''Riesgo operativo''': editar &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; con valores erróneos y ejecutar el script '''puede dejar la máquina inaccesible por SSH''' (la política final es &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;). Realizar siempre el cambio con una consola de &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt; abierta como vía de recuperación.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19189</id>
		<title>Instalacion cartelia 10</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19189"/>
		<updated>2026-07-13T10:04:25Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* Diagnósticos */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[:Media:cartelia-despliegue-vm-documentacion-tecnica.pdf|Instalación de Cartelia 1.0]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
= Introducción =&lt;br /&gt;
&lt;br /&gt;
'''Cartelia''' es el producto de cartelería digital (digital signage) de la compañía.&lt;br /&gt;
&lt;br /&gt;
El presente documento describe el procedimiento de despliegue de una nueva instancia de Cartelia partiendo de una '''máquina virtual base''' con las siguientes características:&lt;br /&gt;
&lt;br /&gt;
* Sistema operativo: '''Debian 13 (trixie)'''.&lt;br /&gt;
* Hipervisor: '''KVM/QEMU''' (gestionado mediante &amp;lt;code&amp;gt;libvirt&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;virt-manager&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Software preinstalado: '''Cartelia 1.0''', instalado en &amp;lt;code&amp;gt;/var/www/html/cartelia&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Punto de partida''': la máquina base se entrega totalmente operativa, con Cartelia instalado de forma nativa sobre Apache + PHP y la base de datos MariaDB local ya creada e inicializada.&lt;br /&gt;
&lt;br /&gt;
'''Restricciones conocidas''':&lt;br /&gt;
&lt;br /&gt;
* La plantilla base '''no debe arrancarse nunca en producción sin personalizar''': contiene identidad de máquina, claves SSH y secretos del CMS compartidos con cualquier otra copia de la plantilla.&lt;br /&gt;
* Los players (pantallas) se autentican contra el CMS mediante la clave del servidor (''CMS Key'') y la URL del CMS; cualquier cambio posterior de IP/FQDN o de claves obliga a volver a autorizar los displays.&lt;br /&gt;
&lt;br /&gt;
= Arquitectura =&lt;br /&gt;
&lt;br /&gt;
== Esquema general del despliegue ==&lt;br /&gt;
&lt;br /&gt;
[[File:Cartelia-arquitectura.png|thumb|center|900px|Esquema general del despliegue de Cartelia sobre KVM/QEMU]]&lt;br /&gt;
&lt;br /&gt;
El CMS está instalado de forma nativa sobre el sistema operativo: Apache 2 con PHP como servidor web del portal, MariaDB local como base de datos y el servicio XMR ejecutándose como unidad de systemd.&lt;br /&gt;
&lt;br /&gt;
== Flujo del proceso de despliegue ==&lt;br /&gt;
&lt;br /&gt;
# El técnico de sistemas clona la plantilla base en el host KVM/QEMU (disco &amp;lt;code&amp;gt;qcow2&amp;lt;/code&amp;gt; + definición de dominio libvirt).&lt;br /&gt;
# En el primer arranque del clon, se personaliza la identidad del sistema operativo: &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt;, hostname, claves SSH de host, red, zona horaria y credenciales locales.&lt;br /&gt;
# Se personaliza el producto Cartelia: URL pública del CMS, secretos y contraseñas de base de datos, clave del servidor (''CMS Key''), dirección pública de XMR y personalización de marca.&lt;br /&gt;
# Se verifican los servicios, la conectividad de los players y el acceso al portal de administración.&lt;br /&gt;
# La máquina queda registrada en inventario/monitorización y se entrega.&lt;br /&gt;
&lt;br /&gt;
== Componentes principales ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Componente !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Portal Cartelia''' || Interfaz de administración de contenidos, layouts, programaciones y pantallas. Servida por Apache 2 + PHP.&lt;br /&gt;
|-&lt;br /&gt;
| '''MariaDB (local)''' || Almacena la configuración, usuarios, programaciones y metadatos de medios del CMS. Servicio nativo del sistema.&lt;br /&gt;
|-&lt;br /&gt;
| '''XMR (Cartelia Message Relay)''' || Canal push que permite al CMS enviar órdenes inmediatas a los players (recarga de contenido, capturas, reinicio). Servicio &amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;. Los players se conectan por WebSocket a la ruta &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, que reenvía a &amp;lt;code&amp;gt;ws://127.0.0.1:8080&amp;lt;/code&amp;gt;; el puerto 9505/TCP queda además permitido en el firewall para el modo de publicación directa.&lt;br /&gt;
|-&lt;br /&gt;
| '''Biblioteca de medios''' || &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;: directorio donde el CMS guarda los ficheros multimedia subidos (configurado en ''Administración &amp;gt; Configuración &amp;gt; Ubicación de la biblioteca'' y alineado con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts).&lt;br /&gt;
|-&lt;br /&gt;
| '''libvirt / KVM-QEMU''' || Capa de virtualización que aloja la VM.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Dependencias e integraciones externas ==&lt;br /&gt;
&lt;br /&gt;
* '''DNS''': registro A/AAAA del FQDN del CMS (imprescindible si los players usan nombre en lugar de IP).&lt;br /&gt;
* '''NTP''': sincronización horaria; las programaciones de contenido dependen de la hora del sistema.&lt;br /&gt;
* '''SMTP''' (opcional): relay de correo para notificaciones del CMS, si el cliente lo requiere. Se configura en el portal (''Administración &amp;gt; Configuración'', pestaña '''Mantenimiento''').&lt;br /&gt;
* '''Certificados TLS''': siempre certificados válidos, nunca autofirmados. Si el cliente dispone de certificado propio para el FQDN, lo aporta él; en caso contrario se emite con Let's Encrypt.&lt;br /&gt;
&lt;br /&gt;
= Personalización del sistema operativo (dentro de la VM) =&lt;br /&gt;
&lt;br /&gt;
== Personalización de identidad y red ==&lt;br /&gt;
&lt;br /&gt;
Todos los comandos se ejecutan como &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; desde la consola de &amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; en el primer arranque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Paso 1: regenerar las claves SSH de host (las de la plantilla son comunes a todos los clones)&lt;br /&gt;
rm -f /etc/ssh/ssh_host_*&lt;br /&gt;
dpkg-reconfigure openssh-server&lt;br /&gt;
systemctl restart ssh&lt;br /&gt;
&lt;br /&gt;
# Paso 2: hostname y resolución local&lt;br /&gt;
hostnamectl set-hostname &amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
sed -i &amp;quot;s/127.0.1.1.*/127.0.1.1\t&amp;lt;nombre-del-entorno&amp;gt; &amp;lt;FQDN-del-CMS&amp;gt;/&amp;quot; /etc/hosts&lt;br /&gt;
&lt;br /&gt;
# Paso 3: configuración de red (ifupdown, /etc/network/interfaces)&lt;br /&gt;
&lt;br /&gt;
# Paso 4: zona horaria y hora (NTP)&lt;br /&gt;
vi /etc/systemd/timesyncd.conf.d/local.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Paso 5: actualización de paquetes del SO&lt;br /&gt;
apt update &amp;amp;&amp;amp; apt upgrade -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Arranque del producto Cartelia ==&lt;br /&gt;
&lt;br /&gt;
El CMS ya viene instalado y operativo en la máquina base; en esta fase únicamente debe verificarse el arranque de los servicios nativos tras la personalización de red:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
&lt;br /&gt;
# Si algún servicio no arranca tras el cambio de red/hostname:&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
journalctl -u apache2 -n 50 --no-pager&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Verificación de la instalación ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# El portal responde en local (la máquina base publica en HTTP; ver 4.3 para HTTPS)&lt;br /&gt;
curl -Is http://localhost/ | head -1          # esperado: HTTP/1.1 200 OK (o 302 a /login)&lt;br /&gt;
&lt;br /&gt;
# Puertos de servicio a la escucha&lt;br /&gt;
ss -tlnp | grep -E ':(80|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Resolución del FQDN desde un puesto cliente&lt;br /&gt;
getent hosts &amp;lt;FQDN-del-CMS&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Acceso final: abrir &amp;lt;code&amp;gt;http://&amp;lt;FQDN-del-CMS&amp;gt;/&amp;lt;/code&amp;gt; en el navegador y validar la pantalla de login de Cartelia (o &amp;lt;code&amp;gt;https://&amp;lt;/code&amp;gt; si se ha habilitado el vhost TLS, ver 4.3).&lt;br /&gt;
&lt;br /&gt;
= Configuración =&lt;br /&gt;
&lt;br /&gt;
== Ficheros de configuración del producto ==&lt;br /&gt;
&lt;br /&gt;
La instalación es nativa (Apache + PHP + MariaDB local); estos son los ficheros que el SAT debe revisar/personalizar en cada clon:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; del CMS''' (&amp;lt;code&amp;gt;/var/www/html/cartelia/web/settings.php&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Descripción !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbhost&amp;lt;/code&amp;gt; || Host de MariaDB (normalmente &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt;) || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$dbuser&amp;lt;/code&amp;gt; || Base de datos y usuario del CMS || No cambiar salvo política del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbpass&amp;lt;/code&amp;gt; || Contraseña del usuario del CMS en MariaDB || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SECRET_KEY&amp;lt;/code&amp;gt; || Clave secreta de la instalación (cifrado interno) || Actualmente no se regenera: se mantiene el valor de la máquina base en todos los despliegues&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''XMR''' (&amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;, unidad en &amp;lt;code&amp;gt;/etc/systemd/system/xibo-xmr.service&amp;lt;/code&amp;gt;): ejecuta &amp;lt;code&amp;gt;/var/www/html/cartelia/vendor/bin/xmr.phar&amp;lt;/code&amp;gt; con PHP como usuario &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;, con reinicio automático (&amp;lt;code&amp;gt;Restart=always&amp;lt;/code&amp;gt;). Sockets por defecto: WebSocket para players en &amp;lt;code&amp;gt;127.0.0.1:8080&amp;lt;/code&amp;gt;, expuesto a través del proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, y publicación interna del CMS en &amp;lt;code&amp;gt;tcp://127.0.0.1:50001&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Tras cualquier cambio: &amp;lt;code&amp;gt;systemctl restart xibo-xmr.service&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Apache''': la máquina base incluye dos vhosts en &amp;lt;code&amp;gt;/etc/apache2/sites-available/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; (habilitado por defecto): sirve el portal en el puerto 80. En la máquina base el &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt; es la IP de la propia máquina; en cada cliente debe actualizarse al FQDN definitivo. Incluye el proxy WebSocket de XMR (&amp;lt;code&amp;gt;ProxyPass /xmr ws://127.0.0.1:8080&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;XSendFile&amp;lt;/code&amp;gt; para la entrega de medios y una exclusión de mod_security (&amp;lt;code&amp;gt;SecRuleRemoveById 920350&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; (deshabilitado por defecto): vhost TLS preparado para clientes con FQDN y certificado. Su activación se describe en la sección 4.3.&lt;br /&gt;
&lt;br /&gt;
Validar siempre con &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; antes de &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Configuración desde el portal de administración de Cartelia ==&lt;br /&gt;
&lt;br /&gt;
Acceder con el usuario '''&amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt;''' y la contraseña estándar de la máquina base (conocida por el SAT; no se documenta aquí) y cambiar dicha contraseña de inmediato, ya que es común a todos los clones. A continuación:&lt;br /&gt;
&lt;br /&gt;
* ''Administración &amp;gt; Configuración &amp;gt; Red'': establecer la dirección del CMS (&amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt;) con el FQDN definitivo. Los players usan este valor para conectarse.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Clave secreta de CMS&amp;quot;''': es la clave que debe introducirse en cada player para autenticarlo contra el CMS. En un clon es idéntica a la de la máquina base (y, por tanto, conocida por cualquier otro despliegue), así que debe sustituirse por una clave nueva y única en cada cliente.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Ubicación de la biblioteca&amp;quot;''': verificar que mantiene el valor &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;; no cambiarlo, ya que debe coincidir con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts de Apache.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Red''' (sección XMR): establecer la dirección pública de XMR como &amp;lt;code&amp;gt;ws://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; (o &amp;lt;code&amp;gt;wss://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; si está activo el vhost HTTPS). Los players se conectan por WebSocket a través del proxy de Apache; el puerto 9505 permanece abierto en el firewall únicamente como vía alternativa de publicación directa.&lt;br /&gt;
&lt;br /&gt;
Los cambios de claves y direcciones obligan a volver a autorizar los displays que estuvieran dados de alta en la máquina base (en un despliegue nuevo no debería haber ninguno; si los hubiera, eliminarlos).&lt;br /&gt;
&lt;br /&gt;
== Configuración a nivel de sistema operativo ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elemento !! Fichero / mecanismo !! Acción&lt;br /&gt;
|-&lt;br /&gt;
| Firewall || &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt; → ejecuta &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;, parametrizado por &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Editar &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; en cada despliegue (ver 4.4): la IP local está fijada a la de la máquina base y debe cambiarse junto con la red del cliente&lt;br /&gt;
|-&lt;br /&gt;
| fail2ban || &amp;lt;code&amp;gt;/etc/fail2ban/jail.d/&amp;lt;/code&amp;gt; || Verificar jail de &amp;lt;code&amp;gt;sshd&amp;lt;/code&amp;gt; activo tras el cambio de IP&lt;br /&gt;
|-&lt;br /&gt;
| Certificado TLS / HTTPS || Vhost &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; incluido de serie (deshabilitado) || Certificado siempre válido, nunca autofirmado: lo aporta el cliente si dispone de él o se emite con Let's Encrypt (&amp;lt;code&amp;gt;certbot certonly&amp;lt;/code&amp;gt; para el FQDN; requiere el puerto 80 alcanzable desde internet y renovación automática vía timer de certbot). Instalar certificado y clave en &amp;lt;code&amp;gt;/etc/ssl/cartelia/&amp;lt;/code&amp;gt; (o apuntar las directivas &amp;lt;code&amp;gt;SSL*&amp;lt;/code&amp;gt; a &amp;lt;code&amp;gt;/etc/letsencrypt/live/&amp;lt;FQDN&amp;gt;/&amp;lt;/code&amp;gt;), ajustar &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2enmod ssl proxy_wstunnel headers&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2ensite cartelia_https&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;. Activar después la redirección HTTP→HTTPS en &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; y actualizar en el portal la CMS Address (&amp;lt;code&amp;gt;https://&amp;lt;FQDN&amp;gt;&amp;lt;/code&amp;gt;) y la dirección de XMR (&amp;lt;code&amp;gt;wss://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Rotación de logs || &amp;lt;code&amp;gt;logrotate&amp;lt;/code&amp;gt; || Verificar&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Firewall (&amp;lt;code&amp;gt;/etc/firewall/&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
El firewall se implementa con nftables mediante dos ficheros, ejecutados en el arranque por &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero !! Función&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt; || Reglas nftables: acepta 80, 443 y 9505 (XMR) hacia la IP local/flotante, 22 solo desde &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt;, checks pasivos de Zabbix (10050) desde el servidor Zabbix, ICMP y tráfico establecido; el resto de entrada se descarta (&amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Variables de entorno que parametrizan las reglas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Variables de &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; a ajustar en cada despliegue:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Valor en la máquina base !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ETH&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;ens3&amp;lt;/code&amp;gt; || Cambiar solo si la interfaz del clon tiene otro nombre (&amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; || IP de la máquina base || Cambiar siempre a la IP del cliente (debe coincidir con la configurada en la sección 3.1, paso 3)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_FLO&amp;lt;/code&amp;gt; || Igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; (sin IP flotante) || Mantener igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; salvo despliegue con alta disponibilidad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_DATOS&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar al direccionamiento del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar a la red desde la que se accede por SSH; es la única red con acceso al puerto 22&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Aplicación y verificación de cambios:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Aplicar (corta y recrea todas las reglas; las conexiones establecidas se mantienen)&lt;br /&gt;
/etc/init.d/firewall start&lt;br /&gt;
&lt;br /&gt;
# Verificar reglas cargadas y contadores&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Verificación remota mínima tras el cambio (desde RED_GESTION)&lt;br /&gt;
ssh &amp;lt;usuario&amp;gt;@&amp;lt;IP-del-servidor&amp;gt;          # el 22 debe seguir accesible&lt;br /&gt;
curl -Is http://&amp;lt;IP-del-servidor&amp;gt;/ | head -1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Aviso|'''Riesgo operativo''': editar &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; con valores erróneos y ejecutar el script '''puede dejar la máquina inaccesible por SSH''' (la política final es &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;). Realizar siempre el cambio con una consola de &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt; abierta como vía de recuperación.}}&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Operacion_cartelia&amp;diff=19188</id>
		<title>Operacion cartelia</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Operacion_cartelia&amp;diff=19188"/>
		<updated>2026-07-13T10:03:12Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= Instalación =&lt;br /&gt;
[[Instalacion_cartelia | Instalacion de cartelia]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Diagnósticos =&lt;br /&gt;
&lt;br /&gt;
== Comandos de diagnóstico ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Estado general de la VM desde el host de virtualización&lt;br /&gt;
virsh dominfo cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
virsh domifaddr cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Dentro de la VM — estado de servicios&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
journalctl -u apache2 -n 100 --no-pager&lt;br /&gt;
journalctl -u xibo-xmr.service -n 100 --no-pager&lt;br /&gt;
&lt;br /&gt;
# Conexión a la base de datos del CMS&lt;br /&gt;
mysql -u &amp;lt;usuario-cms&amp;gt; -p -e &amp;quot;SELECT COUNT(*) FROM display;&amp;quot; &amp;lt;bbdd-cms&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Firewall: reglas activas y contadores por regla&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Conectividad de los puertos de producto&lt;br /&gt;
ss -tlnp | grep -E ':(80|443|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Prueba del API de players (XMDS): debe responder el WSDL&lt;br /&gt;
curl -s &amp;quot;http://localhost/xmds.php?wsdl&amp;quot; | head -5&lt;br /&gt;
&lt;br /&gt;
# Comprobar identidad correcta del clon (no debe coincidir con la plantilla)&lt;br /&gt;
cat /etc/machine-id&lt;br /&gt;
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ficheros de log ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero / origen !! Contenido !! Rotación&lt;br /&gt;
|-&lt;br /&gt;
| Portal ''Administración &amp;gt; Avanzado &amp;gt; Log'' || Log de aplicación del CMS (registro de players, errores XMDS) || Gestionada por la tarea de mantenimiento del CMS&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/var/log/apache2/cartelia_access.log&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/apache2/cartelia_error.log&amp;lt;/code&amp;gt; (y &amp;lt;code&amp;gt;cartelia_ssl_*.log&amp;lt;/code&amp;gt; con el vhost HTTPS activo) || Accesos y errores del servidor web (portal y API XMDS de players) || logrotate estándar de apache2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u xibo-xmr.service&amp;lt;/code&amp;gt; || Log del servicio XMR || journald&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u ssh&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/fail2ban.log&amp;lt;/code&amp;gt; || Seguridad de acceso al SO || Estándar journald / logrotate&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Errores comunes y soluciones ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Síntoma / mensaje !! Causa probable !! Solución&lt;br /&gt;
|-&lt;br /&gt;
| El portal no carga tras el clonado || La red de la VM no se personalizó o la interfaz cambió de nombre || Revisar &amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/etc/network/interfaces.d/&amp;lt;/code&amp;gt;, y el bridge asignado en libvirt&lt;br /&gt;
|-&lt;br /&gt;
| Los players no consiguen registrarse || &amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;CMS Secret Key&amp;lt;/code&amp;gt; incorrectos, o 80/443 filtrados || Verificar sección 4.2 y &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; del firewall (4.4); probar &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; al XMDS desde la red de players&lt;br /&gt;
|-&lt;br /&gt;
| Los players se registran pero no reciben órdenes push || Dirección pública de XMR errónea, proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; no operativo o &amp;lt;code&amp;gt;xibo-xmr&amp;lt;/code&amp;gt; caído || Verificar &amp;lt;code&amp;gt;ws(s)://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt; en el portal, &amp;lt;code&amp;gt;systemctl status xibo-xmr.service&amp;lt;/code&amp;gt; y el módulo &amp;lt;code&amp;gt;proxy_wstunnel&amp;lt;/code&amp;gt; de Apache; reiniciar XMR&lt;br /&gt;
|-&lt;br /&gt;
| Aviso de certificado en el navegador || Certificado de la plantilla aún instalado || Sustituir por el certificado del FQDN del entorno&lt;br /&gt;
|-&lt;br /&gt;
| Dos clones aparecen como la misma máquina en DHCP/monitorización || &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt; no regenerado || Ejecutar &amp;lt;code&amp;gt;rm -f /etc/machine-id &amp;amp;&amp;amp; systemd-machine-id-setup&amp;lt;/code&amp;gt; y reiniciar&lt;br /&gt;
|-&lt;br /&gt;
| El CMS no conecta con la base de datos tras cambiar contraseñas || Contraseña cambiada en &amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; pero no en MariaDB (o viceversa) || Sincronizar ambas (ver sección 4.1)&lt;br /&gt;
|-&lt;br /&gt;
| Sin acceso SSH tras personalizar el firewall || &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; erróneas en &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; con política final &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt; || Entrar por &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt;, corregir &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; y re-ejecutar &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| La hora de las programaciones no coincide || Zona horaria o NTP sin configurar || &amp;lt;code&amp;gt;timedatectl set-timezone Europe/Madrid&amp;lt;/code&amp;gt; y verificar &amp;lt;code&amp;gt;timedatectl status&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Procedimientos básicos =&lt;br /&gt;
&lt;br /&gt;
== Modificar textos idioma ==&lt;br /&gt;
&lt;br /&gt;
'''Herramientas necesarias''':&lt;br /&gt;
&lt;br /&gt;
* poedit (https://poedit.com/); nos permitirá:&lt;br /&gt;
** Descompilar fichero &amp;quot;.mo&amp;quot; (el que entiende cartelia) existente a &amp;quot;.po&amp;quot; para modificar textos de idioma&lt;br /&gt;
*** Se hace con la herramienta &amp;lt;code&amp;gt;C:\Program Files\Poedit\GettextTools\bin\msgunfmt.exe&amp;lt;/code&amp;gt;&lt;br /&gt;
*** Ejemplo invocación: &amp;lt;code&amp;gt;msgunfmt.exe &amp;quot;C:\cartelia\locale\es.mo&amp;quot; -o &amp;quot;C:\cartelia\locale\es.po&amp;quot; &amp;lt;/code&amp;gt; (las carpetas cambiarán en cada caso)&lt;br /&gt;
* Ver las traducciones para un fichero &amp;quot;.po&amp;quot;&lt;br /&gt;
* Modificar y &amp;quot;compilar&amp;quot; a fichero &amp;quot;.mo&amp;quot;&lt;br /&gt;
'''La herramienta poedit es de uso sencillo y no requiere de instrucciones específicas para personal técnico de mdtel'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Instrucciones para cambiar mensajes'''&lt;br /&gt;
:ejemplo para idioma español&lt;br /&gt;
:entre paréntesis perfil que puede realizar la tarea con seguridad&lt;br /&gt;
#.- (SAT) Obtener el fichero &amp;quot;.mo&amp;quot; original de /var/www/html/cartelia/locale/es.mo; este es un fichero &amp;quot;compilado&amp;quot;&lt;br /&gt;
#.- (PU) Descompilar el fichero con la herramienta msgunfmt&lt;br /&gt;
#.- (PU) Modificar mensajes con &amp;quot;poedit&amp;quot; y compilar&lt;br /&gt;
#.- (SAT) Subir el fichero modificado a /var/www/html/cartelia/locale/es.mo&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:tecnico]]&lt;br /&gt;
[[Category:administrador]]&lt;br /&gt;
[[Category:Cartelia]]&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Operacion_cartelia&amp;diff=19187</id>
		<title>Operacion cartelia</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Operacion_cartelia&amp;diff=19187"/>
		<updated>2026-07-13T10:02:45Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* Instalación */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= Instalación =&lt;br /&gt;
[[Instalacion_cartelia | Instalacion de cartelia]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Diagnósticos =&lt;br /&gt;
&lt;br /&gt;
== Comandos de diagnóstico ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Estado general de la VM desde el host de virtualización&lt;br /&gt;
virsh dominfo cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
virsh domifaddr cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Dentro de la VM — estado de servicios&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
journalctl -u apache2 -n 100 --no-pager&lt;br /&gt;
journalctl -u xibo-xmr.service -n 100 --no-pager&lt;br /&gt;
&lt;br /&gt;
# Conexión a la base de datos del CMS&lt;br /&gt;
mysql -u &amp;lt;usuario-cms&amp;gt; -p -e &amp;quot;SELECT COUNT(*) FROM display;&amp;quot; &amp;lt;bbdd-cms&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Firewall: reglas activas y contadores por regla&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Conectividad de los puertos de producto&lt;br /&gt;
ss -tlnp | grep -E ':(80|443|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Prueba del API de players (XMDS): debe responder el WSDL&lt;br /&gt;
curl -s &amp;quot;http://localhost/xmds.php?wsdl&amp;quot; | head -5&lt;br /&gt;
&lt;br /&gt;
# Comprobar identidad correcta del clon (no debe coincidir con la plantilla)&lt;br /&gt;
cat /etc/machine-id&lt;br /&gt;
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ficheros de log ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero / origen !! Contenido !! Rotación&lt;br /&gt;
|-&lt;br /&gt;
| Portal ''Administración &amp;gt; Avanzado &amp;gt; Log'' || Log de aplicación del CMS (registro de players, errores XMDS) || Gestionada por la tarea de mantenimiento del CMS&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/var/log/apache2/cartelia_access.log&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/apache2/cartelia_error.log&amp;lt;/code&amp;gt; (y &amp;lt;code&amp;gt;cartelia_ssl_*.log&amp;lt;/code&amp;gt; con el vhost HTTPS activo) || Accesos y errores del servidor web (portal y API XMDS de players) || logrotate estándar de apache2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u xibo-xmr.service&amp;lt;/code&amp;gt; || Log del servicio XMR || journald&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u ssh&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/fail2ban.log&amp;lt;/code&amp;gt; || Seguridad de acceso al SO || Estándar journald / logrotate&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Errores comunes y soluciones ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Síntoma / mensaje !! Causa probable !! Solución&lt;br /&gt;
|-&lt;br /&gt;
| El portal no carga tras el clonado || La red de la VM no se personalizó o la interfaz cambió de nombre || Revisar &amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/etc/network/interfaces.d/&amp;lt;/code&amp;gt;, y el bridge asignado en libvirt&lt;br /&gt;
|-&lt;br /&gt;
| Los players no consiguen registrarse || &amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;CMS Secret Key&amp;lt;/code&amp;gt; incorrectos, o 80/443 filtrados || Verificar sección 4.2 y &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; del firewall (4.4); probar &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; al XMDS desde la red de players&lt;br /&gt;
|-&lt;br /&gt;
| Los players se registran pero no reciben órdenes push || Dirección pública de XMR errónea, proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; no operativo o &amp;lt;code&amp;gt;xibo-xmr&amp;lt;/code&amp;gt; caído || Verificar &amp;lt;code&amp;gt;ws(s)://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt; en el portal, &amp;lt;code&amp;gt;systemctl status xibo-xmr.service&amp;lt;/code&amp;gt; y el módulo &amp;lt;code&amp;gt;proxy_wstunnel&amp;lt;/code&amp;gt; de Apache; reiniciar XMR&lt;br /&gt;
|-&lt;br /&gt;
| Aviso de certificado en el navegador || Certificado de la plantilla aún instalado || Sustituir por el certificado del FQDN del entorno&lt;br /&gt;
|-&lt;br /&gt;
| Dos clones aparecen como la misma máquina en DHCP/monitorización || &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt; no regenerado || Ejecutar &amp;lt;code&amp;gt;rm -f /etc/machine-id &amp;amp;&amp;amp; systemd-machine-id-setup&amp;lt;/code&amp;gt; y reiniciar&lt;br /&gt;
|-&lt;br /&gt;
| El CMS no conecta con la base de datos tras cambiar contraseñas || Contraseña cambiada en &amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; pero no en MariaDB (o viceversa) || Sincronizar ambas (ver sección 4.1)&lt;br /&gt;
|-&lt;br /&gt;
| Sin acceso SSH tras personalizar el firewall || &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; erróneas en &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; con política final &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt; || Entrar por &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt;, corregir &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; y re-ejecutar &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| La hora de las programaciones no coincide || Zona horaria o NTP sin configurar || &amp;lt;code&amp;gt;timedatectl set-timezone Europe/Madrid&amp;lt;/code&amp;gt; y verificar &amp;lt;code&amp;gt;timedatectl status&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Procedimientos básicos ==&lt;br /&gt;
&lt;br /&gt;
=== Modificar textos idioma ===&lt;br /&gt;
&lt;br /&gt;
'''Herramientas necesarias''':&lt;br /&gt;
&lt;br /&gt;
* poedit (https://poedit.com/); nos permitirá:&lt;br /&gt;
** Descompilar fichero &amp;quot;.mo&amp;quot; (el que entiende cartelia) existente a &amp;quot;.po&amp;quot; para modificar textos de idioma&lt;br /&gt;
*** Se hace con la herramienta &amp;lt;code&amp;gt;C:\Program Files\Poedit\GettextTools\bin\msgunfmt.exe&amp;lt;/code&amp;gt;&lt;br /&gt;
*** Ejemplo invocación: &amp;lt;code&amp;gt;msgunfmt.exe &amp;quot;C:\cartelia\locale\es.mo&amp;quot; -o &amp;quot;C:\cartelia\locale\es.po&amp;quot; &amp;lt;/code&amp;gt; (las carpetas cambiarán en cada caso)&lt;br /&gt;
* Ver las traducciones para un fichero &amp;quot;.po&amp;quot;&lt;br /&gt;
* Modificar y &amp;quot;compilar&amp;quot; a fichero &amp;quot;.mo&amp;quot;&lt;br /&gt;
'''La herramienta poedit es de uso sencillo y no requiere de instrucciones específicas para personal técnico de mdtel'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Instrucciones para cambiar mensajes'''&lt;br /&gt;
:ejemplo para idioma español&lt;br /&gt;
:entre paréntesis perfil que puede realizar la tarea con seguridad&lt;br /&gt;
#.- (SAT) Obtener el fichero &amp;quot;.mo&amp;quot; original de /var/www/html/cartelia/locale/es.mo; este es un fichero &amp;quot;compilado&amp;quot;&lt;br /&gt;
#.- (PU) Descompilar el fichero con la herramienta msgunfmt&lt;br /&gt;
#.- (PU) Modificar mensajes con &amp;quot;poedit&amp;quot; y compilar&lt;br /&gt;
#.- (SAT) Subir el fichero modificado a /var/www/html/cartelia/locale/es.mo&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:tecnico]]&lt;br /&gt;
[[Category:administrador]]&lt;br /&gt;
[[Category:Cartelia]]&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19186</id>
		<title>Instalacion cartelia 10</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19186"/>
		<updated>2026-07-13T09:36:18Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[:Media:cartelia-despliegue-vm-documentacion-tecnica.pdf|Instalación de Cartelia 1.0]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
= Introducción =&lt;br /&gt;
&lt;br /&gt;
'''Cartelia''' es el producto de cartelería digital (digital signage) de la compañía.&lt;br /&gt;
&lt;br /&gt;
El presente documento describe el procedimiento de despliegue de una nueva instancia de Cartelia partiendo de una '''máquina virtual base''' con las siguientes características:&lt;br /&gt;
&lt;br /&gt;
* Sistema operativo: '''Debian 13 (trixie)'''.&lt;br /&gt;
* Hipervisor: '''KVM/QEMU''' (gestionado mediante &amp;lt;code&amp;gt;libvirt&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;virt-manager&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Software preinstalado: '''Cartelia 1.0''', instalado en &amp;lt;code&amp;gt;/var/www/html/cartelia&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Punto de partida''': la máquina base se entrega totalmente operativa, con Cartelia instalado de forma nativa sobre Apache + PHP y la base de datos MariaDB local ya creada e inicializada.&lt;br /&gt;
&lt;br /&gt;
'''Restricciones conocidas''':&lt;br /&gt;
&lt;br /&gt;
* La plantilla base '''no debe arrancarse nunca en producción sin personalizar''': contiene identidad de máquina, claves SSH y secretos del CMS compartidos con cualquier otra copia de la plantilla.&lt;br /&gt;
* Los players (pantallas) se autentican contra el CMS mediante la clave del servidor (''CMS Key'') y la URL del CMS; cualquier cambio posterior de IP/FQDN o de claves obliga a volver a autorizar los displays.&lt;br /&gt;
&lt;br /&gt;
= Arquitectura =&lt;br /&gt;
&lt;br /&gt;
== Esquema general del despliegue ==&lt;br /&gt;
&lt;br /&gt;
[[File:Cartelia-arquitectura.png|thumb|center|900px|Esquema general del despliegue de Cartelia sobre KVM/QEMU]]&lt;br /&gt;
&lt;br /&gt;
El CMS está instalado de forma nativa sobre el sistema operativo: Apache 2 con PHP como servidor web del portal, MariaDB local como base de datos y el servicio XMR ejecutándose como unidad de systemd.&lt;br /&gt;
&lt;br /&gt;
== Flujo del proceso de despliegue ==&lt;br /&gt;
&lt;br /&gt;
# El técnico de sistemas clona la plantilla base en el host KVM/QEMU (disco &amp;lt;code&amp;gt;qcow2&amp;lt;/code&amp;gt; + definición de dominio libvirt).&lt;br /&gt;
# En el primer arranque del clon, se personaliza la identidad del sistema operativo: &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt;, hostname, claves SSH de host, red, zona horaria y credenciales locales.&lt;br /&gt;
# Se personaliza el producto Cartelia: URL pública del CMS, secretos y contraseñas de base de datos, clave del servidor (''CMS Key''), dirección pública de XMR y personalización de marca.&lt;br /&gt;
# Se verifican los servicios, la conectividad de los players y el acceso al portal de administración.&lt;br /&gt;
# La máquina queda registrada en inventario/monitorización y se entrega.&lt;br /&gt;
&lt;br /&gt;
== Componentes principales ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Componente !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Portal Cartelia''' || Interfaz de administración de contenidos, layouts, programaciones y pantallas. Servida por Apache 2 + PHP.&lt;br /&gt;
|-&lt;br /&gt;
| '''MariaDB (local)''' || Almacena la configuración, usuarios, programaciones y metadatos de medios del CMS. Servicio nativo del sistema.&lt;br /&gt;
|-&lt;br /&gt;
| '''XMR (Cartelia Message Relay)''' || Canal push que permite al CMS enviar órdenes inmediatas a los players (recarga de contenido, capturas, reinicio). Servicio &amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;. Los players se conectan por WebSocket a la ruta &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, que reenvía a &amp;lt;code&amp;gt;ws://127.0.0.1:8080&amp;lt;/code&amp;gt;; el puerto 9505/TCP queda además permitido en el firewall para el modo de publicación directa.&lt;br /&gt;
|-&lt;br /&gt;
| '''Biblioteca de medios''' || &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;: directorio donde el CMS guarda los ficheros multimedia subidos (configurado en ''Administración &amp;gt; Configuración &amp;gt; Ubicación de la biblioteca'' y alineado con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts).&lt;br /&gt;
|-&lt;br /&gt;
| '''libvirt / KVM-QEMU''' || Capa de virtualización que aloja la VM.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Dependencias e integraciones externas ==&lt;br /&gt;
&lt;br /&gt;
* '''DNS''': registro A/AAAA del FQDN del CMS (imprescindible si los players usan nombre en lugar de IP).&lt;br /&gt;
* '''NTP''': sincronización horaria; las programaciones de contenido dependen de la hora del sistema.&lt;br /&gt;
* '''SMTP''' (opcional): relay de correo para notificaciones del CMS, si el cliente lo requiere. Se configura en el portal (''Administración &amp;gt; Configuración'', pestaña '''Mantenimiento''').&lt;br /&gt;
* '''Certificados TLS''': siempre certificados válidos, nunca autofirmados. Si el cliente dispone de certificado propio para el FQDN, lo aporta él; en caso contrario se emite con Let's Encrypt.&lt;br /&gt;
&lt;br /&gt;
= Personalización del sistema operativo (dentro de la VM) =&lt;br /&gt;
&lt;br /&gt;
== Personalización de identidad y red ==&lt;br /&gt;
&lt;br /&gt;
Todos los comandos se ejecutan como &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; desde la consola de &amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; en el primer arranque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Paso 1: regenerar las claves SSH de host (las de la plantilla son comunes a todos los clones)&lt;br /&gt;
rm -f /etc/ssh/ssh_host_*&lt;br /&gt;
dpkg-reconfigure openssh-server&lt;br /&gt;
systemctl restart ssh&lt;br /&gt;
&lt;br /&gt;
# Paso 2: hostname y resolución local&lt;br /&gt;
hostnamectl set-hostname &amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
sed -i &amp;quot;s/127.0.1.1.*/127.0.1.1\t&amp;lt;nombre-del-entorno&amp;gt; &amp;lt;FQDN-del-CMS&amp;gt;/&amp;quot; /etc/hosts&lt;br /&gt;
&lt;br /&gt;
# Paso 3: configuración de red (ifupdown, /etc/network/interfaces)&lt;br /&gt;
&lt;br /&gt;
# Paso 4: zona horaria y hora (NTP)&lt;br /&gt;
vi /etc/systemd/timesyncd.conf.d/local.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Paso 5: actualización de paquetes del SO&lt;br /&gt;
apt update &amp;amp;&amp;amp; apt upgrade -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Arranque del producto Cartelia ==&lt;br /&gt;
&lt;br /&gt;
El CMS ya viene instalado y operativo en la máquina base; en esta fase únicamente debe verificarse el arranque de los servicios nativos tras la personalización de red:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
&lt;br /&gt;
# Si algún servicio no arranca tras el cambio de red/hostname:&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
journalctl -u apache2 -n 50 --no-pager&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Verificación de la instalación ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# El portal responde en local (la máquina base publica en HTTP; ver 4.3 para HTTPS)&lt;br /&gt;
curl -Is http://localhost/ | head -1          # esperado: HTTP/1.1 200 OK (o 302 a /login)&lt;br /&gt;
&lt;br /&gt;
# Puertos de servicio a la escucha&lt;br /&gt;
ss -tlnp | grep -E ':(80|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Resolución del FQDN desde un puesto cliente&lt;br /&gt;
getent hosts &amp;lt;FQDN-del-CMS&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Acceso final: abrir &amp;lt;code&amp;gt;http://&amp;lt;FQDN-del-CMS&amp;gt;/&amp;lt;/code&amp;gt; en el navegador y validar la pantalla de login de Cartelia (o &amp;lt;code&amp;gt;https://&amp;lt;/code&amp;gt; si se ha habilitado el vhost TLS, ver 4.3).&lt;br /&gt;
&lt;br /&gt;
= Configuración =&lt;br /&gt;
&lt;br /&gt;
== Ficheros de configuración del producto ==&lt;br /&gt;
&lt;br /&gt;
La instalación es nativa (Apache + PHP + MariaDB local); estos son los ficheros que el SAT debe revisar/personalizar en cada clon:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; del CMS''' (&amp;lt;code&amp;gt;/var/www/html/cartelia/web/settings.php&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Descripción !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbhost&amp;lt;/code&amp;gt; || Host de MariaDB (normalmente &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt;) || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$dbuser&amp;lt;/code&amp;gt; || Base de datos y usuario del CMS || No cambiar salvo política del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbpass&amp;lt;/code&amp;gt; || Contraseña del usuario del CMS en MariaDB || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SECRET_KEY&amp;lt;/code&amp;gt; || Clave secreta de la instalación (cifrado interno) || Actualmente no se regenera: se mantiene el valor de la máquina base en todos los despliegues&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''XMR''' (&amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;, unidad en &amp;lt;code&amp;gt;/etc/systemd/system/xibo-xmr.service&amp;lt;/code&amp;gt;): ejecuta &amp;lt;code&amp;gt;/var/www/html/cartelia/vendor/bin/xmr.phar&amp;lt;/code&amp;gt; con PHP como usuario &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;, con reinicio automático (&amp;lt;code&amp;gt;Restart=always&amp;lt;/code&amp;gt;). Sockets por defecto: WebSocket para players en &amp;lt;code&amp;gt;127.0.0.1:8080&amp;lt;/code&amp;gt;, expuesto a través del proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, y publicación interna del CMS en &amp;lt;code&amp;gt;tcp://127.0.0.1:50001&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Tras cualquier cambio: &amp;lt;code&amp;gt;systemctl restart xibo-xmr.service&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Apache''': la máquina base incluye dos vhosts en &amp;lt;code&amp;gt;/etc/apache2/sites-available/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; (habilitado por defecto): sirve el portal en el puerto 80. En la máquina base el &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt; es la IP de la propia máquina; en cada cliente debe actualizarse al FQDN definitivo. Incluye el proxy WebSocket de XMR (&amp;lt;code&amp;gt;ProxyPass /xmr ws://127.0.0.1:8080&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;XSendFile&amp;lt;/code&amp;gt; para la entrega de medios y una exclusión de mod_security (&amp;lt;code&amp;gt;SecRuleRemoveById 920350&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; (deshabilitado por defecto): vhost TLS preparado para clientes con FQDN y certificado. Su activación se describe en la sección 4.3.&lt;br /&gt;
&lt;br /&gt;
Validar siempre con &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; antes de &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Configuración desde el portal de administración de Cartelia ==&lt;br /&gt;
&lt;br /&gt;
Acceder con el usuario '''&amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt;''' y la contraseña estándar de la máquina base (conocida por el SAT; no se documenta aquí) y cambiar dicha contraseña de inmediato, ya que es común a todos los clones. A continuación:&lt;br /&gt;
&lt;br /&gt;
* ''Administración &amp;gt; Configuración &amp;gt; Red'': establecer la dirección del CMS (&amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt;) con el FQDN definitivo. Los players usan este valor para conectarse.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Clave secreta de CMS&amp;quot;''': es la clave que debe introducirse en cada player para autenticarlo contra el CMS. En un clon es idéntica a la de la máquina base (y, por tanto, conocida por cualquier otro despliegue), así que debe sustituirse por una clave nueva y única en cada cliente.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Ubicación de la biblioteca&amp;quot;''': verificar que mantiene el valor &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;; no cambiarlo, ya que debe coincidir con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts de Apache.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Red''' (sección XMR): establecer la dirección pública de XMR como &amp;lt;code&amp;gt;ws://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; (o &amp;lt;code&amp;gt;wss://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; si está activo el vhost HTTPS). Los players se conectan por WebSocket a través del proxy de Apache; el puerto 9505 permanece abierto en el firewall únicamente como vía alternativa de publicación directa.&lt;br /&gt;
&lt;br /&gt;
Los cambios de claves y direcciones obligan a volver a autorizar los displays que estuvieran dados de alta en la máquina base (en un despliegue nuevo no debería haber ninguno; si los hubiera, eliminarlos).&lt;br /&gt;
&lt;br /&gt;
== Configuración a nivel de sistema operativo ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elemento !! Fichero / mecanismo !! Acción&lt;br /&gt;
|-&lt;br /&gt;
| Firewall || &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt; → ejecuta &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;, parametrizado por &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Editar &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; en cada despliegue (ver 4.4): la IP local está fijada a la de la máquina base y debe cambiarse junto con la red del cliente&lt;br /&gt;
|-&lt;br /&gt;
| fail2ban || &amp;lt;code&amp;gt;/etc/fail2ban/jail.d/&amp;lt;/code&amp;gt; || Verificar jail de &amp;lt;code&amp;gt;sshd&amp;lt;/code&amp;gt; activo tras el cambio de IP&lt;br /&gt;
|-&lt;br /&gt;
| Certificado TLS / HTTPS || Vhost &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; incluido de serie (deshabilitado) || Certificado siempre válido, nunca autofirmado: lo aporta el cliente si dispone de él o se emite con Let's Encrypt (&amp;lt;code&amp;gt;certbot certonly&amp;lt;/code&amp;gt; para el FQDN; requiere el puerto 80 alcanzable desde internet y renovación automática vía timer de certbot). Instalar certificado y clave en &amp;lt;code&amp;gt;/etc/ssl/cartelia/&amp;lt;/code&amp;gt; (o apuntar las directivas &amp;lt;code&amp;gt;SSL*&amp;lt;/code&amp;gt; a &amp;lt;code&amp;gt;/etc/letsencrypt/live/&amp;lt;FQDN&amp;gt;/&amp;lt;/code&amp;gt;), ajustar &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2enmod ssl proxy_wstunnel headers&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2ensite cartelia_https&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;. Activar después la redirección HTTP→HTTPS en &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; y actualizar en el portal la CMS Address (&amp;lt;code&amp;gt;https://&amp;lt;FQDN&amp;gt;&amp;lt;/code&amp;gt;) y la dirección de XMR (&amp;lt;code&amp;gt;wss://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Rotación de logs || &amp;lt;code&amp;gt;logrotate&amp;lt;/code&amp;gt; || Verificar&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Firewall (&amp;lt;code&amp;gt;/etc/firewall/&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
El firewall se implementa con nftables mediante dos ficheros, ejecutados en el arranque por &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero !! Función&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt; || Reglas nftables: acepta 80, 443 y 9505 (XMR) hacia la IP local/flotante, 22 solo desde &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt;, checks pasivos de Zabbix (10050) desde el servidor Zabbix, ICMP y tráfico establecido; el resto de entrada se descarta (&amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Variables de entorno que parametrizan las reglas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Variables de &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; a ajustar en cada despliegue:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Valor en la máquina base !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ETH&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;ens3&amp;lt;/code&amp;gt; || Cambiar solo si la interfaz del clon tiene otro nombre (&amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; || IP de la máquina base || Cambiar siempre a la IP del cliente (debe coincidir con la configurada en la sección 3.1, paso 3)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_FLO&amp;lt;/code&amp;gt; || Igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; (sin IP flotante) || Mantener igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; salvo despliegue con alta disponibilidad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_DATOS&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar al direccionamiento del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar a la red desde la que se accede por SSH; es la única red con acceso al puerto 22&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Aplicación y verificación de cambios:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Aplicar (corta y recrea todas las reglas; las conexiones establecidas se mantienen)&lt;br /&gt;
/etc/init.d/firewall start&lt;br /&gt;
&lt;br /&gt;
# Verificar reglas cargadas y contadores&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Verificación remota mínima tras el cambio (desde RED_GESTION)&lt;br /&gt;
ssh &amp;lt;usuario&amp;gt;@&amp;lt;IP-del-servidor&amp;gt;          # el 22 debe seguir accesible&lt;br /&gt;
curl -Is http://&amp;lt;IP-del-servidor&amp;gt;/ | head -1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Aviso|'''Riesgo operativo''': editar &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; con valores erróneos y ejecutar el script '''puede dejar la máquina inaccesible por SSH''' (la política final es &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;). Realizar siempre el cambio con una consola de &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt; abierta como vía de recuperación.}}&lt;br /&gt;
&lt;br /&gt;
= Diagnósticos =&lt;br /&gt;
&lt;br /&gt;
== Comandos de diagnóstico ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Estado general de la VM desde el host de virtualización&lt;br /&gt;
virsh dominfo cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
virsh domifaddr cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Dentro de la VM — estado de servicios&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
journalctl -u apache2 -n 100 --no-pager&lt;br /&gt;
journalctl -u xibo-xmr.service -n 100 --no-pager&lt;br /&gt;
&lt;br /&gt;
# Conexión a la base de datos del CMS&lt;br /&gt;
mysql -u &amp;lt;usuario-cms&amp;gt; -p -e &amp;quot;SELECT COUNT(*) FROM display;&amp;quot; &amp;lt;bbdd-cms&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Firewall: reglas activas y contadores por regla&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Conectividad de los puertos de producto&lt;br /&gt;
ss -tlnp | grep -E ':(80|443|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Prueba del API de players (XMDS): debe responder el WSDL&lt;br /&gt;
curl -s &amp;quot;http://localhost/xmds.php?wsdl&amp;quot; | head -5&lt;br /&gt;
&lt;br /&gt;
# Comprobar identidad correcta del clon (no debe coincidir con la plantilla)&lt;br /&gt;
cat /etc/machine-id&lt;br /&gt;
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ficheros de log ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero / origen !! Contenido !! Rotación&lt;br /&gt;
|-&lt;br /&gt;
| Portal ''Administración &amp;gt; Avanzado &amp;gt; Log'' || Log de aplicación del CMS (registro de players, errores XMDS) || Gestionada por la tarea de mantenimiento del CMS&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/var/log/apache2/cartelia_access.log&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/apache2/cartelia_error.log&amp;lt;/code&amp;gt; (y &amp;lt;code&amp;gt;cartelia_ssl_*.log&amp;lt;/code&amp;gt; con el vhost HTTPS activo) || Accesos y errores del servidor web (portal y API XMDS de players) || logrotate estándar de apache2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u xibo-xmr.service&amp;lt;/code&amp;gt; || Log del servicio XMR || journald&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u ssh&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/fail2ban.log&amp;lt;/code&amp;gt; || Seguridad de acceso al SO || Estándar journald / logrotate&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Errores comunes y soluciones ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Síntoma / mensaje !! Causa probable !! Solución&lt;br /&gt;
|-&lt;br /&gt;
| El portal no carga tras el clonado || La red de la VM no se personalizó o la interfaz cambió de nombre || Revisar &amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/etc/network/interfaces.d/&amp;lt;/code&amp;gt;, y el bridge asignado en libvirt&lt;br /&gt;
|-&lt;br /&gt;
| Los players no consiguen registrarse || &amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;CMS Secret Key&amp;lt;/code&amp;gt; incorrectos, o 80/443 filtrados || Verificar sección 4.2 y &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; del firewall (4.4); probar &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; al XMDS desde la red de players&lt;br /&gt;
|-&lt;br /&gt;
| Los players se registran pero no reciben órdenes push || Dirección pública de XMR errónea, proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; no operativo o &amp;lt;code&amp;gt;xibo-xmr&amp;lt;/code&amp;gt; caído || Verificar &amp;lt;code&amp;gt;ws(s)://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt; en el portal, &amp;lt;code&amp;gt;systemctl status xibo-xmr.service&amp;lt;/code&amp;gt; y el módulo &amp;lt;code&amp;gt;proxy_wstunnel&amp;lt;/code&amp;gt; de Apache; reiniciar XMR&lt;br /&gt;
|-&lt;br /&gt;
| Aviso de certificado en el navegador || Certificado de la plantilla aún instalado || Sustituir por el certificado del FQDN del entorno&lt;br /&gt;
|-&lt;br /&gt;
| Dos clones aparecen como la misma máquina en DHCP/monitorización || &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt; no regenerado || Ejecutar &amp;lt;code&amp;gt;rm -f /etc/machine-id &amp;amp;&amp;amp; systemd-machine-id-setup&amp;lt;/code&amp;gt; y reiniciar&lt;br /&gt;
|-&lt;br /&gt;
| El CMS no conecta con la base de datos tras cambiar contraseñas || Contraseña cambiada en &amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; pero no en MariaDB (o viceversa) || Sincronizar ambas (ver sección 4.1)&lt;br /&gt;
|-&lt;br /&gt;
| Sin acceso SSH tras personalizar el firewall || &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; erróneas en &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; con política final &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt; || Entrar por &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt;, corregir &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; y re-ejecutar &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| La hora de las programaciones no coincide || Zona horaria o NTP sin configurar || &amp;lt;code&amp;gt;timedatectl set-timezone Europe/Madrid&amp;lt;/code&amp;gt; y verificar &amp;lt;code&amp;gt;timedatectl status&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19185</id>
		<title>Instalacion cartelia 10</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19185"/>
		<updated>2026-07-13T09:35:42Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* Comandos de diagnóstico */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[:Media:cartelia-despliegue-vm-documentacion-tecnica.pdf|Instalación de Cartelia 1.0]]&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
= Introducción =&lt;br /&gt;
&lt;br /&gt;
'''Cartelia''' es el producto de cartelería digital (digital signage) de la compañía.&lt;br /&gt;
&lt;br /&gt;
El presente documento describe el procedimiento de despliegue de una nueva instancia de Cartelia partiendo de una '''máquina virtual base''' con las siguientes características:&lt;br /&gt;
&lt;br /&gt;
* Sistema operativo: '''Debian 13 (trixie)'''.&lt;br /&gt;
* Hipervisor: '''KVM/QEMU''' (gestionado mediante &amp;lt;code&amp;gt;libvirt&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;virt-manager&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Software preinstalado: '''Cartelia 1.0''', instalado en &amp;lt;code&amp;gt;/var/www/html/cartelia&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Punto de partida''': la máquina base se entrega totalmente operativa, con Cartelia instalado de forma nativa sobre Apache + PHP y la base de datos MariaDB local ya creada e inicializada.&lt;br /&gt;
&lt;br /&gt;
'''Restricciones conocidas''':&lt;br /&gt;
&lt;br /&gt;
* La plantilla base '''no debe arrancarse nunca en producción sin personalizar''': contiene identidad de máquina, claves SSH y secretos del CMS compartidos con cualquier otra copia de la plantilla.&lt;br /&gt;
* Los players (pantallas) se autentican contra el CMS mediante la clave del servidor (''CMS Key'') y la URL del CMS; cualquier cambio posterior de IP/FQDN o de claves obliga a volver a autorizar los displays.&lt;br /&gt;
&lt;br /&gt;
= Arquitectura =&lt;br /&gt;
&lt;br /&gt;
== Esquema general del despliegue ==&lt;br /&gt;
&lt;br /&gt;
[[File:Cartelia-arquitectura.png|thumb|center|900px|Esquema general del despliegue de Cartelia sobre KVM/QEMU]]&lt;br /&gt;
&lt;br /&gt;
El CMS está instalado de forma nativa sobre el sistema operativo: Apache 2 con PHP como servidor web del portal, MariaDB local como base de datos y el servicio XMR ejecutándose como unidad de systemd.&lt;br /&gt;
&lt;br /&gt;
== Flujo del proceso de despliegue ==&lt;br /&gt;
&lt;br /&gt;
# El técnico de sistemas clona la plantilla base en el host KVM/QEMU (disco &amp;lt;code&amp;gt;qcow2&amp;lt;/code&amp;gt; + definición de dominio libvirt).&lt;br /&gt;
# En el primer arranque del clon, se personaliza la identidad del sistema operativo: &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt;, hostname, claves SSH de host, red, zona horaria y credenciales locales.&lt;br /&gt;
# Se personaliza el producto Cartelia: URL pública del CMS, secretos y contraseñas de base de datos, clave del servidor (''CMS Key''), dirección pública de XMR y personalización de marca.&lt;br /&gt;
# Se verifican los servicios, la conectividad de los players y el acceso al portal de administración.&lt;br /&gt;
# La máquina queda registrada en inventario/monitorización y se entrega.&lt;br /&gt;
&lt;br /&gt;
== Componentes principales ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Componente !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Portal Cartelia''' || Interfaz de administración de contenidos, layouts, programaciones y pantallas. Servida por Apache 2 + PHP.&lt;br /&gt;
|-&lt;br /&gt;
| '''MariaDB (local)''' || Almacena la configuración, usuarios, programaciones y metadatos de medios del CMS. Servicio nativo del sistema.&lt;br /&gt;
|-&lt;br /&gt;
| '''XMR (Cartelia Message Relay)''' || Canal push que permite al CMS enviar órdenes inmediatas a los players (recarga de contenido, capturas, reinicio). Servicio &amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;. Los players se conectan por WebSocket a la ruta &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, que reenvía a &amp;lt;code&amp;gt;ws://127.0.0.1:8080&amp;lt;/code&amp;gt;; el puerto 9505/TCP queda además permitido en el firewall para el modo de publicación directa.&lt;br /&gt;
|-&lt;br /&gt;
| '''Biblioteca de medios''' || &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;: directorio donde el CMS guarda los ficheros multimedia subidos (configurado en ''Administración &amp;gt; Configuración &amp;gt; Ubicación de la biblioteca'' y alineado con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts).&lt;br /&gt;
|-&lt;br /&gt;
| '''libvirt / KVM-QEMU''' || Capa de virtualización que aloja la VM.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Dependencias e integraciones externas ==&lt;br /&gt;
&lt;br /&gt;
* '''DNS''': registro A/AAAA del FQDN del CMS (imprescindible si los players usan nombre en lugar de IP).&lt;br /&gt;
* '''NTP''': sincronización horaria; las programaciones de contenido dependen de la hora del sistema.&lt;br /&gt;
* '''SMTP''' (opcional): relay de correo para notificaciones del CMS, si el cliente lo requiere. Se configura en el portal (''Administración &amp;gt; Configuración'', pestaña '''Mantenimiento''').&lt;br /&gt;
* '''Certificados TLS''': siempre certificados válidos, nunca autofirmados. Si el cliente dispone de certificado propio para el FQDN, lo aporta él; en caso contrario se emite con Let's Encrypt.&lt;br /&gt;
&lt;br /&gt;
= Personalización del sistema operativo (dentro de la VM) =&lt;br /&gt;
&lt;br /&gt;
== Personalización de identidad y red ==&lt;br /&gt;
&lt;br /&gt;
Todos los comandos se ejecutan como &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; desde la consola de &amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; en el primer arranque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Paso 1: regenerar las claves SSH de host (las de la plantilla son comunes a todos los clones)&lt;br /&gt;
rm -f /etc/ssh/ssh_host_*&lt;br /&gt;
dpkg-reconfigure openssh-server&lt;br /&gt;
systemctl restart ssh&lt;br /&gt;
&lt;br /&gt;
# Paso 2: hostname y resolución local&lt;br /&gt;
hostnamectl set-hostname &amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
sed -i &amp;quot;s/127.0.1.1.*/127.0.1.1\t&amp;lt;nombre-del-entorno&amp;gt; &amp;lt;FQDN-del-CMS&amp;gt;/&amp;quot; /etc/hosts&lt;br /&gt;
&lt;br /&gt;
# Paso 3: configuración de red (ifupdown, /etc/network/interfaces)&lt;br /&gt;
&lt;br /&gt;
# Paso 4: zona horaria y hora (NTP)&lt;br /&gt;
vi /etc/systemd/timesyncd.conf.d/local.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Paso 5: actualización de paquetes del SO&lt;br /&gt;
apt update &amp;amp;&amp;amp; apt upgrade -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Arranque del producto Cartelia ==&lt;br /&gt;
&lt;br /&gt;
El CMS ya viene instalado y operativo en la máquina base; en esta fase únicamente debe verificarse el arranque de los servicios nativos tras la personalización de red:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
&lt;br /&gt;
# Si algún servicio no arranca tras el cambio de red/hostname:&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
journalctl -u apache2 -n 50 --no-pager&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Verificación de la instalación ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# El portal responde en local (la máquina base publica en HTTP; ver 4.3 para HTTPS)&lt;br /&gt;
curl -Is http://localhost/ | head -1          # esperado: HTTP/1.1 200 OK (o 302 a /login)&lt;br /&gt;
&lt;br /&gt;
# Puertos de servicio a la escucha&lt;br /&gt;
ss -tlnp | grep -E ':(80|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Resolución del FQDN desde un puesto cliente&lt;br /&gt;
getent hosts &amp;lt;FQDN-del-CMS&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Acceso final: abrir &amp;lt;code&amp;gt;http://&amp;lt;FQDN-del-CMS&amp;gt;/&amp;lt;/code&amp;gt; en el navegador y validar la pantalla de login de Cartelia (o &amp;lt;code&amp;gt;https://&amp;lt;/code&amp;gt; si se ha habilitado el vhost TLS, ver 4.3).&lt;br /&gt;
&lt;br /&gt;
= Configuración =&lt;br /&gt;
&lt;br /&gt;
== Ficheros de configuración del producto ==&lt;br /&gt;
&lt;br /&gt;
La instalación es nativa (Apache + PHP + MariaDB local); estos son los ficheros que el SAT debe revisar/personalizar en cada clon:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; del CMS''' (&amp;lt;code&amp;gt;/var/www/html/cartelia/web/settings.php&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Descripción !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbhost&amp;lt;/code&amp;gt; || Host de MariaDB (normalmente &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt;) || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$dbuser&amp;lt;/code&amp;gt; || Base de datos y usuario del CMS || No cambiar salvo política del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbpass&amp;lt;/code&amp;gt; || Contraseña del usuario del CMS en MariaDB || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SECRET_KEY&amp;lt;/code&amp;gt; || Clave secreta de la instalación (cifrado interno) || Actualmente no se regenera: se mantiene el valor de la máquina base en todos los despliegues&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''XMR''' (&amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;, unidad en &amp;lt;code&amp;gt;/etc/systemd/system/xibo-xmr.service&amp;lt;/code&amp;gt;): ejecuta &amp;lt;code&amp;gt;/var/www/html/cartelia/vendor/bin/xmr.phar&amp;lt;/code&amp;gt; con PHP como usuario &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;, con reinicio automático (&amp;lt;code&amp;gt;Restart=always&amp;lt;/code&amp;gt;). Sockets por defecto: WebSocket para players en &amp;lt;code&amp;gt;127.0.0.1:8080&amp;lt;/code&amp;gt;, expuesto a través del proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, y publicación interna del CMS en &amp;lt;code&amp;gt;tcp://127.0.0.1:50001&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Tras cualquier cambio: &amp;lt;code&amp;gt;systemctl restart xibo-xmr.service&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Apache''': la máquina base incluye dos vhosts en &amp;lt;code&amp;gt;/etc/apache2/sites-available/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; (habilitado por defecto): sirve el portal en el puerto 80. En la máquina base el &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt; es la IP de la propia máquina; en cada cliente debe actualizarse al FQDN definitivo. Incluye el proxy WebSocket de XMR (&amp;lt;code&amp;gt;ProxyPass /xmr ws://127.0.0.1:8080&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;XSendFile&amp;lt;/code&amp;gt; para la entrega de medios y una exclusión de mod_security (&amp;lt;code&amp;gt;SecRuleRemoveById 920350&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; (deshabilitado por defecto): vhost TLS preparado para clientes con FQDN y certificado. Su activación se describe en la sección 4.3.&lt;br /&gt;
&lt;br /&gt;
Validar siempre con &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; antes de &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Configuración desde el portal de administración de Cartelia ==&lt;br /&gt;
&lt;br /&gt;
Acceder con el usuario '''&amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt;''' y la contraseña estándar de la máquina base (conocida por el SAT; no se documenta aquí) y cambiar dicha contraseña de inmediato, ya que es común a todos los clones. A continuación:&lt;br /&gt;
&lt;br /&gt;
* ''Administración &amp;gt; Configuración &amp;gt; Red'': establecer la dirección del CMS (&amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt;) con el FQDN definitivo. Los players usan este valor para conectarse.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Clave secreta de CMS&amp;quot;''': es la clave que debe introducirse en cada player para autenticarlo contra el CMS. En un clon es idéntica a la de la máquina base (y, por tanto, conocida por cualquier otro despliegue), así que debe sustituirse por una clave nueva y única en cada cliente.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Ubicación de la biblioteca&amp;quot;''': verificar que mantiene el valor &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;; no cambiarlo, ya que debe coincidir con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts de Apache.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Red''' (sección XMR): establecer la dirección pública de XMR como &amp;lt;code&amp;gt;ws://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; (o &amp;lt;code&amp;gt;wss://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; si está activo el vhost HTTPS). Los players se conectan por WebSocket a través del proxy de Apache; el puerto 9505 permanece abierto en el firewall únicamente como vía alternativa de publicación directa.&lt;br /&gt;
&lt;br /&gt;
Los cambios de claves y direcciones obligan a volver a autorizar los displays que estuvieran dados de alta en la máquina base (en un despliegue nuevo no debería haber ninguno; si los hubiera, eliminarlos).&lt;br /&gt;
&lt;br /&gt;
== Configuración a nivel de sistema operativo ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elemento !! Fichero / mecanismo !! Acción&lt;br /&gt;
|-&lt;br /&gt;
| Firewall || &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt; → ejecuta &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;, parametrizado por &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Editar &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; en cada despliegue (ver 4.4): la IP local está fijada a la de la máquina base y debe cambiarse junto con la red del cliente&lt;br /&gt;
|-&lt;br /&gt;
| fail2ban || &amp;lt;code&amp;gt;/etc/fail2ban/jail.d/&amp;lt;/code&amp;gt; || Verificar jail de &amp;lt;code&amp;gt;sshd&amp;lt;/code&amp;gt; activo tras el cambio de IP&lt;br /&gt;
|-&lt;br /&gt;
| Certificado TLS / HTTPS || Vhost &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; incluido de serie (deshabilitado) || Certificado siempre válido, nunca autofirmado: lo aporta el cliente si dispone de él o se emite con Let's Encrypt (&amp;lt;code&amp;gt;certbot certonly&amp;lt;/code&amp;gt; para el FQDN; requiere el puerto 80 alcanzable desde internet y renovación automática vía timer de certbot). Instalar certificado y clave en &amp;lt;code&amp;gt;/etc/ssl/cartelia/&amp;lt;/code&amp;gt; (o apuntar las directivas &amp;lt;code&amp;gt;SSL*&amp;lt;/code&amp;gt; a &amp;lt;code&amp;gt;/etc/letsencrypt/live/&amp;lt;FQDN&amp;gt;/&amp;lt;/code&amp;gt;), ajustar &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2enmod ssl proxy_wstunnel headers&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2ensite cartelia_https&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;. Activar después la redirección HTTP→HTTPS en &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; y actualizar en el portal la CMS Address (&amp;lt;code&amp;gt;https://&amp;lt;FQDN&amp;gt;&amp;lt;/code&amp;gt;) y la dirección de XMR (&amp;lt;code&amp;gt;wss://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Rotación de logs || &amp;lt;code&amp;gt;logrotate&amp;lt;/code&amp;gt; || Verificar&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Firewall (&amp;lt;code&amp;gt;/etc/firewall/&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
El firewall se implementa con nftables mediante dos ficheros, ejecutados en el arranque por &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero !! Función&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt; || Reglas nftables: acepta 80, 443 y 9505 (XMR) hacia la IP local/flotante, 22 solo desde &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt;, checks pasivos de Zabbix (10050) desde el servidor Zabbix, ICMP y tráfico establecido; el resto de entrada se descarta (&amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Variables de entorno que parametrizan las reglas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Variables de &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; a ajustar en cada despliegue:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Valor en la máquina base !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ETH&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;ens3&amp;lt;/code&amp;gt; || Cambiar solo si la interfaz del clon tiene otro nombre (&amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; || IP de la máquina base || Cambiar siempre a la IP del cliente (debe coincidir con la configurada en la sección 3.1, paso 3)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_FLO&amp;lt;/code&amp;gt; || Igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; (sin IP flotante) || Mantener igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; salvo despliegue con alta disponibilidad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_DATOS&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar al direccionamiento del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar a la red desde la que se accede por SSH; es la única red con acceso al puerto 22&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Aplicación y verificación de cambios:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Aplicar (corta y recrea todas las reglas; las conexiones establecidas se mantienen)&lt;br /&gt;
/etc/init.d/firewall start&lt;br /&gt;
&lt;br /&gt;
# Verificar reglas cargadas y contadores&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Verificación remota mínima tras el cambio (desde RED_GESTION)&lt;br /&gt;
ssh &amp;lt;usuario&amp;gt;@&amp;lt;IP-del-servidor&amp;gt;          # el 22 debe seguir accesible&lt;br /&gt;
curl -Is http://&amp;lt;IP-del-servidor&amp;gt;/ | head -1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Aviso|'''Riesgo operativo''': editar &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; con valores erróneos y ejecutar el script '''puede dejar la máquina inaccesible por SSH''' (la política final es &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;). Realizar siempre el cambio con una consola de &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt; abierta como vía de recuperación.}}&lt;br /&gt;
&lt;br /&gt;
= Diagnósticos =&lt;br /&gt;
&lt;br /&gt;
== Comandos de diagnóstico ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Estado general de la VM desde el host de virtualización&lt;br /&gt;
virsh dominfo cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
virsh domifaddr cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Dentro de la VM — estado de servicios&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
journalctl -u apache2 -n 100 --no-pager&lt;br /&gt;
journalctl -u xibo-xmr.service -n 100 --no-pager&lt;br /&gt;
&lt;br /&gt;
# Conexión a la base de datos del CMS&lt;br /&gt;
mysql -u &amp;lt;usuario-cms&amp;gt; -p -e &amp;quot;SELECT COUNT(*) FROM display;&amp;quot; &amp;lt;bbdd-cms&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Firewall: reglas activas y contadores por regla&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Conectividad de los puertos de producto&lt;br /&gt;
ss -tlnp | grep -E ':(80|443|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Prueba del API de players (XMDS): debe responder el WSDL&lt;br /&gt;
curl -s &amp;quot;http://localhost/xmds.php?wsdl&amp;quot; | head -5&lt;br /&gt;
&lt;br /&gt;
# Comprobar identidad correcta del clon (no debe coincidir con la plantilla)&lt;br /&gt;
cat /etc/machine-id&lt;br /&gt;
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ficheros de log ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero / origen !! Contenido !! Rotación&lt;br /&gt;
|-&lt;br /&gt;
| Portal ''Administración &amp;gt; Avanzado &amp;gt; Log'' || Log de aplicación del CMS (registro de players, errores XMDS) || Gestionada por la tarea de mantenimiento del CMS&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/var/log/apache2/cartelia_access.log&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/apache2/cartelia_error.log&amp;lt;/code&amp;gt; (y &amp;lt;code&amp;gt;cartelia_ssl_*.log&amp;lt;/code&amp;gt; con el vhost HTTPS activo) || Accesos y errores del servidor web (portal y API XMDS de players) || logrotate estándar de apache2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u xibo-xmr.service&amp;lt;/code&amp;gt; || Log del servicio XMR || journald&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u ssh&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/fail2ban.log&amp;lt;/code&amp;gt; || Seguridad de acceso al SO || Estándar journald / logrotate&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Errores comunes y soluciones ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Síntoma / mensaje !! Causa probable !! Solución&lt;br /&gt;
|-&lt;br /&gt;
| El portal no carga tras el clonado || La red de la VM no se personalizó o la interfaz cambió de nombre || Revisar &amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/etc/network/interfaces.d/&amp;lt;/code&amp;gt;, y el bridge asignado en libvirt&lt;br /&gt;
|-&lt;br /&gt;
| Los players no consiguen registrarse || &amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;CMS Secret Key&amp;lt;/code&amp;gt; incorrectos, o 80/443 filtrados || Verificar sección 4.2 y &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; del firewall (4.4); probar &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; al XMDS desde la red de players&lt;br /&gt;
|-&lt;br /&gt;
| Los players se registran pero no reciben órdenes push || Dirección pública de XMR errónea, proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; no operativo o &amp;lt;code&amp;gt;xibo-xmr&amp;lt;/code&amp;gt; caído || Verificar &amp;lt;code&amp;gt;ws(s)://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt; en el portal, &amp;lt;code&amp;gt;systemctl status xibo-xmr.service&amp;lt;/code&amp;gt; y el módulo &amp;lt;code&amp;gt;proxy_wstunnel&amp;lt;/code&amp;gt; de Apache; reiniciar XMR&lt;br /&gt;
|-&lt;br /&gt;
| Aviso de certificado en el navegador || Certificado de la plantilla aún instalado || Sustituir por el certificado del FQDN del entorno&lt;br /&gt;
|-&lt;br /&gt;
| Dos clones aparecen como la misma máquina en DHCP/monitorización || &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt; no regenerado || Ejecutar &amp;lt;code&amp;gt;rm -f /etc/machine-id &amp;amp;&amp;amp; systemd-machine-id-setup&amp;lt;/code&amp;gt; y reiniciar&lt;br /&gt;
|-&lt;br /&gt;
| El CMS no conecta con la base de datos tras cambiar contraseñas || Contraseña cambiada en &amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; pero no en MariaDB (o viceversa) || Sincronizar ambas (ver sección 4.1)&lt;br /&gt;
|-&lt;br /&gt;
| Sin acceso SSH tras personalizar el firewall || &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; erróneas en &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; con política final &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt; || Entrar por &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt;, corregir &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; y re-ejecutar &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| La hora de las programaciones no coincide || Zona horaria o NTP sin configurar || &amp;lt;code&amp;gt;timedatectl set-timezone Europe/Madrid&amp;lt;/code&amp;gt; y verificar &amp;lt;code&amp;gt;timedatectl status&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19184</id>
		<title>Instalacion cartelia 10</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19184"/>
		<updated>2026-07-13T09:35:24Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* Firewall (/etc/firewall/) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[:Media:cartelia-despliegue-vm-documentacion-tecnica.pdf|Instalación de Cartelia 1.0]]&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
= Introducción =&lt;br /&gt;
&lt;br /&gt;
'''Cartelia''' es el producto de cartelería digital (digital signage) de la compañía.&lt;br /&gt;
&lt;br /&gt;
El presente documento describe el procedimiento de despliegue de una nueva instancia de Cartelia partiendo de una '''máquina virtual base''' con las siguientes características:&lt;br /&gt;
&lt;br /&gt;
* Sistema operativo: '''Debian 13 (trixie)'''.&lt;br /&gt;
* Hipervisor: '''KVM/QEMU''' (gestionado mediante &amp;lt;code&amp;gt;libvirt&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;virt-manager&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Software preinstalado: '''Cartelia 1.0''', instalado en &amp;lt;code&amp;gt;/var/www/html/cartelia&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Punto de partida''': la máquina base se entrega totalmente operativa, con Cartelia instalado de forma nativa sobre Apache + PHP y la base de datos MariaDB local ya creada e inicializada.&lt;br /&gt;
&lt;br /&gt;
'''Restricciones conocidas''':&lt;br /&gt;
&lt;br /&gt;
* La plantilla base '''no debe arrancarse nunca en producción sin personalizar''': contiene identidad de máquina, claves SSH y secretos del CMS compartidos con cualquier otra copia de la plantilla.&lt;br /&gt;
* Los players (pantallas) se autentican contra el CMS mediante la clave del servidor (''CMS Key'') y la URL del CMS; cualquier cambio posterior de IP/FQDN o de claves obliga a volver a autorizar los displays.&lt;br /&gt;
&lt;br /&gt;
= Arquitectura =&lt;br /&gt;
&lt;br /&gt;
== Esquema general del despliegue ==&lt;br /&gt;
&lt;br /&gt;
[[File:Cartelia-arquitectura.png|thumb|center|900px|Esquema general del despliegue de Cartelia sobre KVM/QEMU]]&lt;br /&gt;
&lt;br /&gt;
El CMS está instalado de forma nativa sobre el sistema operativo: Apache 2 con PHP como servidor web del portal, MariaDB local como base de datos y el servicio XMR ejecutándose como unidad de systemd.&lt;br /&gt;
&lt;br /&gt;
== Flujo del proceso de despliegue ==&lt;br /&gt;
&lt;br /&gt;
# El técnico de sistemas clona la plantilla base en el host KVM/QEMU (disco &amp;lt;code&amp;gt;qcow2&amp;lt;/code&amp;gt; + definición de dominio libvirt).&lt;br /&gt;
# En el primer arranque del clon, se personaliza la identidad del sistema operativo: &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt;, hostname, claves SSH de host, red, zona horaria y credenciales locales.&lt;br /&gt;
# Se personaliza el producto Cartelia: URL pública del CMS, secretos y contraseñas de base de datos, clave del servidor (''CMS Key''), dirección pública de XMR y personalización de marca.&lt;br /&gt;
# Se verifican los servicios, la conectividad de los players y el acceso al portal de administración.&lt;br /&gt;
# La máquina queda registrada en inventario/monitorización y se entrega.&lt;br /&gt;
&lt;br /&gt;
== Componentes principales ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Componente !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Portal Cartelia''' || Interfaz de administración de contenidos, layouts, programaciones y pantallas. Servida por Apache 2 + PHP.&lt;br /&gt;
|-&lt;br /&gt;
| '''MariaDB (local)''' || Almacena la configuración, usuarios, programaciones y metadatos de medios del CMS. Servicio nativo del sistema.&lt;br /&gt;
|-&lt;br /&gt;
| '''XMR (Cartelia Message Relay)''' || Canal push que permite al CMS enviar órdenes inmediatas a los players (recarga de contenido, capturas, reinicio). Servicio &amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;. Los players se conectan por WebSocket a la ruta &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, que reenvía a &amp;lt;code&amp;gt;ws://127.0.0.1:8080&amp;lt;/code&amp;gt;; el puerto 9505/TCP queda además permitido en el firewall para el modo de publicación directa.&lt;br /&gt;
|-&lt;br /&gt;
| '''Biblioteca de medios''' || &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;: directorio donde el CMS guarda los ficheros multimedia subidos (configurado en ''Administración &amp;gt; Configuración &amp;gt; Ubicación de la biblioteca'' y alineado con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts).&lt;br /&gt;
|-&lt;br /&gt;
| '''libvirt / KVM-QEMU''' || Capa de virtualización que aloja la VM.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Dependencias e integraciones externas ==&lt;br /&gt;
&lt;br /&gt;
* '''DNS''': registro A/AAAA del FQDN del CMS (imprescindible si los players usan nombre en lugar de IP).&lt;br /&gt;
* '''NTP''': sincronización horaria; las programaciones de contenido dependen de la hora del sistema.&lt;br /&gt;
* '''SMTP''' (opcional): relay de correo para notificaciones del CMS, si el cliente lo requiere. Se configura en el portal (''Administración &amp;gt; Configuración'', pestaña '''Mantenimiento''').&lt;br /&gt;
* '''Certificados TLS''': siempre certificados válidos, nunca autofirmados. Si el cliente dispone de certificado propio para el FQDN, lo aporta él; en caso contrario se emite con Let's Encrypt.&lt;br /&gt;
&lt;br /&gt;
= Personalización del sistema operativo (dentro de la VM) =&lt;br /&gt;
&lt;br /&gt;
== Personalización de identidad y red ==&lt;br /&gt;
&lt;br /&gt;
Todos los comandos se ejecutan como &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; desde la consola de &amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; en el primer arranque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Paso 1: regenerar las claves SSH de host (las de la plantilla son comunes a todos los clones)&lt;br /&gt;
rm -f /etc/ssh/ssh_host_*&lt;br /&gt;
dpkg-reconfigure openssh-server&lt;br /&gt;
systemctl restart ssh&lt;br /&gt;
&lt;br /&gt;
# Paso 2: hostname y resolución local&lt;br /&gt;
hostnamectl set-hostname &amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
sed -i &amp;quot;s/127.0.1.1.*/127.0.1.1\t&amp;lt;nombre-del-entorno&amp;gt; &amp;lt;FQDN-del-CMS&amp;gt;/&amp;quot; /etc/hosts&lt;br /&gt;
&lt;br /&gt;
# Paso 3: configuración de red (ifupdown, /etc/network/interfaces)&lt;br /&gt;
&lt;br /&gt;
# Paso 4: zona horaria y hora (NTP)&lt;br /&gt;
vi /etc/systemd/timesyncd.conf.d/local.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Paso 5: actualización de paquetes del SO&lt;br /&gt;
apt update &amp;amp;&amp;amp; apt upgrade -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Arranque del producto Cartelia ==&lt;br /&gt;
&lt;br /&gt;
El CMS ya viene instalado y operativo en la máquina base; en esta fase únicamente debe verificarse el arranque de los servicios nativos tras la personalización de red:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
&lt;br /&gt;
# Si algún servicio no arranca tras el cambio de red/hostname:&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
journalctl -u apache2 -n 50 --no-pager&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Verificación de la instalación ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# El portal responde en local (la máquina base publica en HTTP; ver 4.3 para HTTPS)&lt;br /&gt;
curl -Is http://localhost/ | head -1          # esperado: HTTP/1.1 200 OK (o 302 a /login)&lt;br /&gt;
&lt;br /&gt;
# Puertos de servicio a la escucha&lt;br /&gt;
ss -tlnp | grep -E ':(80|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Resolución del FQDN desde un puesto cliente&lt;br /&gt;
getent hosts &amp;lt;FQDN-del-CMS&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Acceso final: abrir &amp;lt;code&amp;gt;http://&amp;lt;FQDN-del-CMS&amp;gt;/&amp;lt;/code&amp;gt; en el navegador y validar la pantalla de login de Cartelia (o &amp;lt;code&amp;gt;https://&amp;lt;/code&amp;gt; si se ha habilitado el vhost TLS, ver 4.3).&lt;br /&gt;
&lt;br /&gt;
= Configuración =&lt;br /&gt;
&lt;br /&gt;
== Ficheros de configuración del producto ==&lt;br /&gt;
&lt;br /&gt;
La instalación es nativa (Apache + PHP + MariaDB local); estos son los ficheros que el SAT debe revisar/personalizar en cada clon:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; del CMS''' (&amp;lt;code&amp;gt;/var/www/html/cartelia/web/settings.php&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Descripción !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbhost&amp;lt;/code&amp;gt; || Host de MariaDB (normalmente &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt;) || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$dbuser&amp;lt;/code&amp;gt; || Base de datos y usuario del CMS || No cambiar salvo política del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbpass&amp;lt;/code&amp;gt; || Contraseña del usuario del CMS en MariaDB || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SECRET_KEY&amp;lt;/code&amp;gt; || Clave secreta de la instalación (cifrado interno) || Actualmente no se regenera: se mantiene el valor de la máquina base en todos los despliegues&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''XMR''' (&amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;, unidad en &amp;lt;code&amp;gt;/etc/systemd/system/xibo-xmr.service&amp;lt;/code&amp;gt;): ejecuta &amp;lt;code&amp;gt;/var/www/html/cartelia/vendor/bin/xmr.phar&amp;lt;/code&amp;gt; con PHP como usuario &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;, con reinicio automático (&amp;lt;code&amp;gt;Restart=always&amp;lt;/code&amp;gt;). Sockets por defecto: WebSocket para players en &amp;lt;code&amp;gt;127.0.0.1:8080&amp;lt;/code&amp;gt;, expuesto a través del proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, y publicación interna del CMS en &amp;lt;code&amp;gt;tcp://127.0.0.1:50001&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Tras cualquier cambio: &amp;lt;code&amp;gt;systemctl restart xibo-xmr.service&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Apache''': la máquina base incluye dos vhosts en &amp;lt;code&amp;gt;/etc/apache2/sites-available/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; (habilitado por defecto): sirve el portal en el puerto 80. En la máquina base el &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt; es la IP de la propia máquina; en cada cliente debe actualizarse al FQDN definitivo. Incluye el proxy WebSocket de XMR (&amp;lt;code&amp;gt;ProxyPass /xmr ws://127.0.0.1:8080&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;XSendFile&amp;lt;/code&amp;gt; para la entrega de medios y una exclusión de mod_security (&amp;lt;code&amp;gt;SecRuleRemoveById 920350&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; (deshabilitado por defecto): vhost TLS preparado para clientes con FQDN y certificado. Su activación se describe en la sección 4.3.&lt;br /&gt;
&lt;br /&gt;
Validar siempre con &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; antes de &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Configuración desde el portal de administración de Cartelia ==&lt;br /&gt;
&lt;br /&gt;
Acceder con el usuario '''&amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt;''' y la contraseña estándar de la máquina base (conocida por el SAT; no se documenta aquí) y cambiar dicha contraseña de inmediato, ya que es común a todos los clones. A continuación:&lt;br /&gt;
&lt;br /&gt;
* ''Administración &amp;gt; Configuración &amp;gt; Red'': establecer la dirección del CMS (&amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt;) con el FQDN definitivo. Los players usan este valor para conectarse.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Clave secreta de CMS&amp;quot;''': es la clave que debe introducirse en cada player para autenticarlo contra el CMS. En un clon es idéntica a la de la máquina base (y, por tanto, conocida por cualquier otro despliegue), así que debe sustituirse por una clave nueva y única en cada cliente.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Ubicación de la biblioteca&amp;quot;''': verificar que mantiene el valor &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;; no cambiarlo, ya que debe coincidir con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts de Apache.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Red''' (sección XMR): establecer la dirección pública de XMR como &amp;lt;code&amp;gt;ws://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; (o &amp;lt;code&amp;gt;wss://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; si está activo el vhost HTTPS). Los players se conectan por WebSocket a través del proxy de Apache; el puerto 9505 permanece abierto en el firewall únicamente como vía alternativa de publicación directa.&lt;br /&gt;
&lt;br /&gt;
Los cambios de claves y direcciones obligan a volver a autorizar los displays que estuvieran dados de alta en la máquina base (en un despliegue nuevo no debería haber ninguno; si los hubiera, eliminarlos).&lt;br /&gt;
&lt;br /&gt;
== Configuración a nivel de sistema operativo ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elemento !! Fichero / mecanismo !! Acción&lt;br /&gt;
|-&lt;br /&gt;
| Firewall || &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt; → ejecuta &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;, parametrizado por &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Editar &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; en cada despliegue (ver 4.4): la IP local está fijada a la de la máquina base y debe cambiarse junto con la red del cliente&lt;br /&gt;
|-&lt;br /&gt;
| fail2ban || &amp;lt;code&amp;gt;/etc/fail2ban/jail.d/&amp;lt;/code&amp;gt; || Verificar jail de &amp;lt;code&amp;gt;sshd&amp;lt;/code&amp;gt; activo tras el cambio de IP&lt;br /&gt;
|-&lt;br /&gt;
| Certificado TLS / HTTPS || Vhost &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; incluido de serie (deshabilitado) || Certificado siempre válido, nunca autofirmado: lo aporta el cliente si dispone de él o se emite con Let's Encrypt (&amp;lt;code&amp;gt;certbot certonly&amp;lt;/code&amp;gt; para el FQDN; requiere el puerto 80 alcanzable desde internet y renovación automática vía timer de certbot). Instalar certificado y clave en &amp;lt;code&amp;gt;/etc/ssl/cartelia/&amp;lt;/code&amp;gt; (o apuntar las directivas &amp;lt;code&amp;gt;SSL*&amp;lt;/code&amp;gt; a &amp;lt;code&amp;gt;/etc/letsencrypt/live/&amp;lt;FQDN&amp;gt;/&amp;lt;/code&amp;gt;), ajustar &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2enmod ssl proxy_wstunnel headers&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2ensite cartelia_https&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;. Activar después la redirección HTTP→HTTPS en &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; y actualizar en el portal la CMS Address (&amp;lt;code&amp;gt;https://&amp;lt;FQDN&amp;gt;&amp;lt;/code&amp;gt;) y la dirección de XMR (&amp;lt;code&amp;gt;wss://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Rotación de logs || &amp;lt;code&amp;gt;logrotate&amp;lt;/code&amp;gt; || Verificar&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Firewall (&amp;lt;code&amp;gt;/etc/firewall/&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
El firewall se implementa con nftables mediante dos ficheros, ejecutados en el arranque por &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero !! Función&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt; || Reglas nftables: acepta 80, 443 y 9505 (XMR) hacia la IP local/flotante, 22 solo desde &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt;, checks pasivos de Zabbix (10050) desde el servidor Zabbix, ICMP y tráfico establecido; el resto de entrada se descarta (&amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Variables de entorno que parametrizan las reglas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Variables de &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; a ajustar en cada despliegue:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Valor en la máquina base !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ETH&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;ens3&amp;lt;/code&amp;gt; || Cambiar solo si la interfaz del clon tiene otro nombre (&amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; || IP de la máquina base || Cambiar siempre a la IP del cliente (debe coincidir con la configurada en la sección 3.1, paso 3)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_FLO&amp;lt;/code&amp;gt; || Igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; (sin IP flotante) || Mantener igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; salvo despliegue con alta disponibilidad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_DATOS&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar al direccionamiento del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar a la red desde la que se accede por SSH; es la única red con acceso al puerto 22&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Aplicación y verificación de cambios:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Aplicar (corta y recrea todas las reglas; las conexiones establecidas se mantienen)&lt;br /&gt;
/etc/init.d/firewall start&lt;br /&gt;
&lt;br /&gt;
# Verificar reglas cargadas y contadores&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Verificación remota mínima tras el cambio (desde RED_GESTION)&lt;br /&gt;
ssh &amp;lt;usuario&amp;gt;@&amp;lt;IP-del-servidor&amp;gt;          # el 22 debe seguir accesible&lt;br /&gt;
curl -Is http://&amp;lt;IP-del-servidor&amp;gt;/ | head -1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Aviso|'''Riesgo operativo''': editar &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; con valores erróneos y ejecutar el script '''puede dejar la máquina inaccesible por SSH''' (la política final es &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;). Realizar siempre el cambio con una consola de &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt; abierta como vía de recuperación.}}&lt;br /&gt;
&lt;br /&gt;
= Diagnósticos =&lt;br /&gt;
&lt;br /&gt;
== Comandos de diagnóstico ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Estado general de la VM desde el host de virtualización&lt;br /&gt;
virsh dominfo cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
virsh domifaddr cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Dentro de la VM — estado de servicios&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
journalctl -u apache2 -n 100 --no-pager&lt;br /&gt;
journalctl -u xibo-xmr.service -n 100 --no-pager&lt;br /&gt;
&lt;br /&gt;
# Conexión a la base de datos del CMS&lt;br /&gt;
mysql -u &amp;lt;usuario-cms&amp;gt; -p -e &amp;quot;SELECT COUNT(*) FROM display;&amp;quot; &amp;lt;bbdd-cms&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Firewall: reglas activas y contadores por regla&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Conectividad de los puertos de producto&lt;br /&gt;
ss -tlnp | grep -E ':(80|443|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Prueba del API de players (XMDS): debe responder el WSDL&lt;br /&gt;
curl -s &amp;quot;http://localhost/xmds.php?wsdl&amp;quot; | head -5&lt;br /&gt;
&lt;br /&gt;
# Comprobar identidad correcta del clon (no debe coincidir con la plantilla)&lt;br /&gt;
cat /etc/machine-id&lt;br /&gt;
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ficheros de log ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero / origen !! Contenido !! Rotación&lt;br /&gt;
|-&lt;br /&gt;
| Portal ''Administración &amp;gt; Avanzado &amp;gt; Log'' || Log de aplicación del CMS (registro de players, errores XMDS) || Gestionada por la tarea de mantenimiento del CMS&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/var/log/apache2/cartelia_access.log&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/apache2/cartelia_error.log&amp;lt;/code&amp;gt; (y &amp;lt;code&amp;gt;cartelia_ssl_*.log&amp;lt;/code&amp;gt; con el vhost HTTPS activo) || Accesos y errores del servidor web (portal y API XMDS de players) || logrotate estándar de apache2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u xibo-xmr.service&amp;lt;/code&amp;gt; || Log del servicio XMR || journald&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u ssh&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/fail2ban.log&amp;lt;/code&amp;gt; || Seguridad de acceso al SO || Estándar journald / logrotate&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Errores comunes y soluciones ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Síntoma / mensaje !! Causa probable !! Solución&lt;br /&gt;
|-&lt;br /&gt;
| El portal no carga tras el clonado || La red de la VM no se personalizó o la interfaz cambió de nombre || Revisar &amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/etc/network/interfaces.d/&amp;lt;/code&amp;gt;, y el bridge asignado en libvirt&lt;br /&gt;
|-&lt;br /&gt;
| Los players no consiguen registrarse || &amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;CMS Secret Key&amp;lt;/code&amp;gt; incorrectos, o 80/443 filtrados || Verificar sección 4.2 y &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; del firewall (4.4); probar &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; al XMDS desde la red de players&lt;br /&gt;
|-&lt;br /&gt;
| Los players se registran pero no reciben órdenes push || Dirección pública de XMR errónea, proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; no operativo o &amp;lt;code&amp;gt;xibo-xmr&amp;lt;/code&amp;gt; caído || Verificar &amp;lt;code&amp;gt;ws(s)://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt; en el portal, &amp;lt;code&amp;gt;systemctl status xibo-xmr.service&amp;lt;/code&amp;gt; y el módulo &amp;lt;code&amp;gt;proxy_wstunnel&amp;lt;/code&amp;gt; de Apache; reiniciar XMR&lt;br /&gt;
|-&lt;br /&gt;
| Aviso de certificado en el navegador || Certificado de la plantilla aún instalado || Sustituir por el certificado del FQDN del entorno&lt;br /&gt;
|-&lt;br /&gt;
| Dos clones aparecen como la misma máquina en DHCP/monitorización || &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt; no regenerado || Ejecutar &amp;lt;code&amp;gt;rm -f /etc/machine-id &amp;amp;&amp;amp; systemd-machine-id-setup&amp;lt;/code&amp;gt; y reiniciar&lt;br /&gt;
|-&lt;br /&gt;
| El CMS no conecta con la base de datos tras cambiar contraseñas || Contraseña cambiada en &amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; pero no en MariaDB (o viceversa) || Sincronizar ambas (ver sección 4.1)&lt;br /&gt;
|-&lt;br /&gt;
| Sin acceso SSH tras personalizar el firewall || &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; erróneas en &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; con política final &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt; || Entrar por &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt;, corregir &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; y re-ejecutar &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| La hora de las programaciones no coincide || Zona horaria o NTP sin configurar || &amp;lt;code&amp;gt;timedatectl set-timezone Europe/Madrid&amp;lt;/code&amp;gt; y verificar &amp;lt;code&amp;gt;timedatectl status&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19183</id>
		<title>Instalacion cartelia 10</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19183"/>
		<updated>2026-07-13T09:34:43Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* 5. Diagnósticos */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[:Media:cartelia-despliegue-vm-documentacion-tecnica.pdf|Instalación de Cartelia 1.0]]&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
= Introducción =&lt;br /&gt;
&lt;br /&gt;
'''Cartelia''' es el producto de cartelería digital (digital signage) de la compañía.&lt;br /&gt;
&lt;br /&gt;
El presente documento describe el procedimiento de despliegue de una nueva instancia de Cartelia partiendo de una '''máquina virtual base''' con las siguientes características:&lt;br /&gt;
&lt;br /&gt;
* Sistema operativo: '''Debian 13 (trixie)'''.&lt;br /&gt;
* Hipervisor: '''KVM/QEMU''' (gestionado mediante &amp;lt;code&amp;gt;libvirt&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;virt-manager&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Software preinstalado: '''Cartelia 1.0''', instalado en &amp;lt;code&amp;gt;/var/www/html/cartelia&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Punto de partida''': la máquina base se entrega totalmente operativa, con Cartelia instalado de forma nativa sobre Apache + PHP y la base de datos MariaDB local ya creada e inicializada.&lt;br /&gt;
&lt;br /&gt;
'''Restricciones conocidas''':&lt;br /&gt;
&lt;br /&gt;
* La plantilla base '''no debe arrancarse nunca en producción sin personalizar''': contiene identidad de máquina, claves SSH y secretos del CMS compartidos con cualquier otra copia de la plantilla.&lt;br /&gt;
* Los players (pantallas) se autentican contra el CMS mediante la clave del servidor (''CMS Key'') y la URL del CMS; cualquier cambio posterior de IP/FQDN o de claves obliga a volver a autorizar los displays.&lt;br /&gt;
&lt;br /&gt;
= Arquitectura =&lt;br /&gt;
&lt;br /&gt;
== Esquema general del despliegue ==&lt;br /&gt;
&lt;br /&gt;
[[File:Cartelia-arquitectura.png|thumb|center|900px|Esquema general del despliegue de Cartelia sobre KVM/QEMU]]&lt;br /&gt;
&lt;br /&gt;
El CMS está instalado de forma nativa sobre el sistema operativo: Apache 2 con PHP como servidor web del portal, MariaDB local como base de datos y el servicio XMR ejecutándose como unidad de systemd.&lt;br /&gt;
&lt;br /&gt;
== Flujo del proceso de despliegue ==&lt;br /&gt;
&lt;br /&gt;
# El técnico de sistemas clona la plantilla base en el host KVM/QEMU (disco &amp;lt;code&amp;gt;qcow2&amp;lt;/code&amp;gt; + definición de dominio libvirt).&lt;br /&gt;
# En el primer arranque del clon, se personaliza la identidad del sistema operativo: &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt;, hostname, claves SSH de host, red, zona horaria y credenciales locales.&lt;br /&gt;
# Se personaliza el producto Cartelia: URL pública del CMS, secretos y contraseñas de base de datos, clave del servidor (''CMS Key''), dirección pública de XMR y personalización de marca.&lt;br /&gt;
# Se verifican los servicios, la conectividad de los players y el acceso al portal de administración.&lt;br /&gt;
# La máquina queda registrada en inventario/monitorización y se entrega.&lt;br /&gt;
&lt;br /&gt;
== Componentes principales ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Componente !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Portal Cartelia''' || Interfaz de administración de contenidos, layouts, programaciones y pantallas. Servida por Apache 2 + PHP.&lt;br /&gt;
|-&lt;br /&gt;
| '''MariaDB (local)''' || Almacena la configuración, usuarios, programaciones y metadatos de medios del CMS. Servicio nativo del sistema.&lt;br /&gt;
|-&lt;br /&gt;
| '''XMR (Cartelia Message Relay)''' || Canal push que permite al CMS enviar órdenes inmediatas a los players (recarga de contenido, capturas, reinicio). Servicio &amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;. Los players se conectan por WebSocket a la ruta &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, que reenvía a &amp;lt;code&amp;gt;ws://127.0.0.1:8080&amp;lt;/code&amp;gt;; el puerto 9505/TCP queda además permitido en el firewall para el modo de publicación directa.&lt;br /&gt;
|-&lt;br /&gt;
| '''Biblioteca de medios''' || &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;: directorio donde el CMS guarda los ficheros multimedia subidos (configurado en ''Administración &amp;gt; Configuración &amp;gt; Ubicación de la biblioteca'' y alineado con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts).&lt;br /&gt;
|-&lt;br /&gt;
| '''libvirt / KVM-QEMU''' || Capa de virtualización que aloja la VM.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Dependencias e integraciones externas ==&lt;br /&gt;
&lt;br /&gt;
* '''DNS''': registro A/AAAA del FQDN del CMS (imprescindible si los players usan nombre en lugar de IP).&lt;br /&gt;
* '''NTP''': sincronización horaria; las programaciones de contenido dependen de la hora del sistema.&lt;br /&gt;
* '''SMTP''' (opcional): relay de correo para notificaciones del CMS, si el cliente lo requiere. Se configura en el portal (''Administración &amp;gt; Configuración'', pestaña '''Mantenimiento''').&lt;br /&gt;
* '''Certificados TLS''': siempre certificados válidos, nunca autofirmados. Si el cliente dispone de certificado propio para el FQDN, lo aporta él; en caso contrario se emite con Let's Encrypt.&lt;br /&gt;
&lt;br /&gt;
= Personalización del sistema operativo (dentro de la VM) =&lt;br /&gt;
&lt;br /&gt;
== Personalización de identidad y red ==&lt;br /&gt;
&lt;br /&gt;
Todos los comandos se ejecutan como &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; desde la consola de &amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; en el primer arranque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Paso 1: regenerar las claves SSH de host (las de la plantilla son comunes a todos los clones)&lt;br /&gt;
rm -f /etc/ssh/ssh_host_*&lt;br /&gt;
dpkg-reconfigure openssh-server&lt;br /&gt;
systemctl restart ssh&lt;br /&gt;
&lt;br /&gt;
# Paso 2: hostname y resolución local&lt;br /&gt;
hostnamectl set-hostname &amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
sed -i &amp;quot;s/127.0.1.1.*/127.0.1.1\t&amp;lt;nombre-del-entorno&amp;gt; &amp;lt;FQDN-del-CMS&amp;gt;/&amp;quot; /etc/hosts&lt;br /&gt;
&lt;br /&gt;
# Paso 3: configuración de red (ifupdown, /etc/network/interfaces)&lt;br /&gt;
&lt;br /&gt;
# Paso 4: zona horaria y hora (NTP)&lt;br /&gt;
vi /etc/systemd/timesyncd.conf.d/local.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Paso 5: actualización de paquetes del SO&lt;br /&gt;
apt update &amp;amp;&amp;amp; apt upgrade -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Arranque del producto Cartelia ==&lt;br /&gt;
&lt;br /&gt;
El CMS ya viene instalado y operativo en la máquina base; en esta fase únicamente debe verificarse el arranque de los servicios nativos tras la personalización de red:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
&lt;br /&gt;
# Si algún servicio no arranca tras el cambio de red/hostname:&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
journalctl -u apache2 -n 50 --no-pager&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Verificación de la instalación ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# El portal responde en local (la máquina base publica en HTTP; ver 4.3 para HTTPS)&lt;br /&gt;
curl -Is http://localhost/ | head -1          # esperado: HTTP/1.1 200 OK (o 302 a /login)&lt;br /&gt;
&lt;br /&gt;
# Puertos de servicio a la escucha&lt;br /&gt;
ss -tlnp | grep -E ':(80|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Resolución del FQDN desde un puesto cliente&lt;br /&gt;
getent hosts &amp;lt;FQDN-del-CMS&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Acceso final: abrir &amp;lt;code&amp;gt;http://&amp;lt;FQDN-del-CMS&amp;gt;/&amp;lt;/code&amp;gt; en el navegador y validar la pantalla de login de Cartelia (o &amp;lt;code&amp;gt;https://&amp;lt;/code&amp;gt; si se ha habilitado el vhost TLS, ver 4.3).&lt;br /&gt;
&lt;br /&gt;
= Configuración =&lt;br /&gt;
&lt;br /&gt;
== Ficheros de configuración del producto ==&lt;br /&gt;
&lt;br /&gt;
La instalación es nativa (Apache + PHP + MariaDB local); estos son los ficheros que el SAT debe revisar/personalizar en cada clon:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; del CMS''' (&amp;lt;code&amp;gt;/var/www/html/cartelia/web/settings.php&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Descripción !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbhost&amp;lt;/code&amp;gt; || Host de MariaDB (normalmente &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt;) || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$dbuser&amp;lt;/code&amp;gt; || Base de datos y usuario del CMS || No cambiar salvo política del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbpass&amp;lt;/code&amp;gt; || Contraseña del usuario del CMS en MariaDB || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SECRET_KEY&amp;lt;/code&amp;gt; || Clave secreta de la instalación (cifrado interno) || Actualmente no se regenera: se mantiene el valor de la máquina base en todos los despliegues&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''XMR''' (&amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;, unidad en &amp;lt;code&amp;gt;/etc/systemd/system/xibo-xmr.service&amp;lt;/code&amp;gt;): ejecuta &amp;lt;code&amp;gt;/var/www/html/cartelia/vendor/bin/xmr.phar&amp;lt;/code&amp;gt; con PHP como usuario &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;, con reinicio automático (&amp;lt;code&amp;gt;Restart=always&amp;lt;/code&amp;gt;). Sockets por defecto: WebSocket para players en &amp;lt;code&amp;gt;127.0.0.1:8080&amp;lt;/code&amp;gt;, expuesto a través del proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, y publicación interna del CMS en &amp;lt;code&amp;gt;tcp://127.0.0.1:50001&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Tras cualquier cambio: &amp;lt;code&amp;gt;systemctl restart xibo-xmr.service&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Apache''': la máquina base incluye dos vhosts en &amp;lt;code&amp;gt;/etc/apache2/sites-available/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; (habilitado por defecto): sirve el portal en el puerto 80. En la máquina base el &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt; es la IP de la propia máquina; en cada cliente debe actualizarse al FQDN definitivo. Incluye el proxy WebSocket de XMR (&amp;lt;code&amp;gt;ProxyPass /xmr ws://127.0.0.1:8080&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;XSendFile&amp;lt;/code&amp;gt; para la entrega de medios y una exclusión de mod_security (&amp;lt;code&amp;gt;SecRuleRemoveById 920350&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; (deshabilitado por defecto): vhost TLS preparado para clientes con FQDN y certificado. Su activación se describe en la sección 4.3.&lt;br /&gt;
&lt;br /&gt;
Validar siempre con &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; antes de &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Configuración desde el portal de administración de Cartelia ==&lt;br /&gt;
&lt;br /&gt;
Acceder con el usuario '''&amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt;''' y la contraseña estándar de la máquina base (conocida por el SAT; no se documenta aquí) y cambiar dicha contraseña de inmediato, ya que es común a todos los clones. A continuación:&lt;br /&gt;
&lt;br /&gt;
* ''Administración &amp;gt; Configuración &amp;gt; Red'': establecer la dirección del CMS (&amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt;) con el FQDN definitivo. Los players usan este valor para conectarse.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Clave secreta de CMS&amp;quot;''': es la clave que debe introducirse en cada player para autenticarlo contra el CMS. En un clon es idéntica a la de la máquina base (y, por tanto, conocida por cualquier otro despliegue), así que debe sustituirse por una clave nueva y única en cada cliente.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Ubicación de la biblioteca&amp;quot;''': verificar que mantiene el valor &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;; no cambiarlo, ya que debe coincidir con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts de Apache.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Red''' (sección XMR): establecer la dirección pública de XMR como &amp;lt;code&amp;gt;ws://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; (o &amp;lt;code&amp;gt;wss://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; si está activo el vhost HTTPS). Los players se conectan por WebSocket a través del proxy de Apache; el puerto 9505 permanece abierto en el firewall únicamente como vía alternativa de publicación directa.&lt;br /&gt;
&lt;br /&gt;
Los cambios de claves y direcciones obligan a volver a autorizar los displays que estuvieran dados de alta en la máquina base (en un despliegue nuevo no debería haber ninguno; si los hubiera, eliminarlos).&lt;br /&gt;
&lt;br /&gt;
== Configuración a nivel de sistema operativo ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elemento !! Fichero / mecanismo !! Acción&lt;br /&gt;
|-&lt;br /&gt;
| Firewall || &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt; → ejecuta &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;, parametrizado por &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Editar &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; en cada despliegue (ver 4.4): la IP local está fijada a la de la máquina base y debe cambiarse junto con la red del cliente&lt;br /&gt;
|-&lt;br /&gt;
| fail2ban || &amp;lt;code&amp;gt;/etc/fail2ban/jail.d/&amp;lt;/code&amp;gt; || Verificar jail de &amp;lt;code&amp;gt;sshd&amp;lt;/code&amp;gt; activo tras el cambio de IP&lt;br /&gt;
|-&lt;br /&gt;
| Certificado TLS / HTTPS || Vhost &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; incluido de serie (deshabilitado) || Certificado siempre válido, nunca autofirmado: lo aporta el cliente si dispone de él o se emite con Let's Encrypt (&amp;lt;code&amp;gt;certbot certonly&amp;lt;/code&amp;gt; para el FQDN; requiere el puerto 80 alcanzable desde internet y renovación automática vía timer de certbot). Instalar certificado y clave en &amp;lt;code&amp;gt;/etc/ssl/cartelia/&amp;lt;/code&amp;gt; (o apuntar las directivas &amp;lt;code&amp;gt;SSL*&amp;lt;/code&amp;gt; a &amp;lt;code&amp;gt;/etc/letsencrypt/live/&amp;lt;FQDN&amp;gt;/&amp;lt;/code&amp;gt;), ajustar &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2enmod ssl proxy_wstunnel headers&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2ensite cartelia_https&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;. Activar después la redirección HTTP→HTTPS en &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; y actualizar en el portal la CMS Address (&amp;lt;code&amp;gt;https://&amp;lt;FQDN&amp;gt;&amp;lt;/code&amp;gt;) y la dirección de XMR (&amp;lt;code&amp;gt;wss://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Rotación de logs || &amp;lt;code&amp;gt;logrotate&amp;lt;/code&amp;gt; || Verificar&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Firewall (&amp;lt;code&amp;gt;/etc/firewall/&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
El firewall se implementa con nftables mediante dos ficheros, ejecutados en el arranque por &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero !! Función&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt; || Reglas nftables: acepta 80, 443 y 9505 (XMR) hacia la IP local/flotante, 22 solo desde &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt;, checks pasivos de Zabbix (10050) desde el servidor Zabbix, ICMP y tráfico establecido; el resto de entrada se descarta (&amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Variables de entorno que parametrizan las reglas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Variables de &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; a ajustar en cada despliegue:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Valor en la máquina base !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ETH&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;ens3&amp;lt;/code&amp;gt; || Cambiar solo si la interfaz del clon tiene otro nombre (&amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; || IP de la máquina base || Cambiar siempre a la IP del cliente (debe coincidir con la configurada en la sección 3.1, paso 3)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_FLO&amp;lt;/code&amp;gt; || Igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; (sin IP flotante) || Mantener igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; salvo despliegue con alta disponibilidad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_DATOS&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar al direccionamiento del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar a la red desde la que se accede por SSH; es la única red con acceso al puerto 22&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Aplicación y verificación de cambios:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Aplicar (corta y recrea todas las reglas; las conexiones establecidas se mantienen)&lt;br /&gt;
/etc/init.d/firewall start&lt;br /&gt;
&lt;br /&gt;
# Verificar reglas cargadas y contadores&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Verificación remota mínima tras el cambio (desde RED_GESTION)&lt;br /&gt;
ssh &amp;lt;usuario&amp;gt;@&amp;lt;IP-del-servidor&amp;gt;          # el 22 debe seguir accesible&lt;br /&gt;
curl -Is http://&amp;lt;IP-del-servidor&amp;gt;/ | head -1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Aviso|'''Riesgo operativo''': editar &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; con valores erróneos y ejecutar el script '''puede dejar la máquina inaccesible por SSH''' (la política final es &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;). Realizar siempre el cambio con una consola de &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt; abierta como vía de recuperación.}}&lt;br /&gt;
&lt;br /&gt;
= Diagnósticos =&lt;br /&gt;
&lt;br /&gt;
== Comandos de diagnóstico ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Estado general de la VM desde el host de virtualización&lt;br /&gt;
virsh dominfo cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
virsh domifaddr cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Dentro de la VM — estado de servicios&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
journalctl -u apache2 -n 100 --no-pager&lt;br /&gt;
journalctl -u xibo-xmr.service -n 100 --no-pager&lt;br /&gt;
&lt;br /&gt;
# Conexión a la base de datos del CMS&lt;br /&gt;
mysql -u &amp;lt;usuario-cms&amp;gt; -p -e &amp;quot;SELECT COUNT(*) FROM display;&amp;quot; &amp;lt;bbdd-cms&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Firewall: reglas activas y contadores por regla&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Conectividad de los puertos de producto&lt;br /&gt;
ss -tlnp | grep -E ':(80|443|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Prueba del API de players (XMDS): debe responder el WSDL&lt;br /&gt;
curl -s &amp;quot;http://localhost/xmds.php?wsdl&amp;quot; | head -5&lt;br /&gt;
&lt;br /&gt;
# Comprobar identidad correcta del clon (no debe coincidir con la plantilla)&lt;br /&gt;
cat /etc/machine-id&lt;br /&gt;
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ficheros de log ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero / origen !! Contenido !! Rotación&lt;br /&gt;
|-&lt;br /&gt;
| Portal ''Administración &amp;gt; Avanzado &amp;gt; Log'' || Log de aplicación del CMS (registro de players, errores XMDS) || Gestionada por la tarea de mantenimiento del CMS&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/var/log/apache2/cartelia_access.log&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/apache2/cartelia_error.log&amp;lt;/code&amp;gt; (y &amp;lt;code&amp;gt;cartelia_ssl_*.log&amp;lt;/code&amp;gt; con el vhost HTTPS activo) || Accesos y errores del servidor web (portal y API XMDS de players) || logrotate estándar de apache2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u xibo-xmr.service&amp;lt;/code&amp;gt; || Log del servicio XMR || journald&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u ssh&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/fail2ban.log&amp;lt;/code&amp;gt; || Seguridad de acceso al SO || Estándar journald / logrotate&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Errores comunes y soluciones ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Síntoma / mensaje !! Causa probable !! Solución&lt;br /&gt;
|-&lt;br /&gt;
| El portal no carga tras el clonado || La red de la VM no se personalizó o la interfaz cambió de nombre || Revisar &amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/etc/network/interfaces.d/&amp;lt;/code&amp;gt;, y el bridge asignado en libvirt&lt;br /&gt;
|-&lt;br /&gt;
| Los players no consiguen registrarse || &amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;CMS Secret Key&amp;lt;/code&amp;gt; incorrectos, o 80/443 filtrados || Verificar sección 4.2 y &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; del firewall (4.4); probar &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; al XMDS desde la red de players&lt;br /&gt;
|-&lt;br /&gt;
| Los players se registran pero no reciben órdenes push || Dirección pública de XMR errónea, proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; no operativo o &amp;lt;code&amp;gt;xibo-xmr&amp;lt;/code&amp;gt; caído || Verificar &amp;lt;code&amp;gt;ws(s)://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt; en el portal, &amp;lt;code&amp;gt;systemctl status xibo-xmr.service&amp;lt;/code&amp;gt; y el módulo &amp;lt;code&amp;gt;proxy_wstunnel&amp;lt;/code&amp;gt; de Apache; reiniciar XMR&lt;br /&gt;
|-&lt;br /&gt;
| Aviso de certificado en el navegador || Certificado de la plantilla aún instalado || Sustituir por el certificado del FQDN del entorno&lt;br /&gt;
|-&lt;br /&gt;
| Dos clones aparecen como la misma máquina en DHCP/monitorización || &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt; no regenerado || Ejecutar &amp;lt;code&amp;gt;rm -f /etc/machine-id &amp;amp;&amp;amp; systemd-machine-id-setup&amp;lt;/code&amp;gt; y reiniciar&lt;br /&gt;
|-&lt;br /&gt;
| El CMS no conecta con la base de datos tras cambiar contraseñas || Contraseña cambiada en &amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; pero no en MariaDB (o viceversa) || Sincronizar ambas (ver sección 4.1)&lt;br /&gt;
|-&lt;br /&gt;
| Sin acceso SSH tras personalizar el firewall || &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; erróneas en &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; con política final &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt; || Entrar por &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt;, corregir &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; y re-ejecutar &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| La hora de las programaciones no coincide || Zona horaria o NTP sin configurar || &amp;lt;code&amp;gt;timedatectl set-timezone Europe/Madrid&amp;lt;/code&amp;gt; y verificar &amp;lt;code&amp;gt;timedatectl status&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19182</id>
		<title>Instalacion cartelia 10</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19182"/>
		<updated>2026-07-13T09:34:22Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* 3. Personalización del sistema operativo (dentro de la VM) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[:Media:cartelia-despliegue-vm-documentacion-tecnica.pdf|Instalación de Cartelia 1.0]]&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
= Introducción =&lt;br /&gt;
&lt;br /&gt;
'''Cartelia''' es el producto de cartelería digital (digital signage) de la compañía.&lt;br /&gt;
&lt;br /&gt;
El presente documento describe el procedimiento de despliegue de una nueva instancia de Cartelia partiendo de una '''máquina virtual base''' con las siguientes características:&lt;br /&gt;
&lt;br /&gt;
* Sistema operativo: '''Debian 13 (trixie)'''.&lt;br /&gt;
* Hipervisor: '''KVM/QEMU''' (gestionado mediante &amp;lt;code&amp;gt;libvirt&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;virt-manager&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Software preinstalado: '''Cartelia 1.0''', instalado en &amp;lt;code&amp;gt;/var/www/html/cartelia&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Punto de partida''': la máquina base se entrega totalmente operativa, con Cartelia instalado de forma nativa sobre Apache + PHP y la base de datos MariaDB local ya creada e inicializada.&lt;br /&gt;
&lt;br /&gt;
'''Restricciones conocidas''':&lt;br /&gt;
&lt;br /&gt;
* La plantilla base '''no debe arrancarse nunca en producción sin personalizar''': contiene identidad de máquina, claves SSH y secretos del CMS compartidos con cualquier otra copia de la plantilla.&lt;br /&gt;
* Los players (pantallas) se autentican contra el CMS mediante la clave del servidor (''CMS Key'') y la URL del CMS; cualquier cambio posterior de IP/FQDN o de claves obliga a volver a autorizar los displays.&lt;br /&gt;
&lt;br /&gt;
= Arquitectura =&lt;br /&gt;
&lt;br /&gt;
== Esquema general del despliegue ==&lt;br /&gt;
&lt;br /&gt;
[[File:Cartelia-arquitectura.png|thumb|center|900px|Esquema general del despliegue de Cartelia sobre KVM/QEMU]]&lt;br /&gt;
&lt;br /&gt;
El CMS está instalado de forma nativa sobre el sistema operativo: Apache 2 con PHP como servidor web del portal, MariaDB local como base de datos y el servicio XMR ejecutándose como unidad de systemd.&lt;br /&gt;
&lt;br /&gt;
== Flujo del proceso de despliegue ==&lt;br /&gt;
&lt;br /&gt;
# El técnico de sistemas clona la plantilla base en el host KVM/QEMU (disco &amp;lt;code&amp;gt;qcow2&amp;lt;/code&amp;gt; + definición de dominio libvirt).&lt;br /&gt;
# En el primer arranque del clon, se personaliza la identidad del sistema operativo: &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt;, hostname, claves SSH de host, red, zona horaria y credenciales locales.&lt;br /&gt;
# Se personaliza el producto Cartelia: URL pública del CMS, secretos y contraseñas de base de datos, clave del servidor (''CMS Key''), dirección pública de XMR y personalización de marca.&lt;br /&gt;
# Se verifican los servicios, la conectividad de los players y el acceso al portal de administración.&lt;br /&gt;
# La máquina queda registrada en inventario/monitorización y se entrega.&lt;br /&gt;
&lt;br /&gt;
== Componentes principales ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Componente !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Portal Cartelia''' || Interfaz de administración de contenidos, layouts, programaciones y pantallas. Servida por Apache 2 + PHP.&lt;br /&gt;
|-&lt;br /&gt;
| '''MariaDB (local)''' || Almacena la configuración, usuarios, programaciones y metadatos de medios del CMS. Servicio nativo del sistema.&lt;br /&gt;
|-&lt;br /&gt;
| '''XMR (Cartelia Message Relay)''' || Canal push que permite al CMS enviar órdenes inmediatas a los players (recarga de contenido, capturas, reinicio). Servicio &amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;. Los players se conectan por WebSocket a la ruta &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, que reenvía a &amp;lt;code&amp;gt;ws://127.0.0.1:8080&amp;lt;/code&amp;gt;; el puerto 9505/TCP queda además permitido en el firewall para el modo de publicación directa.&lt;br /&gt;
|-&lt;br /&gt;
| '''Biblioteca de medios''' || &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;: directorio donde el CMS guarda los ficheros multimedia subidos (configurado en ''Administración &amp;gt; Configuración &amp;gt; Ubicación de la biblioteca'' y alineado con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts).&lt;br /&gt;
|-&lt;br /&gt;
| '''libvirt / KVM-QEMU''' || Capa de virtualización que aloja la VM.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Dependencias e integraciones externas ==&lt;br /&gt;
&lt;br /&gt;
* '''DNS''': registro A/AAAA del FQDN del CMS (imprescindible si los players usan nombre en lugar de IP).&lt;br /&gt;
* '''NTP''': sincronización horaria; las programaciones de contenido dependen de la hora del sistema.&lt;br /&gt;
* '''SMTP''' (opcional): relay de correo para notificaciones del CMS, si el cliente lo requiere. Se configura en el portal (''Administración &amp;gt; Configuración'', pestaña '''Mantenimiento''').&lt;br /&gt;
* '''Certificados TLS''': siempre certificados válidos, nunca autofirmados. Si el cliente dispone de certificado propio para el FQDN, lo aporta él; en caso contrario se emite con Let's Encrypt.&lt;br /&gt;
&lt;br /&gt;
= Personalización del sistema operativo (dentro de la VM) =&lt;br /&gt;
&lt;br /&gt;
== Personalización de identidad y red ==&lt;br /&gt;
&lt;br /&gt;
Todos los comandos se ejecutan como &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; desde la consola de &amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; en el primer arranque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Paso 1: regenerar las claves SSH de host (las de la plantilla son comunes a todos los clones)&lt;br /&gt;
rm -f /etc/ssh/ssh_host_*&lt;br /&gt;
dpkg-reconfigure openssh-server&lt;br /&gt;
systemctl restart ssh&lt;br /&gt;
&lt;br /&gt;
# Paso 2: hostname y resolución local&lt;br /&gt;
hostnamectl set-hostname &amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
sed -i &amp;quot;s/127.0.1.1.*/127.0.1.1\t&amp;lt;nombre-del-entorno&amp;gt; &amp;lt;FQDN-del-CMS&amp;gt;/&amp;quot; /etc/hosts&lt;br /&gt;
&lt;br /&gt;
# Paso 3: configuración de red (ifupdown, /etc/network/interfaces)&lt;br /&gt;
&lt;br /&gt;
# Paso 4: zona horaria y hora (NTP)&lt;br /&gt;
vi /etc/systemd/timesyncd.conf.d/local.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Paso 5: actualización de paquetes del SO&lt;br /&gt;
apt update &amp;amp;&amp;amp; apt upgrade -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Arranque del producto Cartelia ==&lt;br /&gt;
&lt;br /&gt;
El CMS ya viene instalado y operativo en la máquina base; en esta fase únicamente debe verificarse el arranque de los servicios nativos tras la personalización de red:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
&lt;br /&gt;
# Si algún servicio no arranca tras el cambio de red/hostname:&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
journalctl -u apache2 -n 50 --no-pager&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Verificación de la instalación ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# El portal responde en local (la máquina base publica en HTTP; ver 4.3 para HTTPS)&lt;br /&gt;
curl -Is http://localhost/ | head -1          # esperado: HTTP/1.1 200 OK (o 302 a /login)&lt;br /&gt;
&lt;br /&gt;
# Puertos de servicio a la escucha&lt;br /&gt;
ss -tlnp | grep -E ':(80|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Resolución del FQDN desde un puesto cliente&lt;br /&gt;
getent hosts &amp;lt;FQDN-del-CMS&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Acceso final: abrir &amp;lt;code&amp;gt;http://&amp;lt;FQDN-del-CMS&amp;gt;/&amp;lt;/code&amp;gt; en el navegador y validar la pantalla de login de Cartelia (o &amp;lt;code&amp;gt;https://&amp;lt;/code&amp;gt; si se ha habilitado el vhost TLS, ver 4.3).&lt;br /&gt;
&lt;br /&gt;
= Configuración =&lt;br /&gt;
&lt;br /&gt;
== Ficheros de configuración del producto ==&lt;br /&gt;
&lt;br /&gt;
La instalación es nativa (Apache + PHP + MariaDB local); estos son los ficheros que el SAT debe revisar/personalizar en cada clon:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; del CMS''' (&amp;lt;code&amp;gt;/var/www/html/cartelia/web/settings.php&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Descripción !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbhost&amp;lt;/code&amp;gt; || Host de MariaDB (normalmente &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt;) || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$dbuser&amp;lt;/code&amp;gt; || Base de datos y usuario del CMS || No cambiar salvo política del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbpass&amp;lt;/code&amp;gt; || Contraseña del usuario del CMS en MariaDB || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SECRET_KEY&amp;lt;/code&amp;gt; || Clave secreta de la instalación (cifrado interno) || Actualmente no se regenera: se mantiene el valor de la máquina base en todos los despliegues&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''XMR''' (&amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;, unidad en &amp;lt;code&amp;gt;/etc/systemd/system/xibo-xmr.service&amp;lt;/code&amp;gt;): ejecuta &amp;lt;code&amp;gt;/var/www/html/cartelia/vendor/bin/xmr.phar&amp;lt;/code&amp;gt; con PHP como usuario &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;, con reinicio automático (&amp;lt;code&amp;gt;Restart=always&amp;lt;/code&amp;gt;). Sockets por defecto: WebSocket para players en &amp;lt;code&amp;gt;127.0.0.1:8080&amp;lt;/code&amp;gt;, expuesto a través del proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, y publicación interna del CMS en &amp;lt;code&amp;gt;tcp://127.0.0.1:50001&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Tras cualquier cambio: &amp;lt;code&amp;gt;systemctl restart xibo-xmr.service&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Apache''': la máquina base incluye dos vhosts en &amp;lt;code&amp;gt;/etc/apache2/sites-available/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; (habilitado por defecto): sirve el portal en el puerto 80. En la máquina base el &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt; es la IP de la propia máquina; en cada cliente debe actualizarse al FQDN definitivo. Incluye el proxy WebSocket de XMR (&amp;lt;code&amp;gt;ProxyPass /xmr ws://127.0.0.1:8080&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;XSendFile&amp;lt;/code&amp;gt; para la entrega de medios y una exclusión de mod_security (&amp;lt;code&amp;gt;SecRuleRemoveById 920350&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; (deshabilitado por defecto): vhost TLS preparado para clientes con FQDN y certificado. Su activación se describe en la sección 4.3.&lt;br /&gt;
&lt;br /&gt;
Validar siempre con &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; antes de &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Configuración desde el portal de administración de Cartelia ==&lt;br /&gt;
&lt;br /&gt;
Acceder con el usuario '''&amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt;''' y la contraseña estándar de la máquina base (conocida por el SAT; no se documenta aquí) y cambiar dicha contraseña de inmediato, ya que es común a todos los clones. A continuación:&lt;br /&gt;
&lt;br /&gt;
* ''Administración &amp;gt; Configuración &amp;gt; Red'': establecer la dirección del CMS (&amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt;) con el FQDN definitivo. Los players usan este valor para conectarse.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Clave secreta de CMS&amp;quot;''': es la clave que debe introducirse en cada player para autenticarlo contra el CMS. En un clon es idéntica a la de la máquina base (y, por tanto, conocida por cualquier otro despliegue), así que debe sustituirse por una clave nueva y única en cada cliente.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Ubicación de la biblioteca&amp;quot;''': verificar que mantiene el valor &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;; no cambiarlo, ya que debe coincidir con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts de Apache.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Red''' (sección XMR): establecer la dirección pública de XMR como &amp;lt;code&amp;gt;ws://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; (o &amp;lt;code&amp;gt;wss://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; si está activo el vhost HTTPS). Los players se conectan por WebSocket a través del proxy de Apache; el puerto 9505 permanece abierto en el firewall únicamente como vía alternativa de publicación directa.&lt;br /&gt;
&lt;br /&gt;
Los cambios de claves y direcciones obligan a volver a autorizar los displays que estuvieran dados de alta en la máquina base (en un despliegue nuevo no debería haber ninguno; si los hubiera, eliminarlos).&lt;br /&gt;
&lt;br /&gt;
== Configuración a nivel de sistema operativo ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elemento !! Fichero / mecanismo !! Acción&lt;br /&gt;
|-&lt;br /&gt;
| Firewall || &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt; → ejecuta &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;, parametrizado por &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Editar &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; en cada despliegue (ver 4.4): la IP local está fijada a la de la máquina base y debe cambiarse junto con la red del cliente&lt;br /&gt;
|-&lt;br /&gt;
| fail2ban || &amp;lt;code&amp;gt;/etc/fail2ban/jail.d/&amp;lt;/code&amp;gt; || Verificar jail de &amp;lt;code&amp;gt;sshd&amp;lt;/code&amp;gt; activo tras el cambio de IP&lt;br /&gt;
|-&lt;br /&gt;
| Certificado TLS / HTTPS || Vhost &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; incluido de serie (deshabilitado) || Certificado siempre válido, nunca autofirmado: lo aporta el cliente si dispone de él o se emite con Let's Encrypt (&amp;lt;code&amp;gt;certbot certonly&amp;lt;/code&amp;gt; para el FQDN; requiere el puerto 80 alcanzable desde internet y renovación automática vía timer de certbot). Instalar certificado y clave en &amp;lt;code&amp;gt;/etc/ssl/cartelia/&amp;lt;/code&amp;gt; (o apuntar las directivas &amp;lt;code&amp;gt;SSL*&amp;lt;/code&amp;gt; a &amp;lt;code&amp;gt;/etc/letsencrypt/live/&amp;lt;FQDN&amp;gt;/&amp;lt;/code&amp;gt;), ajustar &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2enmod ssl proxy_wstunnel headers&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2ensite cartelia_https&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;. Activar después la redirección HTTP→HTTPS en &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; y actualizar en el portal la CMS Address (&amp;lt;code&amp;gt;https://&amp;lt;FQDN&amp;gt;&amp;lt;/code&amp;gt;) y la dirección de XMR (&amp;lt;code&amp;gt;wss://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Rotación de logs || &amp;lt;code&amp;gt;logrotate&amp;lt;/code&amp;gt; || Verificar&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Firewall (&amp;lt;code&amp;gt;/etc/firewall/&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
El firewall se implementa con nftables mediante dos ficheros, ejecutados en el arranque por &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero !! Función&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt; || Reglas nftables: acepta 80, 443 y 9505 (XMR) hacia la IP local/flotante, 22 solo desde &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt;, checks pasivos de Zabbix (10050) desde el servidor Zabbix, ICMP y tráfico establecido; el resto de entrada se descarta (&amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Variables de entorno que parametrizan las reglas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Variables de &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; a ajustar en cada despliegue:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Valor en la máquina base !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ETH&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;ens3&amp;lt;/code&amp;gt; || Cambiar solo si la interfaz del clon tiene otro nombre (&amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; || IP de la máquina base || Cambiar siempre a la IP del cliente (debe coincidir con la configurada en la sección 3.1, paso 3)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_FLO&amp;lt;/code&amp;gt; || Igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; (sin IP flotante) || Mantener igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; salvo despliegue con alta disponibilidad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_DATOS&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar al direccionamiento del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar a la red desde la que se accede por SSH; es la única red con acceso al puerto 22&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Aplicación y verificación de cambios:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Aplicar (corta y recrea todas las reglas; las conexiones establecidas se mantienen)&lt;br /&gt;
/etc/init.d/firewall start&lt;br /&gt;
&lt;br /&gt;
# Verificar reglas cargadas y contadores&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Verificación remota mínima tras el cambio (desde RED_GESTION)&lt;br /&gt;
ssh &amp;lt;usuario&amp;gt;@&amp;lt;IP-del-servidor&amp;gt;          # el 22 debe seguir accesible&lt;br /&gt;
curl -Is http://&amp;lt;IP-del-servidor&amp;gt;/ | head -1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Aviso|'''Riesgo operativo''': editar &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; con valores erróneos y ejecutar el script '''puede dejar la máquina inaccesible por SSH''' (la política final es &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;). Realizar siempre el cambio con una consola de &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt; abierta como vía de recuperación.}}&lt;br /&gt;
&lt;br /&gt;
= 5. Diagnósticos =&lt;br /&gt;
&lt;br /&gt;
== 5.1 Comandos de diagnóstico ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Estado general de la VM desde el host de virtualización&lt;br /&gt;
virsh dominfo cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
virsh domifaddr cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Dentro de la VM — estado de servicios&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
journalctl -u apache2 -n 100 --no-pager&lt;br /&gt;
journalctl -u xibo-xmr.service -n 100 --no-pager&lt;br /&gt;
&lt;br /&gt;
# Conexión a la base de datos del CMS&lt;br /&gt;
mysql -u &amp;lt;usuario-cms&amp;gt; -p -e &amp;quot;SELECT COUNT(*) FROM display;&amp;quot; &amp;lt;bbdd-cms&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Firewall: reglas activas y contadores por regla&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Conectividad de los puertos de producto&lt;br /&gt;
ss -tlnp | grep -E ':(80|443|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Prueba del API de players (XMDS): debe responder el WSDL&lt;br /&gt;
curl -s &amp;quot;http://localhost/xmds.php?wsdl&amp;quot; | head -5&lt;br /&gt;
&lt;br /&gt;
# Comprobar identidad correcta del clon (no debe coincidir con la plantilla)&lt;br /&gt;
cat /etc/machine-id&lt;br /&gt;
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 5.2 Ficheros de log ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero / origen !! Contenido !! Rotación&lt;br /&gt;
|-&lt;br /&gt;
| Portal ''Administración &amp;gt; Avanzado &amp;gt; Log'' || Log de aplicación del CMS (registro de players, errores XMDS) || Gestionada por la tarea de mantenimiento del CMS&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/var/log/apache2/cartelia_access.log&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/apache2/cartelia_error.log&amp;lt;/code&amp;gt; (y &amp;lt;code&amp;gt;cartelia_ssl_*.log&amp;lt;/code&amp;gt; con el vhost HTTPS activo) || Accesos y errores del servidor web (portal y API XMDS de players) || logrotate estándar de apache2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u xibo-xmr.service&amp;lt;/code&amp;gt; || Log del servicio XMR || journald&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u ssh&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/fail2ban.log&amp;lt;/code&amp;gt; || Seguridad de acceso al SO || Estándar journald / logrotate&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 5.3 Errores comunes y soluciones ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Síntoma / mensaje !! Causa probable !! Solución&lt;br /&gt;
|-&lt;br /&gt;
| El portal no carga tras el clonado || La red de la VM no se personalizó o la interfaz cambió de nombre || Revisar &amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/etc/network/interfaces.d/&amp;lt;/code&amp;gt;, y el bridge asignado en libvirt&lt;br /&gt;
|-&lt;br /&gt;
| Los players no consiguen registrarse || &amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;CMS Secret Key&amp;lt;/code&amp;gt; incorrectos, o 80/443 filtrados || Verificar sección 4.2 y &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; del firewall (4.4); probar &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; al XMDS desde la red de players&lt;br /&gt;
|-&lt;br /&gt;
| Los players se registran pero no reciben órdenes push || Dirección pública de XMR errónea, proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; no operativo o &amp;lt;code&amp;gt;xibo-xmr&amp;lt;/code&amp;gt; caído || Verificar &amp;lt;code&amp;gt;ws(s)://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt; en el portal, &amp;lt;code&amp;gt;systemctl status xibo-xmr.service&amp;lt;/code&amp;gt; y el módulo &amp;lt;code&amp;gt;proxy_wstunnel&amp;lt;/code&amp;gt; de Apache; reiniciar XMR&lt;br /&gt;
|-&lt;br /&gt;
| Aviso de certificado en el navegador || Certificado de la plantilla aún instalado || Sustituir por el certificado del FQDN del entorno&lt;br /&gt;
|-&lt;br /&gt;
| Dos clones aparecen como la misma máquina en DHCP/monitorización || &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt; no regenerado || Ejecutar &amp;lt;code&amp;gt;rm -f /etc/machine-id &amp;amp;&amp;amp; systemd-machine-id-setup&amp;lt;/code&amp;gt; y reiniciar&lt;br /&gt;
|-&lt;br /&gt;
| El CMS no conecta con la base de datos tras cambiar contraseñas || Contraseña cambiada en &amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; pero no en MariaDB (o viceversa) || Sincronizar ambas (ver sección 4.1)&lt;br /&gt;
|-&lt;br /&gt;
| Sin acceso SSH tras personalizar el firewall || &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; erróneas en &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; con política final &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt; || Entrar por &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt;, corregir &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; y re-ejecutar &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| La hora de las programaciones no coincide || Zona horaria o NTP sin configurar || &amp;lt;code&amp;gt;timedatectl set-timezone Europe/Madrid&amp;lt;/code&amp;gt; y verificar &amp;lt;code&amp;gt;timedatectl status&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19181</id>
		<title>Instalacion cartelia 10</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19181"/>
		<updated>2026-07-13T09:34:04Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* 2. Arquitectura */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[:Media:cartelia-despliegue-vm-documentacion-tecnica.pdf|Instalación de Cartelia 1.0]]&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
= Introducción =&lt;br /&gt;
&lt;br /&gt;
'''Cartelia''' es el producto de cartelería digital (digital signage) de la compañía.&lt;br /&gt;
&lt;br /&gt;
El presente documento describe el procedimiento de despliegue de una nueva instancia de Cartelia partiendo de una '''máquina virtual base''' con las siguientes características:&lt;br /&gt;
&lt;br /&gt;
* Sistema operativo: '''Debian 13 (trixie)'''.&lt;br /&gt;
* Hipervisor: '''KVM/QEMU''' (gestionado mediante &amp;lt;code&amp;gt;libvirt&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;virt-manager&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Software preinstalado: '''Cartelia 1.0''', instalado en &amp;lt;code&amp;gt;/var/www/html/cartelia&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Punto de partida''': la máquina base se entrega totalmente operativa, con Cartelia instalado de forma nativa sobre Apache + PHP y la base de datos MariaDB local ya creada e inicializada.&lt;br /&gt;
&lt;br /&gt;
'''Restricciones conocidas''':&lt;br /&gt;
&lt;br /&gt;
* La plantilla base '''no debe arrancarse nunca en producción sin personalizar''': contiene identidad de máquina, claves SSH y secretos del CMS compartidos con cualquier otra copia de la plantilla.&lt;br /&gt;
* Los players (pantallas) se autentican contra el CMS mediante la clave del servidor (''CMS Key'') y la URL del CMS; cualquier cambio posterior de IP/FQDN o de claves obliga a volver a autorizar los displays.&lt;br /&gt;
&lt;br /&gt;
= Arquitectura =&lt;br /&gt;
&lt;br /&gt;
== Esquema general del despliegue ==&lt;br /&gt;
&lt;br /&gt;
[[File:Cartelia-arquitectura.png|thumb|center|900px|Esquema general del despliegue de Cartelia sobre KVM/QEMU]]&lt;br /&gt;
&lt;br /&gt;
El CMS está instalado de forma nativa sobre el sistema operativo: Apache 2 con PHP como servidor web del portal, MariaDB local como base de datos y el servicio XMR ejecutándose como unidad de systemd.&lt;br /&gt;
&lt;br /&gt;
== Flujo del proceso de despliegue ==&lt;br /&gt;
&lt;br /&gt;
# El técnico de sistemas clona la plantilla base en el host KVM/QEMU (disco &amp;lt;code&amp;gt;qcow2&amp;lt;/code&amp;gt; + definición de dominio libvirt).&lt;br /&gt;
# En el primer arranque del clon, se personaliza la identidad del sistema operativo: &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt;, hostname, claves SSH de host, red, zona horaria y credenciales locales.&lt;br /&gt;
# Se personaliza el producto Cartelia: URL pública del CMS, secretos y contraseñas de base de datos, clave del servidor (''CMS Key''), dirección pública de XMR y personalización de marca.&lt;br /&gt;
# Se verifican los servicios, la conectividad de los players y el acceso al portal de administración.&lt;br /&gt;
# La máquina queda registrada en inventario/monitorización y se entrega.&lt;br /&gt;
&lt;br /&gt;
== Componentes principales ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Componente !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Portal Cartelia''' || Interfaz de administración de contenidos, layouts, programaciones y pantallas. Servida por Apache 2 + PHP.&lt;br /&gt;
|-&lt;br /&gt;
| '''MariaDB (local)''' || Almacena la configuración, usuarios, programaciones y metadatos de medios del CMS. Servicio nativo del sistema.&lt;br /&gt;
|-&lt;br /&gt;
| '''XMR (Cartelia Message Relay)''' || Canal push que permite al CMS enviar órdenes inmediatas a los players (recarga de contenido, capturas, reinicio). Servicio &amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;. Los players se conectan por WebSocket a la ruta &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, que reenvía a &amp;lt;code&amp;gt;ws://127.0.0.1:8080&amp;lt;/code&amp;gt;; el puerto 9505/TCP queda además permitido en el firewall para el modo de publicación directa.&lt;br /&gt;
|-&lt;br /&gt;
| '''Biblioteca de medios''' || &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;: directorio donde el CMS guarda los ficheros multimedia subidos (configurado en ''Administración &amp;gt; Configuración &amp;gt; Ubicación de la biblioteca'' y alineado con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts).&lt;br /&gt;
|-&lt;br /&gt;
| '''libvirt / KVM-QEMU''' || Capa de virtualización que aloja la VM.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Dependencias e integraciones externas ==&lt;br /&gt;
&lt;br /&gt;
* '''DNS''': registro A/AAAA del FQDN del CMS (imprescindible si los players usan nombre en lugar de IP).&lt;br /&gt;
* '''NTP''': sincronización horaria; las programaciones de contenido dependen de la hora del sistema.&lt;br /&gt;
* '''SMTP''' (opcional): relay de correo para notificaciones del CMS, si el cliente lo requiere. Se configura en el portal (''Administración &amp;gt; Configuración'', pestaña '''Mantenimiento''').&lt;br /&gt;
* '''Certificados TLS''': siempre certificados válidos, nunca autofirmados. Si el cliente dispone de certificado propio para el FQDN, lo aporta él; en caso contrario se emite con Let's Encrypt.&lt;br /&gt;
&lt;br /&gt;
= 3. Personalización del sistema operativo (dentro de la VM) =&lt;br /&gt;
&lt;br /&gt;
== 3.1 Personalización de identidad y red ==&lt;br /&gt;
&lt;br /&gt;
Todos los comandos se ejecutan como &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; desde la consola de &amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; en el primer arranque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Paso 1: regenerar las claves SSH de host (las de la plantilla son comunes a todos los clones)&lt;br /&gt;
rm -f /etc/ssh/ssh_host_*&lt;br /&gt;
dpkg-reconfigure openssh-server&lt;br /&gt;
systemctl restart ssh&lt;br /&gt;
&lt;br /&gt;
# Paso 2: hostname y resolución local&lt;br /&gt;
hostnamectl set-hostname &amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
sed -i &amp;quot;s/127.0.1.1.*/127.0.1.1\t&amp;lt;nombre-del-entorno&amp;gt; &amp;lt;FQDN-del-CMS&amp;gt;/&amp;quot; /etc/hosts&lt;br /&gt;
&lt;br /&gt;
# Paso 3: configuración de red (ifupdown, /etc/network/interfaces)&lt;br /&gt;
&lt;br /&gt;
# Paso 4: zona horaria y hora (NTP)&lt;br /&gt;
vi /etc/systemd/timesyncd.conf.d/local.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Paso 5: actualización de paquetes del SO&lt;br /&gt;
apt update &amp;amp;&amp;amp; apt upgrade -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.2 Arranque del producto Cartelia ==&lt;br /&gt;
&lt;br /&gt;
El CMS ya viene instalado y operativo en la máquina base; en esta fase únicamente debe verificarse el arranque de los servicios nativos tras la personalización de red:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
&lt;br /&gt;
# Si algún servicio no arranca tras el cambio de red/hostname:&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
journalctl -u apache2 -n 50 --no-pager&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.3 Verificación de la instalación ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# El portal responde en local (la máquina base publica en HTTP; ver 4.3 para HTTPS)&lt;br /&gt;
curl -Is http://localhost/ | head -1          # esperado: HTTP/1.1 200 OK (o 302 a /login)&lt;br /&gt;
&lt;br /&gt;
# Puertos de servicio a la escucha&lt;br /&gt;
ss -tlnp | grep -E ':(80|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Resolución del FQDN desde un puesto cliente&lt;br /&gt;
getent hosts &amp;lt;FQDN-del-CMS&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Acceso final: abrir &amp;lt;code&amp;gt;http://&amp;lt;FQDN-del-CMS&amp;gt;/&amp;lt;/code&amp;gt; en el navegador y validar la pantalla de login de Cartelia (o &amp;lt;code&amp;gt;https://&amp;lt;/code&amp;gt; si se ha habilitado el vhost TLS, ver 4.3).&lt;br /&gt;
&lt;br /&gt;
= Configuración =&lt;br /&gt;
&lt;br /&gt;
== Ficheros de configuración del producto ==&lt;br /&gt;
&lt;br /&gt;
La instalación es nativa (Apache + PHP + MariaDB local); estos son los ficheros que el SAT debe revisar/personalizar en cada clon:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; del CMS''' (&amp;lt;code&amp;gt;/var/www/html/cartelia/web/settings.php&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Descripción !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbhost&amp;lt;/code&amp;gt; || Host de MariaDB (normalmente &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt;) || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$dbuser&amp;lt;/code&amp;gt; || Base de datos y usuario del CMS || No cambiar salvo política del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbpass&amp;lt;/code&amp;gt; || Contraseña del usuario del CMS en MariaDB || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SECRET_KEY&amp;lt;/code&amp;gt; || Clave secreta de la instalación (cifrado interno) || Actualmente no se regenera: se mantiene el valor de la máquina base en todos los despliegues&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''XMR''' (&amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;, unidad en &amp;lt;code&amp;gt;/etc/systemd/system/xibo-xmr.service&amp;lt;/code&amp;gt;): ejecuta &amp;lt;code&amp;gt;/var/www/html/cartelia/vendor/bin/xmr.phar&amp;lt;/code&amp;gt; con PHP como usuario &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;, con reinicio automático (&amp;lt;code&amp;gt;Restart=always&amp;lt;/code&amp;gt;). Sockets por defecto: WebSocket para players en &amp;lt;code&amp;gt;127.0.0.1:8080&amp;lt;/code&amp;gt;, expuesto a través del proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, y publicación interna del CMS en &amp;lt;code&amp;gt;tcp://127.0.0.1:50001&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Tras cualquier cambio: &amp;lt;code&amp;gt;systemctl restart xibo-xmr.service&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Apache''': la máquina base incluye dos vhosts en &amp;lt;code&amp;gt;/etc/apache2/sites-available/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; (habilitado por defecto): sirve el portal en el puerto 80. En la máquina base el &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt; es la IP de la propia máquina; en cada cliente debe actualizarse al FQDN definitivo. Incluye el proxy WebSocket de XMR (&amp;lt;code&amp;gt;ProxyPass /xmr ws://127.0.0.1:8080&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;XSendFile&amp;lt;/code&amp;gt; para la entrega de medios y una exclusión de mod_security (&amp;lt;code&amp;gt;SecRuleRemoveById 920350&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; (deshabilitado por defecto): vhost TLS preparado para clientes con FQDN y certificado. Su activación se describe en la sección 4.3.&lt;br /&gt;
&lt;br /&gt;
Validar siempre con &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; antes de &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Configuración desde el portal de administración de Cartelia ==&lt;br /&gt;
&lt;br /&gt;
Acceder con el usuario '''&amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt;''' y la contraseña estándar de la máquina base (conocida por el SAT; no se documenta aquí) y cambiar dicha contraseña de inmediato, ya que es común a todos los clones. A continuación:&lt;br /&gt;
&lt;br /&gt;
* ''Administración &amp;gt; Configuración &amp;gt; Red'': establecer la dirección del CMS (&amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt;) con el FQDN definitivo. Los players usan este valor para conectarse.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Clave secreta de CMS&amp;quot;''': es la clave que debe introducirse en cada player para autenticarlo contra el CMS. En un clon es idéntica a la de la máquina base (y, por tanto, conocida por cualquier otro despliegue), así que debe sustituirse por una clave nueva y única en cada cliente.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Ubicación de la biblioteca&amp;quot;''': verificar que mantiene el valor &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;; no cambiarlo, ya que debe coincidir con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts de Apache.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Red''' (sección XMR): establecer la dirección pública de XMR como &amp;lt;code&amp;gt;ws://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; (o &amp;lt;code&amp;gt;wss://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; si está activo el vhost HTTPS). Los players se conectan por WebSocket a través del proxy de Apache; el puerto 9505 permanece abierto en el firewall únicamente como vía alternativa de publicación directa.&lt;br /&gt;
&lt;br /&gt;
Los cambios de claves y direcciones obligan a volver a autorizar los displays que estuvieran dados de alta en la máquina base (en un despliegue nuevo no debería haber ninguno; si los hubiera, eliminarlos).&lt;br /&gt;
&lt;br /&gt;
== Configuración a nivel de sistema operativo ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elemento !! Fichero / mecanismo !! Acción&lt;br /&gt;
|-&lt;br /&gt;
| Firewall || &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt; → ejecuta &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;, parametrizado por &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Editar &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; en cada despliegue (ver 4.4): la IP local está fijada a la de la máquina base y debe cambiarse junto con la red del cliente&lt;br /&gt;
|-&lt;br /&gt;
| fail2ban || &amp;lt;code&amp;gt;/etc/fail2ban/jail.d/&amp;lt;/code&amp;gt; || Verificar jail de &amp;lt;code&amp;gt;sshd&amp;lt;/code&amp;gt; activo tras el cambio de IP&lt;br /&gt;
|-&lt;br /&gt;
| Certificado TLS / HTTPS || Vhost &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; incluido de serie (deshabilitado) || Certificado siempre válido, nunca autofirmado: lo aporta el cliente si dispone de él o se emite con Let's Encrypt (&amp;lt;code&amp;gt;certbot certonly&amp;lt;/code&amp;gt; para el FQDN; requiere el puerto 80 alcanzable desde internet y renovación automática vía timer de certbot). Instalar certificado y clave en &amp;lt;code&amp;gt;/etc/ssl/cartelia/&amp;lt;/code&amp;gt; (o apuntar las directivas &amp;lt;code&amp;gt;SSL*&amp;lt;/code&amp;gt; a &amp;lt;code&amp;gt;/etc/letsencrypt/live/&amp;lt;FQDN&amp;gt;/&amp;lt;/code&amp;gt;), ajustar &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2enmod ssl proxy_wstunnel headers&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2ensite cartelia_https&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;. Activar después la redirección HTTP→HTTPS en &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; y actualizar en el portal la CMS Address (&amp;lt;code&amp;gt;https://&amp;lt;FQDN&amp;gt;&amp;lt;/code&amp;gt;) y la dirección de XMR (&amp;lt;code&amp;gt;wss://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Rotación de logs || &amp;lt;code&amp;gt;logrotate&amp;lt;/code&amp;gt; || Verificar&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Firewall (&amp;lt;code&amp;gt;/etc/firewall/&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
El firewall se implementa con nftables mediante dos ficheros, ejecutados en el arranque por &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero !! Función&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt; || Reglas nftables: acepta 80, 443 y 9505 (XMR) hacia la IP local/flotante, 22 solo desde &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt;, checks pasivos de Zabbix (10050) desde el servidor Zabbix, ICMP y tráfico establecido; el resto de entrada se descarta (&amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Variables de entorno que parametrizan las reglas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Variables de &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; a ajustar en cada despliegue:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Valor en la máquina base !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ETH&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;ens3&amp;lt;/code&amp;gt; || Cambiar solo si la interfaz del clon tiene otro nombre (&amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; || IP de la máquina base || Cambiar siempre a la IP del cliente (debe coincidir con la configurada en la sección 3.1, paso 3)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_FLO&amp;lt;/code&amp;gt; || Igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; (sin IP flotante) || Mantener igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; salvo despliegue con alta disponibilidad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_DATOS&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar al direccionamiento del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar a la red desde la que se accede por SSH; es la única red con acceso al puerto 22&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Aplicación y verificación de cambios:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Aplicar (corta y recrea todas las reglas; las conexiones establecidas se mantienen)&lt;br /&gt;
/etc/init.d/firewall start&lt;br /&gt;
&lt;br /&gt;
# Verificar reglas cargadas y contadores&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Verificación remota mínima tras el cambio (desde RED_GESTION)&lt;br /&gt;
ssh &amp;lt;usuario&amp;gt;@&amp;lt;IP-del-servidor&amp;gt;          # el 22 debe seguir accesible&lt;br /&gt;
curl -Is http://&amp;lt;IP-del-servidor&amp;gt;/ | head -1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Aviso|'''Riesgo operativo''': editar &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; con valores erróneos y ejecutar el script '''puede dejar la máquina inaccesible por SSH''' (la política final es &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;). Realizar siempre el cambio con una consola de &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt; abierta como vía de recuperación.}}&lt;br /&gt;
&lt;br /&gt;
= 5. Diagnósticos =&lt;br /&gt;
&lt;br /&gt;
== 5.1 Comandos de diagnóstico ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Estado general de la VM desde el host de virtualización&lt;br /&gt;
virsh dominfo cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
virsh domifaddr cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Dentro de la VM — estado de servicios&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
journalctl -u apache2 -n 100 --no-pager&lt;br /&gt;
journalctl -u xibo-xmr.service -n 100 --no-pager&lt;br /&gt;
&lt;br /&gt;
# Conexión a la base de datos del CMS&lt;br /&gt;
mysql -u &amp;lt;usuario-cms&amp;gt; -p -e &amp;quot;SELECT COUNT(*) FROM display;&amp;quot; &amp;lt;bbdd-cms&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Firewall: reglas activas y contadores por regla&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Conectividad de los puertos de producto&lt;br /&gt;
ss -tlnp | grep -E ':(80|443|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Prueba del API de players (XMDS): debe responder el WSDL&lt;br /&gt;
curl -s &amp;quot;http://localhost/xmds.php?wsdl&amp;quot; | head -5&lt;br /&gt;
&lt;br /&gt;
# Comprobar identidad correcta del clon (no debe coincidir con la plantilla)&lt;br /&gt;
cat /etc/machine-id&lt;br /&gt;
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 5.2 Ficheros de log ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero / origen !! Contenido !! Rotación&lt;br /&gt;
|-&lt;br /&gt;
| Portal ''Administración &amp;gt; Avanzado &amp;gt; Log'' || Log de aplicación del CMS (registro de players, errores XMDS) || Gestionada por la tarea de mantenimiento del CMS&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/var/log/apache2/cartelia_access.log&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/apache2/cartelia_error.log&amp;lt;/code&amp;gt; (y &amp;lt;code&amp;gt;cartelia_ssl_*.log&amp;lt;/code&amp;gt; con el vhost HTTPS activo) || Accesos y errores del servidor web (portal y API XMDS de players) || logrotate estándar de apache2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u xibo-xmr.service&amp;lt;/code&amp;gt; || Log del servicio XMR || journald&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u ssh&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/fail2ban.log&amp;lt;/code&amp;gt; || Seguridad de acceso al SO || Estándar journald / logrotate&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 5.3 Errores comunes y soluciones ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Síntoma / mensaje !! Causa probable !! Solución&lt;br /&gt;
|-&lt;br /&gt;
| El portal no carga tras el clonado || La red de la VM no se personalizó o la interfaz cambió de nombre || Revisar &amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/etc/network/interfaces.d/&amp;lt;/code&amp;gt;, y el bridge asignado en libvirt&lt;br /&gt;
|-&lt;br /&gt;
| Los players no consiguen registrarse || &amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;CMS Secret Key&amp;lt;/code&amp;gt; incorrectos, o 80/443 filtrados || Verificar sección 4.2 y &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; del firewall (4.4); probar &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; al XMDS desde la red de players&lt;br /&gt;
|-&lt;br /&gt;
| Los players se registran pero no reciben órdenes push || Dirección pública de XMR errónea, proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; no operativo o &amp;lt;code&amp;gt;xibo-xmr&amp;lt;/code&amp;gt; caído || Verificar &amp;lt;code&amp;gt;ws(s)://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt; en el portal, &amp;lt;code&amp;gt;systemctl status xibo-xmr.service&amp;lt;/code&amp;gt; y el módulo &amp;lt;code&amp;gt;proxy_wstunnel&amp;lt;/code&amp;gt; de Apache; reiniciar XMR&lt;br /&gt;
|-&lt;br /&gt;
| Aviso de certificado en el navegador || Certificado de la plantilla aún instalado || Sustituir por el certificado del FQDN del entorno&lt;br /&gt;
|-&lt;br /&gt;
| Dos clones aparecen como la misma máquina en DHCP/monitorización || &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt; no regenerado || Ejecutar &amp;lt;code&amp;gt;rm -f /etc/machine-id &amp;amp;&amp;amp; systemd-machine-id-setup&amp;lt;/code&amp;gt; y reiniciar&lt;br /&gt;
|-&lt;br /&gt;
| El CMS no conecta con la base de datos tras cambiar contraseñas || Contraseña cambiada en &amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; pero no en MariaDB (o viceversa) || Sincronizar ambas (ver sección 4.1)&lt;br /&gt;
|-&lt;br /&gt;
| Sin acceso SSH tras personalizar el firewall || &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; erróneas en &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; con política final &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt; || Entrar por &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt;, corregir &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; y re-ejecutar &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| La hora de las programaciones no coincide || Zona horaria o NTP sin configurar || &amp;lt;code&amp;gt;timedatectl set-timezone Europe/Madrid&amp;lt;/code&amp;gt; y verificar &amp;lt;code&amp;gt;timedatectl status&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19180</id>
		<title>Instalacion cartelia 10</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19180"/>
		<updated>2026-07-13T09:33:47Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* 1. Introducción */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[:Media:cartelia-despliegue-vm-documentacion-tecnica.pdf|Instalación de Cartelia 1.0]]&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
= Introducción =&lt;br /&gt;
&lt;br /&gt;
'''Cartelia''' es el producto de cartelería digital (digital signage) de la compañía.&lt;br /&gt;
&lt;br /&gt;
El presente documento describe el procedimiento de despliegue de una nueva instancia de Cartelia partiendo de una '''máquina virtual base''' con las siguientes características:&lt;br /&gt;
&lt;br /&gt;
* Sistema operativo: '''Debian 13 (trixie)'''.&lt;br /&gt;
* Hipervisor: '''KVM/QEMU''' (gestionado mediante &amp;lt;code&amp;gt;libvirt&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;virt-manager&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Software preinstalado: '''Cartelia 1.0''', instalado en &amp;lt;code&amp;gt;/var/www/html/cartelia&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Punto de partida''': la máquina base se entrega totalmente operativa, con Cartelia instalado de forma nativa sobre Apache + PHP y la base de datos MariaDB local ya creada e inicializada.&lt;br /&gt;
&lt;br /&gt;
'''Restricciones conocidas''':&lt;br /&gt;
&lt;br /&gt;
* La plantilla base '''no debe arrancarse nunca en producción sin personalizar''': contiene identidad de máquina, claves SSH y secretos del CMS compartidos con cualquier otra copia de la plantilla.&lt;br /&gt;
* Los players (pantallas) se autentican contra el CMS mediante la clave del servidor (''CMS Key'') y la URL del CMS; cualquier cambio posterior de IP/FQDN o de claves obliga a volver a autorizar los displays.&lt;br /&gt;
&lt;br /&gt;
= 2. Arquitectura =&lt;br /&gt;
&lt;br /&gt;
== 2.1 Esquema general del despliegue ==&lt;br /&gt;
&lt;br /&gt;
[[File:Cartelia-arquitectura.png|thumb|center|900px|Esquema general del despliegue de Cartelia sobre KVM/QEMU]]&lt;br /&gt;
&lt;br /&gt;
El CMS está instalado de forma nativa sobre el sistema operativo: Apache 2 con PHP como servidor web del portal, MariaDB local como base de datos y el servicio XMR ejecutándose como unidad de systemd.&lt;br /&gt;
&lt;br /&gt;
== 2.2 Flujo del proceso de despliegue ==&lt;br /&gt;
&lt;br /&gt;
# El técnico de sistemas clona la plantilla base en el host KVM/QEMU (disco &amp;lt;code&amp;gt;qcow2&amp;lt;/code&amp;gt; + definición de dominio libvirt).&lt;br /&gt;
# En el primer arranque del clon, se personaliza la identidad del sistema operativo: &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt;, hostname, claves SSH de host, red, zona horaria y credenciales locales.&lt;br /&gt;
# Se personaliza el producto Cartelia: URL pública del CMS, secretos y contraseñas de base de datos, clave del servidor (''CMS Key''), dirección pública de XMR y personalización de marca.&lt;br /&gt;
# Se verifican los servicios, la conectividad de los players y el acceso al portal de administración.&lt;br /&gt;
# La máquina queda registrada en inventario/monitorización y se entrega.&lt;br /&gt;
&lt;br /&gt;
== 2.3 Componentes principales ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Componente !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Portal Cartelia''' || Interfaz de administración de contenidos, layouts, programaciones y pantallas. Servida por Apache 2 + PHP.&lt;br /&gt;
|-&lt;br /&gt;
| '''MariaDB (local)''' || Almacena la configuración, usuarios, programaciones y metadatos de medios del CMS. Servicio nativo del sistema.&lt;br /&gt;
|-&lt;br /&gt;
| '''XMR (Cartelia Message Relay)''' || Canal push que permite al CMS enviar órdenes inmediatas a los players (recarga de contenido, capturas, reinicio). Servicio &amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;. Los players se conectan por WebSocket a la ruta &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, que reenvía a &amp;lt;code&amp;gt;ws://127.0.0.1:8080&amp;lt;/code&amp;gt;; el puerto 9505/TCP queda además permitido en el firewall para el modo de publicación directa.&lt;br /&gt;
|-&lt;br /&gt;
| '''Biblioteca de medios''' || &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;: directorio donde el CMS guarda los ficheros multimedia subidos (configurado en ''Administración &amp;gt; Configuración &amp;gt; Ubicación de la biblioteca'' y alineado con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts).&lt;br /&gt;
|-&lt;br /&gt;
| '''libvirt / KVM-QEMU''' || Capa de virtualización que aloja la VM.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.4 Dependencias e integraciones externas ==&lt;br /&gt;
&lt;br /&gt;
* '''DNS''': registro A/AAAA del FQDN del CMS (imprescindible si los players usan nombre en lugar de IP).&lt;br /&gt;
* '''NTP''': sincronización horaria; las programaciones de contenido dependen de la hora del sistema.&lt;br /&gt;
* '''SMTP''' (opcional): relay de correo para notificaciones del CMS, si el cliente lo requiere. Se configura en el portal (''Administración &amp;gt; Configuración'', pestaña '''Mantenimiento''').&lt;br /&gt;
* '''Certificados TLS''': siempre certificados válidos, nunca autofirmados. Si el cliente dispone de certificado propio para el FQDN, lo aporta él; en caso contrario se emite con Let's Encrypt.&lt;br /&gt;
&lt;br /&gt;
= 3. Personalización del sistema operativo (dentro de la VM) =&lt;br /&gt;
&lt;br /&gt;
== 3.1 Personalización de identidad y red ==&lt;br /&gt;
&lt;br /&gt;
Todos los comandos se ejecutan como &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; desde la consola de &amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; en el primer arranque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Paso 1: regenerar las claves SSH de host (las de la plantilla son comunes a todos los clones)&lt;br /&gt;
rm -f /etc/ssh/ssh_host_*&lt;br /&gt;
dpkg-reconfigure openssh-server&lt;br /&gt;
systemctl restart ssh&lt;br /&gt;
&lt;br /&gt;
# Paso 2: hostname y resolución local&lt;br /&gt;
hostnamectl set-hostname &amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
sed -i &amp;quot;s/127.0.1.1.*/127.0.1.1\t&amp;lt;nombre-del-entorno&amp;gt; &amp;lt;FQDN-del-CMS&amp;gt;/&amp;quot; /etc/hosts&lt;br /&gt;
&lt;br /&gt;
# Paso 3: configuración de red (ifupdown, /etc/network/interfaces)&lt;br /&gt;
&lt;br /&gt;
# Paso 4: zona horaria y hora (NTP)&lt;br /&gt;
vi /etc/systemd/timesyncd.conf.d/local.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Paso 5: actualización de paquetes del SO&lt;br /&gt;
apt update &amp;amp;&amp;amp; apt upgrade -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.2 Arranque del producto Cartelia ==&lt;br /&gt;
&lt;br /&gt;
El CMS ya viene instalado y operativo en la máquina base; en esta fase únicamente debe verificarse el arranque de los servicios nativos tras la personalización de red:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
&lt;br /&gt;
# Si algún servicio no arranca tras el cambio de red/hostname:&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
journalctl -u apache2 -n 50 --no-pager&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.3 Verificación de la instalación ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# El portal responde en local (la máquina base publica en HTTP; ver 4.3 para HTTPS)&lt;br /&gt;
curl -Is http://localhost/ | head -1          # esperado: HTTP/1.1 200 OK (o 302 a /login)&lt;br /&gt;
&lt;br /&gt;
# Puertos de servicio a la escucha&lt;br /&gt;
ss -tlnp | grep -E ':(80|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Resolución del FQDN desde un puesto cliente&lt;br /&gt;
getent hosts &amp;lt;FQDN-del-CMS&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Acceso final: abrir &amp;lt;code&amp;gt;http://&amp;lt;FQDN-del-CMS&amp;gt;/&amp;lt;/code&amp;gt; en el navegador y validar la pantalla de login de Cartelia (o &amp;lt;code&amp;gt;https://&amp;lt;/code&amp;gt; si se ha habilitado el vhost TLS, ver 4.3).&lt;br /&gt;
&lt;br /&gt;
= Configuración =&lt;br /&gt;
&lt;br /&gt;
== Ficheros de configuración del producto ==&lt;br /&gt;
&lt;br /&gt;
La instalación es nativa (Apache + PHP + MariaDB local); estos son los ficheros que el SAT debe revisar/personalizar en cada clon:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; del CMS''' (&amp;lt;code&amp;gt;/var/www/html/cartelia/web/settings.php&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Descripción !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbhost&amp;lt;/code&amp;gt; || Host de MariaDB (normalmente &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt;) || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$dbuser&amp;lt;/code&amp;gt; || Base de datos y usuario del CMS || No cambiar salvo política del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbpass&amp;lt;/code&amp;gt; || Contraseña del usuario del CMS en MariaDB || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SECRET_KEY&amp;lt;/code&amp;gt; || Clave secreta de la instalación (cifrado interno) || Actualmente no se regenera: se mantiene el valor de la máquina base en todos los despliegues&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''XMR''' (&amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;, unidad en &amp;lt;code&amp;gt;/etc/systemd/system/xibo-xmr.service&amp;lt;/code&amp;gt;): ejecuta &amp;lt;code&amp;gt;/var/www/html/cartelia/vendor/bin/xmr.phar&amp;lt;/code&amp;gt; con PHP como usuario &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;, con reinicio automático (&amp;lt;code&amp;gt;Restart=always&amp;lt;/code&amp;gt;). Sockets por defecto: WebSocket para players en &amp;lt;code&amp;gt;127.0.0.1:8080&amp;lt;/code&amp;gt;, expuesto a través del proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, y publicación interna del CMS en &amp;lt;code&amp;gt;tcp://127.0.0.1:50001&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Tras cualquier cambio: &amp;lt;code&amp;gt;systemctl restart xibo-xmr.service&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Apache''': la máquina base incluye dos vhosts en &amp;lt;code&amp;gt;/etc/apache2/sites-available/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; (habilitado por defecto): sirve el portal en el puerto 80. En la máquina base el &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt; es la IP de la propia máquina; en cada cliente debe actualizarse al FQDN definitivo. Incluye el proxy WebSocket de XMR (&amp;lt;code&amp;gt;ProxyPass /xmr ws://127.0.0.1:8080&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;XSendFile&amp;lt;/code&amp;gt; para la entrega de medios y una exclusión de mod_security (&amp;lt;code&amp;gt;SecRuleRemoveById 920350&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; (deshabilitado por defecto): vhost TLS preparado para clientes con FQDN y certificado. Su activación se describe en la sección 4.3.&lt;br /&gt;
&lt;br /&gt;
Validar siempre con &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; antes de &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Configuración desde el portal de administración de Cartelia ==&lt;br /&gt;
&lt;br /&gt;
Acceder con el usuario '''&amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt;''' y la contraseña estándar de la máquina base (conocida por el SAT; no se documenta aquí) y cambiar dicha contraseña de inmediato, ya que es común a todos los clones. A continuación:&lt;br /&gt;
&lt;br /&gt;
* ''Administración &amp;gt; Configuración &amp;gt; Red'': establecer la dirección del CMS (&amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt;) con el FQDN definitivo. Los players usan este valor para conectarse.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Clave secreta de CMS&amp;quot;''': es la clave que debe introducirse en cada player para autenticarlo contra el CMS. En un clon es idéntica a la de la máquina base (y, por tanto, conocida por cualquier otro despliegue), así que debe sustituirse por una clave nueva y única en cada cliente.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Ubicación de la biblioteca&amp;quot;''': verificar que mantiene el valor &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;; no cambiarlo, ya que debe coincidir con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts de Apache.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Red''' (sección XMR): establecer la dirección pública de XMR como &amp;lt;code&amp;gt;ws://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; (o &amp;lt;code&amp;gt;wss://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; si está activo el vhost HTTPS). Los players se conectan por WebSocket a través del proxy de Apache; el puerto 9505 permanece abierto en el firewall únicamente como vía alternativa de publicación directa.&lt;br /&gt;
&lt;br /&gt;
Los cambios de claves y direcciones obligan a volver a autorizar los displays que estuvieran dados de alta en la máquina base (en un despliegue nuevo no debería haber ninguno; si los hubiera, eliminarlos).&lt;br /&gt;
&lt;br /&gt;
== Configuración a nivel de sistema operativo ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elemento !! Fichero / mecanismo !! Acción&lt;br /&gt;
|-&lt;br /&gt;
| Firewall || &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt; → ejecuta &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;, parametrizado por &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Editar &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; en cada despliegue (ver 4.4): la IP local está fijada a la de la máquina base y debe cambiarse junto con la red del cliente&lt;br /&gt;
|-&lt;br /&gt;
| fail2ban || &amp;lt;code&amp;gt;/etc/fail2ban/jail.d/&amp;lt;/code&amp;gt; || Verificar jail de &amp;lt;code&amp;gt;sshd&amp;lt;/code&amp;gt; activo tras el cambio de IP&lt;br /&gt;
|-&lt;br /&gt;
| Certificado TLS / HTTPS || Vhost &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; incluido de serie (deshabilitado) || Certificado siempre válido, nunca autofirmado: lo aporta el cliente si dispone de él o se emite con Let's Encrypt (&amp;lt;code&amp;gt;certbot certonly&amp;lt;/code&amp;gt; para el FQDN; requiere el puerto 80 alcanzable desde internet y renovación automática vía timer de certbot). Instalar certificado y clave en &amp;lt;code&amp;gt;/etc/ssl/cartelia/&amp;lt;/code&amp;gt; (o apuntar las directivas &amp;lt;code&amp;gt;SSL*&amp;lt;/code&amp;gt; a &amp;lt;code&amp;gt;/etc/letsencrypt/live/&amp;lt;FQDN&amp;gt;/&amp;lt;/code&amp;gt;), ajustar &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2enmod ssl proxy_wstunnel headers&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2ensite cartelia_https&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;. Activar después la redirección HTTP→HTTPS en &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; y actualizar en el portal la CMS Address (&amp;lt;code&amp;gt;https://&amp;lt;FQDN&amp;gt;&amp;lt;/code&amp;gt;) y la dirección de XMR (&amp;lt;code&amp;gt;wss://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Rotación de logs || &amp;lt;code&amp;gt;logrotate&amp;lt;/code&amp;gt; || Verificar&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Firewall (&amp;lt;code&amp;gt;/etc/firewall/&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
El firewall se implementa con nftables mediante dos ficheros, ejecutados en el arranque por &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero !! Función&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt; || Reglas nftables: acepta 80, 443 y 9505 (XMR) hacia la IP local/flotante, 22 solo desde &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt;, checks pasivos de Zabbix (10050) desde el servidor Zabbix, ICMP y tráfico establecido; el resto de entrada se descarta (&amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Variables de entorno que parametrizan las reglas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Variables de &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; a ajustar en cada despliegue:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Valor en la máquina base !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ETH&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;ens3&amp;lt;/code&amp;gt; || Cambiar solo si la interfaz del clon tiene otro nombre (&amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; || IP de la máquina base || Cambiar siempre a la IP del cliente (debe coincidir con la configurada en la sección 3.1, paso 3)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_FLO&amp;lt;/code&amp;gt; || Igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; (sin IP flotante) || Mantener igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; salvo despliegue con alta disponibilidad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_DATOS&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar al direccionamiento del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar a la red desde la que se accede por SSH; es la única red con acceso al puerto 22&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Aplicación y verificación de cambios:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Aplicar (corta y recrea todas las reglas; las conexiones establecidas se mantienen)&lt;br /&gt;
/etc/init.d/firewall start&lt;br /&gt;
&lt;br /&gt;
# Verificar reglas cargadas y contadores&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Verificación remota mínima tras el cambio (desde RED_GESTION)&lt;br /&gt;
ssh &amp;lt;usuario&amp;gt;@&amp;lt;IP-del-servidor&amp;gt;          # el 22 debe seguir accesible&lt;br /&gt;
curl -Is http://&amp;lt;IP-del-servidor&amp;gt;/ | head -1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Aviso|'''Riesgo operativo''': editar &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; con valores erróneos y ejecutar el script '''puede dejar la máquina inaccesible por SSH''' (la política final es &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;). Realizar siempre el cambio con una consola de &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt; abierta como vía de recuperación.}}&lt;br /&gt;
&lt;br /&gt;
= 5. Diagnósticos =&lt;br /&gt;
&lt;br /&gt;
== 5.1 Comandos de diagnóstico ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Estado general de la VM desde el host de virtualización&lt;br /&gt;
virsh dominfo cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
virsh domifaddr cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Dentro de la VM — estado de servicios&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
journalctl -u apache2 -n 100 --no-pager&lt;br /&gt;
journalctl -u xibo-xmr.service -n 100 --no-pager&lt;br /&gt;
&lt;br /&gt;
# Conexión a la base de datos del CMS&lt;br /&gt;
mysql -u &amp;lt;usuario-cms&amp;gt; -p -e &amp;quot;SELECT COUNT(*) FROM display;&amp;quot; &amp;lt;bbdd-cms&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Firewall: reglas activas y contadores por regla&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Conectividad de los puertos de producto&lt;br /&gt;
ss -tlnp | grep -E ':(80|443|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Prueba del API de players (XMDS): debe responder el WSDL&lt;br /&gt;
curl -s &amp;quot;http://localhost/xmds.php?wsdl&amp;quot; | head -5&lt;br /&gt;
&lt;br /&gt;
# Comprobar identidad correcta del clon (no debe coincidir con la plantilla)&lt;br /&gt;
cat /etc/machine-id&lt;br /&gt;
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 5.2 Ficheros de log ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero / origen !! Contenido !! Rotación&lt;br /&gt;
|-&lt;br /&gt;
| Portal ''Administración &amp;gt; Avanzado &amp;gt; Log'' || Log de aplicación del CMS (registro de players, errores XMDS) || Gestionada por la tarea de mantenimiento del CMS&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/var/log/apache2/cartelia_access.log&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/apache2/cartelia_error.log&amp;lt;/code&amp;gt; (y &amp;lt;code&amp;gt;cartelia_ssl_*.log&amp;lt;/code&amp;gt; con el vhost HTTPS activo) || Accesos y errores del servidor web (portal y API XMDS de players) || logrotate estándar de apache2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u xibo-xmr.service&amp;lt;/code&amp;gt; || Log del servicio XMR || journald&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u ssh&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/fail2ban.log&amp;lt;/code&amp;gt; || Seguridad de acceso al SO || Estándar journald / logrotate&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 5.3 Errores comunes y soluciones ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Síntoma / mensaje !! Causa probable !! Solución&lt;br /&gt;
|-&lt;br /&gt;
| El portal no carga tras el clonado || La red de la VM no se personalizó o la interfaz cambió de nombre || Revisar &amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/etc/network/interfaces.d/&amp;lt;/code&amp;gt;, y el bridge asignado en libvirt&lt;br /&gt;
|-&lt;br /&gt;
| Los players no consiguen registrarse || &amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;CMS Secret Key&amp;lt;/code&amp;gt; incorrectos, o 80/443 filtrados || Verificar sección 4.2 y &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; del firewall (4.4); probar &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; al XMDS desde la red de players&lt;br /&gt;
|-&lt;br /&gt;
| Los players se registran pero no reciben órdenes push || Dirección pública de XMR errónea, proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; no operativo o &amp;lt;code&amp;gt;xibo-xmr&amp;lt;/code&amp;gt; caído || Verificar &amp;lt;code&amp;gt;ws(s)://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt; en el portal, &amp;lt;code&amp;gt;systemctl status xibo-xmr.service&amp;lt;/code&amp;gt; y el módulo &amp;lt;code&amp;gt;proxy_wstunnel&amp;lt;/code&amp;gt; de Apache; reiniciar XMR&lt;br /&gt;
|-&lt;br /&gt;
| Aviso de certificado en el navegador || Certificado de la plantilla aún instalado || Sustituir por el certificado del FQDN del entorno&lt;br /&gt;
|-&lt;br /&gt;
| Dos clones aparecen como la misma máquina en DHCP/monitorización || &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt; no regenerado || Ejecutar &amp;lt;code&amp;gt;rm -f /etc/machine-id &amp;amp;&amp;amp; systemd-machine-id-setup&amp;lt;/code&amp;gt; y reiniciar&lt;br /&gt;
|-&lt;br /&gt;
| El CMS no conecta con la base de datos tras cambiar contraseñas || Contraseña cambiada en &amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; pero no en MariaDB (o viceversa) || Sincronizar ambas (ver sección 4.1)&lt;br /&gt;
|-&lt;br /&gt;
| Sin acceso SSH tras personalizar el firewall || &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; erróneas en &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; con política final &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt; || Entrar por &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt;, corregir &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; y re-ejecutar &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| La hora de las programaciones no coincide || Zona horaria o NTP sin configurar || &amp;lt;code&amp;gt;timedatectl set-timezone Europe/Madrid&amp;lt;/code&amp;gt; y verificar &amp;lt;code&amp;gt;timedatectl status&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19179</id>
		<title>Instalacion cartelia 10</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19179"/>
		<updated>2026-07-13T09:33:36Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* 4. Configuración */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[:Media:cartelia-despliegue-vm-documentacion-tecnica.pdf|Instalación de Cartelia 1.0]]&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
= 1. Introducción =&lt;br /&gt;
&lt;br /&gt;
'''Cartelia''' es el producto de cartelería digital (digital signage) de la compañía.&lt;br /&gt;
&lt;br /&gt;
El presente documento describe el procedimiento de despliegue de una nueva instancia de Cartelia partiendo de una '''máquina virtual base''' con las siguientes características:&lt;br /&gt;
&lt;br /&gt;
* Sistema operativo: '''Debian 13 (trixie)'''.&lt;br /&gt;
* Hipervisor: '''KVM/QEMU''' (gestionado mediante &amp;lt;code&amp;gt;libvirt&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;virt-manager&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Software preinstalado: '''Cartelia 1.0''', instalado en &amp;lt;code&amp;gt;/var/www/html/cartelia&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Punto de partida''': la máquina base se entrega totalmente operativa, con Cartelia instalado de forma nativa sobre Apache + PHP y la base de datos MariaDB local ya creada e inicializada.&lt;br /&gt;
&lt;br /&gt;
'''Restricciones conocidas''':&lt;br /&gt;
&lt;br /&gt;
* La plantilla base '''no debe arrancarse nunca en producción sin personalizar''': contiene identidad de máquina, claves SSH y secretos del CMS compartidos con cualquier otra copia de la plantilla.&lt;br /&gt;
* Los players (pantallas) se autentican contra el CMS mediante la clave del servidor (''CMS Key'') y la URL del CMS; cualquier cambio posterior de IP/FQDN o de claves obliga a volver a autorizar los displays.&lt;br /&gt;
&lt;br /&gt;
= 2. Arquitectura =&lt;br /&gt;
&lt;br /&gt;
== 2.1 Esquema general del despliegue ==&lt;br /&gt;
&lt;br /&gt;
[[File:Cartelia-arquitectura.png|thumb|center|900px|Esquema general del despliegue de Cartelia sobre KVM/QEMU]]&lt;br /&gt;
&lt;br /&gt;
El CMS está instalado de forma nativa sobre el sistema operativo: Apache 2 con PHP como servidor web del portal, MariaDB local como base de datos y el servicio XMR ejecutándose como unidad de systemd.&lt;br /&gt;
&lt;br /&gt;
== 2.2 Flujo del proceso de despliegue ==&lt;br /&gt;
&lt;br /&gt;
# El técnico de sistemas clona la plantilla base en el host KVM/QEMU (disco &amp;lt;code&amp;gt;qcow2&amp;lt;/code&amp;gt; + definición de dominio libvirt).&lt;br /&gt;
# En el primer arranque del clon, se personaliza la identidad del sistema operativo: &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt;, hostname, claves SSH de host, red, zona horaria y credenciales locales.&lt;br /&gt;
# Se personaliza el producto Cartelia: URL pública del CMS, secretos y contraseñas de base de datos, clave del servidor (''CMS Key''), dirección pública de XMR y personalización de marca.&lt;br /&gt;
# Se verifican los servicios, la conectividad de los players y el acceso al portal de administración.&lt;br /&gt;
# La máquina queda registrada en inventario/monitorización y se entrega.&lt;br /&gt;
&lt;br /&gt;
== 2.3 Componentes principales ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Componente !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Portal Cartelia''' || Interfaz de administración de contenidos, layouts, programaciones y pantallas. Servida por Apache 2 + PHP.&lt;br /&gt;
|-&lt;br /&gt;
| '''MariaDB (local)''' || Almacena la configuración, usuarios, programaciones y metadatos de medios del CMS. Servicio nativo del sistema.&lt;br /&gt;
|-&lt;br /&gt;
| '''XMR (Cartelia Message Relay)''' || Canal push que permite al CMS enviar órdenes inmediatas a los players (recarga de contenido, capturas, reinicio). Servicio &amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;. Los players se conectan por WebSocket a la ruta &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, que reenvía a &amp;lt;code&amp;gt;ws://127.0.0.1:8080&amp;lt;/code&amp;gt;; el puerto 9505/TCP queda además permitido en el firewall para el modo de publicación directa.&lt;br /&gt;
|-&lt;br /&gt;
| '''Biblioteca de medios''' || &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;: directorio donde el CMS guarda los ficheros multimedia subidos (configurado en ''Administración &amp;gt; Configuración &amp;gt; Ubicación de la biblioteca'' y alineado con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts).&lt;br /&gt;
|-&lt;br /&gt;
| '''libvirt / KVM-QEMU''' || Capa de virtualización que aloja la VM.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.4 Dependencias e integraciones externas ==&lt;br /&gt;
&lt;br /&gt;
* '''DNS''': registro A/AAAA del FQDN del CMS (imprescindible si los players usan nombre en lugar de IP).&lt;br /&gt;
* '''NTP''': sincronización horaria; las programaciones de contenido dependen de la hora del sistema.&lt;br /&gt;
* '''SMTP''' (opcional): relay de correo para notificaciones del CMS, si el cliente lo requiere. Se configura en el portal (''Administración &amp;gt; Configuración'', pestaña '''Mantenimiento''').&lt;br /&gt;
* '''Certificados TLS''': siempre certificados válidos, nunca autofirmados. Si el cliente dispone de certificado propio para el FQDN, lo aporta él; en caso contrario se emite con Let's Encrypt.&lt;br /&gt;
&lt;br /&gt;
= 3. Personalización del sistema operativo (dentro de la VM) =&lt;br /&gt;
&lt;br /&gt;
== 3.1 Personalización de identidad y red ==&lt;br /&gt;
&lt;br /&gt;
Todos los comandos se ejecutan como &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; desde la consola de &amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; en el primer arranque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Paso 1: regenerar las claves SSH de host (las de la plantilla son comunes a todos los clones)&lt;br /&gt;
rm -f /etc/ssh/ssh_host_*&lt;br /&gt;
dpkg-reconfigure openssh-server&lt;br /&gt;
systemctl restart ssh&lt;br /&gt;
&lt;br /&gt;
# Paso 2: hostname y resolución local&lt;br /&gt;
hostnamectl set-hostname &amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
sed -i &amp;quot;s/127.0.1.1.*/127.0.1.1\t&amp;lt;nombre-del-entorno&amp;gt; &amp;lt;FQDN-del-CMS&amp;gt;/&amp;quot; /etc/hosts&lt;br /&gt;
&lt;br /&gt;
# Paso 3: configuración de red (ifupdown, /etc/network/interfaces)&lt;br /&gt;
&lt;br /&gt;
# Paso 4: zona horaria y hora (NTP)&lt;br /&gt;
vi /etc/systemd/timesyncd.conf.d/local.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Paso 5: actualización de paquetes del SO&lt;br /&gt;
apt update &amp;amp;&amp;amp; apt upgrade -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.2 Arranque del producto Cartelia ==&lt;br /&gt;
&lt;br /&gt;
El CMS ya viene instalado y operativo en la máquina base; en esta fase únicamente debe verificarse el arranque de los servicios nativos tras la personalización de red:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
&lt;br /&gt;
# Si algún servicio no arranca tras el cambio de red/hostname:&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
journalctl -u apache2 -n 50 --no-pager&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.3 Verificación de la instalación ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# El portal responde en local (la máquina base publica en HTTP; ver 4.3 para HTTPS)&lt;br /&gt;
curl -Is http://localhost/ | head -1          # esperado: HTTP/1.1 200 OK (o 302 a /login)&lt;br /&gt;
&lt;br /&gt;
# Puertos de servicio a la escucha&lt;br /&gt;
ss -tlnp | grep -E ':(80|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Resolución del FQDN desde un puesto cliente&lt;br /&gt;
getent hosts &amp;lt;FQDN-del-CMS&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Acceso final: abrir &amp;lt;code&amp;gt;http://&amp;lt;FQDN-del-CMS&amp;gt;/&amp;lt;/code&amp;gt; en el navegador y validar la pantalla de login de Cartelia (o &amp;lt;code&amp;gt;https://&amp;lt;/code&amp;gt; si se ha habilitado el vhost TLS, ver 4.3).&lt;br /&gt;
&lt;br /&gt;
= Configuración =&lt;br /&gt;
&lt;br /&gt;
== Ficheros de configuración del producto ==&lt;br /&gt;
&lt;br /&gt;
La instalación es nativa (Apache + PHP + MariaDB local); estos son los ficheros que el SAT debe revisar/personalizar en cada clon:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; del CMS''' (&amp;lt;code&amp;gt;/var/www/html/cartelia/web/settings.php&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Descripción !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbhost&amp;lt;/code&amp;gt; || Host de MariaDB (normalmente &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt;) || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$dbuser&amp;lt;/code&amp;gt; || Base de datos y usuario del CMS || No cambiar salvo política del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbpass&amp;lt;/code&amp;gt; || Contraseña del usuario del CMS en MariaDB || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SECRET_KEY&amp;lt;/code&amp;gt; || Clave secreta de la instalación (cifrado interno) || Actualmente no se regenera: se mantiene el valor de la máquina base en todos los despliegues&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''XMR''' (&amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;, unidad en &amp;lt;code&amp;gt;/etc/systemd/system/xibo-xmr.service&amp;lt;/code&amp;gt;): ejecuta &amp;lt;code&amp;gt;/var/www/html/cartelia/vendor/bin/xmr.phar&amp;lt;/code&amp;gt; con PHP como usuario &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;, con reinicio automático (&amp;lt;code&amp;gt;Restart=always&amp;lt;/code&amp;gt;). Sockets por defecto: WebSocket para players en &amp;lt;code&amp;gt;127.0.0.1:8080&amp;lt;/code&amp;gt;, expuesto a través del proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, y publicación interna del CMS en &amp;lt;code&amp;gt;tcp://127.0.0.1:50001&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Tras cualquier cambio: &amp;lt;code&amp;gt;systemctl restart xibo-xmr.service&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Apache''': la máquina base incluye dos vhosts en &amp;lt;code&amp;gt;/etc/apache2/sites-available/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; (habilitado por defecto): sirve el portal en el puerto 80. En la máquina base el &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt; es la IP de la propia máquina; en cada cliente debe actualizarse al FQDN definitivo. Incluye el proxy WebSocket de XMR (&amp;lt;code&amp;gt;ProxyPass /xmr ws://127.0.0.1:8080&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;XSendFile&amp;lt;/code&amp;gt; para la entrega de medios y una exclusión de mod_security (&amp;lt;code&amp;gt;SecRuleRemoveById 920350&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; (deshabilitado por defecto): vhost TLS preparado para clientes con FQDN y certificado. Su activación se describe en la sección 4.3.&lt;br /&gt;
&lt;br /&gt;
Validar siempre con &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; antes de &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Configuración desde el portal de administración de Cartelia ==&lt;br /&gt;
&lt;br /&gt;
Acceder con el usuario '''&amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt;''' y la contraseña estándar de la máquina base (conocida por el SAT; no se documenta aquí) y cambiar dicha contraseña de inmediato, ya que es común a todos los clones. A continuación:&lt;br /&gt;
&lt;br /&gt;
* ''Administración &amp;gt; Configuración &amp;gt; Red'': establecer la dirección del CMS (&amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt;) con el FQDN definitivo. Los players usan este valor para conectarse.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Clave secreta de CMS&amp;quot;''': es la clave que debe introducirse en cada player para autenticarlo contra el CMS. En un clon es idéntica a la de la máquina base (y, por tanto, conocida por cualquier otro despliegue), así que debe sustituirse por una clave nueva y única en cada cliente.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Ubicación de la biblioteca&amp;quot;''': verificar que mantiene el valor &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;; no cambiarlo, ya que debe coincidir con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts de Apache.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Red''' (sección XMR): establecer la dirección pública de XMR como &amp;lt;code&amp;gt;ws://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; (o &amp;lt;code&amp;gt;wss://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; si está activo el vhost HTTPS). Los players se conectan por WebSocket a través del proxy de Apache; el puerto 9505 permanece abierto en el firewall únicamente como vía alternativa de publicación directa.&lt;br /&gt;
&lt;br /&gt;
Los cambios de claves y direcciones obligan a volver a autorizar los displays que estuvieran dados de alta en la máquina base (en un despliegue nuevo no debería haber ninguno; si los hubiera, eliminarlos).&lt;br /&gt;
&lt;br /&gt;
== Configuración a nivel de sistema operativo ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elemento !! Fichero / mecanismo !! Acción&lt;br /&gt;
|-&lt;br /&gt;
| Firewall || &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt; → ejecuta &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;, parametrizado por &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Editar &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; en cada despliegue (ver 4.4): la IP local está fijada a la de la máquina base y debe cambiarse junto con la red del cliente&lt;br /&gt;
|-&lt;br /&gt;
| fail2ban || &amp;lt;code&amp;gt;/etc/fail2ban/jail.d/&amp;lt;/code&amp;gt; || Verificar jail de &amp;lt;code&amp;gt;sshd&amp;lt;/code&amp;gt; activo tras el cambio de IP&lt;br /&gt;
|-&lt;br /&gt;
| Certificado TLS / HTTPS || Vhost &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; incluido de serie (deshabilitado) || Certificado siempre válido, nunca autofirmado: lo aporta el cliente si dispone de él o se emite con Let's Encrypt (&amp;lt;code&amp;gt;certbot certonly&amp;lt;/code&amp;gt; para el FQDN; requiere el puerto 80 alcanzable desde internet y renovación automática vía timer de certbot). Instalar certificado y clave en &amp;lt;code&amp;gt;/etc/ssl/cartelia/&amp;lt;/code&amp;gt; (o apuntar las directivas &amp;lt;code&amp;gt;SSL*&amp;lt;/code&amp;gt; a &amp;lt;code&amp;gt;/etc/letsencrypt/live/&amp;lt;FQDN&amp;gt;/&amp;lt;/code&amp;gt;), ajustar &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2enmod ssl proxy_wstunnel headers&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2ensite cartelia_https&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;. Activar después la redirección HTTP→HTTPS en &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; y actualizar en el portal la CMS Address (&amp;lt;code&amp;gt;https://&amp;lt;FQDN&amp;gt;&amp;lt;/code&amp;gt;) y la dirección de XMR (&amp;lt;code&amp;gt;wss://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Rotación de logs || &amp;lt;code&amp;gt;logrotate&amp;lt;/code&amp;gt; || Verificar&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Firewall (&amp;lt;code&amp;gt;/etc/firewall/&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
El firewall se implementa con nftables mediante dos ficheros, ejecutados en el arranque por &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero !! Función&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt; || Reglas nftables: acepta 80, 443 y 9505 (XMR) hacia la IP local/flotante, 22 solo desde &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt;, checks pasivos de Zabbix (10050) desde el servidor Zabbix, ICMP y tráfico establecido; el resto de entrada se descarta (&amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Variables de entorno que parametrizan las reglas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Variables de &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; a ajustar en cada despliegue:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Valor en la máquina base !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ETH&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;ens3&amp;lt;/code&amp;gt; || Cambiar solo si la interfaz del clon tiene otro nombre (&amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; || IP de la máquina base || Cambiar siempre a la IP del cliente (debe coincidir con la configurada en la sección 3.1, paso 3)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_FLO&amp;lt;/code&amp;gt; || Igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; (sin IP flotante) || Mantener igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; salvo despliegue con alta disponibilidad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_DATOS&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar al direccionamiento del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar a la red desde la que se accede por SSH; es la única red con acceso al puerto 22&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Aplicación y verificación de cambios:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Aplicar (corta y recrea todas las reglas; las conexiones establecidas se mantienen)&lt;br /&gt;
/etc/init.d/firewall start&lt;br /&gt;
&lt;br /&gt;
# Verificar reglas cargadas y contadores&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Verificación remota mínima tras el cambio (desde RED_GESTION)&lt;br /&gt;
ssh &amp;lt;usuario&amp;gt;@&amp;lt;IP-del-servidor&amp;gt;          # el 22 debe seguir accesible&lt;br /&gt;
curl -Is http://&amp;lt;IP-del-servidor&amp;gt;/ | head -1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Aviso|'''Riesgo operativo''': editar &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; con valores erróneos y ejecutar el script '''puede dejar la máquina inaccesible por SSH''' (la política final es &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;). Realizar siempre el cambio con una consola de &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt; abierta como vía de recuperación.}}&lt;br /&gt;
&lt;br /&gt;
= 5. Diagnósticos =&lt;br /&gt;
&lt;br /&gt;
== 5.1 Comandos de diagnóstico ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Estado general de la VM desde el host de virtualización&lt;br /&gt;
virsh dominfo cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
virsh domifaddr cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Dentro de la VM — estado de servicios&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
journalctl -u apache2 -n 100 --no-pager&lt;br /&gt;
journalctl -u xibo-xmr.service -n 100 --no-pager&lt;br /&gt;
&lt;br /&gt;
# Conexión a la base de datos del CMS&lt;br /&gt;
mysql -u &amp;lt;usuario-cms&amp;gt; -p -e &amp;quot;SELECT COUNT(*) FROM display;&amp;quot; &amp;lt;bbdd-cms&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Firewall: reglas activas y contadores por regla&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Conectividad de los puertos de producto&lt;br /&gt;
ss -tlnp | grep -E ':(80|443|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Prueba del API de players (XMDS): debe responder el WSDL&lt;br /&gt;
curl -s &amp;quot;http://localhost/xmds.php?wsdl&amp;quot; | head -5&lt;br /&gt;
&lt;br /&gt;
# Comprobar identidad correcta del clon (no debe coincidir con la plantilla)&lt;br /&gt;
cat /etc/machine-id&lt;br /&gt;
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 5.2 Ficheros de log ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero / origen !! Contenido !! Rotación&lt;br /&gt;
|-&lt;br /&gt;
| Portal ''Administración &amp;gt; Avanzado &amp;gt; Log'' || Log de aplicación del CMS (registro de players, errores XMDS) || Gestionada por la tarea de mantenimiento del CMS&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/var/log/apache2/cartelia_access.log&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/apache2/cartelia_error.log&amp;lt;/code&amp;gt; (y &amp;lt;code&amp;gt;cartelia_ssl_*.log&amp;lt;/code&amp;gt; con el vhost HTTPS activo) || Accesos y errores del servidor web (portal y API XMDS de players) || logrotate estándar de apache2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u xibo-xmr.service&amp;lt;/code&amp;gt; || Log del servicio XMR || journald&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u ssh&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/fail2ban.log&amp;lt;/code&amp;gt; || Seguridad de acceso al SO || Estándar journald / logrotate&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 5.3 Errores comunes y soluciones ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Síntoma / mensaje !! Causa probable !! Solución&lt;br /&gt;
|-&lt;br /&gt;
| El portal no carga tras el clonado || La red de la VM no se personalizó o la interfaz cambió de nombre || Revisar &amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/etc/network/interfaces.d/&amp;lt;/code&amp;gt;, y el bridge asignado en libvirt&lt;br /&gt;
|-&lt;br /&gt;
| Los players no consiguen registrarse || &amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;CMS Secret Key&amp;lt;/code&amp;gt; incorrectos, o 80/443 filtrados || Verificar sección 4.2 y &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; del firewall (4.4); probar &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; al XMDS desde la red de players&lt;br /&gt;
|-&lt;br /&gt;
| Los players se registran pero no reciben órdenes push || Dirección pública de XMR errónea, proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; no operativo o &amp;lt;code&amp;gt;xibo-xmr&amp;lt;/code&amp;gt; caído || Verificar &amp;lt;code&amp;gt;ws(s)://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt; en el portal, &amp;lt;code&amp;gt;systemctl status xibo-xmr.service&amp;lt;/code&amp;gt; y el módulo &amp;lt;code&amp;gt;proxy_wstunnel&amp;lt;/code&amp;gt; de Apache; reiniciar XMR&lt;br /&gt;
|-&lt;br /&gt;
| Aviso de certificado en el navegador || Certificado de la plantilla aún instalado || Sustituir por el certificado del FQDN del entorno&lt;br /&gt;
|-&lt;br /&gt;
| Dos clones aparecen como la misma máquina en DHCP/monitorización || &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt; no regenerado || Ejecutar &amp;lt;code&amp;gt;rm -f /etc/machine-id &amp;amp;&amp;amp; systemd-machine-id-setup&amp;lt;/code&amp;gt; y reiniciar&lt;br /&gt;
|-&lt;br /&gt;
| El CMS no conecta con la base de datos tras cambiar contraseñas || Contraseña cambiada en &amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; pero no en MariaDB (o viceversa) || Sincronizar ambas (ver sección 4.1)&lt;br /&gt;
|-&lt;br /&gt;
| Sin acceso SSH tras personalizar el firewall || &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; erróneas en &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; con política final &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt; || Entrar por &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt;, corregir &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; y re-ejecutar &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| La hora de las programaciones no coincide || Zona horaria o NTP sin configurar || &amp;lt;code&amp;gt;timedatectl set-timezone Europe/Madrid&amp;lt;/code&amp;gt; y verificar &amp;lt;code&amp;gt;timedatectl status&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19178</id>
		<title>Instalacion cartelia 10</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19178"/>
		<updated>2026-07-13T09:32:49Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* 3.3 Verificación de la instalación */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[:Media:cartelia-despliegue-vm-documentacion-tecnica.pdf|Instalación de Cartelia 1.0]]&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
= 1. Introducción =&lt;br /&gt;
&lt;br /&gt;
'''Cartelia''' es el producto de cartelería digital (digital signage) de la compañía.&lt;br /&gt;
&lt;br /&gt;
El presente documento describe el procedimiento de despliegue de una nueva instancia de Cartelia partiendo de una '''máquina virtual base''' con las siguientes características:&lt;br /&gt;
&lt;br /&gt;
* Sistema operativo: '''Debian 13 (trixie)'''.&lt;br /&gt;
* Hipervisor: '''KVM/QEMU''' (gestionado mediante &amp;lt;code&amp;gt;libvirt&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;virt-manager&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Software preinstalado: '''Cartelia 1.0''', instalado en &amp;lt;code&amp;gt;/var/www/html/cartelia&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Punto de partida''': la máquina base se entrega totalmente operativa, con Cartelia instalado de forma nativa sobre Apache + PHP y la base de datos MariaDB local ya creada e inicializada.&lt;br /&gt;
&lt;br /&gt;
'''Restricciones conocidas''':&lt;br /&gt;
&lt;br /&gt;
* La plantilla base '''no debe arrancarse nunca en producción sin personalizar''': contiene identidad de máquina, claves SSH y secretos del CMS compartidos con cualquier otra copia de la plantilla.&lt;br /&gt;
* Los players (pantallas) se autentican contra el CMS mediante la clave del servidor (''CMS Key'') y la URL del CMS; cualquier cambio posterior de IP/FQDN o de claves obliga a volver a autorizar los displays.&lt;br /&gt;
&lt;br /&gt;
= 2. Arquitectura =&lt;br /&gt;
&lt;br /&gt;
== 2.1 Esquema general del despliegue ==&lt;br /&gt;
&lt;br /&gt;
[[File:Cartelia-arquitectura.png|thumb|center|900px|Esquema general del despliegue de Cartelia sobre KVM/QEMU]]&lt;br /&gt;
&lt;br /&gt;
El CMS está instalado de forma nativa sobre el sistema operativo: Apache 2 con PHP como servidor web del portal, MariaDB local como base de datos y el servicio XMR ejecutándose como unidad de systemd.&lt;br /&gt;
&lt;br /&gt;
== 2.2 Flujo del proceso de despliegue ==&lt;br /&gt;
&lt;br /&gt;
# El técnico de sistemas clona la plantilla base en el host KVM/QEMU (disco &amp;lt;code&amp;gt;qcow2&amp;lt;/code&amp;gt; + definición de dominio libvirt).&lt;br /&gt;
# En el primer arranque del clon, se personaliza la identidad del sistema operativo: &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt;, hostname, claves SSH de host, red, zona horaria y credenciales locales.&lt;br /&gt;
# Se personaliza el producto Cartelia: URL pública del CMS, secretos y contraseñas de base de datos, clave del servidor (''CMS Key''), dirección pública de XMR y personalización de marca.&lt;br /&gt;
# Se verifican los servicios, la conectividad de los players y el acceso al portal de administración.&lt;br /&gt;
# La máquina queda registrada en inventario/monitorización y se entrega.&lt;br /&gt;
&lt;br /&gt;
== 2.3 Componentes principales ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Componente !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Portal Cartelia''' || Interfaz de administración de contenidos, layouts, programaciones y pantallas. Servida por Apache 2 + PHP.&lt;br /&gt;
|-&lt;br /&gt;
| '''MariaDB (local)''' || Almacena la configuración, usuarios, programaciones y metadatos de medios del CMS. Servicio nativo del sistema.&lt;br /&gt;
|-&lt;br /&gt;
| '''XMR (Cartelia Message Relay)''' || Canal push que permite al CMS enviar órdenes inmediatas a los players (recarga de contenido, capturas, reinicio). Servicio &amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;. Los players se conectan por WebSocket a la ruta &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, que reenvía a &amp;lt;code&amp;gt;ws://127.0.0.1:8080&amp;lt;/code&amp;gt;; el puerto 9505/TCP queda además permitido en el firewall para el modo de publicación directa.&lt;br /&gt;
|-&lt;br /&gt;
| '''Biblioteca de medios''' || &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;: directorio donde el CMS guarda los ficheros multimedia subidos (configurado en ''Administración &amp;gt; Configuración &amp;gt; Ubicación de la biblioteca'' y alineado con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts).&lt;br /&gt;
|-&lt;br /&gt;
| '''libvirt / KVM-QEMU''' || Capa de virtualización que aloja la VM.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.4 Dependencias e integraciones externas ==&lt;br /&gt;
&lt;br /&gt;
* '''DNS''': registro A/AAAA del FQDN del CMS (imprescindible si los players usan nombre en lugar de IP).&lt;br /&gt;
* '''NTP''': sincronización horaria; las programaciones de contenido dependen de la hora del sistema.&lt;br /&gt;
* '''SMTP''' (opcional): relay de correo para notificaciones del CMS, si el cliente lo requiere. Se configura en el portal (''Administración &amp;gt; Configuración'', pestaña '''Mantenimiento''').&lt;br /&gt;
* '''Certificados TLS''': siempre certificados válidos, nunca autofirmados. Si el cliente dispone de certificado propio para el FQDN, lo aporta él; en caso contrario se emite con Let's Encrypt.&lt;br /&gt;
&lt;br /&gt;
= 3. Personalización del sistema operativo (dentro de la VM) =&lt;br /&gt;
&lt;br /&gt;
== 3.1 Personalización de identidad y red ==&lt;br /&gt;
&lt;br /&gt;
Todos los comandos se ejecutan como &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; desde la consola de &amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; en el primer arranque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Paso 1: regenerar las claves SSH de host (las de la plantilla son comunes a todos los clones)&lt;br /&gt;
rm -f /etc/ssh/ssh_host_*&lt;br /&gt;
dpkg-reconfigure openssh-server&lt;br /&gt;
systemctl restart ssh&lt;br /&gt;
&lt;br /&gt;
# Paso 2: hostname y resolución local&lt;br /&gt;
hostnamectl set-hostname &amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
sed -i &amp;quot;s/127.0.1.1.*/127.0.1.1\t&amp;lt;nombre-del-entorno&amp;gt; &amp;lt;FQDN-del-CMS&amp;gt;/&amp;quot; /etc/hosts&lt;br /&gt;
&lt;br /&gt;
# Paso 3: configuración de red (ifupdown, /etc/network/interfaces)&lt;br /&gt;
&lt;br /&gt;
# Paso 4: zona horaria y hora (NTP)&lt;br /&gt;
vi /etc/systemd/timesyncd.conf.d/local.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Paso 5: actualización de paquetes del SO&lt;br /&gt;
apt update &amp;amp;&amp;amp; apt upgrade -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.2 Arranque del producto Cartelia ==&lt;br /&gt;
&lt;br /&gt;
El CMS ya viene instalado y operativo en la máquina base; en esta fase únicamente debe verificarse el arranque de los servicios nativos tras la personalización de red:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
&lt;br /&gt;
# Si algún servicio no arranca tras el cambio de red/hostname:&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
journalctl -u apache2 -n 50 --no-pager&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.3 Verificación de la instalación ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# El portal responde en local (la máquina base publica en HTTP; ver 4.3 para HTTPS)&lt;br /&gt;
curl -Is http://localhost/ | head -1          # esperado: HTTP/1.1 200 OK (o 302 a /login)&lt;br /&gt;
&lt;br /&gt;
# Puertos de servicio a la escucha&lt;br /&gt;
ss -tlnp | grep -E ':(80|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Resolución del FQDN desde un puesto cliente&lt;br /&gt;
getent hosts &amp;lt;FQDN-del-CMS&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Acceso final: abrir &amp;lt;code&amp;gt;http://&amp;lt;FQDN-del-CMS&amp;gt;/&amp;lt;/code&amp;gt; en el navegador y validar la pantalla de login de Cartelia (o &amp;lt;code&amp;gt;https://&amp;lt;/code&amp;gt; si se ha habilitado el vhost TLS, ver 4.3).&lt;br /&gt;
&lt;br /&gt;
= 4. Configuración =&lt;br /&gt;
&lt;br /&gt;
== 4.1 Ficheros de configuración del producto ==&lt;br /&gt;
&lt;br /&gt;
La instalación es nativa (Apache + PHP + MariaDB local); estos son los ficheros que el SAT debe revisar/personalizar en cada clon:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; del CMS''' (&amp;lt;code&amp;gt;/var/www/html/cartelia/web/settings.php&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Descripción !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbhost&amp;lt;/code&amp;gt; || Host de MariaDB (normalmente &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt;) || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$dbuser&amp;lt;/code&amp;gt; || Base de datos y usuario del CMS || No cambiar salvo política del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbpass&amp;lt;/code&amp;gt; || Contraseña del usuario del CMS en MariaDB || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SECRET_KEY&amp;lt;/code&amp;gt; || Clave secreta de la instalación (cifrado interno) || Actualmente no se regenera: se mantiene el valor de la máquina base en todos los despliegues&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''XMR''' (&amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;, unidad en &amp;lt;code&amp;gt;/etc/systemd/system/xibo-xmr.service&amp;lt;/code&amp;gt;): ejecuta &amp;lt;code&amp;gt;/var/www/html/cartelia/vendor/bin/xmr.phar&amp;lt;/code&amp;gt; con PHP como usuario &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;, con reinicio automático (&amp;lt;code&amp;gt;Restart=always&amp;lt;/code&amp;gt;). Sockets por defecto: WebSocket para players en &amp;lt;code&amp;gt;127.0.0.1:8080&amp;lt;/code&amp;gt;, expuesto a través del proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, y publicación interna del CMS en &amp;lt;code&amp;gt;tcp://127.0.0.1:50001&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Tras cualquier cambio: &amp;lt;code&amp;gt;systemctl restart xibo-xmr.service&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Apache''': la máquina base incluye dos vhosts en &amp;lt;code&amp;gt;/etc/apache2/sites-available/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; (habilitado por defecto): sirve el portal en el puerto 80. En la máquina base el &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt; es la IP de la propia máquina; en cada cliente debe actualizarse al FQDN definitivo. Incluye el proxy WebSocket de XMR (&amp;lt;code&amp;gt;ProxyPass /xmr ws://127.0.0.1:8080&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;XSendFile&amp;lt;/code&amp;gt; para la entrega de medios y una exclusión de mod_security (&amp;lt;code&amp;gt;SecRuleRemoveById 920350&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; (deshabilitado por defecto): vhost TLS preparado para clientes con FQDN y certificado. Su activación se describe en la sección 4.3.&lt;br /&gt;
&lt;br /&gt;
Validar siempre con &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; antes de &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.2 Configuración desde el portal de administración de Cartelia ==&lt;br /&gt;
&lt;br /&gt;
Acceder con el usuario '''&amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt;''' y la contraseña estándar de la máquina base (conocida por el SAT; no se documenta aquí) y cambiar dicha contraseña de inmediato, ya que es común a todos los clones. A continuación:&lt;br /&gt;
&lt;br /&gt;
* ''Administración &amp;gt; Configuración &amp;gt; Red'': establecer la dirección del CMS (&amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt;) con el FQDN definitivo. Los players usan este valor para conectarse.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Clave secreta de CMS&amp;quot;''': es la clave que debe introducirse en cada player para autenticarlo contra el CMS. En un clon es idéntica a la de la máquina base (y, por tanto, conocida por cualquier otro despliegue), así que debe sustituirse por una clave nueva y única en cada cliente.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Ubicación de la biblioteca&amp;quot;''': verificar que mantiene el valor &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;; no cambiarlo, ya que debe coincidir con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts de Apache.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Red''' (sección XMR): establecer la dirección pública de XMR como &amp;lt;code&amp;gt;ws://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; (o &amp;lt;code&amp;gt;wss://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; si está activo el vhost HTTPS). Los players se conectan por WebSocket a través del proxy de Apache; el puerto 9505 permanece abierto en el firewall únicamente como vía alternativa de publicación directa.&lt;br /&gt;
&lt;br /&gt;
Los cambios de claves y direcciones obligan a volver a autorizar los displays que estuvieran dados de alta en la máquina base (en un despliegue nuevo no debería haber ninguno; si los hubiera, eliminarlos).&lt;br /&gt;
&lt;br /&gt;
== 4.3 Configuración a nivel de sistema operativo ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elemento !! Fichero / mecanismo !! Acción&lt;br /&gt;
|-&lt;br /&gt;
| Firewall || &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt; → ejecuta &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;, parametrizado por &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Editar &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; en cada despliegue (ver 4.4): la IP local está fijada a la de la máquina base y debe cambiarse junto con la red del cliente&lt;br /&gt;
|-&lt;br /&gt;
| fail2ban || &amp;lt;code&amp;gt;/etc/fail2ban/jail.d/&amp;lt;/code&amp;gt; || Verificar jail de &amp;lt;code&amp;gt;sshd&amp;lt;/code&amp;gt; activo tras el cambio de IP&lt;br /&gt;
|-&lt;br /&gt;
| Certificado TLS / HTTPS || Vhost &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; incluido de serie (deshabilitado) || Certificado siempre válido, nunca autofirmado: lo aporta el cliente si dispone de él o se emite con Let's Encrypt (&amp;lt;code&amp;gt;certbot certonly&amp;lt;/code&amp;gt; para el FQDN; requiere el puerto 80 alcanzable desde internet y renovación automática vía timer de certbot). Instalar certificado y clave en &amp;lt;code&amp;gt;/etc/ssl/cartelia/&amp;lt;/code&amp;gt; (o apuntar las directivas &amp;lt;code&amp;gt;SSL*&amp;lt;/code&amp;gt; a &amp;lt;code&amp;gt;/etc/letsencrypt/live/&amp;lt;FQDN&amp;gt;/&amp;lt;/code&amp;gt;), ajustar &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2enmod ssl proxy_wstunnel headers&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2ensite cartelia_https&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;. Activar después la redirección HTTP→HTTPS en &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; y actualizar en el portal la CMS Address (&amp;lt;code&amp;gt;https://&amp;lt;FQDN&amp;gt;&amp;lt;/code&amp;gt;) y la dirección de XMR (&amp;lt;code&amp;gt;wss://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Rotación de logs || &amp;lt;code&amp;gt;logrotate&amp;lt;/code&amp;gt; || Verificar&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 4.4 Firewall (&amp;lt;code&amp;gt;/etc/firewall/&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
El firewall se implementa con nftables mediante dos ficheros, ejecutados en el arranque por &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero !! Función&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt; || Reglas nftables: acepta 80, 443 y 9505 (XMR) hacia la IP local/flotante, 22 solo desde &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt;, checks pasivos de Zabbix (10050) desde el servidor Zabbix, ICMP y tráfico establecido; el resto de entrada se descarta (&amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Variables de entorno que parametrizan las reglas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Variables de &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; a ajustar en cada despliegue:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Valor en la máquina base !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ETH&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;ens3&amp;lt;/code&amp;gt; || Cambiar solo si la interfaz del clon tiene otro nombre (&amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; || IP de la máquina base || Cambiar siempre a la IP del cliente (debe coincidir con la configurada en la sección 3.1, paso 3)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_FLO&amp;lt;/code&amp;gt; || Igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; (sin IP flotante) || Mantener igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; salvo despliegue con alta disponibilidad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_DATOS&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar al direccionamiento del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar a la red desde la que se accede por SSH; es la única red con acceso al puerto 22&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Aplicación y verificación de cambios:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Aplicar (corta y recrea todas las reglas; las conexiones establecidas se mantienen)&lt;br /&gt;
/etc/init.d/firewall start&lt;br /&gt;
&lt;br /&gt;
# Verificar reglas cargadas y contadores&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Verificación remota mínima tras el cambio (desde RED_GESTION)&lt;br /&gt;
ssh &amp;lt;usuario&amp;gt;@&amp;lt;IP-del-servidor&amp;gt;          # el 22 debe seguir accesible&lt;br /&gt;
curl -Is http://&amp;lt;IP-del-servidor&amp;gt;/ | head -1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Aviso|'''Riesgo operativo''': editar &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; con valores erróneos y ejecutar el script '''puede dejar la máquina inaccesible por SSH''' (la política final es &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;). Realizar siempre el cambio con una consola de &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt; abierta como vía de recuperación.}}&lt;br /&gt;
&lt;br /&gt;
= 5. Diagnósticos =&lt;br /&gt;
&lt;br /&gt;
== 5.1 Comandos de diagnóstico ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Estado general de la VM desde el host de virtualización&lt;br /&gt;
virsh dominfo cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
virsh domifaddr cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Dentro de la VM — estado de servicios&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
journalctl -u apache2 -n 100 --no-pager&lt;br /&gt;
journalctl -u xibo-xmr.service -n 100 --no-pager&lt;br /&gt;
&lt;br /&gt;
# Conexión a la base de datos del CMS&lt;br /&gt;
mysql -u &amp;lt;usuario-cms&amp;gt; -p -e &amp;quot;SELECT COUNT(*) FROM display;&amp;quot; &amp;lt;bbdd-cms&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Firewall: reglas activas y contadores por regla&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Conectividad de los puertos de producto&lt;br /&gt;
ss -tlnp | grep -E ':(80|443|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Prueba del API de players (XMDS): debe responder el WSDL&lt;br /&gt;
curl -s &amp;quot;http://localhost/xmds.php?wsdl&amp;quot; | head -5&lt;br /&gt;
&lt;br /&gt;
# Comprobar identidad correcta del clon (no debe coincidir con la plantilla)&lt;br /&gt;
cat /etc/machine-id&lt;br /&gt;
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 5.2 Ficheros de log ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero / origen !! Contenido !! Rotación&lt;br /&gt;
|-&lt;br /&gt;
| Portal ''Administración &amp;gt; Avanzado &amp;gt; Log'' || Log de aplicación del CMS (registro de players, errores XMDS) || Gestionada por la tarea de mantenimiento del CMS&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/var/log/apache2/cartelia_access.log&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/apache2/cartelia_error.log&amp;lt;/code&amp;gt; (y &amp;lt;code&amp;gt;cartelia_ssl_*.log&amp;lt;/code&amp;gt; con el vhost HTTPS activo) || Accesos y errores del servidor web (portal y API XMDS de players) || logrotate estándar de apache2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u xibo-xmr.service&amp;lt;/code&amp;gt; || Log del servicio XMR || journald&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u ssh&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/fail2ban.log&amp;lt;/code&amp;gt; || Seguridad de acceso al SO || Estándar journald / logrotate&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 5.3 Errores comunes y soluciones ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Síntoma / mensaje !! Causa probable !! Solución&lt;br /&gt;
|-&lt;br /&gt;
| El portal no carga tras el clonado || La red de la VM no se personalizó o la interfaz cambió de nombre || Revisar &amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/etc/network/interfaces.d/&amp;lt;/code&amp;gt;, y el bridge asignado en libvirt&lt;br /&gt;
|-&lt;br /&gt;
| Los players no consiguen registrarse || &amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;CMS Secret Key&amp;lt;/code&amp;gt; incorrectos, o 80/443 filtrados || Verificar sección 4.2 y &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; del firewall (4.4); probar &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; al XMDS desde la red de players&lt;br /&gt;
|-&lt;br /&gt;
| Los players se registran pero no reciben órdenes push || Dirección pública de XMR errónea, proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; no operativo o &amp;lt;code&amp;gt;xibo-xmr&amp;lt;/code&amp;gt; caído || Verificar &amp;lt;code&amp;gt;ws(s)://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt; en el portal, &amp;lt;code&amp;gt;systemctl status xibo-xmr.service&amp;lt;/code&amp;gt; y el módulo &amp;lt;code&amp;gt;proxy_wstunnel&amp;lt;/code&amp;gt; de Apache; reiniciar XMR&lt;br /&gt;
|-&lt;br /&gt;
| Aviso de certificado en el navegador || Certificado de la plantilla aún instalado || Sustituir por el certificado del FQDN del entorno&lt;br /&gt;
|-&lt;br /&gt;
| Dos clones aparecen como la misma máquina en DHCP/monitorización || &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt; no regenerado || Ejecutar &amp;lt;code&amp;gt;rm -f /etc/machine-id &amp;amp;&amp;amp; systemd-machine-id-setup&amp;lt;/code&amp;gt; y reiniciar&lt;br /&gt;
|-&lt;br /&gt;
| El CMS no conecta con la base de datos tras cambiar contraseñas || Contraseña cambiada en &amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; pero no en MariaDB (o viceversa) || Sincronizar ambas (ver sección 4.1)&lt;br /&gt;
|-&lt;br /&gt;
| Sin acceso SSH tras personalizar el firewall || &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; erróneas en &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; con política final &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt; || Entrar por &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt;, corregir &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; y re-ejecutar &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| La hora de las programaciones no coincide || Zona horaria o NTP sin configurar || &amp;lt;code&amp;gt;timedatectl set-timezone Europe/Madrid&amp;lt;/code&amp;gt; y verificar &amp;lt;code&amp;gt;timedatectl status&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19177</id>
		<title>Instalacion cartelia 10</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19177"/>
		<updated>2026-07-13T09:32:28Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* 3.2 Arranque del producto Cartelia */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[:Media:cartelia-despliegue-vm-documentacion-tecnica.pdf|Instalación de Cartelia 1.0]]&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
= 1. Introducción =&lt;br /&gt;
&lt;br /&gt;
'''Cartelia''' es el producto de cartelería digital (digital signage) de la compañía.&lt;br /&gt;
&lt;br /&gt;
El presente documento describe el procedimiento de despliegue de una nueva instancia de Cartelia partiendo de una '''máquina virtual base''' con las siguientes características:&lt;br /&gt;
&lt;br /&gt;
* Sistema operativo: '''Debian 13 (trixie)'''.&lt;br /&gt;
* Hipervisor: '''KVM/QEMU''' (gestionado mediante &amp;lt;code&amp;gt;libvirt&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;virt-manager&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Software preinstalado: '''Cartelia 1.0''', instalado en &amp;lt;code&amp;gt;/var/www/html/cartelia&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Punto de partida''': la máquina base se entrega totalmente operativa, con Cartelia instalado de forma nativa sobre Apache + PHP y la base de datos MariaDB local ya creada e inicializada.&lt;br /&gt;
&lt;br /&gt;
'''Restricciones conocidas''':&lt;br /&gt;
&lt;br /&gt;
* La plantilla base '''no debe arrancarse nunca en producción sin personalizar''': contiene identidad de máquina, claves SSH y secretos del CMS compartidos con cualquier otra copia de la plantilla.&lt;br /&gt;
* Los players (pantallas) se autentican contra el CMS mediante la clave del servidor (''CMS Key'') y la URL del CMS; cualquier cambio posterior de IP/FQDN o de claves obliga a volver a autorizar los displays.&lt;br /&gt;
&lt;br /&gt;
= 2. Arquitectura =&lt;br /&gt;
&lt;br /&gt;
== 2.1 Esquema general del despliegue ==&lt;br /&gt;
&lt;br /&gt;
[[File:Cartelia-arquitectura.png|thumb|center|900px|Esquema general del despliegue de Cartelia sobre KVM/QEMU]]&lt;br /&gt;
&lt;br /&gt;
El CMS está instalado de forma nativa sobre el sistema operativo: Apache 2 con PHP como servidor web del portal, MariaDB local como base de datos y el servicio XMR ejecutándose como unidad de systemd.&lt;br /&gt;
&lt;br /&gt;
== 2.2 Flujo del proceso de despliegue ==&lt;br /&gt;
&lt;br /&gt;
# El técnico de sistemas clona la plantilla base en el host KVM/QEMU (disco &amp;lt;code&amp;gt;qcow2&amp;lt;/code&amp;gt; + definición de dominio libvirt).&lt;br /&gt;
# En el primer arranque del clon, se personaliza la identidad del sistema operativo: &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt;, hostname, claves SSH de host, red, zona horaria y credenciales locales.&lt;br /&gt;
# Se personaliza el producto Cartelia: URL pública del CMS, secretos y contraseñas de base de datos, clave del servidor (''CMS Key''), dirección pública de XMR y personalización de marca.&lt;br /&gt;
# Se verifican los servicios, la conectividad de los players y el acceso al portal de administración.&lt;br /&gt;
# La máquina queda registrada en inventario/monitorización y se entrega.&lt;br /&gt;
&lt;br /&gt;
== 2.3 Componentes principales ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Componente !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Portal Cartelia''' || Interfaz de administración de contenidos, layouts, programaciones y pantallas. Servida por Apache 2 + PHP.&lt;br /&gt;
|-&lt;br /&gt;
| '''MariaDB (local)''' || Almacena la configuración, usuarios, programaciones y metadatos de medios del CMS. Servicio nativo del sistema.&lt;br /&gt;
|-&lt;br /&gt;
| '''XMR (Cartelia Message Relay)''' || Canal push que permite al CMS enviar órdenes inmediatas a los players (recarga de contenido, capturas, reinicio). Servicio &amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;. Los players se conectan por WebSocket a la ruta &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, que reenvía a &amp;lt;code&amp;gt;ws://127.0.0.1:8080&amp;lt;/code&amp;gt;; el puerto 9505/TCP queda además permitido en el firewall para el modo de publicación directa.&lt;br /&gt;
|-&lt;br /&gt;
| '''Biblioteca de medios''' || &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;: directorio donde el CMS guarda los ficheros multimedia subidos (configurado en ''Administración &amp;gt; Configuración &amp;gt; Ubicación de la biblioteca'' y alineado con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts).&lt;br /&gt;
|-&lt;br /&gt;
| '''libvirt / KVM-QEMU''' || Capa de virtualización que aloja la VM.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.4 Dependencias e integraciones externas ==&lt;br /&gt;
&lt;br /&gt;
* '''DNS''': registro A/AAAA del FQDN del CMS (imprescindible si los players usan nombre en lugar de IP).&lt;br /&gt;
* '''NTP''': sincronización horaria; las programaciones de contenido dependen de la hora del sistema.&lt;br /&gt;
* '''SMTP''' (opcional): relay de correo para notificaciones del CMS, si el cliente lo requiere. Se configura en el portal (''Administración &amp;gt; Configuración'', pestaña '''Mantenimiento''').&lt;br /&gt;
* '''Certificados TLS''': siempre certificados válidos, nunca autofirmados. Si el cliente dispone de certificado propio para el FQDN, lo aporta él; en caso contrario se emite con Let's Encrypt.&lt;br /&gt;
&lt;br /&gt;
= 3. Personalización del sistema operativo (dentro de la VM) =&lt;br /&gt;
&lt;br /&gt;
== 3.1 Personalización de identidad y red ==&lt;br /&gt;
&lt;br /&gt;
Todos los comandos se ejecutan como &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; desde la consola de &amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; en el primer arranque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Paso 1: regenerar las claves SSH de host (las de la plantilla son comunes a todos los clones)&lt;br /&gt;
rm -f /etc/ssh/ssh_host_*&lt;br /&gt;
dpkg-reconfigure openssh-server&lt;br /&gt;
systemctl restart ssh&lt;br /&gt;
&lt;br /&gt;
# Paso 2: hostname y resolución local&lt;br /&gt;
hostnamectl set-hostname &amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
sed -i &amp;quot;s/127.0.1.1.*/127.0.1.1\t&amp;lt;nombre-del-entorno&amp;gt; &amp;lt;FQDN-del-CMS&amp;gt;/&amp;quot; /etc/hosts&lt;br /&gt;
&lt;br /&gt;
# Paso 3: configuración de red (ifupdown, /etc/network/interfaces)&lt;br /&gt;
&lt;br /&gt;
# Paso 4: zona horaria y hora (NTP)&lt;br /&gt;
vi /etc/systemd/timesyncd.conf.d/local.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Paso 5: actualización de paquetes del SO&lt;br /&gt;
apt update &amp;amp;&amp;amp; apt upgrade -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.2 Arranque del producto Cartelia ==&lt;br /&gt;
&lt;br /&gt;
El CMS ya viene instalado y operativo en la máquina base; en esta fase únicamente debe verificarse el arranque de los servicios nativos tras la personalización de red:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
&lt;br /&gt;
# Si algún servicio no arranca tras el cambio de red/hostname:&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
journalctl -u apache2 -n 50 --no-pager&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.3 Verificación de la instalación ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# El portal responde en local (la máquina base publica en HTTP; ver 4.3 para HTTPS)&lt;br /&gt;
curl -Is http://localhost/ | head -1          # esperado: HTTP/1.1 200 OK (o 302 a /login)&lt;br /&gt;
&lt;br /&gt;
# Puertos de servicio a la escucha&lt;br /&gt;
ss -tlnp | grep -E ':(80|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Resolución del FQDN desde un puesto cliente&lt;br /&gt;
getent hosts &amp;lt;FQDN-del-CMS&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Acceso final: abrir &amp;lt;code&amp;gt;http://&amp;lt;FQDN-del-CMS&amp;gt;/&amp;lt;/code&amp;gt; en el navegador y validar la pantalla de login de Cartelia (o &amp;lt;code&amp;gt;https://&amp;lt;/code&amp;gt; si se ha habilitado el vhost TLS, ver 4.3).&lt;br /&gt;
&lt;br /&gt;
= 4. Configuración =&lt;br /&gt;
&lt;br /&gt;
== 4.1 Ficheros de configuración del producto ==&lt;br /&gt;
&lt;br /&gt;
La instalación es nativa (Apache + PHP + MariaDB local); estos son los ficheros que el SAT debe revisar/personalizar en cada clon:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; del CMS''' (&amp;lt;code&amp;gt;/var/www/html/cartelia/web/settings.php&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Descripción !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbhost&amp;lt;/code&amp;gt; || Host de MariaDB (normalmente &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt;) || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$dbuser&amp;lt;/code&amp;gt; || Base de datos y usuario del CMS || No cambiar salvo política del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbpass&amp;lt;/code&amp;gt; || Contraseña del usuario del CMS en MariaDB || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SECRET_KEY&amp;lt;/code&amp;gt; || Clave secreta de la instalación (cifrado interno) || Actualmente no se regenera: se mantiene el valor de la máquina base en todos los despliegues&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''XMR''' (&amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;, unidad en &amp;lt;code&amp;gt;/etc/systemd/system/xibo-xmr.service&amp;lt;/code&amp;gt;): ejecuta &amp;lt;code&amp;gt;/var/www/html/cartelia/vendor/bin/xmr.phar&amp;lt;/code&amp;gt; con PHP como usuario &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;, con reinicio automático (&amp;lt;code&amp;gt;Restart=always&amp;lt;/code&amp;gt;). Sockets por defecto: WebSocket para players en &amp;lt;code&amp;gt;127.0.0.1:8080&amp;lt;/code&amp;gt;, expuesto a través del proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, y publicación interna del CMS en &amp;lt;code&amp;gt;tcp://127.0.0.1:50001&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Tras cualquier cambio: &amp;lt;code&amp;gt;systemctl restart xibo-xmr.service&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Apache''': la máquina base incluye dos vhosts en &amp;lt;code&amp;gt;/etc/apache2/sites-available/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; (habilitado por defecto): sirve el portal en el puerto 80. En la máquina base el &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt; es la IP de la propia máquina; en cada cliente debe actualizarse al FQDN definitivo. Incluye el proxy WebSocket de XMR (&amp;lt;code&amp;gt;ProxyPass /xmr ws://127.0.0.1:8080&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;XSendFile&amp;lt;/code&amp;gt; para la entrega de medios y una exclusión de mod_security (&amp;lt;code&amp;gt;SecRuleRemoveById 920350&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; (deshabilitado por defecto): vhost TLS preparado para clientes con FQDN y certificado. Su activación se describe en la sección 4.3.&lt;br /&gt;
&lt;br /&gt;
Validar siempre con &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; antes de &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.2 Configuración desde el portal de administración de Cartelia ==&lt;br /&gt;
&lt;br /&gt;
Acceder con el usuario '''&amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt;''' y la contraseña estándar de la máquina base (conocida por el SAT; no se documenta aquí) y cambiar dicha contraseña de inmediato, ya que es común a todos los clones. A continuación:&lt;br /&gt;
&lt;br /&gt;
* ''Administración &amp;gt; Configuración &amp;gt; Red'': establecer la dirección del CMS (&amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt;) con el FQDN definitivo. Los players usan este valor para conectarse.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Clave secreta de CMS&amp;quot;''': es la clave que debe introducirse en cada player para autenticarlo contra el CMS. En un clon es idéntica a la de la máquina base (y, por tanto, conocida por cualquier otro despliegue), así que debe sustituirse por una clave nueva y única en cada cliente.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Ubicación de la biblioteca&amp;quot;''': verificar que mantiene el valor &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;; no cambiarlo, ya que debe coincidir con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts de Apache.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Red''' (sección XMR): establecer la dirección pública de XMR como &amp;lt;code&amp;gt;ws://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; (o &amp;lt;code&amp;gt;wss://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; si está activo el vhost HTTPS). Los players se conectan por WebSocket a través del proxy de Apache; el puerto 9505 permanece abierto en el firewall únicamente como vía alternativa de publicación directa.&lt;br /&gt;
&lt;br /&gt;
Los cambios de claves y direcciones obligan a volver a autorizar los displays que estuvieran dados de alta en la máquina base (en un despliegue nuevo no debería haber ninguno; si los hubiera, eliminarlos).&lt;br /&gt;
&lt;br /&gt;
== 4.3 Configuración a nivel de sistema operativo ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elemento !! Fichero / mecanismo !! Acción&lt;br /&gt;
|-&lt;br /&gt;
| Firewall || &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt; → ejecuta &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;, parametrizado por &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Editar &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; en cada despliegue (ver 4.4): la IP local está fijada a la de la máquina base y debe cambiarse junto con la red del cliente&lt;br /&gt;
|-&lt;br /&gt;
| fail2ban || &amp;lt;code&amp;gt;/etc/fail2ban/jail.d/&amp;lt;/code&amp;gt; || Verificar jail de &amp;lt;code&amp;gt;sshd&amp;lt;/code&amp;gt; activo tras el cambio de IP&lt;br /&gt;
|-&lt;br /&gt;
| Certificado TLS / HTTPS || Vhost &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; incluido de serie (deshabilitado) || Certificado siempre válido, nunca autofirmado: lo aporta el cliente si dispone de él o se emite con Let's Encrypt (&amp;lt;code&amp;gt;certbot certonly&amp;lt;/code&amp;gt; para el FQDN; requiere el puerto 80 alcanzable desde internet y renovación automática vía timer de certbot). Instalar certificado y clave en &amp;lt;code&amp;gt;/etc/ssl/cartelia/&amp;lt;/code&amp;gt; (o apuntar las directivas &amp;lt;code&amp;gt;SSL*&amp;lt;/code&amp;gt; a &amp;lt;code&amp;gt;/etc/letsencrypt/live/&amp;lt;FQDN&amp;gt;/&amp;lt;/code&amp;gt;), ajustar &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2enmod ssl proxy_wstunnel headers&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2ensite cartelia_https&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;. Activar después la redirección HTTP→HTTPS en &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; y actualizar en el portal la CMS Address (&amp;lt;code&amp;gt;https://&amp;lt;FQDN&amp;gt;&amp;lt;/code&amp;gt;) y la dirección de XMR (&amp;lt;code&amp;gt;wss://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Rotación de logs || &amp;lt;code&amp;gt;logrotate&amp;lt;/code&amp;gt; || Verificar&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 4.4 Firewall (&amp;lt;code&amp;gt;/etc/firewall/&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
El firewall se implementa con nftables mediante dos ficheros, ejecutados en el arranque por &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero !! Función&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt; || Reglas nftables: acepta 80, 443 y 9505 (XMR) hacia la IP local/flotante, 22 solo desde &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt;, checks pasivos de Zabbix (10050) desde el servidor Zabbix, ICMP y tráfico establecido; el resto de entrada se descarta (&amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Variables de entorno que parametrizan las reglas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Variables de &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; a ajustar en cada despliegue:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Valor en la máquina base !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ETH&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;ens3&amp;lt;/code&amp;gt; || Cambiar solo si la interfaz del clon tiene otro nombre (&amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; || IP de la máquina base || Cambiar siempre a la IP del cliente (debe coincidir con la configurada en la sección 3.1, paso 3)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_FLO&amp;lt;/code&amp;gt; || Igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; (sin IP flotante) || Mantener igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; salvo despliegue con alta disponibilidad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_DATOS&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar al direccionamiento del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar a la red desde la que se accede por SSH; es la única red con acceso al puerto 22&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Aplicación y verificación de cambios:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Aplicar (corta y recrea todas las reglas; las conexiones establecidas se mantienen)&lt;br /&gt;
/etc/init.d/firewall start&lt;br /&gt;
&lt;br /&gt;
# Verificar reglas cargadas y contadores&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Verificación remota mínima tras el cambio (desde RED_GESTION)&lt;br /&gt;
ssh &amp;lt;usuario&amp;gt;@&amp;lt;IP-del-servidor&amp;gt;          # el 22 debe seguir accesible&lt;br /&gt;
curl -Is http://&amp;lt;IP-del-servidor&amp;gt;/ | head -1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Aviso|'''Riesgo operativo''': editar &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; con valores erróneos y ejecutar el script '''puede dejar la máquina inaccesible por SSH''' (la política final es &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;). Realizar siempre el cambio con una consola de &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt; abierta como vía de recuperación.}}&lt;br /&gt;
&lt;br /&gt;
= 5. Diagnósticos =&lt;br /&gt;
&lt;br /&gt;
== 5.1 Comandos de diagnóstico ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Estado general de la VM desde el host de virtualización&lt;br /&gt;
virsh dominfo cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
virsh domifaddr cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Dentro de la VM — estado de servicios&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
journalctl -u apache2 -n 100 --no-pager&lt;br /&gt;
journalctl -u xibo-xmr.service -n 100 --no-pager&lt;br /&gt;
&lt;br /&gt;
# Conexión a la base de datos del CMS&lt;br /&gt;
mysql -u &amp;lt;usuario-cms&amp;gt; -p -e &amp;quot;SELECT COUNT(*) FROM display;&amp;quot; &amp;lt;bbdd-cms&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Firewall: reglas activas y contadores por regla&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Conectividad de los puertos de producto&lt;br /&gt;
ss -tlnp | grep -E ':(80|443|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Prueba del API de players (XMDS): debe responder el WSDL&lt;br /&gt;
curl -s &amp;quot;http://localhost/xmds.php?wsdl&amp;quot; | head -5&lt;br /&gt;
&lt;br /&gt;
# Comprobar identidad correcta del clon (no debe coincidir con la plantilla)&lt;br /&gt;
cat /etc/machine-id&lt;br /&gt;
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 5.2 Ficheros de log ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero / origen !! Contenido !! Rotación&lt;br /&gt;
|-&lt;br /&gt;
| Portal ''Administración &amp;gt; Avanzado &amp;gt; Log'' || Log de aplicación del CMS (registro de players, errores XMDS) || Gestionada por la tarea de mantenimiento del CMS&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/var/log/apache2/cartelia_access.log&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/apache2/cartelia_error.log&amp;lt;/code&amp;gt; (y &amp;lt;code&amp;gt;cartelia_ssl_*.log&amp;lt;/code&amp;gt; con el vhost HTTPS activo) || Accesos y errores del servidor web (portal y API XMDS de players) || logrotate estándar de apache2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u xibo-xmr.service&amp;lt;/code&amp;gt; || Log del servicio XMR || journald&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u ssh&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/fail2ban.log&amp;lt;/code&amp;gt; || Seguridad de acceso al SO || Estándar journald / logrotate&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 5.3 Errores comunes y soluciones ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Síntoma / mensaje !! Causa probable !! Solución&lt;br /&gt;
|-&lt;br /&gt;
| El portal no carga tras el clonado || La red de la VM no se personalizó o la interfaz cambió de nombre || Revisar &amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/etc/network/interfaces.d/&amp;lt;/code&amp;gt;, y el bridge asignado en libvirt&lt;br /&gt;
|-&lt;br /&gt;
| Los players no consiguen registrarse || &amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;CMS Secret Key&amp;lt;/code&amp;gt; incorrectos, o 80/443 filtrados || Verificar sección 4.2 y &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; del firewall (4.4); probar &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; al XMDS desde la red de players&lt;br /&gt;
|-&lt;br /&gt;
| Los players se registran pero no reciben órdenes push || Dirección pública de XMR errónea, proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; no operativo o &amp;lt;code&amp;gt;xibo-xmr&amp;lt;/code&amp;gt; caído || Verificar &amp;lt;code&amp;gt;ws(s)://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt; en el portal, &amp;lt;code&amp;gt;systemctl status xibo-xmr.service&amp;lt;/code&amp;gt; y el módulo &amp;lt;code&amp;gt;proxy_wstunnel&amp;lt;/code&amp;gt; de Apache; reiniciar XMR&lt;br /&gt;
|-&lt;br /&gt;
| Aviso de certificado en el navegador || Certificado de la plantilla aún instalado || Sustituir por el certificado del FQDN del entorno&lt;br /&gt;
|-&lt;br /&gt;
| Dos clones aparecen como la misma máquina en DHCP/monitorización || &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt; no regenerado || Ejecutar &amp;lt;code&amp;gt;rm -f /etc/machine-id &amp;amp;&amp;amp; systemd-machine-id-setup&amp;lt;/code&amp;gt; y reiniciar&lt;br /&gt;
|-&lt;br /&gt;
| El CMS no conecta con la base de datos tras cambiar contraseñas || Contraseña cambiada en &amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; pero no en MariaDB (o viceversa) || Sincronizar ambas (ver sección 4.1)&lt;br /&gt;
|-&lt;br /&gt;
| Sin acceso SSH tras personalizar el firewall || &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; erróneas en &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; con política final &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt; || Entrar por &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt;, corregir &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; y re-ejecutar &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| La hora de las programaciones no coincide || Zona horaria o NTP sin configurar || &amp;lt;code&amp;gt;timedatectl set-timezone Europe/Madrid&amp;lt;/code&amp;gt; y verificar &amp;lt;code&amp;gt;timedatectl status&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19176</id>
		<title>Instalacion cartelia 10</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19176"/>
		<updated>2026-07-13T09:31:59Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* 3.1 Personalización de identidad y red */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[:Media:cartelia-despliegue-vm-documentacion-tecnica.pdf|Instalación de Cartelia 1.0]]&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
= 1. Introducción =&lt;br /&gt;
&lt;br /&gt;
'''Cartelia''' es el producto de cartelería digital (digital signage) de la compañía.&lt;br /&gt;
&lt;br /&gt;
El presente documento describe el procedimiento de despliegue de una nueva instancia de Cartelia partiendo de una '''máquina virtual base''' con las siguientes características:&lt;br /&gt;
&lt;br /&gt;
* Sistema operativo: '''Debian 13 (trixie)'''.&lt;br /&gt;
* Hipervisor: '''KVM/QEMU''' (gestionado mediante &amp;lt;code&amp;gt;libvirt&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;virt-manager&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Software preinstalado: '''Cartelia 1.0''', instalado en &amp;lt;code&amp;gt;/var/www/html/cartelia&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Punto de partida''': la máquina base se entrega totalmente operativa, con Cartelia instalado de forma nativa sobre Apache + PHP y la base de datos MariaDB local ya creada e inicializada.&lt;br /&gt;
&lt;br /&gt;
'''Restricciones conocidas''':&lt;br /&gt;
&lt;br /&gt;
* La plantilla base '''no debe arrancarse nunca en producción sin personalizar''': contiene identidad de máquina, claves SSH y secretos del CMS compartidos con cualquier otra copia de la plantilla.&lt;br /&gt;
* Los players (pantallas) se autentican contra el CMS mediante la clave del servidor (''CMS Key'') y la URL del CMS; cualquier cambio posterior de IP/FQDN o de claves obliga a volver a autorizar los displays.&lt;br /&gt;
&lt;br /&gt;
= 2. Arquitectura =&lt;br /&gt;
&lt;br /&gt;
== 2.1 Esquema general del despliegue ==&lt;br /&gt;
&lt;br /&gt;
[[File:Cartelia-arquitectura.png|thumb|center|900px|Esquema general del despliegue de Cartelia sobre KVM/QEMU]]&lt;br /&gt;
&lt;br /&gt;
El CMS está instalado de forma nativa sobre el sistema operativo: Apache 2 con PHP como servidor web del portal, MariaDB local como base de datos y el servicio XMR ejecutándose como unidad de systemd.&lt;br /&gt;
&lt;br /&gt;
== 2.2 Flujo del proceso de despliegue ==&lt;br /&gt;
&lt;br /&gt;
# El técnico de sistemas clona la plantilla base en el host KVM/QEMU (disco &amp;lt;code&amp;gt;qcow2&amp;lt;/code&amp;gt; + definición de dominio libvirt).&lt;br /&gt;
# En el primer arranque del clon, se personaliza la identidad del sistema operativo: &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt;, hostname, claves SSH de host, red, zona horaria y credenciales locales.&lt;br /&gt;
# Se personaliza el producto Cartelia: URL pública del CMS, secretos y contraseñas de base de datos, clave del servidor (''CMS Key''), dirección pública de XMR y personalización de marca.&lt;br /&gt;
# Se verifican los servicios, la conectividad de los players y el acceso al portal de administración.&lt;br /&gt;
# La máquina queda registrada en inventario/monitorización y se entrega.&lt;br /&gt;
&lt;br /&gt;
== 2.3 Componentes principales ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Componente !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Portal Cartelia''' || Interfaz de administración de contenidos, layouts, programaciones y pantallas. Servida por Apache 2 + PHP.&lt;br /&gt;
|-&lt;br /&gt;
| '''MariaDB (local)''' || Almacena la configuración, usuarios, programaciones y metadatos de medios del CMS. Servicio nativo del sistema.&lt;br /&gt;
|-&lt;br /&gt;
| '''XMR (Cartelia Message Relay)''' || Canal push que permite al CMS enviar órdenes inmediatas a los players (recarga de contenido, capturas, reinicio). Servicio &amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;. Los players se conectan por WebSocket a la ruta &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, que reenvía a &amp;lt;code&amp;gt;ws://127.0.0.1:8080&amp;lt;/code&amp;gt;; el puerto 9505/TCP queda además permitido en el firewall para el modo de publicación directa.&lt;br /&gt;
|-&lt;br /&gt;
| '''Biblioteca de medios''' || &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;: directorio donde el CMS guarda los ficheros multimedia subidos (configurado en ''Administración &amp;gt; Configuración &amp;gt; Ubicación de la biblioteca'' y alineado con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts).&lt;br /&gt;
|-&lt;br /&gt;
| '''libvirt / KVM-QEMU''' || Capa de virtualización que aloja la VM.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.4 Dependencias e integraciones externas ==&lt;br /&gt;
&lt;br /&gt;
* '''DNS''': registro A/AAAA del FQDN del CMS (imprescindible si los players usan nombre en lugar de IP).&lt;br /&gt;
* '''NTP''': sincronización horaria; las programaciones de contenido dependen de la hora del sistema.&lt;br /&gt;
* '''SMTP''' (opcional): relay de correo para notificaciones del CMS, si el cliente lo requiere. Se configura en el portal (''Administración &amp;gt; Configuración'', pestaña '''Mantenimiento''').&lt;br /&gt;
* '''Certificados TLS''': siempre certificados válidos, nunca autofirmados. Si el cliente dispone de certificado propio para el FQDN, lo aporta él; en caso contrario se emite con Let's Encrypt.&lt;br /&gt;
&lt;br /&gt;
= 3. Personalización del sistema operativo (dentro de la VM) =&lt;br /&gt;
&lt;br /&gt;
== 3.1 Personalización de identidad y red ==&lt;br /&gt;
&lt;br /&gt;
Todos los comandos se ejecutan como &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; desde la consola de &amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; en el primer arranque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
# Paso 1: regenerar las claves SSH de host (las de la plantilla son comunes a todos los clones)&lt;br /&gt;
rm -f /etc/ssh/ssh_host_*&lt;br /&gt;
dpkg-reconfigure openssh-server&lt;br /&gt;
systemctl restart ssh&lt;br /&gt;
&lt;br /&gt;
# Paso 2: hostname y resolución local&lt;br /&gt;
hostnamectl set-hostname &amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
sed -i &amp;quot;s/127.0.1.1.*/127.0.1.1\t&amp;lt;nombre-del-entorno&amp;gt; &amp;lt;FQDN-del-CMS&amp;gt;/&amp;quot; /etc/hosts&lt;br /&gt;
&lt;br /&gt;
# Paso 3: configuración de red (ifupdown, /etc/network/interfaces)&lt;br /&gt;
&lt;br /&gt;
# Paso 4: zona horaria y hora (NTP)&lt;br /&gt;
vi /etc/systemd/timesyncd.conf.d/local.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Paso 5: actualización de paquetes del SO&lt;br /&gt;
apt update &amp;amp;&amp;amp; apt upgrade -y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.2 Arranque del producto Cartelia ==&lt;br /&gt;
&lt;br /&gt;
El CMS ya viene instalado y operativo en la máquina base; en esta fase únicamente debe verificarse el arranque de los servicios nativos tras la personalización de red:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
&lt;br /&gt;
# Si algún servicio no arranca tras el cambio de red/hostname:&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
journalctl -u apache2 -n 50 --no-pager&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.3 Verificación de la instalación ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# El portal responde en local (la máquina base publica en HTTP; ver 4.3 para HTTPS)&lt;br /&gt;
curl -Is http://localhost/ | head -1          # esperado: HTTP/1.1 200 OK (o 302 a /login)&lt;br /&gt;
&lt;br /&gt;
# Puertos de servicio a la escucha&lt;br /&gt;
ss -tlnp | grep -E ':(80|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Resolución del FQDN desde un puesto cliente&lt;br /&gt;
getent hosts &amp;lt;FQDN-del-CMS&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Acceso final: abrir &amp;lt;code&amp;gt;http://&amp;lt;FQDN-del-CMS&amp;gt;/&amp;lt;/code&amp;gt; en el navegador y validar la pantalla de login de Cartelia (o &amp;lt;code&amp;gt;https://&amp;lt;/code&amp;gt; si se ha habilitado el vhost TLS, ver 4.3).&lt;br /&gt;
&lt;br /&gt;
= 4. Configuración =&lt;br /&gt;
&lt;br /&gt;
== 4.1 Ficheros de configuración del producto ==&lt;br /&gt;
&lt;br /&gt;
La instalación es nativa (Apache + PHP + MariaDB local); estos son los ficheros que el SAT debe revisar/personalizar en cada clon:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; del CMS''' (&amp;lt;code&amp;gt;/var/www/html/cartelia/web/settings.php&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Descripción !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbhost&amp;lt;/code&amp;gt; || Host de MariaDB (normalmente &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt;) || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$dbuser&amp;lt;/code&amp;gt; || Base de datos y usuario del CMS || No cambiar salvo política del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbpass&amp;lt;/code&amp;gt; || Contraseña del usuario del CMS en MariaDB || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SECRET_KEY&amp;lt;/code&amp;gt; || Clave secreta de la instalación (cifrado interno) || Actualmente no se regenera: se mantiene el valor de la máquina base en todos los despliegues&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''XMR''' (&amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;, unidad en &amp;lt;code&amp;gt;/etc/systemd/system/xibo-xmr.service&amp;lt;/code&amp;gt;): ejecuta &amp;lt;code&amp;gt;/var/www/html/cartelia/vendor/bin/xmr.phar&amp;lt;/code&amp;gt; con PHP como usuario &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;, con reinicio automático (&amp;lt;code&amp;gt;Restart=always&amp;lt;/code&amp;gt;). Sockets por defecto: WebSocket para players en &amp;lt;code&amp;gt;127.0.0.1:8080&amp;lt;/code&amp;gt;, expuesto a través del proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, y publicación interna del CMS en &amp;lt;code&amp;gt;tcp://127.0.0.1:50001&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Tras cualquier cambio: &amp;lt;code&amp;gt;systemctl restart xibo-xmr.service&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Apache''': la máquina base incluye dos vhosts en &amp;lt;code&amp;gt;/etc/apache2/sites-available/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; (habilitado por defecto): sirve el portal en el puerto 80. En la máquina base el &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt; es la IP de la propia máquina; en cada cliente debe actualizarse al FQDN definitivo. Incluye el proxy WebSocket de XMR (&amp;lt;code&amp;gt;ProxyPass /xmr ws://127.0.0.1:8080&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;XSendFile&amp;lt;/code&amp;gt; para la entrega de medios y una exclusión de mod_security (&amp;lt;code&amp;gt;SecRuleRemoveById 920350&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; (deshabilitado por defecto): vhost TLS preparado para clientes con FQDN y certificado. Su activación se describe en la sección 4.3.&lt;br /&gt;
&lt;br /&gt;
Validar siempre con &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; antes de &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.2 Configuración desde el portal de administración de Cartelia ==&lt;br /&gt;
&lt;br /&gt;
Acceder con el usuario '''&amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt;''' y la contraseña estándar de la máquina base (conocida por el SAT; no se documenta aquí) y cambiar dicha contraseña de inmediato, ya que es común a todos los clones. A continuación:&lt;br /&gt;
&lt;br /&gt;
* ''Administración &amp;gt; Configuración &amp;gt; Red'': establecer la dirección del CMS (&amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt;) con el FQDN definitivo. Los players usan este valor para conectarse.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Clave secreta de CMS&amp;quot;''': es la clave que debe introducirse en cada player para autenticarlo contra el CMS. En un clon es idéntica a la de la máquina base (y, por tanto, conocida por cualquier otro despliegue), así que debe sustituirse por una clave nueva y única en cada cliente.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Ubicación de la biblioteca&amp;quot;''': verificar que mantiene el valor &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;; no cambiarlo, ya que debe coincidir con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts de Apache.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Red''' (sección XMR): establecer la dirección pública de XMR como &amp;lt;code&amp;gt;ws://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; (o &amp;lt;code&amp;gt;wss://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; si está activo el vhost HTTPS). Los players se conectan por WebSocket a través del proxy de Apache; el puerto 9505 permanece abierto en el firewall únicamente como vía alternativa de publicación directa.&lt;br /&gt;
&lt;br /&gt;
Los cambios de claves y direcciones obligan a volver a autorizar los displays que estuvieran dados de alta en la máquina base (en un despliegue nuevo no debería haber ninguno; si los hubiera, eliminarlos).&lt;br /&gt;
&lt;br /&gt;
== 4.3 Configuración a nivel de sistema operativo ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elemento !! Fichero / mecanismo !! Acción&lt;br /&gt;
|-&lt;br /&gt;
| Firewall || &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt; → ejecuta &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;, parametrizado por &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Editar &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; en cada despliegue (ver 4.4): la IP local está fijada a la de la máquina base y debe cambiarse junto con la red del cliente&lt;br /&gt;
|-&lt;br /&gt;
| fail2ban || &amp;lt;code&amp;gt;/etc/fail2ban/jail.d/&amp;lt;/code&amp;gt; || Verificar jail de &amp;lt;code&amp;gt;sshd&amp;lt;/code&amp;gt; activo tras el cambio de IP&lt;br /&gt;
|-&lt;br /&gt;
| Certificado TLS / HTTPS || Vhost &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; incluido de serie (deshabilitado) || Certificado siempre válido, nunca autofirmado: lo aporta el cliente si dispone de él o se emite con Let's Encrypt (&amp;lt;code&amp;gt;certbot certonly&amp;lt;/code&amp;gt; para el FQDN; requiere el puerto 80 alcanzable desde internet y renovación automática vía timer de certbot). Instalar certificado y clave en &amp;lt;code&amp;gt;/etc/ssl/cartelia/&amp;lt;/code&amp;gt; (o apuntar las directivas &amp;lt;code&amp;gt;SSL*&amp;lt;/code&amp;gt; a &amp;lt;code&amp;gt;/etc/letsencrypt/live/&amp;lt;FQDN&amp;gt;/&amp;lt;/code&amp;gt;), ajustar &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2enmod ssl proxy_wstunnel headers&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2ensite cartelia_https&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;. Activar después la redirección HTTP→HTTPS en &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; y actualizar en el portal la CMS Address (&amp;lt;code&amp;gt;https://&amp;lt;FQDN&amp;gt;&amp;lt;/code&amp;gt;) y la dirección de XMR (&amp;lt;code&amp;gt;wss://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Rotación de logs || &amp;lt;code&amp;gt;logrotate&amp;lt;/code&amp;gt; || Verificar&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 4.4 Firewall (&amp;lt;code&amp;gt;/etc/firewall/&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
El firewall se implementa con nftables mediante dos ficheros, ejecutados en el arranque por &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero !! Función&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt; || Reglas nftables: acepta 80, 443 y 9505 (XMR) hacia la IP local/flotante, 22 solo desde &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt;, checks pasivos de Zabbix (10050) desde el servidor Zabbix, ICMP y tráfico establecido; el resto de entrada se descarta (&amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Variables de entorno que parametrizan las reglas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Variables de &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; a ajustar en cada despliegue:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Valor en la máquina base !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ETH&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;ens3&amp;lt;/code&amp;gt; || Cambiar solo si la interfaz del clon tiene otro nombre (&amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; || IP de la máquina base || Cambiar siempre a la IP del cliente (debe coincidir con la configurada en la sección 3.1, paso 3)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_FLO&amp;lt;/code&amp;gt; || Igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; (sin IP flotante) || Mantener igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; salvo despliegue con alta disponibilidad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_DATOS&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar al direccionamiento del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar a la red desde la que se accede por SSH; es la única red con acceso al puerto 22&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Aplicación y verificación de cambios:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Aplicar (corta y recrea todas las reglas; las conexiones establecidas se mantienen)&lt;br /&gt;
/etc/init.d/firewall start&lt;br /&gt;
&lt;br /&gt;
# Verificar reglas cargadas y contadores&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Verificación remota mínima tras el cambio (desde RED_GESTION)&lt;br /&gt;
ssh &amp;lt;usuario&amp;gt;@&amp;lt;IP-del-servidor&amp;gt;          # el 22 debe seguir accesible&lt;br /&gt;
curl -Is http://&amp;lt;IP-del-servidor&amp;gt;/ | head -1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Aviso|'''Riesgo operativo''': editar &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; con valores erróneos y ejecutar el script '''puede dejar la máquina inaccesible por SSH''' (la política final es &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;). Realizar siempre el cambio con una consola de &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt; abierta como vía de recuperación.}}&lt;br /&gt;
&lt;br /&gt;
= 5. Diagnósticos =&lt;br /&gt;
&lt;br /&gt;
== 5.1 Comandos de diagnóstico ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Estado general de la VM desde el host de virtualización&lt;br /&gt;
virsh dominfo cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
virsh domifaddr cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Dentro de la VM — estado de servicios&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
journalctl -u apache2 -n 100 --no-pager&lt;br /&gt;
journalctl -u xibo-xmr.service -n 100 --no-pager&lt;br /&gt;
&lt;br /&gt;
# Conexión a la base de datos del CMS&lt;br /&gt;
mysql -u &amp;lt;usuario-cms&amp;gt; -p -e &amp;quot;SELECT COUNT(*) FROM display;&amp;quot; &amp;lt;bbdd-cms&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Firewall: reglas activas y contadores por regla&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Conectividad de los puertos de producto&lt;br /&gt;
ss -tlnp | grep -E ':(80|443|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Prueba del API de players (XMDS): debe responder el WSDL&lt;br /&gt;
curl -s &amp;quot;http://localhost/xmds.php?wsdl&amp;quot; | head -5&lt;br /&gt;
&lt;br /&gt;
# Comprobar identidad correcta del clon (no debe coincidir con la plantilla)&lt;br /&gt;
cat /etc/machine-id&lt;br /&gt;
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 5.2 Ficheros de log ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero / origen !! Contenido !! Rotación&lt;br /&gt;
|-&lt;br /&gt;
| Portal ''Administración &amp;gt; Avanzado &amp;gt; Log'' || Log de aplicación del CMS (registro de players, errores XMDS) || Gestionada por la tarea de mantenimiento del CMS&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/var/log/apache2/cartelia_access.log&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/apache2/cartelia_error.log&amp;lt;/code&amp;gt; (y &amp;lt;code&amp;gt;cartelia_ssl_*.log&amp;lt;/code&amp;gt; con el vhost HTTPS activo) || Accesos y errores del servidor web (portal y API XMDS de players) || logrotate estándar de apache2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u xibo-xmr.service&amp;lt;/code&amp;gt; || Log del servicio XMR || journald&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u ssh&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/fail2ban.log&amp;lt;/code&amp;gt; || Seguridad de acceso al SO || Estándar journald / logrotate&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 5.3 Errores comunes y soluciones ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Síntoma / mensaje !! Causa probable !! Solución&lt;br /&gt;
|-&lt;br /&gt;
| El portal no carga tras el clonado || La red de la VM no se personalizó o la interfaz cambió de nombre || Revisar &amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/etc/network/interfaces.d/&amp;lt;/code&amp;gt;, y el bridge asignado en libvirt&lt;br /&gt;
|-&lt;br /&gt;
| Los players no consiguen registrarse || &amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;CMS Secret Key&amp;lt;/code&amp;gt; incorrectos, o 80/443 filtrados || Verificar sección 4.2 y &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; del firewall (4.4); probar &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; al XMDS desde la red de players&lt;br /&gt;
|-&lt;br /&gt;
| Los players se registran pero no reciben órdenes push || Dirección pública de XMR errónea, proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; no operativo o &amp;lt;code&amp;gt;xibo-xmr&amp;lt;/code&amp;gt; caído || Verificar &amp;lt;code&amp;gt;ws(s)://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt; en el portal, &amp;lt;code&amp;gt;systemctl status xibo-xmr.service&amp;lt;/code&amp;gt; y el módulo &amp;lt;code&amp;gt;proxy_wstunnel&amp;lt;/code&amp;gt; de Apache; reiniciar XMR&lt;br /&gt;
|-&lt;br /&gt;
| Aviso de certificado en el navegador || Certificado de la plantilla aún instalado || Sustituir por el certificado del FQDN del entorno&lt;br /&gt;
|-&lt;br /&gt;
| Dos clones aparecen como la misma máquina en DHCP/monitorización || &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt; no regenerado || Ejecutar &amp;lt;code&amp;gt;rm -f /etc/machine-id &amp;amp;&amp;amp; systemd-machine-id-setup&amp;lt;/code&amp;gt; y reiniciar&lt;br /&gt;
|-&lt;br /&gt;
| El CMS no conecta con la base de datos tras cambiar contraseñas || Contraseña cambiada en &amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; pero no en MariaDB (o viceversa) || Sincronizar ambas (ver sección 4.1)&lt;br /&gt;
|-&lt;br /&gt;
| Sin acceso SSH tras personalizar el firewall || &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; erróneas en &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; con política final &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt; || Entrar por &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt;, corregir &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; y re-ejecutar &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| La hora de las programaciones no coincide || Zona horaria o NTP sin configurar || &amp;lt;code&amp;gt;timedatectl set-timezone Europe/Madrid&amp;lt;/code&amp;gt; y verificar &amp;lt;code&amp;gt;timedatectl status&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Archivo:Cartelia-arquitectura.png&amp;diff=19175</id>
		<title>Archivo:Cartelia-arquitectura.png</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Archivo:Cartelia-arquitectura.png&amp;diff=19175"/>
		<updated>2026-07-13T09:29:13Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19174</id>
		<title>Instalacion cartelia 10</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia_10&amp;diff=19174"/>
		<updated>2026-07-13T09:28:20Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: Página creada con «Instalación de Cartelia 1.0 ---  = 1. Introducción =  '''Cartelia''' es el producto de cartelería digital (di…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[:Media:cartelia-despliegue-vm-documentacion-tecnica.pdf|Instalación de Cartelia 1.0]]&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
= 1. Introducción =&lt;br /&gt;
&lt;br /&gt;
'''Cartelia''' es el producto de cartelería digital (digital signage) de la compañía.&lt;br /&gt;
&lt;br /&gt;
El presente documento describe el procedimiento de despliegue de una nueva instancia de Cartelia partiendo de una '''máquina virtual base''' con las siguientes características:&lt;br /&gt;
&lt;br /&gt;
* Sistema operativo: '''Debian 13 (trixie)'''.&lt;br /&gt;
* Hipervisor: '''KVM/QEMU''' (gestionado mediante &amp;lt;code&amp;gt;libvirt&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;virt-manager&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Software preinstalado: '''Cartelia 1.0''', instalado en &amp;lt;code&amp;gt;/var/www/html/cartelia&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Punto de partida''': la máquina base se entrega totalmente operativa, con Cartelia instalado de forma nativa sobre Apache + PHP y la base de datos MariaDB local ya creada e inicializada.&lt;br /&gt;
&lt;br /&gt;
'''Restricciones conocidas''':&lt;br /&gt;
&lt;br /&gt;
* La plantilla base '''no debe arrancarse nunca en producción sin personalizar''': contiene identidad de máquina, claves SSH y secretos del CMS compartidos con cualquier otra copia de la plantilla.&lt;br /&gt;
* Los players (pantallas) se autentican contra el CMS mediante la clave del servidor (''CMS Key'') y la URL del CMS; cualquier cambio posterior de IP/FQDN o de claves obliga a volver a autorizar los displays.&lt;br /&gt;
&lt;br /&gt;
= 2. Arquitectura =&lt;br /&gt;
&lt;br /&gt;
== 2.1 Esquema general del despliegue ==&lt;br /&gt;
&lt;br /&gt;
[[File:Cartelia-arquitectura.png|thumb|center|900px|Esquema general del despliegue de Cartelia sobre KVM/QEMU]]&lt;br /&gt;
&lt;br /&gt;
El CMS está instalado de forma nativa sobre el sistema operativo: Apache 2 con PHP como servidor web del portal, MariaDB local como base de datos y el servicio XMR ejecutándose como unidad de systemd.&lt;br /&gt;
&lt;br /&gt;
== 2.2 Flujo del proceso de despliegue ==&lt;br /&gt;
&lt;br /&gt;
# El técnico de sistemas clona la plantilla base en el host KVM/QEMU (disco &amp;lt;code&amp;gt;qcow2&amp;lt;/code&amp;gt; + definición de dominio libvirt).&lt;br /&gt;
# En el primer arranque del clon, se personaliza la identidad del sistema operativo: &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt;, hostname, claves SSH de host, red, zona horaria y credenciales locales.&lt;br /&gt;
# Se personaliza el producto Cartelia: URL pública del CMS, secretos y contraseñas de base de datos, clave del servidor (''CMS Key''), dirección pública de XMR y personalización de marca.&lt;br /&gt;
# Se verifican los servicios, la conectividad de los players y el acceso al portal de administración.&lt;br /&gt;
# La máquina queda registrada en inventario/monitorización y se entrega.&lt;br /&gt;
&lt;br /&gt;
== 2.3 Componentes principales ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Componente !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Portal Cartelia''' || Interfaz de administración de contenidos, layouts, programaciones y pantallas. Servida por Apache 2 + PHP.&lt;br /&gt;
|-&lt;br /&gt;
| '''MariaDB (local)''' || Almacena la configuración, usuarios, programaciones y metadatos de medios del CMS. Servicio nativo del sistema.&lt;br /&gt;
|-&lt;br /&gt;
| '''XMR (Cartelia Message Relay)''' || Canal push que permite al CMS enviar órdenes inmediatas a los players (recarga de contenido, capturas, reinicio). Servicio &amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;. Los players se conectan por WebSocket a la ruta &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, que reenvía a &amp;lt;code&amp;gt;ws://127.0.0.1:8080&amp;lt;/code&amp;gt;; el puerto 9505/TCP queda además permitido en el firewall para el modo de publicación directa.&lt;br /&gt;
|-&lt;br /&gt;
| '''Biblioteca de medios''' || &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;: directorio donde el CMS guarda los ficheros multimedia subidos (configurado en ''Administración &amp;gt; Configuración &amp;gt; Ubicación de la biblioteca'' y alineado con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts).&lt;br /&gt;
|-&lt;br /&gt;
| '''libvirt / KVM-QEMU''' || Capa de virtualización que aloja la VM.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.4 Dependencias e integraciones externas ==&lt;br /&gt;
&lt;br /&gt;
* '''DNS''': registro A/AAAA del FQDN del CMS (imprescindible si los players usan nombre en lugar de IP).&lt;br /&gt;
* '''NTP''': sincronización horaria; las programaciones de contenido dependen de la hora del sistema.&lt;br /&gt;
* '''SMTP''' (opcional): relay de correo para notificaciones del CMS, si el cliente lo requiere. Se configura en el portal (''Administración &amp;gt; Configuración'', pestaña '''Mantenimiento''').&lt;br /&gt;
* '''Certificados TLS''': siempre certificados válidos, nunca autofirmados. Si el cliente dispone de certificado propio para el FQDN, lo aporta él; en caso contrario se emite con Let's Encrypt.&lt;br /&gt;
&lt;br /&gt;
= 3. Personalización del sistema operativo (dentro de la VM) =&lt;br /&gt;
&lt;br /&gt;
== 3.1 Personalización de identidad y red ==&lt;br /&gt;
&lt;br /&gt;
Todos los comandos se ejecutan como &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; desde la consola de &amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; en el primer arranque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Paso 1: regenerar las claves SSH de host (las de la plantilla son comunes a todos los clones)&lt;br /&gt;
rm -f /etc/ssh/ssh_host_*&lt;br /&gt;
dpkg-reconfigure openssh-server&lt;br /&gt;
systemctl restart ssh&lt;br /&gt;
&lt;br /&gt;
# Paso 2: hostname y resolución local&lt;br /&gt;
hostnamectl set-hostname &amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
sed -i &amp;quot;s/127.0.1.1.*/127.0.1.1\t&amp;lt;nombre-del-entorno&amp;gt; &amp;lt;FQDN-del-CMS&amp;gt;/&amp;quot; /etc/hosts&lt;br /&gt;
&lt;br /&gt;
# Paso 3: configuración de red (ifupdown, /etc/network/interfaces)&lt;br /&gt;
&lt;br /&gt;
# Paso 4: zona horaria y hora (NTP)&lt;br /&gt;
vi /etc/systemd/timesyncd.conf.d/local.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Paso 5: actualización de paquetes del SO&lt;br /&gt;
apt update &amp;amp;&amp;amp; apt upgrade -y&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.2 Arranque del producto Cartelia ==&lt;br /&gt;
&lt;br /&gt;
El CMS ya viene instalado y operativo en la máquina base; en esta fase únicamente debe verificarse el arranque de los servicios nativos tras la personalización de red:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
&lt;br /&gt;
# Si algún servicio no arranca tras el cambio de red/hostname:&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
journalctl -u apache2 -n 50 --no-pager&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.3 Verificación de la instalación ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# El portal responde en local (la máquina base publica en HTTP; ver 4.3 para HTTPS)&lt;br /&gt;
curl -Is http://localhost/ | head -1          # esperado: HTTP/1.1 200 OK (o 302 a /login)&lt;br /&gt;
&lt;br /&gt;
# Puertos de servicio a la escucha&lt;br /&gt;
ss -tlnp | grep -E ':(80|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Resolución del FQDN desde un puesto cliente&lt;br /&gt;
getent hosts &amp;lt;FQDN-del-CMS&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Acceso final: abrir &amp;lt;code&amp;gt;http://&amp;lt;FQDN-del-CMS&amp;gt;/&amp;lt;/code&amp;gt; en el navegador y validar la pantalla de login de Cartelia (o &amp;lt;code&amp;gt;https://&amp;lt;/code&amp;gt; si se ha habilitado el vhost TLS, ver 4.3).&lt;br /&gt;
&lt;br /&gt;
= 4. Configuración =&lt;br /&gt;
&lt;br /&gt;
== 4.1 Ficheros de configuración del producto ==&lt;br /&gt;
&lt;br /&gt;
La instalación es nativa (Apache + PHP + MariaDB local); estos son los ficheros que el SAT debe revisar/personalizar en cada clon:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; del CMS''' (&amp;lt;code&amp;gt;/var/www/html/cartelia/web/settings.php&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Descripción !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbhost&amp;lt;/code&amp;gt; || Host de MariaDB (normalmente &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt;) || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$dbuser&amp;lt;/code&amp;gt; || Base de datos y usuario del CMS || No cambiar salvo política del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbpass&amp;lt;/code&amp;gt; || Contraseña del usuario del CMS en MariaDB || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SECRET_KEY&amp;lt;/code&amp;gt; || Clave secreta de la instalación (cifrado interno) || Actualmente no se regenera: se mantiene el valor de la máquina base en todos los despliegues&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''XMR''' (&amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;, unidad en &amp;lt;code&amp;gt;/etc/systemd/system/xibo-xmr.service&amp;lt;/code&amp;gt;): ejecuta &amp;lt;code&amp;gt;/var/www/html/cartelia/vendor/bin/xmr.phar&amp;lt;/code&amp;gt; con PHP como usuario &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;, con reinicio automático (&amp;lt;code&amp;gt;Restart=always&amp;lt;/code&amp;gt;). Sockets por defecto: WebSocket para players en &amp;lt;code&amp;gt;127.0.0.1:8080&amp;lt;/code&amp;gt;, expuesto a través del proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, y publicación interna del CMS en &amp;lt;code&amp;gt;tcp://127.0.0.1:50001&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Tras cualquier cambio: &amp;lt;code&amp;gt;systemctl restart xibo-xmr.service&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Apache''': la máquina base incluye dos vhosts en &amp;lt;code&amp;gt;/etc/apache2/sites-available/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; (habilitado por defecto): sirve el portal en el puerto 80. En la máquina base el &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt; es la IP de la propia máquina; en cada cliente debe actualizarse al FQDN definitivo. Incluye el proxy WebSocket de XMR (&amp;lt;code&amp;gt;ProxyPass /xmr ws://127.0.0.1:8080&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;XSendFile&amp;lt;/code&amp;gt; para la entrega de medios y una exclusión de mod_security (&amp;lt;code&amp;gt;SecRuleRemoveById 920350&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; (deshabilitado por defecto): vhost TLS preparado para clientes con FQDN y certificado. Su activación se describe en la sección 4.3.&lt;br /&gt;
&lt;br /&gt;
Validar siempre con &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; antes de &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.2 Configuración desde el portal de administración de Cartelia ==&lt;br /&gt;
&lt;br /&gt;
Acceder con el usuario '''&amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt;''' y la contraseña estándar de la máquina base (conocida por el SAT; no se documenta aquí) y cambiar dicha contraseña de inmediato, ya que es común a todos los clones. A continuación:&lt;br /&gt;
&lt;br /&gt;
* ''Administración &amp;gt; Configuración &amp;gt; Red'': establecer la dirección del CMS (&amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt;) con el FQDN definitivo. Los players usan este valor para conectarse.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Clave secreta de CMS&amp;quot;''': es la clave que debe introducirse en cada player para autenticarlo contra el CMS. En un clon es idéntica a la de la máquina base (y, por tanto, conocida por cualquier otro despliegue), así que debe sustituirse por una clave nueva y única en cada cliente.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Ubicación de la biblioteca&amp;quot;''': verificar que mantiene el valor &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;; no cambiarlo, ya que debe coincidir con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts de Apache.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Red''' (sección XMR): establecer la dirección pública de XMR como &amp;lt;code&amp;gt;ws://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; (o &amp;lt;code&amp;gt;wss://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; si está activo el vhost HTTPS). Los players se conectan por WebSocket a través del proxy de Apache; el puerto 9505 permanece abierto en el firewall únicamente como vía alternativa de publicación directa.&lt;br /&gt;
&lt;br /&gt;
Los cambios de claves y direcciones obligan a volver a autorizar los displays que estuvieran dados de alta en la máquina base (en un despliegue nuevo no debería haber ninguno; si los hubiera, eliminarlos).&lt;br /&gt;
&lt;br /&gt;
== 4.3 Configuración a nivel de sistema operativo ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elemento !! Fichero / mecanismo !! Acción&lt;br /&gt;
|-&lt;br /&gt;
| Firewall || &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt; → ejecuta &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;, parametrizado por &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Editar &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; en cada despliegue (ver 4.4): la IP local está fijada a la de la máquina base y debe cambiarse junto con la red del cliente&lt;br /&gt;
|-&lt;br /&gt;
| fail2ban || &amp;lt;code&amp;gt;/etc/fail2ban/jail.d/&amp;lt;/code&amp;gt; || Verificar jail de &amp;lt;code&amp;gt;sshd&amp;lt;/code&amp;gt; activo tras el cambio de IP&lt;br /&gt;
|-&lt;br /&gt;
| Certificado TLS / HTTPS || Vhost &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; incluido de serie (deshabilitado) || Certificado siempre válido, nunca autofirmado: lo aporta el cliente si dispone de él o se emite con Let's Encrypt (&amp;lt;code&amp;gt;certbot certonly&amp;lt;/code&amp;gt; para el FQDN; requiere el puerto 80 alcanzable desde internet y renovación automática vía timer de certbot). Instalar certificado y clave en &amp;lt;code&amp;gt;/etc/ssl/cartelia/&amp;lt;/code&amp;gt; (o apuntar las directivas &amp;lt;code&amp;gt;SSL*&amp;lt;/code&amp;gt; a &amp;lt;code&amp;gt;/etc/letsencrypt/live/&amp;lt;FQDN&amp;gt;/&amp;lt;/code&amp;gt;), ajustar &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2enmod ssl proxy_wstunnel headers&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2ensite cartelia_https&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;. Activar después la redirección HTTP→HTTPS en &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; y actualizar en el portal la CMS Address (&amp;lt;code&amp;gt;https://&amp;lt;FQDN&amp;gt;&amp;lt;/code&amp;gt;) y la dirección de XMR (&amp;lt;code&amp;gt;wss://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Rotación de logs || &amp;lt;code&amp;gt;logrotate&amp;lt;/code&amp;gt; || Verificar&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 4.4 Firewall (&amp;lt;code&amp;gt;/etc/firewall/&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
El firewall se implementa con nftables mediante dos ficheros, ejecutados en el arranque por &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero !! Función&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt; || Reglas nftables: acepta 80, 443 y 9505 (XMR) hacia la IP local/flotante, 22 solo desde &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt;, checks pasivos de Zabbix (10050) desde el servidor Zabbix, ICMP y tráfico establecido; el resto de entrada se descarta (&amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Variables de entorno que parametrizan las reglas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Variables de &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; a ajustar en cada despliegue:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Valor en la máquina base !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ETH&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;ens3&amp;lt;/code&amp;gt; || Cambiar solo si la interfaz del clon tiene otro nombre (&amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; || IP de la máquina base || Cambiar siempre a la IP del cliente (debe coincidir con la configurada en la sección 3.1, paso 3)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_FLO&amp;lt;/code&amp;gt; || Igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; (sin IP flotante) || Mantener igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; salvo despliegue con alta disponibilidad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_DATOS&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar al direccionamiento del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar a la red desde la que se accede por SSH; es la única red con acceso al puerto 22&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Aplicación y verificación de cambios:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Aplicar (corta y recrea todas las reglas; las conexiones establecidas se mantienen)&lt;br /&gt;
/etc/init.d/firewall start&lt;br /&gt;
&lt;br /&gt;
# Verificar reglas cargadas y contadores&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Verificación remota mínima tras el cambio (desde RED_GESTION)&lt;br /&gt;
ssh &amp;lt;usuario&amp;gt;@&amp;lt;IP-del-servidor&amp;gt;          # el 22 debe seguir accesible&lt;br /&gt;
curl -Is http://&amp;lt;IP-del-servidor&amp;gt;/ | head -1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Aviso|'''Riesgo operativo''': editar &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; con valores erróneos y ejecutar el script '''puede dejar la máquina inaccesible por SSH''' (la política final es &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;). Realizar siempre el cambio con una consola de &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt; abierta como vía de recuperación.}}&lt;br /&gt;
&lt;br /&gt;
= 5. Diagnósticos =&lt;br /&gt;
&lt;br /&gt;
== 5.1 Comandos de diagnóstico ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Estado general de la VM desde el host de virtualización&lt;br /&gt;
virsh dominfo cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
virsh domifaddr cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Dentro de la VM — estado de servicios&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
journalctl -u apache2 -n 100 --no-pager&lt;br /&gt;
journalctl -u xibo-xmr.service -n 100 --no-pager&lt;br /&gt;
&lt;br /&gt;
# Conexión a la base de datos del CMS&lt;br /&gt;
mysql -u &amp;lt;usuario-cms&amp;gt; -p -e &amp;quot;SELECT COUNT(*) FROM display;&amp;quot; &amp;lt;bbdd-cms&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Firewall: reglas activas y contadores por regla&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Conectividad de los puertos de producto&lt;br /&gt;
ss -tlnp | grep -E ':(80|443|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Prueba del API de players (XMDS): debe responder el WSDL&lt;br /&gt;
curl -s &amp;quot;http://localhost/xmds.php?wsdl&amp;quot; | head -5&lt;br /&gt;
&lt;br /&gt;
# Comprobar identidad correcta del clon (no debe coincidir con la plantilla)&lt;br /&gt;
cat /etc/machine-id&lt;br /&gt;
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 5.2 Ficheros de log ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero / origen !! Contenido !! Rotación&lt;br /&gt;
|-&lt;br /&gt;
| Portal ''Administración &amp;gt; Avanzado &amp;gt; Log'' || Log de aplicación del CMS (registro de players, errores XMDS) || Gestionada por la tarea de mantenimiento del CMS&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/var/log/apache2/cartelia_access.log&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/apache2/cartelia_error.log&amp;lt;/code&amp;gt; (y &amp;lt;code&amp;gt;cartelia_ssl_*.log&amp;lt;/code&amp;gt; con el vhost HTTPS activo) || Accesos y errores del servidor web (portal y API XMDS de players) || logrotate estándar de apache2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u xibo-xmr.service&amp;lt;/code&amp;gt; || Log del servicio XMR || journald&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u ssh&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/fail2ban.log&amp;lt;/code&amp;gt; || Seguridad de acceso al SO || Estándar journald / logrotate&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 5.3 Errores comunes y soluciones ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Síntoma / mensaje !! Causa probable !! Solución&lt;br /&gt;
|-&lt;br /&gt;
| El portal no carga tras el clonado || La red de la VM no se personalizó o la interfaz cambió de nombre || Revisar &amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/etc/network/interfaces.d/&amp;lt;/code&amp;gt;, y el bridge asignado en libvirt&lt;br /&gt;
|-&lt;br /&gt;
| Los players no consiguen registrarse || &amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;CMS Secret Key&amp;lt;/code&amp;gt; incorrectos, o 80/443 filtrados || Verificar sección 4.2 y &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; del firewall (4.4); probar &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; al XMDS desde la red de players&lt;br /&gt;
|-&lt;br /&gt;
| Los players se registran pero no reciben órdenes push || Dirección pública de XMR errónea, proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; no operativo o &amp;lt;code&amp;gt;xibo-xmr&amp;lt;/code&amp;gt; caído || Verificar &amp;lt;code&amp;gt;ws(s)://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt; en el portal, &amp;lt;code&amp;gt;systemctl status xibo-xmr.service&amp;lt;/code&amp;gt; y el módulo &amp;lt;code&amp;gt;proxy_wstunnel&amp;lt;/code&amp;gt; de Apache; reiniciar XMR&lt;br /&gt;
|-&lt;br /&gt;
| Aviso de certificado en el navegador || Certificado de la plantilla aún instalado || Sustituir por el certificado del FQDN del entorno&lt;br /&gt;
|-&lt;br /&gt;
| Dos clones aparecen como la misma máquina en DHCP/monitorización || &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt; no regenerado || Ejecutar &amp;lt;code&amp;gt;rm -f /etc/machine-id &amp;amp;&amp;amp; systemd-machine-id-setup&amp;lt;/code&amp;gt; y reiniciar&lt;br /&gt;
|-&lt;br /&gt;
| El CMS no conecta con la base de datos tras cambiar contraseñas || Contraseña cambiada en &amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; pero no en MariaDB (o viceversa) || Sincronizar ambas (ver sección 4.1)&lt;br /&gt;
|-&lt;br /&gt;
| Sin acceso SSH tras personalizar el firewall || &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; erróneas en &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; con política final &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt; || Entrar por &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt;, corregir &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; y re-ejecutar &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| La hora de las programaciones no coincide || Zona horaria o NTP sin configurar || &amp;lt;code&amp;gt;timedatectl set-timezone Europe/Madrid&amp;lt;/code&amp;gt; y verificar &amp;lt;code&amp;gt;timedatectl status&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia&amp;diff=19173</id>
		<title>Instalacion cartelia</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia&amp;diff=19173"/>
		<updated>2026-07-13T09:27:55Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Instalacion_cartelia_10 | Manual de instalación de cartelia 1.0]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia&amp;diff=19172</id>
		<title>Instalacion cartelia</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia&amp;diff=19172"/>
		<updated>2026-07-13T09:25:11Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: Página reemplazada por «== Manual de instalación de cartelia 1.0 == Instalación de Cartelia 1.0 &amp;lt;br&amp;gt;»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Manual de instalación de cartelia 1.0 ==&lt;br /&gt;
[[:Media:cartelia-despliegue-vm-documentacion-tecnica.pdf|Instalación de Cartelia 1.0]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia&amp;diff=19171</id>
		<title>Instalacion cartelia</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia&amp;diff=19171"/>
		<updated>2026-07-13T09:24:46Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Manual de instalación de cartelia 1.0 ==&lt;br /&gt;
[[:Media:cartelia-despliegue-vm-documentacion-tecnica.pdf|Instalación de Cartelia 1.0]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
{{DISPLAYTITLE:Cartelia — Despliegue de máquina virtual base (Debian 13 / KVM-QEMU)}}&lt;br /&gt;
&lt;br /&gt;
= Introducción =&lt;br /&gt;
&lt;br /&gt;
'''Cartelia''' es el producto de cartelería digital (digital signage) de la compañía.&lt;br /&gt;
&lt;br /&gt;
El presente documento describe el procedimiento de despliegue de una nueva instancia de Cartelia partiendo de una '''máquina virtual base''' con las siguientes características:&lt;br /&gt;
&lt;br /&gt;
* Sistema operativo: '''Debian 13 (trixie)'''.&lt;br /&gt;
* Hipervisor: '''KVM/QEMU''' (gestionado mediante &amp;lt;code&amp;gt;libvirt&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;virt-manager&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Software preinstalado: '''Cartelia 1.0''', instalado en &amp;lt;code&amp;gt;/var/www/html/cartelia&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Punto de partida''': la máquina base se entrega totalmente operativa, con Cartelia instalado de forma nativa sobre Apache + PHP y la base de datos MariaDB local ya creada e inicializada.&lt;br /&gt;
&lt;br /&gt;
'''Restricciones conocidas''':&lt;br /&gt;
&lt;br /&gt;
* La plantilla base '''no debe arrancarse nunca en producción sin personalizar''': contiene identidad de máquina, claves SSH y secretos del CMS compartidos con cualquier otra copia de la plantilla.&lt;br /&gt;
* Los players (pantallas) se autentican contra el CMS mediante la clave del servidor (''CMS Key'') y la URL del CMS; cualquier cambio posterior de IP/FQDN o de claves obliga a volver a autorizar los displays.&lt;br /&gt;
&lt;br /&gt;
= Arquitectura =&lt;br /&gt;
&lt;br /&gt;
== Esquema general del despliegue ==&lt;br /&gt;
&lt;br /&gt;
[[File:Cartelia-arquitectura.png|thumb|center|900px|Esquema general del despliegue de Cartelia sobre KVM/QEMU]]&lt;br /&gt;
&lt;br /&gt;
El CMS está instalado de forma nativa sobre el sistema operativo: Apache 2 con PHP como servidor web del portal, MariaDB local como base de datos y el servicio XMR ejecutándose como unidad de systemd.&lt;br /&gt;
&lt;br /&gt;
== Flujo del proceso de despliegue ==&lt;br /&gt;
&lt;br /&gt;
# El técnico de sistemas clona la plantilla base en el host KVM/QEMU (disco &amp;lt;code&amp;gt;qcow2&amp;lt;/code&amp;gt; + definición de dominio libvirt).&lt;br /&gt;
# En el primer arranque del clon, se personaliza la identidad del sistema operativo: &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt;, hostname, claves SSH de host, red, zona horaria y credenciales locales.&lt;br /&gt;
# Se personaliza el producto Cartelia: URL pública del CMS, secretos y contraseñas de base de datos, clave del servidor (''CMS Key''), dirección pública de XMR y personalización de marca.&lt;br /&gt;
# Se verifican los servicios, la conectividad de los players y el acceso al portal de administración.&lt;br /&gt;
# La máquina queda registrada en inventario/monitorización y se entrega.&lt;br /&gt;
&lt;br /&gt;
== Componentes principales ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Componente !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Portal Cartelia''' || Interfaz de administración de contenidos, layouts, programaciones y pantallas. Servida por Apache 2 + PHP.&lt;br /&gt;
|-&lt;br /&gt;
| '''MariaDB (local)''' || Almacena la configuración, usuarios, programaciones y metadatos de medios del CMS. Servicio nativo del sistema.&lt;br /&gt;
|-&lt;br /&gt;
| '''XMR (Cartelia Message Relay)''' || Canal push que permite al CMS enviar órdenes inmediatas a los players (recarga de contenido, capturas, reinicio). Servicio &amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;. Los players se conectan por WebSocket a la ruta &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, que reenvía a &amp;lt;code&amp;gt;ws://127.0.0.1:8080&amp;lt;/code&amp;gt;; el puerto 9505/TCP queda además permitido en el firewall para el modo de publicación directa.&lt;br /&gt;
|-&lt;br /&gt;
| '''Biblioteca de medios''' || &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;: directorio donde el CMS guarda los ficheros multimedia subidos (configurado en ''Administración &amp;gt; Configuración &amp;gt; Ubicación de la biblioteca'' y alineado con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts).&lt;br /&gt;
|-&lt;br /&gt;
| '''libvirt / KVM-QEMU''' || Capa de virtualización que aloja la VM.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Dependencias e integraciones externas ==&lt;br /&gt;
&lt;br /&gt;
* '''DNS''': registro A/AAAA del FQDN del CMS (imprescindible si los players usan nombre en lugar de IP).&lt;br /&gt;
* '''NTP''': sincronización horaria; las programaciones de contenido dependen de la hora del sistema.&lt;br /&gt;
* '''SMTP''' (opcional): relay de correo para notificaciones del CMS, si el cliente lo requiere. Se configura en el portal (''Administración &amp;gt; Configuración'', pestaña '''Mantenimiento''').&lt;br /&gt;
* '''Certificados TLS''': siempre certificados válidos, nunca autofirmados. Si el cliente dispone de certificado propio para el FQDN, lo aporta él; en caso contrario se emite con Let's Encrypt.&lt;br /&gt;
&lt;br /&gt;
= Personalización del sistema operativo (dentro de la VM) =&lt;br /&gt;
&lt;br /&gt;
== Personalización de identidad y red ==&lt;br /&gt;
&lt;br /&gt;
Todos los comandos se ejecutan como &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; desde la consola de &amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; en el primer arranque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Paso 1: regenerar las claves SSH de host (las de la plantilla son comunes a todos los clones)&lt;br /&gt;
rm -f /etc/ssh/ssh_host_*&lt;br /&gt;
dpkg-reconfigure openssh-server&lt;br /&gt;
systemctl restart ssh&lt;br /&gt;
&lt;br /&gt;
# Paso 2: hostname y resolución local&lt;br /&gt;
hostnamectl set-hostname &amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
sed -i &amp;quot;s/127.0.1.1.*/127.0.1.1\t&amp;lt;nombre-del-entorno&amp;gt; &amp;lt;FQDN-del-CMS&amp;gt;/&amp;quot; /etc/hosts&lt;br /&gt;
&lt;br /&gt;
# Paso 3: configuración de red (ifupdown, /etc/network/interfaces)&lt;br /&gt;
&lt;br /&gt;
# Paso 4: zona horaria y hora (NTP)&lt;br /&gt;
vi /etc/systemd/timesyncd.conf.d/local.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Paso 5: actualización de paquetes del SO&lt;br /&gt;
apt update &amp;amp;&amp;amp; apt upgrade -y&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Arranque del producto Cartelia ==&lt;br /&gt;
&lt;br /&gt;
El CMS ya viene instalado y operativo en la máquina base; en esta fase únicamente debe verificarse el arranque de los servicios nativos tras la personalización de red:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
&lt;br /&gt;
# Si algún servicio no arranca tras el cambio de red/hostname:&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
journalctl -u apache2 -n 50 --no-pager&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Verificación de la instalación ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# El portal responde en local (la máquina base publica en HTTP; ver 4.3 para HTTPS)&lt;br /&gt;
curl -Is http://localhost/ | head -1          # esperado: HTTP/1.1 200 OK (o 302 a /login)&lt;br /&gt;
&lt;br /&gt;
# Puertos de servicio a la escucha&lt;br /&gt;
ss -tlnp | grep -E ':(80|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Resolución del FQDN desde un puesto cliente&lt;br /&gt;
getent hosts &amp;lt;FQDN-del-CMS&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Acceso final: abrir &amp;lt;code&amp;gt;http://&amp;lt;FQDN-del-CMS&amp;gt;/&amp;lt;/code&amp;gt; en el navegador y validar la pantalla de login de Cartelia (o &amp;lt;code&amp;gt;https://&amp;lt;/code&amp;gt; si se ha habilitado el vhost TLS, ver 4.3).&lt;br /&gt;
&lt;br /&gt;
= Configuración =&lt;br /&gt;
&lt;br /&gt;
== Ficheros de configuración del producto ==&lt;br /&gt;
&lt;br /&gt;
La instalación es nativa (Apache + PHP + MariaDB local); estos son los ficheros que el SAT debe revisar/personalizar en cada clon:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; del CMS''' (&amp;lt;code&amp;gt;/var/www/html/cartelia/web/settings.php&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Descripción !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbhost&amp;lt;/code&amp;gt; || Host de MariaDB (normalmente &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt;) || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$dbuser&amp;lt;/code&amp;gt; || Base de datos y usuario del CMS || No cambiar salvo política del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbpass&amp;lt;/code&amp;gt; || Contraseña del usuario del CMS en MariaDB || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SECRET_KEY&amp;lt;/code&amp;gt; || Clave secreta de la instalación (cifrado interno) || Actualmente no se regenera: se mantiene el valor de la máquina base en todos los despliegues&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''XMR''' (&amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;, unidad en &amp;lt;code&amp;gt;/etc/systemd/system/xibo-xmr.service&amp;lt;/code&amp;gt;): ejecuta &amp;lt;code&amp;gt;/var/www/html/cartelia/vendor/bin/xmr.phar&amp;lt;/code&amp;gt; con PHP como usuario &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;, con reinicio automático (&amp;lt;code&amp;gt;Restart=always&amp;lt;/code&amp;gt;). Sockets por defecto: WebSocket para players en &amp;lt;code&amp;gt;127.0.0.1:8080&amp;lt;/code&amp;gt;, expuesto a través del proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, y publicación interna del CMS en &amp;lt;code&amp;gt;tcp://127.0.0.1:50001&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Tras cualquier cambio: &amp;lt;code&amp;gt;systemctl restart xibo-xmr.service&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Apache''': la máquina base incluye dos vhosts en &amp;lt;code&amp;gt;/etc/apache2/sites-available/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; (habilitado por defecto): sirve el portal en el puerto 80. En la máquina base el &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt; es la IP de la propia máquina; en cada cliente debe actualizarse al FQDN definitivo. Incluye el proxy WebSocket de XMR (&amp;lt;code&amp;gt;ProxyPass /xmr ws://127.0.0.1:8080&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;XSendFile&amp;lt;/code&amp;gt; para la entrega de medios y una exclusión de mod_security (&amp;lt;code&amp;gt;SecRuleRemoveById 920350&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; (deshabilitado por defecto): vhost TLS preparado para clientes con FQDN y certificado. Su activación se describe en la sección 4.3.&lt;br /&gt;
&lt;br /&gt;
Validar siempre con &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; antes de &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Configuración desde el portal de administración de Cartelia ==&lt;br /&gt;
&lt;br /&gt;
Acceder con el usuario '''&amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt;''' y la contraseña estándar de la máquina base (conocida por el SAT; no se documenta aquí) y cambiar dicha contraseña de inmediato, ya que es común a todos los clones. A continuación:&lt;br /&gt;
&lt;br /&gt;
* ''Administración &amp;gt; Configuración &amp;gt; Red'': establecer la dirección del CMS (&amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt;) con el FQDN definitivo. Los players usan este valor para conectarse.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Clave secreta de CMS&amp;quot;''': es la clave que debe introducirse en cada player para autenticarlo contra el CMS. En un clon es idéntica a la de la máquina base (y, por tanto, conocida por cualquier otro despliegue), así que debe sustituirse por una clave nueva y única en cada cliente.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Ubicación de la biblioteca&amp;quot;''': verificar que mantiene el valor &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;; no cambiarlo, ya que debe coincidir con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts de Apache.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Red''' (sección XMR): establecer la dirección pública de XMR como &amp;lt;code&amp;gt;ws://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; (o &amp;lt;code&amp;gt;wss://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; si está activo el vhost HTTPS). Los players se conectan por WebSocket a través del proxy de Apache; el puerto 9505 permanece abierto en el firewall únicamente como vía alternativa de publicación directa.&lt;br /&gt;
&lt;br /&gt;
Los cambios de claves y direcciones obligan a volver a autorizar los displays que estuvieran dados de alta en la máquina base (en un despliegue nuevo no debería haber ninguno; si los hubiera, eliminarlos).&lt;br /&gt;
&lt;br /&gt;
== Configuración a nivel de sistema operativo ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elemento !! Fichero / mecanismo !! Acción&lt;br /&gt;
|-&lt;br /&gt;
| Firewall || &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt; → ejecuta &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;, parametrizado por &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Editar &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; en cada despliegue (ver 4.4): la IP local está fijada a la de la máquina base y debe cambiarse junto con la red del cliente&lt;br /&gt;
|-&lt;br /&gt;
| fail2ban || &amp;lt;code&amp;gt;/etc/fail2ban/jail.d/&amp;lt;/code&amp;gt; || Verificar jail de &amp;lt;code&amp;gt;sshd&amp;lt;/code&amp;gt; activo tras el cambio de IP&lt;br /&gt;
|-&lt;br /&gt;
| Certificado TLS / HTTPS || Vhost &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; incluido de serie (deshabilitado) || Certificado siempre válido, nunca autofirmado: lo aporta el cliente si dispone de él o se emite con Let's Encrypt (&amp;lt;code&amp;gt;certbot certonly&amp;lt;/code&amp;gt; para el FQDN; requiere el puerto 80 alcanzable desde internet y renovación automática vía timer de certbot). Instalar certificado y clave en &amp;lt;code&amp;gt;/etc/ssl/cartelia/&amp;lt;/code&amp;gt; (o apuntar las directivas &amp;lt;code&amp;gt;SSL*&amp;lt;/code&amp;gt; a &amp;lt;code&amp;gt;/etc/letsencrypt/live/&amp;lt;FQDN&amp;gt;/&amp;lt;/code&amp;gt;), ajustar &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2enmod ssl proxy_wstunnel headers&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2ensite cartelia_https&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;. Activar después la redirección HTTP→HTTPS en &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; y actualizar en el portal la CMS Address (&amp;lt;code&amp;gt;https://&amp;lt;FQDN&amp;gt;&amp;lt;/code&amp;gt;) y la dirección de XMR (&amp;lt;code&amp;gt;wss://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Rotación de logs || &amp;lt;code&amp;gt;logrotate&amp;lt;/code&amp;gt; || Verificar&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Firewall (&amp;lt;code&amp;gt;/etc/firewall/&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
El firewall se implementa con nftables mediante dos ficheros, ejecutados en el arranque por &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero !! Función&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt; || Reglas nftables: acepta 80, 443 y 9505 (XMR) hacia la IP local/flotante, 22 solo desde &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt;, checks pasivos de Zabbix (10050) desde el servidor Zabbix, ICMP y tráfico establecido; el resto de entrada se descarta (&amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Variables de entorno que parametrizan las reglas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Variables de &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; a ajustar en cada despliegue:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Valor en la máquina base !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ETH&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;ens3&amp;lt;/code&amp;gt; || Cambiar solo si la interfaz del clon tiene otro nombre (&amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; || IP de la máquina base || Cambiar siempre a la IP del cliente (debe coincidir con la configurada en la sección 3.1, paso 3)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_FLO&amp;lt;/code&amp;gt; || Igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; (sin IP flotante) || Mantener igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; salvo despliegue con alta disponibilidad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_DATOS&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar al direccionamiento del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar a la red desde la que se accede por SSH; es la única red con acceso al puerto 22&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Aplicación y verificación de cambios:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Aplicar (corta y recrea todas las reglas; las conexiones establecidas se mantienen)&lt;br /&gt;
/etc/init.d/firewall start&lt;br /&gt;
&lt;br /&gt;
# Verificar reglas cargadas y contadores&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Verificación remota mínima tras el cambio (desde RED_GESTION)&lt;br /&gt;
ssh &amp;lt;usuario&amp;gt;@&amp;lt;IP-del-servidor&amp;gt;          # el 22 debe seguir accesible&lt;br /&gt;
curl -Is http://&amp;lt;IP-del-servidor&amp;gt;/ | head -1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Aviso|'''Riesgo operativo''': editar &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; con valores erróneos y ejecutar el script '''puede dejar la máquina inaccesible por SSH''' (la política final es &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;). Realizar siempre el cambio con una consola de &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt; abierta como vía de recuperación.}}&lt;br /&gt;
&lt;br /&gt;
= Diagnósticos =&lt;br /&gt;
&lt;br /&gt;
== Comandos de diagnóstico ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Estado general de la VM desde el host de virtualización&lt;br /&gt;
virsh dominfo cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
virsh domifaddr cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Dentro de la VM — estado de servicios&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
journalctl -u apache2 -n 100 --no-pager&lt;br /&gt;
journalctl -u xibo-xmr.service -n 100 --no-pager&lt;br /&gt;
&lt;br /&gt;
# Conexión a la base de datos del CMS&lt;br /&gt;
mysql -u &amp;lt;usuario-cms&amp;gt; -p -e &amp;quot;SELECT COUNT(*) FROM display;&amp;quot; &amp;lt;bbdd-cms&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Firewall: reglas activas y contadores por regla&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Conectividad de los puertos de producto&lt;br /&gt;
ss -tlnp | grep -E ':(80|443|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Prueba del API de players (XMDS): debe responder el WSDL&lt;br /&gt;
curl -s &amp;quot;http://localhost/xmds.php?wsdl&amp;quot; | head -5&lt;br /&gt;
&lt;br /&gt;
# Comprobar identidad correcta del clon (no debe coincidir con la plantilla)&lt;br /&gt;
cat /etc/machine-id&lt;br /&gt;
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ficheros de log ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero / origen !! Contenido !! Rotación&lt;br /&gt;
|-&lt;br /&gt;
| Portal ''Administración &amp;gt; Avanzado &amp;gt; Log'' || Log de aplicación del CMS (registro de players, errores XMDS) || Gestionada por la tarea de mantenimiento del CMS&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/var/log/apache2/cartelia_access.log&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/apache2/cartelia_error.log&amp;lt;/code&amp;gt; (y &amp;lt;code&amp;gt;cartelia_ssl_*.log&amp;lt;/code&amp;gt; con el vhost HTTPS activo) || Accesos y errores del servidor web (portal y API XMDS de players) || logrotate estándar de apache2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u xibo-xmr.service&amp;lt;/code&amp;gt; || Log del servicio XMR || journald&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u ssh&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/fail2ban.log&amp;lt;/code&amp;gt; || Seguridad de acceso al SO || Estándar journald / logrotate&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Errores comunes y soluciones ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Síntoma / mensaje !! Causa probable !! Solución&lt;br /&gt;
|-&lt;br /&gt;
| El portal no carga tras el clonado || La red de la VM no se personalizó o la interfaz cambió de nombre || Revisar &amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/etc/network/interfaces.d/&amp;lt;/code&amp;gt;, y el bridge asignado en libvirt&lt;br /&gt;
|-&lt;br /&gt;
| Los players no consiguen registrarse || &amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;CMS Secret Key&amp;lt;/code&amp;gt; incorrectos, o 80/443 filtrados || Verificar sección 4.2 y &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; del firewall (4.4); probar &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; al XMDS desde la red de players&lt;br /&gt;
|-&lt;br /&gt;
| Los players se registran pero no reciben órdenes push || Dirección pública de XMR errónea, proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; no operativo o &amp;lt;code&amp;gt;xibo-xmr&amp;lt;/code&amp;gt; caído || Verificar &amp;lt;code&amp;gt;ws(s)://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt; en el portal, &amp;lt;code&amp;gt;systemctl status xibo-xmr.service&amp;lt;/code&amp;gt; y el módulo &amp;lt;code&amp;gt;proxy_wstunnel&amp;lt;/code&amp;gt; de Apache; reiniciar XMR&lt;br /&gt;
|-&lt;br /&gt;
| Aviso de certificado en el navegador || Certificado de la plantilla aún instalado || Sustituir por el certificado del FQDN del entorno&lt;br /&gt;
|-&lt;br /&gt;
| Dos clones aparecen como la misma máquina en DHCP/monitorización || &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt; no regenerado || Ejecutar &amp;lt;code&amp;gt;rm -f /etc/machine-id &amp;amp;&amp;amp; systemd-machine-id-setup&amp;lt;/code&amp;gt; y reiniciar&lt;br /&gt;
|-&lt;br /&gt;
| El CMS no conecta con la base de datos tras cambiar contraseñas || Contraseña cambiada en &amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; pero no en MariaDB (o viceversa) || Sincronizar ambas (ver sección 4.1)&lt;br /&gt;
|-&lt;br /&gt;
| Sin acceso SSH tras personalizar el firewall || &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; erróneas en &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; con política final &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt; || Entrar por &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt;, corregir &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; y re-ejecutar &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| La hora de las programaciones no coincide || Zona horaria o NTP sin configurar || &amp;lt;code&amp;gt;timedatectl set-timezone Europe/Madrid&amp;lt;/code&amp;gt; y verificar &amp;lt;code&amp;gt;timedatectl status&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia&amp;diff=19170</id>
		<title>Instalacion cartelia</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia&amp;diff=19170"/>
		<updated>2026-07-13T09:23:16Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Manual de instalación de cartelia 1.0 ==&lt;br /&gt;
[[:Media:cartelia-despliegue-vm-documentacion-tecnica.pdf|Instalación de Cartelia 1.0]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
{{DISPLAYTITLE:Cartelia — Despliegue de máquina virtual base (Debian 13 / KVM-QEMU)}}&lt;br /&gt;
&lt;br /&gt;
= 1. Introducción =&lt;br /&gt;
&lt;br /&gt;
'''Cartelia''' es el producto de cartelería digital (digital signage) de la compañía.&lt;br /&gt;
&lt;br /&gt;
El presente documento describe el procedimiento de despliegue de una nueva instancia de Cartelia partiendo de una '''máquina virtual base''' con las siguientes características:&lt;br /&gt;
&lt;br /&gt;
* Sistema operativo: '''Debian 13 (trixie)'''.&lt;br /&gt;
* Hipervisor: '''KVM/QEMU''' (gestionado mediante &amp;lt;code&amp;gt;libvirt&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;virt-manager&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Software preinstalado: '''Cartelia 1.0''', instalado en &amp;lt;code&amp;gt;/var/www/html/cartelia&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Punto de partida''': la máquina base se entrega totalmente operativa, con Cartelia instalado de forma nativa sobre Apache + PHP y la base de datos MariaDB local ya creada e inicializada.&lt;br /&gt;
&lt;br /&gt;
'''Restricciones conocidas''':&lt;br /&gt;
&lt;br /&gt;
* La plantilla base '''no debe arrancarse nunca en producción sin personalizar''': contiene identidad de máquina, claves SSH y secretos del CMS compartidos con cualquier otra copia de la plantilla.&lt;br /&gt;
* Los players (pantallas) se autentican contra el CMS mediante la clave del servidor (''CMS Key'') y la URL del CMS; cualquier cambio posterior de IP/FQDN o de claves obliga a volver a autorizar los displays.&lt;br /&gt;
&lt;br /&gt;
= 2. Arquitectura =&lt;br /&gt;
&lt;br /&gt;
== 2.1 Esquema general del despliegue ==&lt;br /&gt;
&lt;br /&gt;
[[File:Cartelia-arquitectura.png|thumb|center|900px|Esquema general del despliegue de Cartelia sobre KVM/QEMU]]&lt;br /&gt;
&lt;br /&gt;
El CMS está instalado de forma nativa sobre el sistema operativo: Apache 2 con PHP como servidor web del portal, MariaDB local como base de datos y el servicio XMR ejecutándose como unidad de systemd.&lt;br /&gt;
&lt;br /&gt;
== 2.2 Flujo del proceso de despliegue ==&lt;br /&gt;
&lt;br /&gt;
# El técnico de sistemas clona la plantilla base en el host KVM/QEMU (disco &amp;lt;code&amp;gt;qcow2&amp;lt;/code&amp;gt; + definición de dominio libvirt).&lt;br /&gt;
# En el primer arranque del clon, se personaliza la identidad del sistema operativo: &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt;, hostname, claves SSH de host, red, zona horaria y credenciales locales.&lt;br /&gt;
# Se personaliza el producto Cartelia: URL pública del CMS, secretos y contraseñas de base de datos, clave del servidor (''CMS Key''), dirección pública de XMR y personalización de marca.&lt;br /&gt;
# Se verifican los servicios, la conectividad de los players y el acceso al portal de administración.&lt;br /&gt;
# La máquina queda registrada en inventario/monitorización y se entrega.&lt;br /&gt;
&lt;br /&gt;
== 2.3 Componentes principales ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Componente !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Portal Cartelia''' || Interfaz de administración de contenidos, layouts, programaciones y pantallas. Servida por Apache 2 + PHP.&lt;br /&gt;
|-&lt;br /&gt;
| '''MariaDB (local)''' || Almacena la configuración, usuarios, programaciones y metadatos de medios del CMS. Servicio nativo del sistema.&lt;br /&gt;
|-&lt;br /&gt;
| '''XMR (Cartelia Message Relay)''' || Canal push que permite al CMS enviar órdenes inmediatas a los players (recarga de contenido, capturas, reinicio). Servicio &amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;. Los players se conectan por WebSocket a la ruta &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, que reenvía a &amp;lt;code&amp;gt;ws://127.0.0.1:8080&amp;lt;/code&amp;gt;; el puerto 9505/TCP queda además permitido en el firewall para el modo de publicación directa.&lt;br /&gt;
|-&lt;br /&gt;
| '''Biblioteca de medios''' || &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;: directorio donde el CMS guarda los ficheros multimedia subidos (configurado en ''Administración &amp;gt; Configuración &amp;gt; Ubicación de la biblioteca'' y alineado con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts).&lt;br /&gt;
|-&lt;br /&gt;
| '''libvirt / KVM-QEMU''' || Capa de virtualización que aloja la VM.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.4 Dependencias e integraciones externas ==&lt;br /&gt;
&lt;br /&gt;
* '''DNS''': registro A/AAAA del FQDN del CMS (imprescindible si los players usan nombre en lugar de IP).&lt;br /&gt;
* '''NTP''': sincronización horaria; las programaciones de contenido dependen de la hora del sistema.&lt;br /&gt;
* '''SMTP''' (opcional): relay de correo para notificaciones del CMS, si el cliente lo requiere. Se configura en el portal (''Administración &amp;gt; Configuración'', pestaña '''Mantenimiento''').&lt;br /&gt;
* '''Certificados TLS''': siempre certificados válidos, nunca autofirmados. Si el cliente dispone de certificado propio para el FQDN, lo aporta él; en caso contrario se emite con Let's Encrypt.&lt;br /&gt;
&lt;br /&gt;
= 3. Personalización del sistema operativo (dentro de la VM) =&lt;br /&gt;
&lt;br /&gt;
== 3.1 Personalización de identidad y red ==&lt;br /&gt;
&lt;br /&gt;
Todos los comandos se ejecutan como &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; desde la consola de &amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; en el primer arranque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Paso 1: regenerar las claves SSH de host (las de la plantilla son comunes a todos los clones)&lt;br /&gt;
rm -f /etc/ssh/ssh_host_*&lt;br /&gt;
dpkg-reconfigure openssh-server&lt;br /&gt;
systemctl restart ssh&lt;br /&gt;
&lt;br /&gt;
# Paso 2: hostname y resolución local&lt;br /&gt;
hostnamectl set-hostname &amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
sed -i &amp;quot;s/127.0.1.1.*/127.0.1.1\t&amp;lt;nombre-del-entorno&amp;gt; &amp;lt;FQDN-del-CMS&amp;gt;/&amp;quot; /etc/hosts&lt;br /&gt;
&lt;br /&gt;
# Paso 3: configuración de red (ifupdown, /etc/network/interfaces)&lt;br /&gt;
&lt;br /&gt;
# Paso 4: zona horaria y hora (NTP)&lt;br /&gt;
vi /etc/systemd/timesyncd.conf.d/local.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Paso 5: actualización de paquetes del SO&lt;br /&gt;
apt update &amp;amp;&amp;amp; apt upgrade -y&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.2 Arranque del producto Cartelia ==&lt;br /&gt;
&lt;br /&gt;
El CMS ya viene instalado y operativo en la máquina base; en esta fase únicamente debe verificarse el arranque de los servicios nativos tras la personalización de red:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
&lt;br /&gt;
# Si algún servicio no arranca tras el cambio de red/hostname:&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
journalctl -u apache2 -n 50 --no-pager&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.3 Verificación de la instalación ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# El portal responde en local (la máquina base publica en HTTP; ver 4.3 para HTTPS)&lt;br /&gt;
curl -Is http://localhost/ | head -1          # esperado: HTTP/1.1 200 OK (o 302 a /login)&lt;br /&gt;
&lt;br /&gt;
# Puertos de servicio a la escucha&lt;br /&gt;
ss -tlnp | grep -E ':(80|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Resolución del FQDN desde un puesto cliente&lt;br /&gt;
getent hosts &amp;lt;FQDN-del-CMS&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Acceso final: abrir &amp;lt;code&amp;gt;http://&amp;lt;FQDN-del-CMS&amp;gt;/&amp;lt;/code&amp;gt; en el navegador y validar la pantalla de login de Cartelia (o &amp;lt;code&amp;gt;https://&amp;lt;/code&amp;gt; si se ha habilitado el vhost TLS, ver 4.3).&lt;br /&gt;
&lt;br /&gt;
= 4. Configuración =&lt;br /&gt;
&lt;br /&gt;
== 4.1 Ficheros de configuración del producto ==&lt;br /&gt;
&lt;br /&gt;
La instalación es nativa (Apache + PHP + MariaDB local); estos son los ficheros que el SAT debe revisar/personalizar en cada clon:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; del CMS''' (&amp;lt;code&amp;gt;/var/www/html/cartelia/web/settings.php&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Descripción !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbhost&amp;lt;/code&amp;gt; || Host de MariaDB (normalmente &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt;) || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$dbuser&amp;lt;/code&amp;gt; || Base de datos y usuario del CMS || No cambiar salvo política del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbpass&amp;lt;/code&amp;gt; || Contraseña del usuario del CMS en MariaDB || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SECRET_KEY&amp;lt;/code&amp;gt; || Clave secreta de la instalación (cifrado interno) || Actualmente no se regenera: se mantiene el valor de la máquina base en todos los despliegues&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''XMR''' (&amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;, unidad en &amp;lt;code&amp;gt;/etc/systemd/system/xibo-xmr.service&amp;lt;/code&amp;gt;): ejecuta &amp;lt;code&amp;gt;/var/www/html/cartelia/vendor/bin/xmr.phar&amp;lt;/code&amp;gt; con PHP como usuario &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;, con reinicio automático (&amp;lt;code&amp;gt;Restart=always&amp;lt;/code&amp;gt;). Sockets por defecto: WebSocket para players en &amp;lt;code&amp;gt;127.0.0.1:8080&amp;lt;/code&amp;gt;, expuesto a través del proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, y publicación interna del CMS en &amp;lt;code&amp;gt;tcp://127.0.0.1:50001&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Tras cualquier cambio: &amp;lt;code&amp;gt;systemctl restart xibo-xmr.service&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Apache''': la máquina base incluye dos vhosts en &amp;lt;code&amp;gt;/etc/apache2/sites-available/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; (habilitado por defecto): sirve el portal en el puerto 80. En la máquina base el &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt; es la IP de la propia máquina; en cada cliente debe actualizarse al FQDN definitivo. Incluye el proxy WebSocket de XMR (&amp;lt;code&amp;gt;ProxyPass /xmr ws://127.0.0.1:8080&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;XSendFile&amp;lt;/code&amp;gt; para la entrega de medios y una exclusión de mod_security (&amp;lt;code&amp;gt;SecRuleRemoveById 920350&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; (deshabilitado por defecto): vhost TLS preparado para clientes con FQDN y certificado. Su activación se describe en la sección 4.3.&lt;br /&gt;
&lt;br /&gt;
Validar siempre con &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; antes de &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.2 Configuración desde el portal de administración de Cartelia ==&lt;br /&gt;
&lt;br /&gt;
Acceder con el usuario '''&amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt;''' y la contraseña estándar de la máquina base (conocida por el SAT; no se documenta aquí) y cambiar dicha contraseña de inmediato, ya que es común a todos los clones. A continuación:&lt;br /&gt;
&lt;br /&gt;
* ''Administración &amp;gt; Configuración &amp;gt; Red'': establecer la dirección del CMS (&amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt;) con el FQDN definitivo. Los players usan este valor para conectarse.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Clave secreta de CMS&amp;quot;''': es la clave que debe introducirse en cada player para autenticarlo contra el CMS. En un clon es idéntica a la de la máquina base (y, por tanto, conocida por cualquier otro despliegue), así que debe sustituirse por una clave nueva y única en cada cliente.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Ubicación de la biblioteca&amp;quot;''': verificar que mantiene el valor &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;; no cambiarlo, ya que debe coincidir con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts de Apache.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Red''' (sección XMR): establecer la dirección pública de XMR como &amp;lt;code&amp;gt;ws://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; (o &amp;lt;code&amp;gt;wss://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; si está activo el vhost HTTPS). Los players se conectan por WebSocket a través del proxy de Apache; el puerto 9505 permanece abierto en el firewall únicamente como vía alternativa de publicación directa.&lt;br /&gt;
&lt;br /&gt;
Los cambios de claves y direcciones obligan a volver a autorizar los displays que estuvieran dados de alta en la máquina base (en un despliegue nuevo no debería haber ninguno; si los hubiera, eliminarlos).&lt;br /&gt;
&lt;br /&gt;
== 4.3 Configuración a nivel de sistema operativo ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elemento !! Fichero / mecanismo !! Acción&lt;br /&gt;
|-&lt;br /&gt;
| Firewall || &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt; → ejecuta &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;, parametrizado por &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Editar &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; en cada despliegue (ver 4.4): la IP local está fijada a la de la máquina base y debe cambiarse junto con la red del cliente&lt;br /&gt;
|-&lt;br /&gt;
| fail2ban || &amp;lt;code&amp;gt;/etc/fail2ban/jail.d/&amp;lt;/code&amp;gt; || Verificar jail de &amp;lt;code&amp;gt;sshd&amp;lt;/code&amp;gt; activo tras el cambio de IP&lt;br /&gt;
|-&lt;br /&gt;
| Certificado TLS / HTTPS || Vhost &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; incluido de serie (deshabilitado) || Certificado siempre válido, nunca autofirmado: lo aporta el cliente si dispone de él o se emite con Let's Encrypt (&amp;lt;code&amp;gt;certbot certonly&amp;lt;/code&amp;gt; para el FQDN; requiere el puerto 80 alcanzable desde internet y renovación automática vía timer de certbot). Instalar certificado y clave en &amp;lt;code&amp;gt;/etc/ssl/cartelia/&amp;lt;/code&amp;gt; (o apuntar las directivas &amp;lt;code&amp;gt;SSL*&amp;lt;/code&amp;gt; a &amp;lt;code&amp;gt;/etc/letsencrypt/live/&amp;lt;FQDN&amp;gt;/&amp;lt;/code&amp;gt;), ajustar &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2enmod ssl proxy_wstunnel headers&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2ensite cartelia_https&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;. Activar después la redirección HTTP→HTTPS en &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; y actualizar en el portal la CMS Address (&amp;lt;code&amp;gt;https://&amp;lt;FQDN&amp;gt;&amp;lt;/code&amp;gt;) y la dirección de XMR (&amp;lt;code&amp;gt;wss://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Rotación de logs || &amp;lt;code&amp;gt;logrotate&amp;lt;/code&amp;gt; || Verificar&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 4.4 Firewall (&amp;lt;code&amp;gt;/etc/firewall/&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
El firewall se implementa con nftables mediante dos ficheros, ejecutados en el arranque por &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero !! Función&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt; || Reglas nftables: acepta 80, 443 y 9505 (XMR) hacia la IP local/flotante, 22 solo desde &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt;, checks pasivos de Zabbix (10050) desde el servidor Zabbix, ICMP y tráfico establecido; el resto de entrada se descarta (&amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Variables de entorno que parametrizan las reglas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Variables de &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; a ajustar en cada despliegue:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Valor en la máquina base !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ETH&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;ens3&amp;lt;/code&amp;gt; || Cambiar solo si la interfaz del clon tiene otro nombre (&amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; || IP de la máquina base || Cambiar siempre a la IP del cliente (debe coincidir con la configurada en la sección 3.1, paso 3)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_FLO&amp;lt;/code&amp;gt; || Igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; (sin IP flotante) || Mantener igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; salvo despliegue con alta disponibilidad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_DATOS&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar al direccionamiento del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar a la red desde la que se accede por SSH; es la única red con acceso al puerto 22&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Aplicación y verificación de cambios:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Aplicar (corta y recrea todas las reglas; las conexiones establecidas se mantienen)&lt;br /&gt;
/etc/init.d/firewall start&lt;br /&gt;
&lt;br /&gt;
# Verificar reglas cargadas y contadores&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Verificación remota mínima tras el cambio (desde RED_GESTION)&lt;br /&gt;
ssh &amp;lt;usuario&amp;gt;@&amp;lt;IP-del-servidor&amp;gt;          # el 22 debe seguir accesible&lt;br /&gt;
curl -Is http://&amp;lt;IP-del-servidor&amp;gt;/ | head -1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Aviso|'''Riesgo operativo''': editar &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; con valores erróneos y ejecutar el script '''puede dejar la máquina inaccesible por SSH''' (la política final es &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;). Realizar siempre el cambio con una consola de &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt; abierta como vía de recuperación.}}&lt;br /&gt;
&lt;br /&gt;
= 5. Diagnósticos =&lt;br /&gt;
&lt;br /&gt;
== 5.1 Comandos de diagnóstico ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Estado general de la VM desde el host de virtualización&lt;br /&gt;
virsh dominfo cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
virsh domifaddr cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Dentro de la VM — estado de servicios&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
journalctl -u apache2 -n 100 --no-pager&lt;br /&gt;
journalctl -u xibo-xmr.service -n 100 --no-pager&lt;br /&gt;
&lt;br /&gt;
# Conexión a la base de datos del CMS&lt;br /&gt;
mysql -u &amp;lt;usuario-cms&amp;gt; -p -e &amp;quot;SELECT COUNT(*) FROM display;&amp;quot; &amp;lt;bbdd-cms&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Firewall: reglas activas y contadores por regla&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Conectividad de los puertos de producto&lt;br /&gt;
ss -tlnp | grep -E ':(80|443|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Prueba del API de players (XMDS): debe responder el WSDL&lt;br /&gt;
curl -s &amp;quot;http://localhost/xmds.php?wsdl&amp;quot; | head -5&lt;br /&gt;
&lt;br /&gt;
# Comprobar identidad correcta del clon (no debe coincidir con la plantilla)&lt;br /&gt;
cat /etc/machine-id&lt;br /&gt;
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 5.2 Ficheros de log ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero / origen !! Contenido !! Rotación&lt;br /&gt;
|-&lt;br /&gt;
| Portal ''Administración &amp;gt; Avanzado &amp;gt; Log'' || Log de aplicación del CMS (registro de players, errores XMDS) || Gestionada por la tarea de mantenimiento del CMS&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/var/log/apache2/cartelia_access.log&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/apache2/cartelia_error.log&amp;lt;/code&amp;gt; (y &amp;lt;code&amp;gt;cartelia_ssl_*.log&amp;lt;/code&amp;gt; con el vhost HTTPS activo) || Accesos y errores del servidor web (portal y API XMDS de players) || logrotate estándar de apache2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u xibo-xmr.service&amp;lt;/code&amp;gt; || Log del servicio XMR || journald&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u ssh&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/fail2ban.log&amp;lt;/code&amp;gt; || Seguridad de acceso al SO || Estándar journald / logrotate&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 5.3 Errores comunes y soluciones ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Síntoma / mensaje !! Causa probable !! Solución&lt;br /&gt;
|-&lt;br /&gt;
| El portal no carga tras el clonado || La red de la VM no se personalizó o la interfaz cambió de nombre || Revisar &amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/etc/network/interfaces.d/&amp;lt;/code&amp;gt;, y el bridge asignado en libvirt&lt;br /&gt;
|-&lt;br /&gt;
| Los players no consiguen registrarse || &amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;CMS Secret Key&amp;lt;/code&amp;gt; incorrectos, o 80/443 filtrados || Verificar sección 4.2 y &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; del firewall (4.4); probar &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; al XMDS desde la red de players&lt;br /&gt;
|-&lt;br /&gt;
| Los players se registran pero no reciben órdenes push || Dirección pública de XMR errónea, proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; no operativo o &amp;lt;code&amp;gt;xibo-xmr&amp;lt;/code&amp;gt; caído || Verificar &amp;lt;code&amp;gt;ws(s)://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt; en el portal, &amp;lt;code&amp;gt;systemctl status xibo-xmr.service&amp;lt;/code&amp;gt; y el módulo &amp;lt;code&amp;gt;proxy_wstunnel&amp;lt;/code&amp;gt; de Apache; reiniciar XMR&lt;br /&gt;
|-&lt;br /&gt;
| Aviso de certificado en el navegador || Certificado de la plantilla aún instalado || Sustituir por el certificado del FQDN del entorno&lt;br /&gt;
|-&lt;br /&gt;
| Dos clones aparecen como la misma máquina en DHCP/monitorización || &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt; no regenerado || Ejecutar &amp;lt;code&amp;gt;rm -f /etc/machine-id &amp;amp;&amp;amp; systemd-machine-id-setup&amp;lt;/code&amp;gt; y reiniciar&lt;br /&gt;
|-&lt;br /&gt;
| El CMS no conecta con la base de datos tras cambiar contraseñas || Contraseña cambiada en &amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; pero no en MariaDB (o viceversa) || Sincronizar ambas (ver sección 4.1)&lt;br /&gt;
|-&lt;br /&gt;
| Sin acceso SSH tras personalizar el firewall || &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; erróneas en &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; con política final &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt; || Entrar por &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt;, corregir &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; y re-ejecutar &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| La hora de las programaciones no coincide || Zona horaria o NTP sin configurar || &amp;lt;code&amp;gt;timedatectl set-timezone Europe/Madrid&amp;lt;/code&amp;gt; y verificar &amp;lt;code&amp;gt;timedatectl status&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia&amp;diff=19169</id>
		<title>Instalacion cartelia</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia&amp;diff=19169"/>
		<updated>2026-07-13T09:22:42Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* Manual de instalación de cartelia 1.0 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Manual de instalación de cartelia 1.0 ==&lt;br /&gt;
[[:Media:cartelia-despliegue-vm-documentacion-tecnica.pdf|Instalación de Cartelia 1.0]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
{{DISPLAYTITLE:Cartelia — Despliegue de máquina virtual base (Debian 13 / KVM-QEMU)}}&lt;br /&gt;
&lt;br /&gt;
'''Documentación técnica de proceso'''&amp;lt;br/&amp;gt;&lt;br /&gt;
Versión del documento: 1.0 · Producto: Cartelia 1.0&amp;lt;br/&amp;gt;&lt;br /&gt;
Fecha: 09/07/2026 · Responsable: Iván Matarrubias&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= 1. Introducción =&lt;br /&gt;
&lt;br /&gt;
'''Cartelia''' es el producto de cartelería digital (digital signage) de la compañía.&lt;br /&gt;
&lt;br /&gt;
El presente documento describe el procedimiento de despliegue de una nueva instancia de Cartelia partiendo de una '''máquina virtual base''' con las siguientes características:&lt;br /&gt;
&lt;br /&gt;
* Sistema operativo: '''Debian 13 (trixie)'''.&lt;br /&gt;
* Hipervisor: '''KVM/QEMU''' (gestionado mediante &amp;lt;code&amp;gt;libvirt&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;virt-manager&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Software preinstalado: '''Cartelia 1.0''', instalado en &amp;lt;code&amp;gt;/var/www/html/cartelia&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Punto de partida''': la máquina base se entrega totalmente operativa, con Cartelia instalado de forma nativa sobre Apache + PHP y la base de datos MariaDB local ya creada e inicializada.&lt;br /&gt;
&lt;br /&gt;
'''Restricciones conocidas''':&lt;br /&gt;
&lt;br /&gt;
* La plantilla base '''no debe arrancarse nunca en producción sin personalizar''': contiene identidad de máquina, claves SSH y secretos del CMS compartidos con cualquier otra copia de la plantilla.&lt;br /&gt;
* Los players (pantallas) se autentican contra el CMS mediante la clave del servidor (''CMS Key'') y la URL del CMS; cualquier cambio posterior de IP/FQDN o de claves obliga a volver a autorizar los displays.&lt;br /&gt;
&lt;br /&gt;
= 2. Arquitectura =&lt;br /&gt;
&lt;br /&gt;
== 2.1 Esquema general del despliegue ==&lt;br /&gt;
&lt;br /&gt;
[[File:Cartelia-arquitectura.png|thumb|center|900px|Esquema general del despliegue de Cartelia sobre KVM/QEMU]]&lt;br /&gt;
&lt;br /&gt;
El CMS está instalado de forma nativa sobre el sistema operativo: Apache 2 con PHP como servidor web del portal, MariaDB local como base de datos y el servicio XMR ejecutándose como unidad de systemd.&lt;br /&gt;
&lt;br /&gt;
== 2.2 Flujo del proceso de despliegue ==&lt;br /&gt;
&lt;br /&gt;
# El técnico de sistemas clona la plantilla base en el host KVM/QEMU (disco &amp;lt;code&amp;gt;qcow2&amp;lt;/code&amp;gt; + definición de dominio libvirt).&lt;br /&gt;
# En el primer arranque del clon, se personaliza la identidad del sistema operativo: &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt;, hostname, claves SSH de host, red, zona horaria y credenciales locales.&lt;br /&gt;
# Se personaliza el producto Cartelia: URL pública del CMS, secretos y contraseñas de base de datos, clave del servidor (''CMS Key''), dirección pública de XMR y personalización de marca.&lt;br /&gt;
# Se verifican los servicios, la conectividad de los players y el acceso al portal de administración.&lt;br /&gt;
# La máquina queda registrada en inventario/monitorización y se entrega.&lt;br /&gt;
&lt;br /&gt;
== 2.3 Componentes principales ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Componente !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Portal Cartelia''' || Interfaz de administración de contenidos, layouts, programaciones y pantallas. Servida por Apache 2 + PHP.&lt;br /&gt;
|-&lt;br /&gt;
| '''MariaDB (local)''' || Almacena la configuración, usuarios, programaciones y metadatos de medios del CMS. Servicio nativo del sistema.&lt;br /&gt;
|-&lt;br /&gt;
| '''XMR (Cartelia Message Relay)''' || Canal push que permite al CMS enviar órdenes inmediatas a los players (recarga de contenido, capturas, reinicio). Servicio &amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;. Los players se conectan por WebSocket a la ruta &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, que reenvía a &amp;lt;code&amp;gt;ws://127.0.0.1:8080&amp;lt;/code&amp;gt;; el puerto 9505/TCP queda además permitido en el firewall para el modo de publicación directa.&lt;br /&gt;
|-&lt;br /&gt;
| '''Biblioteca de medios''' || &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;: directorio donde el CMS guarda los ficheros multimedia subidos (configurado en ''Administración &amp;gt; Configuración &amp;gt; Ubicación de la biblioteca'' y alineado con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts).&lt;br /&gt;
|-&lt;br /&gt;
| '''libvirt / KVM-QEMU''' || Capa de virtualización que aloja la VM.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.4 Dependencias e integraciones externas ==&lt;br /&gt;
&lt;br /&gt;
* '''DNS''': registro A/AAAA del FQDN del CMS (imprescindible si los players usan nombre en lugar de IP).&lt;br /&gt;
* '''NTP''': sincronización horaria; las programaciones de contenido dependen de la hora del sistema.&lt;br /&gt;
* '''SMTP''' (opcional): relay de correo para notificaciones del CMS, si el cliente lo requiere. Se configura en el portal (''Administración &amp;gt; Configuración'', pestaña '''Mantenimiento''').&lt;br /&gt;
* '''Certificados TLS''': siempre certificados válidos, nunca autofirmados. Si el cliente dispone de certificado propio para el FQDN, lo aporta él; en caso contrario se emite con Let's Encrypt.&lt;br /&gt;
&lt;br /&gt;
= 3. Personalización del sistema operativo (dentro de la VM) =&lt;br /&gt;
&lt;br /&gt;
== 3.1 Personalización de identidad y red ==&lt;br /&gt;
&lt;br /&gt;
Todos los comandos se ejecutan como &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; desde la consola de &amp;lt;code&amp;gt;virsh&amp;lt;/code&amp;gt; en el primer arranque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Paso 1: regenerar las claves SSH de host (las de la plantilla son comunes a todos los clones)&lt;br /&gt;
rm -f /etc/ssh/ssh_host_*&lt;br /&gt;
dpkg-reconfigure openssh-server&lt;br /&gt;
systemctl restart ssh&lt;br /&gt;
&lt;br /&gt;
# Paso 2: hostname y resolución local&lt;br /&gt;
hostnamectl set-hostname &amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
sed -i &amp;quot;s/127.0.1.1.*/127.0.1.1\t&amp;lt;nombre-del-entorno&amp;gt; &amp;lt;FQDN-del-CMS&amp;gt;/&amp;quot; /etc/hosts&lt;br /&gt;
&lt;br /&gt;
# Paso 3: configuración de red (ifupdown, /etc/network/interfaces)&lt;br /&gt;
&lt;br /&gt;
# Paso 4: zona horaria y hora (NTP)&lt;br /&gt;
vi /etc/systemd/timesyncd.conf.d/local.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Paso 5: actualización de paquetes del SO&lt;br /&gt;
apt update &amp;amp;&amp;amp; apt upgrade -y&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.2 Arranque del producto Cartelia ==&lt;br /&gt;
&lt;br /&gt;
El CMS ya viene instalado y operativo en la máquina base; en esta fase únicamente debe verificarse el arranque de los servicios nativos tras la personalización de red:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
&lt;br /&gt;
# Si algún servicio no arranca tras el cambio de red/hostname:&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
journalctl -u apache2 -n 50 --no-pager&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.3 Verificación de la instalación ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# El portal responde en local (la máquina base publica en HTTP; ver 4.3 para HTTPS)&lt;br /&gt;
curl -Is http://localhost/ | head -1          # esperado: HTTP/1.1 200 OK (o 302 a /login)&lt;br /&gt;
&lt;br /&gt;
# Puertos de servicio a la escucha&lt;br /&gt;
ss -tlnp | grep -E ':(80|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Resolución del FQDN desde un puesto cliente&lt;br /&gt;
getent hosts &amp;lt;FQDN-del-CMS&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Acceso final: abrir &amp;lt;code&amp;gt;http://&amp;lt;FQDN-del-CMS&amp;gt;/&amp;lt;/code&amp;gt; en el navegador y validar la pantalla de login de Cartelia (o &amp;lt;code&amp;gt;https://&amp;lt;/code&amp;gt; si se ha habilitado el vhost TLS, ver 4.3).&lt;br /&gt;
&lt;br /&gt;
= 4. Configuración =&lt;br /&gt;
&lt;br /&gt;
== 4.1 Ficheros de configuración del producto ==&lt;br /&gt;
&lt;br /&gt;
La instalación es nativa (Apache + PHP + MariaDB local); estos son los ficheros que el SAT debe revisar/personalizar en cada clon:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; del CMS''' (&amp;lt;code&amp;gt;/var/www/html/cartelia/web/settings.php&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Descripción !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbhost&amp;lt;/code&amp;gt; || Host de MariaDB (normalmente &amp;lt;code&amp;gt;localhost&amp;lt;/code&amp;gt;) || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$dbuser&amp;lt;/code&amp;gt; || Base de datos y usuario del CMS || No cambiar salvo política del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$dbpass&amp;lt;/code&amp;gt; || Contraseña del usuario del CMS en MariaDB || No cambiar&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SECRET_KEY&amp;lt;/code&amp;gt; || Clave secreta de la instalación (cifrado interno) || Actualmente no se regenera: se mantiene el valor de la máquina base en todos los despliegues&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''XMR''' (&amp;lt;code&amp;gt;xibo-xmr.service&amp;lt;/code&amp;gt;, unidad en &amp;lt;code&amp;gt;/etc/systemd/system/xibo-xmr.service&amp;lt;/code&amp;gt;): ejecuta &amp;lt;code&amp;gt;/var/www/html/cartelia/vendor/bin/xmr.phar&amp;lt;/code&amp;gt; con PHP como usuario &amp;lt;code&amp;gt;www-data&amp;lt;/code&amp;gt;, con reinicio automático (&amp;lt;code&amp;gt;Restart=always&amp;lt;/code&amp;gt;). Sockets por defecto: WebSocket para players en &amp;lt;code&amp;gt;127.0.0.1:8080&amp;lt;/code&amp;gt;, expuesto a través del proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; del vhost de Apache, y publicación interna del CMS en &amp;lt;code&amp;gt;tcp://127.0.0.1:50001&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Tras cualquier cambio: &amp;lt;code&amp;gt;systemctl restart xibo-xmr.service&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Apache''': la máquina base incluye dos vhosts en &amp;lt;code&amp;gt;/etc/apache2/sites-available/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; (habilitado por defecto): sirve el portal en el puerto 80. En la máquina base el &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt; es la IP de la propia máquina; en cada cliente debe actualizarse al FQDN definitivo. Incluye el proxy WebSocket de XMR (&amp;lt;code&amp;gt;ProxyPass /xmr ws://127.0.0.1:8080&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;XSendFile&amp;lt;/code&amp;gt; para la entrega de medios y una exclusión de mod_security (&amp;lt;code&amp;gt;SecRuleRemoveById 920350&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; (deshabilitado por defecto): vhost TLS preparado para clientes con FQDN y certificado. Su activación se describe en la sección 4.3.&lt;br /&gt;
&lt;br /&gt;
Validar siempre con &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; antes de &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.2 Configuración desde el portal de administración de Cartelia ==&lt;br /&gt;
&lt;br /&gt;
Acceder con el usuario '''&amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt;''' y la contraseña estándar de la máquina base (conocida por el SAT; no se documenta aquí) y cambiar dicha contraseña de inmediato, ya que es común a todos los clones. A continuación:&lt;br /&gt;
&lt;br /&gt;
* ''Administración &amp;gt; Configuración &amp;gt; Red'': establecer la dirección del CMS (&amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt;) con el FQDN definitivo. Los players usan este valor para conectarse.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Clave secreta de CMS&amp;quot;''': es la clave que debe introducirse en cada player para autenticarlo contra el CMS. En un clon es idéntica a la de la máquina base (y, por tanto, conocida por cualquier otro despliegue), así que debe sustituirse por una clave nueva y única en cada cliente.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Configuración''', campo '''&amp;quot;Ubicación de la biblioteca&amp;quot;''': verificar que mantiene el valor &amp;lt;code&amp;gt;/var/lib/cartelia/library/&amp;lt;/code&amp;gt;; no cambiarlo, ya que debe coincidir con la directiva &amp;lt;code&amp;gt;XSendFilePath&amp;lt;/code&amp;gt; de los vhosts de Apache.&lt;br /&gt;
* ''Administración &amp;gt; Configuración'', pestaña '''Red''' (sección XMR): establecer la dirección pública de XMR como &amp;lt;code&amp;gt;ws://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; (o &amp;lt;code&amp;gt;wss://&amp;lt;FQDN-del-CMS&amp;gt;/xmr&amp;lt;/code&amp;gt; si está activo el vhost HTTPS). Los players se conectan por WebSocket a través del proxy de Apache; el puerto 9505 permanece abierto en el firewall únicamente como vía alternativa de publicación directa.&lt;br /&gt;
&lt;br /&gt;
Los cambios de claves y direcciones obligan a volver a autorizar los displays que estuvieran dados de alta en la máquina base (en un despliegue nuevo no debería haber ninguno; si los hubiera, eliminarlos).&lt;br /&gt;
&lt;br /&gt;
== 4.3 Configuración a nivel de sistema operativo ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elemento !! Fichero / mecanismo !! Acción&lt;br /&gt;
|-&lt;br /&gt;
| Firewall || &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt; → ejecuta &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;, parametrizado por &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Editar &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; en cada despliegue (ver 4.4): la IP local está fijada a la de la máquina base y debe cambiarse junto con la red del cliente&lt;br /&gt;
|-&lt;br /&gt;
| fail2ban || &amp;lt;code&amp;gt;/etc/fail2ban/jail.d/&amp;lt;/code&amp;gt; || Verificar jail de &amp;lt;code&amp;gt;sshd&amp;lt;/code&amp;gt; activo tras el cambio de IP&lt;br /&gt;
|-&lt;br /&gt;
| Certificado TLS / HTTPS || Vhost &amp;lt;code&amp;gt;cartelia_https.conf&amp;lt;/code&amp;gt; incluido de serie (deshabilitado) || Certificado siempre válido, nunca autofirmado: lo aporta el cliente si dispone de él o se emite con Let's Encrypt (&amp;lt;code&amp;gt;certbot certonly&amp;lt;/code&amp;gt; para el FQDN; requiere el puerto 80 alcanzable desde internet y renovación automática vía timer de certbot). Instalar certificado y clave en &amp;lt;code&amp;gt;/etc/ssl/cartelia/&amp;lt;/code&amp;gt; (o apuntar las directivas &amp;lt;code&amp;gt;SSL*&amp;lt;/code&amp;gt; a &amp;lt;code&amp;gt;/etc/letsencrypt/live/&amp;lt;FQDN&amp;gt;/&amp;lt;/code&amp;gt;), ajustar &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2enmod ssl proxy_wstunnel headers&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;a2ensite cartelia_https&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;apache2ctl configtest&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;systemctl reload apache2&amp;lt;/code&amp;gt;. Activar después la redirección HTTP→HTTPS en &amp;lt;code&amp;gt;cartelia_http.conf&amp;lt;/code&amp;gt; y actualizar en el portal la CMS Address (&amp;lt;code&amp;gt;https://&amp;lt;FQDN&amp;gt;&amp;lt;/code&amp;gt;) y la dirección de XMR (&amp;lt;code&amp;gt;wss://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Rotación de logs || &amp;lt;code&amp;gt;logrotate&amp;lt;/code&amp;gt; || Verificar&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 4.4 Firewall (&amp;lt;code&amp;gt;/etc/firewall/&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
El firewall se implementa con nftables mediante dos ficheros, ejecutados en el arranque por &amp;lt;code&amp;gt;firewall.service&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero !! Función&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt; || Reglas nftables: acepta 80, 443 y 9505 (XMR) hacia la IP local/flotante, 22 solo desde &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt;, checks pasivos de Zabbix (10050) desde el servidor Zabbix, ICMP y tráfico establecido; el resto de entrada se descarta (&amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt; || Variables de entorno que parametrizan las reglas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Variables de &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; a ajustar en cada despliegue:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Valor en la máquina base !! Acción en el despliegue&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ETH&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;ens3&amp;lt;/code&amp;gt; || Cambiar solo si la interfaz del clon tiene otro nombre (&amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; || IP de la máquina base || Cambiar siempre a la IP del cliente (debe coincidir con la configurada en la sección 3.1, paso 3)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IP_FLO&amp;lt;/code&amp;gt; || Igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; (sin IP flotante) || Mantener igual a &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; salvo despliegue con alta disponibilidad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_DATOS&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar al direccionamiento del cliente&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; || Red corporativa de la máquina base || Ajustar a la red desde la que se accede por SSH; es la única red con acceso al puerto 22&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Aplicación y verificación de cambios:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Aplicar (corta y recrea todas las reglas; las conexiones establecidas se mantienen)&lt;br /&gt;
/etc/init.d/firewall start&lt;br /&gt;
&lt;br /&gt;
# Verificar reglas cargadas y contadores&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Verificación remota mínima tras el cambio (desde RED_GESTION)&lt;br /&gt;
ssh &amp;lt;usuario&amp;gt;@&amp;lt;IP-del-servidor&amp;gt;          # el 22 debe seguir accesible&lt;br /&gt;
curl -Is http://&amp;lt;IP-del-servidor&amp;gt;/ | head -1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Aviso|'''Riesgo operativo''': editar &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; con valores erróneos y ejecutar el script '''puede dejar la máquina inaccesible por SSH''' (la política final es &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;). Realizar siempre el cambio con una consola de &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt; abierta como vía de recuperación.}}&lt;br /&gt;
&lt;br /&gt;
= 5. Diagnósticos =&lt;br /&gt;
&lt;br /&gt;
== 5.1 Comandos de diagnóstico ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Estado general de la VM desde el host de virtualización&lt;br /&gt;
virsh dominfo cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
virsh domifaddr cartelia-&amp;lt;nombre-del-entorno&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Dentro de la VM — estado de servicios&lt;br /&gt;
systemctl status apache2 mariadb&lt;br /&gt;
systemctl status xibo-xmr.service&lt;br /&gt;
journalctl -u apache2 -n 100 --no-pager&lt;br /&gt;
journalctl -u xibo-xmr.service -n 100 --no-pager&lt;br /&gt;
&lt;br /&gt;
# Conexión a la base de datos del CMS&lt;br /&gt;
mysql -u &amp;lt;usuario-cms&amp;gt; -p -e &amp;quot;SELECT COUNT(*) FROM display;&amp;quot; &amp;lt;bbdd-cms&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Firewall: reglas activas y contadores por regla&lt;br /&gt;
/etc/init.d/firewall status&lt;br /&gt;
&lt;br /&gt;
# Conectividad de los puertos de producto&lt;br /&gt;
ss -tlnp | grep -E ':(80|443|9505)\b'&lt;br /&gt;
&lt;br /&gt;
# Prueba del API de players (XMDS): debe responder el WSDL&lt;br /&gt;
curl -s &amp;quot;http://localhost/xmds.php?wsdl&amp;quot; | head -5&lt;br /&gt;
&lt;br /&gt;
# Comprobar identidad correcta del clon (no debe coincidir con la plantilla)&lt;br /&gt;
cat /etc/machine-id&lt;br /&gt;
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 5.2 Ficheros de log ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Fichero / origen !! Contenido !! Rotación&lt;br /&gt;
|-&lt;br /&gt;
| Portal ''Administración &amp;gt; Avanzado &amp;gt; Log'' || Log de aplicación del CMS (registro de players, errores XMDS) || Gestionada por la tarea de mantenimiento del CMS&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/var/log/apache2/cartelia_access.log&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/apache2/cartelia_error.log&amp;lt;/code&amp;gt; (y &amp;lt;code&amp;gt;cartelia_ssl_*.log&amp;lt;/code&amp;gt; con el vhost HTTPS activo) || Accesos y errores del servidor web (portal y API XMDS de players) || logrotate estándar de apache2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u xibo-xmr.service&amp;lt;/code&amp;gt; || Log del servicio XMR || journald&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;journalctl -u ssh&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/var/log/fail2ban.log&amp;lt;/code&amp;gt; || Seguridad de acceso al SO || Estándar journald / logrotate&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 5.3 Errores comunes y soluciones ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Síntoma / mensaje !! Causa probable !! Solución&lt;br /&gt;
|-&lt;br /&gt;
| El portal no carga tras el clonado || La red de la VM no se personalizó o la interfaz cambió de nombre || Revisar &amp;lt;code&amp;gt;ip a&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/etc/network/interfaces.d/&amp;lt;/code&amp;gt;, y el bridge asignado en libvirt&lt;br /&gt;
|-&lt;br /&gt;
| Los players no consiguen registrarse || &amp;lt;code&amp;gt;CMS Address&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;CMS Secret Key&amp;lt;/code&amp;gt; incorrectos, o 80/443 filtrados || Verificar sección 4.2 y &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; del firewall (4.4); probar &amp;lt;code&amp;gt;curl&amp;lt;/code&amp;gt; al XMDS desde la red de players&lt;br /&gt;
|-&lt;br /&gt;
| Los players se registran pero no reciben órdenes push || Dirección pública de XMR errónea, proxy &amp;lt;code&amp;gt;/xmr&amp;lt;/code&amp;gt; no operativo o &amp;lt;code&amp;gt;xibo-xmr&amp;lt;/code&amp;gt; caído || Verificar &amp;lt;code&amp;gt;ws(s)://&amp;lt;FQDN&amp;gt;/xmr&amp;lt;/code&amp;gt; en el portal, &amp;lt;code&amp;gt;systemctl status xibo-xmr.service&amp;lt;/code&amp;gt; y el módulo &amp;lt;code&amp;gt;proxy_wstunnel&amp;lt;/code&amp;gt; de Apache; reiniciar XMR&lt;br /&gt;
|-&lt;br /&gt;
| Aviso de certificado en el navegador || Certificado de la plantilla aún instalado || Sustituir por el certificado del FQDN del entorno&lt;br /&gt;
|-&lt;br /&gt;
| Dos clones aparecen como la misma máquina en DHCP/monitorización || &amp;lt;code&amp;gt;machine-id&amp;lt;/code&amp;gt; no regenerado || Ejecutar &amp;lt;code&amp;gt;rm -f /etc/machine-id &amp;amp;&amp;amp; systemd-machine-id-setup&amp;lt;/code&amp;gt; y reiniciar&lt;br /&gt;
|-&lt;br /&gt;
| El CMS no conecta con la base de datos tras cambiar contraseñas || Contraseña cambiada en &amp;lt;code&amp;gt;settings.php&amp;lt;/code&amp;gt; pero no en MariaDB (o viceversa) || Sincronizar ambas (ver sección 4.1)&lt;br /&gt;
|-&lt;br /&gt;
| Sin acceso SSH tras personalizar el firewall || &amp;lt;code&amp;gt;RED_GESTION&amp;lt;/code&amp;gt; o &amp;lt;code&amp;gt;IP_LOC&amp;lt;/code&amp;gt; erróneas en &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; con política final &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt; || Entrar por &amp;lt;code&amp;gt;virsh console&amp;lt;/code&amp;gt;, corregir &amp;lt;code&amp;gt;vars.sh&amp;lt;/code&amp;gt; y re-ejecutar &amp;lt;code&amp;gt;/etc/firewall/firewall.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| La hora de las programaciones no coincide || Zona horaria o NTP sin configurar || &amp;lt;code&amp;gt;timedatectl set-timezone Europe/Madrid&amp;lt;/code&amp;gt; y verificar &amp;lt;code&amp;gt;timedatectl status&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Archivo:Cartelia-despliegue-vm-documentacion-tecnica.pdf&amp;diff=19168</id>
		<title>Archivo:Cartelia-despliegue-vm-documentacion-tecnica.pdf</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Archivo:Cartelia-despliegue-vm-documentacion-tecnica.pdf&amp;diff=19168"/>
		<updated>2026-07-13T08:28:41Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia&amp;diff=19167</id>
		<title>Instalacion cartelia</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia&amp;diff=19167"/>
		<updated>2026-07-13T08:28:27Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* Manual de instalación de cartelia 1.0 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Manual de instalación de cartelia 1.0 ==&lt;br /&gt;
[[:Media:cartelia-despliegue-vm-documentacion-tecnica.pdf|Instalación de Cartelia 1.0]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Omnisuite_videoCan&amp;diff=19166</id>
		<title>Omnisuite videoCan</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Omnisuite_videoCan&amp;diff=19166"/>
		<updated>2026-07-13T08:26:36Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Qué es Videocan ==&lt;br /&gt;
&lt;br /&gt;
Videocan es una plataforma de vídeo que dota de '''videocanal''' a un contact center basado en OmniSuite. Permite que una interacción que entra como '''chat''' a través de '''OpenChannel''' se convierta, en la práctica, en una '''videollamada de audio y vídeo''' entre un usuario externo y un agente.&lt;br /&gt;
&lt;br /&gt;
La idea central es sencilla: la llamada '''no es una llamada de audio tradicional''' (no interviene Asterisk en ningún punto). El usuario y el agente acaban entrando en la '''misma sala de videoconferencia''' (hoy basada en Jitsi Meet, comercialmente &amp;quot;Vybite Meet&amp;quot;), y todo el control de cola, enrutado y atención del agente se apoya en la infraestructura existente de OmniSuite vía OpenChannel.&lt;br /&gt;
&lt;br /&gt;
Puntos clave del alcance funcional actual:&lt;br /&gt;
* Solo hay '''audio y vídeo'''. No hay compartición de pantalla.&lt;br /&gt;
* El '''chat está desactivado''': si se quisiera, debería salir por OpenChannel, no por Meet, así que de momento no se usa.&lt;br /&gt;
* Sustituye a la solución anterior basada en '''Vydao''', que se ha reemplazado por '''Meet'''.&lt;br /&gt;
&lt;br /&gt;
=== Contexto: qué es un OpenChannel ===&lt;br /&gt;
&lt;br /&gt;
OpenChannel es el mecanismo de OmniSuite para meter un '''canal de chat''' dentro del contact center. Lo que se inicia es, técnicamente, una '''interacción de chat''' que se encola, hereda todos los procesos típicos de OmniSuite (colas, prioridades, asignación) y acaba siendo atendida por un agente. Videocan se apoya en ese canal de chat para transportar al agente el enlace de la videollamada.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Flujo funcional ==&lt;br /&gt;
&lt;br /&gt;
=== Llamada entrante (usuario → agente) ===&lt;br /&gt;
&lt;br /&gt;
# Un usuario, desde una aplicación web, un navegador o una '''app móvil''' (que internamente abre una página web), introduce una serie de datos y pulsa '''&amp;quot;Iniciar videollamada&amp;quot;'''.&lt;br /&gt;
# Ese evento desencadena '''dos cosas en paralelo''':&lt;br /&gt;
#* '''Lado usuario:''' se le crea una '''sala de Meet''' y queda en la pantalla de espera de la sala (&amp;quot;esperando conexión&amp;quot;).&lt;br /&gt;
#* '''Lado OmniSuite:''' se genera una '''interacción de chat por OpenChannel''' que se encola y llega a un agente.&lt;br /&gt;
# El agente (logueado en OmniSuite con sus canales) recibe el aviso de interacción en cola. Al aceptarla se le abre una pestaña tipo chat con un mensaje del estilo ''&amp;quot;Nueva llamada de [Nombre], pulsa aquí para unirte&amp;quot;'' y una '''URL'''.&lt;br /&gt;
# Esa URL '''no es una URL de Meet''': es una URL del '''API de agente de Videocan''' (lleva &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;get&amp;lt;/code&amp;gt;, agente, api-key, etc.). El agente la pulsa.&lt;br /&gt;
# Videocan, a partir de esa URL, '''autentica al agente como moderador''' en Meet mediante '''JWT''' y lo introduce en la sala (la misma del usuario).&lt;br /&gt;
# Se establece la videollamada. El usuario, que estaba esperando, ve entrar al agente y comienza la comunicación (audio + vídeo vía Meet).&lt;br /&gt;
&lt;br /&gt;
Detalle de seguridad relevante: '''el agente no conoce el nombre de la sala'''. En la URL que recibe va &amp;quot;encholado&amp;quot; (codificado) tanto el JWT como el nombre de sala, de modo que esa URL solo sirve para '''entrarn en esa sala concreta'''.&lt;br /&gt;
&lt;br /&gt;
=== Llamada saliente / &amp;quot;nueva sala&amp;quot; (agente → usuario) ===&lt;br /&gt;
&lt;br /&gt;
La llamada saliente asume que ya existe un canal de comunicación con el destinatario. El mecanismo es deliberadamente simple:&lt;br /&gt;
&lt;br /&gt;
# El agente dispone de un '''plugin / botón (&amp;quot;compartir enlace&amp;quot;)''' que genera una nueva sala.&lt;br /&gt;
# Videocan '''crea el nombre de la sala al vuelo''' (aleatorio) — la sala la crea Videocan, no Meet directamente.&lt;br /&gt;
# Videocan genera un '''JWT''' firmado para esa sala y construye una página web que mete al agente '''ya autenticado''' como moderador.&lt;br /&gt;
# El agente '''copia el enlace''' de la reunión y lo envía al destinatario por el canal que corresponda (p. ej. WhatsApp, el propio canal por el que se estuviera hablando).&lt;br /&gt;
# Cualquiera que abra ese enlace entra en la sala. Si lo abren varios, entran varios.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;El '''API de agente está filtrado por IP''': solo se puede invocar desde dentro (IP privada) o desde una IP fija conocida (p. ej. la salida del entorno del cliente), según el despliegue.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Cierre de la llamada ===&lt;br /&gt;
&lt;br /&gt;
La interacción de OpenChannel debería cerrarse al colgar la videollamada (se cuelga &amp;quot;como se cuelga una llamada&amp;quot;). En la demo se observó que en ocasiones el agente tuvo que cerrarla a mano en OpenChannel; queda como punto a confirmar con el equipo experto en OmniSuite si el cierre debe ser automático o manual. Como red de seguridad existen ''timeouts'' (ver §6) para liberar el canal aunque algo quede colgado.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Arquitectura y componentes ==&lt;br /&gt;
&lt;br /&gt;
Todo el módulo se despliega en una '''máquina virtual independiente''' (separada de la de OpenChannel/OmniSuite), sobre '''Debian 13''', y '''requiere una IP pública dedicada''' (puede estar NATeada 1:1). El puerto de RTP de Meet usa esa IP pública.&lt;br /&gt;
&lt;br /&gt;
Conceptualmente es '''una instalación de Vybite Meet (Jitsi) personalizada''' más el demonio propio Videocan. Componentes:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Componente !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Nginx''' || Proxy inverso y servidor de contenido. Punto de entrada HTTPS (443/TCP). Publica los tres APIs de Videocan.&lt;br /&gt;
|-&lt;br /&gt;
| '''Certbot''' || Generación y renovación automática de certificados TLS (Let's Encrypt). Solo en instalaciones '''públicas'''; en instalaciones internas no se instala.&lt;br /&gt;
|-&lt;br /&gt;
| '''Prosody''' || Servidor XMPP (programado en Lua) sobre el que se apoya Meet. Equivalente moderno al antiguo OpenFire.&lt;br /&gt;
|-&lt;br /&gt;
| '''Módulo Prosody propio (&amp;quot;mod&amp;quot;)''' || Módulo desarrollado a medida que engancha con Videocan; informa de entradas y salidas de la sala para mantener sincronizado OpenChannel con el estado real de Meet.&lt;br /&gt;
|-&lt;br /&gt;
| '''Jitsi Meet + Jicofo + JVB''' || Pila de videoconferencia. '''JVB = Jitsi Video Bridge''' (puente de medios). Se instala mediante una lista de paquetes homologados.&lt;br /&gt;
|-&lt;br /&gt;
| '''Videocan (demonio)''' || Demonio propio. Es el &amp;quot;cerebro&amp;quot;: expone los APIs, controla canales/llamadas, construye plantillas, gestiona la autenticación del agente y aplica la firma de licencia.&lt;br /&gt;
|-&lt;br /&gt;
| '''Fail2ban''' || Seguridad (bloqueo por intentos).&lt;br /&gt;
|-&lt;br /&gt;
| '''nftables''' || Cortafuegos (sustituto de iptables).&lt;br /&gt;
|-&lt;br /&gt;
| '''Zabbix''' || Monitorización. No reside en esta máquina, pero puede consultarse vía interfaz &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;nc&amp;lt;/code&amp;gt; (especialmente para vigilar congestiones).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
No hay '''MySQL ni base de datos''' en esta máquina. Tampoco hay LDAP en este entorno. Toda la configuración del módulo vive en un único fichero (ver §6).&lt;br /&gt;
&lt;br /&gt;
=== Los tres APIs del demonio Videocan ===&lt;br /&gt;
&lt;br /&gt;
A través de Nginx, Videocan expone '''tres APIs''':&lt;br /&gt;
&lt;br /&gt;
# '''API de cliente (usuario):''' lo invoca la aplicación del usuario para iniciar la videollamada.&lt;br /&gt;
# '''API de agente:''' devuelve al agente la URL que lo autentica como moderador. Filtrable por IP.&lt;br /&gt;
# '''API hacia Prosody:''' la usa el módulo de Prosody para notificar eventos de sala (conexión/desconexión, destrucción de sala). Es la &amp;quot;flecha vertical&amp;quot; del diagrama.&lt;br /&gt;
&lt;br /&gt;
Ejemplo de evento observado en el log al destruirse una sala:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
POST Prosody v_room_destroy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Con estos eventos Videocan mantiene '''sincronizados los canales''' con lo que existe realmente en Meet. No debería crearse ninguna sala sin que intervenga Videocan.&lt;br /&gt;
&lt;br /&gt;
=== Protocolos (leyenda del diagrama) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Color de flecha !! Protocolo&lt;br /&gt;
|-&lt;br /&gt;
| Azul || HTTP / HTTPS (incluye el API REST)&lt;br /&gt;
|-&lt;br /&gt;
| Naranja || XMPP y '''BOSH''' (BOSH = encapsulación de XMPP sobre HTTP)&lt;br /&gt;
|-&lt;br /&gt;
| Verde || '''RTP''' (audio y vídeo), por '''10000/UDP''' en el lado de Meet&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;El '''10000/UDP''' coincide con el rango que usa Asterisk (10000–20000/UDP), pero no hay conflicto porque '''nunca conviven un Asterisk y un Meet en la misma máquina'''. Ese puerto debe abrirse en el firewall sobre la IP pública del módulo.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Modelo de autenticación y seguridad ==&lt;br /&gt;
&lt;br /&gt;
El modelo es deliberadamente &amp;quot;sin usuarios&amp;quot;:&lt;br /&gt;
* '''No hay usuarios, ni contraseñas, ni LDAP, ni inventario de usuarios''' en ningún punto.&lt;br /&gt;
* Igual que en Meet estándar, '''la seguridad se basa en conocer (o no) las URLs / el nombre de sala'''. Quien conoce el nombre de una sala abierta, entra.&lt;br /&gt;
* '''Moderador (agente):''' entra autenticado mediante '''JWT'''. El mero hecho de conocer la URL de agente (un &amp;quot;churro&amp;quot; largo que en teoría solo conoce el agente que coge la llamada) implica ser agente. Esa URL lleva el JWT y el nombre de sala codificados, y solo sirve para esa sala.&lt;br /&gt;
* '''Invitados:''' cualquiera que conozca el nombre de la sala puede entrar '''sin autenticar'''.&lt;br /&gt;
* Si un agente reenvía su URL a otra persona, esa persona también entraría como moderador. Si dos agentes pinchan la URL que circula por OpenChannel, ambos entran en la misma sala.&lt;br /&gt;
&lt;br /&gt;
=== Diferencias frente a un Vybite Meet estándar ===&lt;br /&gt;
&lt;br /&gt;
Son básicamente '''dos''':&lt;br /&gt;
&lt;br /&gt;
# '''Autenticación del moderador.''' En Vybite Meet estándar el moderador se valida contra LDAP o contra la base de datos de usuarios de Vybite. En Videocan, el moderador (agente) se autentica vía '''JWT generado al vuelo por Videocan''', sin LDAP ni base de datos.&lt;br /&gt;
# '''Carteles (textos/idiomas de la interfaz).''' Se sustituyen para que no aparezca la palabra &amp;quot;Jitsi&amp;quot; sino &amp;quot;Vybite&amp;quot;, y para corregir las traducciones al castellano.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Conclusión operativa:''' un Vybite Meet existente de un cliente '''no sirve''' para dar este servicio. Serían máquinas e instalaciones distintas (por los carteles, las personalizaciones y la IP pública). Solo en un caso muy forzado podría plantearse compartir máquina usando '''dos dominios distintos''' sobre una misma IP pública. Como norma general: '''no'''.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Control de canales ==&lt;br /&gt;
&lt;br /&gt;
* Un '''canal = una llamada'''. El servicio se factura por '''canales simultáneos'''.&lt;br /&gt;
* Videocan lleva un control del número de canales en uso y aplica una '''limitación de canales concurrentes''' (&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;videocan_canales_maximo&amp;lt;/code&amp;gt;). Si se alcanza el máximo, las nuevas llamadas entran con '''congestión'''.&lt;br /&gt;
* Los &amp;quot;hilos&amp;quot; del demonio (p. ej. 2) son para atender peticiones web y no guardan relación con el número de canales; con pocos hilos basta porque no hay tanto tráfico web.&lt;br /&gt;
* Diagnóstico en caliente mediante el socket de control:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nc localhost 1132&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Muestra, entre otras cosas, los canales activos (&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;canales_...&amp;lt;/code&amp;gt;) y el contador de alarmas (las alarmas suelen deberse a temas de logs).&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Configuración: videocan.conf ==&lt;br /&gt;
&lt;br /&gt;
La configuración del módulo está centralizada en un único fichero en formato '''libconfig''', ubicado dentro del árbol &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/etc/mdtel/&amp;lt;/code&amp;gt; (en la máquina de desarrollo mostrada aparecía también como &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/etc/mdtel-videocan.conf&amp;lt;/code&amp;gt;; la convención estándar es &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/etc/mdtel/videocan.conf&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Para facilitar el despliegue existe un '''configurador''' (cuestionario) que el centro de servicios debe rellenar antes de arrancar una instalación y entregar cumplimentado.&lt;br /&gt;
&lt;br /&gt;
=== Parámetros globales ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Descripción&lt;br /&gt;
|-&lt;br /&gt;
| '''host''' (nombre DNS) || El más crítico. Es el nombre de dominio completo (FQDN), p. ej. &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;labmeetvideo.mednova.local&amp;lt;/code&amp;gt;. Aparece en '''multitud de sitios, incluso en nombres de fichero'''. Es la razón por la que se instala de cero en cada despliegue (ver §8).&lt;br /&gt;
|-&lt;br /&gt;
| '''openchannel_apikey''' || API key de OpenChannel/OmniSuite. Por su tamaño no cabe como cadena en libconfig, así que '''se guarda en un fichero aparte''' y el programa lo carga. Ruta: &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/etc/mdtel/apikey_openchannel.txt&amp;lt;/code&amp;gt;. La proporciona el equipo de OmniSuite.&lt;br /&gt;
|-&lt;br /&gt;
| '''videocan_canales_maximo''' || Número de canales (llamadas) concurrentes soportados.&lt;br /&gt;
|-&lt;br /&gt;
| '''Filtro IP del API de agente''' || Restringe desde qué IP/máscara se puede invocar el API de agente (p. ej. &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;172.25.x.x&amp;lt;/code&amp;gt;). A &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;0&amp;lt;/code&amp;gt; queda abierto.&lt;br /&gt;
|-&lt;br /&gt;
| '''Dominios y certificados''' || Indica si se trabaja con certificados; debe resolverse '''antes''' de instalar.&lt;br /&gt;
|-&lt;br /&gt;
| '''firma''' || Firma electrónica de la licencia (ver §9). En un fichero base va vacía.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== 6.2. Parámetros por servicio ===&lt;br /&gt;
&lt;br /&gt;
Los '''servicios''' son, en la práctica, los '''OpenChannels''' (conceptualmente equivalentes a VDNs): los distintos &amp;quot;puntos de entrada&amp;quot; temáticos. Por cada servicio se configura:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Descripción&lt;br /&gt;
|-&lt;br /&gt;
| '''Nombre interno''' || Identificador intrascendente (1, 2, 3…).&lt;br /&gt;
|-&lt;br /&gt;
| '''Nombre a mostrar''' || Nombre descriptivo que ve el cliente por defecto como interlocutor (p. ej. &amp;quot;Antonio&amp;quot;). Hay APIs para que cada agente salga con el suyo.&lt;br /&gt;
|-&lt;br /&gt;
| '''token de servicio''' || Token que el '''usuario''' (no el agente) debe conocer para invocar el servicio; viaja en la URL de usuario. En algún despliegue concreto (FAPS) se decidió que no viaje nada y baste la URL.&lt;br /&gt;
|-&lt;br /&gt;
| '''url_openchannel''' || URL de OpenChannel que crea el proveedor de la plataforma (Skally) para ese servicio.&lt;br /&gt;
|-&lt;br /&gt;
| '''Proxy / verificación TLS de OpenChannel''' || Si se sale por proxy y si hay que verificar el certificado de OpenChannel (si es HTTPS).&lt;br /&gt;
|-&lt;br /&gt;
| '''Timeout de conexión de agente (s)''' || Tiempo máximo que el cliente espera sin que entre el agente; al vencer se '''cuelga la interacción de OpenChannel''' (en Meet no se puede informar al cliente, así que solo se corta OpenChannel). Se baraja fijarlo en torno a '''3600 s''' como red de seguridad y sacarlo del configurador.&lt;br /&gt;
|-&lt;br /&gt;
| '''Expiración del JWT de agente (s)''' || Tiempo que tiene el agente para '''entrar''' con el JWT (no limita la duración de la conversación). Valor mostrado: '''1800 s''' (30 min).&lt;br /&gt;
|-&lt;br /&gt;
| '''Antirrebotes''' || Si llegan varias peticiones al mismo servicio desde la misma IP en una ventana (p. ej. '''20 s'''), se etiquetan como rebote (doble clic) y no entran.&lt;br /&gt;
|-&lt;br /&gt;
| '''Timeout de liberación de sala (s)''' || Si una sala no se libera sola, se libera el canal a los '''30 s''' de detectar que no hay sala. Red de seguridad heredada de antes de existir el API de Prosody; el canal liberado cuenta para los concurrentes.&lt;br /&gt;
|-&lt;br /&gt;
| '''Nombre por defecto''' || Nombre a mostrar cuando los datos entrantes no incluyen nombre.&lt;br /&gt;
|-&lt;br /&gt;
| '''Variables''' || Pares nombre/valor (ver §7). Las fijas (&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;$0&amp;lt;/code&amp;gt;–&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;$2&amp;lt;/code&amp;gt;) más las específicas por servicio (de &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;$3&amp;lt;/code&amp;gt; en adelante).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Datos de entrada del usuario ===&lt;br /&gt;
&lt;br /&gt;
La aplicación de front-end recopila los datos que quiera y los envía al invocar el inicio de videollamada. '''No hay un conjunto de datos fijo'''; pueden llegar como argumentos de un GET o como JSON, pero el API siempre trabaja con '''pares nombre/valor'''. Ejemplos:&lt;br /&gt;
* '''Servicio &amp;quot;videollamada&amp;quot; (FAPS):''' &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;name&amp;lt;/code&amp;gt;, &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;lastname&amp;lt;/code&amp;gt;, &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;id&amp;lt;/code&amp;gt; (que aquí es el móvil), correo, &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;dni&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Servicio &amp;quot;emergencia 112&amp;quot;:''' solo llegan '''latitud y longitud'''; al no llegar nombre, el campo nombre queda vacío.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Plantillas ==&lt;br /&gt;
&lt;br /&gt;
Ubicación: &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/etc/mdtel-videocan/templates&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Una '''plantilla''' es la '''página web''' que Videocan devuelve cuando se invoca una URL del API (por ejemplo &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;get_agente_nuevasala&amp;lt;/code&amp;gt;). Es una página con lógica, específica de cada llamada (no solo de cada servicio), porque el nombre de sala se genera al vuelo para cada llamada.&lt;br /&gt;
&lt;br /&gt;
* Las '''variables''' se marcan con $:&lt;br /&gt;
** &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;$0&amp;lt;/code&amp;gt; → host&lt;br /&gt;
** &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;$1&amp;lt;/code&amp;gt; → sala de la videollamada (creada al vuelo)&lt;br /&gt;
** &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;$2&amp;lt;/code&amp;gt; → nombre a mostrar (&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;displayName&amp;lt;/code&amp;gt;)&lt;br /&gt;
** &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;$3&amp;lt;/code&amp;gt; → token JWT (cadena)&lt;br /&gt;
** de &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;$3&amp;lt;/code&amp;gt;/siguientes en adelante → variables específicas del servicio&lt;br /&gt;
* Videocan sustituye las variables en la plantilla y entrega la página resultante. Quien la recibe queda viendo una '''sala de Meet ya con el JWT aplicado''', entrando autenticado.&lt;br /&gt;
* Las plantillas usan el '''API de integración de Jitsi Meet''' (referencia pública: &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;jitsi-meet-api-integration&amp;lt;/code&amp;gt;). '''No se usa un IFrame''': la sala se integra directamente en la página (un IFrame &amp;quot;siempre es puñetero&amp;quot;). El JavaScript de la integración vive en las plantillas.&lt;br /&gt;
* Permiten '''personalizar el aspecto''': por ejemplo &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;toolbarButtons&amp;lt;/code&amp;gt; (qué botones se muestran; hay muchos comentados/quitados), &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;startWithAudioMuted&amp;lt;/code&amp;gt;, el botón de '''Full Screen''' (se muestra el botón, no se entra en pantalla completa automáticamente), etc.&lt;br /&gt;
* Puede haber '''una plantilla por servicio''', pero lo habitual es que sean '''compartidas''' porque todos los servicios ven prácticamente lo mismo. Las diferencias razonables serían pequeñas (p. ej. permitir o no grabar, activar el botón de chat) y se tocarían vía &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;toolbarButtons&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Limitación conocida (móvil):''' al entrar compartiendo la URL, el usuario entra en vista de '''interlocutor en grande''' (no en cuadrícula), por lo que en el móvil '''no se ve a sí mismo'''. Es un problema relevante para lengua de signos, donde la persona necesita verse para comprobar el encuadre. Pulsando el botón de cuadrícula se soluciona, pero la intención es que la app sea transparente. El ajuste no se puede hacer por parámetros de URL; '''habría que resolverlo con JavaScript''' en la plantilla. Queda como punto abierto.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Instalación ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;El planteamiento actual es '''instalar siempre de cero''' (no entregar una imagen de máquina virtual), porque el '''nombre del host está en multitud de sitios''' (incluidos nombres de fichero) y reescribirlo en una imagen sería más complejo. Si en el futuro hubiera muchas instalaciones, podría replantearse.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Prerrequisitos y orden ===&lt;br /&gt;
&lt;br /&gt;
# Obtener la '''IP pública''' y darla de alta en '''DNS''' (lo hace el cliente o nosotros, según de quién sea el dominio). Sin nombre DNS no se puede instalar (se necesita para el certificado).&lt;br /&gt;
# Instalar '''Nginx''' y '''Certbot''', obtener el '''certificado''' y crear el '''firewall''' (nftables).&lt;br /&gt;
# Instalar '''Meet''' mediante la lista de paquetes homologados (&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;apt install &amp;amp;lt;paquete&amp;amp;gt;&amp;lt;/code&amp;gt;, uno a uno). '''No se instala el repositorio de Jitsi''', sino paquetes concretos y homologados.&lt;br /&gt;
# La instalación de Meet '''modifica la configuración de Nginx y de Prosody''', así que tras instalarlo hay que '''reajustar''' ambos. (La configuración que deja Meet por defecto no sirve.) El proceso requiere iterar y reconfigurar varias veces.&lt;br /&gt;
# Sustituir el '''contenido estático''' (ver §8.2).&lt;br /&gt;
# Rellenar &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;videocan.conf&amp;lt;/code&amp;gt;, instalar el demonio, configurar el JWT en Prosody y '''firmar''' (ver §9).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Detalle de &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;apt&amp;lt;/code&amp;gt;: para instalar un &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;.deb&amp;lt;/code&amp;gt; local hay que indicar una ruta de directorio; por eso se usa &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;apt install ./paquete.deb&amp;lt;/code&amp;gt; (con &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;./&amp;lt;/code&amp;gt;). Se usa &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;apt install&amp;lt;/code&amp;gt; en lugar de &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;dpkg -i&amp;lt;/code&amp;gt; porque '''resuelve dependencias'''.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Existe un '''punto intermedio de validación''' muy útil: cuando todo funciona '''sin autenticación''', cualquiera que conozca el nombre de sala entra directamente. Si &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;host/pepito&amp;lt;/code&amp;gt; permite que varios se conecten a la sala &amp;quot;pepito&amp;quot; sin autenticar, la instalación base está correcta. A partir de ahí se valida el resto tirando de logs y de la herramienta &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;jitsi-debug&amp;lt;/code&amp;gt; (sección ''Health'').&lt;br /&gt;
&lt;br /&gt;
=== Contenido estático (carteles y personalización) ===&lt;br /&gt;
&lt;br /&gt;
* Jitsi instala un directorio de contenido estático en &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/usr/share/jitsi-meet/…&amp;lt;/code&amp;gt;. Videocan '''lo reemplaza entero''' por uno propio (logos, fondos, textos &amp;quot;Vybite Meet&amp;quot;). Ese directorio propio es '''igual para todas las instalaciones''' (no se configura nada en él).&lt;br /&gt;
* Los '''carteles''' (textos de interfaz) están en &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/usr/share/jitsi-meet/lang/&amp;lt;/code&amp;gt;:&lt;br /&gt;
** &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;main.json&amp;lt;/code&amp;gt; → inglés (suele estar bien, retocado para sustituir &amp;quot;Jitsi&amp;quot; por &amp;quot;Vybite&amp;quot;).&lt;br /&gt;
** &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;main-es.json&amp;lt;/code&amp;gt; → castellano (~1700 carteles; las traducciones por defecto son deficientes y se corrigen).&lt;br /&gt;
* '''No se recomienda modificar los DEB''' para empaquetar el contenido propio: como los paquetes modifican configuraciones y Meet cambia con frecuencia, no compensa.&lt;br /&gt;
* '''Actualizaciones (update/upgrade):''' son arriesgadas porque pueden '''reescribir los carteles''' (decenas de cambios por actualización). El procedimiento de mantenimiento de carteles consiste en comparar a tres (inglés viejo, inglés nuevo, español nuevo) con una herramienta tipo '''Meld''' o el comparador de '''Notepad++''', y trasladar los cambios manteniendo coherencia terminológica. Por eso Meet '''no se actualiza en cada release''', sino periódicamente, y solo cuando interesa (la mayoría de novedades —integración con Drive, transcripción, traducción simultánea— no se usan). La transcripción se apoya en '''Vosk''', que de momento da resultados pobres. Las actualizaciones por '''seguridad''' sí deberán contemplarse.&lt;br /&gt;
&lt;br /&gt;
=== Instalación del demonio Videocan ===&lt;br /&gt;
&lt;br /&gt;
Sigue el estándar de los demonios &amp;quot;mdtel&amp;quot;:&lt;br /&gt;
* Binario y módulo en '''&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/opt/videocan/bin/&amp;lt;/code&amp;gt;''' (&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/opt/videocan/&amp;lt;/code&amp;gt; como raíz; el módulo de Prosody también reside ahí).&lt;br /&gt;
* Arranque en '''&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/etc/init.d/&amp;lt;/code&amp;gt;'''.&lt;br /&gt;
* Configuración en '''&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/etc/mdtel/videocan.conf&amp;lt;/code&amp;gt;''' (más &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;apikey_openchannel.txt&amp;lt;/code&amp;gt; en el mismo árbol).&lt;br /&gt;
* Rotación de logs en '''&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/etc/logrotate.d/videocan&amp;lt;/code&amp;gt;'''.&lt;br /&gt;
* Logs en '''&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/var/log/videocan/videocan.log&amp;lt;/code&amp;gt;''' (el demonio corre como usuario &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;videocan&amp;lt;/code&amp;gt;, '''no como root''', por estar publicado en web).&lt;br /&gt;
&lt;br /&gt;
=== Instalaciones existentes (referencia) ===&lt;br /&gt;
&lt;br /&gt;
* '''&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;labmeetvideo.mednova.local&amp;lt;/code&amp;gt;''' — instalación interna (sin Certbot, no publicada).&lt;br /&gt;
* '''&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;mdtel.videocan01.vybite.es&amp;lt;/code&amp;gt;''' — instalación con IP pública (en Soax), para el centro de servicios de pruebas/demos.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Firma de licencia y tokens ==&lt;br /&gt;
&lt;br /&gt;
El &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;videocan.conf&amp;lt;/code&amp;gt; debe estar protegido para que '''no se pueda manipular''' (por ejemplo, cambiar el número de canales a 2000). Esa protección es la '''firma electrónica''', que usa el '''mismo procedimiento y los mismos certificados que Vybite'''.&lt;br /&gt;
&lt;br /&gt;
=== Qué se protege ===&lt;br /&gt;
&lt;br /&gt;
La firma cubre '''tres''' valores:&lt;br /&gt;
# '''Número de servicios''' (no su contenido: se pueden modificar libremente, pero no crear más de los firmados).&lt;br /&gt;
# '''Número de canales.'''&lt;br /&gt;
# '''host''' (dominio) — para que no se pueda instalar en muchos sitios con la misma licencia.&lt;br /&gt;
&lt;br /&gt;
=== Tokens ===&lt;br /&gt;
&lt;br /&gt;
* Los '''tokens''' y el '''&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;JWT_SECRET&amp;lt;/code&amp;gt;''' hacen que cada instalación sea '''distinta'''. La herramienta de firma puede regenerarlos (claves particulares aleatorias por instalación).&lt;br /&gt;
* El '''token de servicio''' debe '''coincidir''' con lo que conoce la '''aplicación de usuario''' del otro lado. Por eso, cuando se regeneran tokens, hay que revisar las URLs de acceso y, en su caso, tocar la página web que se entrega al cliente (p. ej. en FAPS, el token lo tenemos nosotros, así que se ajusta en la página web alojada en esta máquina).&lt;br /&gt;
* El '''&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;JWT_SECRET&amp;lt;/code&amp;gt;''' debe configurarse en '''Prosody''' como '''&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;APP_SECRET&amp;lt;/code&amp;gt;''' (ver §9.4).&lt;br /&gt;
&lt;br /&gt;
=== Herramienta videocan-firmar ===&lt;br /&gt;
&lt;br /&gt;
Primer parámetro = operación a realizar:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Operación !! Efecto&lt;br /&gt;
|-&lt;br /&gt;
| '''Generar tokens''' || Regenera los tokens (not firma). No requiere la clave; podría delegarse al cliente.&lt;br /&gt;
|-&lt;br /&gt;
| '''Firmar''' || Generar solo la firma.&lt;br /&gt;
|-&lt;br /&gt;
| '''Generar tokens y firmar''' || Operación recomendada para todas las instalaciones.&lt;br /&gt;
|-&lt;br /&gt;
| '''Verificar''' || Indica si la firma del fichero es válida. No requiere clave (va embebida en la herramienta).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Reglas:&lt;br /&gt;
* Siempre se indica '''el fichero de configuración''' (no se modifica el original: la herramienta entrega '''otro fichero''' ya procesado).&lt;br /&gt;
* Para '''firmar''' se necesita el '''fichero de clave privada (.key)'''; para '''verificar''' no se necesita nada.&lt;br /&gt;
&lt;br /&gt;
Ejemplos:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Verificar&lt;br /&gt;
videocan-firmar verificar /etc/mdtel/videocan.conf&lt;br /&gt;
# → &amp;quot;La sección Videocan tiene un campo firma que no es correcto.&lt;br /&gt;
#     Error al verificar firma de videocan.conf.&amp;quot;   (si no es válido)&lt;br /&gt;
&lt;br /&gt;
# Generar tokens + firmar (recomendado)&lt;br /&gt;
videocan-firmar tokens-firmar mdtel.key videocan.conf&lt;br /&gt;
# → &amp;quot;Operación correcta. Se actualiza el fichero.&amp;quot;&lt;br /&gt;
#   Avisos: token de servicio modificado (revisar URLs de acceso),&lt;br /&gt;
#           JWT_SECRET modificado (configurar APP_SECRET y reiniciar Prosody),&lt;br /&gt;
#           firma del archivo modificada.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Una verificación correcta enumera qué se está firmando (host, número de servicios, número de canales) y termina con un &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;OK&amp;lt;/code&amp;gt; en la '''última línea''':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Host labmeetvideo... ok&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tras firmar ===&lt;br /&gt;
&lt;br /&gt;
# Configurar '''&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;APP_SECRET&amp;lt;/code&amp;gt;''' en Prosody con el nuevo &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;JWT_SECRET&amp;lt;/code&amp;gt;. Configuración de Prosody en '''&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/etc/prosody/conf.avail/&amp;lt;/code&amp;gt;''' (estructura similar a la de Nginx; el fichero incluye el nombre de dominio).&lt;br /&gt;
# '''Reiniciar Prosody.'''&lt;br /&gt;
# Revisar las '''URLs de acceso''' afectadas por el cambio de tokens de servicio.&lt;br /&gt;
&lt;br /&gt;
=== 9.5. Comportamiento sin firma válida (&amp;quot;la bomba&amp;quot;) ===&lt;br /&gt;
&lt;br /&gt;
Si la firma '''no es válida''', el sistema '''sigue funcionando pero limitado a 1 canal''' (&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;canales_max = 1&amp;lt;/code&amp;gt;). El paso a 1 canal '''no ocurre en el arranque''', sino tras un tiempo indeterminado (diseñado así para dificultar su localización en el código). Esto permite, en la práctica, '''hacer demos''': con el fichero sin firmar y configurado a 1 canal, todo funciona. El procedimiento habitual del cliente puede ser instalar primero (con tokens, para que arranque y se pueda probar) y '''entregarnos después el fichero para que lo firmemos''' con las licencias.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Diagnóstico y logs ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Recurso !! Uso&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;nc localhost 1132&amp;lt;/code&amp;gt; || Socket de control de Videocan: canales activos, alarmas, congestión.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/var/log/videocan/videocan.log&amp;lt;/code&amp;gt; || Log del demonio Videocan.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/var/log/prosody/&amp;lt;/code&amp;gt; || Log de Prosody.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/var/log/nginx/&amp;lt;/code&amp;gt; || Log de Nginx.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/var/log/jitsi/&amp;lt;/code&amp;gt; || Log de la pila Jitsi.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;jitsi-debug&amp;lt;/code&amp;gt; (script) || Comprobación de salud de la instalación (sección ''Health'').&lt;br /&gt;
|-&lt;br /&gt;
| '''Zabbix''' (vía &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;nc&amp;lt;/code&amp;gt;) || Monitorización externa, especialmente de congestiones, explotando el socket &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;nc&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Resumen de rutas y puertos ==&lt;br /&gt;
&lt;br /&gt;
'''Rutas (convención estándar &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/etc/mdtel/&amp;lt;/code&amp;gt;):'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/opt/videocan/bin/                      # demonio Videocan + módulo&lt;br /&gt;
/etc/init.d/videocan                    # arranque&lt;br /&gt;
/etc/mdtel/videocan.conf                # configuración principal (libconfig)&lt;br /&gt;
/etc/mdtel/apikey_openchannel.txt       # API key de OpenChannel&lt;br /&gt;
/etc/mdtel-videocan/templates/          # plantillas (páginas web con JS de integración Meet)&lt;br /&gt;
/etc/logrotate.d/videocan               # rotación de logs&lt;br /&gt;
/etc/prosody/conf.avail/                # configuración de Prosody (APP_SECRET)&lt;br /&gt;
/var/log/videocan/videocan.log          # log del demonio (usuario videocan)&lt;br /&gt;
/usr/share/jitsi-meet/                  # contenido estático (reemplazado por el propio)&lt;br /&gt;
/usr/share/jitsi-meet/lang/main.json    # carteles inglés&lt;br /&gt;
/usr/share/jitsi-meet/lang/main-es.json # carteles castellano (~1700)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Puertos:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
443/TCP    Nginx (HTTPS, proxy inverso, APIs de Videocan)&lt;br /&gt;
10000/UDP  RTP de Meet (audio/vídeo) sobre la IP pública&lt;br /&gt;
1132       Socket de control local de Videocan (nc localhost 1132)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Limitaciones y puntos abiertos ==&lt;br /&gt;
&lt;br /&gt;
* '''Solo audio y vídeo'''; sin compartición de pantalla ni chat (el chat, si se activase, debería ir por OpenChannel).&lt;br /&gt;
* '''Cierre de la interacción OpenChannel:''' confirmar con el equipo de OmniSuite si debe ser automático o manual.&lt;br /&gt;
* '''Requiere IP pública dedicada''' por máquina (a día de hoy).&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Omnisuite_videoCan&amp;diff=19165</id>
		<title>Omnisuite videoCan</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Omnisuite_videoCan&amp;diff=19165"/>
		<updated>2026-07-13T08:23:59Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* Doc de transcripción */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Qué es Videocan ==&lt;br /&gt;
&lt;br /&gt;
Videocan es una plataforma de vídeo que dota de '''videocanal''' a un contact center basado en OmniSuite. Permite que una interacción que entra como '''chat''' a través de '''OpenChannel''' se convierta, en la práctica, en una '''videollamada de audio y vídeo''' entre un usuario externo y un agente.&lt;br /&gt;
&lt;br /&gt;
La idea central es sencilla: la llamada '''no es una llamada de audio tradicional''' (no interviene Asterisk en ningún punto). El usuario y el agente acaban entrando en la '''misma sala de videoconferencia''' (hoy basada en Jitsi Meet, comercialmente &amp;quot;Vybite Meet&amp;quot;), y todo el control de cola, enrutado y atención del agente se apoya en la infraestructura existente de OmniSuite vía OpenChannel.&lt;br /&gt;
&lt;br /&gt;
Puntos clave del alcance funcional actual:&lt;br /&gt;
* Solo hay '''audio y vídeo'''. No hay compartición de pantalla.&lt;br /&gt;
* El '''chat está desactivado''': si se quisiera, debería salir por OpenChannel, no por Meet, así que de momento no se usa.&lt;br /&gt;
* Sustituye a la solución anterior basada en '''Vydao''', que se ha reemplazado por '''Meet'''.&lt;br /&gt;
&lt;br /&gt;
=== Contexto: qué es un OpenChannel ===&lt;br /&gt;
&lt;br /&gt;
OpenChannel es el mecanismo de OmniSuite para meter un '''canal de chat''' dentro del contact center. Lo que se inicia es, técnicamente, una '''interacción de chat''' que se encola, hereda todos los procesos típicos de OmniSuite (colas, prioridades, asignación) y acaba siendo atendida por un agente. Videocan se apoya en ese canal de chat para transportar al agente el enlace de la videollamada.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Flujo funcional ==&lt;br /&gt;
&lt;br /&gt;
=== Llamada entrante (usuario → agente) ===&lt;br /&gt;
&lt;br /&gt;
# Un usuario, desde una aplicación web, un navegador o una '''app móvil''' (que internamente abre una página web), introduce una serie de datos y pulsa '''&amp;quot;Iniciar videollamada&amp;quot;'''.&lt;br /&gt;
# Ese evento desencadena '''dos cosas en paralelo''':&lt;br /&gt;
#* '''Lado usuario:''' se le crea una '''sala de Meet''' y queda en la pantalla de espera de la sala (&amp;quot;esperando conexión&amp;quot;).&lt;br /&gt;
#* '''Lado OmniSuite:''' se genera una '''interacción de chat por OpenChannel''' que se encola y llega a un agente.&lt;br /&gt;
# El agente (logueado en OmniSuite con sus canales) recibe el aviso de interacción en cola. Al aceptarla se le abre una pestaña tipo chat con un mensaje del estilo ''&amp;quot;Nueva llamada de [Nombre], pulsa aquí para unirte&amp;quot;'' y una '''URL'''.&lt;br /&gt;
# Esa URL '''no es una URL de Meet''': es una URL del '''API de agente de Videocan''' (lleva &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;get&amp;lt;/code&amp;gt;, agente, api-key, etc.). El agente la pulsa.&lt;br /&gt;
# Videocan, a partir de esa URL, '''autentica al agente como moderador''' en Meet mediante '''JWT''' y lo introduce en la sala (la misma del usuario).&lt;br /&gt;
# Se establece la videollamada. El usuario, que estaba esperando, ve entrar al agente y comienza la comunicación (audio + vídeo vía Meet).&lt;br /&gt;
&lt;br /&gt;
Detalle de seguridad relevante: '''el agente no conoce el nombre de la sala'''. En la URL que recibe va &amp;quot;encholado&amp;quot; (codificado) tanto el JWT como el nombre de sala, de modo que esa URL solo sirve para '''entrarn en esa sala concreta'''.&lt;br /&gt;
&lt;br /&gt;
=== Llamada saliente / &amp;quot;nueva sala&amp;quot; (agente → usuario) ===&lt;br /&gt;
&lt;br /&gt;
La llamada saliente asume que ya existe un canal de comunicación con el destinatario. El mecanismo es deliberadamente simple:&lt;br /&gt;
&lt;br /&gt;
# El agente dispone de un '''plugin / botón (&amp;quot;compartir enlace&amp;quot;)''' que genera una nueva sala.&lt;br /&gt;
# Videocan '''crea el nombre de la sala al vuelo''' (aleatorio) — la sala la crea Videocan, no Meet directamente.&lt;br /&gt;
# Videocan genera un '''JWT''' firmado para esa sala y construye una página web que mete al agente '''ya autenticado''' como moderador.&lt;br /&gt;
# El agente '''copia el enlace''' de la reunión y lo envía al destinatario por el canal que corresponda (p. ej. WhatsApp, el propio canal por el que se estuviera hablando).&lt;br /&gt;
# Cualquiera que abra ese enlace entra en la sala. Si lo abren varios, entran varios.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;El '''API de agente está filtrado por IP''': solo se puede invocar desde dentro (IP privada) o desde una IP fija conocida (p. ej. la salida del entorno del cliente), según el despliegue.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Cierre de la llamada ===&lt;br /&gt;
&lt;br /&gt;
La interacción de OpenChannel debería cerrarse al colgar la videollamada (se cuelga &amp;quot;como se cuelga una llamada&amp;quot;). En la demo se observó que en ocasiones el agente tuvo que cerrarla a mano en OpenChannel; queda como punto a confirmar con el equipo experto en OmniSuite si el cierre debe ser automático o manual. Como red de seguridad existen ''timeouts'' (ver §6) para liberar el canal aunque algo quede colgado.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== 3. Arquitectura y componentes ==&lt;br /&gt;
&lt;br /&gt;
Todo el módulo se despliega en una '''máquina virtual independiente''' (separada de la de OpenChannel/OmniSuite), sobre '''Debian 13''', y '''requiere una IP pública dedicada''' (puede estar NATeada 1:1). El puerto de RTP de Meet usa esa IP pública.&lt;br /&gt;
&lt;br /&gt;
Conceptualmente es '''una instalación de Vybite Meet (Jitsi) personalizada''' más el demonio propio Videocan. Componentes:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Componente !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Nginx''' || Proxy inverso y servidor de contenido. Punto de entrada HTTPS (443/TCP). Publica los tres APIs de Videocan.&lt;br /&gt;
|-&lt;br /&gt;
| '''Certbot''' || Generación y renovación automática de certificados TLS (Let's Encrypt). Solo en instalaciones '''públicas'''; en instalaciones internas no se instala.&lt;br /&gt;
|-&lt;br /&gt;
| '''Prosody''' || Servidor XMPP (programado en Lua) sobre el que se apoya Meet. Equivalente moderno al antiguo OpenFire.&lt;br /&gt;
|-&lt;br /&gt;
| '''Módulo Prosody propio (&amp;quot;mod&amp;quot;)''' || Módulo desarrollado a medida que engancha con Videocan; informa de entradas y salidas de la sala para mantener sincronizado OpenChannel con el estado real de Meet.&lt;br /&gt;
|-&lt;br /&gt;
| '''Jitsi Meet + Jicofo + JVB''' || Pila de videoconferencia. '''JVB = Jitsi Video Bridge''' (puente de medios). Se instala mediante una lista de paquetes homologados.&lt;br /&gt;
|-&lt;br /&gt;
| '''Videocan (demonio)''' || Demonio propio. Es el &amp;quot;cerebro&amp;quot;: expone los APIs, controla canales/llamadas, construye plantillas, gestiona la autenticación del agente y aplica la firma de licencia.&lt;br /&gt;
|-&lt;br /&gt;
| '''Fail2ban''' || Seguridad (bloqueo por intentos).&lt;br /&gt;
|-&lt;br /&gt;
| '''nftables''' || Cortafuegos (sustituto de iptables).&lt;br /&gt;
|-&lt;br /&gt;
| '''Zabbix''' || Monitorización. No reside en esta máquina, pero puede consultarse vía interfaz &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;nc&amp;lt;/code&amp;gt; (especialmente para vigilar congestiones).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
No hay '''MySQL ni base de datos''' en esta máquina. Tampoco hay LDAP en este entorno. Toda la configuración del módulo vive en un único fichero (ver §6).&lt;br /&gt;
&lt;br /&gt;
=== 3.1. Los tres APIs del demonio Videocan ===&lt;br /&gt;
&lt;br /&gt;
A través de Nginx, Videocan expone '''tres APIs''':&lt;br /&gt;
&lt;br /&gt;
# '''API de cliente (usuario):''' lo invoca la aplicación del usuario para iniciar la videollamada.&lt;br /&gt;
# '''API de agente:''' devuelve al agente la URL que lo autentica como moderador. Filtrable por IP.&lt;br /&gt;
# '''API hacia Prosody:''' la usa el módulo de Prosody para notificar eventos de sala (conexión/desconexión, destrucción de sala). Es la &amp;quot;flecha vertical&amp;quot; del diagrama.&lt;br /&gt;
&lt;br /&gt;
Ejemplo de evento observado en el log al destruirse una sala:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
POST Prosody v_room_destroy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Con estos eventos Videocan mantiene '''sincronizados los canales''' con lo que existe realmente en Meet. No debería crearse ninguna sala sin que intervenga Videocan.&lt;br /&gt;
&lt;br /&gt;
=== 3.2. Protocolos (leyenda del diagrama) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Color de flecha !! Protocolo&lt;br /&gt;
|-&lt;br /&gt;
| Azul || HTTP / HTTPS (incluye el API REST)&lt;br /&gt;
|-&lt;br /&gt;
| Naranja || XMPP y '''BOSH''' (BOSH = encapsulación de XMPP sobre HTTP)&lt;br /&gt;
|-&lt;br /&gt;
| Verde || '''RTP''' (audio y vídeo), por '''10000/UDP''' en el lado de Meet&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;El '''10000/UDP''' coincide con el rango que usa Asterisk (10000–20000/UDP), pero no hay conflicto porque '''nunca conviven un Asterisk y un Meet en la misma máquina'''. Ese puerto debe abrirse en el firewall sobre la IP pública del módulo.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== 4. Modelo de autenticación y seguridad ==&lt;br /&gt;
&lt;br /&gt;
El modelo es deliberadamente &amp;quot;sin usuarios&amp;quot;:&lt;br /&gt;
* '''No hay usuarios, ni contraseñas, ni LDAP, ni inventario de usuarios''' en ningún punto.&lt;br /&gt;
* Igual que en Meet estándar, '''la seguridad se basa en conocer (o no) las URLs / el nombre de sala'''. Quien conoce el nombre de una sala abierta, entra.&lt;br /&gt;
* '''Moderador (agente):''' entra autenticado mediante '''JWT'''. El mero hecho de conocer la URL de agente (un &amp;quot;churro&amp;quot; largo que en teoría solo conoce el agente que coge la llamada) implica ser agente. Esa URL lleva el JWT y el nombre de sala codificados, y solo sirve para esa sala.&lt;br /&gt;
* '''Invitados:''' cualquiera que conozca el nombre de la sala puede entrar '''sin autenticar'''.&lt;br /&gt;
* Si un agente reenvía su URL a otra persona, esa persona también entraría como moderador. Si dos agentes pinchan la URL que circula por OpenChannel, ambos entran en la misma sala.&lt;br /&gt;
&lt;br /&gt;
=== Diferencias frente a un Vybite Meet estándar ===&lt;br /&gt;
&lt;br /&gt;
Son básicamente '''dos''':&lt;br /&gt;
&lt;br /&gt;
# '''Autenticación del moderador.''' En Vybite Meet estándar el moderador se valida contra LDAP o contra la base de datos de usuarios de Vybite. En Videocan, el moderador (agente) se autentica vía '''JWT generado al vuelo por Videocan''', sin LDAP ni base de datos.&lt;br /&gt;
# '''Carteles (textos/idiomas de la interfaz).''' Se sustituyen para que no aparezca la palabra &amp;quot;Jitsi&amp;quot; sino &amp;quot;Vybite&amp;quot;, y para corregir las traducciones al castellano.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Conclusión operativa:''' un Vybite Meet existente de un cliente '''no sirve''' para dar este servicio. Serían máquinas e instalaciones distintas (por los carteles, las personalizaciones y la IP pública). Solo en un caso muy forzado podría plantearse compartir máquina usando '''dos dominios distintos''' sobre una misma IP pública. Como norma general: '''no'''.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== 5. Control de canales ==&lt;br /&gt;
&lt;br /&gt;
* Un '''canal = una llamada'''. El servicio se factura por '''canales simultáneos'''.&lt;br /&gt;
* Videocan lleva un control del número de canales en uso y aplica una '''limitación de canales concurrentes''' (&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;videocan_canales_maximo&amp;lt;/code&amp;gt;). Si se alcanza el máximo, las nuevas llamadas entran con '''congestión'''.&lt;br /&gt;
* Los &amp;quot;hilos&amp;quot; del demonio (p. ej. 2) son para atender peticiones web y no guardan relación con el número de canales; con pocos hilos basta porque no hay tanto tráfico web.&lt;br /&gt;
* Diagnóstico en caliente mediante el socket de control:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nc localhost 1132&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Muestra, entre otras cosas, los canales activos (&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;canales_...&amp;lt;/code&amp;gt;) y el contador de alarmas (las alarmas suelen deberse a temas de logs).&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== 6. Configuración: videocan.conf ==&lt;br /&gt;
&lt;br /&gt;
La configuración del módulo está centralizada en un único fichero en formato '''libconfig''', ubicado dentro del árbol &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/etc/mdtel/&amp;lt;/code&amp;gt; (en la máquina de desarrollo mostrada aparecía también como &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/etc/mdtel-videocan.conf&amp;lt;/code&amp;gt;; la convención estándar es &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/etc/mdtel/videocan.conf&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Para facilitar el despliegue existe un '''configurador''' (cuestionario) que el centro de servicios debe rellenar antes de arrancar una instalación y entregar cumplimentado.&lt;br /&gt;
&lt;br /&gt;
=== 6.1. Parámetros globales ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Descripción&lt;br /&gt;
|-&lt;br /&gt;
| '''host''' (nombre DNS) || El más crítico. Es el nombre de dominio completo (FQDN), p. ej. &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;labmeetvideo.mednova.local&amp;lt;/code&amp;gt;. Aparece en '''multitud de sitios, incluso en nombres de fichero'''. Es la razón por la que se instala de cero en cada despliegue (ver §8).&lt;br /&gt;
|-&lt;br /&gt;
| '''openchannel_apikey''' || API key de OpenChannel/OmniSuite. Por su tamaño no cabe como cadena en libconfig, así que '''se guarda en un fichero aparte''' y el programa lo carga. Ruta: &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/etc/mdtel/apikey_openchannel.txt&amp;lt;/code&amp;gt;. La proporciona el equipo de OmniSuite.&lt;br /&gt;
|-&lt;br /&gt;
| '''videocan_canales_maximo''' || Número de canales (llamadas) concurrentes soportados.&lt;br /&gt;
|-&lt;br /&gt;
| '''Filtro IP del API de agente''' || Restringe desde qué IP/máscara se puede invocar el API de agente (p. ej. &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;172.25.x.x&amp;lt;/code&amp;gt;). A &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;0&amp;lt;/code&amp;gt; queda abierto.&lt;br /&gt;
|-&lt;br /&gt;
| '''Dominios y certificados''' || Indica si se trabaja con certificados; debe resolverse '''antes''' de instalar.&lt;br /&gt;
|-&lt;br /&gt;
| '''firma''' || Firma electrónica de la licencia (ver §9). En un fichero base va vacía.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== 6.2. Parámetros por servicio ===&lt;br /&gt;
&lt;br /&gt;
Los '''servicios''' son, en la práctica, los '''OpenChannels''' (conceptualmente equivalentes a VDNs): los distintos &amp;quot;puntos de entrada&amp;quot; temáticos. Por cada servicio se configura:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Descripción&lt;br /&gt;
|-&lt;br /&gt;
| '''Nombre interno''' || Identificador intrascendente (1, 2, 3…).&lt;br /&gt;
|-&lt;br /&gt;
| '''Nombre a mostrar''' || Nombre descriptivo que ve el cliente por defecto como interlocutor (p. ej. &amp;quot;Antonio&amp;quot;). Hay APIs para que cada agente salga con el suyo.&lt;br /&gt;
|-&lt;br /&gt;
| '''token de servicio''' || Token que el '''usuario''' (no el agente) debe conocer para invocar el servicio; viaja en la URL de usuario. En algún despliegue concreto (FAPS) se decidió que no viaje nada y baste la URL.&lt;br /&gt;
|-&lt;br /&gt;
| '''url_openchannel''' || URL de OpenChannel que crea el proveedor de la plataforma (Skally) para ese servicio.&lt;br /&gt;
|-&lt;br /&gt;
| '''Proxy / verificación TLS de OpenChannel''' || Si se sale por proxy y si hay que verificar el certificado de OpenChannel (si es HTTPS).&lt;br /&gt;
|-&lt;br /&gt;
| '''Timeout de conexión de agente (s)''' || Tiempo máximo que el cliente espera sin que entre el agente; al vencer se '''cuelga la interacción de OpenChannel''' (en Meet no se puede informar al cliente, así que solo se corta OpenChannel). Se baraja fijarlo en torno a '''3600 s''' como red de seguridad y sacarlo del configurador.&lt;br /&gt;
|-&lt;br /&gt;
| '''Expiración del JWT de agente (s)''' || Tiempo que tiene el agente para '''entrar''' con el JWT (no limita la duración de la conversación). Valor mostrado: '''1800 s''' (30 min).&lt;br /&gt;
|-&lt;br /&gt;
| '''Antirrebotes''' || Si llegan varias peticiones al mismo servicio desde la misma IP en una ventana (p. ej. '''20 s'''), se etiquetan como rebote (doble clic) y no entran.&lt;br /&gt;
|-&lt;br /&gt;
| '''Timeout de liberación de sala (s)''' || Si una sala no se libera sola, se libera el canal a los '''30 s''' de detectar que no hay sala. Red de seguridad heredada de antes de existir el API de Prosody; el canal liberado cuenta para los concurrentes.&lt;br /&gt;
|-&lt;br /&gt;
| '''Nombre por defecto''' || Nombre a mostrar cuando los datos entrantes no incluyen nombre.&lt;br /&gt;
|-&lt;br /&gt;
| '''Variables''' || Pares nombre/valor (ver §7). Las fijas (&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;$0&amp;lt;/code&amp;gt;–&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;$2&amp;lt;/code&amp;gt;) más las específicas por servicio (de &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;$3&amp;lt;/code&amp;gt; en adelante).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== 6.3. Datos de entrada del usuario ===&lt;br /&gt;
&lt;br /&gt;
La aplicación de front-end recopila los datos que quiera y los envía al invocar el inicio de videollamada. '''No hay un conjunto de datos fijo'''; pueden llegar como argumentos de un GET o como JSON, pero el API siempre trabaja con '''pares nombre/valor'''. Ejemplos:&lt;br /&gt;
* '''Servicio &amp;quot;videollamada&amp;quot; (FAPS):''' &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;name&amp;lt;/code&amp;gt;, &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;lastname&amp;lt;/code&amp;gt;, &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;id&amp;lt;/code&amp;gt; (que aquí es el móvil), correo, &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;dni&amp;lt;/code&amp;gt;.&lt;br /&gt;
* '''Servicio &amp;quot;emergencia 112&amp;quot;:''' solo llegan '''latitud y longitud'''; al no llegar nombre, el campo nombre queda vacío.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== 7. Plantillas ==&lt;br /&gt;
&lt;br /&gt;
Ubicación: &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/etc/mdtel-videocan/templates&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Una '''plantilla''' es la '''página web''' que Videocan devuelve cuando se invoca una URL del API (por ejemplo &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;get_agente_nuevasala&amp;lt;/code&amp;gt;). Es una página con lógica, específica de cada llamada (no solo de cada servicio), porque el nombre de sala se genera al vuelo para cada llamada.&lt;br /&gt;
&lt;br /&gt;
* Las '''variables''' se marcan con $:&lt;br /&gt;
** &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;$0&amp;lt;/code&amp;gt; → host&lt;br /&gt;
** &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;$1&amp;lt;/code&amp;gt; → sala de la videollamada (creada al vuelo)&lt;br /&gt;
** &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;$2&amp;lt;/code&amp;gt; → nombre a mostrar (&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;displayName&amp;lt;/code&amp;gt;)&lt;br /&gt;
** &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;$3&amp;lt;/code&amp;gt; → token JWT (cadena)&lt;br /&gt;
** de &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;$3&amp;lt;/code&amp;gt;/siguientes en adelante → variables específicas del servicio&lt;br /&gt;
* Videocan sustituye las variables en la plantilla y entrega la página resultante. Quien la recibe queda viendo una '''sala de Meet ya con el JWT aplicado''', entrando autenticado.&lt;br /&gt;
* Las plantillas usan el '''API de integración de Jitsi Meet''' (referencia pública: &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;jitsi-meet-api-integration&amp;lt;/code&amp;gt;). '''No se usa un IFrame''': la sala se integra directamente en la página (un IFrame &amp;quot;siempre es puñetero&amp;quot;). El JavaScript de la integración vive en las plantillas.&lt;br /&gt;
* Permiten '''personalizar el aspecto''': por ejemplo &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;toolbarButtons&amp;lt;/code&amp;gt; (qué botones se muestran; hay muchos comentados/quitados), &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;startWithAudioMuted&amp;lt;/code&amp;gt;, el botón de '''Full Screen''' (se muestra el botón, no se entra en pantalla completa automáticamente), etc.&lt;br /&gt;
* Puede haber '''una plantilla por servicio''', pero lo habitual es que sean '''compartidas''' porque todos los servicios ven prácticamente lo mismo. Las diferencias razonables serían pequeñas (p. ej. permitir o no grabar, activar el botón de chat) y se tocarían vía &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;toolbarButtons&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Limitación conocida (móvil):''' al entrar compartiendo la URL, el usuario entra en vista de '''interlocutor en grande''' (no en cuadrícula), por lo que en el móvil '''no se ve a sí mismo'''. Es un problema relevante para lengua de signos, donde la persona necesita verse para comprobar el encuadre. Pulsando el botón de cuadrícula se soluciona, pero la intención es que la app sea transparente. El ajuste no se puede hacer por parámetros de URL; '''habría que resolverlo con JavaScript''' en la plantilla. Queda como punto abierto.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== 8. Instalación ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;El planteamiento actual es '''instalar siempre de cero''' (no entregar una imagen de máquina virtual), porque el '''nombre del host está en multitud de sitios''' (incluidos nombres de fichero) y reescribirlo en una imagen sería más complejo. Si en el futuro hubiera muchas instalaciones, podría replantearse.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 8.1. Prerrequisitos y orden ===&lt;br /&gt;
&lt;br /&gt;
# Obtener la '''IP pública''' y darla de alta en '''DNS''' (lo hace el cliente o nosotros, según de quién sea el dominio). Sin nombre DNS no se puede instalar (se necesita para el certificado).&lt;br /&gt;
# Instalar '''Nginx''' y '''Certbot''', obtener el '''certificado''' y crear el '''firewall''' (nftables).&lt;br /&gt;
# Instalar '''Meet''' mediante la lista de paquetes homologados (&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;apt install &amp;amp;lt;paquete&amp;amp;gt;&amp;lt;/code&amp;gt;, uno a uno). '''No se instala el repositorio de Jitsi''', sino paquetes concretos y homologados.&lt;br /&gt;
# La instalación de Meet '''modifica la configuración de Nginx y de Prosody''', así que tras instalarlo hay que '''reajustar''' ambos. (La configuración que deja Meet por defecto no sirve.) El proceso requiere iterar y reconfigurar varias veces.&lt;br /&gt;
# Sustituir el '''contenido estático''' (ver §8.2).&lt;br /&gt;
# Rellenar &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;videocan.conf&amp;lt;/code&amp;gt;, instalar el demonio, configurar el JWT en Prosody y '''firmar''' (ver §9).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Detalle de &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;apt&amp;lt;/code&amp;gt;: para instalar un &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;.deb&amp;lt;/code&amp;gt; local hay que indicar una ruta de directorio; por eso se usa &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;apt install ./paquete.deb&amp;lt;/code&amp;gt; (con &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;./&amp;lt;/code&amp;gt;). Se usa &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;apt install&amp;lt;/code&amp;gt; en lugar de &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;dpkg -i&amp;lt;/code&amp;gt; porque '''resuelve dependencias'''.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Existe un '''punto intermedio de validación''' muy útil: cuando todo funciona '''sin autenticación''', cualquiera que conozca el nombre de sala entra directamente. Si &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;host/pepito&amp;lt;/code&amp;gt; permite que varios se conecten a la sala &amp;quot;pepito&amp;quot; sin autenticar, la instalación base está correcta. A partir de ahí se valida el resto tirando de logs y de la herramienta &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;jitsi-debug&amp;lt;/code&amp;gt; (sección ''Health'').&lt;br /&gt;
&lt;br /&gt;
=== 8.2. Contenido estático (carteles y personalización) ===&lt;br /&gt;
&lt;br /&gt;
* Jitsi instala un directorio de contenido estático en &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/usr/share/jitsi-meet/…&amp;lt;/code&amp;gt;. Videocan '''lo reemplaza entero''' por uno propio (logos, fondos, textos &amp;quot;Vybite Meet&amp;quot;). Ese directorio propio es '''igual para todas las instalaciones''' (no se configura nada en él).&lt;br /&gt;
* Los '''carteles''' (textos de interfaz) están en &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/usr/share/jitsi-meet/lang/&amp;lt;/code&amp;gt;:&lt;br /&gt;
** &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;main.json&amp;lt;/code&amp;gt; → inglés (suele estar bien, retocado para sustituir &amp;quot;Jitsi&amp;quot; por &amp;quot;Vybite&amp;quot;).&lt;br /&gt;
** &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;main-es.json&amp;lt;/code&amp;gt; → castellano (~1700 carteles; las traducciones por defecto son deficientes y se corrigen).&lt;br /&gt;
* '''No se recomienda modificar los DEB''' para empaquetar el contenido propio: como los paquetes modifican configuraciones y Meet cambia con frecuencia, no compensa.&lt;br /&gt;
* '''Actualizaciones (update/upgrade):''' son arriesgadas porque pueden '''reescribir los carteles''' (decenas de cambios por actualización). El procedimiento de mantenimiento de carteles consiste en comparar a tres (inglés viejo, inglés nuevo, español nuevo) con una herramienta tipo '''Meld''' o el comparador de '''Notepad++''', y trasladar los cambios manteniendo coherencia terminológica. Por eso Meet '''no se actualiza en cada release''', sino periódicamente, y solo cuando interesa (la mayoría de novedades —integración con Drive, transcripción, traducción simultánea— no se usan). La transcripción se apoya en '''Vosk''', que de momento da resultados pobres. Las actualizaciones por '''seguridad''' sí deberán contemplarse.&lt;br /&gt;
&lt;br /&gt;
=== 8.3. Instalación del demonio Videocan ===&lt;br /&gt;
&lt;br /&gt;
Sigue el estándar de los demonios &amp;quot;mdtel&amp;quot;:&lt;br /&gt;
* Binario y módulo en '''&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/opt/videocan/bin/&amp;lt;/code&amp;gt;''' (&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/opt/videocan/&amp;lt;/code&amp;gt; como raíz; el módulo de Prosody también reside ahí).&lt;br /&gt;
* Arranque en '''&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/etc/init.d/&amp;lt;/code&amp;gt;'''.&lt;br /&gt;
* Configuración en '''&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/etc/mdtel/videocan.conf&amp;lt;/code&amp;gt;''' (más &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;apikey_openchannel.txt&amp;lt;/code&amp;gt; en el mismo árbol).&lt;br /&gt;
* Rotación de logs en '''&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/etc/logrotate.d/videocan&amp;lt;/code&amp;gt;'''.&lt;br /&gt;
* Logs en '''&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/var/log/videocan/videocan.log&amp;lt;/code&amp;gt;''' (el demonio corre como usuario &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;videocan&amp;lt;/code&amp;gt;, '''no como root''', por estar publicado en web).&lt;br /&gt;
&lt;br /&gt;
=== 8.4. Instalaciones existentes (referencia) ===&lt;br /&gt;
&lt;br /&gt;
* '''&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;labmeetvideo.mednova.local&amp;lt;/code&amp;gt;''' — instalación interna (sin Certbot, no publicada).&lt;br /&gt;
* '''&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;mdtel.videocan01.vybite.es&amp;lt;/code&amp;gt;''' — instalación con IP pública (en Soax), para el centro de servicios de pruebas/demos.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== 9. Firma de licencia y tokens ==&lt;br /&gt;
&lt;br /&gt;
El &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;videocan.conf&amp;lt;/code&amp;gt; debe estar protegido para que '''no se pueda manipular''' (por ejemplo, cambiar el número de canales a 2000). Esa protección es la '''firma electrónica''', que usa el '''mismo procedimiento y los mismos certificados que Vybite'''.&lt;br /&gt;
&lt;br /&gt;
=== 9.1. Qué se protege ===&lt;br /&gt;
&lt;br /&gt;
La firma cubre '''tres''' valores:&lt;br /&gt;
# '''Número de servicios''' (no su contenido: se pueden modificar libremente, pero no crear más de los firmados).&lt;br /&gt;
# '''Número de canales.'''&lt;br /&gt;
# '''host''' (dominio) — para que no se pueda instalar en muchos sitios con la misma licencia.&lt;br /&gt;
&lt;br /&gt;
=== 9.2. Tokens ===&lt;br /&gt;
&lt;br /&gt;
* Los '''tokens''' y el '''&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;JWT_SECRET&amp;lt;/code&amp;gt;''' hacen que cada instalación sea '''distinta'''. La herramienta de firma puede regenerarlos (claves particulares aleatorias por instalación).&lt;br /&gt;
* El '''token de servicio''' debe '''coincidir''' con lo que conoce la '''aplicación de usuario''' del otro lado. Por eso, cuando se regeneran tokens, hay que revisar las URLs de acceso y, en su caso, tocar la página web que se entrega al cliente (p. ej. en FAPS, el token lo tenemos nosotros, así que se ajusta en la página web alojada en esta máquina).&lt;br /&gt;
* El '''&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;JWT_SECRET&amp;lt;/code&amp;gt;''' debe configurarse en '''Prosody''' como '''&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;APP_SECRET&amp;lt;/code&amp;gt;''' (ver §9.4).&lt;br /&gt;
&lt;br /&gt;
=== 9.3. Herramienta videocan-firmar ===&lt;br /&gt;
&lt;br /&gt;
Primer parámetro = operación a realizar:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Operación !! Efecto&lt;br /&gt;
|-&lt;br /&gt;
| '''Generar tokens''' || Regenera los tokens (not firma). No requiere la clave; podría delegarse al cliente.&lt;br /&gt;
|-&lt;br /&gt;
| '''Firmar''' || Generar solo la firma.&lt;br /&gt;
|-&lt;br /&gt;
| '''Generar tokens y firmar''' || Operación recomendada para todas las instalaciones.&lt;br /&gt;
|-&lt;br /&gt;
| '''Verificar''' || Indica si la firma del fichero es válida. No requiere clave (va embebida en la herramienta).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Reglas:&lt;br /&gt;
* Siempre se indica '''el fichero de configuración''' (no se modifica el original: la herramienta entrega '''otro fichero''' ya procesado).&lt;br /&gt;
* Para '''firmar''' se necesita el '''fichero de clave privada (.key)'''; para '''verificar''' no se necesita nada.&lt;br /&gt;
&lt;br /&gt;
Ejemplos:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Verificar&lt;br /&gt;
videocan-firmar verificar /etc/mdtel/videocan.conf&lt;br /&gt;
# → &amp;quot;La sección Videocan tiene un campo firma que no es correcto.&lt;br /&gt;
#     Error al verificar firma de videocan.conf.&amp;quot;   (si no es válido)&lt;br /&gt;
&lt;br /&gt;
# Generar tokens + firmar (recomendado)&lt;br /&gt;
videocan-firmar tokens-firmar mdtel.key videocan.conf&lt;br /&gt;
# → &amp;quot;Operación correcta. Se actualiza el fichero.&amp;quot;&lt;br /&gt;
#   Avisos: token de servicio modificado (revisar URLs de acceso),&lt;br /&gt;
#           JWT_SECRET modificado (configurar APP_SECRET y reiniciar Prosody),&lt;br /&gt;
#           firma del archivo modificada.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Una verificación correcta enumera qué se está firmando (host, número de servicios, número de canales) y termina con un &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;OK&amp;lt;/code&amp;gt; en la '''última línea''':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Host labmeetvideo... ok&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 9.4. Tras firmar ===&lt;br /&gt;
&lt;br /&gt;
# Configurar '''&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;APP_SECRET&amp;lt;/code&amp;gt;''' en Prosody con el nuevo &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;JWT_SECRET&amp;lt;/code&amp;gt;. Configuración de Prosody en '''&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/etc/prosody/conf.avail/&amp;lt;/code&amp;gt;''' (estructura similar a la de Nginx; el fichero incluye el nombre de dominio).&lt;br /&gt;
# '''Reiniciar Prosody.'''&lt;br /&gt;
# Revisar las '''URLs de acceso''' afectadas por el cambio de tokens de servicio.&lt;br /&gt;
&lt;br /&gt;
=== 9.5. Comportamiento sin firma válida (&amp;quot;la bomba&amp;quot;) ===&lt;br /&gt;
&lt;br /&gt;
Si la firma '''no es válida''', el sistema '''sigue funcionando pero limitado a 1 canal''' (&amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;canales_max = 1&amp;lt;/code&amp;gt;). El paso a 1 canal '''no ocurre en el arranque''', sino tras un tiempo indeterminado (diseñado así para dificultar su localización en el código). Esto permite, en la práctica, '''hacer demos''': con el fichero sin firmar y configurado a 1 canal, todo funciona. El procedimiento habitual del cliente puede ser instalar primero (con tokens, para que arranque y se pueda probar) y '''entregarnos después el fichero para que lo firmemos''' con las licencias.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== 10. Diagnóstico y logs ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Recurso !! Uso&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;nc localhost 1132&amp;lt;/code&amp;gt; || Socket de control de Videocan: canales activos, alarmas, congestión.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/var/log/videocan/videocan.log&amp;lt;/code&amp;gt; || Log del demonio Videocan.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/var/log/prosody/&amp;lt;/code&amp;gt; || Log de Prosody.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/var/log/nginx/&amp;lt;/code&amp;gt; || Log de Nginx.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/var/log/jitsi/&amp;lt;/code&amp;gt; || Log de la pila Jitsi.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;jitsi-debug&amp;lt;/code&amp;gt; (script) || Comprobación de salud de la instalación (sección ''Health'').&lt;br /&gt;
|-&lt;br /&gt;
| '''Zabbix''' (vía &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;nc&amp;lt;/code&amp;gt;) || Monitorización externa, especialmente de congestiones, explotando el socket &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;nc&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== 11. Resumen de rutas y puertos ==&lt;br /&gt;
&lt;br /&gt;
'''Rutas (convención estándar &amp;lt;code style=&amp;quot;background:none; border:none; padding:0;&amp;quot;&amp;gt;/etc/mdtel/&amp;lt;/code&amp;gt;):'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/opt/videocan/bin/                      # demonio Videocan + módulo&lt;br /&gt;
/etc/init.d/videocan                    # arranque&lt;br /&gt;
/etc/mdtel/videocan.conf                # configuración principal (libconfig)&lt;br /&gt;
/etc/mdtel/apikey_openchannel.txt       # API key de OpenChannel&lt;br /&gt;
/etc/mdtel-videocan/templates/          # plantillas (páginas web con JS de integración Meet)&lt;br /&gt;
/etc/logrotate.d/videocan               # rotación de logs&lt;br /&gt;
/etc/prosody/conf.avail/                # configuración de Prosody (APP_SECRET)&lt;br /&gt;
/var/log/videocan/videocan.log          # log del demonio (usuario videocan)&lt;br /&gt;
/usr/share/jitsi-meet/                  # contenido estático (reemplazado por el propio)&lt;br /&gt;
/usr/share/jitsi-meet/lang/main.json    # carteles inglés&lt;br /&gt;
/usr/share/jitsi-meet/lang/main-es.json # carteles castellano (~1700)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Puertos:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
443/TCP    Nginx (HTTPS, proxy inverso, APIs de Videocan)&lt;br /&gt;
10000/UDP  RTP de Meet (audio/vídeo) sobre la IP pública&lt;br /&gt;
1132       Socket de control local de Videocan (nc localhost 1132)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== 12. Limitaciones y puntos abiertos ==&lt;br /&gt;
&lt;br /&gt;
* '''Solo audio y vídeo'''; sin compartición de pantalla ni chat (el chat, si se activase, debería ir por OpenChannel).&lt;br /&gt;
* '''Vista en móvil:''' el usuario no se ve a sí mismo al entrar (entra en vista de interlocutor, no en cuadrícula). Relevante para lengua de signos. Pendiente de resolver vía JavaScript en plantilla.&lt;br /&gt;
* '''Cierre de la interacción OpenChannel:''' confirmar con el equipo de OmniSuite si debe ser automático o manual.&lt;br /&gt;
* '''Transcripción (Vosk):''' calidad pobre; no apta de momento.&lt;br /&gt;
* '''Actualizaciones de Meet:''' arriesgadas por los carteles; solo cuando interese o por seguridad.&lt;br /&gt;
* '''Requiere IP pública dedicada''' por máquina (a día de hoy).&lt;br /&gt;
* '''Validación de la instalación completa''' sobre máquina estándar de producción: pendiente de cerrar.&lt;br /&gt;
* Un '''Vybite Meet''' de cliente '''no''' sirve para este servicio (instalaciones distintas).&lt;br /&gt;
&lt;br /&gt;
= Notas tomadas =&lt;br /&gt;
&lt;br /&gt;
== Maquina genérica ==&lt;br /&gt;
* '''Debian 13'''&lt;br /&gt;
* '''nginx'''&lt;br /&gt;
* '''certbot'''&lt;br /&gt;
* '''prosody'''&lt;br /&gt;
* No hay Mariadb/Mysql&lt;br /&gt;
* Para montar el meet habrá un procedimiento que nos dará Antonio&lt;br /&gt;
&lt;br /&gt;
== Diferencias con un VIVAit Meet &amp;quot;standard&amp;quot; ==&lt;br /&gt;
* '''Autenticación:''' VIVAit Meet autentica con credenciales con LDAP o BBDD VIVAit; aquí no hay LDAP ni usuarios. En la URL que llega del chat de la URL de videocan llega un Token. Con esa URL, cuando se conecta el agente, se autentica usando JWT y ya entra autenticado como moderador.&lt;br /&gt;
* '''Carteles'''&lt;br /&gt;
&lt;br /&gt;
== Consideraciones de arquitectura ==&lt;br /&gt;
* '''No se entrega máquina virtual, siempre se instalará:''' Por ejemplo, el nombre de host está en una cantidad de sitios tan grande que es inmanejable de otra forma.&lt;br /&gt;
* '''Nodo dedicado:''' Siempre instalado en un nodo entero; no es compatible con Asterisk (ambos usan el puerto 10000).&lt;br /&gt;
* '''Red:''' Requiere una IP Pública entera (puede ser Nateada).&lt;br /&gt;
* '''Exclusividad:''' No es compatible con &amp;quot;otro meet&amp;quot; que pudiera haber en el cliente.&lt;br /&gt;
&lt;br /&gt;
== Desarrollos ==&lt;br /&gt;
* '''Módulo mod en prosody'''&lt;br /&gt;
* '''Videocan (Demonio):''' Proporciona APIs:&lt;br /&gt;
** API de conexión de cliente&lt;br /&gt;
** API de conexión de Agente&lt;br /&gt;
** API contra prosody (control de canales)&lt;br /&gt;
* '''Aplicación para firmar (videoCanFirmar):''' Usa la clave privada habitual.&lt;br /&gt;
** Se le pasa un fichero &amp;lt;code&amp;gt;videoCan.conf&amp;lt;/code&amp;gt; y devuelve otro modificado (no lo machaca).&lt;br /&gt;
** Puede generar firma, &amp;lt;code&amp;gt;jwt_secret&amp;lt;/code&amp;gt; (para prosody) y tokens (para la conexión desde el lado cliente a URL de videoCan para el servicio).&lt;br /&gt;
* '''Plantilla:''' Cuando se invoca a una URL de videocan, la página que se le devuelve es una plantilla. Personalizan aspectos &amp;quot;del meet&amp;quot;, reciben parámetros, etc.&lt;br /&gt;
* Cuando invocamos a &amp;lt;code&amp;gt;openchannel&amp;lt;/code&amp;gt; desde videocan también existe una plantilla para &amp;quot;lo que le entra al agente&amp;quot;.&lt;br /&gt;
* '''Plantillas:''' Tienen Javascript.&lt;br /&gt;
&lt;br /&gt;
== Proceso de instalación ==&lt;br /&gt;
* Pendiente del detalle.&lt;br /&gt;
* Configurar prosody (seguramente solo cambiar nombre de host).&lt;br /&gt;
* Modificar el JWT.&lt;br /&gt;
* Reconfigurar varias veces NGINX y meet.&lt;br /&gt;
* Puntos intermedios de prueba en los que se puede probar vídeo (sin autenticación).&lt;br /&gt;
* '''Importante:''' Ir viendo logs en todo el proceso.&lt;br /&gt;
&lt;br /&gt;
== Seguridad ==&lt;br /&gt;
=== Medidas de protección ===&lt;br /&gt;
* '''Nftables'''&lt;br /&gt;
* '''Fail2ban:''' Manejamos el nginx y el mcan.&lt;br /&gt;
* '''Firmas de control:''' Firmamos una cadena que contiene los valores que nos interesa proteger para poder tener distribución y que, por ejemplo, no nos amplíen el número de canales. Protegemos:&lt;br /&gt;
** Número de servicios&lt;br /&gt;
** Número de canales&lt;br /&gt;
** Host&lt;br /&gt;
* '''Actualizaciones (por seguridad):''' &amp;lt;code&amp;gt;update&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;upgrade&amp;lt;/code&amp;gt;, y cuando saquemos actualizaciones de meet o videocan.&lt;br /&gt;
&lt;br /&gt;
== Configuraciones ==&lt;br /&gt;
* Hay un fichero guía de instalación / cuestionario a cliente.&lt;br /&gt;
* &amp;lt;code&amp;gt;videoCan.conf&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Diagnósticos ==&lt;br /&gt;
=== Videocan ===&lt;br /&gt;
* Comando de diagnóstico:&lt;br /&gt;
: &amp;lt;code&amp;gt;nc localhost 1132&amp;lt;/code&amp;gt;&lt;br /&gt;
* Rutas de logs principales:&lt;br /&gt;
: &amp;lt;code&amp;gt;/var/log/videoCan/videoCan.log&amp;lt;/code&amp;gt;&lt;br /&gt;
: &amp;lt;code&amp;gt;/var/log/nginx&amp;lt;/code&amp;gt; (Típicos de nginx)&lt;br /&gt;
: &amp;lt;code&amp;gt;/var/log/prosody&amp;lt;/code&amp;gt;&lt;br /&gt;
: &amp;lt;code&amp;gt;/var/log/jitsi&amp;lt;/code&amp;gt;&lt;br /&gt;
* Monitoreo: '''Zabbix''' (explotando el comando &amp;quot;nc&amp;quot;).&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=MediaWiki:Sidebar&amp;diff=19164</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=MediaWiki:Sidebar&amp;diff=19164"/>
		<updated>2026-07-13T08:23:04Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
**mainpage|mainpage-description&lt;br /&gt;
&lt;br /&gt;
* Usuario&lt;br /&gt;
** Documentación de usuario VIVAit Call|VIVAit Call&lt;br /&gt;
** Documentacion de usuario VIVAit Suite|VIVAit Suite&lt;br /&gt;
** Documentacion de usuario VIVAit Alert|VIVAit Alert&lt;br /&gt;
&amp;lt;!--*** Documentación de usuario VIVAit Fax|VIVAit Fax--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Administrador&lt;br /&gt;
** Arquitectura VIVAit|Arquitectura&lt;br /&gt;
** Release Notes|Release Notes&lt;br /&gt;
** Funcionalidades | Funcionalidades&lt;br /&gt;
** Portales de administración VIVAit |Portales de administración&lt;br /&gt;
** Preguntas frecuentes administración | Preguntas frecuentes&lt;br /&gt;
&lt;br /&gt;
* Servicio técnico&lt;br /&gt;
** Manuales de instalación|Instalación&lt;br /&gt;
** Actualización|Actualización&lt;br /&gt;
** Manuales de operación plataforma VIVAit |Manuales de operación&lt;br /&gt;
** Terminales homologados en VIVAit | Terminales&lt;br /&gt;
** Hylafax + IAXmodem en VIVAit Call| Solución de fax para VIVAit Call&lt;br /&gt;
** Howtos| Howtos&lt;br /&gt;
** Formación| Formación&lt;br /&gt;
** Incidencias| Incidencias&lt;br /&gt;
** Base de datos| Base de datos&lt;br /&gt;
&lt;br /&gt;
* Desarrollo&lt;br /&gt;
** APIs integracion|API's de integración&lt;br /&gt;
** Kit argumentarios|Desarrollo de argumentarios&lt;br /&gt;
&lt;br /&gt;
* vFlow&lt;br /&gt;
** Manual de operación de vFlow|Operación&lt;br /&gt;
** Portal de administración de vFlow|Administración&lt;br /&gt;
&lt;br /&gt;
* Omnisuite&lt;br /&gt;
** RecordOmni|Mejora grabaciones&lt;br /&gt;
** Manual de operación de vFlow | Integración vflow (punto 6)&lt;br /&gt;
** Omnisuite STT y TTS | STT y TTS&lt;br /&gt;
** Omnisuite_videoCan | Módulo de vídeo en Omnisuite (VideoCan)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* VIVAit Fax&lt;br /&gt;
** Documentación de usuario VIVAit Fax|Usuario&lt;br /&gt;
** Arquitectura VIVAit Fax|Arquitectura&lt;br /&gt;
** Instalación VIVAit Fax|Instalación&lt;br /&gt;
** Documentacion técnica|Servicio Técnico&lt;br /&gt;
&lt;br /&gt;
* Cartelia&lt;br /&gt;
** Instalacion_cartelia | Instalacion de cartelia&lt;br /&gt;
** Operacion_cartelia | Operacion de cartelia&lt;br /&gt;
&lt;br /&gt;
*  Roadmap&lt;br /&gt;
** Proyectos en desarrollo|Proyectos en desarrollo&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia&amp;diff=19163</id>
		<title>Instalacion cartelia</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Instalacion_cartelia&amp;diff=19163"/>
		<updated>2026-07-13T08:21:03Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: Página creada con «== Manual de instalación de cartelia 1.0 ==»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Manual de instalación de cartelia 1.0 ==&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=MediaWiki:Sidebar&amp;diff=19162</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=MediaWiki:Sidebar&amp;diff=19162"/>
		<updated>2026-07-13T08:19:12Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
**mainpage|mainpage-description&lt;br /&gt;
&lt;br /&gt;
* Usuario&lt;br /&gt;
** Documentación de usuario VIVAit Call|VIVAit Call&lt;br /&gt;
** Documentacion de usuario VIVAit Suite|VIVAit Suite&lt;br /&gt;
** Documentacion de usuario VIVAit Alert|VIVAit Alert&lt;br /&gt;
&amp;lt;!--*** Documentación de usuario VIVAit Fax|VIVAit Fax--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Administrador&lt;br /&gt;
** Arquitectura VIVAit|Arquitectura&lt;br /&gt;
** Release Notes|Release Notes&lt;br /&gt;
** Funcionalidades | Funcionalidades&lt;br /&gt;
** Portales de administración VIVAit |Portales de administración&lt;br /&gt;
** Preguntas frecuentes administración | Preguntas frecuentes&lt;br /&gt;
&lt;br /&gt;
* Servicio técnico&lt;br /&gt;
** Manuales de instalación|Instalación&lt;br /&gt;
** Actualización|Actualización&lt;br /&gt;
** Manuales de operación plataforma VIVAit |Manuales de operación&lt;br /&gt;
** Terminales homologados en VIVAit | Terminales&lt;br /&gt;
** Hylafax + IAXmodem en VIVAit Call| Solución de fax para VIVAit Call&lt;br /&gt;
** Howtos| Howtos&lt;br /&gt;
** Formación| Formación&lt;br /&gt;
** Incidencias| Incidencias&lt;br /&gt;
** Base de datos| Base de datos&lt;br /&gt;
&lt;br /&gt;
* Desarrollo&lt;br /&gt;
** APIs integracion|API's de integración&lt;br /&gt;
** Kit argumentarios|Desarrollo de argumentarios&lt;br /&gt;
&lt;br /&gt;
* vFlow&lt;br /&gt;
** Manual de operación de vFlow|Operación&lt;br /&gt;
** Portal de administración de vFlow|Administración&lt;br /&gt;
&lt;br /&gt;
* Omnisuite&lt;br /&gt;
** RecordOmni|Mejora grabaciones&lt;br /&gt;
** Manual de operación de vFlow | Integración vflow (punto 6)&lt;br /&gt;
** Omnisuite STT y TTS | STT y TTS&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* VIVAit Fax&lt;br /&gt;
** Documentación de usuario VIVAit Fax|Usuario&lt;br /&gt;
** Arquitectura VIVAit Fax|Arquitectura&lt;br /&gt;
** Instalación VIVAit Fax|Instalación&lt;br /&gt;
** Documentacion técnica|Servicio Técnico&lt;br /&gt;
&lt;br /&gt;
* Cartelia&lt;br /&gt;
** Instalacion_cartelia | Instalacion de cartelia&lt;br /&gt;
** Operacion_cartelia | Operacion de cartelia&lt;br /&gt;
&lt;br /&gt;
*  Roadmap&lt;br /&gt;
** Proyectos en desarrollo|Proyectos en desarrollo&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Manual_de_operaci%C3%B3n_de_vFlow&amp;diff=19161</id>
		<title>Manual de operación de vFlow</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Manual_de_operaci%C3%B3n_de_vFlow&amp;diff=19161"/>
		<updated>2026-07-07T10:09:47Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* Gestión en vFlow */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Descripción general vFlow ==&lt;br /&gt;
&lt;br /&gt;
vFlow es un módulo de conexión a sistemas de inteligencia artifical para sistemas de comunicaciones unificadas, ya sean sistemas corporativos o contact center&lt;br /&gt;
Gracias a vFlow, las plataformas de UC dispondrán de una solución para comunicarse con sistemas IA utilizando un mismo mecanismo independientemente de la solución de inteligencia artificial que se utilice&lt;br /&gt;
&lt;br /&gt;
Para proporcionar el servicio de manera completa, vFlow (en concreto el orquestador) se conectará a sistemas de inteligencia artificial (LLM) que permitirán desarrollar los agentes definidos en los orquestadores&lt;br /&gt;
&lt;br /&gt;
'''Conceptos:'''&lt;br /&gt;
* Plataforma&amp;lt;span style=&amp;quot;margin-left: 3em;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;--&amp;gt; Plataforma de comunicaciones unificadas; por ejemplo Omnisuite o VIVAit Call&lt;br /&gt;
* Orquestador&amp;lt;span style=&amp;quot;margin-left: 3em;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;--&amp;gt; Plataforma agéntica de IA (por ejemplo Flowise)&lt;br /&gt;
* vFlowProxy&amp;lt;span style=&amp;quot;margin-left: 3em;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;--&amp;gt; Módulo VIVAit que conecta multiples plataformas con múltiples orquestadores&lt;br /&gt;
* LLM&amp;lt;span style=&amp;quot;margin-left: 3em;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;--&amp;gt; Modelo de lenguaje natural que usará un orquestadores&lt;br /&gt;
* Agente&amp;lt;span style=&amp;quot;margin-left: 3em;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;--&amp;gt; Cada uno de los flujos creados en vFlow; corresponde a un par plataforma/agentflow de orquestador&lt;br /&gt;
* Servicio&amp;lt;span style=&amp;quot;margin-left: 3em;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;--&amp;gt; Cada elemento de negocio en la plataforma de CU (por ejemplo VDN)&lt;br /&gt;
&lt;br /&gt;
[[Archivo:Arquitectura Vflow - v2.jpg|1400px|center|Arquitecura de vFlow]]&lt;br /&gt;
&lt;br /&gt;
Los '''módulos principales''' de vFlow son:&lt;br /&gt;
* vFlowProxy: Recibe las conexiones de los sistemas de comunicaciones unificadas, y conecta con los orquestadores de Inteligencia Artificial de manera segura y adaptada al tipo de servicio; el acceso a vFlow Proxy desde las plataformas se realizará mediante:&lt;br /&gt;
* Programa cliente: Se utiliza en el sistema de comunicaciones unificadas (actualmente VIVAit Call y Omnsisuite) para invocar a vFlow&lt;br /&gt;
* API REST: Alternativa al programa cliente, vFlowProxy proporciona una API REST que facilita que cualquier plataforma pueda comunicarse mediante un procedimiento estándar y documentado&lt;br /&gt;
* Portal de administración vFlow: Permite visualizar las interaciones realizadas y configurar el sistema&lt;br /&gt;
* Orquestador de IA: Herramienta de Inteligencia Artificial que permitirá la creación de aplicaciones personalizadas (agentes)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
'''Otros elementos''' relevantes serán:&lt;br /&gt;
* Base de datos vFlow:&lt;br /&gt;
:* Almacena información sobre sesiones y transacciones realizadas&lt;br /&gt;
:* Almacena información de configuración sobre vFlow&lt;br /&gt;
:* Gestiona el RAG de las inteligencias artificiales a usar&lt;br /&gt;
&lt;br /&gt;
== Puesta en marcha de nodo vFlow ==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Existe un nodo vFlow en los repositorios habituales proporcionados&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para '''dar de alta nodo vflow en un cliente''' hay que:&lt;br /&gt;
* Configurar IP (por defecto la maquina va configurada por DHCP)&lt;br /&gt;
* Adaptar el firewall, para ello REVISAR el fichero &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
* Certificados validos en apache&lt;br /&gt;
* REVISAR ficheros &amp;lt;code&amp;gt;/etc/apache2/sites-enabled/flowise.conf&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;/etc/apache2/sites-enabled/vFlow.conf&amp;lt;/code&amp;gt; la variable &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt; (nombre valido de la maquina)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Accesos vFlow''' (se debe cambiar tras instalación):&lt;br /&gt;
* Usuario ssh y de SO por defecto es sat y clave a proporcionar.&lt;br /&gt;
* Para el portal de flowise las credenciales son usuario: vfloadmin@vflow.com clave: A proporcionar&lt;br /&gt;
* Para el portal de vflow las credenciales son usaurio sat y clave a proporcionar.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Accesos BBDD vFlow'''&lt;br /&gt;
* Para acceder a la base de datos desde el workbenck solo desde localhost (o tunel):&lt;br /&gt;
* BBDD Vlfow (admin)  vflowadmin // clave a proporcionar&lt;br /&gt;
* BBDD Vlfow (no_admin)  vflow //  clave a proporcionar&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Portal orquestador Flowise'''&lt;br /&gt;
&lt;br /&gt;
ubicado en https://host.cliente.xx:4567&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #fef6e7; border: 1px solid #fbd68a; padding: 1em; border-radius: 4px;width: fit-content; margin-left: 50px&amp;quot;&amp;gt;&lt;br /&gt;
'''⚠️ ATENCION !!'''&lt;br /&gt;
'''Los cambios en tablas de configuración de BBDD de vFlow (orquestadores, plataformas, agentes) requieren reinicio del servicio vFlowProxy'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', 'Monaco', 'Courier New', monospace;&amp;quot;&amp;gt;&lt;br /&gt;
/etc/init.d/vFlowProxy.service status&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
/etc/init.d/vFlowProxy.service stop&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
/etc/init.d/vFlowProxy.service start&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
El fichero de configuración del demonio &amp;lt;code&amp;gt;vFlowProxy&amp;lt;/code&amp;gt; se encuentra en &amp;lt;code&amp;gt;/etc/MDtel/vFlowProxy.conf&amp;lt;/code&amp;gt;, si bien este fichero de configuración no se modificará habitualmente (los parámetros generales de configuración de vFlowProxy se encuentran en la BBDD de vFlow)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Procedimientos de respaldo y restauración ==&lt;br /&gt;
&lt;br /&gt;
=== Respaldo ===&lt;br /&gt;
&lt;br /&gt;
* Hacer backup de las bases de datosdel orquestador (flowise) y de vFlow&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', 'Monaco', 'Courier New', monospace;&amp;quot;&amp;gt;&lt;br /&gt;
mariadb-dump -u root -p --single-transaction --routines --events --triggers --default-character-set=utf8mb4 vflow_flowise_config &amp;gt; vflow_flowise_config_$(date +%F_%H%M%S).sql&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
mariadb-dump -u root -p --single-transaction --routines --events --triggers --default-character-set=utf8mb4 vflow_flowise_config &amp;gt; vflow_flowise_upsert_$(date +%F_%H%M%S).sql&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
mariadb-dump -u root -p --single-transaction --routines --events --triggers --default-character-set=utf8mb4 vFlow &amp;gt; vFlow_$(date +%F_%H%M%S).sql&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* Copiar:&lt;br /&gt;
** El directorio /opt/vFlow_flowise/.flowise&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', 'Monaco', 'Courier New', monospace;&amp;quot;&amp;gt;&lt;br /&gt;
cp -vai  /opt/vFlow_flowise/.flowise  /opt/vFlow_flowise/.flowise_$(date +%F_%H%M%S)&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
** El directorio /opt/vFlow_flowise/archivos&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', 'Monaco', 'Courier New', monospace;&amp;quot;&amp;gt;&lt;br /&gt;
cp -vai  /opt/vFlow_flowise/archivos /opt/vFlow_flowise/archivos_$(date +%F_%H%M%S)&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
'''Todos los ficheros creados pueden ser movidos al destino deseado para almacenar la copia de respaldo'''&lt;br /&gt;
&lt;br /&gt;
=== Restauración ===&lt;br /&gt;
Para restaurar, será necesario&lt;br /&gt;
* Importar de nuevo las dos bases de datos de flowise y la base de datos de vFlow:&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', 'Monaco', 'Courier New', monospace;&amp;quot;&amp;gt;&lt;br /&gt;
mysql -u root -p vflow_flowise_config &amp;lt;  vflow_flowise_config_ULTIMAFECHA.sql&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
mysql -u root -p vflow_flowise_upsert &amp;lt;  vflow_flowise_upsert_ULTIMAFECHA.sql&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
mysql -u root -p vFlow &amp;lt;  vFlow_ULTIMAFECHA.sql&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* Volver a poner las carpetas de /opt/vFlow_flowise/&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', 'Monaco', 'Courier New', monospace;&amp;quot;&amp;gt;&lt;br /&gt;
mv -vi  /opt/vFlow_flowise/.flowise_ULTIMAFECHA  /opt/vFlow_flowise/.flowise&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
mv -vi /opt/vFlow_flowise/archivos_ULTIMAFECHA  /opt/vFlow_flowise/archivos&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
'''Las ubicaciones de los archivos a resturar pueden ser diferentes'''&lt;br /&gt;
&lt;br /&gt;
== Gestión en vFlow ==&lt;br /&gt;
vFlow prevé la existencia de tres entornos que permita hacer una gestión segura de agentes y RAG:&lt;br /&gt;
&lt;br /&gt;
* Producción&lt;br /&gt;
* Preproducción&lt;br /&gt;
* Pruebas&lt;br /&gt;
&lt;br /&gt;
Para cada agente o store de RAG se podrá desplegar un entorno, dos o los tres entornos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f0fff4; border: 3px solid #c6f6d5; padding: 1em; border-radius: 4px;width: fit-content; margin-left: 0px&amp;quot;&amp;gt;&lt;br /&gt;
✅ '''Recomendación'''&amp;lt;br&amp;gt;&lt;br /&gt;
::En la mayoría de los casos con disponer de entorno de producción y preproducción tanto para agente como para RAG será suficiente&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Para realizar una gestión completa en vFlow (suponiendo tres entornos y gestión de agentes y RAG), deberemos tener&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Archivo:Gestión RAG.png|1200px|miniaturadeimagen|centro|Gestión en vFlow|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== En orquestador (Flowise) ===&lt;br /&gt;
* '''&amp;lt;big&amp;gt;1.- Crear agente&amp;lt;/big&amp;gt;''': Se crearán hasta '''tres agentes''' (pro/pre/pru) en función de los entornos deseados; es importante '''anotar los ID's de los agentes''' creados (se ven en la URL)&lt;br /&gt;
::[[Archivo:Captura de pantalla 2026-05-20 144432.png|800px|miniaturadeimagen|no|Creación de agente en orquestador flowise (uno por entorno)|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f0fff4; border: 3px solid #c6f6d5; padding: 1em; border-radius: 4px;width: fit-content; margin-left: 50px&amp;quot;&amp;gt;&lt;br /&gt;
✅ '''Puntos 2, 3 y 4 solo en caso de tener RAG'''&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''&amp;lt;big&amp;gt;2.- Crear store &amp;lt;/big&amp;gt;''': Se crearán hasta '''tres stores''' (pro/pre/pru) en función de los entornos deseados; es importante '''anotar los ID's de los stores''' creados (se ven en la URL)&lt;br /&gt;
::[[Archivo:Captura de pantalla 2026-05-20 135417.png|800px|miniaturadeimagen|no|Creación de store (uno por entorno)|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* '''&amp;lt;big&amp;gt;3.- Crear loader'''&amp;lt;/big&amp;gt; : Para cada loader que se desee manejar, se creará en el orquestador y en el document store, para los entornos deseados&lt;br /&gt;
::* Subir fichero (p.ej &amp;quot;ld1.txt&amp;quot; a &amp;lt;code&amp;gt;/var/www.html/storages/production&amp;lt;/code&amp;gt; (o a &amp;lt;code&amp;gt;/staging&amp;lt;/code&amp;gt; o a &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt; si procede)&lt;br /&gt;
::::[[Archivo:Captura de pantalla 2026-05-20 135757.png|700px|miniaturadeimagen|no|Subir fichero inicial (uno por entorno)|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
::* Crear loader&lt;br /&gt;
::::* Tipo: API loader&lt;br /&gt;
::::* Method: get&lt;br /&gt;
::::* URL : &amp;lt;cde&amp;gt;http://127.0.0.1/storages/production/nombrefich.txt&amp;lt;/code&amp;gt; (o  /staging /test) (formatos posibles txt, pdf, doc, docx)&lt;br /&gt;
::::* Splitter: Recursive character text splitter&lt;br /&gt;
::::* Comprobar con &amp;quot;preview chunks&amp;quot;&lt;br /&gt;
::::* Pulsar &amp;quot;process&amp;quot;&lt;br /&gt;
::::::[[Archivo:Captura de pantalla 2026-05-20 140146.png|700px|miniaturadeimagen|no|Creador loader en orquestador flowise|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
::::::[[Archivo:Captura de pantalla 2026-05-20 140326.png|700px|miniaturadeimagen|no|Loader creado en orquestador flowise|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* '''&amp;lt;big&amp;gt;4.- Sincronizar chunks&amp;lt;/big&amp;gt;''' en store ('''para cada entorno''')&lt;br /&gt;
::* En Store, more actions / Upsert All Chunks&lt;br /&gt;
::::[[Archivo:Captura de pantalla 2026-05-20 141118.png|700px|miniaturadeimagen|no|Upsert chunks store flowise|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
::::* Embeddings: Por ejemplo OpenAI embeddings (requiere &amp;quot;Credential&amp;quot;)&lt;br /&gt;
::::* Vector Store: Qdrant&lt;br /&gt;
::::::* Credential: cflow_qdrant&lt;br /&gt;
::::::* URL: http://localhost:6333&lt;br /&gt;
::::::* Qdrant Collection Name: vflow&lt;br /&gt;
::::* Record Manager: MySQL&lt;br /&gt;
::::::* Connect credential: mysql_upsert&lt;br /&gt;
::::::* Host: localhost&lt;br /&gt;
::::::* Database: vflow_flowise_upsert&lt;br /&gt;
::::::* Cleaun: Full&lt;br /&gt;
::::* Aplicar&lt;br /&gt;
::::::* Save config&lt;br /&gt;
::::::* Upsert&lt;br /&gt;
::::::[[Archivo:Captura de pantalla 2026-05-20 141626.png|700px|miniaturadeimagen|no|Sincronizado de store en flowise|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
La siguiente imagen muestra como quedará en el orquestador (flowise) un document store de vflow con entornos de producción, reproducción y pruebas&lt;br /&gt;
::[[Archivo:Captura de pantalla 2026-05-20 142148.png|700px|miniaturadeimagen|no|Document store en flowise con los tres entornos (tres document stores)|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== En flow ===&lt;br /&gt;
* 1.- '''&amp;lt;big&amp;gt; Crear un agente&amp;lt;/big&amp;gt;''': Vincularlo a los tres agentes de orquestador (pro/pre/pru) anotados anteriormente&lt;br /&gt;
::::[[Archivo:Captura de pantalla 2026-05-20 143843.png|800px|miniaturadeimagen|no|Crear agente en vflow|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f0fff4; border: 3px solid #c6f6d5; padding: 1em; border-radius: 4px;width: fit-content; margin-left: 50px&amp;quot;&amp;gt;&lt;br /&gt;
✅ '''Puntos 2 y 3 solo en caso de tener RAG'''&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* 2.- '''&amp;lt;big&amp;gt;Crear un store&amp;lt;/big&amp;gt;''': Vinculado a los stores de orquestador anotados anteriormente (pro/pre/pru)&lt;br /&gt;
::::[[Archivo:Captura de pantalla 2026-05-20 142920.png|800px|miniaturadeimagen|no|Creacion de Store en vflow|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* 3.- '''&amp;lt;big&amp;gt;Crear un loader&amp;lt;/big&amp;gt;'''&lt;br /&gt;
::* Loader vinculado a agente de vflow&lt;br /&gt;
::* El sistema comprobará que el fichero ya existe en el orquestador&lt;br /&gt;
:: Pulsar &amp;quot;crear&amp;quot;&lt;br /&gt;
::::[[Archivo:Captura de pantalla 2026-05-20 143126.png|700px|miniaturadeimagen|no|Crear loader en vflow|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
::::[[Archivo:Captura de pantalla 2026-05-20 143239.png|700px|miniaturadeimagen|no|Store, loader y detalle de loader|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Diagnósticos ==&lt;br /&gt;
Fichero de log, en nodo vFlowProxy, para cualquier canal&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
tail -f /var/log/vFlowProxy/vFlowProxy.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Monitorizar estado del proceso vflowProxy, en nodo vFlowProxy&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
nc localhost 1131&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;proceso&amp;quot;: {&lt;br /&gt;
    &amp;quot;nombre&amp;quot;: &amp;quot;vFlowProxy&amp;quot;,&lt;br /&gt;
    &amp;quot;version&amp;quot;: &amp;quot;00.00.01&amp;quot;,&lt;br /&gt;
    &amp;quot;inicio_ts&amp;quot;: 1771315153,&lt;br /&gt;
    &amp;quot;inicio_cad&amp;quot;: &amp;quot;20260217 085913&amp;quot;,&lt;br /&gt;
    &amp;quot;log_alarmas_val&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;log_alarma_ultimo_ts&amp;quot;: 1771970401,&lt;br /&gt;
    &amp;quot;log_alarma_ultimo_ts_cad&amp;quot;: &amp;quot;20260224 230001&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;diagnostico&amp;quot;: {&lt;br /&gt;
    &amp;quot;gmp&amp;quot;: {&lt;br /&gt;
      &amp;quot;msj_val&amp;quot;: 1022,&lt;br /&gt;
      &amp;quot;msj_max&amp;quot;: 1024,&lt;br /&gt;
      &amp;quot;buf_val&amp;quot;: 1024,&lt;br /&gt;
      &amp;quot;buf_max&amp;quot;: 1024,&lt;br /&gt;
      &amp;quot;tarea_val&amp;quot;: 7,&lt;br /&gt;
      &amp;quot;tarea_max&amp;quot;: 15&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;tiempo&amp;quot;: {&lt;br /&gt;
      &amp;quot;uptime&amp;quot;: 716665,&lt;br /&gt;
      &amp;quot;uptime_dias&amp;quot;: 8,&lt;br /&gt;
      &amp;quot;uptime_horas&amp;quot;: 7,&lt;br /&gt;
      &amp;quot;uptime_minutos&amp;quot;: 4,&lt;br /&gt;
      &amp;quot;uptime_segundos&amp;quot;: 25&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;wws&amp;quot;: {&lt;br /&gt;
      &amp;quot;conexiones_val&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;conexiones_max_periodo&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;hilos_val&amp;quot;: 4,&lt;br /&gt;
      &amp;quot;hilos_max&amp;quot;: 4,&lt;br /&gt;
      &amp;quot;wsi_cad&amp;quot;: &amp;quot;sesiones=0/200&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;alarmas_nivel_max&amp;quot;: 0,&lt;br /&gt;
  &amp;quot;alarmas&amp;quot;: []&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Es relevante la monitorización de sesiones  &amp;lt;code&amp;gt;&amp;quot;wsi_cad&amp;quot;: &amp;quot;sesiones=0/200&amp;quot;&amp;lt;/code&amp;gt; (usadas/máximas)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
En nodo Omnisuite, para canal voz&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
asterisk -rv | grep &amp;lt;callysquare_name&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
en nodo Omnisuite, para canal voz&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
tail -f /var/log/xcally/&amp;lt;agi-combined.yyyy-mm-dd.log&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
en nodo Omnisuite, para cualquier canal&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
tail -f /var/log/xcally/&amp;lt;routing-combined.yyyy-mm-dd.log&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Pruebas desde vFlow ==&lt;br /&gt;
&lt;br /&gt;
En /home/sat/vFlowProxy hay scripts de prueba (se configuran en el vars.sh); para usar los scripts de prueba tendremos que tener también &amp;quot;.ini&amp;quot; en vFlow&lt;br /&gt;
&lt;br /&gt;
Es útil comenzar con&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/home/sat/vFlowProxy/vFlowGetInfo.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
que sin parámetros adicionales confirma el correcto estado de vFlowProxy&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;errorNum&amp;quot;: 0,&lt;br /&gt;
  &amp;quot;errorStr&amp;quot;: &amp;quot;OK&amp;quot;,&lt;br /&gt;
  &amp;quot;app&amp;quot;: &amp;quot;vFlowProxy&amp;quot;,&lt;br /&gt;
  &amp;quot;version&amp;quot;: &amp;quot;00.00.01&amp;quot;,&lt;br /&gt;
  &amp;quot;sessions_opened&amp;quot;: 0,&lt;br /&gt;
  &amp;quot;sessions_limit&amp;quot;: 200,&lt;br /&gt;
  &amp;quot;sessions_sleep_timeout_s&amp;quot;: 3600,&lt;br /&gt;
  &amp;quot;alarms&amp;quot;: 8&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Integración de vFlow desde Omnisuite ==&lt;br /&gt;
=== Descripción general ===&lt;br /&gt;
En Omnisuite, la integración con vFlow, se realiza con el programa vFlowOmnisuite, que podrá ser invocado como ejecutable (más rápido, para debian), o como Python (más universal)&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; max-width: 500px; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite (OPCIÓN PREFERENTE)&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite.py (LEGACY)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Asociado al programa existen los siguientes ficheros de configuración (.ini):&lt;br /&gt;
&lt;br /&gt;
Un '''&amp;quot;.ini&amp;quot; de plataforma''' Omnisuite en vFlow --&amp;gt; Solo contiene uuid de la plataforma; se entrega un &amp;quot;.ini&amp;quot; a modo de ejemplo en &amp;lt;code&amp;gt;/etc/MDtel/vflow/platform.ini&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
EJEMPLO &amp;quot;.INI&amp;quot; DE PLATAFORMA&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
[uuids]&lt;br /&gt;
platform=1d111530-e22d-11f0-b0f2-5254008bef96&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un '''&amp;quot;.ini&amp;quot; por agente''' en vFlow --&amp;gt; Solo contiene uuid del agente según su identificación en vFlow ('''NO''' en un orquestador, por ejemplo flowise); se entrega un &amp;quot;.ini&amp;quot; asociado a un agente &amp;quot;loop&amp;quot; existente en Flowise &amp;lt;code&amp;gt;/etc/MDtel/vflow/agent_loop_01.ini&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
EJEMPLO &amp;quot;.INI&amp;quot; DE AGENTE&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
[uuids]&lt;br /&gt;
agent=1a3a1020-ea1d-11f0-b4a5-5254008bef96&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un '''&amp;quot;.ini&amp;quot; por servicio''' --&amp;gt; Configuración de cada servicio en Omnisuite; se entrega un &amp;quot;.ini&amp;quot; a modo de ejemplo en &amp;lt;code&amp;gt;/etc/MDtel/vflow/service.ini&amp;lt;/code&amp;gt;&lt;br /&gt;
En cada fichero de servicio configuraremos&lt;br /&gt;
::* Donde está Vflow&lt;br /&gt;
::* Agente&lt;br /&gt;
::* Plataforma&lt;br /&gt;
::* timeout_s --&amp;gt; Importante, es afectado por el LLM&lt;br /&gt;
::* channel_text_type --&amp;gt; IMPORTANTE si el servicio es de texto que esté bien (vacio solo si el servicio es de texto, NO COMENTARLO)&lt;br /&gt;
::* environment --&amp;gt; production, staging, test&lt;br /&gt;
EJEMPLO &amp;quot;.INI&amp;quot; DE SERVICIO&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
  [arch_uuids]&lt;br /&gt;
  agent=/etc/MDtel/vflow/agent_loop_01.ini&lt;br /&gt;
  platform=/etc/MDtel/vflow/platform.ini&lt;br /&gt;
&lt;br /&gt;
  [vflow]&lt;br /&gt;
  host_port=172.25.129.242:7900&lt;br /&gt;
  timeout_s=20&lt;br /&gt;
  # channel_type=[voice|chat|email]&lt;br /&gt;
  channel_type=chat&lt;br /&gt;
  # environment=[production|staging|test]&lt;br /&gt;
  environment=production&lt;br /&gt;
  language=es&lt;br /&gt;
&lt;br /&gt;
  [omnisuite]&lt;br /&gt;
  # channel_text_type=[chat|mail|sms|whatsup]&lt;br /&gt;
  channel_text_type=chat&lt;br /&gt;
  service_id=vflow_service_id&lt;br /&gt;
  service_name=vflow_service_name&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La imagen siguiente muestra el esquema de relación entre orquestador/plataforma/agente/servicio en la plataforma y en vFlow&lt;br /&gt;
&lt;br /&gt;
[[Archivo:Relaciones vFlow plat orq ag serv.png|800px|miniaturadeimagen|centro|Relación orquestador-plataforma-agente-servicio|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Invocación ===&lt;br /&gt;
==== Generales ====&lt;br /&gt;
&lt;br /&gt;
===== Ver configuración =====&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;lt;config_arch&amp;gt; configPrint&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ejemplo de respuesta&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
Configuration:&lt;br /&gt;
  agent_arch_uuid=/etc/MDtel/vflow/agent_fse_rapido.ini&lt;br /&gt;
  agent_uuid=3487af28-1d14-11f1-803c-525400ef204c&lt;br /&gt;
  platform_arch_uuid=/etc/MDtel/vflow/platform_labomsui.ini&lt;br /&gt;
  platform_uuid=9a54ea74-f050-11f0-bdf1-5254008bef96&lt;br /&gt;
&lt;br /&gt;
  vflow_host_port=labvflow.mdnova.local&lt;br /&gt;
  vflow_timeout_s=50&lt;br /&gt;
  vflow_environment=production&lt;br /&gt;
  vflow_channel_type=voice&lt;br /&gt;
  vflow_language=es&lt;br /&gt;
&lt;br /&gt;
  omnisuite_channel_text_type=chat&lt;br /&gt;
  omnisuite_service_id=287&lt;br /&gt;
  omnisuite_service_name=desarrollo&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;errorNum&amp;quot;: 0,&lt;br /&gt;
  &amp;quot;errorCad&amp;quot;: &amp;quot;OK&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Ver versión =====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite version&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ejemplo de respuesta&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
00.00.02&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Para canales de texto ====&lt;br /&gt;
&lt;br /&gt;
Para canales de texto en Omnisuite existe un único Comando de invocación &amp;quot;omnisuiteText&amp;quot;&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;lt;config_arch&amp;gt; omnisuiteText &amp;lt;omnisuite_id&amp;gt; &amp;lt;omnisuite_websiteId&amp;gt; &amp;lt;omnisuite_createdAt&amp;gt; &amp;lt;vflow_client_id&amp;gt; &amp;lt;vflow_client_phone_number&amp;gt; &amp;lt;vflow_client_email&amp;gt; &amp;lt;question&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parámetros ( Los OPCIONALES son &amp;quot;&amp;quot; si no se envía valor):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Obligatoriedad !! Descripción&lt;br /&gt;
|-&lt;br /&gt;
| `&amp;lt;config_arch&amp;gt;` || OBLIGATORIO || &amp;quot;.ini&amp;quot; del servicio&lt;br /&gt;
|-&lt;br /&gt;
| `&amp;lt;omnisuite_id&amp;gt;` || OBLIGATORIO || Identificativo de la interacción en Omnisuite&lt;br /&gt;
|-&lt;br /&gt;
| `&amp;lt;omnisuite_websiteId&amp;gt;` || OBLIGATORIO || Identificativo del servicio en Omnisuite (ej. website id en chat)&lt;br /&gt;
|-&lt;br /&gt;
| `&amp;lt;omnisuite_createdAt&amp;gt;` || OBLIGATORIO || Creación de la interacción&lt;br /&gt;
|-&lt;br /&gt;
| `&amp;lt;vflow_client_id&amp;gt;` || OPCIONAL || Id de cliente en Omnisuite&lt;br /&gt;
|-&lt;br /&gt;
| `&amp;lt;vflow_client_phone_number&amp;gt;` || OPCIONAL || Telf de cliente en Omnisuite&lt;br /&gt;
|-&lt;br /&gt;
| `&amp;lt;vflow_client_email&amp;gt;` || OPCIONAL || Email de cliente en Omnisuite&lt;br /&gt;
|-&lt;br /&gt;
| `&amp;lt;question&amp;gt;` || OBLIGATORIO || Texto a enviar al orquestado (p. ej. Flowise)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ejemplo de respuesta JSON&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; max-width: 400px; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
 &amp;quot;errorNum&amp;quot;: 0,&lt;br /&gt;
 &amp;quot;errorStr&amp;quot;: &amp;quot;OK&amp;quot;,&lt;br /&gt;
 &amp;quot;session&amp;quot;: &amp;quot;e926548d-fdcf-11f0-a793-525400ef204c&amp;quot;,&lt;br /&gt;
 &amp;quot;language&amp;quot;: &amp;quot;es&amp;quot;,&lt;br /&gt;
 &amp;quot;response&amp;quot;: &amp;quot;HOLA&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Para canales de voz ====&lt;br /&gt;
Para  canales de voz, existen comandos para &amp;quot;abrir sesión&amp;quot;, &amp;quot;enviar texto&amp;quot; y &amp;quot;cerrar sesión&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===== Abrir sesión =====&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;lt;config_arch&amp;gt; sessionOpen &amp;lt;omnisuite_UniqueId&amp;gt; &amp;lt;vflow_client_id&amp;gt; &amp;lt;vflow_client_phone_number&amp;gt; &amp;lt;vflow_client_email&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parámetros (Los OPCIONALES son &amp;quot;&amp;quot; si no se envía valor):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Requisito !! Descripción&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;config_arch&amp;gt;&amp;lt;/code&amp;gt; || OBLIGATORIO || &amp;quot;.ini&amp;quot; del servicio&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;omnisuite_UniqueId&amp;gt;&amp;lt;/code&amp;gt; || OBLIGATORIO || Unique_ID de asterisk de la llamada en Omnisuite&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;vflow_client_id&amp;gt;&amp;lt;/code&amp;gt; || OPCIONAL || Id de cliente en Omnisuite&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;vflow_client_phone_number&amp;gt;&amp;lt;/code&amp;gt; || OPCIONAL || Telf de cliente en Omnisuite&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;vflow_client_email&amp;gt;&amp;lt;/code&amp;gt; || OPCIONAL || Email de cliente en Omnisuite&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejemplo de respuesta JSON&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
 {&lt;br /&gt;
    &amp;quot;errorNum&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;errorStr&amp;quot;: &amp;quot;OK&amp;quot;,&lt;br /&gt;
    &amp;quot;session&amp;quot;: &amp;quot;ec73df29-f08a-11f0-a8ec-525400ef204c&amp;quot;,&lt;br /&gt;
    &amp;quot;platform_id&amp;quot;: &amp;quot;146&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''El value correspondiente al key &amp;quot;session&amp;quot; deberá ser guardado en una variable para siguientes invocaciones'''&lt;br /&gt;
&lt;br /&gt;
===== Enviar texto =====&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;lt;config_arch&amp;gt; textRequest &amp;lt;vflow_session_uuid&amp;gt; &amp;lt;question&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parámetros:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Requisito !! Descripción&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;config_arch&amp;gt;&amp;lt;/code&amp;gt; || OBLIGATORIO || &amp;quot;.ini&amp;quot; del servicio&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;vflow_session_uuid&amp;gt;&amp;lt;/code&amp;gt; || OBLIGATORIO || Variable &amp;quot;session&amp;quot; almacenada en el &amp;quot;sessionOpen&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;question&amp;gt;&amp;lt;/code&amp;gt; || OBLIGATORIO || Texto a enviar al orquestado (p. ej. Flowise) (normal, abandoned, other)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ejemplo de respuesta JSON&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
 {&lt;br /&gt;
    &amp;quot;errorNum&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;errorStr&amp;quot;: &amp;quot;OK&amp;quot;,&lt;br /&gt;
    &amp;quot;session&amp;quot;: &amp;quot;c6f6fad7-f6c1-11f0-a793-525400ef204c&amp;quot;,&lt;br /&gt;
    &amp;quot;language&amp;quot;: &amp;quot;ES&amp;quot;,&lt;br /&gt;
    &amp;quot;response&amp;quot;: &amp;quot;Cristóbal Colón.&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Cerrar sesión=====&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;lt;config_arch&amp;gt; sessionClose &amp;lt;vflow_session_uuid&amp;gt; &amp;lt;vflow_cause&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parámetros  (Los OPCIONALES son &amp;quot;&amp;quot; si no se envía valor):&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Estado !! Descripción&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;config_arch&amp;gt;&amp;lt;/code&amp;gt; || OBLIGATORIO || &amp;quot;.ini&amp;quot; del servicio&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;vflow_session_uuid&amp;gt;&amp;lt;/code&amp;gt; || OBLIGATORIO || Variable &amp;quot;session&amp;quot; almacenada en el &amp;quot;sessionOpen&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;vflow_cause&amp;gt;&amp;lt;/code&amp;gt; || OPCIONAL || (normal, abandoned, expired, other)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejemplo de respuesta JSON&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
 {&lt;br /&gt;
    &amp;quot;errorNum&amp;quot;: 104,&lt;br /&gt;
    &amp;quot;errorStr&amp;quot;: &amp;quot;Wrong session&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ejemplos para omnisuite ===&lt;br /&gt;
&lt;br /&gt;
==== Ejemplo de chat ====&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;quot;/etc/MDtel/vflow/service_chat.ini&amp;quot; &amp;quot;omnisuiteText&amp;quot; &amp;quot;{{interaction.id}}&amp;quot; &amp;quot;{{account.id}}&amp;quot; &amp;quot;{{interaction.createdAt}}&amp;quot; &amp;quot;&amp;quot; &amp;quot;&amp;quot; &amp;quot;&amp;quot; &amp;quot;{{message.body}}&amp;quot; | jq -r '.response'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Ejemplo de voz ====&lt;br /&gt;
&lt;br /&gt;
[[Archivo:Imagen cally square.jpg|1024px|none|miniatura|Ejemplo de flujo de Cally Square]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;quot;/etc/MDtel/vflow/service_voice.ini&amp;quot; &amp;quot;sessionOpen&amp;quot; &amp;quot;{UNIQUEID}&amp;quot; &amp;quot;&amp;quot; &amp;quot;&amp;quot; &amp;quot;&amp;quot; |  jq -r '.session' &amp;lt;/pre&amp;gt;&lt;br /&gt;
::&amp;lt;small&amp;gt;salida del comando almacenado en variable &amp;quot;vflow_sessionopen_response&amp;quot; para su posterior uso en cally square&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Archivo:Imagen sessionopen.jpg|550px|center|miniatura|Abrir sesión en vFlow]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;quot;/etc/MDtel/vflow/service_desa_voz.ini&amp;quot; &amp;quot;textRequest&amp;quot; &amp;quot;{vflow_sessionopen_response}&amp;quot; &amp;quot;{OPENAI_WHISPER_TRANSCRIPT}&amp;quot; | jq -r '.response'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
::&amp;lt;small&amp;gt;la voz se ha transcrito con OpenAI, por eso se usa como parámetro {OPENAI_WHISPER_TRANSCRIPT})&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Archivo:Imagen textrequest.jpg|550px|center|miniatura|Enviar texto en vFlow]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt; &lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;quot;/etc/MDtel/vflow/service_desa_voz.ini&amp;quot; &amp;quot;sessionClose&amp;quot; &amp;quot;{{vflow_sessionopen_response}}&amp;quot; &amp;quot;normal&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Archivo:Imagen sessionclose.jpg|900px|center|miniatura|Cerrar sesión en vFlow]]&lt;br /&gt;
&lt;br /&gt;
[[Category:tecnico]]&lt;br /&gt;
[[Category:VIVAit Call]]&lt;br /&gt;
[[Category:Omnisuite]]&lt;br /&gt;
[[Category:IA]]&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Manual_de_operaci%C3%B3n_de_vFlow&amp;diff=19160</id>
		<title>Manual de operación de vFlow</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Manual_de_operaci%C3%B3n_de_vFlow&amp;diff=19160"/>
		<updated>2026-07-07T10:09:38Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* Gestión en vFlow */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Descripción general vFlow ==&lt;br /&gt;
&lt;br /&gt;
vFlow es un módulo de conexión a sistemas de inteligencia artifical para sistemas de comunicaciones unificadas, ya sean sistemas corporativos o contact center&lt;br /&gt;
Gracias a vFlow, las plataformas de UC dispondrán de una solución para comunicarse con sistemas IA utilizando un mismo mecanismo independientemente de la solución de inteligencia artificial que se utilice&lt;br /&gt;
&lt;br /&gt;
Para proporcionar el servicio de manera completa, vFlow (en concreto el orquestador) se conectará a sistemas de inteligencia artificial (LLM) que permitirán desarrollar los agentes definidos en los orquestadores&lt;br /&gt;
&lt;br /&gt;
'''Conceptos:'''&lt;br /&gt;
* Plataforma&amp;lt;span style=&amp;quot;margin-left: 3em;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;--&amp;gt; Plataforma de comunicaciones unificadas; por ejemplo Omnisuite o VIVAit Call&lt;br /&gt;
* Orquestador&amp;lt;span style=&amp;quot;margin-left: 3em;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;--&amp;gt; Plataforma agéntica de IA (por ejemplo Flowise)&lt;br /&gt;
* vFlowProxy&amp;lt;span style=&amp;quot;margin-left: 3em;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;--&amp;gt; Módulo VIVAit que conecta multiples plataformas con múltiples orquestadores&lt;br /&gt;
* LLM&amp;lt;span style=&amp;quot;margin-left: 3em;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;--&amp;gt; Modelo de lenguaje natural que usará un orquestadores&lt;br /&gt;
* Agente&amp;lt;span style=&amp;quot;margin-left: 3em;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;--&amp;gt; Cada uno de los flujos creados en vFlow; corresponde a un par plataforma/agentflow de orquestador&lt;br /&gt;
* Servicio&amp;lt;span style=&amp;quot;margin-left: 3em;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;--&amp;gt; Cada elemento de negocio en la plataforma de CU (por ejemplo VDN)&lt;br /&gt;
&lt;br /&gt;
[[Archivo:Arquitectura Vflow - v2.jpg|1400px|center|Arquitecura de vFlow]]&lt;br /&gt;
&lt;br /&gt;
Los '''módulos principales''' de vFlow son:&lt;br /&gt;
* vFlowProxy: Recibe las conexiones de los sistemas de comunicaciones unificadas, y conecta con los orquestadores de Inteligencia Artificial de manera segura y adaptada al tipo de servicio; el acceso a vFlow Proxy desde las plataformas se realizará mediante:&lt;br /&gt;
* Programa cliente: Se utiliza en el sistema de comunicaciones unificadas (actualmente VIVAit Call y Omnsisuite) para invocar a vFlow&lt;br /&gt;
* API REST: Alternativa al programa cliente, vFlowProxy proporciona una API REST que facilita que cualquier plataforma pueda comunicarse mediante un procedimiento estándar y documentado&lt;br /&gt;
* Portal de administración vFlow: Permite visualizar las interaciones realizadas y configurar el sistema&lt;br /&gt;
* Orquestador de IA: Herramienta de Inteligencia Artificial que permitirá la creación de aplicaciones personalizadas (agentes)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
'''Otros elementos''' relevantes serán:&lt;br /&gt;
* Base de datos vFlow:&lt;br /&gt;
:* Almacena información sobre sesiones y transacciones realizadas&lt;br /&gt;
:* Almacena información de configuración sobre vFlow&lt;br /&gt;
:* Gestiona el RAG de las inteligencias artificiales a usar&lt;br /&gt;
&lt;br /&gt;
== Puesta en marcha de nodo vFlow ==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Existe un nodo vFlow en los repositorios habituales proporcionados&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para '''dar de alta nodo vflow en un cliente''' hay que:&lt;br /&gt;
* Configurar IP (por defecto la maquina va configurada por DHCP)&lt;br /&gt;
* Adaptar el firewall, para ello REVISAR el fichero &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
* Certificados validos en apache&lt;br /&gt;
* REVISAR ficheros &amp;lt;code&amp;gt;/etc/apache2/sites-enabled/flowise.conf&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;/etc/apache2/sites-enabled/vFlow.conf&amp;lt;/code&amp;gt; la variable &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt; (nombre valido de la maquina)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Accesos vFlow''' (se debe cambiar tras instalación):&lt;br /&gt;
* Usuario ssh y de SO por defecto es sat y clave a proporcionar.&lt;br /&gt;
* Para el portal de flowise las credenciales son usuario: vfloadmin@vflow.com clave: A proporcionar&lt;br /&gt;
* Para el portal de vflow las credenciales son usaurio sat y clave a proporcionar.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Accesos BBDD vFlow'''&lt;br /&gt;
* Para acceder a la base de datos desde el workbenck solo desde localhost (o tunel):&lt;br /&gt;
* BBDD Vlfow (admin)  vflowadmin // clave a proporcionar&lt;br /&gt;
* BBDD Vlfow (no_admin)  vflow //  clave a proporcionar&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Portal orquestador Flowise'''&lt;br /&gt;
&lt;br /&gt;
ubicado en https://host.cliente.xx:4567&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #fef6e7; border: 1px solid #fbd68a; padding: 1em; border-radius: 4px;width: fit-content; margin-left: 50px&amp;quot;&amp;gt;&lt;br /&gt;
'''⚠️ ATENCION !!'''&lt;br /&gt;
'''Los cambios en tablas de configuración de BBDD de vFlow (orquestadores, plataformas, agentes) requieren reinicio del servicio vFlowProxy'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', 'Monaco', 'Courier New', monospace;&amp;quot;&amp;gt;&lt;br /&gt;
/etc/init.d/vFlowProxy.service status&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
/etc/init.d/vFlowProxy.service stop&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
/etc/init.d/vFlowProxy.service start&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
El fichero de configuración del demonio &amp;lt;code&amp;gt;vFlowProxy&amp;lt;/code&amp;gt; se encuentra en &amp;lt;code&amp;gt;/etc/MDtel/vFlowProxy.conf&amp;lt;/code&amp;gt;, si bien este fichero de configuración no se modificará habitualmente (los parámetros generales de configuración de vFlowProxy se encuentran en la BBDD de vFlow)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Procedimientos de respaldo y restauración ==&lt;br /&gt;
&lt;br /&gt;
=== Respaldo ===&lt;br /&gt;
&lt;br /&gt;
* Hacer backup de las bases de datosdel orquestador (flowise) y de vFlow&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', 'Monaco', 'Courier New', monospace;&amp;quot;&amp;gt;&lt;br /&gt;
mariadb-dump -u root -p --single-transaction --routines --events --triggers --default-character-set=utf8mb4 vflow_flowise_config &amp;gt; vflow_flowise_config_$(date +%F_%H%M%S).sql&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
mariadb-dump -u root -p --single-transaction --routines --events --triggers --default-character-set=utf8mb4 vflow_flowise_config &amp;gt; vflow_flowise_upsert_$(date +%F_%H%M%S).sql&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
mariadb-dump -u root -p --single-transaction --routines --events --triggers --default-character-set=utf8mb4 vFlow &amp;gt; vFlow_$(date +%F_%H%M%S).sql&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* Copiar:&lt;br /&gt;
** El directorio /opt/vFlow_flowise/.flowise&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', 'Monaco', 'Courier New', monospace;&amp;quot;&amp;gt;&lt;br /&gt;
cp -vai  /opt/vFlow_flowise/.flowise  /opt/vFlow_flowise/.flowise_$(date +%F_%H%M%S)&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
** El directorio /opt/vFlow_flowise/archivos&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', 'Monaco', 'Courier New', monospace;&amp;quot;&amp;gt;&lt;br /&gt;
cp -vai  /opt/vFlow_flowise/archivos /opt/vFlow_flowise/archivos_$(date +%F_%H%M%S)&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
'''Todos los ficheros creados pueden ser movidos al destino deseado para almacenar la copia de respaldo'''&lt;br /&gt;
&lt;br /&gt;
=== Restauración ===&lt;br /&gt;
Para restaurar, será necesario&lt;br /&gt;
* Importar de nuevo las dos bases de datos de flowise y la base de datos de vFlow:&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', 'Monaco', 'Courier New', monospace;&amp;quot;&amp;gt;&lt;br /&gt;
mysql -u root -p vflow_flowise_config &amp;lt;  vflow_flowise_config_ULTIMAFECHA.sql&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
mysql -u root -p vflow_flowise_upsert &amp;lt;  vflow_flowise_upsert_ULTIMAFECHA.sql&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
mysql -u root -p vFlow &amp;lt;  vFlow_ULTIMAFECHA.sql&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* Volver a poner las carpetas de /opt/vFlow_flowise/&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', 'Monaco', 'Courier New', monospace;&amp;quot;&amp;gt;&lt;br /&gt;
mv -vi  /opt/vFlow_flowise/.flowise_ULTIMAFECHA  /opt/vFlow_flowise/.flowise&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
mv -vi /opt/vFlow_flowise/archivos_ULTIMAFECHA  /opt/vFlow_flowise/archivos&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
'''Las ubicaciones de los archivos a resturar pueden ser diferentes'''&lt;br /&gt;
&lt;br /&gt;
== Gestión en vFlow ==&lt;br /&gt;
vFlow prevé la existencia de tres entornos que permita hacer una gestión segura de agentes y RAG:&lt;br /&gt;
&lt;br /&gt;
* Producción&lt;br /&gt;
* Preproducción&lt;br /&gt;
* Pruebas&lt;br /&gt;
&lt;br /&gt;
Para cada agente o store de RAG se podrá desplegar un entorno, dos o los tres entornos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f0fff4; border: 3px solid #c6f6d5; padding: 1em; border-radius: 4px;width: fit-content; margin-left: 0px&amp;quot;&amp;gt;&lt;br /&gt;
✅ '''Recomendación'''&amp;lt;br&amp;gt;&lt;br /&gt;
::En la mayoría de los casos con disponer de entorno de producción y preproducción tanto para agente como para RAG será suficiente&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Para realizar una gestión completa en vFlow (suponiendo tres entornos y gestión de agentes y RAG), deberemos tener&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Archivo:Gestión RAG.png|1300px|miniaturadeimagen|centro|Gestión en vFlow|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== En orquestador (Flowise) ===&lt;br /&gt;
* '''&amp;lt;big&amp;gt;1.- Crear agente&amp;lt;/big&amp;gt;''': Se crearán hasta '''tres agentes''' (pro/pre/pru) en función de los entornos deseados; es importante '''anotar los ID's de los agentes''' creados (se ven en la URL)&lt;br /&gt;
::[[Archivo:Captura de pantalla 2026-05-20 144432.png|800px|miniaturadeimagen|no|Creación de agente en orquestador flowise (uno por entorno)|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f0fff4; border: 3px solid #c6f6d5; padding: 1em; border-radius: 4px;width: fit-content; margin-left: 50px&amp;quot;&amp;gt;&lt;br /&gt;
✅ '''Puntos 2, 3 y 4 solo en caso de tener RAG'''&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''&amp;lt;big&amp;gt;2.- Crear store &amp;lt;/big&amp;gt;''': Se crearán hasta '''tres stores''' (pro/pre/pru) en función de los entornos deseados; es importante '''anotar los ID's de los stores''' creados (se ven en la URL)&lt;br /&gt;
::[[Archivo:Captura de pantalla 2026-05-20 135417.png|800px|miniaturadeimagen|no|Creación de store (uno por entorno)|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* '''&amp;lt;big&amp;gt;3.- Crear loader'''&amp;lt;/big&amp;gt; : Para cada loader que se desee manejar, se creará en el orquestador y en el document store, para los entornos deseados&lt;br /&gt;
::* Subir fichero (p.ej &amp;quot;ld1.txt&amp;quot; a &amp;lt;code&amp;gt;/var/www.html/storages/production&amp;lt;/code&amp;gt; (o a &amp;lt;code&amp;gt;/staging&amp;lt;/code&amp;gt; o a &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt; si procede)&lt;br /&gt;
::::[[Archivo:Captura de pantalla 2026-05-20 135757.png|700px|miniaturadeimagen|no|Subir fichero inicial (uno por entorno)|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
::* Crear loader&lt;br /&gt;
::::* Tipo: API loader&lt;br /&gt;
::::* Method: get&lt;br /&gt;
::::* URL : &amp;lt;cde&amp;gt;http://127.0.0.1/storages/production/nombrefich.txt&amp;lt;/code&amp;gt; (o  /staging /test) (formatos posibles txt, pdf, doc, docx)&lt;br /&gt;
::::* Splitter: Recursive character text splitter&lt;br /&gt;
::::* Comprobar con &amp;quot;preview chunks&amp;quot;&lt;br /&gt;
::::* Pulsar &amp;quot;process&amp;quot;&lt;br /&gt;
::::::[[Archivo:Captura de pantalla 2026-05-20 140146.png|700px|miniaturadeimagen|no|Creador loader en orquestador flowise|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
::::::[[Archivo:Captura de pantalla 2026-05-20 140326.png|700px|miniaturadeimagen|no|Loader creado en orquestador flowise|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* '''&amp;lt;big&amp;gt;4.- Sincronizar chunks&amp;lt;/big&amp;gt;''' en store ('''para cada entorno''')&lt;br /&gt;
::* En Store, more actions / Upsert All Chunks&lt;br /&gt;
::::[[Archivo:Captura de pantalla 2026-05-20 141118.png|700px|miniaturadeimagen|no|Upsert chunks store flowise|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
::::* Embeddings: Por ejemplo OpenAI embeddings (requiere &amp;quot;Credential&amp;quot;)&lt;br /&gt;
::::* Vector Store: Qdrant&lt;br /&gt;
::::::* Credential: cflow_qdrant&lt;br /&gt;
::::::* URL: http://localhost:6333&lt;br /&gt;
::::::* Qdrant Collection Name: vflow&lt;br /&gt;
::::* Record Manager: MySQL&lt;br /&gt;
::::::* Connect credential: mysql_upsert&lt;br /&gt;
::::::* Host: localhost&lt;br /&gt;
::::::* Database: vflow_flowise_upsert&lt;br /&gt;
::::::* Cleaun: Full&lt;br /&gt;
::::* Aplicar&lt;br /&gt;
::::::* Save config&lt;br /&gt;
::::::* Upsert&lt;br /&gt;
::::::[[Archivo:Captura de pantalla 2026-05-20 141626.png|700px|miniaturadeimagen|no|Sincronizado de store en flowise|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
La siguiente imagen muestra como quedará en el orquestador (flowise) un document store de vflow con entornos de producción, reproducción y pruebas&lt;br /&gt;
::[[Archivo:Captura de pantalla 2026-05-20 142148.png|700px|miniaturadeimagen|no|Document store en flowise con los tres entornos (tres document stores)|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== En flow ===&lt;br /&gt;
* 1.- '''&amp;lt;big&amp;gt; Crear un agente&amp;lt;/big&amp;gt;''': Vincularlo a los tres agentes de orquestador (pro/pre/pru) anotados anteriormente&lt;br /&gt;
::::[[Archivo:Captura de pantalla 2026-05-20 143843.png|800px|miniaturadeimagen|no|Crear agente en vflow|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f0fff4; border: 3px solid #c6f6d5; padding: 1em; border-radius: 4px;width: fit-content; margin-left: 50px&amp;quot;&amp;gt;&lt;br /&gt;
✅ '''Puntos 2 y 3 solo en caso de tener RAG'''&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* 2.- '''&amp;lt;big&amp;gt;Crear un store&amp;lt;/big&amp;gt;''': Vinculado a los stores de orquestador anotados anteriormente (pro/pre/pru)&lt;br /&gt;
::::[[Archivo:Captura de pantalla 2026-05-20 142920.png|800px|miniaturadeimagen|no|Creacion de Store en vflow|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* 3.- '''&amp;lt;big&amp;gt;Crear un loader&amp;lt;/big&amp;gt;'''&lt;br /&gt;
::* Loader vinculado a agente de vflow&lt;br /&gt;
::* El sistema comprobará que el fichero ya existe en el orquestador&lt;br /&gt;
:: Pulsar &amp;quot;crear&amp;quot;&lt;br /&gt;
::::[[Archivo:Captura de pantalla 2026-05-20 143126.png|700px|miniaturadeimagen|no|Crear loader en vflow|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
::::[[Archivo:Captura de pantalla 2026-05-20 143239.png|700px|miniaturadeimagen|no|Store, loader y detalle de loader|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Diagnósticos ==&lt;br /&gt;
Fichero de log, en nodo vFlowProxy, para cualquier canal&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
tail -f /var/log/vFlowProxy/vFlowProxy.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Monitorizar estado del proceso vflowProxy, en nodo vFlowProxy&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
nc localhost 1131&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;proceso&amp;quot;: {&lt;br /&gt;
    &amp;quot;nombre&amp;quot;: &amp;quot;vFlowProxy&amp;quot;,&lt;br /&gt;
    &amp;quot;version&amp;quot;: &amp;quot;00.00.01&amp;quot;,&lt;br /&gt;
    &amp;quot;inicio_ts&amp;quot;: 1771315153,&lt;br /&gt;
    &amp;quot;inicio_cad&amp;quot;: &amp;quot;20260217 085913&amp;quot;,&lt;br /&gt;
    &amp;quot;log_alarmas_val&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;log_alarma_ultimo_ts&amp;quot;: 1771970401,&lt;br /&gt;
    &amp;quot;log_alarma_ultimo_ts_cad&amp;quot;: &amp;quot;20260224 230001&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;diagnostico&amp;quot;: {&lt;br /&gt;
    &amp;quot;gmp&amp;quot;: {&lt;br /&gt;
      &amp;quot;msj_val&amp;quot;: 1022,&lt;br /&gt;
      &amp;quot;msj_max&amp;quot;: 1024,&lt;br /&gt;
      &amp;quot;buf_val&amp;quot;: 1024,&lt;br /&gt;
      &amp;quot;buf_max&amp;quot;: 1024,&lt;br /&gt;
      &amp;quot;tarea_val&amp;quot;: 7,&lt;br /&gt;
      &amp;quot;tarea_max&amp;quot;: 15&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;tiempo&amp;quot;: {&lt;br /&gt;
      &amp;quot;uptime&amp;quot;: 716665,&lt;br /&gt;
      &amp;quot;uptime_dias&amp;quot;: 8,&lt;br /&gt;
      &amp;quot;uptime_horas&amp;quot;: 7,&lt;br /&gt;
      &amp;quot;uptime_minutos&amp;quot;: 4,&lt;br /&gt;
      &amp;quot;uptime_segundos&amp;quot;: 25&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;wws&amp;quot;: {&lt;br /&gt;
      &amp;quot;conexiones_val&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;conexiones_max_periodo&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;hilos_val&amp;quot;: 4,&lt;br /&gt;
      &amp;quot;hilos_max&amp;quot;: 4,&lt;br /&gt;
      &amp;quot;wsi_cad&amp;quot;: &amp;quot;sesiones=0/200&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;alarmas_nivel_max&amp;quot;: 0,&lt;br /&gt;
  &amp;quot;alarmas&amp;quot;: []&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Es relevante la monitorización de sesiones  &amp;lt;code&amp;gt;&amp;quot;wsi_cad&amp;quot;: &amp;quot;sesiones=0/200&amp;quot;&amp;lt;/code&amp;gt; (usadas/máximas)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
En nodo Omnisuite, para canal voz&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
asterisk -rv | grep &amp;lt;callysquare_name&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
en nodo Omnisuite, para canal voz&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
tail -f /var/log/xcally/&amp;lt;agi-combined.yyyy-mm-dd.log&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
en nodo Omnisuite, para cualquier canal&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
tail -f /var/log/xcally/&amp;lt;routing-combined.yyyy-mm-dd.log&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Pruebas desde vFlow ==&lt;br /&gt;
&lt;br /&gt;
En /home/sat/vFlowProxy hay scripts de prueba (se configuran en el vars.sh); para usar los scripts de prueba tendremos que tener también &amp;quot;.ini&amp;quot; en vFlow&lt;br /&gt;
&lt;br /&gt;
Es útil comenzar con&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/home/sat/vFlowProxy/vFlowGetInfo.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
que sin parámetros adicionales confirma el correcto estado de vFlowProxy&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;errorNum&amp;quot;: 0,&lt;br /&gt;
  &amp;quot;errorStr&amp;quot;: &amp;quot;OK&amp;quot;,&lt;br /&gt;
  &amp;quot;app&amp;quot;: &amp;quot;vFlowProxy&amp;quot;,&lt;br /&gt;
  &amp;quot;version&amp;quot;: &amp;quot;00.00.01&amp;quot;,&lt;br /&gt;
  &amp;quot;sessions_opened&amp;quot;: 0,&lt;br /&gt;
  &amp;quot;sessions_limit&amp;quot;: 200,&lt;br /&gt;
  &amp;quot;sessions_sleep_timeout_s&amp;quot;: 3600,&lt;br /&gt;
  &amp;quot;alarms&amp;quot;: 8&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Integración de vFlow desde Omnisuite ==&lt;br /&gt;
=== Descripción general ===&lt;br /&gt;
En Omnisuite, la integración con vFlow, se realiza con el programa vFlowOmnisuite, que podrá ser invocado como ejecutable (más rápido, para debian), o como Python (más universal)&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; max-width: 500px; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite (OPCIÓN PREFERENTE)&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite.py (LEGACY)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Asociado al programa existen los siguientes ficheros de configuración (.ini):&lt;br /&gt;
&lt;br /&gt;
Un '''&amp;quot;.ini&amp;quot; de plataforma''' Omnisuite en vFlow --&amp;gt; Solo contiene uuid de la plataforma; se entrega un &amp;quot;.ini&amp;quot; a modo de ejemplo en &amp;lt;code&amp;gt;/etc/MDtel/vflow/platform.ini&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
EJEMPLO &amp;quot;.INI&amp;quot; DE PLATAFORMA&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
[uuids]&lt;br /&gt;
platform=1d111530-e22d-11f0-b0f2-5254008bef96&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un '''&amp;quot;.ini&amp;quot; por agente''' en vFlow --&amp;gt; Solo contiene uuid del agente según su identificación en vFlow ('''NO''' en un orquestador, por ejemplo flowise); se entrega un &amp;quot;.ini&amp;quot; asociado a un agente &amp;quot;loop&amp;quot; existente en Flowise &amp;lt;code&amp;gt;/etc/MDtel/vflow/agent_loop_01.ini&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
EJEMPLO &amp;quot;.INI&amp;quot; DE AGENTE&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
[uuids]&lt;br /&gt;
agent=1a3a1020-ea1d-11f0-b4a5-5254008bef96&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un '''&amp;quot;.ini&amp;quot; por servicio''' --&amp;gt; Configuración de cada servicio en Omnisuite; se entrega un &amp;quot;.ini&amp;quot; a modo de ejemplo en &amp;lt;code&amp;gt;/etc/MDtel/vflow/service.ini&amp;lt;/code&amp;gt;&lt;br /&gt;
En cada fichero de servicio configuraremos&lt;br /&gt;
::* Donde está Vflow&lt;br /&gt;
::* Agente&lt;br /&gt;
::* Plataforma&lt;br /&gt;
::* timeout_s --&amp;gt; Importante, es afectado por el LLM&lt;br /&gt;
::* channel_text_type --&amp;gt; IMPORTANTE si el servicio es de texto que esté bien (vacio solo si el servicio es de texto, NO COMENTARLO)&lt;br /&gt;
::* environment --&amp;gt; production, staging, test&lt;br /&gt;
EJEMPLO &amp;quot;.INI&amp;quot; DE SERVICIO&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
  [arch_uuids]&lt;br /&gt;
  agent=/etc/MDtel/vflow/agent_loop_01.ini&lt;br /&gt;
  platform=/etc/MDtel/vflow/platform.ini&lt;br /&gt;
&lt;br /&gt;
  [vflow]&lt;br /&gt;
  host_port=172.25.129.242:7900&lt;br /&gt;
  timeout_s=20&lt;br /&gt;
  # channel_type=[voice|chat|email]&lt;br /&gt;
  channel_type=chat&lt;br /&gt;
  # environment=[production|staging|test]&lt;br /&gt;
  environment=production&lt;br /&gt;
  language=es&lt;br /&gt;
&lt;br /&gt;
  [omnisuite]&lt;br /&gt;
  # channel_text_type=[chat|mail|sms|whatsup]&lt;br /&gt;
  channel_text_type=chat&lt;br /&gt;
  service_id=vflow_service_id&lt;br /&gt;
  service_name=vflow_service_name&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La imagen siguiente muestra el esquema de relación entre orquestador/plataforma/agente/servicio en la plataforma y en vFlow&lt;br /&gt;
&lt;br /&gt;
[[Archivo:Relaciones vFlow plat orq ag serv.png|800px|miniaturadeimagen|centro|Relación orquestador-plataforma-agente-servicio|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Invocación ===&lt;br /&gt;
==== Generales ====&lt;br /&gt;
&lt;br /&gt;
===== Ver configuración =====&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;lt;config_arch&amp;gt; configPrint&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ejemplo de respuesta&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
Configuration:&lt;br /&gt;
  agent_arch_uuid=/etc/MDtel/vflow/agent_fse_rapido.ini&lt;br /&gt;
  agent_uuid=3487af28-1d14-11f1-803c-525400ef204c&lt;br /&gt;
  platform_arch_uuid=/etc/MDtel/vflow/platform_labomsui.ini&lt;br /&gt;
  platform_uuid=9a54ea74-f050-11f0-bdf1-5254008bef96&lt;br /&gt;
&lt;br /&gt;
  vflow_host_port=labvflow.mdnova.local&lt;br /&gt;
  vflow_timeout_s=50&lt;br /&gt;
  vflow_environment=production&lt;br /&gt;
  vflow_channel_type=voice&lt;br /&gt;
  vflow_language=es&lt;br /&gt;
&lt;br /&gt;
  omnisuite_channel_text_type=chat&lt;br /&gt;
  omnisuite_service_id=287&lt;br /&gt;
  omnisuite_service_name=desarrollo&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;errorNum&amp;quot;: 0,&lt;br /&gt;
  &amp;quot;errorCad&amp;quot;: &amp;quot;OK&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Ver versión =====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite version&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ejemplo de respuesta&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
00.00.02&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Para canales de texto ====&lt;br /&gt;
&lt;br /&gt;
Para canales de texto en Omnisuite existe un único Comando de invocación &amp;quot;omnisuiteText&amp;quot;&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;lt;config_arch&amp;gt; omnisuiteText &amp;lt;omnisuite_id&amp;gt; &amp;lt;omnisuite_websiteId&amp;gt; &amp;lt;omnisuite_createdAt&amp;gt; &amp;lt;vflow_client_id&amp;gt; &amp;lt;vflow_client_phone_number&amp;gt; &amp;lt;vflow_client_email&amp;gt; &amp;lt;question&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parámetros ( Los OPCIONALES son &amp;quot;&amp;quot; si no se envía valor):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Obligatoriedad !! Descripción&lt;br /&gt;
|-&lt;br /&gt;
| `&amp;lt;config_arch&amp;gt;` || OBLIGATORIO || &amp;quot;.ini&amp;quot; del servicio&lt;br /&gt;
|-&lt;br /&gt;
| `&amp;lt;omnisuite_id&amp;gt;` || OBLIGATORIO || Identificativo de la interacción en Omnisuite&lt;br /&gt;
|-&lt;br /&gt;
| `&amp;lt;omnisuite_websiteId&amp;gt;` || OBLIGATORIO || Identificativo del servicio en Omnisuite (ej. website id en chat)&lt;br /&gt;
|-&lt;br /&gt;
| `&amp;lt;omnisuite_createdAt&amp;gt;` || OBLIGATORIO || Creación de la interacción&lt;br /&gt;
|-&lt;br /&gt;
| `&amp;lt;vflow_client_id&amp;gt;` || OPCIONAL || Id de cliente en Omnisuite&lt;br /&gt;
|-&lt;br /&gt;
| `&amp;lt;vflow_client_phone_number&amp;gt;` || OPCIONAL || Telf de cliente en Omnisuite&lt;br /&gt;
|-&lt;br /&gt;
| `&amp;lt;vflow_client_email&amp;gt;` || OPCIONAL || Email de cliente en Omnisuite&lt;br /&gt;
|-&lt;br /&gt;
| `&amp;lt;question&amp;gt;` || OBLIGATORIO || Texto a enviar al orquestado (p. ej. Flowise)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ejemplo de respuesta JSON&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; max-width: 400px; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
 &amp;quot;errorNum&amp;quot;: 0,&lt;br /&gt;
 &amp;quot;errorStr&amp;quot;: &amp;quot;OK&amp;quot;,&lt;br /&gt;
 &amp;quot;session&amp;quot;: &amp;quot;e926548d-fdcf-11f0-a793-525400ef204c&amp;quot;,&lt;br /&gt;
 &amp;quot;language&amp;quot;: &amp;quot;es&amp;quot;,&lt;br /&gt;
 &amp;quot;response&amp;quot;: &amp;quot;HOLA&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Para canales de voz ====&lt;br /&gt;
Para  canales de voz, existen comandos para &amp;quot;abrir sesión&amp;quot;, &amp;quot;enviar texto&amp;quot; y &amp;quot;cerrar sesión&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===== Abrir sesión =====&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;lt;config_arch&amp;gt; sessionOpen &amp;lt;omnisuite_UniqueId&amp;gt; &amp;lt;vflow_client_id&amp;gt; &amp;lt;vflow_client_phone_number&amp;gt; &amp;lt;vflow_client_email&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parámetros (Los OPCIONALES son &amp;quot;&amp;quot; si no se envía valor):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Requisito !! Descripción&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;config_arch&amp;gt;&amp;lt;/code&amp;gt; || OBLIGATORIO || &amp;quot;.ini&amp;quot; del servicio&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;omnisuite_UniqueId&amp;gt;&amp;lt;/code&amp;gt; || OBLIGATORIO || Unique_ID de asterisk de la llamada en Omnisuite&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;vflow_client_id&amp;gt;&amp;lt;/code&amp;gt; || OPCIONAL || Id de cliente en Omnisuite&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;vflow_client_phone_number&amp;gt;&amp;lt;/code&amp;gt; || OPCIONAL || Telf de cliente en Omnisuite&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;vflow_client_email&amp;gt;&amp;lt;/code&amp;gt; || OPCIONAL || Email de cliente en Omnisuite&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejemplo de respuesta JSON&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
 {&lt;br /&gt;
    &amp;quot;errorNum&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;errorStr&amp;quot;: &amp;quot;OK&amp;quot;,&lt;br /&gt;
    &amp;quot;session&amp;quot;: &amp;quot;ec73df29-f08a-11f0-a8ec-525400ef204c&amp;quot;,&lt;br /&gt;
    &amp;quot;platform_id&amp;quot;: &amp;quot;146&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''El value correspondiente al key &amp;quot;session&amp;quot; deberá ser guardado en una variable para siguientes invocaciones'''&lt;br /&gt;
&lt;br /&gt;
===== Enviar texto =====&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;lt;config_arch&amp;gt; textRequest &amp;lt;vflow_session_uuid&amp;gt; &amp;lt;question&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parámetros:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Requisito !! Descripción&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;config_arch&amp;gt;&amp;lt;/code&amp;gt; || OBLIGATORIO || &amp;quot;.ini&amp;quot; del servicio&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;vflow_session_uuid&amp;gt;&amp;lt;/code&amp;gt; || OBLIGATORIO || Variable &amp;quot;session&amp;quot; almacenada en el &amp;quot;sessionOpen&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;question&amp;gt;&amp;lt;/code&amp;gt; || OBLIGATORIO || Texto a enviar al orquestado (p. ej. Flowise) (normal, abandoned, other)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ejemplo de respuesta JSON&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
 {&lt;br /&gt;
    &amp;quot;errorNum&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;errorStr&amp;quot;: &amp;quot;OK&amp;quot;,&lt;br /&gt;
    &amp;quot;session&amp;quot;: &amp;quot;c6f6fad7-f6c1-11f0-a793-525400ef204c&amp;quot;,&lt;br /&gt;
    &amp;quot;language&amp;quot;: &amp;quot;ES&amp;quot;,&lt;br /&gt;
    &amp;quot;response&amp;quot;: &amp;quot;Cristóbal Colón.&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Cerrar sesión=====&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;lt;config_arch&amp;gt; sessionClose &amp;lt;vflow_session_uuid&amp;gt; &amp;lt;vflow_cause&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parámetros  (Los OPCIONALES son &amp;quot;&amp;quot; si no se envía valor):&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Estado !! Descripción&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;config_arch&amp;gt;&amp;lt;/code&amp;gt; || OBLIGATORIO || &amp;quot;.ini&amp;quot; del servicio&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;vflow_session_uuid&amp;gt;&amp;lt;/code&amp;gt; || OBLIGATORIO || Variable &amp;quot;session&amp;quot; almacenada en el &amp;quot;sessionOpen&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;vflow_cause&amp;gt;&amp;lt;/code&amp;gt; || OPCIONAL || (normal, abandoned, expired, other)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejemplo de respuesta JSON&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
 {&lt;br /&gt;
    &amp;quot;errorNum&amp;quot;: 104,&lt;br /&gt;
    &amp;quot;errorStr&amp;quot;: &amp;quot;Wrong session&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ejemplos para omnisuite ===&lt;br /&gt;
&lt;br /&gt;
==== Ejemplo de chat ====&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;quot;/etc/MDtel/vflow/service_chat.ini&amp;quot; &amp;quot;omnisuiteText&amp;quot; &amp;quot;{{interaction.id}}&amp;quot; &amp;quot;{{account.id}}&amp;quot; &amp;quot;{{interaction.createdAt}}&amp;quot; &amp;quot;&amp;quot; &amp;quot;&amp;quot; &amp;quot;&amp;quot; &amp;quot;{{message.body}}&amp;quot; | jq -r '.response'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Ejemplo de voz ====&lt;br /&gt;
&lt;br /&gt;
[[Archivo:Imagen cally square.jpg|1024px|none|miniatura|Ejemplo de flujo de Cally Square]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;quot;/etc/MDtel/vflow/service_voice.ini&amp;quot; &amp;quot;sessionOpen&amp;quot; &amp;quot;{UNIQUEID}&amp;quot; &amp;quot;&amp;quot; &amp;quot;&amp;quot; &amp;quot;&amp;quot; |  jq -r '.session' &amp;lt;/pre&amp;gt;&lt;br /&gt;
::&amp;lt;small&amp;gt;salida del comando almacenado en variable &amp;quot;vflow_sessionopen_response&amp;quot; para su posterior uso en cally square&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Archivo:Imagen sessionopen.jpg|550px|center|miniatura|Abrir sesión en vFlow]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;quot;/etc/MDtel/vflow/service_desa_voz.ini&amp;quot; &amp;quot;textRequest&amp;quot; &amp;quot;{vflow_sessionopen_response}&amp;quot; &amp;quot;{OPENAI_WHISPER_TRANSCRIPT}&amp;quot; | jq -r '.response'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
::&amp;lt;small&amp;gt;la voz se ha transcrito con OpenAI, por eso se usa como parámetro {OPENAI_WHISPER_TRANSCRIPT})&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Archivo:Imagen textrequest.jpg|550px|center|miniatura|Enviar texto en vFlow]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt; &lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;quot;/etc/MDtel/vflow/service_desa_voz.ini&amp;quot; &amp;quot;sessionClose&amp;quot; &amp;quot;{{vflow_sessionopen_response}}&amp;quot; &amp;quot;normal&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Archivo:Imagen sessionclose.jpg|900px|center|miniatura|Cerrar sesión en vFlow]]&lt;br /&gt;
&lt;br /&gt;
[[Category:tecnico]]&lt;br /&gt;
[[Category:VIVAit Call]]&lt;br /&gt;
[[Category:Omnisuite]]&lt;br /&gt;
[[Category:IA]]&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Archivo:Gesti%C3%B3n_RAG.png&amp;diff=19159</id>
		<title>Archivo:Gestión RAG.png</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Archivo:Gesti%C3%B3n_RAG.png&amp;diff=19159"/>
		<updated>2026-07-07T10:08:53Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: Alfredo.rodriguez subió una nueva versión de Archivo:Gestión RAG.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Gestión RAG&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Manual_de_operaci%C3%B3n_de_vFlow&amp;diff=19158</id>
		<title>Manual de operación de vFlow</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Manual_de_operaci%C3%B3n_de_vFlow&amp;diff=19158"/>
		<updated>2026-07-07T09:59:34Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* Descripción general vFlow */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Descripción general vFlow ==&lt;br /&gt;
&lt;br /&gt;
vFlow es un módulo de conexión a sistemas de inteligencia artifical para sistemas de comunicaciones unificadas, ya sean sistemas corporativos o contact center&lt;br /&gt;
Gracias a vFlow, las plataformas de UC dispondrán de una solución para comunicarse con sistemas IA utilizando un mismo mecanismo independientemente de la solución de inteligencia artificial que se utilice&lt;br /&gt;
&lt;br /&gt;
Para proporcionar el servicio de manera completa, vFlow (en concreto el orquestador) se conectará a sistemas de inteligencia artificial (LLM) que permitirán desarrollar los agentes definidos en los orquestadores&lt;br /&gt;
&lt;br /&gt;
'''Conceptos:'''&lt;br /&gt;
* Plataforma&amp;lt;span style=&amp;quot;margin-left: 3em;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;--&amp;gt; Plataforma de comunicaciones unificadas; por ejemplo Omnisuite o VIVAit Call&lt;br /&gt;
* Orquestador&amp;lt;span style=&amp;quot;margin-left: 3em;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;--&amp;gt; Plataforma agéntica de IA (por ejemplo Flowise)&lt;br /&gt;
* vFlowProxy&amp;lt;span style=&amp;quot;margin-left: 3em;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;--&amp;gt; Módulo VIVAit que conecta multiples plataformas con múltiples orquestadores&lt;br /&gt;
* LLM&amp;lt;span style=&amp;quot;margin-left: 3em;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;--&amp;gt; Modelo de lenguaje natural que usará un orquestadores&lt;br /&gt;
* Agente&amp;lt;span style=&amp;quot;margin-left: 3em;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;--&amp;gt; Cada uno de los flujos creados en vFlow; corresponde a un par plataforma/agentflow de orquestador&lt;br /&gt;
* Servicio&amp;lt;span style=&amp;quot;margin-left: 3em;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;--&amp;gt; Cada elemento de negocio en la plataforma de CU (por ejemplo VDN)&lt;br /&gt;
&lt;br /&gt;
[[Archivo:Arquitectura Vflow - v2.jpg|1400px|center|Arquitecura de vFlow]]&lt;br /&gt;
&lt;br /&gt;
Los '''módulos principales''' de vFlow son:&lt;br /&gt;
* vFlowProxy: Recibe las conexiones de los sistemas de comunicaciones unificadas, y conecta con los orquestadores de Inteligencia Artificial de manera segura y adaptada al tipo de servicio; el acceso a vFlow Proxy desde las plataformas se realizará mediante:&lt;br /&gt;
* Programa cliente: Se utiliza en el sistema de comunicaciones unificadas (actualmente VIVAit Call y Omnsisuite) para invocar a vFlow&lt;br /&gt;
* API REST: Alternativa al programa cliente, vFlowProxy proporciona una API REST que facilita que cualquier plataforma pueda comunicarse mediante un procedimiento estándar y documentado&lt;br /&gt;
* Portal de administración vFlow: Permite visualizar las interaciones realizadas y configurar el sistema&lt;br /&gt;
* Orquestador de IA: Herramienta de Inteligencia Artificial que permitirá la creación de aplicaciones personalizadas (agentes)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
'''Otros elementos''' relevantes serán:&lt;br /&gt;
* Base de datos vFlow:&lt;br /&gt;
:* Almacena información sobre sesiones y transacciones realizadas&lt;br /&gt;
:* Almacena información de configuración sobre vFlow&lt;br /&gt;
:* Gestiona el RAG de las inteligencias artificiales a usar&lt;br /&gt;
&lt;br /&gt;
== Puesta en marcha de nodo vFlow ==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Existe un nodo vFlow en los repositorios habituales proporcionados&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para '''dar de alta nodo vflow en un cliente''' hay que:&lt;br /&gt;
* Configurar IP (por defecto la maquina va configurada por DHCP)&lt;br /&gt;
* Adaptar el firewall, para ello REVISAR el fichero &amp;lt;code&amp;gt;/etc/firewall/vars.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
* Certificados validos en apache&lt;br /&gt;
* REVISAR ficheros &amp;lt;code&amp;gt;/etc/apache2/sites-enabled/flowise.conf&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;/etc/apache2/sites-enabled/vFlow.conf&amp;lt;/code&amp;gt; la variable &amp;lt;code&amp;gt;ServerName&amp;lt;/code&amp;gt; (nombre valido de la maquina)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Accesos vFlow''' (se debe cambiar tras instalación):&lt;br /&gt;
* Usuario ssh y de SO por defecto es sat y clave a proporcionar.&lt;br /&gt;
* Para el portal de flowise las credenciales son usuario: vfloadmin@vflow.com clave: A proporcionar&lt;br /&gt;
* Para el portal de vflow las credenciales son usaurio sat y clave a proporcionar.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Accesos BBDD vFlow'''&lt;br /&gt;
* Para acceder a la base de datos desde el workbenck solo desde localhost (o tunel):&lt;br /&gt;
* BBDD Vlfow (admin)  vflowadmin // clave a proporcionar&lt;br /&gt;
* BBDD Vlfow (no_admin)  vflow //  clave a proporcionar&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Portal orquestador Flowise'''&lt;br /&gt;
&lt;br /&gt;
ubicado en https://host.cliente.xx:4567&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #fef6e7; border: 1px solid #fbd68a; padding: 1em; border-radius: 4px;width: fit-content; margin-left: 50px&amp;quot;&amp;gt;&lt;br /&gt;
'''⚠️ ATENCION !!'''&lt;br /&gt;
'''Los cambios en tablas de configuración de BBDD de vFlow (orquestadores, plataformas, agentes) requieren reinicio del servicio vFlowProxy'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', 'Monaco', 'Courier New', monospace;&amp;quot;&amp;gt;&lt;br /&gt;
/etc/init.d/vFlowProxy.service status&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
/etc/init.d/vFlowProxy.service stop&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
/etc/init.d/vFlowProxy.service start&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
El fichero de configuración del demonio &amp;lt;code&amp;gt;vFlowProxy&amp;lt;/code&amp;gt; se encuentra en &amp;lt;code&amp;gt;/etc/MDtel/vFlowProxy.conf&amp;lt;/code&amp;gt;, si bien este fichero de configuración no se modificará habitualmente (los parámetros generales de configuración de vFlowProxy se encuentran en la BBDD de vFlow)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Procedimientos de respaldo y restauración ==&lt;br /&gt;
&lt;br /&gt;
=== Respaldo ===&lt;br /&gt;
&lt;br /&gt;
* Hacer backup de las bases de datosdel orquestador (flowise) y de vFlow&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', 'Monaco', 'Courier New', monospace;&amp;quot;&amp;gt;&lt;br /&gt;
mariadb-dump -u root -p --single-transaction --routines --events --triggers --default-character-set=utf8mb4 vflow_flowise_config &amp;gt; vflow_flowise_config_$(date +%F_%H%M%S).sql&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
mariadb-dump -u root -p --single-transaction --routines --events --triggers --default-character-set=utf8mb4 vflow_flowise_config &amp;gt; vflow_flowise_upsert_$(date +%F_%H%M%S).sql&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
mariadb-dump -u root -p --single-transaction --routines --events --triggers --default-character-set=utf8mb4 vFlow &amp;gt; vFlow_$(date +%F_%H%M%S).sql&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* Copiar:&lt;br /&gt;
** El directorio /opt/vFlow_flowise/.flowise&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', 'Monaco', 'Courier New', monospace;&amp;quot;&amp;gt;&lt;br /&gt;
cp -vai  /opt/vFlow_flowise/.flowise  /opt/vFlow_flowise/.flowise_$(date +%F_%H%M%S)&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
** El directorio /opt/vFlow_flowise/archivos&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', 'Monaco', 'Courier New', monospace;&amp;quot;&amp;gt;&lt;br /&gt;
cp -vai  /opt/vFlow_flowise/archivos /opt/vFlow_flowise/archivos_$(date +%F_%H%M%S)&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
'''Todos los ficheros creados pueden ser movidos al destino deseado para almacenar la copia de respaldo'''&lt;br /&gt;
&lt;br /&gt;
=== Restauración ===&lt;br /&gt;
Para restaurar, será necesario&lt;br /&gt;
* Importar de nuevo las dos bases de datos de flowise y la base de datos de vFlow:&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', 'Monaco', 'Courier New', monospace;&amp;quot;&amp;gt;&lt;br /&gt;
mysql -u root -p vflow_flowise_config &amp;lt;  vflow_flowise_config_ULTIMAFECHA.sql&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
mysql -u root -p vflow_flowise_upsert &amp;lt;  vflow_flowise_upsert_ULTIMAFECHA.sql&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
mysql -u root -p vFlow &amp;lt;  vFlow_ULTIMAFECHA.sql&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* Volver a poner las carpetas de /opt/vFlow_flowise/&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', 'Monaco', 'Courier New', monospace;&amp;quot;&amp;gt;&lt;br /&gt;
mv -vi  /opt/vFlow_flowise/.flowise_ULTIMAFECHA  /opt/vFlow_flowise/.flowise&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
mv -vi /opt/vFlow_flowise/archivos_ULTIMAFECHA  /opt/vFlow_flowise/archivos&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
'''Las ubicaciones de los archivos a resturar pueden ser diferentes'''&lt;br /&gt;
&lt;br /&gt;
== Gestión en vFlow ==&lt;br /&gt;
vFlow prevé la existencia de tres entornos que permita hacer una gestión segura de agentes y RAG:&lt;br /&gt;
&lt;br /&gt;
* Producción&lt;br /&gt;
* Preproducción&lt;br /&gt;
* Pruebas&lt;br /&gt;
&lt;br /&gt;
Para cada agente o store de RAG se podrá desplegar un entorno, dos o los tres entornos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f0fff4; border: 3px solid #c6f6d5; padding: 1em; border-radius: 4px;width: fit-content; margin-left: 0px&amp;quot;&amp;gt;&lt;br /&gt;
✅ '''Recomendación'''&amp;lt;br&amp;gt;&lt;br /&gt;
::En la mayoría de los casos con disponer de entorno de producción y preproducción tanto para agente como para RAG será suficiente&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Para realizar una gestión completa en vFlow (suponiendo tres entornos y gestión de agentes y RAG), deberemos tener&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Archivo:Gestión RAG.png|1000px|miniaturadeimagen|centro|Gestión en vFlow|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== En orquestador (Flowise) ===&lt;br /&gt;
* '''&amp;lt;big&amp;gt;1.- Crear agente&amp;lt;/big&amp;gt;''': Se crearán hasta '''tres agentes''' (pro/pre/pru) en función de los entornos deseados; es importante '''anotar los ID's de los agentes''' creados (se ven en la URL)&lt;br /&gt;
::[[Archivo:Captura de pantalla 2026-05-20 144432.png|800px|miniaturadeimagen|no|Creación de agente en orquestador flowise (uno por entorno)|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f0fff4; border: 3px solid #c6f6d5; padding: 1em; border-radius: 4px;width: fit-content; margin-left: 50px&amp;quot;&amp;gt;&lt;br /&gt;
✅ '''Puntos 2, 3 y 4 solo en caso de tener RAG'''&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''&amp;lt;big&amp;gt;2.- Crear store &amp;lt;/big&amp;gt;''': Se crearán hasta '''tres stores''' (pro/pre/pru) en función de los entornos deseados; es importante '''anotar los ID's de los stores''' creados (se ven en la URL)&lt;br /&gt;
::[[Archivo:Captura de pantalla 2026-05-20 135417.png|800px|miniaturadeimagen|no|Creación de store (uno por entorno)|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* '''&amp;lt;big&amp;gt;3.- Crear loader'''&amp;lt;/big&amp;gt; : Para cada loader que se desee manejar, se creará en el orquestador y en el document store, para los entornos deseados&lt;br /&gt;
::* Subir fichero (p.ej &amp;quot;ld1.txt&amp;quot; a &amp;lt;code&amp;gt;/var/www.html/storages/production&amp;lt;/code&amp;gt; (o a &amp;lt;code&amp;gt;/staging&amp;lt;/code&amp;gt; o a &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt; si procede)&lt;br /&gt;
::::[[Archivo:Captura de pantalla 2026-05-20 135757.png|700px|miniaturadeimagen|no|Subir fichero inicial (uno por entorno)|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
::* Crear loader&lt;br /&gt;
::::* Tipo: API loader&lt;br /&gt;
::::* Method: get&lt;br /&gt;
::::* URL : &amp;lt;cde&amp;gt;http://127.0.0.1/storages/production/nombrefich.txt&amp;lt;/code&amp;gt; (o  /staging /test) (formatos posibles txt, pdf, doc, docx)&lt;br /&gt;
::::* Splitter: Recursive character text splitter&lt;br /&gt;
::::* Comprobar con &amp;quot;preview chunks&amp;quot;&lt;br /&gt;
::::* Pulsar &amp;quot;process&amp;quot;&lt;br /&gt;
::::::[[Archivo:Captura de pantalla 2026-05-20 140146.png|700px|miniaturadeimagen|no|Creador loader en orquestador flowise|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
::::::[[Archivo:Captura de pantalla 2026-05-20 140326.png|700px|miniaturadeimagen|no|Loader creado en orquestador flowise|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* '''&amp;lt;big&amp;gt;4.- Sincronizar chunks&amp;lt;/big&amp;gt;''' en store ('''para cada entorno''')&lt;br /&gt;
::* En Store, more actions / Upsert All Chunks&lt;br /&gt;
::::[[Archivo:Captura de pantalla 2026-05-20 141118.png|700px|miniaturadeimagen|no|Upsert chunks store flowise|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
::::* Embeddings: Por ejemplo OpenAI embeddings (requiere &amp;quot;Credential&amp;quot;)&lt;br /&gt;
::::* Vector Store: Qdrant&lt;br /&gt;
::::::* Credential: cflow_qdrant&lt;br /&gt;
::::::* URL: http://localhost:6333&lt;br /&gt;
::::::* Qdrant Collection Name: vflow&lt;br /&gt;
::::* Record Manager: MySQL&lt;br /&gt;
::::::* Connect credential: mysql_upsert&lt;br /&gt;
::::::* Host: localhost&lt;br /&gt;
::::::* Database: vflow_flowise_upsert&lt;br /&gt;
::::::* Cleaun: Full&lt;br /&gt;
::::* Aplicar&lt;br /&gt;
::::::* Save config&lt;br /&gt;
::::::* Upsert&lt;br /&gt;
::::::[[Archivo:Captura de pantalla 2026-05-20 141626.png|700px|miniaturadeimagen|no|Sincronizado de store en flowise|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
La siguiente imagen muestra como quedará en el orquestador (flowise) un document store de vflow con entornos de producción, reproducción y pruebas&lt;br /&gt;
::[[Archivo:Captura de pantalla 2026-05-20 142148.png|700px|miniaturadeimagen|no|Document store en flowise con los tres entornos (tres document stores)|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== En flow ===&lt;br /&gt;
* 1.- '''&amp;lt;big&amp;gt; Crear un agente&amp;lt;/big&amp;gt;''': Vincularlo a los tres agentes de orquestador (pro/pre/pru) anotados anteriormente&lt;br /&gt;
::::[[Archivo:Captura de pantalla 2026-05-20 143843.png|800px|miniaturadeimagen|no|Crear agente en vflow|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f0fff4; border: 3px solid #c6f6d5; padding: 1em; border-radius: 4px;width: fit-content; margin-left: 50px&amp;quot;&amp;gt;&lt;br /&gt;
✅ '''Puntos 2 y 3 solo en caso de tener RAG'''&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* 2.- '''&amp;lt;big&amp;gt;Crear un store&amp;lt;/big&amp;gt;''': Vinculado a los stores de orquestador anotados anteriormente (pro/pre/pru)&lt;br /&gt;
::::[[Archivo:Captura de pantalla 2026-05-20 142920.png|800px|miniaturadeimagen|no|Creacion de Store en vflow|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
* 3.- '''&amp;lt;big&amp;gt;Crear un loader&amp;lt;/big&amp;gt;'''&lt;br /&gt;
::* Loader vinculado a agente de vflow&lt;br /&gt;
::* El sistema comprobará que el fichero ya existe en el orquestador&lt;br /&gt;
:: Pulsar &amp;quot;crear&amp;quot;&lt;br /&gt;
::::[[Archivo:Captura de pantalla 2026-05-20 143126.png|700px|miniaturadeimagen|no|Crear loader en vflow|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
::::[[Archivo:Captura de pantalla 2026-05-20 143239.png|700px|miniaturadeimagen|no|Store, loader y detalle de loader|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Diagnósticos ==&lt;br /&gt;
Fichero de log, en nodo vFlowProxy, para cualquier canal&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
tail -f /var/log/vFlowProxy/vFlowProxy.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Monitorizar estado del proceso vflowProxy, en nodo vFlowProxy&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
nc localhost 1131&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;proceso&amp;quot;: {&lt;br /&gt;
    &amp;quot;nombre&amp;quot;: &amp;quot;vFlowProxy&amp;quot;,&lt;br /&gt;
    &amp;quot;version&amp;quot;: &amp;quot;00.00.01&amp;quot;,&lt;br /&gt;
    &amp;quot;inicio_ts&amp;quot;: 1771315153,&lt;br /&gt;
    &amp;quot;inicio_cad&amp;quot;: &amp;quot;20260217 085913&amp;quot;,&lt;br /&gt;
    &amp;quot;log_alarmas_val&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;log_alarma_ultimo_ts&amp;quot;: 1771970401,&lt;br /&gt;
    &amp;quot;log_alarma_ultimo_ts_cad&amp;quot;: &amp;quot;20260224 230001&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;diagnostico&amp;quot;: {&lt;br /&gt;
    &amp;quot;gmp&amp;quot;: {&lt;br /&gt;
      &amp;quot;msj_val&amp;quot;: 1022,&lt;br /&gt;
      &amp;quot;msj_max&amp;quot;: 1024,&lt;br /&gt;
      &amp;quot;buf_val&amp;quot;: 1024,&lt;br /&gt;
      &amp;quot;buf_max&amp;quot;: 1024,&lt;br /&gt;
      &amp;quot;tarea_val&amp;quot;: 7,&lt;br /&gt;
      &amp;quot;tarea_max&amp;quot;: 15&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;tiempo&amp;quot;: {&lt;br /&gt;
      &amp;quot;uptime&amp;quot;: 716665,&lt;br /&gt;
      &amp;quot;uptime_dias&amp;quot;: 8,&lt;br /&gt;
      &amp;quot;uptime_horas&amp;quot;: 7,&lt;br /&gt;
      &amp;quot;uptime_minutos&amp;quot;: 4,&lt;br /&gt;
      &amp;quot;uptime_segundos&amp;quot;: 25&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;wws&amp;quot;: {&lt;br /&gt;
      &amp;quot;conexiones_val&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;conexiones_max_periodo&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;hilos_val&amp;quot;: 4,&lt;br /&gt;
      &amp;quot;hilos_max&amp;quot;: 4,&lt;br /&gt;
      &amp;quot;wsi_cad&amp;quot;: &amp;quot;sesiones=0/200&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;alarmas_nivel_max&amp;quot;: 0,&lt;br /&gt;
  &amp;quot;alarmas&amp;quot;: []&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Es relevante la monitorización de sesiones  &amp;lt;code&amp;gt;&amp;quot;wsi_cad&amp;quot;: &amp;quot;sesiones=0/200&amp;quot;&amp;lt;/code&amp;gt; (usadas/máximas)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
En nodo Omnisuite, para canal voz&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
asterisk -rv | grep &amp;lt;callysquare_name&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
en nodo Omnisuite, para canal voz&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
tail -f /var/log/xcally/&amp;lt;agi-combined.yyyy-mm-dd.log&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
en nodo Omnisuite, para cualquier canal&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
tail -f /var/log/xcally/&amp;lt;routing-combined.yyyy-mm-dd.log&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Pruebas desde vFlow ==&lt;br /&gt;
&lt;br /&gt;
En /home/sat/vFlowProxy hay scripts de prueba (se configuran en el vars.sh); para usar los scripts de prueba tendremos que tener también &amp;quot;.ini&amp;quot; en vFlow&lt;br /&gt;
&lt;br /&gt;
Es útil comenzar con&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/home/sat/vFlowProxy/vFlowGetInfo.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
que sin parámetros adicionales confirma el correcto estado de vFlowProxy&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;errorNum&amp;quot;: 0,&lt;br /&gt;
  &amp;quot;errorStr&amp;quot;: &amp;quot;OK&amp;quot;,&lt;br /&gt;
  &amp;quot;app&amp;quot;: &amp;quot;vFlowProxy&amp;quot;,&lt;br /&gt;
  &amp;quot;version&amp;quot;: &amp;quot;00.00.01&amp;quot;,&lt;br /&gt;
  &amp;quot;sessions_opened&amp;quot;: 0,&lt;br /&gt;
  &amp;quot;sessions_limit&amp;quot;: 200,&lt;br /&gt;
  &amp;quot;sessions_sleep_timeout_s&amp;quot;: 3600,&lt;br /&gt;
  &amp;quot;alarms&amp;quot;: 8&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Integración de vFlow desde Omnisuite ==&lt;br /&gt;
=== Descripción general ===&lt;br /&gt;
En Omnisuite, la integración con vFlow, se realiza con el programa vFlowOmnisuite, que podrá ser invocado como ejecutable (más rápido, para debian), o como Python (más universal)&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; max-width: 500px; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite (OPCIÓN PREFERENTE)&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite.py (LEGACY)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Asociado al programa existen los siguientes ficheros de configuración (.ini):&lt;br /&gt;
&lt;br /&gt;
Un '''&amp;quot;.ini&amp;quot; de plataforma''' Omnisuite en vFlow --&amp;gt; Solo contiene uuid de la plataforma; se entrega un &amp;quot;.ini&amp;quot; a modo de ejemplo en &amp;lt;code&amp;gt;/etc/MDtel/vflow/platform.ini&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
EJEMPLO &amp;quot;.INI&amp;quot; DE PLATAFORMA&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
[uuids]&lt;br /&gt;
platform=1d111530-e22d-11f0-b0f2-5254008bef96&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un '''&amp;quot;.ini&amp;quot; por agente''' en vFlow --&amp;gt; Solo contiene uuid del agente según su identificación en vFlow ('''NO''' en un orquestador, por ejemplo flowise); se entrega un &amp;quot;.ini&amp;quot; asociado a un agente &amp;quot;loop&amp;quot; existente en Flowise &amp;lt;code&amp;gt;/etc/MDtel/vflow/agent_loop_01.ini&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
EJEMPLO &amp;quot;.INI&amp;quot; DE AGENTE&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
[uuids]&lt;br /&gt;
agent=1a3a1020-ea1d-11f0-b4a5-5254008bef96&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un '''&amp;quot;.ini&amp;quot; por servicio''' --&amp;gt; Configuración de cada servicio en Omnisuite; se entrega un &amp;quot;.ini&amp;quot; a modo de ejemplo en &amp;lt;code&amp;gt;/etc/MDtel/vflow/service.ini&amp;lt;/code&amp;gt;&lt;br /&gt;
En cada fichero de servicio configuraremos&lt;br /&gt;
::* Donde está Vflow&lt;br /&gt;
::* Agente&lt;br /&gt;
::* Plataforma&lt;br /&gt;
::* timeout_s --&amp;gt; Importante, es afectado por el LLM&lt;br /&gt;
::* channel_text_type --&amp;gt; IMPORTANTE si el servicio es de texto que esté bien (vacio solo si el servicio es de texto, NO COMENTARLO)&lt;br /&gt;
::* environment --&amp;gt; production, staging, test&lt;br /&gt;
EJEMPLO &amp;quot;.INI&amp;quot; DE SERVICIO&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
  [arch_uuids]&lt;br /&gt;
  agent=/etc/MDtel/vflow/agent_loop_01.ini&lt;br /&gt;
  platform=/etc/MDtel/vflow/platform.ini&lt;br /&gt;
&lt;br /&gt;
  [vflow]&lt;br /&gt;
  host_port=172.25.129.242:7900&lt;br /&gt;
  timeout_s=20&lt;br /&gt;
  # channel_type=[voice|chat|email]&lt;br /&gt;
  channel_type=chat&lt;br /&gt;
  # environment=[production|staging|test]&lt;br /&gt;
  environment=production&lt;br /&gt;
  language=es&lt;br /&gt;
&lt;br /&gt;
  [omnisuite]&lt;br /&gt;
  # channel_text_type=[chat|mail|sms|whatsup]&lt;br /&gt;
  channel_text_type=chat&lt;br /&gt;
  service_id=vflow_service_id&lt;br /&gt;
  service_name=vflow_service_name&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La imagen siguiente muestra el esquema de relación entre orquestador/plataforma/agente/servicio en la plataforma y en vFlow&lt;br /&gt;
&lt;br /&gt;
[[Archivo:Relaciones vFlow plat orq ag serv.png|800px|miniaturadeimagen|centro|Relación orquestador-plataforma-agente-servicio|link=]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Invocación ===&lt;br /&gt;
==== Generales ====&lt;br /&gt;
&lt;br /&gt;
===== Ver configuración =====&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;lt;config_arch&amp;gt; configPrint&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ejemplo de respuesta&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
Configuration:&lt;br /&gt;
  agent_arch_uuid=/etc/MDtel/vflow/agent_fse_rapido.ini&lt;br /&gt;
  agent_uuid=3487af28-1d14-11f1-803c-525400ef204c&lt;br /&gt;
  platform_arch_uuid=/etc/MDtel/vflow/platform_labomsui.ini&lt;br /&gt;
  platform_uuid=9a54ea74-f050-11f0-bdf1-5254008bef96&lt;br /&gt;
&lt;br /&gt;
  vflow_host_port=labvflow.mdnova.local&lt;br /&gt;
  vflow_timeout_s=50&lt;br /&gt;
  vflow_environment=production&lt;br /&gt;
  vflow_channel_type=voice&lt;br /&gt;
  vflow_language=es&lt;br /&gt;
&lt;br /&gt;
  omnisuite_channel_text_type=chat&lt;br /&gt;
  omnisuite_service_id=287&lt;br /&gt;
  omnisuite_service_name=desarrollo&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;errorNum&amp;quot;: 0,&lt;br /&gt;
  &amp;quot;errorCad&amp;quot;: &amp;quot;OK&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Ver versión =====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite version&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ejemplo de respuesta&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
00.00.02&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Para canales de texto ====&lt;br /&gt;
&lt;br /&gt;
Para canales de texto en Omnisuite existe un único Comando de invocación &amp;quot;omnisuiteText&amp;quot;&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;lt;config_arch&amp;gt; omnisuiteText &amp;lt;omnisuite_id&amp;gt; &amp;lt;omnisuite_websiteId&amp;gt; &amp;lt;omnisuite_createdAt&amp;gt; &amp;lt;vflow_client_id&amp;gt; &amp;lt;vflow_client_phone_number&amp;gt; &amp;lt;vflow_client_email&amp;gt; &amp;lt;question&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parámetros ( Los OPCIONALES son &amp;quot;&amp;quot; si no se envía valor):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Obligatoriedad !! Descripción&lt;br /&gt;
|-&lt;br /&gt;
| `&amp;lt;config_arch&amp;gt;` || OBLIGATORIO || &amp;quot;.ini&amp;quot; del servicio&lt;br /&gt;
|-&lt;br /&gt;
| `&amp;lt;omnisuite_id&amp;gt;` || OBLIGATORIO || Identificativo de la interacción en Omnisuite&lt;br /&gt;
|-&lt;br /&gt;
| `&amp;lt;omnisuite_websiteId&amp;gt;` || OBLIGATORIO || Identificativo del servicio en Omnisuite (ej. website id en chat)&lt;br /&gt;
|-&lt;br /&gt;
| `&amp;lt;omnisuite_createdAt&amp;gt;` || OBLIGATORIO || Creación de la interacción&lt;br /&gt;
|-&lt;br /&gt;
| `&amp;lt;vflow_client_id&amp;gt;` || OPCIONAL || Id de cliente en Omnisuite&lt;br /&gt;
|-&lt;br /&gt;
| `&amp;lt;vflow_client_phone_number&amp;gt;` || OPCIONAL || Telf de cliente en Omnisuite&lt;br /&gt;
|-&lt;br /&gt;
| `&amp;lt;vflow_client_email&amp;gt;` || OPCIONAL || Email de cliente en Omnisuite&lt;br /&gt;
|-&lt;br /&gt;
| `&amp;lt;question&amp;gt;` || OBLIGATORIO || Texto a enviar al orquestado (p. ej. Flowise)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ejemplo de respuesta JSON&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; max-width: 400px; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
 &amp;quot;errorNum&amp;quot;: 0,&lt;br /&gt;
 &amp;quot;errorStr&amp;quot;: &amp;quot;OK&amp;quot;,&lt;br /&gt;
 &amp;quot;session&amp;quot;: &amp;quot;e926548d-fdcf-11f0-a793-525400ef204c&amp;quot;,&lt;br /&gt;
 &amp;quot;language&amp;quot;: &amp;quot;es&amp;quot;,&lt;br /&gt;
 &amp;quot;response&amp;quot;: &amp;quot;HOLA&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Para canales de voz ====&lt;br /&gt;
Para  canales de voz, existen comandos para &amp;quot;abrir sesión&amp;quot;, &amp;quot;enviar texto&amp;quot; y &amp;quot;cerrar sesión&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===== Abrir sesión =====&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;lt;config_arch&amp;gt; sessionOpen &amp;lt;omnisuite_UniqueId&amp;gt; &amp;lt;vflow_client_id&amp;gt; &amp;lt;vflow_client_phone_number&amp;gt; &amp;lt;vflow_client_email&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parámetros (Los OPCIONALES son &amp;quot;&amp;quot; si no se envía valor):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Requisito !! Descripción&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;config_arch&amp;gt;&amp;lt;/code&amp;gt; || OBLIGATORIO || &amp;quot;.ini&amp;quot; del servicio&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;omnisuite_UniqueId&amp;gt;&amp;lt;/code&amp;gt; || OBLIGATORIO || Unique_ID de asterisk de la llamada en Omnisuite&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;vflow_client_id&amp;gt;&amp;lt;/code&amp;gt; || OPCIONAL || Id de cliente en Omnisuite&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;vflow_client_phone_number&amp;gt;&amp;lt;/code&amp;gt; || OPCIONAL || Telf de cliente en Omnisuite&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;vflow_client_email&amp;gt;&amp;lt;/code&amp;gt; || OPCIONAL || Email de cliente en Omnisuite&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejemplo de respuesta JSON&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
 {&lt;br /&gt;
    &amp;quot;errorNum&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;errorStr&amp;quot;: &amp;quot;OK&amp;quot;,&lt;br /&gt;
    &amp;quot;session&amp;quot;: &amp;quot;ec73df29-f08a-11f0-a8ec-525400ef204c&amp;quot;,&lt;br /&gt;
    &amp;quot;platform_id&amp;quot;: &amp;quot;146&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''El value correspondiente al key &amp;quot;session&amp;quot; deberá ser guardado en una variable para siguientes invocaciones'''&lt;br /&gt;
&lt;br /&gt;
===== Enviar texto =====&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;lt;config_arch&amp;gt; textRequest &amp;lt;vflow_session_uuid&amp;gt; &amp;lt;question&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parámetros:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Requisito !! Descripción&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;config_arch&amp;gt;&amp;lt;/code&amp;gt; || OBLIGATORIO || &amp;quot;.ini&amp;quot; del servicio&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;vflow_session_uuid&amp;gt;&amp;lt;/code&amp;gt; || OBLIGATORIO || Variable &amp;quot;session&amp;quot; almacenada en el &amp;quot;sessionOpen&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;question&amp;gt;&amp;lt;/code&amp;gt; || OBLIGATORIO || Texto a enviar al orquestado (p. ej. Flowise) (normal, abandoned, other)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ejemplo de respuesta JSON&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
 {&lt;br /&gt;
    &amp;quot;errorNum&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;errorStr&amp;quot;: &amp;quot;OK&amp;quot;,&lt;br /&gt;
    &amp;quot;session&amp;quot;: &amp;quot;c6f6fad7-f6c1-11f0-a793-525400ef204c&amp;quot;,&lt;br /&gt;
    &amp;quot;language&amp;quot;: &amp;quot;ES&amp;quot;,&lt;br /&gt;
    &amp;quot;response&amp;quot;: &amp;quot;Cristóbal Colón.&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Cerrar sesión=====&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;lt;config_arch&amp;gt; sessionClose &amp;lt;vflow_session_uuid&amp;gt; &amp;lt;vflow_cause&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parámetros  (Los OPCIONALES son &amp;quot;&amp;quot; si no se envía valor):&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parámetro !! Estado !! Descripción&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;config_arch&amp;gt;&amp;lt;/code&amp;gt; || OBLIGATORIO || &amp;quot;.ini&amp;quot; del servicio&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;vflow_session_uuid&amp;gt;&amp;lt;/code&amp;gt; || OBLIGATORIO || Variable &amp;quot;session&amp;quot; almacenada en el &amp;quot;sessionOpen&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;vflow_cause&amp;gt;&amp;lt;/code&amp;gt; || OPCIONAL || (normal, abandoned, expired, other)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejemplo de respuesta JSON&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 50px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
 {&lt;br /&gt;
    &amp;quot;errorNum&amp;quot;: 104,&lt;br /&gt;
    &amp;quot;errorStr&amp;quot;: &amp;quot;Wrong session&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ejemplos para omnisuite ===&lt;br /&gt;
&lt;br /&gt;
==== Ejemplo de chat ====&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;quot;/etc/MDtel/vflow/service_chat.ini&amp;quot; &amp;quot;omnisuiteText&amp;quot; &amp;quot;{{interaction.id}}&amp;quot; &amp;quot;{{account.id}}&amp;quot; &amp;quot;{{interaction.createdAt}}&amp;quot; &amp;quot;&amp;quot; &amp;quot;&amp;quot; &amp;quot;&amp;quot; &amp;quot;{{message.body}}&amp;quot; | jq -r '.response'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Ejemplo de voz ====&lt;br /&gt;
&lt;br /&gt;
[[Archivo:Imagen cally square.jpg|1024px|none|miniatura|Ejemplo de flujo de Cally Square]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;quot;/etc/MDtel/vflow/service_voice.ini&amp;quot; &amp;quot;sessionOpen&amp;quot; &amp;quot;{UNIQUEID}&amp;quot; &amp;quot;&amp;quot; &amp;quot;&amp;quot; &amp;quot;&amp;quot; |  jq -r '.session' &amp;lt;/pre&amp;gt;&lt;br /&gt;
::&amp;lt;small&amp;gt;salida del comando almacenado en variable &amp;quot;vflow_sessionopen_response&amp;quot; para su posterior uso en cally square&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Archivo:Imagen sessionopen.jpg|550px|center|miniatura|Abrir sesión en vFlow]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;quot;/etc/MDtel/vflow/service_desa_voz.ini&amp;quot; &amp;quot;textRequest&amp;quot; &amp;quot;{vflow_sessionopen_response}&amp;quot; &amp;quot;{OPENAI_WHISPER_TRANSCRIPT}&amp;quot; | jq -r '.response'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
::&amp;lt;small&amp;gt;la voz se ha transcrito con OpenAI, por eso se usa como parámetro {OPENAI_WHISPER_TRANSCRIPT})&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Archivo:Imagen textrequest.jpg|550px|center|miniatura|Enviar texto en vFlow]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background-color: #f6f8fa; border: 1px solid #d1d5da; padding: 1em; border-radius: 4px; width: fit-content; margin-left: 0px; font-family: 'Ubuntu Mono', 'Consolas', monospace; white-space: pre-wrap;&amp;quot;&amp;gt; &lt;br /&gt;
/opt/omnisuite/bin/vFlowOmnisuite &amp;quot;/etc/MDtel/vflow/service_desa_voz.ini&amp;quot; &amp;quot;sessionClose&amp;quot; &amp;quot;{{vflow_sessionopen_response}}&amp;quot; &amp;quot;normal&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Archivo:Imagen sessionclose.jpg|900px|center|miniatura|Cerrar sesión en vFlow]]&lt;br /&gt;
&lt;br /&gt;
[[Category:tecnico]]&lt;br /&gt;
[[Category:VIVAit Call]]&lt;br /&gt;
[[Category:Omnisuite]]&lt;br /&gt;
[[Category:IA]]&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Archivo:Arquitectura_Vflow_-_v2.jpg&amp;diff=19157</id>
		<title>Archivo:Arquitectura Vflow - v2.jpg</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Archivo:Arquitectura_Vflow_-_v2.jpg&amp;diff=19157"/>
		<updated>2026-07-07T09:58:18Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: Alfredo.rodriguez subió una nueva versión de Archivo:Arquitectura Vflow - v2.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Arquitectura de vFlow&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Howto%27s_5.0&amp;diff=19156</id>
		<title>Howto's 5.0</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Howto%27s_5.0&amp;diff=19156"/>
		<updated>2026-07-07T09:39:42Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* Signgle Sign On Oauth2/SAML */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &amp;lt;big&amp;gt;Guías Prácticas versión 5.x&amp;lt;/big&amp;gt; ==&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;Utilizar los siguientes enlaces para descargar las guías practicas, sobre las funcionalidades indicadas en cada apartado, de la versión 5.0 de '''''VIVA'''it CALL''.&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
=== Conexión con Teams ===&lt;br /&gt;
:&amp;lt;big&amp;gt;[[:media:Conexión Teams modelo Smart.pdf| Guía práctica para la configuración de la ''Conexión con Teams'', modelo Smart]]&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Puesta en marcha direc ===&lt;br /&gt;
:&amp;lt;big&amp;gt;[[:media:Puesta en marcha direc.pdf| Guía práctica para la ''Puesta en marcha de direc'']]&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Puesta en marcha SIPREC ===&lt;br /&gt;
:&amp;lt;big&amp;gt;[[:media:Puesta en marcha SIPREC.pdf| Guía práctica para la ''Puesta en marcha de SIPREC'']]&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Puesta en marcha TBC ===&lt;br /&gt;
:&amp;lt;big&amp;gt;[[:media:Puesta en marcha TBC.pdf| Guía práctica para la ''Puesta en marcha de TBC'']]&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Importación masiva de usuarios ===&lt;br /&gt;
:&amp;lt;big&amp;gt;[[:media:importación+masiva_V5+(2).pdf| Guía práctica para la ''Importación masiva'' de usuarios]]&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Puesta en marcha Grabación bajo demanda ===&lt;br /&gt;
:&amp;lt;big&amp;gt;[[:media:Grabación_bajo_demanda_V5111.pdf| Guía práctica para la ''Puesta en marcha de Grabación bajo demanda'']]&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Single Sign On Oauth2/SAML ===&lt;br /&gt;
:&amp;lt;big&amp;gt;[[:media:Admin_VIVAit-sso-documentacion-tecnica.pdf| Implementación ''SSO para administrador de VIVAit Call'']]&amp;lt;/big&amp;gt;&lt;br /&gt;
:&amp;lt;big&amp;gt;[[:media:Admin MS-Integracion VIVAit con MS Teams y SSO v4.pdf| Implementación ''SSO para administrador de MICROSOFT'']]&amp;lt;/big&amp;gt;&lt;br /&gt;
:&amp;lt;big&amp;gt;[[:media:Admin Google-Integración VIVAit con Google OAuth para SSO.pdf| Implementación ''SSO para administrador de GOOGLE'']]&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Página_principal | Volver a la Página Principal]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[[Category:tecnico]]&lt;br /&gt;
[[Category:usuario]]&lt;br /&gt;
[[Category:administrador]]&lt;br /&gt;
[[Category:VIVAit Call]]&lt;br /&gt;
[[Category:IA]]&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Archivo:Admin_Google-Integraci%C3%B3n_VIVAit_con_Google_OAuth_para_SSO.pdf&amp;diff=19155</id>
		<title>Archivo:Admin Google-Integración VIVAit con Google OAuth para SSO.pdf</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Archivo:Admin_Google-Integraci%C3%B3n_VIVAit_con_Google_OAuth_para_SSO.pdf&amp;diff=19155"/>
		<updated>2026-07-07T09:38:13Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Archivo:Admin_MS-Integracion_VIVAit_con_MS_Teams_y_SSO_v4.pdf&amp;diff=19154</id>
		<title>Archivo:Admin MS-Integracion VIVAit con MS Teams y SSO v4.pdf</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Archivo:Admin_MS-Integracion_VIVAit_con_MS_Teams_y_SSO_v4.pdf&amp;diff=19154"/>
		<updated>2026-07-07T09:38:00Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Archivo:Admin_VIVAit-sso-documentacion-tecnica.pdf&amp;diff=19153</id>
		<title>Archivo:Admin VIVAit-sso-documentacion-tecnica.pdf</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Archivo:Admin_VIVAit-sso-documentacion-tecnica.pdf&amp;diff=19153"/>
		<updated>2026-07-07T09:37:37Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Howto%27s_5.0&amp;diff=19152</id>
		<title>Howto's 5.0</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Howto%27s_5.0&amp;diff=19152"/>
		<updated>2026-07-07T09:37:11Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* Guías Prácticas versión 5.x */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &amp;lt;big&amp;gt;Guías Prácticas versión 5.x&amp;lt;/big&amp;gt; ==&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;Utilizar los siguientes enlaces para descargar las guías practicas, sobre las funcionalidades indicadas en cada apartado, de la versión 5.0 de '''''VIVA'''it CALL''.&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
=== Conexión con Teams ===&lt;br /&gt;
:&amp;lt;big&amp;gt;[[:media:Conexión Teams modelo Smart.pdf| Guía práctica para la configuración de la ''Conexión con Teams'', modelo Smart]]&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Puesta en marcha direc ===&lt;br /&gt;
:&amp;lt;big&amp;gt;[[:media:Puesta en marcha direc.pdf| Guía práctica para la ''Puesta en marcha de direc'']]&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Puesta en marcha SIPREC ===&lt;br /&gt;
:&amp;lt;big&amp;gt;[[:media:Puesta en marcha SIPREC.pdf| Guía práctica para la ''Puesta en marcha de SIPREC'']]&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Puesta en marcha TBC ===&lt;br /&gt;
:&amp;lt;big&amp;gt;[[:media:Puesta en marcha TBC.pdf| Guía práctica para la ''Puesta en marcha de TBC'']]&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Importación masiva de usuarios ===&lt;br /&gt;
:&amp;lt;big&amp;gt;[[:media:importación+masiva_V5+(2).pdf| Guía práctica para la ''Importación masiva'' de usuarios]]&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Puesta en marcha Grabación bajo demanda ===&lt;br /&gt;
:&amp;lt;big&amp;gt;[[:media:Grabación_bajo_demanda_V5111.pdf| Guía práctica para la ''Puesta en marcha de Grabación bajo demanda'']]&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Signgle Sign On Oauth2/SAML ===&lt;br /&gt;
:&amp;lt;big&amp;gt;[[:media:Admin_VIVAit-sso-documentacion-tecnica.pdf| Implementación ''SSO para administrador de VIVAit Call'']]&amp;lt;/big&amp;gt;&lt;br /&gt;
:&amp;lt;big&amp;gt;[[:media:Admin MS-Integracion VIVAit con MS Teams y SSO v4.pdf| Implementación ''SSO para administrador de MICROSOFT'']]&amp;lt;/big&amp;gt;&lt;br /&gt;
:&amp;lt;big&amp;gt;[[:media:Admin Google-Integración VIVAit con Google OAuth para SSO.pdf| Implementación ''SSO para administrador de GOOGLE'']]&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Página_principal | Volver a la Página Principal]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[[Category:tecnico]]&lt;br /&gt;
[[Category:usuario]]&lt;br /&gt;
[[Category:administrador]]&lt;br /&gt;
[[Category:VIVAit Call]]&lt;br /&gt;
[[Category:IA]]&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Howtos&amp;diff=19151</id>
		<title>Howtos</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Howtos&amp;diff=19151"/>
		<updated>2026-07-07T09:32:00Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! '''Producto:  '''!! VIVAit Call&lt;br /&gt;
VIVAit Suite&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Utilizar los enlaces siguientes para acceder a la información sobre guías práctica en las distintas versiones de '''''VIVA'''it''.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
::[[Howto's | &amp;lt;big&amp;gt;Guías Prácticas VIVAit&amp;lt;/big&amp;gt;]]&lt;br /&gt;
:::Guías paso a paso de funcionalidades del sistema '''''VIVA'''''it Call / '''''VIVA'''''it Suite de '''''&amp;lt;span style=&amp;quot;color:#144F9B&amp;quot;&amp;gt;MD&amp;lt;/span&amp;gt;'''''Tel.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
::[[Howto's 5.0 | &amp;lt;big&amp;gt;Guías Prácticas especificas de VIVAit 5.x&amp;lt;/big&amp;gt;]]&lt;br /&gt;
:::Guía paso a paso de funcionalidades espécificas para la versión 5.0 del sistema '''''VIVA'''''it Call / '''''VIVA'''''it Suite de '''''&amp;lt;span style=&amp;quot;color:#144F9B&amp;quot;&amp;gt;MD&amp;lt;/span&amp;gt;'''''Tel.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[[Página_principal | Volver a la Página Principal]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[[Category:tecnico]]&lt;br /&gt;
[[Category:usuario]]&lt;br /&gt;
[[Category:administrador]]&lt;br /&gt;
[[Category:VIVAit Call]]&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Portal_administracion_de_vFlow_v01.04&amp;diff=19150</id>
		<title>Portal administracion de vFlow v01.04</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Portal_administracion_de_vFlow_v01.04&amp;diff=19150"/>
		<updated>2026-07-06T12:14:40Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Manual de usuario — VFlow (Portal de IA) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Versión de la aplicación:''' v01.04.09 · © 2026 MDtel&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 1. Introducción ===&lt;br /&gt;
&lt;br /&gt;
'''VFlow''' es el portal de administración y analítica de los agentes de IA de MDtel. Desde una única interfaz web permite:&lt;br /&gt;
&lt;br /&gt;
* Consultar '''métricas de uso''' (tokens, peticiones, sesiones y tiempos de respuesta) por modelo y periodo.&lt;br /&gt;
* Revisar el '''historial de peticiones''' y el '''detalle de las conversaciones''' de cada sesión.&lt;br /&gt;
* Gestionar la '''base de conocimiento RAG''' (almacenes de documentos y loaders).&lt;br /&gt;
* Administrar los componentes del sistema: '''plataformas, agentes, orquestadores, usuarios''' y '''parámetros globales'''.&lt;br /&gt;
* Mantener '''objetos de datos estructurados''' (Metabase de datos).&lt;br /&gt;
&lt;br /&gt;
El manual recorre todas las pantallas en el orden en el que aparecen en el menú lateral.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 2. Acceso a la aplicación (Login) ===&lt;br /&gt;
&lt;br /&gt;
Al abrir &amp;lt;code&amp;gt;https://labvflow/vflow&amp;lt;/code&amp;gt; la aplicación redirige a la pantalla de inicio de sesión.&lt;br /&gt;
&lt;br /&gt;
[[File:00-login.png|1000px|center|Pantalla de login de VFlow]]&lt;br /&gt;
&lt;br /&gt;
'''Pasos para iniciar sesión:'''&lt;br /&gt;
&lt;br /&gt;
# Introduce tu '''Usuario''' en el primer campo.&lt;br /&gt;
# Introduce tu '''Contraseña'''.&lt;br /&gt;
# Pulsa el botón '''Entrar'''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;El acceso está restringido a usuarios expresamente autorizados. Si las credenciales son incorrectas, la aplicación no permitirá el acceso y permanecerá en esta pantalla.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Una vez autenticado, se accede al '''Panel''' (dashboard) principal.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 3. Estructura general y menú de navegación ===&lt;br /&gt;
&lt;br /&gt;
Tras iniciar sesión, la interfaz se organiza en dos zonas:&lt;br /&gt;
&lt;br /&gt;
* '''Barra lateral izquierda:''' menú de navegación por iconos. Al pasar el ratón se muestra el nombre de cada sección.&lt;br /&gt;
* '''Área de contenido:''' muestra la pantalla de la sección seleccionada.&lt;br /&gt;
&lt;br /&gt;
El menú lateral contiene las siguientes secciones (de arriba a abajo):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Icono !! Sección !! Descripción&lt;br /&gt;
|-&lt;br /&gt;
| 📊 || '''Panel''' || Analítica y métricas de uso (dashboard).&lt;br /&gt;
|-&lt;br /&gt;
| 📋 || '''Peticiones''' || Historial de todas las peticiones realizadas.&lt;br /&gt;
|-&lt;br /&gt;
| 💬 || '''Sesiones''' || Historial de sesiones y detalle de conversaciones.&lt;br /&gt;
|-&lt;br /&gt;
| 🗄️ || '''Gestión RAG''' || Documentos y versiones de los almacenes RAG.&lt;br /&gt;
|-&lt;br /&gt;
| 🛡️ || '''Administración''' || Panel de administración de todos los componentes.&lt;br /&gt;
|-&lt;br /&gt;
| ⚙️ || '''Configuración''' || Ajustes de la interfaz (tema, idioma, etiquetas).&lt;br /&gt;
|-&lt;br /&gt;
| ⤺ || '''Salir''' || Cierra la sesión.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
En la esquina inferior izquierda se muestra siempre la '''versión''' de la aplicación (v01.04.09) y el aviso de copyright.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 4. Panel (Dashboard) ===&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/dashboard&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es la pantalla de inicio. Muestra el análisis y las métricas de uso del sistema.&lt;br /&gt;
&lt;br /&gt;
[[File:01-dashboard.png|1000px|center|Panel de VFlow (dashboard)]]&lt;br /&gt;
&lt;br /&gt;
'''Elementos de la cabecera:'''&lt;br /&gt;
&lt;br /&gt;
* '''Total de tokens''', '''Total de peticiones''' y '''Chats únicos''': contadores globales del periodo seleccionado.&lt;br /&gt;
* '''Gráficas''' (desplegable): permite mostrar/ocultar las gráficas disponibles.&lt;br /&gt;
* '''Periodo''' (desplegable): filtra todas las métricas por el rango de fechas elegido.&lt;br /&gt;
* '''+ Añadir gráfica''': abre el asistente para crear una gráfica personalizada (ver 4.1).&lt;br /&gt;
&lt;br /&gt;
'''Gráficas incluidas por defecto:'''&lt;br /&gt;
&lt;br /&gt;
* '''Tokens por Modelo''' — tabla con el total de tokens consumidos por cada modelo.&lt;br /&gt;
* '''Evolución de Peticiones''' — evolución temporal del número de peticiones.&lt;br /&gt;
* '''Peticiones por Modelo''' — comparativa de peticiones por modelo.&lt;br /&gt;
* '''Evolución de Tokens''' — evolución temporal del consumo de tokens.&lt;br /&gt;
* '''Llamadas LLM por Día''', '''Tiempo de respuesta por modelo (ms)''' y '''Peticiones por hora del día''' (más abajo en la página).&lt;br /&gt;
&lt;br /&gt;
Cada gráfica dispone del botón '''⚙ Configuración de Gráficos''' y de una leyenda con los modelos, donde se puede quitar un modelo pulsando la '''✕''' de su etiqueta.&lt;br /&gt;
&lt;br /&gt;
==== 4.1 Añadir una gráfica personalizada ====&lt;br /&gt;
&lt;br /&gt;
Al pulsar '''+ Añadir gráfica''' se abre el asistente '''Crear gráfica personalizada''':&lt;br /&gt;
&lt;br /&gt;
[[File:dlg-anadir-grafica.png|1000px|center|Diálogo de creación de gráfica personalizada]]&lt;br /&gt;
&lt;br /&gt;
Opciones de configuración:&lt;br /&gt;
&lt;br /&gt;
* '''Nombre de la gráfica''': título que se mostrará.&lt;br /&gt;
* '''Fuente de datos''': origen de los datos (p. ej. ''Consumos (DAT_CONSUMOS)'').&lt;br /&gt;
* '''Agrupar por''': dimensión de agrupación (p. ej. ''Por Modelo'').&lt;br /&gt;
* '''Métrica''': valor a representar (p. ej. ''Número de llamadas'').&lt;br /&gt;
* '''Tipo de gráfica''': Barras, Horizontal, Línea, Área, Circular, Donut, KPI, Radar, Mapa de calor, Medidor, Histograma, Treemap o Dispersión.&lt;br /&gt;
* '''Color''', '''Estilo''' (mostrar leyenda, opacidad), rangos '''Y mínimo / Y máximo''' y '''Umbral de alerta'''.&lt;br /&gt;
&lt;br /&gt;
A la derecha se muestra una '''Vista previa''' en tiempo real. Pulsa '''Guardar gráfica''' para añadirla al panel o '''Cancelar''' para descartar.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Nota: la creación de gráficas personalizadas puede estar limitada por rol (ver [[#8.5 Configuración del sistema|8.5 Configuración del sistema → Overrides por rol]]).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 5. Peticiones ===&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/requests&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Muestra el '''Historial de Peticiones''': la lista completa de todas las peticiones realizadas al sistema.&lt;br /&gt;
&lt;br /&gt;
[[File:02-peticiones.png|1000px|center|Historial de Peticiones]]&lt;br /&gt;
&lt;br /&gt;
'''Filtros (parte superior):'''&lt;br /&gt;
&lt;br /&gt;
* '''Plataformas''', '''Agentes''', '''Orquestadores''': desplegables para filtrar por cada componente.&lt;br /&gt;
* '''Periodo''': filtra por rango de fechas.&lt;br /&gt;
&lt;br /&gt;
'''Tabla de Peticiones:'''&lt;br /&gt;
&lt;br /&gt;
* Campo de '''Búsqueda''' y selector de '''Registros por página''' (10 por defecto).&lt;br /&gt;
* Columnas: '''Message ID''', '''ID de sesión''', '''Fecha''', '''Pregunta''' y '''Respuesta'''.&lt;br /&gt;
* Indicador ''&amp;quot;Mostrando 1 a 10 de N resultados&amp;quot;'' y '''paginación''' en la parte inferior.&lt;br /&gt;
&lt;br /&gt;
Es la vista de referencia para auditar de forma tabular qué se preguntó, cuándo y qué respondió el agente.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 6. Sesiones ===&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/conversations&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Muestra el '''Historial de sesiones'''. Cada sesión agrupa los mensajes de una conversación.&lt;br /&gt;
&lt;br /&gt;
[[File:03-sesiones.png|1000px|center|Listado de Sesiones]]&lt;br /&gt;
&lt;br /&gt;
'''Panel izquierdo (listado):'''&lt;br /&gt;
&lt;br /&gt;
* Buscador '''&amp;quot;Buscar por ID de sesión o texto&amp;quot;'''.&lt;br /&gt;
* Botón '''Cargar más''' para paginar resultados.&lt;br /&gt;
* Cada tarjeta muestra: plataforma (p. ej. &amp;lt;code&amp;gt;omsui_1&amp;lt;/code&amp;gt;), fecha/hora, '''agente''' e '''ID de sesión''', y el número de mensajes (&amp;lt;code&amp;gt;N msg&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Filtros superiores: '''Plataformas''', '''Agentes''', '''Orquestadores''', '''Sesiones''' y '''Periodo'''.&lt;br /&gt;
&lt;br /&gt;
'''Panel derecho (detalle):''' al seleccionar una sesión se muestra la conversación completa en formato chat.&lt;br /&gt;
&lt;br /&gt;
[[File:sesion-detalle.png|1000px|center|Detalle de una sesión]]&lt;br /&gt;
&lt;br /&gt;
En el detalle se ven, en orden cronológico, los mensajes del '''usuario''' (a la derecha) y las respuestas del '''agente''' (a la izquierda, con el nombre del agente), junto con la cabecera de la sesión (plataforma, agente e ID).&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 7. Gestión RAG ===&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/rag-management&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Permite gestionar los documentos del sistema '''RAG''' (Retrieval-Augmented Generation), organizados por almacén (''store'').&lt;br /&gt;
&lt;br /&gt;
[[File:04-gestion-rag.png|1000px|center|Gestión RAG]]&lt;br /&gt;
&lt;br /&gt;
* Cada bloque corresponde a un '''RAG Store''' (p. ej. &amp;lt;code&amp;gt;ARA002&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;General&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DS_ARA&amp;lt;/code&amp;gt;) e indica su '''UUID''' y un estado ('''ACTUALIZADO''').&lt;br /&gt;
* Al expandir un store (flecha ▾) se muestran sus '''documentos/loaders'''. Para cada documento:&lt;br /&gt;
** Nombre del documento (p. ej. &amp;lt;code&amp;gt;ARA002_ld1&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''Versión activa''' (etiqueta, p. ej. &amp;lt;code&amp;gt;v3&amp;lt;/code&amp;gt;).&lt;br /&gt;
** Acciones: '''subir/actualizar''' (icono nube) y '''eliminar''' (icono papelera).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Esta pantalla es la vista operativa del contenido RAG. La definición de los stores y loaders se realiza en Administración (ver [[#8.6 RAG Stores|8.6]] y [[#8.7 RAG Loaders|8.7]]).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 8. Administración ===&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/admin&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Panel central para administrar y configurar todos los componentes del sistema VFlow. Se presenta como una cuadrícula de tarjetas de acceso.&lt;br /&gt;
&lt;br /&gt;
[[File:05-administracion.png|1000px|center|Panel de administración de VFlow]]&lt;br /&gt;
&lt;br /&gt;
Tarjetas disponibles:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Tarjeta !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Plataformas''' || Gestión de plataformas.&lt;br /&gt;
|-&lt;br /&gt;
| '''Agentes''' || Gestión de agentes.&lt;br /&gt;
|-&lt;br /&gt;
| '''Orquestadores''' || Gestión de orquestadores.&lt;br /&gt;
|-&lt;br /&gt;
| '''Usuarios''' || Gestión de usuarios.&lt;br /&gt;
|-&lt;br /&gt;
| '''Configuración del sistema''' || Parámetros y ajustes globales.&lt;br /&gt;
|-&lt;br /&gt;
| '''RAG Stores''' || Almacenes de documentos RAG.&lt;br /&gt;
|-&lt;br /&gt;
| '''RAG Loaders''' || Loaders de documentos RAG.&lt;br /&gt;
|-&lt;br /&gt;
| '''Metabase de datos''' || Objetos, campos y registros estructurados.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Aviso mostrado en la propia pantalla: ''&amp;quot;Desde este panel puedes administrar todas las configuraciones críticas del sistema VFlow. Asegúrate de tener los permisos necesarios antes de realizar cambios.&amp;quot;''&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En todas las subpantallas de administración el botón '''← Volver''' regresa a este panel.&lt;br /&gt;
&lt;br /&gt;
==== 8.1 Plataformas ====&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/admin/plataformas&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Listado de plataformas conectadas (p. ej. VIVAit, OmniSuite).&lt;br /&gt;
&lt;br /&gt;
[[File:adm-plataformas.png|1000px|center|Listado de Plataformas]]&lt;br /&gt;
&lt;br /&gt;
* Columnas: '''Nombre''', '''Identificador (UUID)''', '''Descripción''', '''Tipo''' (&amp;lt;code&amp;gt;vivait&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;omniSuite&amp;lt;/code&amp;gt;…), '''Max Sesiones''' y '''Acciones''' (editar ✏️ / eliminar 🗑️).&lt;br /&gt;
* Botón '''+ Crear''' para dar de alta una plataforma.&lt;br /&gt;
&lt;br /&gt;
'''Formulario de creación/edición:'''&lt;br /&gt;
&lt;br /&gt;
[[File:dlg-plataforma.png|1000px|center|Formulario de plataforma]]&lt;br /&gt;
&lt;br /&gt;
Campos:&lt;br /&gt;
&lt;br /&gt;
* '''Nombre''' ''(obligatorio)''.&lt;br /&gt;
* '''Tipo''' ''(obligatorio)'': selector de tipo de plataforma.&lt;br /&gt;
* '''Descripción'''.&lt;br /&gt;
* '''Max Sesiones Abiertas''', '''Max Peticiones Simultáneas''', '''Max Peticiones/Min/Sesión''': límites de capacidad.&lt;br /&gt;
&lt;br /&gt;
Pulsa '''Guardar''' para confirmar o '''Cancelar''' para descartar.&lt;br /&gt;
&lt;br /&gt;
==== 8.2 Agentes ====&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/admin/agentes&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Gestión de los agentes de IA.&lt;br /&gt;
&lt;br /&gt;
[[File:adm-agentes.png|1000px|center|Listado de Agentes]]&lt;br /&gt;
&lt;br /&gt;
* Columnas: '''Nombre''', '''Descripción''', '''Plataformas''', '''Orquestadores''', '''IDs entorno''' (PRO / PRE / PRU) y '''Acciones'''.&lt;br /&gt;
* Los '''IDs entorno''' muestran el identificador del agente en cada entorno: '''PRO''' (Producción), '''PRE''' (Preproducción) y '''PRU''' (Pruebas).&lt;br /&gt;
* Botón '''+ Nuevo Agente'''.&lt;br /&gt;
&lt;br /&gt;
'''Formulario de agente:'''&lt;br /&gt;
&lt;br /&gt;
[[File:dlg-agente.png|1000px|center|Formulario de nuevo agente]]&lt;br /&gt;
&lt;br /&gt;
Campos:&lt;br /&gt;
&lt;br /&gt;
* '''Nombre''' ''(obligatorio)''.&lt;br /&gt;
* '''ID Agente Producción''' ''(obligatorio)'', '''ID Agente Preproducción''', '''ID Agente Pruebas''': identificadores del agente en cada entorno.&lt;br /&gt;
* '''Descripción'''.&lt;br /&gt;
* '''Plataformas''' ''(obligatorio)'' y '''Orquestadores''' ''(obligatorio)'': selección del componente asociado.&lt;br /&gt;
* '''Timeout Respuesta (ms)''': tiempo máximo de espera de respuesta (30000 por defecto).&lt;br /&gt;
&lt;br /&gt;
Los campos marcados con &amp;lt;code&amp;gt;*&amp;lt;/code&amp;gt; son obligatorios. Pulsa '''Guardar'''.&lt;br /&gt;
&lt;br /&gt;
==== 8.3 Orquestadores ====&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/admin/orquestadores&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Gestión de los orquestadores (motores que enrutan/ejecutan las peticiones, p. ej. ''Flowise'', ''Bucle'').&lt;br /&gt;
&lt;br /&gt;
[[File:adm-orquestadores.png|1000px|center|Listado de Orquestadores]]&lt;br /&gt;
&lt;br /&gt;
* Columnas: '''Nombre''', '''Descripción''', '''Tipo''' (Bucle, Flowise…), '''URL Conexión''' y '''Acciones'''.&lt;br /&gt;
* Botón '''+ Crear'''.&lt;br /&gt;
&lt;br /&gt;
'''Formulario de orquestador:'''&lt;br /&gt;
&lt;br /&gt;
[[File:dlg-orquestador.png|1000px|center|Formulario de orquestador]]&lt;br /&gt;
&lt;br /&gt;
Campos:&lt;br /&gt;
&lt;br /&gt;
* '''Nombre''' ''(obligatorio)'' y '''Tipo''' ''(obligatorio)''.&lt;br /&gt;
* '''URL Conexión''' ''(obligatorio)'': endpoint del orquestador.&lt;br /&gt;
* '''URL Proxy (opcional)''', '''URL RAG'''.&lt;br /&gt;
* '''Cadena de Autenticación''': Bearer token o API Key.&lt;br /&gt;
* '''Usuario (opcional)''' y '''Contraseña (opcional)'''.&lt;br /&gt;
* '''Descripción'''.&lt;br /&gt;
&lt;br /&gt;
==== 8.4 Usuarios ====&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/admin/usuarios&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Gestión de las cuentas de usuario de VFlow.&lt;br /&gt;
&lt;br /&gt;
[[File:adm-usuarios.png|1000px|center|Listado de Usuarios]]&lt;br /&gt;
&lt;br /&gt;
* Columnas: '''Nombre''', '''Cuenta (login)''', '''Rol''' (Invitado, Usuario, Administrador), '''Activo''' y '''Acciones'''.&lt;br /&gt;
* Botón '''+ Crear'''.&lt;br /&gt;
&lt;br /&gt;
'''Formulario de usuario:'''&lt;br /&gt;
&lt;br /&gt;
[[File:dlg-usuario.png|1000px|center|Formulario de usuario]]&lt;br /&gt;
&lt;br /&gt;
Campos:&lt;br /&gt;
&lt;br /&gt;
* '''Nombre''' ''(obligatorio)'', '''Primer Apellido''', '''Segundo Apellido'''.&lt;br /&gt;
* '''Email''' ''(obligatorio)'', '''Móvil''', '''Cuenta (login)''' ''(obligatorio)''.&lt;br /&gt;
* '''Contraseña''' ''(obligatorio)''.&lt;br /&gt;
* '''Rol''' ''(obligatorio)'': perfil de permisos.&lt;br /&gt;
* '''Modo de Login''': ''Local'' (u otros modos disponibles, p. ej. SSO).&lt;br /&gt;
&lt;br /&gt;
==== 8.5 Configuración del sistema ====&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/admin/configuracion&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parámetros y ajustes globales del sistema. Está organizada en '''pestañas'''. Los cambios se confirman con el botón '''Guardar Configuración''' (abajo a la derecha).&lt;br /&gt;
&lt;br /&gt;
'''Pestaña Monitorización''' — estado general e incidencias recientes del frontend:&lt;br /&gt;
&lt;br /&gt;
[[File:adm-configuracion-sistema.png|1000px|center|Configuración del sistema — Monitorización]]&lt;br /&gt;
&lt;br /&gt;
Muestra tarjetas de estado: '''Estado''' (Backend disponible), '''Nivel de log''', '''Stores pendientes''', '''Histórico de sincronización''', '''Errores recientes''', '''Warnings recientes''' y '''Última comprobación'''. El botón '''Actualizar estado''' refresca los datos. Debajo se listan los ''stores pendientes'' de sincronización y el ''histórico de sincronización''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Indicación en pantalla: los logs de frontend se ven en &amp;lt;code&amp;gt;F12 &amp;gt; Consola&amp;lt;/code&amp;gt;; los del backend en &amp;lt;code&amp;gt;/opt/tomcat11/logs/catalina.out&amp;lt;/code&amp;gt;.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Pestaña Tarificación:'''&lt;br /&gt;
&lt;br /&gt;
[[File:cfg-tarificacion.png|1000px|center|Configuración del sistema — Tarificación]]&lt;br /&gt;
&lt;br /&gt;
* '''Peticiones por Bloque a Tarificar''' y '''Segundos por Bloque a Tarificar'''.&lt;br /&gt;
&lt;br /&gt;
'''Pestaña Configuración runtime''' — se guarda en &amp;lt;code&amp;gt;vflow-config.json&amp;lt;/code&amp;gt; y se aplica al refrescar la aplicación:&lt;br /&gt;
&lt;br /&gt;
[[File:cfg-configuracion.png|1000px|center|Configuración del sistema — Configuración runtime]]&lt;br /&gt;
&lt;br /&gt;
* '''URL de la API backend''' (p. ej. &amp;lt;code&amp;gt;/vflow/api&amp;lt;/code&amp;gt;): ruta que usa el frontend para llamar al backend.&lt;br /&gt;
* '''Tamaño de página de sesiones''': nº de sesiones por tanda en la pantalla de conversaciones.&lt;br /&gt;
* '''Nivel de log''': DEBUG muestra todo, ERROR solo fallos.&lt;br /&gt;
* '''Overrides por rol''': permite ajustar 2FA y la '''visibilidad del dashboard''' por perfil (Administrador, Invitado, Usuario), incluyendo qué gráficas ve cada rol y si puede crear gráficas personalizadas.&lt;br /&gt;
&lt;br /&gt;
'''Pestaña Rutas de Archivos''' — configuradas en servidor, '''no editables''' desde la interfaz:&lt;br /&gt;
&lt;br /&gt;
[[File:cfg-rutas.png|1000px|center|Configuración del sistema — Rutas de Archivos]]&lt;br /&gt;
&lt;br /&gt;
* '''Ruta de Documentos''' (p. ej. &amp;lt;code&amp;gt;/etc/MDtel/vFlow/Documentos/&amp;lt;/code&amp;gt;).&lt;br /&gt;
* '''Ruta API Loader''' (p. ej. &amp;lt;code&amp;gt;/var/www/html/storages/&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
'''Pestaña Timeouts de Sesión (segundos):'''&lt;br /&gt;
&lt;br /&gt;
[[File:cfg-timeouts.png|1000px|center|Configuración del sistema — Timeouts de Sesión]]&lt;br /&gt;
&lt;br /&gt;
* '''Dormir Sesión''', '''Sesión Voz''', '''Sesión Chat''' y '''Sesión Email''': tiempos de expiración por tipo de sesión.&lt;br /&gt;
&lt;br /&gt;
==== 8.6 RAG Stores ====&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/admin/rag-stores&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Gestión de los almacenes de documentos RAG.&lt;br /&gt;
&lt;br /&gt;
[[File:adm-rag-stores.png|1000px|center|Listado de RAG Stores]]&lt;br /&gt;
&lt;br /&gt;
* Columnas: '''Nombre''', '''Descripción''', '''Plataformas''', '''ID Store Producción''', '''ID Store Preproducción''', '''ID Store Pruebas''' y '''Acciones'''.&lt;br /&gt;
* Botón '''+ Nuevo RAG Store'''.&lt;br /&gt;
&lt;br /&gt;
'''Formulario de RAG Store:'''&lt;br /&gt;
&lt;br /&gt;
[[File:dlg-ragstore.png|1000px|center|Formulario de RAG Store]]&lt;br /&gt;
&lt;br /&gt;
Campos:&lt;br /&gt;
&lt;br /&gt;
* '''Nombre''' ''(obligatorio)'', '''Plataformas''' ''(obligatorio)'', '''Orquestadores''' ''(obligatorio)''.&lt;br /&gt;
* '''Descripción'''.&lt;br /&gt;
* '''ID Store Producción''' ''(obligatorio)'', '''ID Store Preproducción''', '''ID Store Pruebas''': identificadores del Document Store en cada entorno.&lt;br /&gt;
&lt;br /&gt;
==== 8.7 RAG Loaders ====&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/admin/rag-loaders&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Gestión de los ''loaders'' (cargadores de documentos) asociados a los RAG Stores.&lt;br /&gt;
&lt;br /&gt;
[[File:adm-rag-loaders.png|1000px|center|Listado de RAG Loaders]]&lt;br /&gt;
&lt;br /&gt;
* Columnas: '''Nombre''', '''RAG Stores''', '''Interno (gestionado por VFlow)''', '''Configuración JSON''' y '''Acciones''' (eliminar).&lt;br /&gt;
* Botón '''+ Añadir loader'''.&lt;br /&gt;
&lt;br /&gt;
'''Formulario de loader:'''&lt;br /&gt;
&lt;br /&gt;
[[File:dlg-ragloader.png|1000px|center|Formulario de añadir loader]]&lt;br /&gt;
&lt;br /&gt;
Campos:&lt;br /&gt;
&lt;br /&gt;
* '''Nombre''' ''(obligatorio)''.&lt;br /&gt;
* '''Descripción'''.&lt;br /&gt;
* '''Nombre del archivo''' ''(obligatorio)''.&lt;br /&gt;
* '''Seleccione un RAG Store''' ''(obligatorio)'': store al que se asocia.&lt;br /&gt;
* '''Contenido detectado del archivo base''': área de texto con el contenido.&lt;br /&gt;
&lt;br /&gt;
Pulsa '''Crear''' para añadirlo.&lt;br /&gt;
&lt;br /&gt;
==== 8.8 Metabase de datos ====&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/metadata&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Gestión de '''objetos de datos estructurados''' (tablas de datos que puede usar el sistema: clientes, doctores, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:adm-metabase.png|1000px|center|Metabase de datos]]&lt;br /&gt;
&lt;br /&gt;
* Cada tarjeta representa un '''objeto''' (p. ej. ''Clientes'', ''Doctores'') e indica su descripción, el '''JSON''' asociado y la '''Ruta'''.&lt;br /&gt;
* Acciones por objeto: '''Editar objeto''' (definición/estructura) y '''Editar/Ver datos''' (registros).&lt;br /&gt;
* Botones superiores: '''↻''' (refrescar) y '''+ Nuevo objeto'''.&lt;br /&gt;
&lt;br /&gt;
'''Nuevo objeto / Editar objeto''' — define la estructura del objeto:&lt;br /&gt;
&lt;br /&gt;
[[File:dlg-metaobjeto.png|1000px|center|Diálogo de nuevo objeto]]&lt;br /&gt;
&lt;br /&gt;
Campos:&lt;br /&gt;
&lt;br /&gt;
* '''Nombre''' ''(obligatorio)'', '''Descripción'''.&lt;br /&gt;
* '''Nombre del JSON''' y '''Ruta de upload'''.&lt;br /&gt;
* '''Campos''': definición de los campos del objeto (botón '''+ Añadir campo''').&lt;br /&gt;
* A la derecha se muestra una vista previa del '''JSON''' resultante.&lt;br /&gt;
&lt;br /&gt;
'''Editar/Ver datos''' — gestiona los registros del objeto:&lt;br /&gt;
&lt;br /&gt;
[[File:meta-ver-datos.png|1000px|center|Vista de datos de un objeto (registros)]]&lt;br /&gt;
&lt;br /&gt;
* Tabla paginada con los registros y sus columnas (Id, Nombre, Fecha, Dirección, Localidad, Teléfono, Email, etc.).&lt;br /&gt;
* Acciones por fila: '''editar''' ✏️ y '''eliminar''' 🗑️.&lt;br /&gt;
* Botones superiores: '''← Volver''', '''↻''' refrescar, '''⤒ Importar''', '''Generar JSON''', '''Eliminar todo''' y '''+ Nuevo registro'''.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 9. Configuración de la interfaz ===&lt;br /&gt;
&lt;br /&gt;
Al pulsar el icono '''⚙ Configuración''' de la barra lateral (parte inferior) se despliega un pequeño menú de ajustes de la interfaz:&lt;br /&gt;
&lt;br /&gt;
[[File:menu-configuracion.png|1000px|center|Menú de configuración de la interfaz]]&lt;br /&gt;
&lt;br /&gt;
Opciones:&lt;br /&gt;
&lt;br /&gt;
* '''Tema Claro / Oscuro''': interruptor para cambiar el aspecto visual.&lt;br /&gt;
* '''Idioma''': selector de idioma (p. ej. '''ES''').&lt;br /&gt;
* '''Etiquetas de navegación''': interruptor para mostrar u ocultar los textos junto a los iconos del menú lateral.&lt;br /&gt;
&lt;br /&gt;
Estos ajustes afectan únicamente a la visualización de la interfaz para el usuario actual.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 10. Salir de la aplicación ===&lt;br /&gt;
&lt;br /&gt;
Para cerrar la sesión, pulsa el icono '''⤺ Salir''' situado en la parte inferior de la barra lateral. La aplicación cerrará la sesión y volverá a la pantalla de [[#2. Acceso a la aplicación (Login)|Login]].&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Anexo — Rutas de la aplicación ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Sección !! Ruta&lt;br /&gt;
|-&lt;br /&gt;
| Login || &amp;lt;code&amp;gt;/vflow/login&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Panel || &amp;lt;code&amp;gt;/vflow/dashboard&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Peticiones || &amp;lt;code&amp;gt;/vflow/requests&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Sesiones || &amp;lt;code&amp;gt;/vflow/conversations&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Gestión RAG || &amp;lt;code&amp;gt;/vflow/rag-management&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Administración || &amp;lt;code&amp;gt;/vflow/admin&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Plataformas || &amp;lt;code&amp;gt;/vflow/admin/plataformas&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Agentes || &amp;lt;code&amp;gt;/vflow/admin/agentes&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Orquestadores || &amp;lt;code&amp;gt;/vflow/admin/orquestadores&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Usuarios || &amp;lt;code&amp;gt;/vflow/admin/usuarios&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Configuración del sistema || &amp;lt;code&amp;gt;/vflow/admin/configuracion&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| RAG Stores || &amp;lt;code&amp;gt;/vflow/admin/rag-stores&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| RAG Loaders || &amp;lt;code&amp;gt;/vflow/admin/rag-loaders&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Metabase de datos || &amp;lt;code&amp;gt;/vflow/metadata&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
''Manual generado para su publicación en MediaWiki. Las imágenes se encuentran en la carpeta &amp;lt;code&amp;gt;img/&amp;lt;/code&amp;gt;.''&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Portal_administracion_de_vFlow_v01.04&amp;diff=19149</id>
		<title>Portal administracion de vFlow v01.04</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Portal_administracion_de_vFlow_v01.04&amp;diff=19149"/>
		<updated>2026-07-06T12:12:33Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Manual de usuario — VFlow (Portal de IA) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Versión de la aplicación:''' v01.04.09 · © 2026 MDtel&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 1. Introducción ===&lt;br /&gt;
&lt;br /&gt;
'''VFlow''' es el portal de administración y analítica de los agentes de IA de MDtel. Desde una única interfaz web permite:&lt;br /&gt;
&lt;br /&gt;
* Consultar '''métricas de uso''' (tokens, peticiones, sesiones y tiempos de respuesta) por modelo y periodo.&lt;br /&gt;
* Revisar el '''historial de peticiones''' y el '''detalle de las conversaciones''' de cada sesión.&lt;br /&gt;
* Gestionar la '''base de conocimiento RAG''' (almacenes de documentos y loaders).&lt;br /&gt;
* Administrar los componentes del sistema: '''plataformas, agentes, orquestadores, usuarios''' y '''parámetros globales'''.&lt;br /&gt;
* Mantener '''objetos de datos estructurados''' (Metabase de datos).&lt;br /&gt;
&lt;br /&gt;
El manual recorre todas las pantallas en el orden en el que aparecen en el menú lateral.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 2. Acceso a la aplicación (Login) ===&lt;br /&gt;
&lt;br /&gt;
Al abrir &amp;lt;code&amp;gt;https://labvflow/vflow&amp;lt;/code&amp;gt; la aplicación redirige a la pantalla de inicio de sesión.&lt;br /&gt;
&lt;br /&gt;
[[File:00-login.png|1000px|Pantalla de login de VFlow]]&lt;br /&gt;
&lt;br /&gt;
'''Pasos para iniciar sesión:'''&lt;br /&gt;
&lt;br /&gt;
# Introduce tu '''Usuario''' en el primer campo.&lt;br /&gt;
# Introduce tu '''Contraseña'''.&lt;br /&gt;
# Pulsa el botón '''Entrar'''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;El acceso está restringido a usuarios expresamente autorizados. Si las credenciales son incorrectas, la aplicación no permitirá el acceso y permanecerá en esta pantalla.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Una vez autenticado, se accede al '''Panel''' (dashboard) principal.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 3. Estructura general y menú de navegación ===&lt;br /&gt;
&lt;br /&gt;
Tras iniciar sesión, la interfaz se organiza en dos zonas:&lt;br /&gt;
&lt;br /&gt;
* '''Barra lateral izquierda:''' menú de navegación por iconos. Al pasar el ratón se muestra el nombre de cada sección.&lt;br /&gt;
* '''Área de contenido:''' muestra la pantalla de la sección seleccionada.&lt;br /&gt;
&lt;br /&gt;
El menú lateral contiene las siguientes secciones (de arriba a abajo):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Icono !! Sección !! Descripción&lt;br /&gt;
|-&lt;br /&gt;
| 📊 || '''Panel''' || Analítica y métricas de uso (dashboard).&lt;br /&gt;
|-&lt;br /&gt;
| 📋 || '''Peticiones''' || Historial de todas las peticiones realizadas.&lt;br /&gt;
|-&lt;br /&gt;
| 💬 || '''Sesiones''' || Historial de sesiones y detalle de conversaciones.&lt;br /&gt;
|-&lt;br /&gt;
| 🗄️ || '''Gestión RAG''' || Documentos y versiones de los almacenes RAG.&lt;br /&gt;
|-&lt;br /&gt;
| 🛡️ || '''Administración''' || Panel de administración de todos los componentes.&lt;br /&gt;
|-&lt;br /&gt;
| ⚙️ || '''Configuración''' || Ajustes de la interfaz (tema, idioma, etiquetas).&lt;br /&gt;
|-&lt;br /&gt;
| ⤺ || '''Salir''' || Cierra la sesión.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
En la esquina inferior izquierda se muestra siempre la '''versión''' de la aplicación (v01.04.09) y el aviso de copyright.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 4. Panel (Dashboard) ===&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/dashboard&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es la pantalla de inicio. Muestra el análisis y las métricas de uso del sistema.&lt;br /&gt;
&lt;br /&gt;
[[File:01-dashboard.png|1000px|Panel de VFlow (dashboard)]]&lt;br /&gt;
&lt;br /&gt;
'''Elementos de la cabecera:'''&lt;br /&gt;
&lt;br /&gt;
* '''Total de tokens''', '''Total de peticiones''' y '''Chats únicos''': contadores globales del periodo seleccionado.&lt;br /&gt;
* '''Gráficas''' (desplegable): permite mostrar/ocultar las gráficas disponibles.&lt;br /&gt;
* '''Periodo''' (desplegable): filtra todas las métricas por el rango de fechas elegido.&lt;br /&gt;
* '''+ Añadir gráfica''': abre el asistente para crear una gráfica personalizada (ver 4.1).&lt;br /&gt;
&lt;br /&gt;
'''Gráficas incluidas por defecto:'''&lt;br /&gt;
&lt;br /&gt;
* '''Tokens por Modelo''' — tabla con el total de tokens consumidos por cada modelo.&lt;br /&gt;
* '''Evolución de Peticiones''' — evolución temporal del número de peticiones.&lt;br /&gt;
* '''Peticiones por Modelo''' — comparativa de peticiones por modelo.&lt;br /&gt;
* '''Evolución de Tokens''' — evolución temporal del consumo de tokens.&lt;br /&gt;
* '''Llamadas LLM por Día''', '''Tiempo de respuesta por modelo (ms)''' y '''Peticiones por hora del día''' (más abajo en la página).&lt;br /&gt;
&lt;br /&gt;
Cada gráfica dispone del botón '''⚙ Configuración de Gráficos''' y de una leyenda con los modelos, donde se puede quitar un modelo pulsando la '''✕''' de su etiqueta.&lt;br /&gt;
&lt;br /&gt;
==== 4.1 Añadir una gráfica personalizada ====&lt;br /&gt;
&lt;br /&gt;
Al pulsar '''+ Añadir gráfica''' se abre el asistente '''Crear gráfica personalizada''':&lt;br /&gt;
&lt;br /&gt;
[[File:dlg-anadir-grafica.png|1000px|Diálogo de creación de gráfica personalizada]]&lt;br /&gt;
&lt;br /&gt;
Opciones de configuración:&lt;br /&gt;
&lt;br /&gt;
* '''Nombre de la gráfica''': título que se mostrará.&lt;br /&gt;
* '''Fuente de datos''': origen de los datos (p. ej. ''Consumos (DAT_CONSUMOS)'').&lt;br /&gt;
* '''Agrupar por''': dimensión de agrupación (p. ej. ''Por Modelo'').&lt;br /&gt;
* '''Métrica''': valor a representar (p. ej. ''Número de llamadas'').&lt;br /&gt;
* '''Tipo de gráfica''': Barras, Horizontal, Línea, Área, Circular, Donut, KPI, Radar, Mapa de calor, Medidor, Histograma, Treemap o Dispersión.&lt;br /&gt;
* '''Color''', '''Estilo''' (mostrar leyenda, opacidad), rangos '''Y mínimo / Y máximo''' y '''Umbral de alerta'''.&lt;br /&gt;
&lt;br /&gt;
A la derecha se muestra una '''Vista previa''' en tiempo real. Pulsa '''Guardar gráfica''' para añadirla al panel o '''Cancelar''' para descartar.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Nota: la creación de gráficas personalizadas puede estar limitada por rol (ver [[#8.5 Configuración del sistema|8.5 Configuración del sistema → Overrides por rol]]).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 5. Peticiones ===&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/requests&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Muestra el '''Historial de Peticiones''': la lista completa de todas las peticiones realizadas al sistema.&lt;br /&gt;
&lt;br /&gt;
[[File:02-peticiones.png|1000px|Historial de Peticiones]]&lt;br /&gt;
&lt;br /&gt;
'''Filtros (parte superior):'''&lt;br /&gt;
&lt;br /&gt;
* '''Plataformas''', '''Agentes''', '''Orquestadores''': desplegables para filtrar por cada componente.&lt;br /&gt;
* '''Periodo''': filtra por rango de fechas.&lt;br /&gt;
&lt;br /&gt;
'''Tabla de Peticiones:'''&lt;br /&gt;
&lt;br /&gt;
* Campo de '''Búsqueda''' y selector de '''Registros por página''' (10 por defecto).&lt;br /&gt;
* Columnas: '''Message ID''', '''ID de sesión''', '''Fecha''', '''Pregunta''' y '''Respuesta'''.&lt;br /&gt;
* Indicador ''&amp;quot;Mostrando 1 a 10 de N resultados&amp;quot;'' y '''paginación''' en la parte inferior.&lt;br /&gt;
&lt;br /&gt;
Es la vista de referencia para auditar de forma tabular qué se preguntó, cuándo y qué respondió el agente.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 6. Sesiones ===&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/conversations&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Muestra el '''Historial de sesiones'''. Cada sesión agrupa los mensajes de una conversación.&lt;br /&gt;
&lt;br /&gt;
[[File:03-sesiones.png|1000px|Listado de Sesiones]]&lt;br /&gt;
&lt;br /&gt;
'''Panel izquierdo (listado):'''&lt;br /&gt;
&lt;br /&gt;
* Buscador '''&amp;quot;Buscar por ID de sesión o texto&amp;quot;'''.&lt;br /&gt;
* Botón '''Cargar más''' para paginar resultados.&lt;br /&gt;
* Cada tarjeta muestra: plataforma (p. ej. &amp;lt;code&amp;gt;omsui_1&amp;lt;/code&amp;gt;), fecha/hora, '''agente''' e '''ID de sesión''', y el número de mensajes (&amp;lt;code&amp;gt;N msg&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Filtros superiores: '''Plataformas''', '''Agentes''', '''Orquestadores''', '''Sesiones''' y '''Periodo'''.&lt;br /&gt;
&lt;br /&gt;
'''Panel derecho (detalle):''' al seleccionar una sesión se muestra la conversación completa en formato chat.&lt;br /&gt;
&lt;br /&gt;
[[File:sesion-detalle.png|1000px|Detalle de una sesión]]&lt;br /&gt;
&lt;br /&gt;
En el detalle se ven, en orden cronológico, los mensajes del '''usuario''' (a la derecha) y las respuestas del '''agente''' (a la izquierda, con el nombre del agente), junto con la cabecera de la sesión (plataforma, agente e ID).&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 7. Gestión RAG ===&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/rag-management&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Permite gestionar los documentos del sistema '''RAG''' (Retrieval-Augmented Generation), organizados por almacén (''store'').&lt;br /&gt;
&lt;br /&gt;
[[File:04-gestion-rag.png|1000px|Gestión RAG]]&lt;br /&gt;
&lt;br /&gt;
* Cada bloque corresponde a un '''RAG Store''' (p. ej. &amp;lt;code&amp;gt;ARA002&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;General&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DS_ARA&amp;lt;/code&amp;gt;) e indica su '''UUID''' y un estado ('''ACTUALIZADO''').&lt;br /&gt;
* Al expandir un store (flecha ▾) se muestran sus '''documentos/loaders'''. Para cada documento:&lt;br /&gt;
** Nombre del documento (p. ej. &amp;lt;code&amp;gt;ARA002_ld1&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''Versión activa''' (etiqueta, p. ej. &amp;lt;code&amp;gt;v3&amp;lt;/code&amp;gt;).&lt;br /&gt;
** Acciones: '''subir/actualizar''' (icono nube) y '''eliminar''' (icono papelera).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Esta pantalla es la vista operativa del contenido RAG. La definición de los stores y loaders se realiza en Administración (ver [[#8.6 RAG Stores|8.6]] y [[#8.7 RAG Loaders|8.7]]).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 8. Administración ===&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/admin&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Panel central para administrar y configurar todos los componentes del sistema VFlow. Se presenta como una cuadrícula de tarjetas de acceso.&lt;br /&gt;
&lt;br /&gt;
[[File:05-administracion.png|1000px|Panel de administración de VFlow]]&lt;br /&gt;
&lt;br /&gt;
Tarjetas disponibles:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Tarjeta !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Plataformas''' || Gestión de plataformas.&lt;br /&gt;
|-&lt;br /&gt;
| '''Agentes''' || Gestión de agentes.&lt;br /&gt;
|-&lt;br /&gt;
| '''Orquestadores''' || Gestión de orquestadores.&lt;br /&gt;
|-&lt;br /&gt;
| '''Usuarios''' || Gestión de usuarios.&lt;br /&gt;
|-&lt;br /&gt;
| '''Configuración del sistema''' || Parámetros y ajustes globales.&lt;br /&gt;
|-&lt;br /&gt;
| '''RAG Stores''' || Almacenes de documentos RAG.&lt;br /&gt;
|-&lt;br /&gt;
| '''RAG Loaders''' || Loaders de documentos RAG.&lt;br /&gt;
|-&lt;br /&gt;
| '''Metabase de datos''' || Objetos, campos y registros estructurados.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Aviso mostrado en la propia pantalla: ''&amp;quot;Desde este panel puedes administrar todas las configuraciones críticas del sistema VFlow. Asegúrate de tener los permisos necesarios antes de realizar cambios.&amp;quot;''&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En todas las subpantallas de administración el botón '''← Volver''' regresa a este panel.&lt;br /&gt;
&lt;br /&gt;
==== 8.1 Plataformas ====&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/admin/plataformas&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Listado de plataformas conectadas (p. ej. VIVAit, OmniSuite).&lt;br /&gt;
&lt;br /&gt;
[[File:adm-plataformas.png|1000px|Listado de Plataformas]]&lt;br /&gt;
&lt;br /&gt;
* Columnas: '''Nombre''', '''Identificador (UUID)''', '''Descripción''', '''Tipo''' (&amp;lt;code&amp;gt;vivait&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;omniSuite&amp;lt;/code&amp;gt;…), '''Max Sesiones''' y '''Acciones''' (editar ✏️ / eliminar 🗑️).&lt;br /&gt;
* Botón '''+ Crear''' para dar de alta una plataforma.&lt;br /&gt;
&lt;br /&gt;
'''Formulario de creación/edición:'''&lt;br /&gt;
&lt;br /&gt;
[[File:dlg-plataforma.png|1000px|Formulario de plataforma]]&lt;br /&gt;
&lt;br /&gt;
Campos:&lt;br /&gt;
&lt;br /&gt;
* '''Nombre''' ''(obligatorio)''.&lt;br /&gt;
* '''Tipo''' ''(obligatorio)'': selector de tipo de plataforma.&lt;br /&gt;
* '''Descripción'''.&lt;br /&gt;
* '''Max Sesiones Abiertas''', '''Max Peticiones Simultáneas''', '''Max Peticiones/Min/Sesión''': límites de capacidad.&lt;br /&gt;
&lt;br /&gt;
Pulsa '''Guardar''' para confirmar o '''Cancelar''' para descartar.&lt;br /&gt;
&lt;br /&gt;
==== 8.2 Agentes ====&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/admin/agentes&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Gestión de los agentes de IA.&lt;br /&gt;
&lt;br /&gt;
[[File:adm-agentes.png|1000px|Listado de Agentes]]&lt;br /&gt;
&lt;br /&gt;
* Columnas: '''Nombre''', '''Descripción''', '''Plataformas''', '''Orquestadores''', '''IDs entorno''' (PRO / PRE / PRU) y '''Acciones'''.&lt;br /&gt;
* Los '''IDs entorno''' muestran el identificador del agente en cada entorno: '''PRO''' (Producción), '''PRE''' (Preproducción) y '''PRU''' (Pruebas).&lt;br /&gt;
* Botón '''+ Nuevo Agente'''.&lt;br /&gt;
&lt;br /&gt;
'''Formulario de agente:'''&lt;br /&gt;
&lt;br /&gt;
[[File:dlg-agente.png|1000px|Formulario de nuevo agente]]&lt;br /&gt;
&lt;br /&gt;
Campos:&lt;br /&gt;
&lt;br /&gt;
* '''Nombre''' ''(obligatorio)''.&lt;br /&gt;
* '''ID Agente Producción''' ''(obligatorio)'', '''ID Agente Preproducción''', '''ID Agente Pruebas''': identificadores del agente en cada entorno.&lt;br /&gt;
* '''Descripción'''.&lt;br /&gt;
* '''Plataformas''' ''(obligatorio)'' y '''Orquestadores''' ''(obligatorio)'': selección del componente asociado.&lt;br /&gt;
* '''Timeout Respuesta (ms)''': tiempo máximo de espera de respuesta (30000 por defecto).&lt;br /&gt;
&lt;br /&gt;
Los campos marcados con &amp;lt;code&amp;gt;*&amp;lt;/code&amp;gt; son obligatorios. Pulsa '''Guardar'''.&lt;br /&gt;
&lt;br /&gt;
==== 8.3 Orquestadores ====&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/admin/orquestadores&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Gestión de los orquestadores (motores que enrutan/ejecutan las peticiones, p. ej. ''Flowise'', ''Bucle'').&lt;br /&gt;
&lt;br /&gt;
[[File:adm-orquestadores.png|1000px|Listado de Orquestadores]]&lt;br /&gt;
&lt;br /&gt;
* Columnas: '''Nombre''', '''Descripción''', '''Tipo''' (Bucle, Flowise…), '''URL Conexión''' y '''Acciones'''.&lt;br /&gt;
* Botón '''+ Crear'''.&lt;br /&gt;
&lt;br /&gt;
'''Formulario de orquestador:'''&lt;br /&gt;
&lt;br /&gt;
[[File:dlg-orquestador.png|1000px|Formulario de orquestador]]&lt;br /&gt;
&lt;br /&gt;
Campos:&lt;br /&gt;
&lt;br /&gt;
* '''Nombre''' ''(obligatorio)'' y '''Tipo''' ''(obligatorio)''.&lt;br /&gt;
* '''URL Conexión''' ''(obligatorio)'': endpoint del orquestador.&lt;br /&gt;
* '''URL Proxy (opcional)''', '''URL RAG'''.&lt;br /&gt;
* '''Cadena de Autenticación''': Bearer token o API Key.&lt;br /&gt;
* '''Usuario (opcional)''' y '''Contraseña (opcional)'''.&lt;br /&gt;
* '''Descripción'''.&lt;br /&gt;
&lt;br /&gt;
==== 8.4 Usuarios ====&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/admin/usuarios&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Gestión de las cuentas de usuario de VFlow.&lt;br /&gt;
&lt;br /&gt;
[[File:adm-usuarios.png|1000px|Listado de Usuarios]]&lt;br /&gt;
&lt;br /&gt;
* Columnas: '''Nombre''', '''Cuenta (login)''', '''Rol''' (Invitado, Usuario, Administrador), '''Activo''' y '''Acciones'''.&lt;br /&gt;
* Botón '''+ Crear'''.&lt;br /&gt;
&lt;br /&gt;
'''Formulario de usuario:'''&lt;br /&gt;
&lt;br /&gt;
[[File:dlg-usuario.png|1000px|Formulario de usuario]]&lt;br /&gt;
&lt;br /&gt;
Campos:&lt;br /&gt;
&lt;br /&gt;
* '''Nombre''' ''(obligatorio)'', '''Primer Apellido''', '''Segundo Apellido'''.&lt;br /&gt;
* '''Email''' ''(obligatorio)'', '''Móvil''', '''Cuenta (login)''' ''(obligatorio)''.&lt;br /&gt;
* '''Contraseña''' ''(obligatorio)''.&lt;br /&gt;
* '''Rol''' ''(obligatorio)'': perfil de permisos.&lt;br /&gt;
* '''Modo de Login''': ''Local'' (u otros modos disponibles, p. ej. SSO).&lt;br /&gt;
&lt;br /&gt;
==== 8.5 Configuración del sistema ====&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/admin/configuracion&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parámetros y ajustes globales del sistema. Está organizada en '''pestañas'''. Los cambios se confirman con el botón '''Guardar Configuración''' (abajo a la derecha).&lt;br /&gt;
&lt;br /&gt;
'''Pestaña Monitorización''' — estado general e incidencias recientes del frontend:&lt;br /&gt;
&lt;br /&gt;
[[File:adm-configuracion-sistema.png|1000px|Configuración del sistema — Monitorización]]&lt;br /&gt;
&lt;br /&gt;
Muestra tarjetas de estado: '''Estado''' (Backend disponible), '''Nivel de log''', '''Stores pendientes''', '''Histórico de sincronización''', '''Errores recientes''', '''Warnings recientes''' y '''Última comprobación'''. El botón '''Actualizar estado''' refresca los datos. Debajo se listan los ''stores pendientes'' de sincronización y el ''histórico de sincronización''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Indicación en pantalla: los logs de frontend se ven en &amp;lt;code&amp;gt;F12 &amp;gt; Consola&amp;lt;/code&amp;gt;; los del backend en &amp;lt;code&amp;gt;/opt/tomcat11/logs/catalina.out&amp;lt;/code&amp;gt;.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Pestaña Tarificación:'''&lt;br /&gt;
&lt;br /&gt;
[[File:cfg-tarificacion.png|1000px|Configuración del sistema — Tarificación]]&lt;br /&gt;
&lt;br /&gt;
* '''Peticiones por Bloque a Tarificar''' y '''Segundos por Bloque a Tarificar'''.&lt;br /&gt;
&lt;br /&gt;
'''Pestaña Configuración runtime''' — se guarda en &amp;lt;code&amp;gt;vflow-config.json&amp;lt;/code&amp;gt; y se aplica al refrescar la aplicación:&lt;br /&gt;
&lt;br /&gt;
[[File:cfg-configuracion.png|1000px|Configuración del sistema — Configuración runtime]]&lt;br /&gt;
&lt;br /&gt;
* '''URL de la API backend''' (p. ej. &amp;lt;code&amp;gt;/vflow/api&amp;lt;/code&amp;gt;): ruta que usa el frontend para llamar al backend.&lt;br /&gt;
* '''Tamaño de página de sesiones''': nº de sesiones por tanda en la pantalla de conversaciones.&lt;br /&gt;
* '''Nivel de log''': DEBUG muestra todo, ERROR solo fallos.&lt;br /&gt;
* '''Overrides por rol''': permite ajustar 2FA y la '''visibilidad del dashboard''' por perfil (Administrador, Invitado, Usuario), incluyendo qué gráficas ve cada rol y si puede crear gráficas personalizadas.&lt;br /&gt;
&lt;br /&gt;
'''Pestaña Rutas de Archivos''' — configuradas en servidor, '''no editables''' desde la interfaz:&lt;br /&gt;
&lt;br /&gt;
[[File:cfg-rutas.png|1000px|Configuración del sistema — Rutas de Archivos]]&lt;br /&gt;
&lt;br /&gt;
* '''Ruta de Documentos''' (p. ej. &amp;lt;code&amp;gt;/etc/MDtel/vFlow/Documentos/&amp;lt;/code&amp;gt;).&lt;br /&gt;
* '''Ruta API Loader''' (p. ej. &amp;lt;code&amp;gt;/var/www/html/storages/&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
'''Pestaña Timeouts de Sesión (segundos):'''&lt;br /&gt;
&lt;br /&gt;
[[File:cfg-timeouts.png|1000px|Configuración del sistema — Timeouts de Sesión]]&lt;br /&gt;
&lt;br /&gt;
* '''Dormir Sesión''', '''Sesión Voz''', '''Sesión Chat''' y '''Sesión Email''': tiempos de expiración por tipo de sesión.&lt;br /&gt;
&lt;br /&gt;
==== 8.6 RAG Stores ====&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/admin/rag-stores&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Gestión de los almacenes de documentos RAG.&lt;br /&gt;
&lt;br /&gt;
[[File:adm-rag-stores.png|1000px|Listado de RAG Stores]]&lt;br /&gt;
&lt;br /&gt;
* Columnas: '''Nombre''', '''Descripción''', '''Plataformas''', '''ID Store Producción''', '''ID Store Preproducción''', '''ID Store Pruebas''' y '''Acciones'''.&lt;br /&gt;
* Botón '''+ Nuevo RAG Store'''.&lt;br /&gt;
&lt;br /&gt;
'''Formulario de RAG Store:'''&lt;br /&gt;
&lt;br /&gt;
[[File:dlg-ragstore.png|1000px|Formulario de RAG Store]]&lt;br /&gt;
&lt;br /&gt;
Campos:&lt;br /&gt;
&lt;br /&gt;
* '''Nombre''' ''(obligatorio)'', '''Plataformas''' ''(obligatorio)'', '''Orquestadores''' ''(obligatorio)''.&lt;br /&gt;
* '''Descripción'''.&lt;br /&gt;
* '''ID Store Producción''' ''(obligatorio)'', '''ID Store Preproducción''', '''ID Store Pruebas''': identificadores del Document Store en cada entorno.&lt;br /&gt;
&lt;br /&gt;
==== 8.7 RAG Loaders ====&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/admin/rag-loaders&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Gestión de los ''loaders'' (cargadores de documentos) asociados a los RAG Stores.&lt;br /&gt;
&lt;br /&gt;
[[File:adm-rag-loaders.png|1000px|Listado de RAG Loaders]]&lt;br /&gt;
&lt;br /&gt;
* Columnas: '''Nombre''', '''RAG Stores''', '''Interno (gestionado por VFlow)''', '''Configuración JSON''' y '''Acciones''' (eliminar).&lt;br /&gt;
* Botón '''+ Añadir loader'''.&lt;br /&gt;
&lt;br /&gt;
'''Formulario de loader:'''&lt;br /&gt;
&lt;br /&gt;
[[File:dlg-ragloader.png|1000px|Formulario de añadir loader]]&lt;br /&gt;
&lt;br /&gt;
Campos:&lt;br /&gt;
&lt;br /&gt;
* '''Nombre''' ''(obligatorio)''.&lt;br /&gt;
* '''Descripción'''.&lt;br /&gt;
* '''Nombre del archivo''' ''(obligatorio)''.&lt;br /&gt;
* '''Seleccione un RAG Store''' ''(obligatorio)'': store al que se asocia.&lt;br /&gt;
* '''Contenido detectado del archivo base''': área de texto con el contenido.&lt;br /&gt;
&lt;br /&gt;
Pulsa '''Crear''' para añadirlo.&lt;br /&gt;
&lt;br /&gt;
==== 8.8 Metabase de datos ====&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/metadata&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Gestión de '''objetos de datos estructurados''' (tablas de datos que puede usar el sistema: clientes, doctores, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:adm-metabase.png|1000px|Metabase de datos]]&lt;br /&gt;
&lt;br /&gt;
* Cada tarjeta representa un '''objeto''' (p. ej. ''Clientes'', ''Doctores'') e indica su descripción, el '''JSON''' asociado y la '''Ruta'''.&lt;br /&gt;
* Acciones por objeto: '''Editar objeto''' (definición/estructura) y '''Editar/Ver datos''' (registros).&lt;br /&gt;
* Botones superiores: '''↻''' (refrescar) y '''+ Nuevo objeto'''.&lt;br /&gt;
&lt;br /&gt;
'''Nuevo objeto / Editar objeto''' — define la estructura del objeto:&lt;br /&gt;
&lt;br /&gt;
[[File:dlg-metaobjeto.png|1000px|Diálogo de nuevo objeto]]&lt;br /&gt;
&lt;br /&gt;
Campos:&lt;br /&gt;
&lt;br /&gt;
* '''Nombre''' ''(obligatorio)'', '''Descripción'''.&lt;br /&gt;
* '''Nombre del JSON''' y '''Ruta de upload'''.&lt;br /&gt;
* '''Campos''': definición de los campos del objeto (botón '''+ Añadir campo''').&lt;br /&gt;
* A la derecha se muestra una vista previa del '''JSON''' resultante.&lt;br /&gt;
&lt;br /&gt;
'''Editar/Ver datos''' — gestiona los registros del objeto:&lt;br /&gt;
&lt;br /&gt;
[[File:meta-ver-datos.png|1000px|Vista de datos de un objeto (registros)]]&lt;br /&gt;
&lt;br /&gt;
* Tabla paginada con los registros y sus columnas (Id, Nombre, Fecha, Dirección, Localidad, Teléfono, Email, etc.).&lt;br /&gt;
* Acciones por fila: '''editar''' ✏️ y '''eliminar''' 🗑️.&lt;br /&gt;
* Botones superiores: '''← Volver''', '''↻''' refrescar, '''⤒ Importar''', '''Generar JSON''', '''Eliminar todo''' y '''+ Nuevo registro'''.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 9. Configuración de la interfaz ===&lt;br /&gt;
&lt;br /&gt;
Al pulsar el icono '''⚙ Configuración''' de la barra lateral (parte inferior) se despliega un pequeño menú de ajustes de la interfaz:&lt;br /&gt;
&lt;br /&gt;
[[File:menu-configuracion.png|1000px|Menú de configuración de la interfaz]]&lt;br /&gt;
&lt;br /&gt;
Opciones:&lt;br /&gt;
&lt;br /&gt;
* '''Tema Claro / Oscuro''': interruptor para cambiar el aspecto visual.&lt;br /&gt;
* '''Idioma''': selector de idioma (p. ej. '''ES''').&lt;br /&gt;
* '''Etiquetas de navegación''': interruptor para mostrar u ocultar los textos junto a los iconos del menú lateral.&lt;br /&gt;
&lt;br /&gt;
Estos ajustes afectan únicamente a la visualización de la interfaz para el usuario actual.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 10. Salir de la aplicación ===&lt;br /&gt;
&lt;br /&gt;
Para cerrar la sesión, pulsa el icono '''⤺ Salir''' situado en la parte inferior de la barra lateral. La aplicación cerrará la sesión y volverá a la pantalla de [[#2. Acceso a la aplicación (Login)|Login]].&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Anexo — Rutas de la aplicación ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Sección !! Ruta&lt;br /&gt;
|-&lt;br /&gt;
| Login || &amp;lt;code&amp;gt;/vflow/login&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Panel || &amp;lt;code&amp;gt;/vflow/dashboard&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Peticiones || &amp;lt;code&amp;gt;/vflow/requests&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Sesiones || &amp;lt;code&amp;gt;/vflow/conversations&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Gestión RAG || &amp;lt;code&amp;gt;/vflow/rag-management&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Administración || &amp;lt;code&amp;gt;/vflow/admin&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Plataformas || &amp;lt;code&amp;gt;/vflow/admin/plataformas&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Agentes || &amp;lt;code&amp;gt;/vflow/admin/agentes&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Orquestadores || &amp;lt;code&amp;gt;/vflow/admin/orquestadores&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Usuarios || &amp;lt;code&amp;gt;/vflow/admin/usuarios&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Configuración del sistema || &amp;lt;code&amp;gt;/vflow/admin/configuracion&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| RAG Stores || &amp;lt;code&amp;gt;/vflow/admin/rag-stores&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| RAG Loaders || &amp;lt;code&amp;gt;/vflow/admin/rag-loaders&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Metabase de datos || &amp;lt;code&amp;gt;/vflow/metadata&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
''Manual generado para su publicación en MediaWiki. Las imágenes se encuentran en la carpeta &amp;lt;code&amp;gt;img/&amp;lt;/code&amp;gt;.''&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Portal_administracion_de_vFlow_v01.04&amp;diff=19148</id>
		<title>Portal administracion de vFlow v01.04</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Portal_administracion_de_vFlow_v01.04&amp;diff=19148"/>
		<updated>2026-07-06T12:00:01Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: /* Manual de usuario — VFlow (Portal de IA) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Manual de usuario — VFlow (Portal de IA) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Versión de la aplicación:''' v01.04.09 · © 2026 MDtel&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 1. Introducción ===&lt;br /&gt;
&lt;br /&gt;
'''VFlow''' es el portal de administración y analítica de los agentes de IA de MDtel. Desde una única interfaz web permite:&lt;br /&gt;
&lt;br /&gt;
* Consultar '''métricas de uso''' (tokens, peticiones, sesiones y tiempos de respuesta) por modelo y periodo.&lt;br /&gt;
* Revisar el '''historial de peticiones''' y el '''detalle de las conversaciones''' de cada sesión.&lt;br /&gt;
* Gestionar la '''base de conocimiento RAG''' (almacenes de documentos y loaders).&lt;br /&gt;
* Administrar los componentes del sistema: '''plataformas, agentes, orquestadores, usuarios''' y '''parámetros globales'''.&lt;br /&gt;
* Mantener '''objetos de datos estructurados''' (Metabase de datos).&lt;br /&gt;
&lt;br /&gt;
El manual recorre todas las pantallas en el orden en el que aparecen en el menú lateral.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 2. Acceso a la aplicación (Login) ===&lt;br /&gt;
&lt;br /&gt;
Al abrir &amp;lt;code&amp;gt;https://labvflow/vflow&amp;lt;/code&amp;gt; la aplicación redirige a la pantalla de inicio de sesión.&lt;br /&gt;
&lt;br /&gt;
[[File:00-login.png|800px|Pantalla de login de VFlow]]&lt;br /&gt;
&lt;br /&gt;
'''Pasos para iniciar sesión:'''&lt;br /&gt;
&lt;br /&gt;
# Introduce tu '''Usuario''' en el primer campo.&lt;br /&gt;
# Introduce tu '''Contraseña'''.&lt;br /&gt;
# Pulsa el botón '''Entrar'''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;El acceso está restringido a usuarios expresamente autorizados. Si las credenciales son incorrectas, la aplicación no permitirá el acceso y permanecerá en esta pantalla.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Una vez autenticado, se accede al '''Panel''' (dashboard) principal.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 3. Estructura general y menú de navegación ===&lt;br /&gt;
&lt;br /&gt;
Tras iniciar sesión, la interfaz se organiza en dos zonas:&lt;br /&gt;
&lt;br /&gt;
* '''Barra lateral izquierda:''' menú de navegación por iconos. Al pasar el ratón se muestra el nombre de cada sección.&lt;br /&gt;
* '''Área de contenido:''' muestra la pantalla de la sección seleccionada.&lt;br /&gt;
&lt;br /&gt;
El menú lateral contiene las siguientes secciones (de arriba a abajo):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Icono !! Sección !! Descripción&lt;br /&gt;
|-&lt;br /&gt;
| 📊 || '''Panel''' || Analítica y métricas de uso (dashboard).&lt;br /&gt;
|-&lt;br /&gt;
| 📋 || '''Peticiones''' || Historial de todas las peticiones realizadas.&lt;br /&gt;
|-&lt;br /&gt;
| 💬 || '''Sesiones''' || Historial de sesiones y detalle de conversaciones.&lt;br /&gt;
|-&lt;br /&gt;
| 🗄️ || '''Gestión RAG''' || Documentos y versiones de los almacenes RAG.&lt;br /&gt;
|-&lt;br /&gt;
| 🛡️ || '''Administración''' || Panel de administración de todos los componentes.&lt;br /&gt;
|-&lt;br /&gt;
| ⚙️ || '''Configuración''' || Ajustes de la interfaz (tema, idioma, etiquetas).&lt;br /&gt;
|-&lt;br /&gt;
| ⤺ || '''Salir''' || Cierra la sesión.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
En la esquina inferior izquierda se muestra siempre la '''versión''' de la aplicación (v01.04.09) y el aviso de copyright.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 4. Panel (Dashboard) ===&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/dashboard&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es la pantalla de inicio. Muestra el análisis y las métricas de uso del sistema.&lt;br /&gt;
&lt;br /&gt;
[[File:01-dashboard.png|800px|Panel de VFlow (dashboard)]]&lt;br /&gt;
&lt;br /&gt;
'''Elementos de la cabecera:'''&lt;br /&gt;
&lt;br /&gt;
* '''Total de tokens''', '''Total de peticiones''' y '''Chats únicos''': contadores globales del periodo seleccionado.&lt;br /&gt;
* '''Gráficas''' (desplegable): permite mostrar/ocultar las gráficas disponibles.&lt;br /&gt;
* '''Periodo''' (desplegable): filtra todas las métricas por el rango de fechas elegido.&lt;br /&gt;
* '''+ Añadir gráfica''': abre el asistente para crear una gráfica personalizada (ver 4.1).&lt;br /&gt;
&lt;br /&gt;
'''Gráficas incluidas por defecto:'''&lt;br /&gt;
&lt;br /&gt;
* '''Tokens por Modelo''' — tabla con el total de tokens consumidos por cada modelo.&lt;br /&gt;
* '''Evolución de Peticiones''' — evolución temporal del número de peticiones.&lt;br /&gt;
* '''Peticiones por Modelo''' — comparativa de peticiones por modelo.&lt;br /&gt;
* '''Evolución de Tokens''' — evolución temporal del consumo de tokens.&lt;br /&gt;
* '''Llamadas LLM por Día''', '''Tiempo de respuesta por modelo (ms)''' y '''Peticiones por hora del día''' (más abajo en la página).&lt;br /&gt;
&lt;br /&gt;
Cada gráfica dispone del botón '''⚙ Configuración de Gráficos''' y de una leyenda con los modelos, donde se puede quitar un modelo pulsando la '''✕''' de su etiqueta.&lt;br /&gt;
&lt;br /&gt;
==== 4.1 Añadir una gráfica personalizada ====&lt;br /&gt;
&lt;br /&gt;
Al pulsar '''+ Añadir gráfica''' se abre el asistente '''Crear gráfica personalizada''':&lt;br /&gt;
&lt;br /&gt;
[[File:dlg-anadir-grafica.png|800px|Diálogo de creación de gráfica personalizada]]&lt;br /&gt;
&lt;br /&gt;
Opciones de configuración:&lt;br /&gt;
&lt;br /&gt;
* '''Nombre de la gráfica''': título que se mostrará.&lt;br /&gt;
* '''Fuente de datos''': origen de los datos (p. ej. ''Consumos (DAT_CONSUMOS)'').&lt;br /&gt;
* '''Agrupar por''': dimensión de agrupación (p. ej. ''Por Modelo'').&lt;br /&gt;
* '''Métrica''': valor a representar (p. ej. ''Número de llamadas'').&lt;br /&gt;
* '''Tipo de gráfica''': Barras, Horizontal, Línea, Área, Circular, Donut, KPI, Radar, Mapa de calor, Medidor, Histograma, Treemap o Dispersión.&lt;br /&gt;
* '''Color''', '''Estilo''' (mostrar leyenda, opacidad), rangos '''Y mínimo / Y máximo''' y '''Umbral de alerta'''.&lt;br /&gt;
&lt;br /&gt;
A la derecha se muestra una '''Vista previa''' en tiempo real. Pulsa '''Guardar gráfica''' para añadirla al panel o '''Cancelar''' para descartar.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Nota: la creación de gráficas personalizadas puede estar limitada por rol (ver [[#8.5 Configuración del sistema|8.5 Configuración del sistema → Overrides por rol]]).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 5. Peticiones ===&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/requests&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Muestra el '''Historial de Peticiones''': la lista completa de todas las peticiones realizadas al sistema.&lt;br /&gt;
&lt;br /&gt;
[[File:02-peticiones.png|800px|Historial de Peticiones]]&lt;br /&gt;
&lt;br /&gt;
'''Filtros (parte superior):'''&lt;br /&gt;
&lt;br /&gt;
* '''Plataformas''', '''Agentes''', '''Orquestadores''': desplegables para filtrar por cada componente.&lt;br /&gt;
* '''Periodo''': filtra por rango de fechas.&lt;br /&gt;
&lt;br /&gt;
'''Tabla de Peticiones:'''&lt;br /&gt;
&lt;br /&gt;
* Campo de '''Búsqueda''' y selector de '''Registros por página''' (10 por defecto).&lt;br /&gt;
* Columnas: '''Message ID''', '''ID de sesión''', '''Fecha''', '''Pregunta''' y '''Respuesta'''.&lt;br /&gt;
* Indicador ''&amp;quot;Mostrando 1 a 10 de N resultados&amp;quot;'' y '''paginación''' en la parte inferior.&lt;br /&gt;
&lt;br /&gt;
Es la vista de referencia para auditar de forma tabular qué se preguntó, cuándo y qué respondió el agente.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 6. Sesiones ===&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/conversations&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Muestra el '''Historial de sesiones'''. Cada sesión agrupa los mensajes de una conversación.&lt;br /&gt;
&lt;br /&gt;
[[File:03-sesiones.png|800px|Listado de Sesiones]]&lt;br /&gt;
&lt;br /&gt;
'''Panel izquierdo (listado):'''&lt;br /&gt;
&lt;br /&gt;
* Buscador '''&amp;quot;Buscar por ID de sesión o texto&amp;quot;'''.&lt;br /&gt;
* Botón '''Cargar más''' para paginar resultados.&lt;br /&gt;
* Cada tarjeta muestra: plataforma (p. ej. &amp;lt;code&amp;gt;omsui_1&amp;lt;/code&amp;gt;), fecha/hora, '''agente''' e '''ID de sesión''', y el número de mensajes (&amp;lt;code&amp;gt;N msg&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Filtros superiores: '''Plataformas''', '''Agentes''', '''Orquestadores''', '''Sesiones''' y '''Periodo'''.&lt;br /&gt;
&lt;br /&gt;
'''Panel derecho (detalle):''' al seleccionar una sesión se muestra la conversación completa en formato chat.&lt;br /&gt;
&lt;br /&gt;
[[File:sesion-detalle.png|800px|Detalle de una sesión]]&lt;br /&gt;
&lt;br /&gt;
En el detalle se ven, en orden cronológico, los mensajes del '''usuario''' (a la derecha) y las respuestas del '''agente''' (a la izquierda, con el nombre del agente), junto con la cabecera de la sesión (plataforma, agente e ID).&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 7. Gestión RAG ===&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/rag-management&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Permite gestionar los documentos del sistema '''RAG''' (Retrieval-Augmented Generation), organizados por almacén (''store'').&lt;br /&gt;
&lt;br /&gt;
[[File:04-gestion-rag.png|800px|Gestión RAG]]&lt;br /&gt;
&lt;br /&gt;
* Cada bloque corresponde a un '''RAG Store''' (p. ej. &amp;lt;code&amp;gt;ARA002&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;General&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DS_ARA&amp;lt;/code&amp;gt;) e indica su '''UUID''' y un estado ('''ACTUALIZADO''').&lt;br /&gt;
* Al expandir un store (flecha ▾) se muestran sus '''documentos/loaders'''. Para cada documento:&lt;br /&gt;
** Nombre del documento (p. ej. &amp;lt;code&amp;gt;ARA002_ld1&amp;lt;/code&amp;gt;).&lt;br /&gt;
** '''Versión activa''' (etiqueta, p. ej. &amp;lt;code&amp;gt;v3&amp;lt;/code&amp;gt;).&lt;br /&gt;
** Acciones: '''subir/actualizar''' (icono nube) y '''eliminar''' (icono papelera).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Esta pantalla es la vista operativa del contenido RAG. La definición de los stores y loaders se realiza en Administración (ver [[#8.6 RAG Stores|8.6]] y [[#8.7 RAG Loaders|8.7]]).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 8. Administración ===&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/admin&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Panel central para administrar y configurar todos los componentes del sistema VFlow. Se presenta como una cuadrícula de tarjetas de acceso.&lt;br /&gt;
&lt;br /&gt;
[[File:05-administracion.png|800px|Panel de administración de VFlow]]&lt;br /&gt;
&lt;br /&gt;
Tarjetas disponibles:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Tarjeta !! Función&lt;br /&gt;
|-&lt;br /&gt;
| '''Plataformas''' || Gestión de plataformas.&lt;br /&gt;
|-&lt;br /&gt;
| '''Agentes''' || Gestión de agentes.&lt;br /&gt;
|-&lt;br /&gt;
| '''Orquestadores''' || Gestión de orquestadores.&lt;br /&gt;
|-&lt;br /&gt;
| '''Usuarios''' || Gestión de usuarios.&lt;br /&gt;
|-&lt;br /&gt;
| '''Configuración del sistema''' || Parámetros y ajustes globales.&lt;br /&gt;
|-&lt;br /&gt;
| '''RAG Stores''' || Almacenes de documentos RAG.&lt;br /&gt;
|-&lt;br /&gt;
| '''RAG Loaders''' || Loaders de documentos RAG.&lt;br /&gt;
|-&lt;br /&gt;
| '''Metabase de datos''' || Objetos, campos y registros estructurados.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Aviso mostrado en la propia pantalla: ''&amp;quot;Desde este panel puedes administrar todas las configuraciones críticas del sistema VFlow. Asegúrate de tener los permisos necesarios antes de realizar cambios.&amp;quot;''&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En todas las subpantallas de administración el botón '''← Volver''' regresa a este panel.&lt;br /&gt;
&lt;br /&gt;
==== 8.1 Plataformas ====&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/admin/plataformas&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Listado de plataformas conectadas (p. ej. VIVAit, OmniSuite).&lt;br /&gt;
&lt;br /&gt;
[[File:adm-plataformas.png|800px|Listado de Plataformas]]&lt;br /&gt;
&lt;br /&gt;
* Columnas: '''Nombre''', '''Identificador (UUID)''', '''Descripción''', '''Tipo''' (&amp;lt;code&amp;gt;vivait&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;omniSuite&amp;lt;/code&amp;gt;…), '''Max Sesiones''' y '''Acciones''' (editar ✏️ / eliminar 🗑️).&lt;br /&gt;
* Botón '''+ Crear''' para dar de alta una plataforma.&lt;br /&gt;
&lt;br /&gt;
'''Formulario de creación/edición:'''&lt;br /&gt;
&lt;br /&gt;
[[File:dlg-plataforma.png|800px|Formulario de plataforma]]&lt;br /&gt;
&lt;br /&gt;
Campos:&lt;br /&gt;
&lt;br /&gt;
* '''Nombre''' ''(obligatorio)''.&lt;br /&gt;
* '''Tipo''' ''(obligatorio)'': selector de tipo de plataforma.&lt;br /&gt;
* '''Descripción'''.&lt;br /&gt;
* '''Max Sesiones Abiertas''', '''Max Peticiones Simultáneas''', '''Max Peticiones/Min/Sesión''': límites de capacidad.&lt;br /&gt;
&lt;br /&gt;
Pulsa '''Guardar''' para confirmar o '''Cancelar''' para descartar.&lt;br /&gt;
&lt;br /&gt;
==== 8.2 Agentes ====&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/admin/agentes&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Gestión de los agentes de IA.&lt;br /&gt;
&lt;br /&gt;
[[File:adm-agentes.png|800px|Listado de Agentes]]&lt;br /&gt;
&lt;br /&gt;
* Columnas: '''Nombre''', '''Descripción''', '''Plataformas''', '''Orquestadores''', '''IDs entorno''' (PRO / PRE / PRU) y '''Acciones'''.&lt;br /&gt;
* Los '''IDs entorno''' muestran el identificador del agente en cada entorno: '''PRO''' (Producción), '''PRE''' (Preproducción) y '''PRU''' (Pruebas).&lt;br /&gt;
* Botón '''+ Nuevo Agente'''.&lt;br /&gt;
&lt;br /&gt;
'''Formulario de agente:'''&lt;br /&gt;
&lt;br /&gt;
[[File:dlg-agente.png|800px|Formulario de nuevo agente]]&lt;br /&gt;
&lt;br /&gt;
Campos:&lt;br /&gt;
&lt;br /&gt;
* '''Nombre''' ''(obligatorio)''.&lt;br /&gt;
* '''ID Agente Producción''' ''(obligatorio)'', '''ID Agente Preproducción''', '''ID Agente Pruebas''': identificadores del agente en cada entorno.&lt;br /&gt;
* '''Descripción'''.&lt;br /&gt;
* '''Plataformas''' ''(obligatorio)'' y '''Orquestadores''' ''(obligatorio)'': selección del componente asociado.&lt;br /&gt;
* '''Timeout Respuesta (ms)''': tiempo máximo de espera de respuesta (30000 por defecto).&lt;br /&gt;
&lt;br /&gt;
Los campos marcados con &amp;lt;code&amp;gt;*&amp;lt;/code&amp;gt; son obligatorios. Pulsa '''Guardar'''.&lt;br /&gt;
&lt;br /&gt;
==== 8.3 Orquestadores ====&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/admin/orquestadores&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Gestión de los orquestadores (motores que enrutan/ejecutan las peticiones, p. ej. ''Flowise'', ''Bucle'').&lt;br /&gt;
&lt;br /&gt;
[[File:adm-orquestadores.png|800px|Listado de Orquestadores]]&lt;br /&gt;
&lt;br /&gt;
* Columnas: '''Nombre''', '''Descripción''', '''Tipo''' (Bucle, Flowise…), '''URL Conexión''' y '''Acciones'''.&lt;br /&gt;
* Botón '''+ Crear'''.&lt;br /&gt;
&lt;br /&gt;
'''Formulario de orquestador:'''&lt;br /&gt;
&lt;br /&gt;
[[File:dlg-orquestador.png|800px|Formulario de orquestador]]&lt;br /&gt;
&lt;br /&gt;
Campos:&lt;br /&gt;
&lt;br /&gt;
* '''Nombre''' ''(obligatorio)'' y '''Tipo''' ''(obligatorio)''.&lt;br /&gt;
* '''URL Conexión''' ''(obligatorio)'': endpoint del orquestador.&lt;br /&gt;
* '''URL Proxy (opcional)''', '''URL RAG'''.&lt;br /&gt;
* '''Cadena de Autenticación''': Bearer token o API Key.&lt;br /&gt;
* '''Usuario (opcional)''' y '''Contraseña (opcional)'''.&lt;br /&gt;
* '''Descripción'''.&lt;br /&gt;
&lt;br /&gt;
==== 8.4 Usuarios ====&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/admin/usuarios&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Gestión de las cuentas de usuario de VFlow.&lt;br /&gt;
&lt;br /&gt;
[[File:adm-usuarios.png|800px|Listado de Usuarios]]&lt;br /&gt;
&lt;br /&gt;
* Columnas: '''Nombre''', '''Cuenta (login)''', '''Rol''' (Invitado, Usuario, Administrador), '''Activo''' y '''Acciones'''.&lt;br /&gt;
* Botón '''+ Crear'''.&lt;br /&gt;
&lt;br /&gt;
'''Formulario de usuario:'''&lt;br /&gt;
&lt;br /&gt;
[[File:dlg-usuario.png|800px|Formulario de usuario]]&lt;br /&gt;
&lt;br /&gt;
Campos:&lt;br /&gt;
&lt;br /&gt;
* '''Nombre''' ''(obligatorio)'', '''Primer Apellido''', '''Segundo Apellido'''.&lt;br /&gt;
* '''Email''' ''(obligatorio)'', '''Móvil''', '''Cuenta (login)''' ''(obligatorio)''.&lt;br /&gt;
* '''Contraseña''' ''(obligatorio)''.&lt;br /&gt;
* '''Rol''' ''(obligatorio)'': perfil de permisos.&lt;br /&gt;
* '''Modo de Login''': ''Local'' (u otros modos disponibles, p. ej. SSO).&lt;br /&gt;
&lt;br /&gt;
==== 8.5 Configuración del sistema ====&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/admin/configuracion&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parámetros y ajustes globales del sistema. Está organizada en '''pestañas'''. Los cambios se confirman con el botón '''Guardar Configuración''' (abajo a la derecha).&lt;br /&gt;
&lt;br /&gt;
'''Pestaña Monitorización''' — estado general e incidencias recientes del frontend:&lt;br /&gt;
&lt;br /&gt;
[[File:adm-configuracion-sistema.png|800px|Configuración del sistema — Monitorización]]&lt;br /&gt;
&lt;br /&gt;
Muestra tarjetas de estado: '''Estado''' (Backend disponible), '''Nivel de log''', '''Stores pendientes''', '''Histórico de sincronización''', '''Errores recientes''', '''Warnings recientes''' y '''Última comprobación'''. El botón '''Actualizar estado''' refresca los datos. Debajo se listan los ''stores pendientes'' de sincronización y el ''histórico de sincronización''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Indicación en pantalla: los logs de frontend se ven en &amp;lt;code&amp;gt;F12 &amp;gt; Consola&amp;lt;/code&amp;gt;; los del backend en &amp;lt;code&amp;gt;/opt/tomcat11/logs/catalina.out&amp;lt;/code&amp;gt;.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Pestaña Tarificación:'''&lt;br /&gt;
&lt;br /&gt;
[[File:cfg-tarificacion.png|800px|Configuración del sistema — Tarificación]]&lt;br /&gt;
&lt;br /&gt;
* '''Peticiones por Bloque a Tarificar''' y '''Segundos por Bloque a Tarificar'''.&lt;br /&gt;
&lt;br /&gt;
'''Pestaña Configuración runtime''' — se guarda en &amp;lt;code&amp;gt;vflow-config.json&amp;lt;/code&amp;gt; y se aplica al refrescar la aplicación:&lt;br /&gt;
&lt;br /&gt;
[[File:cfg-configuracion.png|800px|Configuración del sistema — Configuración runtime]]&lt;br /&gt;
&lt;br /&gt;
* '''URL de la API backend''' (p. ej. &amp;lt;code&amp;gt;/vflow/api&amp;lt;/code&amp;gt;): ruta que usa el frontend para llamar al backend.&lt;br /&gt;
* '''Tamaño de página de sesiones''': nº de sesiones por tanda en la pantalla de conversaciones.&lt;br /&gt;
* '''Nivel de log''': DEBUG muestra todo, ERROR solo fallos.&lt;br /&gt;
* '''Overrides por rol''': permite ajustar 2FA y la '''visibilidad del dashboard''' por perfil (Administrador, Invitado, Usuario), incluyendo qué gráficas ve cada rol y si puede crear gráficas personalizadas.&lt;br /&gt;
&lt;br /&gt;
'''Pestaña Rutas de Archivos''' — configuradas en servidor, '''no editables''' desde la interfaz:&lt;br /&gt;
&lt;br /&gt;
[[File:cfg-rutas.png|800px|Configuración del sistema — Rutas de Archivos]]&lt;br /&gt;
&lt;br /&gt;
* '''Ruta de Documentos''' (p. ej. &amp;lt;code&amp;gt;/etc/MDtel/vFlow/Documentos/&amp;lt;/code&amp;gt;).&lt;br /&gt;
* '''Ruta API Loader''' (p. ej. &amp;lt;code&amp;gt;/var/www/html/storages/&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
'''Pestaña Timeouts de Sesión (segundos):'''&lt;br /&gt;
&lt;br /&gt;
[[File:cfg-timeouts.png|800px|Configuración del sistema — Timeouts de Sesión]]&lt;br /&gt;
&lt;br /&gt;
* '''Dormir Sesión''', '''Sesión Voz''', '''Sesión Chat''' y '''Sesión Email''': tiempos de expiración por tipo de sesión.&lt;br /&gt;
&lt;br /&gt;
==== 8.6 RAG Stores ====&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/admin/rag-stores&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Gestión de los almacenes de documentos RAG.&lt;br /&gt;
&lt;br /&gt;
[[File:adm-rag-stores.png|800px|Listado de RAG Stores]]&lt;br /&gt;
&lt;br /&gt;
* Columnas: '''Nombre''', '''Descripción''', '''Plataformas''', '''ID Store Producción''', '''ID Store Preproducción''', '''ID Store Pruebas''' y '''Acciones'''.&lt;br /&gt;
* Botón '''+ Nuevo RAG Store'''.&lt;br /&gt;
&lt;br /&gt;
'''Formulario de RAG Store:'''&lt;br /&gt;
&lt;br /&gt;
[[File:dlg-ragstore.png|800px|Formulario de RAG Store]]&lt;br /&gt;
&lt;br /&gt;
Campos:&lt;br /&gt;
&lt;br /&gt;
* '''Nombre''' ''(obligatorio)'', '''Plataformas''' ''(obligatorio)'', '''Orquestadores''' ''(obligatorio)''.&lt;br /&gt;
* '''Descripción'''.&lt;br /&gt;
* '''ID Store Producción''' ''(obligatorio)'', '''ID Store Preproducción''', '''ID Store Pruebas''': identificadores del Document Store en cada entorno.&lt;br /&gt;
&lt;br /&gt;
==== 8.7 RAG Loaders ====&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/admin/rag-loaders&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Gestión de los ''loaders'' (cargadores de documentos) asociados a los RAG Stores.&lt;br /&gt;
&lt;br /&gt;
[[File:adm-rag-loaders.png|800px|Listado de RAG Loaders]]&lt;br /&gt;
&lt;br /&gt;
* Columnas: '''Nombre''', '''RAG Stores''', '''Interno (gestionado por VFlow)''', '''Configuración JSON''' y '''Acciones''' (eliminar).&lt;br /&gt;
* Botón '''+ Añadir loader'''.&lt;br /&gt;
&lt;br /&gt;
'''Formulario de loader:'''&lt;br /&gt;
&lt;br /&gt;
[[File:dlg-ragloader.png|800px|Formulario de añadir loader]]&lt;br /&gt;
&lt;br /&gt;
Campos:&lt;br /&gt;
&lt;br /&gt;
* '''Nombre''' ''(obligatorio)''.&lt;br /&gt;
* '''Descripción'''.&lt;br /&gt;
* '''Nombre del archivo''' ''(obligatorio)''.&lt;br /&gt;
* '''Seleccione un RAG Store''' ''(obligatorio)'': store al que se asocia.&lt;br /&gt;
* '''Contenido detectado del archivo base''': área de texto con el contenido.&lt;br /&gt;
&lt;br /&gt;
Pulsa '''Crear''' para añadirlo.&lt;br /&gt;
&lt;br /&gt;
==== 8.8 Metabase de datos ====&lt;br /&gt;
&lt;br /&gt;
'''Ruta:''' &amp;lt;code&amp;gt;/vflow/metadata&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Gestión de '''objetos de datos estructurados''' (tablas de datos que puede usar el sistema: clientes, doctores, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:adm-metabase.png|800px|Metabase de datos]]&lt;br /&gt;
&lt;br /&gt;
* Cada tarjeta representa un '''objeto''' (p. ej. ''Clientes'', ''Doctores'') e indica su descripción, el '''JSON''' asociado y la '''Ruta'''.&lt;br /&gt;
* Acciones por objeto: '''Editar objeto''' (definición/estructura) y '''Editar/Ver datos''' (registros).&lt;br /&gt;
* Botones superiores: '''↻''' (refrescar) y '''+ Nuevo objeto'''.&lt;br /&gt;
&lt;br /&gt;
'''Nuevo objeto / Editar objeto''' — define la estructura del objeto:&lt;br /&gt;
&lt;br /&gt;
[[File:dlg-metaobjeto.png|800px|Diálogo de nuevo objeto]]&lt;br /&gt;
&lt;br /&gt;
Campos:&lt;br /&gt;
&lt;br /&gt;
* '''Nombre''' ''(obligatorio)'', '''Descripción'''.&lt;br /&gt;
* '''Nombre del JSON''' y '''Ruta de upload'''.&lt;br /&gt;
* '''Campos''': definición de los campos del objeto (botón '''+ Añadir campo''').&lt;br /&gt;
* A la derecha se muestra una vista previa del '''JSON''' resultante.&lt;br /&gt;
&lt;br /&gt;
'''Editar/Ver datos''' — gestiona los registros del objeto:&lt;br /&gt;
&lt;br /&gt;
[[File:meta-ver-datos.png|800px|Vista de datos de un objeto (registros)]]&lt;br /&gt;
&lt;br /&gt;
* Tabla paginada con los registros y sus columnas (Id, Nombre, Fecha, Dirección, Localidad, Teléfono, Email, etc.).&lt;br /&gt;
* Acciones por fila: '''editar''' ✏️ y '''eliminar''' 🗑️.&lt;br /&gt;
* Botones superiores: '''← Volver''', '''↻''' refrescar, '''⤒ Importar''', '''Generar JSON''', '''Eliminar todo''' y '''+ Nuevo registro'''.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 9. Configuración de la interfaz ===&lt;br /&gt;
&lt;br /&gt;
Al pulsar el icono '''⚙ Configuración''' de la barra lateral (parte inferior) se despliega un pequeño menú de ajustes de la interfaz:&lt;br /&gt;
&lt;br /&gt;
[[File:menu-configuracion.png|800px|Menú de configuración de la interfaz]]&lt;br /&gt;
&lt;br /&gt;
Opciones:&lt;br /&gt;
&lt;br /&gt;
* '''Tema Claro / Oscuro''': interruptor para cambiar el aspecto visual.&lt;br /&gt;
* '''Idioma''': selector de idioma (p. ej. '''ES''').&lt;br /&gt;
* '''Etiquetas de navegación''': interruptor para mostrar u ocultar los textos junto a los iconos del menú lateral.&lt;br /&gt;
&lt;br /&gt;
Estos ajustes afectan únicamente a la visualización de la interfaz para el usuario actual.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 10. Salir de la aplicación ===&lt;br /&gt;
&lt;br /&gt;
Para cerrar la sesión, pulsa el icono '''⤺ Salir''' situado en la parte inferior de la barra lateral. La aplicación cerrará la sesión y volverá a la pantalla de [[#2. Acceso a la aplicación (Login)|Login]].&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Anexo — Rutas de la aplicación ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Sección !! Ruta&lt;br /&gt;
|-&lt;br /&gt;
| Login || &amp;lt;code&amp;gt;/vflow/login&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Panel || &amp;lt;code&amp;gt;/vflow/dashboard&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Peticiones || &amp;lt;code&amp;gt;/vflow/requests&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Sesiones || &amp;lt;code&amp;gt;/vflow/conversations&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Gestión RAG || &amp;lt;code&amp;gt;/vflow/rag-management&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Administración || &amp;lt;code&amp;gt;/vflow/admin&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Plataformas || &amp;lt;code&amp;gt;/vflow/admin/plataformas&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Agentes || &amp;lt;code&amp;gt;/vflow/admin/agentes&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Orquestadores || &amp;lt;code&amp;gt;/vflow/admin/orquestadores&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Usuarios || &amp;lt;code&amp;gt;/vflow/admin/usuarios&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Configuración del sistema || &amp;lt;code&amp;gt;/vflow/admin/configuracion&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| RAG Stores || &amp;lt;code&amp;gt;/vflow/admin/rag-stores&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| RAG Loaders || &amp;lt;code&amp;gt;/vflow/admin/rag-loaders&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Metabase de datos || &amp;lt;code&amp;gt;/vflow/metadata&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
''Manual generado para su publicación en MediaWiki. Las imágenes se encuentran en la carpeta &amp;lt;code&amp;gt;img/&amp;lt;/code&amp;gt;.''&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Archivo:Sesion-detalle.png&amp;diff=19147</id>
		<title>Archivo:Sesion-detalle.png</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Archivo:Sesion-detalle.png&amp;diff=19147"/>
		<updated>2026-07-06T11:59:04Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
	<entry>
		<id>https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Archivo:Meta-ver-datos.png&amp;diff=19146</id>
		<title>Archivo:Meta-ver-datos.png</title>
		<link rel="alternate" type="text/html" href="https://vivait-wiki.mdnova.local/wiki/vivait/index.php?title=Archivo:Meta-ver-datos.png&amp;diff=19146"/>
		<updated>2026-07-06T11:58:46Z</updated>

		<summary type="html">&lt;p&gt;Alfredo.rodriguez: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Alfredo.rodriguez</name></author>
		
	</entry>
</feed>