[{"content":" Technitium DNS — caso de éxito\nLa presentación está pensada para pantallas grandes. Abrila en pantalla completa para leerla cómodamente.\nAbrir presentación → Navegá con las flechas o deslizando. Abrir pantalla completa → El caso en 6 puntos # Tipo. Software como servicio: infraestructura de red operada para un cliente.\nProblema. La red necesitaba visibilidad, control y protección en una sola plataforma, sin depender de servicios externos.\nSolución. Despliegue y operación de Technitium DNS Server con contenedores Podman y scripts manage para instalación, configuración, estado y mantenimiento.\nTecnologías. Technitium DNS, Podman, contenedores y scripts manage.\nResultado. Implementación entregada y facturada según alcance, con documentación operativa y transferencia de conocimiento.\nAprendizajes. La infraestructura moderna no es solo tecnología: es visibilidad, control y seguridad operando juntos.\n","externalUrl":null,"permalink":"/proyectos/technitium-dns/","section":"Proyectos","summary":"Caso de éxito de Technitium DNS: DNS moderno, autohospedado y operado como servicio con Podman y scripts manage.","title":"Technitium DNS operado como servicio","type":"proyectos"},{"content":" Seafile — cloud privado autohospedado\nLa presentación está pensada para pantallas grandes. Abrila en pantalla completa para leerla cómodamente.\nAbrir presentación → Navegá con las flechas o deslizando. Abrir pantalla completa → El caso en 6 puntos # Tipo. Software como servicio: infraestructura de archivos autohospedada y operada para un cliente.\nProblema. Los documentos estaban en servicios de terceros y se necesitaba edición Office online, control de acceso y soberanía de datos, sin sumar licencias SaaS.\nSolución. Seafile CE con OnlyOffice, contenedores Podman, MariaDB + Redis, scripts manage y reverse proxy con TLS.\nTecnologías. Seafile CE, OnlyOffice, Podman, MariaDB, Redis, scripts manage, Nginx Proxy Manager / HAProxy.\nResultado. Plataforma de archivos autohospedada operativa, con edición Office online, documentada y entregada; proyecto facturado según alcance.\nAprendizajes. Self-hosted dejó de ser un requisito técnico para ser un diferenciador: se puede tener la comodidad de la nube sin entregar el control de los datos.\n","externalUrl":null,"permalink":"/proyectos/seafile-cloud-privado/","section":"Proyectos","summary":"Caso de éxito de Seafile: cloud privado, edición Office online y control de datos, autohospedado con Podman y scripts manage.","title":"Seafile: cloud privado autohospedado","type":"proyectos"},{"content":" Moodle — plataforma educativa autohospedada\nLa presentación está pensada para pantallas grandes. Abrila en pantalla completa para leerla cómodamente.\nAbrir presentación → Navegá con las flechas o deslizando. Abrir pantalla completa → El caso en 6 puntos # Tipo. Software como servicio: plataforma educativa autohospedada y operada para una organización.\nProblema. El cliente necesitaba capacitar a su gente y no tenía una plataforma propia: los datos quedaban en terceros, los costos por suscripción crecían con cada usuario y la capacitación no se adaptaba a la realidad de la organización.\nSolución. Despliegue y operación de Moodle como servicio autohospedado: instalación, mantenimiento, respaldos y operación diaria a cargo nuestro; la organización se enfoca en enseñar.\nTecnologías. Moodle, PHP 8.3 + Apache, Podman, contenedores (MariaDB + Redis) y scripts de gestión con make.\nResultado. Plataforma funcionando en producción, documentada y en manos del cliente; alcance cerrado, entregado y facturado.\nAprendizajes. La infraestructura también se vende como producto; el valor está en la operación, no solo en el despliegue; el autohospedaje da control total y costo previsible.\n","externalUrl":null,"permalink":"/proyectos/moodle/","section":"Proyectos","summary":"Caso de éxito de Moodle: plataforma educativa autohospedada, desplegada y operada como servicio, con Podman y scripts de gestión.","title":"Moodle autohospedado, operado de punta a punta","type":"proyectos"},{"content":"","date":"25 de octubre de 2026","externalUrl":null,"permalink":"/tags/api-football/","section":"Tags","summary":"","title":"Api-Football","type":"tags"},{"content":"","date":"25 de octubre de 2026","externalUrl":null,"permalink":"/tags/autohospedaje/","section":"Tags","summary":"","title":"Autohospedaje","type":"tags"},{"content":"Apuntes técnicos, tecnologías de código abierto, experiencias y proyectos en público.\n“El software es un lugar donde se siembran sueños y se cosechan pesadillas.” — Brad J. Cox\n","date":"25 de octubre de 2026","externalUrl":null,"permalink":"/posts/","section":"Blog","summary":"","title":"Blog","type":"posts"},{"content":"","date":"25 de octubre de 2026","externalUrl":null,"permalink":"/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"},{"content":"Todo empezó por una molestia simple: para seguir el fútbol que me gusta —argentino, uruguayo e italiano— tenía que saltar entre varios sitios, cada uno con su publicidad, su cuenta y sus resultados a medias. Quería fixture, resultados y posiciones en un solo lugar. De ahí nació El Bagual del Gol, un proyecto personal que hoy está en producción en bagualgol.duckdns.org.\nNo es un trabajo para un cliente ni un producto comercial: es un hobby de un apasionado del fútbol, hecho para otros aficionados. El pie del sitio lo dice mejor que cualquier pitch: \u0026ldquo;Hecho por un bagual para otros baguales futboleros\u0026rdquo;.\nQué muestra hoy # Partidos del día, con filtro de todos / en vivo, marcador, DTs y estadio. Competiciones agrupadas en el menú: Mundial, Uruguay, Internacional, selecciones, Argentina, Inglaterra, España, Italia y más. Mundial 2026: grupos, tabla de posiciones, partidos por jornada y ranking de goleadores. Noticias de fútbol desde fuentes RSS, con titulares y antigüedad. Cómo está armado # El frontend es una SPA con React 19 + Vite 7 + TailwindCSS 4. El backend es Express 5 sobre Node, que expone una API REST. Lo interesante está en los datos: hay varias fuentes conviviendo.\nAPI-Football y SportsRC (planes gratuitos): fixtures, resultados y posiciones de las ligas. PostgreSQL: modelo propio con 23 tablas —torneos, jugadores, eventos, predicciones, entrenadores y alineaciones—. MongoDB: el Mundial 2026 vive ahí: grupos, partidos, equipos y estadios. RSS: noticias de Google News y Ovación, cacheadas cada 15 minutos. Para no quedar atado a un proveedor, el backend usa un patrón provider: cada fuente implementa la misma interfaz (getFixtures(), getLiveFixtures(), getCompetitions()) y un factory decide cuál responde según la liga. Los DTOs normalizan la respuesta cruda de cada proveedor a una misma forma antes de salir por la API. Sumar una fuente nueva es crear un archivo y registrarla en dos lugares: cero cambios en controllers, services o rutas.\nTambién hay un openapi.yaml con el contrato de la API, que es lo que uso de referencia cuando vuelvo al proyecto después de un tiempo.\nCómo quedó desplegado # Autohospedado, como casi todo lo que corro: un solo servidor Debian con Nginx Proxy Manager terminando TLS con Let\u0026rsquo;s Encrypt, nginx sirviendo los estáticos del build de Vite y proxeando /api/ al backend, PM2 manteniendo vivo el proceso Node y DuckDNS resolviendo el dominio dinámico.\nUn par de detalles que parecen menores y no lo son:\nCache agresiva para assets: Vite hashea los nombres, así que /assets/ se cachea un año con immutable. El HTML nunca se cachea. Headers de seguridad y bloqueos: X-Frame-Options, nosniff, Referrer-Policy, y sin acceso a archivos ocultos, source maps, node_modules ni .git. SPA fallback: cualquier ruta desconocida responde index.html, para que la navegación del frontend no dé 404. Lo que aprendí # Un hobby merece el mismo rigor que un trabajo facturado. Documentar el despliegue en una guía paso a paso fue lo que me permitió retomar el proyecto después de semanas sin tocarlo. Hay que diseñar para datos incompletos. Los planes gratuitos limitan consultas y cobertura: puede haber retrasos o información desactualizada. El sitio lo dice en su aviso legal. Mejor asumirlo desde el diseño que prometer exactitud. El patrón provider y los DTOs rindieron más de lo que esperaba. Cambiar o sumar fuentes de datos tocó un solo archivo por fuente, sin reescribir media API. Las partes aburridas son las que sostienen: cache, logs, reinicio automático, respaldos y headers de seguridad. Estado actual: en pausa, a propósito # El sitio está en vivo y funcionando, pero el desarrollo está en pausa: hace tiempo que no le sumo funcionalidades nuevas, y está bien así. Cuando tenga más tiempo libre quiero volver: más estadísticas, resultados históricos y planteles, que es justo lo que está en proceso de incorporación continua.\nMientras tanto sigue ahí, gratis y sin registrarse, por si alguien quiere mirar un rato el fútbol que sigo. Y si encontrás un dato raro o querés sugerir una liga, el aviso legal del sitio tiene un correo para eso.\n","date":"25 de octubre de 2026","externalUrl":null,"permalink":"/posts/nacio-el-bagual-del-gol/","section":"Blog","summary":"Fixture, resultados y posiciones del fútbol argentino, uruguayo e italiano en un solo sitio. Cómo nació El Bagual del Gol, cómo está armado y qué aprendí.","title":"Cómo nació El Bagual del Gol: de un hobby futbolero a producción","type":"posts"},{"content":"","date":"25 de octubre de 2026","externalUrl":null,"permalink":"/categories/experiencias/","section":"Categories","summary":"","title":"Experiencias","type":"categories"},{"content":" 01 Servicios Qué puedo resolver Soporte, infraestructura, desarrollo y automatización para problemas concretos.\nSoporte informático Incidentes, mantenimiento y mejoras en entornos Linux y servicios informáticos. Ver servicio Infraestructura y sistemas Proxmox, contenedores, DNS, proxy inverso, TLS, correo, monitoreo y autohospedaje. Ver servicio Desarrollo web y software Aplicaciones web y APIs, mantenimiento de sistemas e integración con bases de datos. Ver servicio Agentes de IA y automatización Agentes de IA que ejecutan tareas por vos, scripts, despliegues reproducibles e integración de herramientas open source. Ver servicio 02 Proyectos Proyectos y soluciones Soluciones informáticas:\nCasos reales de infraestructura y software como servicio, con la presentación completa de cada proyecto.\n¿Cansado de sistemas con licenciamiento?\nSoluciones open source sin licencias: transparencia total, control de tu información y privacidad por diseño.\nVer los casos de éxito 03 Proceso Cómo trabajo Un método simple: entender el problema, proponer un alcance, implementar y documentar.\n1 Relevamiento y diagnóstico Entiendo el problema, el entorno y las restricciones antes de proponer una solución. 2 Propuesta y alcance Defino qué se hace, qué queda fuera y cómo se valida el resultado. 3 Implementación Trabajo en cambios pequeños, verificables y documentados. 4 Documentación y transferencia El sistema queda operable, entendible y con el conocimiento transferido. Documentación\nEl sistema queda operable.\nNo entrego solo el cambio: dejo el contexto, las decisiones y los pasos para que se pueda mantener en el tiempo.\n04 Sitios propios Sitios que construyo y mantengo Sitios web que desarrollo, publico y mantengo de punta a punta. La mejor forma de ver cómo trabajo es verlo funcionando.\nEn vivo El Bagual del Gol Fixture, resultados y posiciones del fútbol argentino, uruguayo e italiano. React \u0026#43; Node.js con API-Football, autohospedado. Desarrollo en pausa: cuando haya tiempo libre, más funcionalidades.\nVisitar el sitio → Cómo nació → Próximamente Camila Bonin · Pastelería artesanal Sitio de pastelería artesanal. En construcción.\nPróximamente EstructurasUY · Construcción y estructuras Sitio de construcción y estructuras. En construcción.\n05 Blog Últimos artículos Notas técnicas, experiencias y proyectos en público.\nCómo nació El Bagual del Gol: de un hobby futbolero a producción 25 de octubre de 2026\u0026middot;668 palabras\u0026middot;4 mins Experiencias React Nodejs Autohospedaje Api-Football Fixture, resultados y posiciones del fútbol argentino, uruguayo e italiano en un solo sitio. Cómo nació El Bagual del Gol, cómo está armado y qué aprendí. Configurar GeoIP2 en Nginx detrás de Nginx Proxy Manager (NPM) 17 de junio de 2026\u0026middot;660 palabras\u0026middot;4 mins Redes Nginx Npm Geoip2 Proxy-Inverso En este artículo quiero mostrar cómo configurar GeoIP2 en Nginx cuando el servidor web se encuentra detrás de un proxy inverso administrado mediante Nginx Proxy Manager (NPM). Cuando el correo deja de llegar: análisis de una caída en una plataforma de correo Zimbra-PMG 22 de mayo de 2026\u0026middot;866 palabras\u0026middot;5 mins Infraestructura Correo Postfix Incidentes Analisis Por cuestiones de confidencialidad no puedo compartir capturas ni publicar comandos ejecutados junto con sus resultados. Aun así, vale la pena contar el análisis del caso porque terminó siendo una situación bastante particular y… Ver todos los artículos → 06 Contacto\n¿Tenés un sistema que ordenar, un servicio que desplegar o una tarea que automatizar? Contame el contexto y vemos el alcance.\nSolicitar presupuesto Ver casos de éxito ","date":"25 de octubre de 2026","externalUrl":null,"permalink":"/","section":"Infraestructura, desarrollo y automatización","summary":"","title":"Infraestructura, desarrollo y automatización","type":"page"},{"content":"","date":"25 de octubre de 2026","externalUrl":null,"permalink":"/tags/nodejs/","section":"Tags","summary":"","title":"Nodejs","type":"tags"},{"content":"","date":"25 de octubre de 2026","externalUrl":null,"permalink":"/tags/react/","section":"Tags","summary":"","title":"React","type":"tags"},{"content":"","date":"25 de octubre de 2026","externalUrl":null,"permalink":"/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"},{"content":" Introducción # En este artículo quiero mostrar cómo configurar GeoIP2 en Nginx cuando el servidor web se encuentra detrás de un proxy inverso administrado mediante Nginx Proxy Manager (NPM).\nEl objetivo es identificar la IP real de los visitantes, conocer su país y ciudad, y posteriormente utilizar esta información para generar estadísticas o alertas de seguridad.\nArquitectura # La arquitectura utilizada es la siguiente:\nCliente → Nginx Proxy Manager (NPM) → Nginx Backend\nNPM recibe las conexiones HTTPS desde Internet y las reenvía hacia un servidor Nginx interno.\nConfigurando la IP real del visitante # Como el servidor se encuentra detrás de Nginx Proxy Manager, inicialmente Nginx registraba la IP privada del proxy en lugar de la IP pública del visitante.\nPara solucionarlo agregué al archivo /etc/nginx/sites-available/misitio dentro del bloque server {}:\nset_real_ip_from 192.0.2.255; real_ip_header X-Forwarded-For; real_ip_recursive on; Donde 192.0.2.255 corresponde a la IP interna de mi servidor Nginx Proxy Manager.\nPosteriormente validé la configuración:\nnginx -t Y recargué el servicio:\nsystemctl reload nginx Verificando la IP real del visitante # Una vez aplicada la configuración, verifiqué el contenido del log:\ntail -f /var/log/nginx/access.log Comencé a observar registros similares a:\n198.51.100.0 - - [16/Jun/2026:11:19:11 -0300] \u0026#34;GET /favicon.ico HTTP/1.1\u0026#34; 200 203.0.113.0 - - [16/Jun/2026:11:20:01 -0300] \u0026#34;GET /api/live/matches HTTP/1.1\u0026#34; 304 Como aparecen direcciones IP públicas reales y no la IP privada de NPM, confirmé que el proxy estaba reenviando correctamente la información del cliente.\nInstalación del módulo GeoIP2 # Instalé el módulo GeoIP2 para Nginx:\napt update apt install libnginx-mod-http-geoip2 Luego verifiqué que el módulo estuviera cargado:\nnginx -T | grep load_module Resultado:\nload_module modules/ngx_http_geoip2_module.so; Descarga de las bases GeoLite2 # Registré una cuenta gratuita en MaxMind y descargué:\nGeoLite2-Country.mmdb GeoLite2-City.mmdb Creé el directorio:\nmkdir -p /etc/nginx/geoip Y copié los archivos:\ncp GeoLite2-Country.mmdb /etc/nginx/geoip/ cp GeoLite2-City.mmdb /etc/nginx/geoip/ Configuración de GeoIP2 en Nginx # Dentro del bloque http {} del archivo /etc/nginx/nginx.conf agregué:\ngeoip2 /etc/nginx/geoip/GeoLite2-Country.mmdb { auto_reload 5m; $geoip2_country_code country iso_code; $geoip2_country_name country names en; } geoip2 /etc/nginx/geoip/GeoLite2-City.mmdb { auto_reload 5m; $geoip2_city_name city names en; } Endpoint de prueba # Para validar la configuración agregué al archivo /etc/nginx/sites-available/misitio dentro del bloque server {}:\nlocation /geoiptest { default_type text/plain; return 200 \u0026#34;$remote_addr | $geoip2_country_code | $geoip2_country_name | $geoip2_city_name\\n\u0026#34;; } Luego validé la configuración:\nnginx -t systemctl reload nginx Al acceder a:\nhttps://misitio.com/geoiptest obtuve:\n192.0.2.0 | UY | Uruguay | Montevideo Lo que confirmó que GeoIP2 estaba funcionando correctamente.\nIncorporando GeoIP al access.log # La configuración del formato de log debe realizarse dentro del bloque http {} del archivo:\n/etc/nginx/nginx.conf Agregué el siguiente formato personalizado:\nlog_format geoip \u0026#39;$remote_addr [$time_local] \u0026#39; \u0026#39;$geoip2_country_code \u0026#39; \u0026#39;$geoip2_country_name \u0026#39; \u0026#39;$geoip2_city_name \u0026#39; \u0026#39;\u0026#34;$request\u0026#34; $status\u0026#39;; Luego configuré el archivo de log para utilizar dicho formato.\nEsto puede hacerse de forma global dentro del bloque http {} en /etc/nginx/nginx.conf:\naccess_log /var/log/nginx/access.log geoip; o de forma específica para un sitio dentro del bloque server {} ubicado normalmente en:\n/etc/nginx/sites-available/misitio o\n/etc/nginx/sites-enabled/misitio Ejemplo:\nserver { access_log /var/log/nginx/access.log geoip; ... } Después de aplicar los cambios validé la configuración:\nnginx -t Y recargué Nginx:\nsystemctl reload nginx Los registros comenzaron a verse así:\n198.52.100.255 [16/Jun/2026:13:15:00 -0300] UY Uruguay Montevideo \u0026#34;GET / HTTP/1.1\u0026#34; 200 A partir de este momento cada acceso queda registrado junto con el país y la ciudad del visitante obtenidos mediante GeoIP2.\nAdemás, si tienes varios virtual hosts detrás de NPM, probablemente te convenga definir el log_format geoip en /etc/nginx/nginx.conf (una sola vez) y luego activar access_log ... geoip; únicamente en los sitios donde quieras registrar geolocalización. Esto te da más flexibilidad para el futuro.\nConclusión # La combinación de Nginx Proxy Manager, Nginx y GeoIP2 permite obtener información geográfica de los visitantes con muy poco consumo de recursos. Esta información puede utilizarse tanto para análisis de tráfico como para mejorar la seguridad del servidor mediante sistemas de monitoreo y alertas.\n¡Salud y buen blogging!\n— Valerka (Montevideo, Uruguay)\n¿Te gustó el post? ¿Dudas, comentarios o querés compartir tu experiencia?\nEscribime a: valerkasystem@protonmail.com — ¡Siempre leo los mails y trato de responder cuando puedo!\n","date":"17 de junio de 2026","externalUrl":null,"permalink":"/posts/configurar-geoip2-nginx-npm/","section":"Blog","summary":"En este artículo quiero mostrar cómo configurar GeoIP2 en Nginx cuando el servidor web se encuentra detrás de un proxy inverso administrado mediante Nginx Proxy Manager (NPM).","title":"Configurar GeoIP2 en Nginx detrás de Nginx Proxy Manager (NPM)","type":"posts"},{"content":"","date":"17 de junio de 2026","externalUrl":null,"permalink":"/tags/geoip2/","section":"Tags","summary":"","title":"Geoip2","type":"tags"},{"content":"","date":"17 de junio de 2026","externalUrl":null,"permalink":"/tags/nginx/","section":"Tags","summary":"","title":"Nginx","type":"tags"},{"content":"","date":"17 de junio de 2026","externalUrl":null,"permalink":"/tags/npm/","section":"Tags","summary":"","title":"Npm","type":"tags"},{"content":"","date":"17 de junio de 2026","externalUrl":null,"permalink":"/tags/proxy-inverso/","section":"Tags","summary":"","title":"Proxy-Inverso","type":"tags"},{"content":"","date":"17 de junio de 2026","externalUrl":null,"permalink":"/categories/redes/","section":"Categories","summary":"","title":"Redes","type":"categories"},{"content":"","date":"22 de mayo de 2026","externalUrl":null,"permalink":"/tags/analisis/","section":"Tags","summary":"","title":"Analisis","type":"tags"},{"content":"","date":"22 de mayo de 2026","externalUrl":null,"permalink":"/tags/correo/","section":"Tags","summary":"","title":"Correo","type":"tags"},{"content":" Por cuestiones de confidencialidad no puedo compartir capturas ni publicar comandos ejecutados junto con sus resultados. Aun así, vale la pena contar el análisis del caso porque terminó siendo una situación bastante particular y probablemente despierte curiosidad en quienes trabajan administrando este tipo de plataformas.\nDurante el día comenzaron a llegar las primeras alertas desde usuarios finales: los correos electrónicos no estaban llegando a destino.\nEn un primer momento no existían señales de una caída del servicio. La plataforma continuaba respondiendo, no se observaban errores evidentes y, a simple vista, el entorno seguía operativo.\nPero como suele pasar en incidentes de este tipo, el síntoma visible (“no llegan correos”) era solo la superficie de un problema más profundo.\nAsí comenzó el proceso de diagnóstico sobre una plataforma de correo legacy compuesta por Zimbra y PMG, que actualmente continúa en operación mientras avanza una migración tecnológica planificada hacia Carbonio y PMG.\nPaso 1 — Verificar el estado de los servicios # El primer paso fue revisar el estado de los servicios involucrados.\nRápidamente apareció algo que llamó la atención: el servicio PMG (pmg-smtp-filter) registraba múltiples fallas de conexión hacia la base de datos, acompañadas por errores repetidos asociados al runtime de Perl (segfault).\nLo curioso era que estos eventos no comenzaron con el incidente, sino que venían ocurriendo desde varias horas antes de la caída.\nCon ese dato se pasó a verificar el estado del servicio de base de datos… y efectivamente no se estaba ejecutando.\nNo era una señal especialmente tranquilizadora.\nSe intentó iniciar nuevamente el servicio esperando encontrar errores adicionales durante el arranque; por suerte la base levantó correctamente y sin fallos visibles.\nCon el servicio operativo nuevamente, el foco dejó de estar en restaurar disponibilidad y pasó a entender por qué la base de datos se había detenido.\nEsto era especialmente relevante porque PMG consulta continuamente reglas y políticas sobre los correos que atraviesan el sistema.\nEl siguiente paso fue entonces revisar el histórico de eventos alrededor del momento del incidente.\nPaso 2 — Buscar eventos alrededor del horario del incidente # Al revisar los logs apareció algo interesante.\nMúltiples conexiones activas estaban siendo cerradas por el propio motor:\nterminating connection because of crash of another server process possibly corrupted shared memory Ese mensaje normalmente indica que:\nun proceso interno terminó de forma anormal; el proceso principal decidió detener el resto para proteger consistencia; el motor entra en recuperación. Un poco antes aparecía la pieza clave:\nserver process was terminated by signal 11: Segmentation fault Un SIGSEGV (Segmentation Fault).\nEse dato cambió completamente el enfoque.\nYa no estábamos buscando un problema funcional del correo.\nEstábamos frente a un crash de proceso.\nPaso 3 — Validar hipótesis clásicas # Antes de asumir un bug de aplicación se revisaron las causas habituales:\nDisco # Se verificaron errores de filesystem y eventos del kernel.\nResultado:\nsin errores detectados Memoria # Se buscaron eventos relacionados con:\nOOM Killed process memory Resultado:\nsin evidencia de agotamiento de memoria Host de virtualización # También se revisaron eventos del host físico buscando:\nerrores ECC; reinicios; eventos de virtualización; fallas de almacenamiento. Resultado:\nsin correlación con el horario del incidente Hasta ese punto no había señales de infraestructura.\nPaso 4 — Encontrar el verdadero patrón # Al seguir profundizando apareció algo más importante.\nEl componente encargado del procesamiento SMTP venía registrando fallos repetidos.\nLos mensajes se repetían durante horas:\nsegfault signal 11 Y entre esos eventos aparecían errores de conexión hacia la base de datos.\nLa secuencia terminó siendo algo parecido a esto:\nProcesamiento SMTP ↓ Error interno ↓ Segmentation fault ↓ Conexiones hacia BD fallan ↓ Motor entra en recuperación ↓ Usuarios dejan de recibir correos Eso explicaba por qué el incidente parecía intermitente y no una caída total.\nPaso 5 — Recuperación y validación # Una vez recuperado el servicio se ejecutaron tareas de mantenimiento sobre la base:\nReconstrucción de índices # REINDEX DATABASE Objetivo:\nreconstruir índices; eliminar posibles inconsistencias lógicas. Limpieza y actualización de estadísticas # VACUUM ANALYZE Objetivo:\nlimpiar registros obsoletos; actualizar estadísticas del optimizador. Después de eso:\nel sistema completó recuperación automática; el flujo de correo volvió a normalidad; no se observaron pérdidas de información. Lecciones aprendidas # Este incidente dejó varias conclusiones útiles:\n1. “Servicio activo” no significa “servicio sano” # El monitoreo mostraba procesos levantados.\nLos logs mostraban otra historia.\n2. Los síntomas rara vez están donde ocurre el problema # El usuario veía:\nno llegan correos La causa real estaba varios componentes más abajo.\n3. Las plataformas legacy requieren observabilidad extra # En sistemas con muchos años de operación es común encontrar:\nprocesos que se recuperan solos; errores silenciosos; componentes que fallan en cascada. Próximos pasos # Este incidente reforzó una decisión que ya estaba en planificación:\nmigración gradual de la plataforma de correo hacia Carbonio; actualización del gateway de correo hacia una plataforma más reciente. A veces el mejor resultado de un incidente no es restaurar el servicio.\nEs entender por qué falló antes de que vuelva a pasar.\n¡Salud y buen blogging!\n— Valerka (Montevideo, Uruguay)\n¿Te gustó el post? ¿Tenés dudas, comentarios o querés compartir tu experiencia?\nEscribime a: valerkasystem@protonmail.com — ¡Siempre leo los mails y trato de responder cuando puedo!\n","date":"22 de mayo de 2026","externalUrl":null,"permalink":"/posts/caida-plataforma-correo-zimbra-pmg/","section":"Blog","summary":"Por cuestiones de confidencialidad no puedo compartir capturas ni publicar comandos ejecutados junto con sus resultados. Aun así, vale la pena contar el análisis del caso porque terminó siendo una situación bastante particular y…","title":"Cuando el correo deja de llegar: análisis de una caída en una plataforma de correo Zimbra-PMG","type":"posts"},{"content":"","date":"22 de mayo de 2026","externalUrl":null,"permalink":"/tags/incidentes/","section":"Tags","summary":"","title":"Incidentes","type":"tags"},{"content":"","date":"22 de mayo de 2026","externalUrl":null,"permalink":"/categories/infraestructura/","section":"Categories","summary":"","title":"Infraestructura","type":"categories"},{"content":"","date":"22 de mayo de 2026","externalUrl":null,"permalink":"/tags/postfix/","section":"Tags","summary":"","title":"Postfix","type":"tags"},{"content":"","date":"14 de mayo de 2026","externalUrl":null,"permalink":"/tags/almacenamiento/","section":"Tags","summary":"","title":"Almacenamiento","type":"tags"},{"content":" En el artículo anterior El día que movimos un cable y congelamos medio Proxmox: Storage GlusterFS conté cómo un problema aparentemente simple —mover un cable en una bond de red— terminó congelando parte de nuestro cluster Proxmox con storage distribuido en GlusterFS.\nEl incidente principal parecía terminado una vez recuperada la conectividad y estabilizado el storage. Pero faltaba el segundo acto.\nPorque en infraestructura, muchas veces el problema más peligroso no es el corte inicial.\nEs el daño silencioso que queda después.\nEl síntoma apareció recién al día siguiente # Horas después del incidente con GlusterFS, encendimos una VM que había quedado apagada abruptamente durante el problema del storage.\nLa VM no arrancó normalmente.\nEn consola de Proxmox apareció algo así:\nEXT4-fs (dm-2): error loading journal Failed to mount /\u0026lt;nombreDirectorioAfectado\u0026gt; You are in emergency mode Linux había entrado automáticamente en emergency mode porque no podía montar uno de los volúmenes.\nEl filesystem EXT4 detectó corrupción en el journal.\nCaptura de pantalla de la máquina virtual en \u0026quot;emergency mode\u0026quot; no puede montar uno de los volúmenes, espera intervención manual. El detalle importante: el problema no estaba en la VM # Y esto es clave entenderlo.\nLa VM no “se rompió sola”.\nEl problema original ocurrió más abajo:\nuna falla en la bond del switch, afectó conectividad del cluster, impactó GlusterFS, la VM perdió acceso consistente al storage, y terminó apagándose abruptamente. El daño al filesystem fue una consecuencia del problema de infraestructura anterior.\nEl arranque en emergency mode # La VM quedaba detenida esperando intervención manual (como se muestra en la imagen anterior).\nPrimero identificamos el volumen afectado:\nlsblk cat /etc/fstab Luego ejecutamos fsck sobre el volumen comprometido.\nEn este caso era un LV montado como /\u0026lt;nombreDirectorioAfectado\u0026gt;.\nCaptura de pantalla detectando nombre del volumen comprometido /dev/mapper/storage-\u0026lt;nombreVolumen\u0026gt;. Ejecutando fsck # El comando fue:\nfsck.ext4 -fy /dev/mapper/storage-\u0026lt;nombreVolumen\u0026gt; Y ahí aparecieron los clásicos mensajes que nunca querés ver en producción:\nFree blocks count wrong Free inodes count wrong El filesystem tenía inconsistencias internas.\nPor suerte, el journal todavía era recuperable y fsck logró corregir todo automáticamente.\nAl finalizar:\nFILE SYSTEM WAS MODIFIED Y sinceramente, esa línea fue un alivio.\nPorque significa:\nencontró corrupción, logró repararla, y el filesystem volvió a un estado consistente. Captura de pantalla ejecutando el comando fsck.ext4 -fy /dev/mapper/storage-\u0026lt;nombreVolumen\u0026gt;. Captura de pantalla muestra que fsck logró corregir todo automáticamente. Al finalizar: FILE SYSTEM WAS MODIFIED Reinicio y validación # Después del fsck reiniciamos la VM.\nEl sistema volvió a levantar normalmente.\nValidamos:\ndf -h,montaje correcto de /\u0026lt;nombreDirectorioAfectado\u0026gt;, logs de EXT4: y dmesg. El kernel confirmó:\nEXT4-fs (dm-3): recovery complete Y lo más importante: no aparecieron errores de I/O ni corrupción adicional.\nCaptura pantalla conectado por ssh:Log EXT4-fs (dm-3): recovery complete Captura de pantalla dmesg no aparecieron errores de I/O ni corrupción adicional. Conclusión # Este incidente también dejó algo claro a nivel operativo:\nel relevamiento y reorganización del cableado del datacenter no puede volver a hacerse sobre infraestructura en producción sin una ventana controlada. Más allá de que el problema inicial pareció menor, terminó generando efectos en cadena sobre la red, el storage distribuido y finalmente sobre los filesystems de algunas VMs. Por ese motivo, el próximo relevamiento deberá planificarse correctamente, realizarse durante un fin de semana y con apagado controlado de los equipos involucrados, minimizando riesgos sobre la operación. Sobre todo considerando que actualmente estamos en proceso de planificación para migrar el datacenter a otra ubicación física, donde este tipo de tareas van a ser inevitables y van a requerir todavía más control y coordinación.\n¡Salud y buen blogging!\n— Valerka (Montevideo, Uruguay)\n¿Te gustó el post? ¿Tenés dudas, comentarios o querés compartir tu experiencia?\nEscribime a: valerkasystem@protonmail.com — ¡Siempre leo los mails y trato de responder cuando puedo!\n","date":"14 de mayo de 2026","externalUrl":null,"permalink":"/posts/glusterfs-corrupcion-ext4-fsck/","section":"Blog","summary":"El incidente principal parecía terminado una vez recuperada la conectividad y estabilizado el storage. Pero faltaba el segundo acto.","title":"El coletazo del incidente en GlusterFS: corrupción EXT4 y el fsck que salvó la VM","type":"posts"},{"content":"","date":"14 de mayo de 2026","externalUrl":null,"permalink":"/tags/ext4/","section":"Tags","summary":"","title":"Ext4","type":"tags"},{"content":"","date":"14 de mayo de 2026","externalUrl":null,"permalink":"/tags/fsck/","section":"Tags","summary":"","title":"Fsck","type":"tags"},{"content":"","date":"14 de mayo de 2026","externalUrl":null,"permalink":"/tags/glusterfs/","section":"Tags","summary":"","title":"Glusterfs","type":"tags"},{"content":"","date":"14 de mayo de 2026","externalUrl":null,"permalink":"/tags/proxmox/","section":"Tags","summary":"","title":"Proxmox","type":"tags"},{"content":" Hoy me tocó vivir uno de esos casos donde un simple movimiento físico termina escalando a una caída completa de servicios 😅\nFuimos al datacenter a realizar una tarea de relevamiento, siguiendo cables de red para identificar hacia qué puertos de los switches estaban conectados los servidores.\nMientras seguíamos uno de los cables, veo que mi compañero lo mueve y noto algo raro: la ficha RJ45 se movía dentro de la boca del switch. En ese momento me dice:\n“esa es la boca de la BOND…”\nAhí recé un Padre Nuestro esperando que GlusterFS no perdiera conectividad y que los servicios siguieran vivos pero no sirvió de nada.\nA los pocos segundos empezaron a llamarnos: “No funciona nada”, “Los usuarios quedaron sin sistema”\nVolvimos corriendo a la oficina y comenzamos a investigar.\nEntramos a Proxmox y encontramos:\nVMs apagadas otras congeladas errores de I/O en discos Eso ya apuntaba fuerte a problemas de almacenamiento distribuido con GlusterFS.\nPrimeras verificaciones # Verificar estado del volumen: # gluster volume status Buscar: bricks offline, puertos en N/A, procesos muertos\nCaptura de pantalla donde se observa que el volumen de nombre gluster_hdd_1 aparece online. Revisar Estado del servicio: # systemctl status glusterd.service Servidor físico1: # May 12 11:41:29 server1 glustershd[2042]: [rpc-clnt-ping.c:152:rpc_clnt_ping_timer_expired] server \u0026lt;server1-IP\u0026gt;:24007 has not responded in the last 42 seconds, disconnecting. Servidor físico2: # May 12 11:37:21 server2 glustershd[1924]: [rpc-clnt-ping.c:152:rpc_clnt_ping_timer_expired] server \u0026lt;server2-IP\u0026gt;:24007 has not responded in the last 42 seconds, disconnecting. Captura de pantalla donde se observa el servicio gluster con el error \u0026quot;has not responded in the last 42 seconds, disconnecting\u0026quot;, en ambos servidores que forman el volumen gluster_hdd_1. El síntoma raro # Si bien el punto de montaje aparecía montado:\nmount | grep gluster Mostraba:\n127.0.0.1:gluster_hdd_1 on /mnt/pve/gluster_hdd_1 type fuse.glusterfs Captura de pantalla donde se observa que el punto de montaje está montado \u0026quot;correctamente\u0026quot;. Pero df -h devolvía:\ndf: /mnt/pve/gluster_hdd_1: Transport endpoint is not connected Ahí quedó confirmado que el mount de Gluster quedó colgado después de la pérdida de conectividad.\nCaptura de pantalla donde se observa Transport endpoint is not connected. Solución aplicada # Desmontar el endpoint colgado:\numount -l /mnt/pve/gluster_hdd_1 Volver a montar:\nmount -t glusterfs 127.0.0.1:gluster_hdd_1 /mnt/pve/gluster_hdd_1/ Validaciones posteriores # Verificar peers:\ngluster peer status Verificar heal pendiente:\ngluster volume heal gluster_hdd_1 info El heal mostraba varios discos .qcow2 pendientes de sincronización entre bricks.\nCaptura de pantalla donde se observa varios discos .qcow2 pendientes de sincronización entre bricks. Conclusión y lección aprendida # En entornos con storage distribuido, un simple falso contacto físico puede terminar congelando VMs, generando errores de I/O y dejando usuarios sin poder trabajar en cuestión de segundos.\nLo más llamativo de este incidente es que el movimiento de un único cable no debería haber afectado de esta manera a un storage donde están los servicios críticos.\nEso nos deja una nueva línea de investigación: entender por qué la redundancia esperada no absorbió la falla como debía hacerlo.\nPorque en teoría:\nla BOND debería tolerar la caída de un enlace, GlusterFS debería mantener disponibilidad entre nodos, y la infraestructura crítica no debería verse afectada por mover un cable durante un relevamiento. Pero la realidad demostró otra cosa.\n¡Salud y buen blogging!\n— Valerka (Montevideo, Uruguay)\n¿Te gustó el post? ¿Tenés dudas, comentarios o querés compartir tu experiencia?\nEscribime a: valerkasystem@protonmail.com — ¡Siempre leo los mails y trato de responder cuando puedo!\n","date":"13 de mayo de 2026","externalUrl":null,"permalink":"/posts/cable-desconectado-proxmox-glusterfs/","section":"Blog","summary":"Fuimos al datacenter a realizar una tarea de relevamiento, siguiendo cables de red para identificar hacia qué puertos de los switches estaban conectados los servidores.","title":"El día que movimos un cable y congelamos medio Proxmox: Storage GlusterFS","type":"posts"},{"content":"","date":"25 de marzo de 2026","externalUrl":null,"permalink":"/tags/centos/","section":"Tags","summary":"","title":"Centos","type":"tags"},{"content":"","date":"25 de marzo de 2026","externalUrl":null,"permalink":"/tags/cryptojacking/","section":"Tags","summary":"","title":"Cryptojacking","type":"tags"},{"content":" Introducción\nTodo empezó con algo bastante clásico: un servidor en producción con CPU al mango.\nEl consumo no bajaba, se mantenía alto, y eso en un sitio web… es raro. Muy raro.\nAsí que nos metimos a ver qué estaba pasando.\nNo era tráfico legítimo, no era un pico de carga… era otra cosa.\nY lo que encontramos fue un caso textbook de cryptojacking: alguien había tomado control del sistema y lo estaba usando para minar criptomonedas.\n¿Qué encontramos? # El atacante aprovechó una vulnerabilidad conocida: CVE-2020-7961, una falla de deserialización insegura en Liferay que permite ejecución remota de código a través del endpoint:\n/api/jsonws/expandocolumn/update-column\nCon eso, logró: # Descargar y ejecutar scripts maliciosos (mon.sh, run.sh)\nInstalar un minero de criptomonedas basado en XMRig (versión 6.15.2)\nDejar binarios ofuscados en el sistema, como:\n/opt/liferay/g → binario ELF estático, ofuscado (posible downloader o minero) /root/L → archivo que contiene el resultado de una redirección a https://www.thc.org/ssh-it/bs Ese último (bs) no es cualquier cosa: es un gusano SSH diseñado para moverse lateralmente buscando claves privadas o contraseñas en historiales, e intentar propagarse por la red.\nEvidencia clave # Durante el análisis forense identificamos una cadena de actividades maliciosas típicas de campañas de cryptojacking automatizadas. Todo comenzó con la descarga de scripts desde servidores externos, como mon.sh y run.sh, alojados en IPs efímeras (151.106.34.115, 189.203.240.235). Estos scripts se ejecutaron de forma automática tras explotar la vulnerabilidad en Liferay.\nUna vez dentro del sistema, el atacante desplegó un minero de criptomonedas basado en XMRig (v6.15.2), detectado activo en /home/usuario/xmrig6152. Pero no se quedó ahí: también dejó binarios ofuscados para asegurar persistencia y evadir detección.\nEl más llamativo es el archivo /opt/liferay/g: un binario ELF 64-bit, estático y ofuscado, cuyo comportamiento sugiere que actúa como downloader o minero secundario. Además, encontramos el archivo /root/L, que contiene el registro de una redirección HTTP hacia https://www.thc.org/ssh-it/bs —un conocido gusano SSH diseñado para propagarse lateralmente mediante credenciales débiles o claves expuestas.\nLo más preocupante: el atacante usó técnicas avanzadas de evasión. Por ejemplo, aplicó atributos inmutables (chattr +i) a algunos archivos para impedir su eliminación accidental, y configuró tareas programadas vía cron para reiniciar el minero si era detenido.\nTambién notamos que cambiaba frecuentemente las IPs y servidores de descarga, lo que indica una infraestructura dinámica pensada para evitar bloqueos y prolongar la vida útil de la infección.\nAfortunadamente, pese a estas tácticas, no hallamos indicios de que lograra moverse a otros servidores de la red interna\n¿Hubo movimiento lateral? # Armamos un script de auditoría específica, luego lo estaré subiendo al repositorio para compartir, lo que hace es:\nIdentifica el sistema operativo\nBusca logs de autenticación /var/log/secure, journalctl\nEscanea por la IP sospechosa 10.100.10.122\nRevisa historial de comandos de root\nAnaliza accesos SSH exitosos y fallidos\nAudita registros de /var/log/audit\nResultado # No encontramos evidencia de movimiento lateral dentro de los activos analizados. El ataque parece haberse limitado a este servidor.\nMedidas implementadas # Dado que no era viable actualizar la plataforma por tratarse de un sistema legacy que debía continuar en producción, se optó por un enfoque orientado a mitigar el riesgo en lugar de eliminarlo completamente.\nLa estrategia adoptada fue rediseñar el entorno para reducir la superficie de ataque y aislar la aplicación vulnerable.\nCambios en la infraestructura # Migración a un host con Debian hardenizado Uso de contenedores con Podman Creación de una imagen con CentOS 7 para mantener compatibilidad con Liferay Aislamiento del servicio dentro del contenedor Este enfoque permitió encapsular la aplicación en un entorno controlado, limitando el impacto ante un posible compromiso.\nMedidas adicionales firewall # Restricción de acceso al sitio por país Reducción de superficie de ataque Mayor control del entorno El objetivo no era hacer el sistema perfecto, sino hacerlo mucho más difícil de comprometer.\nConclusión # Fueron la consecuencia de un sistema expuesto, atacado por herramientas automatizadas que explotan vulnerabilidades conocidas.\nLa solución no fue solo técnica, sino estratégica: pasar de reaccionar a incidentes → a diseñar un entorno más seguro.\nPorque en seguridad, muchas veces, no gana el sistema más fuerte…\nsino el que está mejor preparado.\nSi querés compartir tu experiencia, escribime a: valerkasystem@protonmail.com\nValerka\nMontevideo, Uruguay ","date":"25 de marzo de 2026","externalUrl":null,"permalink":"/posts/cryptojacking-centos-7-forense/","section":"Blog","summary":"Todo empezó con algo bastante clásico: un servidor en producción con CPU al mango . El consumo no bajaba, se mantenía alto, y eso en un sitio web… es raro . Muy raro.","title":"Cryptojacking en un servidor CentOS 7: análisis forense de una infección por minero de criptomonedas","type":"posts"},{"content":"","date":"25 de marzo de 2026","externalUrl":null,"permalink":"/tags/forense/","section":"Tags","summary":"","title":"Forense","type":"tags"},{"content":"","date":"25 de marzo de 2026","externalUrl":null,"permalink":"/categories/seguridad/","section":"Categories","summary":"","title":"Seguridad","type":"categories"},{"content":"","date":"21 de marzo de 2026","externalUrl":null,"permalink":"/tags/dns/","section":"Tags","summary":"","title":"Dns","type":"tags"},{"content":" Ni la primera semana de haber vuelto de la licencia… todo desconectado estaba, tratando de retomar el ritmo. Me preparo un mate, arranco la jornada tranquilo y, casi por costumbre, ya que hacia un par de semanas habia puesto en producción el DNS Technitium se me da por entrar al para ver cómo venía la red.\nGrave error… o gran acierto.\nEmpiezo a mirar el top de dominios consultados y aparece algo que no cerraba para nada. Dominios raros, completamente fuera de lo habitual. Ahí ya me hizo ruido.\nSiguiente paso: ver qué equipos estaban haciendo esas consultas.\nCaptura de pantalla, consultando desde el DNS, el dominio sospechoso y las direcciones IP involucradas. Cuando veo las IP… servidores internos.\nAhí fue cuando pensé: “okey bueno, arrancó el baile”. Todo indicaba que podía estar frente a algún tipo de malware o actividad maliciosa dentro de la red.\nY a partir de ese momento, empezó el análisis.\nPunto de partida: consultas DNS sospechosas # Detecto consultas recurrentes a un dominio que no me cerraba por ningún lado:\nv1ns.9kpk.com\nPrimera reacción: bloquearlo directamente desde el DNS.\nVista del dashboard de Technitium: a la izquierda, el top de dominios consultados y, a la derecha, el top de dominios bloqueados. Se destaca el volumen de consultas (Hits: 16.138) hacia el dominio sospechoso. v1ns.9kpk.com A los pocos minutos… boom.\nPasa al top de dominios bloqueados.\nAhí ya no era casualidad.\nMientras tanto, algo no me cerraba en la cabeza:\nestos servidores no tienen o no deberían tener salida a internet, y además son servicios internos, no expuestos.\nY sin embargo… estaban consultando dominios externos.\nCon esa contradicción dando vueltas, me conecto al servidor infectado para analizar qué estaba pasando desde adentro.\nAnálisis en servidor comprometido # Antes de meter mano, lo primero fue entender dónde estaba parado.\nLos servidores afectados corrían sobre:\nSistema operativo: CentOS 5.10 Kernel: 2.6.18-371.12.1.el5.centos.plus Y acá ya aparece un dato no menor… estamos hablando de sistemas legacy, sin soporte y con múltiples vulnerabilidades conocidas.\nCon ese contexto, todo empezaba a tener más sentido.\nEntonces arranco con lo básico para ver ese trafico hacia el servidor DNS interno:\ntcpdump -i any port 53 Y lo que veo confirma la sospecha:\nConsultas tipo A hacia dominios raros Respuestas NXDOMAIN (dominios inexistentes) Consultas PTR asociadas Comportamiento típico de manual:\nIntentos de contacto con servidores de comando y control (C2) Validación de conectividad Posible uso de DGA (Domain Generation Algorithm) Y ahí aparece el segundo actor en escena:\n2.ip1100.com\nListo, ya no era uno solo.\nEl tráfico malicioso estaba apuntando a:\nv1ns.9kpk.com 2.ip1100.com Buscando el origen # Empiezo a revisar servicios en el servidor… y algo no cuadraba.\ncat /etc/init.d/selinux\nEn CentOS 5 ese servicio no existe.\nAhí había algo raro.\nVeo el contenido:\n#!/bin/bash /usr/bin/bsd-port/knerl Bien!! Sospechoso de acá a la china esto ya era otra cosa.\nBuscando referencias, aparece el primer indicador claro:\nUn binario llamado knerl, intentando hacerse pasar por kernel.\nClásico intento de camuflaje.\nEl problema: no lo podía matar # Y ahí empezó la parte frustrante.\nBuscaba el proceso:\nps awx | grep knerl Nada.\nCon top… nada.\nHoras pasando… y el proceso seguía ahí, generando tráfico.\nProbaba matar otros procesos, volvía a mirar con tcpdump…\nseguía sucio.\nYa era personal.\nRootkit en juego # Investigando más a fondo, todo apuntaba a lo mismo:\ncomportamiento tipo rootkit\nEso explicaba todo:\nps, top, netstat → comprometidos El proceso estaba… pero no lo podía ver Hermoso desafío.\nContraataque # La solución fue ir por afuera:\nMe traje binarios limpios (ps, top, netstat) desde un servidor no comprometido, los empaqueté y los ejecuté directamente en el infectado.\nY ahí sí…\n./ps -AF | grep knerl Apareció !!!\n/usr/bin/bsd-port/knerl (PID 7372)\nAhí te tenía.\nPrimer golpe # kill -9 7372\nVuelvo corriendo a mirar el tráfico:\ntcpdump -i any port 53 …\nSigue habiendo tráfico sucio.\nPero algo cambió.\nv1ns.9kpk.com desapareció\nQuedaba solo 2.ip1100.com\nEso confirmaba que andaba otro cangrejo vivo.\nel malware tenía más de un componente activo\nY la limpieza… todavía no había terminado.\nSegundo componente malicioso # Si algo ya estaba claro, era esto: no estaba peleando contra un solo proceso.\nSigo revisando… y aparece otro candidato sospechoso un binario:\n/usr/bin/sshupdate-bootsystem-insserv\nEste tipo de nombres intenta simular procesos legítimos del sistema.\nSe procedió nuevamente:\nkill -9 \u0026lt;PID\u0026gt;\nEl momento de la verdad # Ahí sí… paro un segundo.\ntiré un “padre nuestro”\ny me fui directo a validar:\ntcpdump -i any port 53 Silencio.\nNi una consulta rara.\nNi v1ns.9kpk.com.\nNi 2.ip1100.com.\nTráfico limpio.\nDespués de horas peleando, el ruido había desaparecido.\nIdentificación de alcance # Con el servidor ya limpio, la siguiente pregunta era inevitable:\n¿cuántos más están infectados?\nPara determinar el alcance real, me apoyé en dos fuentes clave:\nLogs DNS en Technitium Tráfico de red desde firewall pfSense Y fui directo a la base de datos del srv DNS:\nSELECT DISTINCT client_ip FROM dns_logs WHERE qname = \u0026#39;v1ns.9kpk.com\u0026#39; AND timestamp \u0026gt;= \u0026#39;fecha_inicio\u0026#39; AND timestamp \u0026lt; \u0026#39;fecha_fin\u0026#39;; Conectado a la base de datos para identificar con certeza equipos infectados, esta captura muestra un select *, pero luego hice un destinct, obtuve todas las ip que hacian consulta a ese dominio. Solución # Con el incidente contenido, el foco ahora pasa a algo igual de importante: evitar que vuelva a ocurrir.\nLa estrategia definida es migrar este servicio a un entorno más controlado y seguro.\nLa idea es la siguiente:\nImplementar un host base sobre Rocky Linux 9, correctamente hardenizado Instalar Podman como motor de contenedores Contenerizar el servicio dentro de una imagen basada en CentOS 7 ¿Por qué CentOS 7?\nPorque el servicio es legacy y tiene dependencias muy específicas que no son compatibles con versiones más nuevas. Forzar una actualización directa no es viable en este momento.\nIndicadores de compromiso (IoC) # Dominios:\n2.ip1100.com v1ns.9kpk.com Binarios:\n/usr/bin/bsd-port/knerl /usr/bin/sshupdate-bootsystem-insserv Persistencia:\n/etc/init.d/selinux modificado Conclusión # Al momento de escribir este artículo, la investigación sigue en curso.\nTodavía no está del todo claro cuál fue el vector inicial de infección ni cómo se propagó hacia otros servidores. La hipótesis más fuerte apunta a un ingreso desde Internet, ya que los servidores afectados son sistemas internos que, en teoría, no deberían estar expuestos y tampoco tienen internet.\nAhí es donde aparece la duda más interesante:\n¿en algún momento existió una exposición no controlada? Un NAT temporal, una apertura puntual, alguna configuración que haya quedado habilitada más tiempo del debido… es una posibilidad que no se puede descartar.\nLo que sí parece poco probable es un origen interno mediante dispositivos físicos (como pendrives u otros medios), ya que no hay indicios que apunten en esa dirección.\nHoy por hoy, la única puerta lógica sigue siendo Internet.\nMientras tanto, continúo revisando logs, correlacionando eventos y tratando de determinar el alcance real de la infección.\nSeguramente este análisis no termine acá:\nsi aparecen nuevos hallazgos, evaluaré si hacer una segunda parte o actualizar esta misma entrada con más información.\nPorque si algo está claro, es que el incidente ya fue contenido…\npero la investigación recién empieza.\nSi querés compartir tu experiencia, escribime a: valerkasystem@protonmail.com\nValerka\nMontevideo, Uruguay ¿Qué es una botnet? - Actualización post-análisis # Esta es la segunda parte del post, luego de haber profundizado en el análisis y confirmado que el malware detectado pertenece a la familia BillGates (también conocida como Elknot), una botnet modular dirigida a sistemas Linux.\nNo voy a reescribir aquí qué es una botnet ni cómo funciona paso a paso —hay material excelente ya publicado—, pero sí quiero dejar un par de ideas clave para contextualizar lo que enfrentamos y por qué este hallazgo cambia la perspectiva del incidente.\nUna botnet (red de bots) es un conjunto de dispositivos comprometidos que, sin conocimiento de sus administradores, son controlados remotamente por un actor malicioso. Estos sistemas \u0026ldquo;zombis\u0026rdquo; se utilizan para:\nAmplificar ataques DDoS, saturando servicios con tráfico coordinado. Enviar spam masivo, aprovechando la reputación de dominios legítimos. Minar criptomonedas en segundo plano, consumiendo recursos. Robar credenciales y datos sensibles, actuando como puerta de entrada a redes internas. Propagarse lateralmente, infectando otros sistemas dentro del mismo entorno. En el caso específico de BillGates/Elknot, estamos ante una amenaza particularmente sigilosa:\nEscrita en C, modular y diseñada para Linux. Se camufla como procesos del sistema knerl simulando kernel . Persiste mediante servicios falsos /etc/init.d/selinux modificado. Se comunica con múltiples dominios C2 para recibir instrucciones. Emplea técnicas rootkit para ocultar procesos y binarios. Todo esto explica por qué el análisis inicial fue tan desafiante: no era solo tráfico raro, era un actor con capacidad de evasión y persistencia.\nSi querés profundizar en el tema, te recomiendo este artículo muy completo:\nBotnet: qué es, cómo funciona y cómo protegerse\n","date":"21 de marzo de 2026","externalUrl":null,"permalink":"/posts/dns-technitium-malware-billgates/","section":"Blog","summary":"Grave error… o gran acierto.","title":"El día que el DNS Technitium me mostró un malware - BotNet BillGates (Elknot)","type":"posts"},{"content":"","date":"21 de marzo de 2026","externalUrl":null,"permalink":"/tags/malware/","section":"Tags","summary":"","title":"Malware","type":"tags"},{"content":"","date":"21 de marzo de 2026","externalUrl":null,"permalink":"/tags/technitium/","section":"Tags","summary":"","title":"Technitium","type":"tags"},{"content":"","date":"10 de febrero de 2026","externalUrl":null,"permalink":"/categories/desarrollo/","section":"Categories","summary":"","title":"Desarrollo","type":"categories"},{"content":"","date":"10 de febrero de 2026","externalUrl":null,"permalink":"/tags/linux-mint/","section":"Tags","summary":"","title":"Linux-Mint","type":"tags"},{"content":"","date":"10 de febrero de 2026","externalUrl":null,"permalink":"/tags/netbeans/","section":"Tags","summary":"","title":"Netbeans","type":"tags"},{"content":"Actualmente, para desarrollo Java EE, estoy trabajando sin problemas con el siguiente stack:\nEclipse Enterprise WildFly PostgreSQL Hibernate Maven Git Java (un surtido importante de versiones, según el proyecto) En mi Linux Mint tengo disponibles varias versiones de Java, algo bastante común cuando se trabaja con proyectos viejos y nuevos a la vez:\nsudo update-alternatives --config java\nSalida:\nExisten 3 opciones para la alternativa java (que provee /usr/bin/java). Selección Ruta Prioridad Estado ------------------------------------------------------------ * 0 /usr/lib/jvm/java-17-openjdk-amd64/bin/java 1711 modo automático 1 /usr/lib/jvm/java-11-openjdk-amd64/bin/java 1111 modo manual 2 /usr/lib/jvm/java-17-openjdk-amd64/bin/java 1711 modo manual 3 /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java 1081 modo manual Pulse \u0026lt;Intro\u0026gt; para mantener el valor por omisión [*] o pulse un número de selección: Todo funcionando correctamente sobre Linux Mint 20 (Ubuntu 20.04 base).\nHasta acá, ningún drama.\nEl objetivo: revivir un proyecto viejo # Quise revivir un proyecto web antiguo llamado Espotify Web, que estaba corriendo en una máquina virtual con Windows 7, usando:\nNetBeans Tomcat MySQL Java EE “clásico” Para eso decidí instalar NetBeans en mi Linux Mint 20 y probar el proyecto localmente.\nAlgo que, en teoría, debería haber sido rápido y sencillo.\nSpoiler: no lo fue. # Problema 1: ni siquiera un Hello World funcionaba # Después de instalar NetBeans desde los repositorios de Mint, al intentar crear un proyecto Java simple y ejecutar un HelloWorld, aparecían errores como:\ncannot access java.lang Fatal Error: Unable to find package java.lang O incluso:\nClass does not have a main method Uncompilable source code La causa # NetBeans no tenía correctamente configurado el JDK como Java Platform, o estaba apuntando a un runtime incorrecto.\nIncluso indicando el path correcto de Java, simplemente no funcionaba, algo que sinceramente no podía creer.\nAdemás, el cache del IDE parecía estar en un estado inconsistente, lo que terminaba de romper cualquier intento de ejecución.\nSin más vueltas, la solución fue: # Eliminar NetBeans instalado desde los repos Borrar completamente cache y configuración: rm -rf ~/.netbeans rm -rf ~/.cache/netbeans Reinstalar NetBeans limpio Después de eso, Java volvió a funcionar correctamente y el HelloWorld finalmente compiló y ejecutó.\nBien ahí… primer obstáculo superado. !!\nProblema 2: NetBeans “funciona”… pero no tiene Maven # Con Java funcionando, el siguiente paso fue probar algo más real:\nel tutorial oficial de Oracle sobre JAX-RS con REST.\nTutorial JAX-RS\nFile → New Project\nsolo aparecían estas categorías:\nJava NetBeans Modules Samples / Java ❌ No había Maven\n❌ No había proyectos Web\n❌ No había JAX-RS\nEn ese punto ya empezaba a mirar el reloj: el tiempo invertido era mucho mayor al que había estimado para hacer un tutorial simple, solo para repasar conceptos.\nPero bueno… ya que estamos en el baile, vamos a bailar 💃\nDecidí investigar por qué NetBeans no tenía Maven.\nEl verdadero problema: NetBeans de los repos de Mint # El NetBeans que viene en los repositorios de Linux Mint / Ubuntu:\nEs muy viejo Viene recortado NO incluye soporte Maven No sirve para Java EE / Jakarta EE moderno Por eso:\nNo pude seguir el tutorial de Oracle en Netbeans No se pueden importar proyectos Maven Entonces # Comentarles mi suerte con NetBeans en Linux Mint 20.\n¿Este incidente amerita actualizar el sistema operativo?\nProbablemente no… pero sí obliga a replantear la herramienta.\nTal vez, cuando tenga más tiempo y voluntad de importar el proyecto, pruebe descargando un NetBeans más nuevo y oficial, compatible con Mint 20, para intentar importar Espotify Web, un proyecto de mis épocas de facultad.\nY lo que ya sabemos todos !\nProgramar no es lo más difícil, a veces…\nsino tener lista la herramienta para empezar a programar.\n¿Y a vos te anduvo?\n¿Tuviste los mismos problemas te funcionó sin vueltas?\nSi querés compartir tu experiencia, dudas o simplemente comentar cómo lo resolviste, escribime a: valerkasystem@protonmail.com\n— Valerka\nMontevideo, Uruguay\n","date":"10 de febrero de 2026","externalUrl":null,"permalink":"/posts/netbeans-linux-mint-20/","section":"Blog","summary":"Actualmente, para desarrollo Java EE , estoy trabajando sin problemas con el siguiente stack:","title":"NetBeans en Linux Mint 20: cuando “empezar a programar” no es tan simple","type":"posts"},{"content":"","date":"7 de febrero de 2026","externalUrl":null,"permalink":"/tags/android/","section":"Tags","summary":"","title":"Android","type":"tags"},{"content":"","date":"7 de febrero de 2026","externalUrl":null,"permalink":"/tags/crdroid/","section":"Tags","summary":"","title":"Crdroid","type":"tags"},{"content":"","date":"7 de febrero de 2026","externalUrl":null,"permalink":"/tags/nextcloud/","section":"Tags","summary":"","title":"Nextcloud","type":"tags"},{"content":"","date":"7 de febrero de 2026","externalUrl":null,"permalink":"/tags/privacidad/","section":"Tags","summary":"","title":"Privacidad","type":"tags"},{"content":" Hace ya un par de años que me cansé de que Google supiera más de mí que yo mismo. Cada app, cada notificación, cada “sugerencia”… todo apuntando a venderme algo o a atraparme en su red. Así que tomé una decisión: salir del ecosistema Google y recuperar el control de mi propio dispositivo.\nY no fue solo por privacidad. Fue también por libertad. Por poder elegir qué software corre en mi celular, cómo se sincroniza, y con quién comparto mis datos. Hoy, todo lo que necesito —contactos, calendarios, notas, fotos, incluso videollamadas— pasa por mi servidor, por mi nube: una instancia de Nextcloud que manejo desde mi VPS. Pero eso es tema pa’ otro post. Hoy te cuento cómo llegué hasta acá.\nMi hardware: Xiaomi Mi 11 Lite 4G (courbet) # Arranqué con un Xiaomi Mi 11 Lite 4G, que venía con MIUI 14 de fábrica. Un sistema lindo, sí, pero lleno de bloatware, servicios ocultos y dependencias innecesarias de la nube de Xiaomi y Google. Lo primero que hice fue investigar si podía desbloquearlo, rootearlo y meterle una ROM limpia.\nSpoiler: sí se puede. Y acá está el camino que recorrí.\nPaso 1: Desbloquear el bootloader # Xiaomi, como muchos fabricantes, bloquea el bootloader por defecto. Pero permite desbloquearlo… con condiciones.\nLo que hice:\nCrear una cuenta Mi y asociarla al número de teléfono.\nActivar modo desarrollador (tocando 7 veces en “Número de compilación”).\nDentro de Opciones de desarrollador, habilité:\nDesbloqueo OEM Depuración USB Depuración USB (ajustes de seguridad) En esa misma sección, usé “Estado de Mi Desbloqueo” → Agregar cuenta y dispositivo. Ahí me confirmó: “Dispositivo asociado con éxito”.\nDescargué la herramienta oficial Mi Unlock desde miui.com/unlock.\nReinicié en modo Fastboot (bajar volumen + power) y conecté el celular al PC.\nEjecuté Mi Flash Unlock como administrador, inicié sesión con mi cuenta Mi… y listo.\n⚠️ Ojo: Xiaomi exige un tiempo de espera (hasta 168 horas) entre asociar la cuenta y poder desbloquear. En mi caso, me lo permitió al toque, pero no siempre es así. Paciencia.\nUna vez desbloqueado, el celular se reinicia como nuevo. Así que hay que volver a activar las opciones de desarrollador y la depuración USB.\nPaso 2: Instalar ADB y Fastboot en Windows # Para comunicarme con el celular desde la PC, usé ADB (Android Debug Bridge). Lo instalé con el famoso “15 Seconds ADB Installer” de XDA Developers (link).\nPasos clave:\nInstalar como admin. Actualizar drivers desde el Administrador de dispositivos (usando los de Google). Verificar con adb devices que el celular aparece. Paso 3: Flashear TWRP Recovery # Con el bootloader desbloqueado, el siguiente paso fue instalar TWRP (Team Win Recovery Project), un recovery personalizado que permite flashear ROMs, hacer backups y mucho más.\nUsé la versión TWRP 3.7.0 para courbet (disponible en comunidades de XDA).\nComandos desde CMD (como admin):\nadb reboot bootloader fastboot devices fastboot flash recovery TWRP-3.7.0-courbet-ygherna.img 💡 Importante: para arrancar directamente en TWRP (sin que MIUI lo sobrescriba), usé:\nfastboot boot TWRP-3.7.0-courbet-ygherna.img Porque si solo flasheás y reiniciás normal, Xiaomi vuelve a cargar su recovery original.\nPaso 4: Instalar crDroid (sin Google) # Descargué la ROM crDroid 9.12 para courbet desde crdroid.net/courbet. Es una ROM basada en Android 13, estable, liviana y sin rastros de Google.\nEn TWRP hice lo siguiente:\nWipe → Format Data (escribir “yes” para confirmar). Install → seleccionar el ZIP de crDroid. NO instalé GApps (ni NikGApps ni nada). Quería un Android limpio. Reinicié al sistema. Resultado: un Android puro, rápido, sin trackers, sin sugerencias, sin sorpresas. Solo lo que yo elijo.\nCaptura pantalla versión androd instalado en Xiaomi MI 11 Lite Ajustes/Personalización crDroid - Abre lo bueno!!! Paso 4.5: Configurar la red móvil (APN) para Antel # Después del primer arranque, me di cuenta de que no tenía datos móviles ni podía usar internet fuera del Wi-Fi. Esto pasa porque las ROMs personalizadas como crDroid no incluyen los perfiles de APN de las operadoras locales.\nEn Uruguay, con Antel, la solución es fácil:\nEntré a https://configuraciones.antel.com.uy/marca/Xiaomi/modelo/Mi+11+Lite Agregué APN manualmente desde la URL, también se puede descargar e instalar el archivo de configuración (es un .apk pequeño). Abrí la app, seguí los pasos y reinicié el celular. Listo: datos móviles, MMS y todo funcionando como si nada hubiera pasado.\n💡 Si usás otra operadora (Claro, Movistar, etc.), buscá “APN + [tu operadora] + [tu modelo]” o ingresá manualmente los valores en Ajustes → Redes móviles → Nombres de punto de acceso (APN).\nPaso 5: Instalar apps sin Google Play # Con Android limpio, Google Play Store no existe. Pero eso no significa que te quedes sin apps. Uso dos fuentes principales:\nF-Droid: apps libres y de código abierto # Mi tienda predeterminada. Ahí encontrás alternativas éticas a casi todo:\nDavx⁵ (para sincronizar con Nextcloud) Element (Matrix/Chat descentralizado) NewPipe (YouTube sin rastreo) Osmand Maps, K-9 Mail, Mull(firefox) AntennaPod, etc. Sitio oficial: https://f-droid.org\nAurora Store: acceso anónimo a Google Play # Para esas apps que no tienen versión libre (como la del banco, ANTEL, Mercado Libre, etc.), uso Aurora Store.\nNo necesitás cuenta de Google. Descargás APKs directamente desde los servidores de Play Store, sin rastreo. Podés buscar, ver reseñas y actualizar como si estuvieras en Play… pero sin Google. Descarga desde: https://auroraoss.com\n💡 Consejo: instalá Aurora en modo “anónimo” y desactivá las notificaciones automáticas si querés más privacidad.\nCon estas dos herramientas, tengo todo lo que necesito, sin depender de Google ni comprometer mi privacidad.\nPaso 6: Conectar todo a mi nube (Nextcloud) # Ahora, en lugar de usar Gmail, Calendar o Keep, uso:\nDavx⁵ para sincronizar contactos y calendarios con mi Nextcloud. Nextcloud Notes para mis notas. Nextcloud Talk para mensajería y videollamadas (¡sí, funciona bien!). Photos y Files para respaldar todo localmente en mi servidor. Todo pasa por mi infraestructura. Mis datos no van a servidores de terceros. Y si mañana quiero cambiar de app o de proveedor, puedo hacerlo sin perder nada.\n¿Vale la pena? # Si, totalmente.\nSí, lleva tiempo. Un poco sí, en entender el procedimiento y juntar todo, hay que leer, probar, equivocarse (tratar de que no). Pero al final, tenés un dispositivo que te pertenece de verdad. No es un “terminal de usuario” diseñado para extraer tu atención. Es una herramienta tuya, bajo tu control.\nY eso, en estos tiempos, es un lujo.\nPróximo post: Cómo configurar Nextcloud All-in-One detrás de Nginx Proxy Manager con DuckDNS y Let’s Encrypt. Porque si vas a tener tu nube, que sea segura, rápida y accesible desde cualquier lado.\n¡Salud y buen blogging!\n— Valerka (Montevideo, Uruguay)\n¿Te gustó el post? ¿Tenés dudas, comentarios o querés compartir tu experiencia?\nEscribime a: valerkasystem@protonmail.com — ¡Siempre leo los mails y trato de responder cuando puedo!\n","date":"7 de febrero de 2026","externalUrl":null,"permalink":"/posts/android-libre-crdroid-nextcloud/","section":"Blog","summary":"Hace ya un par de años que me cansé de que Google supiera más de mí que yo mismo. Cada app, cada notificación, cada “sugerencia”… todo apuntando a venderme algo o a atraparme en su red. Así que tomé una decisión: salir del ecosistema Google…","title":"Salir de Google: mi camino a un Android libre con crDroid y Nextcloud","type":"posts"},{"content":"","date":"4 de diciembre de 2025","externalUrl":null,"permalink":"/categories/automatizaci%C3%B3n/","section":"Categories","summary":"","title":"Automatización","type":"categories"},{"content":"","date":"4 de diciembre de 2025","externalUrl":null,"permalink":"/tags/docker/","section":"Tags","summary":"","title":"Docker","type":"tags"},{"content":" En mi infraestructura casera, basada en Proxmox VE con contenedores LXC, hoy conviven dos buscadores: Whoogle y SearXNG.\nNo porque uno sea mejor que el otro, sino porque me sirven para búsquedas distintas, según el tipo de información que necesito:\nbúsquedas directas y rápidas, o una exploración más amplia y comparativa.\nWhoogle lo uso cuando quiero resultados al estilo Google, pero sin rastreo, sin JavaScript invasivo y sin cookies.\nSearXNG, en cambio, permite buscar en más de 100 fuentes distintas y priorizar resultados locales, por ejemplo de Uruguay, según cómo lo configures.\nAmbos corren en mi red, detrás de Nginx Proxy Manager, con HTTPS automático vía DuckDNS + Let’s Encrypt, y son accesibles desde cualquier dispositivo mediante usuario y contraseña.\nOpción 1: Whoogle — tu Google privado # Whoogle es ideal si querés la experiencia de Google, pero sin espiar.\nFiltra anuncios, elimina AMP, bloquea tracking y te da URLs limpias.\nComando docker para levantarlo (con autenticación básica) # docker run --restart=always \\ --publish 5000:5000 \\ --detach \\ --name whoogle-search \\ -e WHOOGLE_USER=tu_usuario \\ -e WHOOGLE_PASS=tu_contraseña_segura \\ -e WHOOGLE_CONFIG_THEME=dark \\ -e WHOOGLE_CONFIG_DISABLE=1 \\ -e WHOOGLE_CONFIG_URL=https://tutorial.duckdns.org \\ -e WHOOGLE_FALLBACK_ENGINE_URL=\u0026#34;https://tutorial.duckdns.org/?q=\u0026#34; \\ benbusby/whoogle-search:latest Nota Importante (2025): # Desde enero de 2025, Google está bloqueando búsquedas sin JavaScript.\nPor eso, el WHOOGLE_FALLBACK_ENGINE_URL es tu plan B:\nsi Whoogle falla, te redirige a DuckDuckGo con la misma consulta.\nConfiguración en Nginx Proxy Manager # Dominio: tu-dominio Forward a: http://IP_DEL_LXC:5000 SSL: activado con Let’s Encrypt ¡Listo! Accedé desde tu celular o browser. # Captura de pantalla acceso al buscador mediante user y pass Captura pantalla dentro de Whoogle Probando un búsqueda por ejemplo ¿Que es Whoogle? Opción 2: SearXNG — el meta-buscador descentralizado # Si Whoogle replica la experiencia de Google de forma limpia, SearXNG juega en otra liga!! ;)\nNo es un buscador único, sino un agregador que consulta múltiples motores al mismo tiempo, sin guardar búsquedas, sin crear perfiles y sin compartir datos entre usuarios.\nBusca en Google, DuckDuckGo, Bing, Wikipedia, YouTube, GitHub, Qwant y decenas más, y presenta los resultados unificados en una sola página.\nInstancias públicas # Pasos para desplegar: # Cloná el repo oficial git clone https://github.com/searxng/searxng-docker.git\nDebe quedar todo descomprimido en el servidor, a mi me quedo así: /home/docker/searxng\n2.1. Dentro del directorio searxng tenemos los siguientes archivos:\ndirectorio -\u0026gt; config directorio -\u0026gt; data archivo -\u0026gt; docker-compose.yml Generá una secret_key segura: openssl rand -hex 32\nEl archivo docker compose, configuralo a gusto: vim docker-compose.yml\nversion: \u0026#39;3.8\u0026#39; services: redis: image: redis:alpine restart: always command: redis-server --save \u0026#34;\u0026#34; --appendonly no tmpfs: - /var/lib/redis cap_drop: - ALL cap_add: - SETGID - SETUID - DAC_OVERRIDE networks: - searxng_net searxng: image: elestio/searxng:latest restart: always ports: - \u0026#34;2468:8888\u0026#34; # Solo accesible desde localhost (NPM hara el proxy) volumes: - ./searxng:/etc/searxng:rw environment: - SEARXNG_BASE_URL=https://tutorial.duckdns.org/ #tu dominio cap_drop: - ALL cap_add: - CHOWN - SETGID - SETUID - DAC_OVERRIDE logging: driver: json-file options: max-size: \u0026#34;1m\u0026#34; max-file: \u0026#34;1\u0026#34; depends_on: - redis networks: - searxng_net networks: searxng_net: internal: true # Aislamiento adicional: solo searxng y redis se ven Configurar el archivo config ( ojo que es muy sensible ) vim config/settings.yml\n# SearXNG - Configuración básica para Uruguay server: port: 8080 # elegir puerto preferido!! bind_address: 0.0.0.0 # donde queres que escuche tu interfaz de red!! secret_key: \u0026#34;tu_secret_key\u0026#34; general: instance_name: \u0026#34;elegí_nombre_instancia\u0026#34; default_locale: \u0026#34;es\u0026#34; search: default_lang: \u0026#34;es-UY\u0026#34; safe_search: 0 # 0=off, 1=moderate, 2=strict formats: - html - json plugins: self_info: false hostname: false ui: theme: \u0026#34;simple\u0026#34; default_theme: \u0026#34;simple\u0026#34; ¡Listo! Accedé desde tu celular o browser. # Captura pantalla dentro del buscador Probando una búsqueda ¿Y si quiero proteger el acceso con usuario y contraseña SearXNG? # Esto evita que tu instancia pública sea usada como proxy abierto o para scraping masivo.\nWhoogle lo hace nativo (WHOOGLE_USER / WHOOGLE_PASS).\nSearXNG no, pero Nginx Proxy Manager sí.\nEn NPM:\nCreá una Access List. Agregá un usuario y contraseña. Asignala al proxy host de SearXNG. Captura pantalla de Nginx Proxy Manager para crear Access List. Resultado: antes de ver la página solicita login\nCaptura pantalla login para SearXNG Errores comunes # 502 Bad Gateway: usualmente el contenedor no responde. Verificá los logs y que el puerto esté escuchando.\nInvalid settings.yml: en SearXNG 2025+, plugins: {} ya no funciona. Usá claves explícitas.\nReflexión final # Autohospedar herramientas como estas no es solo tecnología.\nEs una decisión técnica y personal.\nNo necesitás ser ingeniero/a: alcanza con curiosidad, paciencia y ganas de no depender de los gigantes.\nHoy, Whoogle y SearXNG corren en mis LXC, detrás de Nginx Proxy Manager, con mi propio dominio.\nY cada búsqueda que hago no alimenta perfiles ni entrena algoritmos: es mía.\n¿Te animás a montar el tuyo?\nEl código es tuyo, la infraestructura es tuya, los resultados también.\n¡Salute y buen blogging!\n— Valerka (Montevideo, Uruguay)\n¿Te gustó el post? ¿Tenés dudas, comentarios o querés compartir tu experiencia?\nEscribime a: valerkasystem@protonmail.com — ¡Siempre leo los mails y trato de responder cuando puedo!\n","date":"4 de diciembre de 2025","externalUrl":null,"permalink":"/posts/buscador-privado-docker-whoogle-searxng/","section":"Blog","summary":"En mi infraestructura casera, basada en Proxmox VE con contenedores LXC, hoy conviven dos buscadores: Whoogle y SearXNG . No porque uno sea mejor que el otro, sino porque me sirven para búsquedas distintas , según el tipo de información que…","title":"Montá tu propio buscador privado en casa con Docker: Whoogle o SearXNG","type":"posts"},{"content":"","date":"4 de diciembre de 2025","externalUrl":null,"permalink":"/tags/searxng/","section":"Tags","summary":"","title":"Searxng","type":"tags"},{"content":"","date":"4 de diciembre de 2025","externalUrl":null,"permalink":"/tags/whoogle/","section":"Tags","summary":"","title":"Whoogle","type":"tags"},{"content":"Bueno, acá te cuento cómo hago —y por qué— cuando necesito agregar mucho espacio a una máquina virtual en Proxmox, ya sea pa’ Samba, Nextcloud o cualquier servicio que coma disco como si no hubiera mañana.\nEn mi caso, suelo seguir dos caminos:\nAgregar varios discos virtuales (qcow2) a la VM y armar un volumen LVM combinado. O, si ya tengo un volumen LVM y me quedé corto, expandirlo agregando otro disco. Hoy te muestro el primer caso: crear un volumen lógico de 4TB usando 4 discos de 1TB cada uno (o los que sean). Todo esto desde adentro de la VM, porque así tengo más control y flexibilidad.\nEscenario de uso # Tengo una VM en Proxmox (Debian/Rocky, pero sirve para cualquier Linux). Necesito mucho espacio: 4TB, por ejemplo. En vez de crear un solo disco gigante de 4TB (que puede complicar backups o migraciones), prefiero agregar 4 discos de 1TB o 8 discos de 500Gb. Dentro de la VM, los junto con LVM y los uso como un solo “disco lógico”. ¿Por qué? Porque LVM me permite después agrandar, achicar, mover o hacer snapshots si uso LVM-Thin. Y porque así Proxmox no se queja tanto con discos muy grandes.\nPaso a paso: de los discos qcow2 al volumen montado # 1. Agregar los discos desde Proxmox # En el panel de Proxmox:\nSeleccioná tu VM. “Hardware” → “Add” → “Hard Disk”. Elegí el storage, el tamaño (ej. 1TB) y formato (qcow2). Repetí esto 4 veces → te van a aparecer como /dev/vdb, /dev/vdc, /dev/vdd, /dev/vde (si no tenías otros discos). 💡 Si ya tenés discos asignados, usá lsblk o fdisk -l para ver sus nombres.\n2. (Opcional) Limpiar particiones # Si los discos son nuevos, no hace falta particionarlos. Pero si querés estar seguro:\nSi los discos son nuevos, no hace falta particionarlos. Pero si querés estar seguro:\nfdisk /dev/vdb\nd → borrar particiones si hay. n → crear una nueva (enter pa’ todo). t → tipo 8e (Linux LVM). w → grabar. Repetí con vdc, vdd, vde. O salteate este paso si confiás en que están limpios.\n3. Crear los Physical Volumes (PV) # Decile a LVM que estos discos son “materia prima”:\npvcreate /dev/vdb /dev/vdc /dev/vdd /dev/vde Verificá:\npvs 4. Crear el Volume Group (VG) # Agrupá los 4 discos en un solo grupo, que yo llamo vg_data:\nvgcreate vg_data /dev/vdb /dev/vdc /dev/vdd /dev/vde Cofirmá\nvgs 5. Crear el Logical Volume (LV) # Ahora armá el “disco final”. Si sabés que son 4TB:\nlvcreate -L 4T -n lv_data vg_data O, si no querés calcular:\nlvcreate -l 100%FREE -n lv_data vg_data Cheuqeá\nlvs 6. Formatear y montar # Formateá con ext4 (o xfs si preferís):\nmkfs.ext4 /dev/vg_data/lv_data Montá:\n1 mkdir -p /mnt/data 2 mount /dev/vg_data/lv_data /mnt/data 7. Montaje permanente # Evitá que se desmonte al reiniciar:\nblkid /dev/vg_data/lv_data Copiá el UUID y agregalo a /etc/fstab:\nUUID=tu-uuid-aquí /mnt/data ext4 defaults 0 0 Probá que funcione:\numount /mnt/data mount -a df -h ¿Y si ya tengo un volumen y quiero agrandarlo? # Fácil:\nAgregá un nuevo disco desde Proxmox. Hacé pvcreate /dev/vdX. Extendé el VG: vgextend vg_data /dev/vdX. Extendé el LV: lvextend -L +1T /dev/vg_data/lv_data. Expandí el filesystem: resize2fs /dev/vg_data/lv_data (pa’ ext4). ¡Y listo! Sin tocar lo que ya tenías andando.\nConclusión # Usar LVM con discos qcow2 en Proxmox me da flexibilidad, orden y futuro. No dependo de un solo archivo gigante, y si mañana quiero migrar un disco o hacer un backup parcial, lo puedo hacer sin dolores de cabeza.\nEs más trabajo al principio, sí. Pero una vez armado, es puro disfrute (o al menos, puro uptime).\n— Valerka (Montevideo, Uruguay)\n¿Te sirvió? ¿Querés compartir tu forma de manejar storage en Proxmox?\nEscribime a: valerkasystem@protonmail.com — ¡Siempre leo los mails y trato de responder cuando puedo!\n","date":"28 de noviembre de 2025","externalUrl":null,"permalink":"/posts/volumen-lvm-4tb-proxmox-qcow2/","section":"Blog","summary":"Bueno, acá te cuento cómo hago —y por qué— cuando necesito agregar mucho espacio a una máquina virtual en Proxmox , ya sea pa’ Samba, Nextcloud o cualquier servicio que coma disco como si no hubiera mañana.","title":"Cómo armar un volumen LVM de 4TB en Proxmox usando discos qcow2","type":"posts"},{"content":"","date":"28 de noviembre de 2025","externalUrl":null,"permalink":"/tags/lvm/","section":"Tags","summary":"","title":"Lvm","type":"tags"},{"content":"","date":"28 de noviembre de 2025","externalUrl":null,"permalink":"/tags/qcow2/","section":"Tags","summary":"","title":"Qcow2","type":"tags"},{"content":"","date":"27 de noviembre de 2025","externalUrl":null,"permalink":"/tags/redundancia/","section":"Tags","summary":"","title":"Redundancia","type":"tags"},{"content":"Bueno, llegó la hora de meterle mano a la redundancia externa de servidores. El pedido está claro: hay que dejar en pie una copia de respaldo —y bien sincronizada— tanto del servidor de correo electrónico como del servidor de archivos (Samba).\nEn esta entrada me voy a centrar en lo de Samba, porque el tema del correo trae su propia historia: estamos aprovechando para migrar de Zimbra a Carbonio, mover toda la data, y de paso implementar redundancia. Pero ya en ese proceso nos topamos con un problema de fondo: el disco qcow2 de Carbonio, alojado en uno de los data centers, anda medio lento, y todo apunta a cuellos de botella en el GlusterFS. Ese tema lo voy a desarollar en otro post, que también da para rato.\n¡Pero volvamos al asunto principal!\nTenemos dos data centers físicamente separados: llamémosles DC A y DC B. La idea es simple: armar un clon del servidor Samba en el DC B y tenerlos sincronizados en modo espejo usando Syncthing.\nSí, ya sé\u0026hellip; a más de uno le va a sonar un poco “a pedal”. Pero la verdad es que es una solución sólida, segura y transparente. Syncthing trabaja con protocolo P2P, cifrado de punta a punta, sin depender de terceros. Claro que existen alternativas más modernas, como MinIO —un servidor de almacenamiento de objetos distribuido, tipo S3— y seguro que en algún momento lo vamos a evaluar. Pero, muchachos, no nos apuremos: implementar algo así requiere investigación, pruebas, ajustes… y un presupuesto que por ahora no está en la agenda. Ese va a ser un lindo desafío para una segunda etapa, cuando el tema esté maduro.\nPor ahora, este esquema “arcaico” —como alguno diría— me da plena confianza: es simple, controlable y cumple con el objetivo: alta disponibilidad sin depender de la nube.\nY listo, ¡manos a la obra!\nAmbos data centers corren Proxmox, así que el flujo de trabajo es relativamente ordenadito:\nPartimos del backup de la VM en cuestión, pero sólo del disco que contiene el sistema operativo. Ese backup lo llevamos al DC B. Lo restauramos, ajustamos IP, nombre de host y firewall. Le añadimos discos duros del mismo tamaño que en el original (hablamos de varios terabytes). Armamos un volumen LVM para manejar el espacio de forma flexible. Instalamos Syncthing en ambos servidores. Configuramos el modo espejo… ¡Y a esperar que los terabytes se sincronicen! No es magia, pero sí es trabajo bien hecho. Y en esto, como en el fútbol, a veces lo simple es lo más efectivo\n¡Salud y buen blogging!\n— Valerka (Montevideo, Uruguay)\n¿Te gustó el post? ¿Tenés dudas, comentarios o querés compartir tu experiencia?\nEscribime a: valerkasystem@protonmail.com — ¡Siempre leo los mails y trato de responder cuando puedo!\n","date":"27 de noviembre de 2025","externalUrl":null,"permalink":"/posts/redundancia-externa-servidores/","section":"Blog","summary":"Bueno, llegó la hora de meterle mano a la redundancia externa de servidores . El pedido está claro: hay que dejar en pie una copia de respaldo —y bien sincronizada— tanto del servidor de correo electrónico como del servidor de archivos…","title":"Redundancia Externa de Servidores: un enfoque a lo Yorugua","type":"posts"},{"content":"","date":"27 de noviembre de 2025","externalUrl":null,"permalink":"/tags/servidores/","section":"Tags","summary":"","title":"Servidores","type":"tags"},{"content":" El escenario: un proyecto que nadie quería tocar # Hace unos días, me enfrenté a algo que muchos desarrolladores temen: un proyecto Android de 2017.\nSí, 2017.\nParte de un sistema universitario multi-módulo (PencaUy) desarrollado para un laboratorio de la facultad. Un proyecto nacido para gestionar pencas deportivas, con un componente mobile que se integraba con el módulo local.\nEste sistema cuenta de tres partes principales:\nMódulo Central: Ejecutándose en la Nube. Módulo Local: Instalado on premise en distintas organizaciones, compuesto por un backoffice y un frontoffice para administración. Cada instancia local se ejecuta sobre WildFly 14 (ya migrado a WildFly 23) y utiliza una base de datos PostgreSQL. Módulo Mobile: La aplicación Android que estuve migrando, permitiendo a los usuarios participar en las pencas. Era un proyecto escrito en Java, con compileSdkVersion 27, minSdkVersion 16, dependencias de android.support.*, Gradle 4.4… y un AndroidManifest.xml que parecía un relicario de la era pre-AndroidX :)\nNadie lo había tocado desde su creación. El código dormía tranquilo, esperando a que alguien lo despertara. Y ese alguien fui yo… con la misión de hacerlo funcionar en Android 14, preparándolo para integrarse con APIs modernas de partidos y torneos\u0026hellip;\nEl objetivo: hacerlo funcionar en 2025 # No quería reescribirlo.\nNo quería empezar desde cero (aunque lo pensé).\nQuería migrar.\nCon todos sus bugs, sus APIs REST, sus AsyncTask, sus ListView… y su alma de Java 8 que en parte se mantiene en la lógica del código, por ahora.\nMi objetivo era claro: actualizar la infraestructura del proyecto para que pudiera compilar y ejecutarse en entornos modernos (Android Studio Flamingo, Gradle 8.x, Android 14), manteniendo la funcionalidad original intacta y preparándolo para futuras integraciones con APIs.\nLa migración: 10 horas de caos, 2 días de paciencia, 1 victoria # Aquí te cuento cómo lo logré!\nPaso 1: El primer error fue el más común — Cannot resolve symbol 'R' # Todo empezó con esto.\nNada compilaba.\nR no existía.\nLas clases android.support.* no se encontraban.\nSolución: # Actualicé Gradle a 8.7 Cambié build.gradle para usar namespace 'penca.pencauy' Eliminé el package del AndroidManifest.xml Agregué android.useAndroidX=true y android.enableJetifier=true en gradle.properties Pero… seguía sin funcionar.\n“¿Por qué no genera R.java?”\nPaso 2: El enemigo invisible — Java 11 vs Java 17 # El error más silencioso, el que me hizo perder 8 horas:\nAndroid Gradle plugin requires Java 17 to run. You are currently using Java 11.\nMi sistema linux tenía instalado Java 8 (configurado para desarrollos específicos en Eclipse) y Java 11 (por defecto del S.O).\nAGP 8.x requiere Java 17 para compilar el proyecto.\nY Android Studio… no lo sabía, o al menos Gradle no lo estaba usando.\nEs importante aclarar: el código Java del proyecto sigue siendo compatible con Java 8 (y eso no lo cambié).\nLo que sí necesitaba actualizar era la versión de Java usada por el proceso de compilación de Gradle.\nGradle 8.7 y AGP 8.x+ necesitan Java 17 o superior para funcionar.\nSolución: # Instalé OpenJDK 17: sudo apt install openjdk-17-jdk Agregué en gradle.properties\norg.gradle.java.home=/usr/lib/jvm/java-17-openjdk-amd64 Y ¡sí! Funcionó.\nGradle pudo ejecutarse correctamente, y el proceso de generación de recursos (y por ende R.java) pudo iniciar.\nLección clave: La versión de Java en la que escribes tu código (Source \u0026amp; Target Compatibility en Project Structure) puede ser diferente a la versión de Java que usa Gradle para compilar.\nPara usar AGP moderno, asegúrate de que Gradle use Java 17+.\nPaso 3: El “constant expression required” — el más frustrante # En MainActivityDrawer.java, esta línea:\ncase R.id.nav_pencas:\n…me decía:\n“No puedo usar esto como constante. ¿Qué demonios?”\nEn esta captura pantalla del código switch, se observa la liena subrayada olor rojo, la que da dolor de cabeza! ¿Por qué? Porque el archivo R.java no contenía los IDs nav_pencas, nav_ranking, etc. como constantes válidas para un switch.\n¿Por qué no los tenía? Parecía haber un error silencioso en el procesamiento de recursos, o una generación incorrecta de R.java, que impedía que los IDs del archivo activity_main_drawer_drawer.xml fueran reconocidos como constantes en tiempo de compilación. A pesar de intentar múltiples veces limpiar, reconstruir, eliminar la carpeta build, reiniciar Android Studio, y hasta usar el AGP Upgrade Assistant, el error persistió como un misterio.\nSolución temporal: # Dado que el objetivo inmediato era ver la aplicación corriendo, comenté las líneas del switch en el método onNavigationItemSelected\nCon esto, el proyecto compiló y la aplicación se ejecutó en el emulador. El botón de \u0026ldquo;Entrar\u0026rdquo; funcionó, el login se conectó a la API REST\u0026hellip; ¡La base estaba lista!\nLección clave (parcial): A veces, para avanzar, hay que dar un paso atrás. Si algo no funciona, aíslo temporalmente y resuelve lo demás. El problema del R.id.nav_... queda pendiente para resolverlo con una estrategia más profunda o incluso reconsiderando la estructura del menú.\nPaso 4: Migrar todo el código — de android.support.* a androidx.* # Cada clase Java tenía import android.support.v7.app.AppCompatActivity;\nCada layout tenía android.support.design.widget.TextInputLayout\nSolución: # Reemplacé manualmente cada import y cada tag XML. Usé el AGP Upgrade Assistant (Tools → AGP Upgrade Assistant) para actualizar de AGP 8.5.2 → 8.13.1. Esto actualizó automáticamente las dependencias y me ayudó a evitar errores de compatibilidad con Gradle 8.7. Lo más valioso: el asistente no arregló todo, pero me guió.\nMe mostró qué cambiar, por qué, y qué versiones eran compatibles.\n¿Funcionó? Sí. Y esto es lo que logré # Captura pantalla del modulo mobile que dormía\u0026hellip; Ahora miogrado y pronto para mejorarlo Al final del camino, tengo un proyecto nacido en 2017 corriendo en 2025, completamente actualizado en su infraestructura:\ncompileSdkVersion 27 → compileSdk 34 targetSdkVersion 27 → targetSdk 34 android.support.* → androidx.* Gradle 4.4 → 8.7 AGP 3.x → 8.13.1 El antiguo package en AndroidManifest.xml → namespace en build.gradle Y el proceso de compilación ahora corre sobre Java 17, aunque el código sigue en Java 8 (¡sí, se puede!). Lo más importante:\nEl emulador funciona con KVM.\nEl login se conecta a la API REST.\nLa aplicación se ejecuta correctamente en Android 14.\nEl proyecto compila (aunque con el switch de navegación temporalmente comentado).\nY, sobre todo, está listo para integrarse con las APIs del módulo local de Penca, tal como fue diseñado originalmente por el laboratorio.\nLecciones aprendidas (para ti, que estás en el mismo barco) # No necesitas reescribir un proyecto viejo para hacerlo moderno.\nPuedes migrarlo. Solo se necesita paciencia, método… y saber que el cache a veces miente. Java 8 + AndroidX + Java 17 es posible.\nTu lógica puede vivir en Java 8, mientras Gradle usa Java 17 para compilar. Son mundos distintos que conviven. ¿El R.java no aparece?\nNo es tu código. Es el estado interno de Android Studio.\n→ Borra app/build/\n→ Cierra el IDE\n→ Abre de nuevo\n→ Rebuild\n(Sí, a veces es así de simple… y frustrante). El AGP Upgrade Assistant no es un “botón mágico”.\nEs un guía inteligente. Úsalo como un aliado, no como una solución automática. Android Studio y Gradle evolucionan rápido.\nLo que funcionaba en 2017 hoy es obsoleto…\nPero no imposible. Solo requiere entender los cambios, uno a uno. ¿Qué sigue? # Ahora que el proyecto levanta y se puede ver en el emulador, el siguiente paso es reintegrar la navegación del Drawer (resolviendo el misterio del R.id.nav_...) y empezar a consumir las APIs del módulo local para gestionar pencas, participantes, partidos, y tablas de posiciones.\n¡Salud y buen blogging!\n— Valerka (Montevideo, Uruguay)\n¿Te gustó el post? ¿Tenés dudas, comentarios o querés compartir tu experiencia?\nEscribime a: valerkasystem@protonmail.com — ¡Siempre leo los mails y trato de responder cuando puedo!\n","date":"21 de noviembre de 2025","externalUrl":null,"permalink":"/posts/migrar-android-2017-a-2025/","section":"Blog","summary":"Hace unos días, me enfrenté a algo que muchos desarrolladores temen: un proyecto Android de 2017 .","title":"De Android 2017 a Android 2025: Cómo migrar un proyecto (y no morir en el intento)","type":"posts"},{"content":"","date":"21 de noviembre de 2025","externalUrl":null,"permalink":"/tags/migracion/","section":"Tags","summary":"","title":"Migracion","type":"tags"},{"content":"","date":"12 de noviembre de 2025","externalUrl":null,"permalink":"/tags/dell/","section":"Tags","summary":"","title":"Dell","type":"tags"},{"content":"Recientemente tuve que actualizar un entorno heredado basado en Proxmox VE 4 (sí, ¡de hace más de una década!) ejecutándose en un clúster, de servidores Dell PowerEdge R710, R720xd y R730, a una versión moderna y mantenible: Proxmox VE 9.\nDell PowerEdge R730 Dell PowerEdge R720xd Dada la gran brecha entre ambas versiones —cambios en la base del sistema operativo (Debian), kernel, stack de clustering y soporte de storage— no era viable una actualización in-place. La decisión fue realizar una instalación limpia en cada nodo, tras una descomposición controlada del clúster antiguo.\nEn este artículo comparto el proceso completo: desde la preparación del medio de instalación hasta la reinstalación secuencial de los nodos, incluyendo los pasos críticos para preservar la integridad del entorno y evitar sorpresas comunes en hardware Dell empresarial.\nTodas las capturas mostradas fueron tomadas durante el proceso real de instalación.\n1. Preparación del pendrive de instalación # Primero, descargué la ISO oficial de Proxmox VE 9.1 desde https://www.proxmox.com.\nLuego, grabé la imagen en un pendrive USB usando el comando dd en Linux:\nsudo dd if=~/Descargas/proxmox-ve_9.1.iso of=/dev/sdb bs=4M status=progress oflag=sync 2. Desarme del clúster Proxmox VE 4 # Antes de apagar cualquier nodo, fue fundamental desarmar el clúster existente para evitar inconsistencias o conflictos al reutilizar nombres e IPs.\nDesde el nodo maestro del clúster PVE 4, ejecuté el siguiente comando por cada nodo secundario:\npvecm delnode NOMBRE_DEL_NODO Repetí el proceso hasta que solo quedó un nodo en el clúster. Luego, apagué todos los servidores de forma ordenada.\nEste paso garantiza que no queden metadatos residuales de Corosync o pmxcfs que puedan interferir en futuras configuraciones.\n3. Instalación de Proxmox VE 9 en los nodos # Con el clúster desarmado y los servidores apagados, procedí a instalar Proxmox VE 9 en cada nodo, uno a uno:\nConecté el pendrive con la ISO.\nArranqué el servidor y presioné F11 para acceder al menú de arranque UEFI.\nSeleccioné el dispositivo USB como fuente de arranque.\nSeguí el asistente gráfico de instalación:\nSelección del disco (¡solo el destinado al sistema en RAID-1!). Configuración de red con IP fija. Zona horaria, contraseña de root y correo de notificaciones. Asistente gráfico de nistalación PVE9 3.1. Caso especial: Problemas con el Dell PowerEdge R710 # Dell Power Edge R710 Durante la instalación en un servidor Dell PowerEdge R710, encontré problemas inesperados al intentar instalar Proxmox VE 9. El instalador no cargaba la interfaz gráfica, y tras varios intentos, aparecían errores relacionados con:\nFallo en unsquashfs durante la extracción del sistema base. Errores de corrupción de datos en el filesystem SquashFS. Fallos en el servidor X (Xorg), lo que impedía cargar la GUI del instalador. error fatal del servidor X, “Bus error”, “Server aborting” command 'unsquashfs' failed with exit code 1 Solución temporal: Modo terminal + sin RAID # Tras investigar, descubrí que el problema estaba relacionado con la controladora RAID PERC H700 del R710, que puede tener conflictos con el kernel moderno de Proxmox VE 9, especialmente si el disco está en modo RAID o si hay problemas de compatibilidad con el firmware.\nPara poder instalar, tomé estas medidas:\nEliminé el RAID virtual desde la utilidad de configuración del controlador (Ctrl+R al arrancar). Pasé a modo JBOD/HBA (discos expuestos individualmente). Arranqué nuevamente desde el pendrive. El instalador ahora se inició en modo terminal (texto), pero fue posible completar la instalación manualmente. Eliminando RAID-1 desde la PERC H700 Asistente instalación PVE9 modo terminal La instalación fue exitosa en modo terminal, pero el uso de RAID sigue siendo necesario para producción. Por lo tanto, mi próximo paso será:\nInvestigar si existe un firmware actualizado para la controladora PERC H700 compatible con Proxmox VE 9. Evaluar si usar ZFS en modo JBOD es viable en este hardware. Considerar alternativas: ¿vale la pena invertir tiempo en hacer funcionar Proxmox en este modelo antiguo, o es mejor destinarlo a otro rol (backup, laboratorio, etc.)? Este caso será tema de un próximo artículo: “Instalación de Proxmox VE 9 en hardware legacy: Dell R710 y controladoras PERC antiguas”.\n4. Próximos pasos # Una vez todos los nodos tienen Proxmox VE 9 instalado:\nActualicé cada sistema: apt update \u0026amp;\u0026amp; apt dist-upgrade -y Planeo crear un nuevo clúster desde cero, estratégico como para implementar servicios en ambientes de Producción, Test, Desarrollo, Validación (sin migrar configuraciones antiguas). El storage anterior basado en GlusterFS ya no cuenta con soporte en Proxmox VE 9, por lo que en su lugar se debe implementar Ceph, la solución de almacenamiento distribuido integrada y oficialmente mantenida por Proxmox, creare otro post para esto. Conclusión # La migración de un entorno Proxmox tan antiguo como la v4 requiere planificación, pero es totalmente factible con una estrategia de reinstalación limpia. El uso de hardware empresarial como los Dell PowerEdge exige atención a detalles de firmware, RAID y arranque —y en algunos casos, como con el Dell R710, incluso reevaluar la viabilidad técnica de seguir utilizando modelos legacy con controladoras antiguas (como la PERC H700).\nEn mi caso, logré instalar Proxmox VE 9 en el R710 solo tras eliminar el RAID y forzar el modo terminal, lo que me permitió avanzar, pero también me dejó una pregunta clave: ¿vale la pena invertir tiempo en hacerlo funcionar en producción? La respuesta dependerá de pruebas futuras con firmware actualizado o alternativas como ZFS en JBOD.\nEste proceso no solo me permitió actualizar la infraestructura, sino también revisar y optimizar la arquitectura de virtualización desde cero: deshacerse de GlusterFS (ya obsoleto en PVE 9), evaluar Ceph como storage moderno, y entender mejor las limitaciones del hardware viejo frente a las exigencias del software actual.\n¡Salud y buen blogging!\n— Valerka (Montevideo, Uruguay)\n¿Te gustó el post? ¿Tenés dudas, comentarios o querés compartir tu experiencia?\nEscribime a: valerkasystem@protonmail.com — ¡Siempre leo los mails y trato de responder cuando puedo!\n","date":"12 de noviembre de 2025","externalUrl":null,"permalink":"/posts/proxmox-ve-9-dell-poweredge/","section":"Blog","summary":"Recientemente tuve que actualizar un entorno heredado basado en Proxmox VE 4 (sí, ¡de hace más de una década!) ejecutándose en un clúster, de servidores Dell PowerEdge R710, R720xd y R730 , a una versión moderna y mantenible: Proxmox VE 9 .","title":"Instalación limpia de Proxmox VE 9 Dell PowerEdge: migración desde PVE 4 paso a paso","type":"posts"},{"content":"","date":"12 de noviembre de 2025","externalUrl":null,"permalink":"/tags/virtualizacion/","section":"Tags","summary":"","title":"Virtualizacion","type":"tags"},{"content":"","date":"12 de noviembre de 2025","externalUrl":null,"permalink":"/tags/bind/","section":"Tags","summary":"","title":"Bind","type":"tags"},{"content":"Hace unos días me enfrenté a una de esas tareas que uno posterga hasta que la VM del DNS viejo empieza a congelarse cada dos por tres… Sí, ese BIND 9.3.4-P1 de 2007 que seguía en pie como un guerrero cansado.\nTenía muchas zonas configuradas, archivos .db acumulados durante casi dos décadas, y un solo objetivo: migrar todo a algo moderno, mantenible y con interfaz web. La elección fue clara: Technitium DNS Server .\nEl plan # Recopilar info del DNS actual (BIND 9 en CentOS 5 — sí, ¡aún existía!). Evaluar opciones: seguir con BIND en Rocky Linux o saltar a Technitium también sobre Rocky. Instalar Technitium con su script automático (¡un solo comando!). Migrar las zonas… sin morir en el intento. Todo iba bien… hasta que llegó el error:\nError! The zone file parser failed to parse \u0026lsquo;rdata\u0026rsquo; field on line #30.\ncaptura pantalla interfaz para administrar bind9 captura pantalla interfaz para administrar bind9 La línea maldita # Technitium es estricto (y con razón): espera archivos de zona en formato RFC 1035 limpio. Pero el viejo BIND era tan permisivo que toleraba cosas como:\ntareas\tIN\t1H\tA\t10.1.1.9 \u0026lt;- ¡TTL en el lugar del tipo! ¿Ves el problema? El TTL (1H) está en la posición del tipo de registro. BIND lo entendía\u0026hellip;; Technitium, no.\nAdemás, el archivo tenía cientos de tabs innecesarios y un bloque SOA roto:\n@\tIN\tSOA\t@\troot.localhost.\t( @ como servidor primario y root.localhost. como contacto… ¡imposible!\nLa solución (con truco de experiencia) # Lo primero que hice fue corregir el orden de los campos, eliminar los TTL mal ubicados y limpiar los espacios y tabs sobrantes. Incluso reescribí el bloque SOA con valores válidos y validé el archivo con named-checkzone.\nPero… el error persistía.\nFue entonces cuando cambié de estrategia. En vez de insistir con el archivo problemático, importé solo unas pocas zonas limpias. Funcionó. Agregué más… y más… hasta que aislé el bloque que contenía la famosa “línea 30”.\nAhí tomé la decisión más simple: recrear esa zona directamente desde la interfaz web de Technitium.\nNada de scripts, nada de formato legacy. Solo fui a Zones → Create Zone, cargué los registros a mano… y ¡listo!Technitium DNS Server es una herramienta sólida, ligera, con una UI clara y funciones modernas (DoH, DoT, bloqueo de dominios…). Pero el verdadero descubrimiento no fue la tecnología, sino el método.\nCuando enfrentás un error persistente, a veces el problema no está en el archivo… sino en el enfoque.\nEn vez de pelearte con un formato legacy que ni el autor original entendía, divide, prueba, aísla y decide: ¿vale la pena arreglarlo… o es más rápido empezar de cero?\nY si algún día te topás con “la línea 30”, no la odies. Solo tomá un respaldo, probá con un subconjunto y recordá:\nLa migración no es un acto heroico… es un proceso iterativo.\nQué placer!!! Nueva interfaz para adminsitrar DNS Configuración final # Forwarders: Ese tipo de zonas, simplemente como eran pocas, agregue desde le panel Web. Zonas inversas: todas importadas igual que las directas. Pruebas: con dig y nslookup desde clientes de prueba antes de apagar el viejo DNS. Conclusión # Technitium DNS Server es una herramienta sólida, ligera, con una UI clara y funciones modernas (DoH, DoT, bloqueo de dominios…). Pero el verdadero descubrimiento no fue la tecnología, sino el método.\nCuando enfrentás un error persistente, a veces el problema no está en el archivo… sino en el enfoque.\nEn vez de pelearte con un formato legacy que ni el autor original entendía, divide, prueba, aísla y decide: ¿vale la pena arreglarlo… o es más rápido empezar de cero?\nY si algún día te topás con “la línea 30”, no la odies. Solo tomá un respaldo, probá con un subconjunto y recordá:\nTip rápido: Instalá Technitium en menos de un minuto # Technitium DNS Server se instala en casi cualquier Linux moderno con un solo comando. Solo necesitás curl y permisos de sudo:\ncurl -sSL https://download.technitium.com/dns/install.sh | sudo bash El script instala automáticamente:\nEl runtime de .NET 8 (si no está presente), El servidor DNS, Y lo configura como servicio del sistema. Una vez instalado, abrí tu navegador y accedé a:\nhttp://\u0026lt;tu-servidor\u0026gt;:5380 Importante: si tenés un firewall activo (como ufw o firewalld), recordá abrir al menos el puerto 5380/tcp para la consola web y 53/udp-tcp para el servicio DNS.\nY listo. Ya tenés tu propio DNS moderno, con interfaz web, bloqueo de publicidad y soporte para DoH/DoT.\n¡Salud y buen blogging!\n— Valerka (Montevideo, Uruguay)\n¿Te gustó el post? ¿Tenés dudas, comentarios o querés compartir tu experiencia?\nEscribime a: valerkasystem@protonmail.com — ¡Siempre leo los mails y trato de responder cuando puedo!\n","date":"12 de noviembre de 2025","externalUrl":null,"permalink":"/posts/migrar-bind-technitium-dns/","section":"Blog","summary":"Hace unos días me enfrenté a una de esas tareas que uno posterga hasta que la VM del DNS viejo empieza a congelarse cada dos por tres… Sí, ese BIND 9.3.4-P1 de 2007 que seguía en pie como un guerrero cansado.","title":"Migrar servidor DNS - BIND 9.3 a Technitium DNS Server (y sobreviviendo al “enemigo de la línea 30”)","type":"posts"},{"content":"","date":"8 de noviembre de 2025","externalUrl":null,"permalink":"/tags/backups/","section":"Tags","summary":"","title":"Backups","type":"tags"},{"content":"","date":"8 de noviembre de 2025","externalUrl":null,"permalink":"/tags/bacula/","section":"Tags","summary":"","title":"Bacula","type":"tags"},{"content":"","date":"8 de noviembre de 2025","externalUrl":null,"permalink":"/tags/lxc/","section":"Tags","summary":"","title":"Lxc","type":"tags"},{"content":"“A veces, la infraestructura también se cansa… y dice: ‘Estoy cansado, jefe’.”\nEstuve lidiando con el envejecimiento de un clúster Proxmox VE 4 (sí, ese que ya tiene más años que algunos desarrolladores juniors). Los cinco nodos funcionaban, pero con cada vez más rarezas: reinicios espontáneos, comandos congelados, y lo peor: el directorio /etc/pve/ se volvía de solo lectura sin aviso.\nDurante meses venía trabajando en migrar todas las máquinas virtuales a la nueva generación de servidores, corriendo Proxmox VE 8. La mayoría de las VMs se movieron sin drama… hasta que llegó Bacula.\n¿Por qué Bacula era crítico? # Bacula no es cualquier servicio. Es el alma, es el sistema de respaldos en cinta LTO:\nManeja dos drives IBM LTO-7 y LTO-8. Escribe backups diarios de sistemas productivos. Usa dispositivos de bloques /dev/st0 y /dev/st1 directamente. No podía perderlo.\nIntento 1: Migrar el LXC como si nada # Primero, copié el disco del contenedor:\n(definiendo el nuevo id en el srv destino)\nscp root@\u0026lt;...\u0026gt;:/var/lib/vz/images/133/vm-133-disk-1.raw /mnt/pve/gluster_ssd/vm-236-disk-1.raw Luego, reconstruí el archivo de configuración (236.conf) con soporte para dispositivos de cinta agregando estas dos lineas:\nlxc.mount.entry: /dev/st0 dev/st0 none bind,optional,create=file lxc.mount.entry: /dev/st1 dev/st1 none bind,optional,create=file Todo parecía en orden… hasta que intenté arrancar el contenedor:\nScript exited with status 2 Failed to run lxc.hook.pre-start for container “236” El error venía del hook de Proxmox: no reconocía el storage gluster_ssd como válido para contenedores LXC.\nLección aprendida: no todos los storages soportan rootdir (solo dir, nfs, zfs, etc.).\nSolución: # crear un storage de tipo dir apuntando al mismo punto de montaje de GlusterFS:\ndir: dir_gluster_ssd path /mnt/pve/gluster_ssd content rootdir,images ¡Ahora el contenedor arrancaba! # Intenté también recuperar el servicio desde un backup generado en Proxmox 4 (vzdump-lxc-133-\u0026lt;...\u0026gt;.tar.gz), pero arrojó exactamente el mismo error al restaurarlo en PVE8. Incluso el comando pct backup 133 en el nodo antiguo quedaba bloqueado, confirmando que el entorno PVE4 ya no era fiable ni siquiera para operaciones básicas, y mucho menos para servicios de producción.\nPero… no todo era color de cinta LTO # Al entrar al contenedor, el desastre se hizo evidente:\n[root@bacula ~]# systemctl status bacula-dir Failed to get D-Bus connection: No such file or directory [root@bacula ~]# ip a eth0: \u0026lt;...\u0026gt; state DOWN ¿Qué pasó? # Proxmox 8 usa cgroups v2 por defecto.\nEl contenedor, basado en CentOS 7, trae una versión antigua de systemd (\u0026lt; v232), incompatible con cgroups v2.\nEl resultado: # Systemd no se inicia correctamente. La red no levanta. Bacula queda en un limbo técnico. El propio Proxmox VE 8 lo advierte:\nWARN: old systemd (\u0026lt; v232) detected, container won't run in a pure cgroupv2 environment!\n¿Y ahora qué? # La migración directa del LXC no es viable en el corto plazo. Pero tengo un plan B:\nMantener el nodo2 aislado del clúster (lo convertí en standalone, y milagrosamente dejó de congelarse).\n→ Bacula sigue haciendo backups desde allí. Migrar Bacula a una VM en Proxmox 8, no a un contenedor.\n→ Proxmox 8 sí permite asignar PCI passthrough de tarjetas SCSI a VMs, algo que Proxmox 4 no soporta. Por esa limitación, en su momento se optó por usar un contenedor LXC, ya que desde el kernel de PVE4 sí era posible acceder directamente a las cintas LTO-7 y LTO-8. Esto implica: # Reinstalar Bacula en una VM nueva. Restaurar configuraciones y catálogo desde respaldos. Probar la conexión con los drives físicos. Pero es el camino más limpio… y seguro.\ncaptura pantalla del dashboard del PVE4 con problema en los cluster, Se observa dell2 como lo dejo modo santdalone para que bacula pueda seguir operativa mientras se evalúa, migrar. Moraleja final # No todo lo que se puede copiar, se puede ejecutar.\nLa evolución del kernel (cgroups v1 → v2), los cambios en la gestión de recursos, y la vida útil de los sistemas operativos dentro de contenedores tienen consecuencias reales.\nProxmox VE 8 es moderno, eficiente… y no perdona la deuda técnica.\nA veces, la solución no es forzar una migración, sino replantear la arquitectura.\npróximo capítulo: “Bacula en VM: resucitando desde la cinta”.\ncaptura pantalla del dashboard del PVE8 donde era la idea levantar LXC de bacula\u0026hellip; ¡Salud y buen blogging!\n— Valerka (Montevideo, Uruguay)\n¿Te gustó el post? ¿Tenés dudas, comentarios o querés compartir tu experiencia?\nEscribime a: valerkasystem@protonmail.com — ¡Siempre leo los mails y trato de responder cuando puedo!\n","date":"8 de noviembre de 2025","externalUrl":null,"permalink":"/posts/bacula-lxc-proxmox-4-a-8/","section":"Blog","summary":"“A veces, la infraestructura también se cansa… y dice: ‘Estoy cansado, jefe’.”","title":"Rescatando a Bacula: la migración fallida (por ahora) de un LXC desde Proxmox 4 a Proxmox 8","type":"posts"},{"content":"","externalUrl":null,"permalink":"/authors/","section":"Authors","summary":"","title":"Authors","type":"authors"},{"content":"¿Tenés un sistema que ordenar, un servicio que desplegar o una tarea que automatizar? Escribime con el contexto y vemos el alcance.\nSolicitar presupuesto # Contame:\nQué necesitás resolver. En qué entorno corre hoy. Qué plazo manejás. Escribir por email Otros canales # Email: valerkasystem@protonmail.com Mastodon: @valercka@mastodon.uy GitHub: vmacarov Gitea: valerkagit.duckdns.org No uso formularios ni cookies de seguimiento. Si preferís, podés escribirme directamente por email o por Mastodon.\n","externalUrl":null,"permalink":"/contacto/","section":"Infraestructura, desarrollo y automatización","summary":"","title":"Contacto","type":"page"},{"content":"Casos reales de infraestructura y software como servicio. Cada ficha incluye la presentación completa del proyecto: tipo, problema, solución, tecnologías, resultado y aprendizajes.\nLos clientes son confidenciales; las tecnologías y el alcance son reales.\n","externalUrl":null,"permalink":"/proyectos/","section":"Proyectos","summary":"","title":"Proyectos","type":"proyectos"},{"content":"","externalUrl":null,"permalink":"/series/","section":"Series","summary":"","title":"Series","type":"series"},{"content":"Trabajo con problemas concretos: sistemas que fallan, servicios que hay que desplegar, tareas que se repiten y aplicaciones que necesitan evolucionar. La prioridad es que la solución quede funcionando, documentada y sea mantenible.\nQué puedo resolver # Soporte informático Diagnóstico y resolución de incidentes, mantenimiento y mejoras en entornos Linux y servicios informáticos.\nDiagnóstico basado en evidencia. Registro de cambios y decisiones. Propuestas para que el problema no vuelva. Infraestructura y sistemas Servidores Linux, virtualización con Proxmox, contenedores, DNS, proxy inverso, TLS, correo y monitoreo.\nMenos tareas manuales y configuraciones frágiles. Servicios reproducibles y documentados. Infraestructura pensada para operar. Desarrollo web y software Aplicaciones web y APIs, mantenimiento de sistemas existentes e integración con bases de datos y servicios.\nDesarrollo incremental, sin reescribir todo. Integración con lo que ya existe. Código mantenible y documentado. Agentes de IA y automatización Agentes de IA que ejecutan tareas por vos, scripts, integración de herramientas, despliegues reproducibles y evaluación de alternativas open source.\nTareas ejecutadas por agentes de IA, con supervisión y registro. Menos trabajo manual y menos errores. Procesos repetibles y auditables. Herramientas open source elegidas por necesidad. Cómo trabajo # 1 Relevamiento y diagnóstico Entiendo el problema, el entorno y las restricciones antes de proponer una solución. 2 Propuesta y alcance Defino qué se va a hacer, qué queda fuera y cómo se valida el resultado. 3 Implementación Trabajo en cambios pequeños, verificables y documentados. 4 Documentación y transferencia El sistema queda operable, entendible y con el conocimiento transferido. Modalidades de contratación # Asistencia técnica por hora para diagnósticos, incidentes y consultas puntuales. Trabajos de infraestructura presupuestados por alcance para migraciones, despliegues y puestas en marcha. Desarrollo de software por proyecto con alcance y entregables definidos. Mantenimiento y soporte recurrente, sujeto a evaluación del entorno y las necesidades. No publico tarifas fijas porque cada trabajo tiene un alcance distinto. Contame qué necesitás y te paso una propuesta.\nSolicitar presupuesto Ver casos de éxito ","externalUrl":null,"permalink":"/servicios/","section":"Servicios","summary":"","title":"Servicios","type":"servicios"},{"content":"Soy Valeri Macarov, Técnico en Informática egresado de la Facultad de Ingeniería de la Universidad de la República (FING–UdelaR), de Uruguay. Llevo 10 años trabajando en infraestructura informática, administración de sistemas y desarrollo de soluciones tecnológicas en entornos reales.\nMe interesa entender cómo funcionan las cosas, encontrar herramientas adecuadas para cada problema y construir soluciones que sean útiles y sostenibles en el tiempo.\nQué hago # Trabajo con servidores Linux, redes, virtualización y servicios autohospedados. También desarrollo aplicaciones e integro distintas tecnologías para resolver necesidades concretas, desde la puesta en marcha de servicios hasta la automatización de tareas y la configuración de entornos completos.\nEn mis proyectos independientes busco ofrecer soluciones ajustadas a cada necesidad, priorizando la autonomía técnica, el uso eficiente de los recursos y, siempre que sea viable, las alternativas de software libre y código abierto.\nProyecto de IA soberana # Hoy lidero un proyecto de IA soberana, sobre el marco de AGESIC para la inteligencia artificial en el Estado uruguayo. El foco está en identificar casos de uso para automatizar —acceso a la información y procesos repetitivos— con una prioridad clara: que la IA sea útil sin que los datos viajen a servidores del exterior. Privacidad, control y tecnología al servicio de quien usa los datos.\nProtección de datos # También soy referente del área informática en la Comisión de Protección de Datos ante la URSEC, donde tecnología y protección de datos personales se encuentran todos los días.\nCómo trabajo # Me gusta investigar antes de implementar, probar las herramientas en entornos reales y documentar las decisiones tomadas. Intento que cada solución no solo funcione, sino que también pueda comprenderse, mantenerse y evolucionar sin depender de tecnologías o servicios cerrados.\nTrabajo de forma práctica e iterativa: analizo el problema, evalúo alternativas, implemento, pruebo y ajusto. Utilizo herramientas de automatización y asistencia mediante inteligencia artificial como apoyo al desarrollo, sin dejar de lado la revisión técnica y la comprensión de lo que construyo.\nTecnologías y áreas de trabajo # Mi trabajo abarca distintas áreas que se complementan entre sí:\nSistemas e infraestructura: Linux, administración de servidores, redes, virtualización con Proxmox y servicios de infraestructura. Contenedores y servicios autohospedados: Docker, despliegue y mantenimiento de aplicaciones y servicios web. Redes y acceso seguro: DNS, VPN, proxy inverso y autenticación centralizada. Desarrollo de software: Java y tecnologías Java EE, JavaScript, React, Node.js y desarrollo de aplicaciones web. Bases de datos: PostgreSQL, MongoDB y administración de servicios de datos. Automatización, agentes de IA y herramientas abiertas: scripting con Bash, agentes de IA que ejecutan tareas de principio a fin, integración de servicios y exploración de tecnologías open source. Este conjunto de herramientas refleja áreas en las que trabajo y desarrollo proyectos, no una lista de certificaciones profesionales.\nEste blog # Escribo sobre lo que aprendo, lo que armo, lo que funciona y lo que falla.\nComparto experiencias, configuraciones, pruebas y soluciones que surgen de mi trabajo y de mis proyectos. La idea es dejar registro del proceso, documentar los problemas encontrados y compartir conocimientos que puedan servirle a otras personas.\nEnlaces # Email: valerkasystem@protonmail.com Mastodon: @valercka@mastodon.uy GitHub: vmacarov Gitea: valerkagit.duckdns.org Hablemos de tu proyecto ","externalUrl":null,"permalink":"/sobre-mi/","section":"Infraestructura, desarrollo y automatización","summary":"","title":"Sobre mí","type":"page"}]