# Notas del Desarrollador

# Sistema linux CVC



# SSH key based authentication

#### En el cliente

ssh-keygen (una vez)

ssh-copy-id &lt;user&gt;@&lt;remote&gt; (si se puede)

#### En el servidor (si no ssh-copy)

Copiar el contenido del archivo local  
*.ssh/id\_rsa.pub*  
al remoto:  
 *.ssh/authorized\_keys*

# Ajustes Generales

#### **-. Programar tareas en Linux**

- Crear script &gt; ***sudo nano nombrescript.sh***
- Los scripts deben llevar al inicio: **\#!/binbash**
- Editar script &gt;***cd /home/cvc/scripts*** &gt; ***sudo nano nombrescript.sh***
- ***Ctrl+X*** para guardar &gt; ***Y*** para confirmar.
- ------
- *crontab -e*
- i &gt; entrar en modo edición.
- ESC &gt; salir de modo edición.
- :wq &gt; guardar y salir del editor.

# Restaurar permisos de apps

Estos comandos restauran los permisos necesarios para las aplicaciones de ElectronJS que están instaladas en los equipos

> chown root /home/cvc/apps/canal/chrome-sandbox  
> chmod 4755 /home/cvc/apps/canal/chrome-sandbox  
> chmod +x /home/cvc/apps/canal/canal
> 
> chown root /home/cvc/apps/totem/chrome-sandbox  
> chmod 4755 /home/cvc/apps/totem/chrome-sandbox  
> chmod +x /home/cvc/apps/totem/totem
> 
> chown root /home/cvc/apps/webviewer/chrome-sandbox  
> chmod 4755 /home/cvc/apps/webviewer/chrome-sandbox  
> chmod +x /home/cvc/apps/webviewer/webviewer
> 
> chown root /home/cvc/apps/guardias/chrome-sandbox  
> chmod 4755 /home/cvc/apps/guardias/chrome-sandbox  
> chmod +x /home/cvc/apps/guardias/guardias

# Comandos para instalar MeshCentral

#### Eliminar Teamviewer

> apt purge -y teamviewer-host  
> apt update  
> rm -r /home/cvc/.local/share/teamviewer15/  
> rm -r /home/cvc/.config/teamviewer/  
> rm -r /home/cvc/.cache/TeamViewer/  
> rm -r /root/.config/teamviewer  
> rm -r /root/.local/share/teamviewer15

#### Instalar agente de MeshCentral

> rm -r mesh/; mkdir mesh &amp;&amp; cd mesh &amp;&amp; curl "https://comunicacionvisualcanarias.com:444/meshagents?script=1" -o ./meshinstall.sh &amp;&amp; chmod 755 ./meshinstall.sh &amp;&amp; echo 'cvc' | sudo -S -E ./meshinstall.sh https://comunicacionvisualcanarias.com:444 'BWd1yDz9wBrA8h8LPbiIzrLJqwICVU10yVuEeM02g0LjaWPq4bf$hQIkrb41yX2@'

#### Identificar equipo (version 2021-2023)

> jq '.info.device.name, .info.device.type' /home/cvc/system/server.json; echo "Teamviewer ID:" $(grep 'ClientID' /opt/teamviewer/config/global.conf | cut -d' ' -f 4)

# Convertir de Pulseaudio a ALSA

#### (Des)instalar

> apt purge \*pulse\* -y  
> apt autoremove -y  
> apt install alsa-utils -y

####   
/etc/modules-load.d/modules.conf  


> snd\_aloop

####   
/etc/modprobe.d/alsa.conf  


> options snd\_hda\_intel index=0  
> options snd-aloop index=1 enable=1 pcm\_substreams=1

####   
~/.bash\_aliases  


> alias audiometro='arecord -q -D hw:1,1 -V mono -f dat /dev/null'

####   
~/.asoundrc  


> pcm.!default {  
>  type asym  
>  playback.pcm "LoopAndReal"  
>  capture.pcm "hw:0,0"  
> }  
> pcm.LoopAndReal {  
>  type plug  
>  slave.pcm mdev  
>  route\_policy "duplicate"  
> }  
> pcm.mdev {  
>  type multi  
>  slaves.a.pcm pcm.MixReale  
>  slaves.a.channels 2  
>  slaves.b.pcm pcm.MixLoopback  
>  slaves.b.channels 2  
>  bindings.0.slave a  
>  bindings.0.channel 0  
>  bindings.1.slave a  
>  bindings.1.channel 1  
>  bindings.2.slave b  
>  bindings.2.channel 0  
>  bindings.3.slave b  
>  bindings.3.channel 1  
> }  
> pcm.MixReale {  
>  type dmix  
>  ipc\_key 1024  
>  slave {  
>  pcm "hw:0,0"  
>  rate 48000  
>  #rate 44100  
>  periods 128  
>  period\_time 0  
>  period\_size 1024 # must be power of 2  
>  buffer\_size 8192  
>  }  
> }  
> pcm.MixLoopback {  
>  type dmix  
>  ipc\_key 1025  
>  slave {  
>  pcm "hw:Loopback,0,0"  
>  rate 48000  
>  #rate 44100  
>  periods 128  
>  period\_time 0  
>  period\_size 1024 # must be power of 2  
>  buffer\_size 8192  
>  }  
> }

# Matrices transformacion Libinput

Option "CalibrationMatrix" "xx"

