Tengo docenas de contenedores de Docker corriendo en mi laboratorio hogareño, y docker compose logs no es la manera más feliz de debuguear un problema.
Durante meses estuve usando una estructura bizantina de volúmenes montados en las rutas donde cada contenedor escribe logs, pero me volvía loco con los permisos: cada aplicación de cada stack reacciona de manera distinta y contradictoria, desde "decime dónde te logueo, jefe, solamente fijate que el directorio exista porque no me quiero tomar la atribución de crearlo" hasta "si el archivo no tiene exactamente los permisos que espero, me hago pis y caca encima y me cierro".
En fin, evidentemente no soy el único con estos problemas, porque Dozzle parece hecho a medida. Es un servicio que lee el socket de Docker, captura los eventos al vuelo y los muestra en tiempo real en un panel web. Está diseñado para ser fácil de implementar. Esta es mi configuración local:
La plataforma de aplicaciones de Cloudflare tiene una limitación bien conocida: no se puede usar patrones con comodines en la ruta (por ejemplo, *.misitio.com). Si uno necesita alojar una aplicación en varios subdominios, tiene que agregar cada uno como una ruta distinta. Esto tiene dos desventajas. La primera: qué paja. La segunda: todos los subdominios existentes son visibles en los registros DNS.
Todo el mundo resuelve esto con redirects, pero yo no quería redirigir al usuario a otra URL, sino servir contenido en cualquier subdominio.
Al principio pensé que la solución era simple: si internamente dirigía todas las peticiones a un mismo lugar, podía alojar la aplicación ahí y responder según la url que figurara en la request. Pero historia larga hecha corta, no se puede: el router de Cloudflare rebota cualquier petición que no haya llegado al subdominio específico donde corre la aplicación.
Estuve un par de tardes peleando con este problema hasta que encontré la solución. Un worker sí puede usar patrones con comodines en la ruta, y además tiene la capacidad de reescribir la petición y devolvérsela al router de Cloudflare para que siga procesándola.
Con Wrangler instalado, usé la siguiente configuración en wrangler.jsonc:
Esta configuración monta un worker que responde en todos los subdominios. El código de index.js es:
function stripSubdomain(hostname) {
const parts = hostname.split('.');
if (parts.length <= 2) return hostname;
return parts.slice(-2).join('.');
}
export default {
fetch: async (req) => {
const originalUrl = new URL(req.url);
const modifiedUrl = new URL(req.url);
const rootDomain = stripSubdomain(originalUrl.hostname);
modifiedUrl.hostname = rootDomain;
const newReq = new Request(modifiedUrl, req);
newReq.headers.set('X-Original-Hostname', originalUrl.hostname);
return fetch(newReq, { cf: { resolveOverride: rootDomain } });
}
};
Esto intercepta la request, la modifica apuntándola a la ruta raíz, y graba la ruta original en la cabecera X-Original-Hostname para poder usarla más adelante.
Una vez que este worker está deployado en un dominio, solamente falta configurar el DNS. Hay que indicarle al navegador que el dominio acepta peticiones a cualquier subdominio. Hay varias formas de hacer esto, pero en Cloudflare la más simple es con un registro AAAA. En Name ponemos * y en Content ponemos 100::.
Hecho esto, cuando llega una petición a algo.misitio.com, el worker le sobreescribe la ruta a misitio.com, y ahí alguna aplicación que tengamos montada (un túnel, por ejemplo) la procesa, aprovechando X-Original-Hostname.
Por ejemplo, mi túnel Zero Trust apunta a un proxy Traefik que captura ciertas peticiones así:
Usando esta lógica se puede modificar completamente el flujo interno de peticiones. La única desventaja es el límite de cien mil ejecuciones de worker gratuitas por día, pero para el uso que le estoy dando, me sobra.
A veces necesitamos montar un servidor web de prueba y no tenemos ganas de pensar. Para estas situaciones podemos usar aplicaciones de Docker que se definen en un par de líneas y salen andando.
Opción 1: echo server
La opción más ligera es un echo server programado en Go que devuelve una respuesta HTTP 200 con un texto arbitrario.
En el directorio www ponemos el sitio, y listo el pollo.
Personalmente prefiero usar aplicaciones de Docker Compose porque son expresivas y es muy fácil manipular redes y volúmenes, pero también se puede configurar con un solo comando:
docker run --detach \
--name web \
--publish 80:80 \
--restart unless-stopped \
--volume ./www:/htdocs \
eriksoderblom/alpine-apache-php:latest
VS Code y sus forks permiten colorear tokens especificos a partir de sus TextMate scopes. Para saber qué scopes tiene un token, ponemos el cursor sobre él, abrimos la paleta de comandos y buscamos "Developer: Inspect Editor Tokens And Scopes". El diálogo muestra todos los scopes aplicables.
El tag de apertura <?php tiene el scope punctuation.section.embedded.begin.php
Copypasteamos el scope que nos interesa y agregamos un bloque como este a nuestro settings.json:
Aparentemente el coloreado semántico tiene precedencia sobre el coloreado por token, así que puede que tengas que desactivarlo buscando "semantic highlighting" en la configuración de VS Code.
Ayer hablé de King Stephen, y no puedo pensar en él sin pensar también en Master Boot Record.
Master Boot Record es un productor italiano que hace chiptune, dark synth, metal sinfónico e industrial. Tiene un proyecto secundario que se llama Keygen Church y suena como música de iglesia, si la iglesia estuviera dedicada al Omnissiah.
Así recuerdo las clases de Catequesis
La palabra "keygen" me despierta recuerdos muy vívidos de madrugadas de verano tomando Ades de durazno y comiendo pizza fría del día anterior, perdido en páginas con fondo negro y letras verdes mientras el resto del mundo dormía. Era feliz y no lo sabía.
Pero tengo una relación muy rara con la retroinformática (a diferencia de mis demás relaciones, que son todas normales y neurotípicas). Siento un cariño enorme por la computación de los 90: PC Users, revistas gallegas con CDs de shareware, Astalavista, Geocities, IRC, Looksharp, SuperKoD, Netbus, SubSeven Bonus... Son literalmente mi infancia. Pero ese afecto es por las lindas experiencias compartidas, y daría cualquier cosa para NO volver a eso.
Este mismo sitio web es un reflejo de ese sentimiento: tiene la estética de mi primera página de Geocities de 1998, pero corre en un Docker con Nginx y tiene diseño responsive. Es un homenaje a mis raíces, no una declaración de que "todo tiempo pasado fue mejor".
No fue un carajo mejor: Windows 95 era una porquería inestable, Linux era inescrutable, navegar con un modem de 56k (que levantaba 33,6k en un buen día) ocupando la línea telefónica y pagando llamada local era un bajón, mi Pentium 75 Mhz con 8 MB de RAM y 812 MB de disco era un pisapapeles que tardaba 5 minutos de reloj en abrir Paint Shop Pro shareware... Se me revuelve el estómago.
Últimamente pareciera que en el Siglo XXI lo único que vende es la nostalgia por el Siglo XX: cuando el futuro se ve tan oscuro, la única que queda es mirar al pasado.
Gracias, Hollywood, es exactamente lo que quería
Pero lo que siento no se trata de nostalgia. Recuerdo con cariño los 90 porque no tenía responsabilidades ni preocupaciones, así que podía quedarme toda la noche en IRC chateando (o en IRCWar) con mis amigos, armando pavadas en Visual Basic 6 o Front Page 98, leyendo tequistés sobre phreaking que habían circulado por BBS durante 20 años antes de terminar en una página de Angelfire, o grindeando madera para la barca en el Argentum mientras escuchaba Theatre of Tragedy. Pero hoy también disfruto todas esas cosas: mi relación con la tecnología no cambió. En ese sentido, el chiptune, el retrofuturismo y la informática vintage son una celebración del camino recorrido, y sirven para darle contexto al presente y sentido al futuro, no para tratar de recuperar un pasado idealizado.
Cuando digo que "la Internet de antes era mejor" no hablo de volver al Internet Explorer 4; me refiero a que sé lo linda que puede ser una comunidad cuando no está montada sobre una plataforma de marketing y psyops armada por un billonario sociópata, y que necesito más de lo primero y menos de lo segundo en mi vida.
En resumen, este tano hace música muy buena que me gusta mucho.
Mudé este sitio web a mi laboratorio hogareño porque la instancia de GCP tenía poco almacenamiento. Configurar Cloudflare Zero Trust para responder peticiones de un subdominio gratuito No-IP fue toda una aventura: definitivamente no es un caso de uso que hayan contemplado. Esto es un tutorial de cómo se hace.
La idea básica es configurar el subdominio de No-IP como un hostname alternativo de un dominio válido en Cloudflare para que las peticiones puedan encontrar el camino hacia nuestro túnel.
Requisitos
Un túnel gratuito Cloudflare Zero Trust apuntando a donde queremos hospedar el sitio No-IP.
Una manera de enrutar las peticiones que llegan a nuestro túnel Zero Trust según la solicitud (ej: un proxy Traefik).
Un subdominio gratuito de No-IP (ej: [misubdominio].myddns.me, [misubdominio].ddns.net, etc.)
Un dominio cualquiera administrado por Cloudflare con el plan gratuito (ej: [midominio].com), al que le vamos a agregar un subdominio para convencer a Cloudflare de aceptar No-IP como válido.
Un servidor web accesible desde Internet que pueda servir archivos de texto en una ruta específica para el desafío HTTP ACME. Por ejemplo, si nuestra PC es visible desde Internet, con eso alcanza. Sino podemos usar una VM en algún servidor cloud o algo por el estilo.
Instrucciones
Configuramos nuestros servidores web:
Las peticiones a [subdominiocualquiera].[midominio].com tienen que devolver una respuesta HTTP OK cualquiera, aunque sea un simple 200 OK sin cuerpo. Tiene que ser una respuesta válida para que Cloudflare lo acepte.
Las peticiones a [misubdominio].myddns.me que lleguen a nuestro túnel Zero Trust tienen que devolver el servicio que queramos publicar. Con Traefik esto es una línea de configuración.
En Cloudflare:
Vamos a Zero Trust -> Networks -> Tunnels & mesh -> [nuestro túnel] -> Published application routes, y agregamos [misubdominio].myddns.me. El selector de dominios parece una lista desplegable, pero en realidad es un cuadro de texto editable, así que podemos ingresar un dominio que no esté vinculado a nuestra cuenta.
Vamos a Cloudflare -> Domains -> [midominio].com -> SSL/TLS -> Custom Hostnames, y activamos "Cloudflare for SaaS".
Configuramos [subdominiocualquiera].[midominio].com como "fallback hostname". Nos aseguramos de que se valide. Por este motivo el subdominio tiene que devolver una respuesta HTTP OK.
En No-IP:
Vamos a DNS Records y configuramos temporalmente nuestro subdominio de No-IP con un registro CNAME apuntando a un servidor web cualquiera que controlemos nosotros. Si solamente tenemos una IP pública (ej: de una VM de GCP), podemos usar un servicio gratuito como nip.io que enruta automáticamente las peticiones a la IP especificada como subdominio (ej: 11.22.33.44.nip.io).
En Cloudflare:
Vamos a Cloudflare -> Domains -> [midominio].com -> SSL/TLS -> Custom Hostnames y agregamos un nombre de host personalizado [misubdominio].myddns.me a nuestro dominio. Esto requiere responder al desafío ACME. Seleccionamos la validación por HTTP.
Validamos el hostname respondiendo el desafío, que es un simple GET HTTP que tiene que devolver una cadena específica que te da Cloudflare. Podemos levantar un servidor web y servir los archivos de texto en la URL /.well-known/acme-challenge/caracteresaleatorios.
En No-IP:
Cambiamos el registro CNAME y lo apuntamos a [subdominiocualquiera].[midominio].com.
¡Listorti!
Resultado
Las peticiones a [misubdominio].myddns.me siguen el CNAME hacia [subdominiocualquiera].[midominio].com. Cloudflare reconoce tanto el origen real (No-IP) como el CNAME como rutas válidas (porque el subdominio de No-IP es un custom hostname del otro dominio), así que reenvía la petición a nuestro túnel. Nuestro servidor recibe una solicitud a subdominio.myddns.me y nuestro proxy Traefik o similar se encarga de enrutarla.
¡Bonus! Cloudflare se encarga del TLS. No hace falta Certbot: el servidor hogareño puede responder HTTP.
Servir múltiples servicios a diferentes subdominios de No-IP
Podemos agregar cualquier cantidad de subdominios de No-IP como custom hostnames de nuestro dominio (hay que responder el desafío ACME por cada uno) y configurarlos con un CNAME apuntando a [subdominiocualquiera].[midominio].com. Nuestro servidor web ve peticiones a los distintos subdominios de No-IP y puede enrutarlos a diferentes servicios según corresponda.
Este sitio corre en una instancia de Google Compute Engine. Todo este tiempo estuve usando shell scripts para subir y bajar archivos con la herramienta de SCP de Google Tools, pero resulta que hay una forma mucho más simple: el firewall de GCP tiene abierto el puerto 22 por defecto, así que se puede entrar por SFTP con FileZilla usando el archivo de clave privada de SSH. Ahora me siento tonto.
Agregué la función de recibir links por e-mail: el usuario puede escribir a [su id]@socialarchivist.online para guardar contenidos.
Para esto creé un email worker de CloudFlare que captura todos los mails que llegan al dominio. Es básicamente una función lambda con acceso al contenido raw del email entrante. Literalmente 20 líneas de código:
Todo lo que parezca extraño, feo, incómodo y desagradable en un nuevo medio de expresión sin duda se convertirá en su identidad. La distorsión del CD, el temblor del video digital, el sonido pobre de 8 bits... Todo esto será celebrado y emulado tan pronto pueda ser evitado. Es el sonido del fracaso: gran parte del arte moderno es el sonido de las cosas saliéndose de control, de un medio llevado hasta sus límites y rompiéndose. La distorsión de la guitarra es el sonido de algo demasiado potente para el medio que debía contenerlo. El cantante de blues con la voz quebrada es el sonido de un grito emocional demasiado poderoso para la garganta que lo libera. La emoción del granulado del film, del blanco y negro lavado, es la emoción de contemplar eventos demasiado trascendentales para el medio asignado para registrarlos.
— Brian Eno, A Year With Swollen Appendices, 1996
Este fragmento de la autobiografía de Eno (productor inglés de música, especialmente electrónica) se viraliza cada pocos meses bajo la consigna de "la teoría de la fealdad".
La idea de belleza en la cultura surge como una celebración de lo que es propicio para la vida humana: los cazadores de las pinturas rupestres, las fértiles curvas de las venus paleolíticas, la robusta simetría de las pirámides. Esa concepción proyecta una enorme sombra sobre el universo, relegando lo asimétrico, lo frágil y lo inútil a la categoría de feo: distante, huérfano, ajeno.
Lo no-nosotros.
Entonces aparece el artista y fija su atención en esa fealdad. No la ignora ni la oculta, sino que la observa con detenimiento, con una mezcla de fascinación y desafío. En lugar de rechazarla, la abraza y la convierte en su materia prima. A partir de ella, crea una obra, que invariablemente genera rechazo y ridículo. Pero en ese acto ocurre un proceso alquímico, ya que incluso a través de la burla, lo que había sido desterrado de nuestra concepción antropocéntrica de la realidad penetra su muralla semántica y pasa formar parte de la cultura.
Pronto el ojo y el oído se acostumbran, y lo que antes nos resultaba ajeno empieza a sentirse familiar. Con el tiempo, cuando el futuro deviene en pasado, lo que fue despreciado pasa a ser objeto de nostalgia. Y finalmente, en un giro irónico, lo que fue feo se vuelve bello.
MilkDrop3 es un programa para Windows que usa el motor de MilkDrop2, el venerable plugin de Winamp, para generar visualizaciones de cualquier cosa que esté sonando en el sistema: YouTube, Spotify o lo que sea. Es compatible con los archivos de visualizaciones de MilkDrop2 y funciona en Windows modernos.
Tengo varios sitios viejos (15+ años) hospedados en GoDaddy usando Cloudflare para habilitar SSL. Hoy estaba haciendo mantenimiento y encontré una catarata de problemas, pero quiero hablar de dos, para cuando Faust del futuro invariablemente se los tope de nuevo.
1) Con HTTPS, veía la página de otra persona
Entro a mi sitio por HTTP: todo perfecto. Entro a mi sitio por HTTPS: veo la web de un actor estadounidense. ¿Finalmente perdí la poca cordura que me quedaba? No: resulta que si un sitio en GoDaddy no tiene configurado un certificado SSL, se vuelve loco y devuelve a Cloudflare otro sitio cualquiera. Por suerte GoDaddy permite crear certificados SSL autofirmados, y eso resuelve el problema.
2) E-mailn't
Mando un mail desde Gmail a uno de mis dominios. No llega. Recibo una autorespuesta:
550 Please turn on SMTP Authentication in your mail client. mail-vk1-f170.google.com [209.85.221.170]:61827 is not permitted to relay through this server without authentication.
Reviso los DNS records: MX, CNAME, SRV. Todo perfecto.
Estuve dos horas googleando para descubrir que a veces AndáPapito decide espontáneamente habilitar el enrutamiento de e-mails para un dominio. ¿Lo hace a propósito? Como sea, cpanel / e-mail routing / direct e-mail, y resuelto.
CarpiScript es un lenguaje de scripting en castellano desarrollado en TypeScript. Incluye analizador léxico, analizador sintáctico e intérprete. Lo armé como experimento para aprender sobre desarrollo de lenguajes de programación y practicar un poco de TS. El próximo paso lógico sería hacer un compilador.
Publicado el 15 de Marzo de 2025 en #tecnología Actualizado el 15 de Marzo de 2026
Esta es mi nueva página web personal. Está desarrollada en FrontPage 2003 (el cenit del diseño web) con PHP (la tecnología backend definitiva) y corre en una instancia e2-micro de Google Compute Engine (cringe). Invitados especiales: Nginx y Certbot. ¡Espero que les guste!
Edit 2026: es exactamente un año después y la instancia e2-micro me quedó corta, así que mudé el sitio a mi laboratorio hogareño detrás de un túnel Cloudflare Zero Trust, y le di una lavada de cara para que se viera peor que antes.
Versión 2025
Versión 2026
¡Firmá el libro de visitas!
Firmas
Code firmó el 18 de Marzo de 2025:
Sitio recontra fachero rey !!!
Uma firmó el 18 de Marzo de 2025:
Que onda locooo!!!1 Todo viento?
Te escribo algo cortito que me queda poco tiempo en el cyber. Pero no quería dejar de pasar.
Alta peli Flow, se acabó muy pronto. Y Engelus un capo, pero bueno tenía que volver a su laburo de mago ya.
Nos vemos en la semana beibi! Un abrazo. :)
Spitter firmó el 16 de Marzo de 2025:
Espero que se pueda leer mi firma uwu
Literatura: Mundodisco, Crónicas de Belgarath, Sandman, Neuromante, 1984, La llamada de Cthulhu Música: Nightwish, Theatre of Tragedy, Rhapsody, SoundTEMP, Gloryhammer Humor: Les Luthiers, Enrique Pinti, Seanbaby, Jason Pargin, Martin Billany Películas: Matrix, The Mist, The Fifth Element, V for Vendetta Anime: Evangelion, Cowboy Bebop, Lain, Full Metal Panic, Dragon Ball, Hunter X Hunter, Madoka, Chuunibyou Tabletop: Dungeons & Dragons, World of Warcraft TCG, Warhammer 40k, Magic: The Gathering Videojuegos: Super Metroid, Super Mario RPG, Mega Man X, Civilization 2, King of Fighters, Starcraft, Diablo 2, Pokémon, Ragnarok Online, Terraria, Vampire Survivors, Hollow Knight
LGR: retroinformática y retrogaming The 8-Bit Guy: para él la retroinformática es simplemente informática Cathode Ray Dude: retroinformática con autismo
Ciencia
Captain Disillusion: mythbuster de SFX y crítica social millennial VSauce: divulgación científica y existencialismo Kurzgesagt: divulgación científica y existencialismo con pájaros HGModernism: sociología, biología y pájaros PBS Idea Channel: análisis de cultura pop (QEPD en paz)
Escritura
Brandon Sanderson: curso de ficción fantasy, tips y podcast Jed Herne: tips para escritores fantasy Bookfox: tips para novelistas Brandon McNulty: tips para novelistas y libretistas Filmento: análisis de libretos de películas