Roundcube: cambiar color skin elastic

Hoy he instalado un roundcube y para hacérmelo más fácil he seguido éste post que hice hace un par de añitos (Gracias Blackhold del pasado por este post!).

Con la versión instalada hoy no me funcionaba el tema larry, así que me he quedado con el tema que viene por defecto, elastic. Al poner el logo, el azul de larry quedaba horrorosamente feo, así que he avanzado un poquito más con la personalización de roundcube. Buscando he llegado a este hilo del foro de roundcube. Decían de modificar el fichero styles.less y compilar los css (¿mande?)

Os lo cuento:

Para cambiar el color del botón de login he tenido que modificar el fichero skins/elastic/styles/styles.less y añadir lo siguiente

#login-form button.mainaction {
  background-color: #8a77b0;
  border-color: #123456;

  &:hover {
    background-color: #123456;
  }
}

Para cambiar el color global, por defecto azul claro, el otro fichero que es necesario modificar es skins/elastic/styles/colors.less y definir en @color-main el color que nos interese, en mi caso:

@color-main:                #8a77b0;

A continuación, para generar el css es necesario instalar el paquete “node-less”:

# apt -y install node-less

Y finalmente ejecutar lo siguiente para aplicar los cambios en los ficheros .less

lessc styles.less styles.min.css

Y ahora ya tienes el roundcube con el color que se adecue a tu empresa o la de tu cliente :)…

Saltando bloqueos de los ISP: HAProxy y autossh

¡Este último mes podríamos decir que he estado muy entretenida! Hace ya casi dos años, un cliente vino a mi harto de que los proveedores de hosting le cerrasen el servidor, durante todo este tiempo de maravilla, hasta que hace un mes y medio Movistar y Vodafone bloquearon el dominio. Ahí es cuando el cliente me contactó de nuevo para realizar un análisis y un informe pericial. El motivo es que el cliente no está realizando ningún acto delictivo que lleve a los proveedores de hosting e ISP a bloquear el servicio, aún así, lo hacen, estamos delante de un caso de Internet Blackout, bloqueo interesado de un servicio en concreto para que los usuarios no puedan acceder a él. ¿Algo ha tenido que ver el recién finalizado y polémico Mundial de Fútbol en Qatar?.

En la fecha del bloqueo del dominio del cliente, mi propuesta al identificar que el bloqueo se estaba realizando a nivel de dominio (que no de DNS, ya que estos si resolvían), le propuse al cliente de registrar otro dominio. La solución funcionó durante 2 semanas más hasta que Movistar y Vodafone bloquearon la dirección IP, como tal, la solución de añadir mas dominios apuntando al servidor, ya no era útil. Por mas INRI, el bloqueo se extendió a más ISP, aislando casi por completo el servidor de Internet (y no sólo en España, otros países de Europa y LatinoAmérica se vieron afectados), pero no todos lo bloquearon!

A partir de aquí se empezó a …

Crear USB Windows 11 con Debian 11

Primero, me da verguenza tener que instalar un windows, pero para un trabajo lo necesito.
Segundo, no dispongo de ningún otro windows para crear el instalable por USB de Windows 11.
Conclusión: Problemas

Así que vamos a ver que he hecho, que tenemos que tener en cuenta y que problemas me he encontrado.

Para crear un USB para instalar Windows, es necesario que este esté en formato FAT32, si algo sabes de sistemas de archivo, el tamaño máximo para los ficheros de FAT32 es de 4Gb, pero en la ISO de Windows 11, hay un ficherito de marras llamado install.wim que pesa exactamente 4.8Gb.

Mi primera opción ha sido usar el comando dd para tostar la ISO al pincho USB. Nada. Lo he probado primero sobre /dev/sdb y nada, lo segundo sobre /dev/sdb1 y tampoco.

La segunda ha sido usar unetbootin y tampoco. He probado de formatear el pincho USB en fat32, en exFAT y NTFS y nada. El problema es que el fichero install.wim no se pasa completamente al pesar mas de 4Gb.

Así que la solución ha pasado por usb el paquete de ubuntu mkusb.

Para ello añadiremos los sources de ubuntu

# vi /etc/apt/sources.list
deb http://ppa.launchpad.net/mkusb/ppa/ubuntu focal main

# apt-key adv --keyserver keyserver.ubuntu.com --recv 54B8C8AC
# apt update
# apt -y install mkusb sudo
$ sudo mkusb

En debian el root no está configurado para cargar aplicaciones gráficas, para ejecutar un comando como root, será necesario usar el comando sudo.

Seguiremos las instrucciones tal como indica esta …

Nextcloud: definir quota de usuario por CLI con occ

En uno de los nextcloud que administro, tras unos meses de uso el usuario evidentemente quiere mas espacio. En su momento les definí 1Tb cuando la capacidad total del disco es de 2Tb. Ni idea de porqué lo hice así, hoy me he encontrado de nuevo el porqué, y es que no ha habido forma humana para definir en el interfaz web una quota de usuario de 1,5Tb, ni poniendo 1500Gb, ni con espacio, ni sin ni la madre que lo parió. Así que otra forma de hacerlo es mediante el uso del comando occ.