<table border="1" id="bkmrk-left-0--1-1-1-0-0-0-" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 27.963%;"></col><col style="width: 72.1606%;"></col></colgroup><tbody><tr><td>LEFT  
</td><td>0 -1 1 1 0 0 0 0 1</td></tr><tr><td>RIGHT  
</td><td>0 1 0 -1 0 1 0 0 1  
</td></tr><tr><td>INVERT  
</td><td>-1 0 1 0 -1 1 0 0 1  
</td></tr><tr><td>NORMAL  
</td><td>1 0 0 0 1 0 0 0 1</td></tr></tbody></table>

# Systemd Startx

```
[Unit]
Description=X11 session for bernat
After=graphical.target systemd-user-sessions.service

[Service]
User=bernat
WorkingDirectory=~

PAMName=login
Environment=XDG_SESSION_TYPE=x11
TTYPath=/dev/tty8
StandardInput=tty
UnsetEnvironment=TERM

UtmpIdentifier=tty8
UtmpMode=user

StandardOutput=journal
ExecStartPre=/usr/bin/chvt 8
ExecStart=/usr/bin/startx -- vt8 -keeptty -verbose 3 -logfile /dev/null
#Restart=no
Restart=always
RestartSec=3

[Install]
WantedBy=graphical.target
```

```
sudo systemctl set-default graphical.target
```

# Lista de paquetes Debian 12