La forma de definir una quota al usuario entonces sería:

root@***cloud:~# su - www-data -s /bin/bash
www-data@***cloud:~$ cd html/nextcloud
www-data@***cloud:~/html/nextcloud$ chmod +x occ
www-data@***cloud:~/html/nextcloud$ ./occ user:setting admin files quota 1500GB

Para ver si se ha aplicado la quota correctamente

www-data@***cloud:~/html/nextcloud$ ./occ user:info admin
  - user_id: admin
  - display_name: admin
  - email: 
  - cloud_id: admin@cloud.***.***
  - enabled: true
  - groups:
    - admin
  - quota: 1500GB
  - storage:
    - free: 589345344031
    - used: 1021267391969
    - total: 1610612736000
    - relative: 63.41
    - quota: 1610612736000
  - last_seen: 2022-09-15T08:59:09+00:00
  - user_directory: /var/www/nextclouddata/admin
  - backend: Database

Fuente: help.nextcloud.com

Archivar los mails del sistema con chewmail

Al ir actualizando los sistemas a veces te encuentras que paquetes que solías usar han dejado de estar mantenidos y ya no aparecen en los repositorios, es posible que incluso al ejecutar el apt-autoremove se rompan cosas, así que mucho cuidado al ejecutarlo.

El caso que me lleva a hacer este post es con el comando archivemail, que tiene como dependencia python2.x, y en la versión 11.4 de debian el paquete ya no está o vete a saber que ha pasado (juraría que en 11.1 si estaba). Sea lo que sea, archivemail no está en los repositorios y toca buscar alternativa, chewmail.

Para instalarlo

# apt -y install chewmail

Luego en el fichero /etc/crontab tendremos que modificar la línea de la siguiente forma:

# clean mails
#59 23    * * *  root            archivemail -d 7 --delete /var/spool/mail/root
59 23    * * *  root            chewmail --days 7 -o root-old root && rm root-old

Me he peleado un rato con el uso del comando y es obligatorio indicarle el destino de los correos electrónicos archivados (-o root-old), hay una opción que es –delete-immediately pero ni caso, así que concateno al comando el borrar el fichero de mails archivados y listo.…

Django 4 y zonas horarias (timezone)

Aquí estamos con mi primer proyecto en el que tengo que tener en cuenta la zona horaria del usuario que visualiza los datos de la aplicación que estoy creando.

La aplicación recolecta unos datos de unos sensores y debe almacenarlos en la base de datos, pero luego estos datos que almaceno en mi servidor, tienen que corresponder a la hora del país donde se encuentra el sensor. Con esto empiezas a preguntarte, ¿cómo debo almacenar el dato? ¿cómo lo muestro?

Respuesta rápida:
– Pones tu aplicación en UTC
– Almacenas todos los datos de los sensores con UTC
– Visualizas los datos según la configuración horaria del navegador y/o del usuario

Al investigar sobre el tema, me han pasado un post en un blog muy divertido en el que explica todo esto de las zonas horarias, ¿sabías que existen 244 zonas horarias distintas y un total de 195 países? Y no todas las zonas horarias saltan de hora a hora, además de que nos encontramos en un país que tiene el horario de invierno y el de verano, cosa que no tienen todos los países. Vamos, todo esto de las zonas horarias es un cacao guapo, guapo, guapo.

Programando con Django, una cosa que me he encontrado varias veces es que hay 2 librerías que se llaman igual y se usan distinto (import datetime vs from datetime import datetime), un auténtico quebradero de cabeza que hace que código que funciona en una parte, no lo haga en otra. Al …

Volcado de memoria con LiME y análisis con Volatility

Un volcado de memoria consiste en almacenar todo lo que está en la RAM de nuestro sistema a un fichero para poder analizarlo posteriormente.

En la RAM se almacena toda aquella información volátil (que se destruye al apagar el sistema) y que contiene información útil sobre la ejecución de los procesos en funcionamiento en nuestro sistema operativo. Ahí también se almacenan contraseñas que están en uso para desbloquear por ejemplo ficheros o particiones cifradas. Así que la opción de “tirar del cable del servidor” para mitigar el problema, puede ser el peor error cometido. ¿Como demuestras quien estaba conectado a la máquina en el momento que ocurrió el problema? ¿Qué procesos se estaban ejecutando?

Nos puede interesar realizar un volcado de memoria por ejemplo si un ransomware está en ejecución y está cifrando los datos de nuestro sistema, para localizar datos se acceso a programas y servicios, identificar fallos y problemas con un software o analizar el funcionamiento de nuestro sistema.
Hay varias formas de realizar un dump de la memoria, todas se basan en el dispositivo “/dev/mem”. La más conocida es memdump, pero en algunos sistemas ejecutar memdump > fichero.dump implica un fallo total de nuestro sistema (¡Vamos! Que se reinicia solo). En resumen: “NO HAGAS ESTO!” (y aún menos en un sistema en producción). La mejor opción si queremos exportar el contenido de “/dev/mem” es hacer uso de dd

# dd if=/dev/mem of=volcado.mem bs=1M 