adduser adwaita-icon-theme alsa-topology-conf alsa-ucm-conf alsa-utils apparmor apt-utils apt at-spi2-common at-spi2-core base-files base-passwd bash-completion bash bc bsdextrautils bsdutils busybox bzip2 ca-certificates console-setup-linux console-setup coreutils cpio cpp-12 cpp cron-daemon-common cron curl dash dbus-bin dbus-daemon dbus-session-bus-common dbus-system-bus-common dbus-user-session dbus dconf-gsettings-backend dconf-service debconf-i18n debconf debian-archive-keyring debianutils desktop-base desktop-file-utils dialog diffutils dirmngr discover-data discover dmidecode dmsetup dosfstools dpkg e2fsprogs efibootmgr eject exfatprogs fdisk featherpad-l10n featherpad feh file findutils firmware-amd-graphics firmware-linux-free firmware-linux-nonfree firmware-misc-nonfree fontconfig-config fontconfig fonts-dejavu-core fonts-droid-fallback fonts-liberation fonts-noto-mono fonts-quicksand fonts-urw-base35 fuse3 gcc-10-base gcc-12-base gcr gdbm-l10n gdisk gir1.2-atk-1.0 gir1.2-freedesktop gir1.2-gdkpixbuf-2.0 gir1.2-glib-2.0 gir1.2-gtk-3.0 gir1.2-harfbuzz-0.0 gir1.2-pango-1.0 gnome-icon-theme gnupg-l10n gnupg-utils gnupg gpg-agent gpg-wks-client gpg-wks-server gpg gpgconf gpgsm gpgv grep groff-base gsettings-desktop-schemas gstreamer1.0-plugins-base gtk-update-icon-cache gvfs-common gvfs-daemons gvfs-libs gvfs gzip hicolor-icon-theme hostname htop init-system-helpers init initramfs-tools-core initramfs-tools installation-report intel-microcode iproute2 iptables iputils-ping isc-dhcp-common iso-codes iucode-tool jq kbd keyboard-configuration klibc-utils kmod krb5-locales laptop-detect less libaacs0 libacl1 libaom3 libapparmor1 libapt-pkg6.0 libargon2-1 libasound2-data libasound2 libassuan0 libatasmart4 libatk-bridge2.0-0 libatk1.0-0 libatopology2 libatspi2.0-0 libattr1 libaudit-common libaudit1 libavahi-client3 libavahi-common-data libavahi-common3 libbdplus0 libblkid1 libblockdev-crypto2 libblockdev-fs2 libblockdev-loop2 libblockdev-part-err2 libblockdev-part2 libblockdev-swap2 libblockdev-utils2 libblockdev2 libbluray2 libbpf1 libbrotli1 libbsd0 libbz2-1.0 libc-ares2 libc-bin libc-l10n libc6 libcairo-gobject2 libcairo2 libcap-ng0 libcap2-bin libcap2 libcbor0.8 libcdparanoia0 libcolord2 libcom-err2 libcrypt1 libcryptsetup12 libcups2 libcurl4 libdatrie1 libdav1d6 libdb5.3 libdbus-1-3 libdbus-glib-1-2 libdconf1 libde265-0 libdebconfclient0 libdeflate0 libdevmapper1.02.1 libdiscover2 libdouble-conversion3 libdrm-amdgpu1 libdrm-common libdrm-intel1 libdrm-nouveau2 libdrm-radeon1 libdrm2 libduktape207 libdw1 libedit2 libefiboot1 libefivar1 libegl-mesa0 libegl1 libelf1 libepoxy0 libevdev2 libexif12 libexpat1 libext2fs2 libfdisk1 libffi8 libfftw3-single3 libfido2-1 libfile-find-rule-perl libfm-data libfm-extra4 libfm-gtk-data libfm-gtk4 libfm-modules libfm4 libfontconfig1 libfontenc1 libfreetype6 libfribidi0 libfuse3-3 libgail-common libgail18 libgbm1 libgcc-s1 libgck-1-0 libgcr-base-3-1 libgcr-ui-3-1 libgcrypt20 libgdbm-compat4 libgdbm6 libgdk-pixbuf-2.0-0 libgdk-pixbuf2.0-bin libgdk-pixbuf2.0-common libgif7 libgirepository-1.0-1 libgl1-mesa-dri libgl1 libglapi-mesa libglib2.0-0 libglib2.0-bin libglib2.0-data libglu1-mesa libglvnd0 libglx-mesa0 libglx0 libgmp10 libgnutls30 libgomp1 libgpg-error0 libgpgme11 libgraphite2-3 libgs-common libgs10-common libgs10 libgssapi-krb5-2 libgstreamer-plugins-base1.0-0 libgstreamer1.0-0 libgtk-3-0 libgtk-3-bin libgtk-3-common libgtk2.0-0 libgtk2.0-bin libgtk2.0-common libgudev-1.0-0 libharfbuzz0b libheif1 libhogweed6 libhunspell-1.7-0 libhwy1 libice6 libicu72 libid3tag0 libidn12 libidn2-0 libijs-0.35 libimlib2 libinput-bin libinput10 libio-pty-perl libip4tc2 libip6tc2 libipc-run-perl libisl23 libjbig0 libjbig2dec0 libjim0.81 libjpeg-turbo-progs libjpeg62-turbo libjq1 libjson-c5 libjxl0.7 libk5crypto3 libkeyutils1 libklibc libkmod2 libkrb5-3 libkrb5support0 libksba8 liblcms2-2 libldap-2.5-0 libldap-common liblerc4 libllvm15 liblocale-gettext-perl libluajit-5.1-2 libluajit-5.1-common liblz4-1 liblzma5 libmagic-mgc libmagic1 libmbim-glib4 libmbim-proxy libmd0 libmd4c0 libmenu-cache-bin libmenu-cache3 libminizip1 libmnl0 libmount1 libmpc3 libmpfr6 libmsgpackc2 libmtdev1 libncurses6 libncursesw6 libnetfilter-conntrack3 libnettle8 libnewt0.52 libnfnetlink0 libnftnl11 libnghttp2-14 libnl-3-200 libnl-genl-3-200 libnode108 libnpth0 libnsl2 libnspr4 libnss-nis libnss-nisplus libnss3 libntfs-3g89 libnuma1 libnumber-compare-perl libobrender32v5 libobt2v5 libogg0 libonig5 libopengl0 libopenjp2-7 libopus0 liborc-0.4-0 libp11-kit0 libpam-modules-bin libpam-modules libpam-runtime libpam-systemd libpam0g libpango-1.0-0 libpangocairo-1.0-0 libpangoft2-1.0-0 libpangoxft-1.0-0 libpaper-utils libpaper1 libparted-fs-resize0 libparted2 libpci3 libpciaccess0 libpcre2-16-0 libpcre2-8-0 libpcre3 libperl5.36 libpipeline1 libpixman-1-0 libplymouth5 libpng16-16 libpolkit-agent-1-0 libpolkit-gobject-1-0 libpopt0 libproc2-0 libpsl5 libpython3-stdlib libpython3.11-minimal libpython3.11-stdlib libqmi-glib5 libqmi-proxy libqrtr-glib0 libqt5core5a libqt5dbus5 libqt5gui5 libqt5network5 libqt5printsupport5 libqt5qml5 libqt5qmlmodels5 libqt5quick5 libqt5svg5 libqt5waylandclient5 libqt5waylandcompositor5 libqt5widgets5 libqt5x11extras5 libreadline8 librsvg2-2 librsvg2-common librtmp1 libsamplerate0 libsasl2-2 libsasl2-modules-db libsasl2-modules libseccomp2 libsecret-1-0 libsecret-common libselinux1 libsemanage-common libsemanage2 libsensors-config libsensors5 libsepol1 libsepol2 libslang2 libsm6 libsmartcols1 libspectre1 libsqlite3-0 libss2 libssh2-1 libssl1.1 libssl3 libstartup-notification0 libstdc++6 libsystemd-shared libsystemd0 libtasn1-6 libtermkey1 libtext-charwidth-perl libtext-glob-perl libtext-iconv-perl libtext-wrapi18n-perl libthai-data libthai0 libtheora0 libtiff6 libtime-duration-perl libtimedate-perl libtinfo6 libtirpc-common libtirpc3 libtree-sitter0 libturbojpeg0 libuchardet0 libudev1 libudfread0 libudisks2-0 libunibilium4 libunistring2 libunwind8 libusb-1.0-0 libutempter0 libuuid1 libuv1 libvisual-0.4-0 libvolume-key1 libvorbis0a libvorbisenc2 libvterm0 libwacom-bin libwacom-common libwacom9 libwayland-client0 libwayland-cursor0 libwayland-egl1 libwayland-server0 libwebp7 libwebpdemux2 libwrap0 libx11-6 libx11-data libx11-xcb1 libx265-199 libxatracker2 libxau6 libxaw7 libxcb-damage0 libxcb-dri2-0 libxcb-dri3-0 libxcb-glx0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-present0 libxcb-randr0 libxcb-render-util0 libxcb-render0 libxcb-shape0 libxcb-shm0 libxcb-sync1 libxcb-util1 libxcb-xfixes0 libxcb-xinerama0 libxcb-xinput0 libxcb-xkb1 libxcb1 libxcomposite1 libxcursor1 libxcvt0 libxdamage1 libxdmcp6 libxdo3 libxext6 libxfixes3 libxfont2 libxft2 libxi6 libxinerama1 libxkbcommon-x11-0 libxkbcommon0 libxkbfile1 libxml2 libxmu6 libxmuu1 libxpm4 libxrandr2 libxrender1 libxshmfence1 libxss1 libxt6 libxtables12 libxtst6 libxv1 libxvmc1 libxxf86dga1 libxxf86vm1 libxxhash0 libz3-4 libzstd1 linux-base linux-image-5.10.0-21-amd64 linux-image-6.1.0-10-amd64 linux-image-amd64 lm-sensors locales login logrotate logsave lsb-base lsof lua-luv lxmenu-data lxpolkit lxsession-data mailcap man-db mawk media-types mime-support moreutils mount ncal ncurses-base ncurses-bin ncurses-term neovim-runtime neovim netbase node-acorn node-busboy node-cjs-module-lexer node-undici node-xtend nodejs-doc nodejs notification-daemon ntfs-3g obconf openbox openssh-client openssh-server openssh-sftp-server openssl parted passwd pci.ids pciutils pcmanfm perl-base perl-modules-5.36 perl pinentry-curses pinentry-gnome3 pkexec plymouth-label plymouth policykit-1-gnome policykit-1 polkitd-pkla polkitd poppler-data procps psmisc publicsuffix python3-cairo python3-gi-cairo python3-gi python3-greenlet python3-libevdev python3-minimal python3-msgpack python3-pynvim python3-pyudev python3.11-minimal python3.11 python3 qt5-gtk-platformtheme qttranslations5-l10n qtwayland5 readline-common runit-helper scrot sed sensible-utils sgml-base shared-mime-info sudo systemd-sysv systemd-timesyncd systemd sysvinit-utils tar tzdata ucf udev udisks2 unzip usb-modeswitch-data usb-modeswitch usbutils usrmerge util-linux-extra util-linux-locales util-linux vim-common whiptail wmctrl x11-apps x11-common x11-session-utils x11-utils x11-xkb-utils x11-xserver-utils xauth xbitmaps xclip xcvt xdotool xfonts-100dpi xfonts-75dpi xfonts-base xfonts-encodings xfonts-scalable xfonts-utils xinit xkb-data xml-core xorg-docs-core xorg xserver-common xserver-xorg-core xserver-xorg-input-all xserver-xorg-input-libinput xserver-xorg-input-wacom xserver-xorg-legacy xserver-xorg-video-all xserver-xorg-video-amdgpu xserver-xorg-video-ati xserver-xorg-video-fbdev xserver-xorg-video-intel xserver-xorg-video-nouveau xserver-xorg-video-qxl xserver-xorg-video-radeon xserver-xorg-video-vesa xserver-xorg-video-vmware xserver-xorg xterm xxd xz-utils yad yudit-common zlib1g zstd libcupsimage2

# Actualizar Debian Bookworm

cd /home/cvc/  
curl -s -L https://comunicacionvisualcanarias.com/software/update1\_2023/update.sh -o update.sh  
chmod +x update.sh  
./update.sh

# CVC | Ficha Ténica de RED para Equipos y Dispositivos

Este documento sirve para informar al equipo de informática sobre la instalación de los equipos y dispositivos de **Comunicación Visual Canarias**, como hilos musicales, reproductor de publicidad, dispensador de turnos o tablets.

El objetivo es **detallar cómo se configuran los equipos en la red** y qué requerimientos son necesarios, para que departamento informático tenga toda la información antes de la instalación.

#### --------------------------------------------------------------------------------------


#### **Responsabilidades del instalador**

- El instalador **solicita y recibe el rango de IP y puerta de enlace** para cada ordenador o dispositivo.
- El instalador configura el ordenador o dispositivo **exactamente con los datos proporcionados**.
- El instalador <u>NO REALIZA CAMBIOS EN LA RED</u> del cliente (routers, switches, VLANs, firewalls, etc.).
- El instalador conecta los equipos únicamente en el **switch y puerto indicado** por el cliente o proveedor de red.

#### --------------------------------------------------------------------------------------


#### **Parámetros de red a configurar**

Para cada equipo se deben configurar los siguientes datos:

- **Dirección IP**
- **Puerta de enlace**
- **Máscara de red**

Estos permiten que el equipo tenga acceso a la red y a Internet para descargar contenidos y promociones, reproducir música y sincronizarse correctamente.

#### --------------------------------------------------------------------------------------


#### **Puertos y servicios utilizados**

<table id="bkmrk-puerto-protocolo-uso"><thead><tr><th>Puerto</th><th>Protocolo</th><th>Uso</th><th>Alcance</th></tr></thead><tbody><tr><td>80</td><td>TCP</td><td>Descarga de contenidos, promociones y música</td><td>Internet (saliente)</td></tr><tr><td>444</td><td>TCP</td><td>Control remoto mediante *MeshCentral*</td><td>Internet (saliente)</td></tr><tr><td>3000</td><td>TCP</td><td>Comunicación interna entre dispositivos (reproductores, tablets, turnomaric)</td><td>Red interna</td></tr><tr><td>123</td><td>UDP</td><td>Sincronización horaria (NTP)</td><td>Internet (saliente)</td></tr></tbody></table>