Si esto nos devuelve un fichero de un tamaño mucho inferior al …

Desplegando un servidor web con alta capacidad

Aquí estoy lamiéndome las heridas de esta noche pasada. Hace unas semanas un cliente me contactó para preparar para alta capacidad una página web que administra. La página web sirve para hacer las inscripciones a una carrera de motos y el día de las inscripciones aquello se pone a fuego.

Tras un presupuesto super ajustado, el cliente opta por la opción más económica. El resultado? pues tras varios “yaque” (instálame un servidor de correo “yaqueestás”), prisas y cambios a último momento, un aumento considerable del tráfico respeto el año pasado y vete a saber que más, el servidor ha estado super saturado y no ha podido servir todas las peticiones necesarias en tiempo y forma; al menos lo importante, que son las inscripciones, se hicieron y con un bajo porcentaje de fallo.

La aplicación está hecha con zendframework2, ergo php5.6, con configuraciones a fuego en el código de la configuración del servidor, correo, etc. Además la web se encontraba en un servidor CentOS 7.0 (del 2014), con unas configuraciones crípticas, no, lo siguiente. ¿Lo de respetar los directorios según LHFS?, ¡¿pa’qué?!.

Para no tener que tocar la configuración del servidor que estaba funcionando, decidí desplegar la página web en otro servidor en mi humilde infraestructura y realizar primero ahí las pruebas.

El entorno de pruebas
Se montó una maquina virtual lxc con debian 11, con 8Gb de RAM y 2 CPU Intel(R) Xeon(R) CPU E5-2670 0 @ 2.60GHz, en mi humilde infraestructura tengo un cuello de botella pendiente de …

Consultar procesos con Celery dentro de uwsgi

Después de unos días de trabajo en mi entorno de desarrollo ha llegado el momento de poner la última versión de la aplicación que estoy haciendo a producción. Como el entorno de producción tiene una configuración distinta que la del entorno de desarrollo, aquí han empezado a aparecer los problemas.

Lo primero es que tenemos una cosa ahí enmedio que se llama uwsgi y es quien ejecuta el código, en lugar del python manage.py runserver. Una de las cosas que me he encontrado es que el trozo de código que comprueba que hay tareas ejecutándose en Celery, no funciona correctamente. En mi caso estaba usando

import time, json
_stats = os.popen('celery inspect stats --json').read()
time.sleep(1)
_stats = json.loads(_stats)

No funcionaba correctamente. He tenido que quebrarme un poco la cabeza para inspeccionar que es lo que estaba ocurriendo, por suerte existe una librería que se llama remote_pdb

(venv) root@app-dev:/var/www/html/app# pip3 install remote-pdb

Y añadimos lo siguiente en el trozo de código que queramos inspeccionar que esté corriendo a través de uwsgi

from remote_pdb import RemotePdb
RemotePdb('127.0.0.1', 4444).set_trace()

Y nos connectaremos al trace por telnet

root@digitplan-dev:~# telnet localhost 4444
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
/var/www/html/app/web/rrd.py(465)check_task_status()
-"""
(Pdb) 

A partir de aquí he podido comprobar que algo le pasa a celery, ya que cualquier comando que ejecutase con celery devolvía vacío. No me ha quedado otra que realizar esta comprobación de otra forma

from celery import Celery
_app = Celery("nombreapp")
_running_tasks = _app.control.inspect().active()['celery@' + str(hostname)]
_status 

Django: tareas en background con celery y rabbitmq

Venga, con este post vamos a subir un poco el nivel de nuestras aplicaciones!

Una de las problemáticas que te encuentras al programar con django es que el envío de mails es horrorosamente lento, el proceso de enviar el mail es relativamente rápido, pero no termino de entender el porqué en general es lento (la conexión y sobre todo la desconexión). Para ello una de las soluciones que más o menos ya había aplicado a mi manera con command hacía que la ejecución cada minuto se solapase con la ejecución de minutos anteriores. Hice una ñapa hace unos días hasta encontrar una solución un poco más elegante. Aquí os la traigo! :D

Hay varios posts que hablan de celery, incluso el libro que uso de consulta “Django 3 by Example”, hablan de usar @tank, pero esta opción está descontinuada para la versión 5, así que aquí veremos como hacerlo con Celery 5. Toda la info la he sacado de éste post.

Configurar e instalar celery y rabbitmq en nuestro proyecto/sistema
Lo primero será instalar celery en nuestro proyecto

laura@melatonina:~/dev/whistleblowerbox$ source venv/bin/activate
(venv) laura@melatonina:~/dev/whistleblowerbox$ pip install celery

A continuación instalamos rabbitmq en nuestro sistema. Rabbitmq es el servicio que encolará las tareas que le pasemos y luego las ejecutará en background

root@melatonina:~# apt -y install rabbitmq-server

Ahora en el fichero settings.py de nuestro proyecto añadimos

(venv) laura@melatonina:~/dev/whistleblowerbox$ vi wbox/settings.py
CELERY_BROKER_URL = 'amqp://localhost'

A continuación, en el mismo directorio donde se encuentra el fichero settings.py vamos a crear uno que se …