**Notas importantes:**

- Todas las conexiones son **salientes**, no se requieren accesos entrantes desde Internet.
- El correcto funcionamiento depende de que estos puertos estén permitidos por la red existente.
- *MeshCentral* se utiliza para el control remoto, siempre mediante **conexiones iniciadas por el propio equipo**.

#### --------------------------------------------------------------------------------------

#### **Mesh Central**

***MeshCentral*** es una plataforma de control y gestión remota de dispositivos que permite administrar ordenadores de forma segura sin intervenir la red del cliente.

**Cómo funciona**

- Cada dispositivo **inicia la conexión** hacia el servidor central; **no se necesitan puertos entrantes** ni cambios en firewalls o routers.
- La comunicación está **cifrada** y el servidor central actúa como intermediario entre técnicos y dispositivos.
- Funciones principales: control remoto, transferencia de archivos, monitorización y despliegue de actualizaciones.
- En nuestros equipos, la conexión remota usa **puerto 444/TCP saliente**.

**Ventajas**

- Seguridad: la red del cliente **no se expone**.
- Simplicidad: no requiere cambios en la infraestructura.
- Control centralizado: permite supervisar y gestionar los dispositivos de manera eficiente.

#### --------------------------------------------------------------------------------------


#### **Consideraciones**

- El equipo no modifica la infraestructura de red del cliente.
- La conexión al puerto de red indicado es obligatoria; **no se deben usar puertos aleatorios**.
- La hora debe estar sincronizada correctamente para la reproducción de contenidos y eventos.
- El equipo solo se comunica con servidores y dispositivos autorizados.

#### --------------------------------------------------------------------------------------

#### **Casos Excepcionales**

En equipos que han permanecido largos periodos sin conexión, puede ocurrir que recuperen Internet y funcionen correctamente a nivel de contenidos, pero que el acceso remoto no esté disponible y que el equipo no siempre aparezca online en MeshCentral. En estos casos, se recomienda confirmar si existe algún servicio o regla habilitada distinta a las previamente enviadas y revisar los logs de la DNS, incluyendo la parte superior del listado, ya que pueden existir descartes de conexión. La solución consiste en añadir una regla de excepción en la DNS o firewall para permitir la comunicación, sin necesidad de realizar cambios en el equipo.

#### --------------------------------------------------------------------------------------


#### **Conclusión**

> Los equipos se configuran con la IP y puerta de enlace proporcionadas, se conectan al puerto de red indicado y utilizan los puertos 80, 444, 3000 y 123 para sus funciones. El control remoto se realiza mediante *MeshCentral*, iniciando la conexión desde el equipo, sin necesidad de abrir accesos entrantes ni modificar la red del cliente.

#### --------------------------------------------------------------------------------------

# Snippets

Snippets útiles

# SQL snippets

Snippets útiles para consultas SQL

#### Copia de eventos en intervalos de tiempo

> DROP TEMPORARY TABLE IF EXISTS temptab;  
> CREATE TEMPORARY TABLE temptab ( hora TIME );
> 
> DELIMITER //
> 
> FOR i IN 1..55  
> DO  
>  SET @HOUR = 8+TRUNCATE(i/4,0);  
>  SET @MINUTE = (i\*15)%60;  
>  SET @horaCompleta = CONCAT(@HOUR, ':', @MINUTE, ':00');  
>  INSERT INTO temptab(hora) VALUES(@horaCompleta);  
>  INSERT INTO events(`name`,`type`,`dateFrom`,`dateTo`,`time`,`weekdays`,`devices`,`data`)  
>  VALUES(  
>  CONCAT('MarketPuertoRico-AvisoNatural',i),  
>  'media',  
>  '2023-01-01',  
>  '2060-01-01',  
>  @horaCompleta,  
>  127,  
>  '1,138,168,169,170,172,173,174,175,176,177,178,179,180,181,182',  
>  '455'  
>  );  
> END FOR;  
> //
> 
> DELIMITER ;
> 
> SELECT \* FROM temptab;

# Crear certificado privado SSL + root CA

Crear certificado autofirmado con openssl para servidores de pruebas con HTTPS, certificados para tablets, etc.

#### domain.ext

> authorityKeyIdentifier=keyid,issuer  
> basicConstraints=CA:FALSE  
> subjectAltName = @alt\_names  
> \[alt\_names\]  
> DNS.1 = domain  
> DNS.2 = \*.domain

#### Create Private Key and Signing Request (csr)

> openssl req -newkey rsa:2048 -nodes -keyout domain.key -out domain.csr

#### Certificate

> openssl x509 -req -CA rootCA.crt -CAkey rootCA.key -in domain.csr -out domain.crt -days 365 -CAcreateserial -extfile domain.ext

#### Crear nuevo root CA  


> openssl req -x509 -sha256 -days 1825 -newkey rsa:2048 -keyout rootCA.key -out rootCA.crt

# Copiar servidor

Comandos para hacer una copia completa del servidor de Arsys

#### Directo con SSH en destino y puerto 666

> ***Ejecutar en el servidor a clonar:***
> 
> dd if=/dev/sda bs=64M status=progress | pigz -c | ssh root@92.172.240.225 -p 666 'pigz -d | dd of=/dev/sda'

dd if=/dev/sda | pigz | nc -w 3 localhost 62222  
nc -l -p 62222 | dd of=/dev/sda bs=64M

# Registrar version en servidor

<p class="callout info">Ejecutar como usuario</p>

> if \[ -f /home/cvc/system.cfg \]; then  
> set -a &amp;&amp; . /home/cvc/system.cfg &amp;&amp; set +a  
> else  
> set -a &amp;&amp; . /home/cvc/system/system.cfg &amp;&amp; set +a  
> fi  
> curl "https://www.comunicacionvisualcanarias.com/\_ext/logs/log.php?mode=version&amp;client=$CLIENT&amp;device="$ID"&amp;version="$VERSION

# Servidor de correos local

Realizar una copia de los correos al servidor:

- Encender el ordenador del servidor
- Buscar correo original en thunderbird
- click derecho -&gt; copiar a "usuario Copia

# Sistema instalado en los equipos

### Sistema Operativo

A los equipos en producción en los clientes se les instala un sistema personalizado **GNU/Linux Debian 12.**

El sistema tiene instalado únicamente el gestor de ventanas **Openbox**. Como gestor de arranque utiliza **systemd-boot** y como gestor de red, **systemd-networkd**.

El gestor de audio es **ALSA**. No se utiliza pulse-audio ni pipewire porque causaban problemas con los drivers de algunos dispositivos, así que no existe cambio automático de dispositivo de salida en caliente. El archivo *~/.asoundrc* tiene la configuracion de ALSA.

El journal del sistema está limitado a 128M para que no crezca excesivamente. No tiene partición Swap y tiene desactivado ipv6 y las mitigaciones de Meltdown y Spectre para aumentar el rendimiento de las CPU a través del bootloader.

Hay una serie de scripts en *~/scripts* que se encargan de funciones básicas como descarga de contenidos, mantener las aplicaciones abiertas, etc.

El splash inicial se muestra con **Plymouth**.

**No tiene ningún demonio de actualizaciones automáticas.** Es buena idea actualizar los sistemas con los parches de seguridad con apt. Dos scripts de postinst se encargan de copiar el kernel y el initramfs a la partición EFI cuando éstos son actualizados.

<span style="background-color: rgb(191, 237, 210); color: rgb(0, 0, 0);">El usuario del sistema es 'cvc' y la contraseña, 'cvc'.</span>

### Proceso de desplegado

Para la instalación en los equipos utilizamos una unidad USB con un **Clonezilla** personalizado y un script que se encarga de todo el proceso de instalación. Hay una copia de dicha unidad en *D:\\CVC\_System.*

Para comenzar la instalación solo hay que arrancar el equipo desde el pendrive y esperar entre 2 y 5 minutos dependiendo de la velocidad de almacenamiento interno. El equipo se reiniciará automáticamente al finalizar la instalación.

La imagen USB solo es compatible con UEFI.

### Directorios de interés

##### ~/apps

Las aplicaciones de emisión de contenidos, totem y servidor de turnos.

##### ~/deploy

Los contenidos, música y demás que se descargan desde el servidor de desplegado.

##### ~/logs

Registros de actividad del sistema a través del script *logger* y registros de las aplicaciones.

##### ~/resources

Recursos de uso del sistema como el fondo de pantalla, los iconos del menu de openbox, el agente de control

##### ~/resources/defaults

Aquí se almacenan los perfiles de los clientes comunes para personalizar el aspecto y configuración de las aplicaciones, fondo de pantalla, tema de plymouth y demás. La aplicación de configuración utiliza esta carpeta para aplicar los cambios al sistema.

#### ~/scripts

Scripts de BASH para funciones básicas del sistema.

- appsCtrl: se encarga de abrir y cerrar las aplicaciones de emisión y mantenerlas en primer plano
- boot: aplica resolución, salida de audio, el fondo y la aplicación especificadas en ~/system.cfg
- CONFIG.app: es una aplicación gráfica para configurar y dejar listo rápidamente un equipo.
- genList\*: genera las listas de contenidos y música a partir del contenidos de las carpetas
- logger: guarda registros del sistema para depuración
- sleepWake: suspende el equipo con y programa la alarma RTC para que despierte a una hora y luego, reinicia el equipo.
- sync: sincroniza contenidos, música y horarios desde el servidor de despliegue
- syncUsb\*: copia contenidos y configuraciones desde un pendrive que tenga la carpeta .CVC. Este script se ejecuta con una regla UDEV.

> \*NOTA: En la versión actual, los scripts genList y syncUsb no funcionan correctamente. Éstos se encargaban de copiar contenidos desde un USB y generar listas json a partir pero tras ciertos cambios en el formato de las listas, cayó en desuso y no se ha actualizado para soportar la nueva versión. Ésto servía para actualizar contenidos, música y configuración simplemente introduciendo un pendrive en los equipos con una carpeta *.CVC* dentro. Unas reglas en Udev permite ejecutar el script syncUsb cuando se introduce un pendrive. Si fuese necesario en el futuro, se podría reparar este sistema, que puede ser útil para realizar cambios en entornos en los que no haya red, como un evento.

# Datos en el equipo de desarrollo

La mayoría de las aplicaciones están en la máquina virtual de VMware 'Debian' con la red puenteada con la IP 192.168.3.2

Las aplicaciones con interfaz gráfica en ElectronJS están en D:\\Apps

En el disco D:\\ está todo lo relacionado con desarrollo.

En el disco E:\\ están los datos de diseño, las máquinas vituales y otras cosas.

# Otras Cosas



# Raspberry Oficina CVC

- La raspberry pi conectada al switch de la oficina tiene el servidor DHCP y DNS de la red interna. Su ip es 192.168.1.20, usuario 'dietpi' y contraseña 'cvc'. Utiliza el demonio dnsmaskq como servidor DHCP y DNS.

# Plugins



# Adobe After Effects: Mr.Horse

Información sobre el plugin **Mr.Horse** para **Adobe After Effect**s.

[![imagen.png](https://documentacion.comunicacionvisualcanarias.com/uploads/images/gallery/2025-08/scaled-1680-/OSfimagen.png)](https://documentacion.comunicacionvisualcanarias.com/uploads/images/gallery/2025-08/OSfimagen.png)

\------------------------------------------------------------------------------------------------------------------------------------------------

[**PÁGINA WEB DEL PLUGIN**](https://misterhorse.com/)

[https://misterhorse.com/](https://misterhorse.com/)

**Mr.Horse** es un plugin <span style="text-decoration: underline; color: rgb(35, 111, 161);">TOTALMENTE GRATUITO</span>.

Su única limitación es que solo puede estar activo en dos ordenadores a la vez por cada cuenta registrada.

\------------------------------------------------------------------------------------------------------------------------------------------------

**CUENTAS REGISTRADAS EN MR.HORSE**

- creativo.cvc@gmail.com
- desarrollo@comunicacionvisualcanarias.com

**Contraseña:** ComunicacionVisualCanarias650mrhorse.-+

\------------------------------------------------------------------------------------------------------------------------------------------------

**¿POR QUÉ MR.HORSE?**

- Es extremadamente útil y cómodo para animar texto.
- Ahorro exponencial en tiempo para aplicar efectos gráficos.
- Tiene varios "prefabs" animados como flechas o casillas de fácil adaptación.
- Transiciones variadas y adaptables de bajo consumo.
- A diferencia de otros plugins, pueden abrirse proyectos que requieran **Mr.Horse** sin tenerlo instalado en el equipo.

\------------------------------------------------------------------------------------------------------------------------------------------------

**TUTORIALES**

El perfil de YouTube **Crehana** dispone de un sencillo tutorial de menos de 6 minutos donde explica como instalar el programa y su uso general.

**[Videotutorial: Mr.Horse](https://www.youtube.com/watch?v=outWOOFJuYU)**

# Scripts Originales

Scripts .PHP originales de la base de datos.

# SO: cambioHora.php

**Script .PHP original de cambio de hora en un subdominio.**

<span style="color: rgb(35, 111, 161);">***SUMAR HORA: VERANO***</span>

- [https://spar.comunicacionvisualcanarias.com/\_scripts/cambioHora.php?sum=1](https://spar.comunicacionvisualcanarias.com/_scripts/cambioHora.php?sum=1)
- [https://frigomartel.comunicacionvisualcanarias.com/\_scripts/cambioHora.php?sum=1](https://frigomartel.comunicacionvisualcanarias.com/_scripts/cambioHora.php?sum=1)
- [https://pizzaroyers.comunicacionvisualcanarias.com/\_scripts/cambioHora.php?sum=1](https://pizzaroyers.comunicacionvisualcanarias.com/_scripts/cambioHora.php?sum=1)
- [https://cashconverters.comunicacionvisualcanarias.com/\_scripts/cambioHora.php?sum=1](https://cashconverters.comunicacionvisualcanarias.com/_scripts/cambioHora.php?sum=1)

**<span style="color: rgb(35, 111, 161);">*RESTAR HORA: INVIERNO*</span>**

- [https://spar.comunicacionvisualcanarias.com/\_scripts/cambioHora.php?sum=-1](https://spar.comunicacionvisualcanarias.com/_scripts/cambioHora.php?sum=-1)
- [https://frigomartel.comunicacionvisualcanarias.com/\_scripts/cambioHora.php?sum=-1](https://frigomartel.comunicacionvisualcanarias.com/_scripts/cambioHora.php?sum=-1)
- [https://pizzaroyers.comunicacionvisualcanarias.com/\_scripts/cambioHora.php?sum=-1](https://pizzaroyers.comunicacionvisualcanarias.com/_scripts/cambioHora.php?sum=-1)
- [https://cashconverters.comunicacionvisualcanarias.com/\_scripts/cambioHora.php?sum=-1](https://cashconverters.comunicacionvisualcanarias.com/_scripts/cambioHora.php?sum=-1)

\-------------------------------------------------------------------------------------------------------------------------------------

**Compatible con:**

- Spar Gran Canaria
- Frigo Martel
- Pizza Royers
- Cash Converters

\-------------------------------------------------------------------------------------------------------------------------------------

> &lt;?php  
> if ( isset($\_GET\['sum'\]) ) {  
>  require \_\_DIR\_\_.'/../boot.php';  
>  global $mysql;  
>  $devices = $mysql-&gt;consulta('SELECT id, power FROM devices');  
>    
>    
>  foreach ($devices as $k =&gt; $dev) {  
>  $power = json\_decode($dev\['power'\]);  
>  $domingo = $power-&gt;D-&gt;on;  
>  $lunes = $power-&gt;L-&gt;on;
> 
>  if ($domingo == '') { // Si no enciende domingo, cambia lunes  
>  $parts = explode(':',$lunes);  
>  $parts\[0\] += $\_GET\['sum'\];  
>  $newLunes = str\_pad($parts\[0\],2,'0',STR\_PAD\_LEFT).':'.$parts\[1\];  
>  $power-&gt;L-&gt;on = $newLunes;  
>  } else { // Si enciende domingo, cambia domingo  
>  $parts = explode(':',$domingo);  
>  $parts\[0\] += $\_GET\['sum'\];  
>  $newDomingo = str\_pad($parts\[0\],2,'0',STR\_PAD\_LEFT).':'.$parts\[1\];;  
>  $power-&gt;D-&gt;on = $newDomingo;  
>  }
> 
>  $sql = "UPDATE devices SET power='".json\_encode($power)."' WHERE id=".$dev\['id'\];  
>  //echo $sql . '&lt;br&gt;&lt;br&gt;';  
>  $mysql-&gt;consulta($sql,false);  
>  }  
>    
>  echo "Se ha sumado " . $\_GET\['sum'\] . " horas a todos los equipos";
> 
>  \\cache\\clearAll(\\cache\\type::all);  
> }  
> ?&gt;

# SO: borrarCache.php

**Script .PHP que borra la cache de un subdominio.**

- [https://spar.comunicacionvisualcanarias.com/\_scripts/borrarCache.php](https://spar.comunicacionvisualcanarias.com/_scripts/borrarCache.php)
- [https://frigomartel.comunicacionvisualcanarias.com/\_scripts/borrarCache.php](https://frigomartel.comunicacionvisualcanarias.com/_scripts/borrarCache.php)
- [https://pizzaroyers.comunicacionvisualcanarias.com/\_scripts/borrarCache.php](https://pizzaroyers.comunicacionvisualcanarias.com/_scripts/borrarCache.php)
- [https://cashconverters.comunicacionvisualcanarias.com/\_scripts/borrarCache.php](https://cashconverters.comunicacionvisualcanarias.com/_scripts/borrarCache.php)

\-------------------------------------------------------------------------------------------------------------------------------------

**Compatible con:**

- Spar Gran Canaria
- Frigo Martel
- Pizza Royers
- Cash Converters

\-------------------------------------------------------------------------------------------------------------------------------------

> &lt;?php  
>  require \_\_DIR\_\_.'/../boot.php';
> 
>   
>  switch ($\_GET\['type'\]) {  
>  case 'media':  
>  cache\\clearAll(\\cache\\type::media);  
>  break;  
>  case 'music':  
>  cache\\clearAll(\\cache\\type::music);  
>  break;  
>  case 'events':  
>  cache\\clearAll(\\cache\\type::events);  
>  break;  
>  case 'config':  
>  cache\\clearAll(\\cache\\type::config);  
>  break;  
>  }  
> ?&gt;

# SO: restaurarHorarios.php

> <div>&lt;?php</div><div> require __DIR__.'/../boot.php';</div><div> global $mysql;</div><div>  
> </div><div>  
> </div><div>$sql = file_get_contents(__DIR__.'/horariosSpar221213.sql');</div><div> $mysql-&gt;consulta($sql,false);</div><div>  
> </div><div> cache\clearAll(\cache\type::config);</div><div>?&gt;</div>

# SO: cambiarCanal.php

**Script encargado de cambiar todas las tiendas a un mismo Canal Musical.**

> &lt;?php  
>  if (@!!$\_GET\['canal'\]) {   
>  require \_\_DIR\_\_.'/../boot.php';  
>  global $mysql;
> 
>  $sql = 'UPDATE shops SET canal='.$\_GET\['canal'\];  
>  $mysql-&gt;consulta($sql,false);  
>    
>  echo "Canal cambiado en todos los equipos a: " . $\_GET\['canal'\];
> 
>  cache\\clearAll(\\cache\\type::deploy);  
>  }  
> ?&gt;

**Ejemplo:**

https://spar.comunicacionvisualcanarias.com/\_scripts/cambiarCanal.php?canal=1

# SO: randomCanal.php

**Script encargado de re-mezclar las canciones de la lista de reproducción.**

> &lt;?php  
>  if (@!!$\_GET\['canal'\]) {   
>  require \_\_DIR\_\_.'/../boot.php';  
>  global $mysql;
> 
>  $sql = 'SELECT songs FROM musicPlaylists WHERE id='.$\_GET\['canal'\];  
>  $songList = @$mysql-&gt;consulta($sql)\[0\]\['songs'\];  
>    
>  if (!!!$songList) {  
>  echo "No existe el canal"; return;  
>  }
> 
>  $songList = explode(',', $songList);  
>  shuffle($songList);  
>  $songList = implode(',', $songList);
> 
>  $sql = 'UPDATE musicPlaylists SET songs="'.$songList.'" WHERE id='.$\_GET\['canal'\];  
>  $mysql-&gt;consulta($sql);  
>    
>    
>  echo "Orden de canciones aleatorizada. Canal: " . $\_GET\['canal'\];  
>  cache\\clearAll(\\cache\\type::deploy);  
>  }  
> ?&gt;

**Ejemplo:**

https://spar.comunicacionvisualcanarias.com/\_scripts/randomCanal.php?canal=1