¿Por qué GPL y no otra licencia?

julio 13th, 2025

Desde hace bastante tiempo, todo software que escribo no sea trivial y que quiera compartir online incluyendo el código porque no lo vaya a explotar comercialmente (o incluso algunos que sí pretendo explotar comercialmente pero no de forma tan obvia), lo publico con licencias como GPL, LGPL y AGPL. La principal razón por la que hago esto es para protegerme a mí y a mis proyectos mediante las cláusulas de viralidad que tiene la familia de licencias *GPL.

Cuando publicas software con licencias como BSD o MIT, estás usando las licencias más permisivas que hay para publicar software dentro de lo mainstream, dándole permiso a cualquier persona a construir a partir de lo que has hecho. Sin embargo, con los años ha quedado evidente que quienes más te van a invitar a publicar bajo esta licencia son también las mayores sanguijuelas del mundo, y es de eso precisamente de lo que me trato de defender.

Al publicar bibliotecas o código con alguna de estas licencias, cualquier persona o empresa puede emplear el código que has hecho como base para crear otras cosas, o usarla como dependencia. No existe ningún tipo de fricción más allá de las pocas cosas que pide la licencia: que no uses el nombre del autor y del proyecto original para implicar apoyo (razón por la que Sony es discreta para decir que el sistema operativo de la PlayStation existe gracias a FreeBSD), y que conserves el texto de la licencia original en el producto final en el que lo usas (esta es la razón por la que tantos programas y aplicaciones móviles hoy día tienen un menú que lista todas las dependencias del mismo y sus licencias).

Pantallazo de la web de licencias de Discord, mostrando partes de las licencias de algunas bibliotecas de software.
Discord no enumera todo lo que tiene en su package.json por gusto, sino porque tiene la obligación de hacerlo.

No existen muchas limitaciones con respecto a lo que se puede hacer con ese código al tomarlo prestado. Puedes escribir el código de una biblioteca JavaScript para crear gráficas SVG, y esa biblioteca puede acabar siendo usada en la pantalla de a bordo de un transbordador espacial, o en la versión web de TikTok o de Instagram.

Cuanto más abierto, más ojos

Eric Raymond con el paso de los años ha tenido el honor de enseñarnos que es un hijo de la grandísima puta, pero cuando escribió originalmente La Catedral y el Bazar después de fundar el concepto «código abierto», acertó con bastantes de las ideas originales que tenía en mente, incluso pese a que, con el paso de las décadas, la manera en la que la sociedad ha acabado usando el código abierto no se ha alineado con lo que originalmente propuso.

Una de esas ideas que nació como una cosa pero que ha acabado convertido en otra completamente diferente es la de que cuanto más abierto y visible sea el desarrollo de un código, más ojos habrá para encontrar los defectos.

Como tal, esto sigue siendo cierto si hay voluntad. Una de las cosas que más feliz me hacen cuando estoy programando con bibliotecas ajenas es tener la oportunidad de depurar un bug, ver que la causa está en una biblioteca ajena, arreglar un archivo que no es mío, y luego enviar la corrección al proyecto original. Y en general esto a pequeña escala sigue siendo frecuente, sobre todo, por parte de personas que tengan menos experiencia.

Sin embargo, no todo el mundo es así. No está de más recordar aquella vez que Microsoft publicó un ticket en el tracker de voluntarios de FFmpeg prácticamente diciendo «lo quiero para ayer» porque la biblioteca falla en una función usada por uno de sus productos estrella. (Siendo justos, FFmpeg está publicado con licencia dual GPL+LGPL, no es una licencia permisiva como la que estoy describiendo aquí.)

Cuando fueron pillados por esto, Microsoft ofreció un simbólico pago de una vez de varios miles de euros por el soporte con este bug. Un bug que, insisto, ocurre en Microsoft Teams. Un programa que a día de hoy mueve el mundo con la energía recíproca con la que miles de trabajadores mueven el ratón cada pocos minutos para que Teams no les marque como ausentes.

Tampoco está de más recordar aquella vez que log4j, una dependencia discreta de Java que normalmente está oculta sin hacer ruido en el fondo de una aplicación, saltó a la fama por una vulnerabilidad que afectaba a demasiadas aplicaciones y que podía reproducirse en productos de Microsoft, Apple, Twitter…

log4j prácticamente por entonces se desarrollaba gratis. Las personas que lo mantenían no habían visto apenas compensación por el trabajo que aportaban a la comunidad, ni siquiera por parte de empresas que habían hecho millones gracias en parte a ese trabajo. Por ponerlo en contexto, uno de los programas donde se usaba log4j era Minecraft, cuyo estudio fue comprado años atrás por Microsoft por 2500 millones de dólares.

log4j ha recibido en los últimos años financiación por parte del STA. Al menos 596.000 €. Su situación sin duda, ha mejorado. Pero es la prueba de que existe mucho software integrado en lo más profundo de la industria, que de desaparecer podría devolvernos atrás varios años, pero que sin embargo no obtiene el reconcimiento que se merece hasta que no es demasiado tarde.

log4j durante un tiempo dio mucho que hablar, y hubo gente que se preocupó por la situación económica y el bienestar de la gente que lo crea, pero con el tiempo volvió a olvidarse el tema. Algo parecido a lo que pasó en 2024 cuando se destapó el backdoor de xz.

Why I GPL

Un artículo antiguo que guardo en mis marcadores como enlace a Web Archive porque ha desaparecido de internet es Why I (A/L)GPL (2011), el cual realmente es bastante parecido a este artículo que estoy escribiendo. En él, se cuenta la historia de Mongrel, uno de los primeros servidores HTTP para Ruby. Las primeras versiones de Ruby on Rails lo usaban, hasta que su creador cambió de stack y el proyecto quedó abandonado y reemplazado por otros servidores HTTP.

Uno de los problemas que su creador se encontró fue que, pese a que Mongrel se volvió durante años en el servidor HTTP de referencia para Ruby on Rails, y pese a ser un stack que durante el boom de la web 2.0 de finales de la década de los 2000s y principios de 2010s creó multimillonarios, no sólo nunca obtuvo reconocimiento, sino que recibió cierto desprecio.

I wrote Mongrel and then gave it away, on the hopes that it would help a bunch of other people, and that giving it away would come back to me in some way. Maybe a job, or some respect, or hell maybe my own company doing more software like it.

Mongrel was a wild success, and lots and lots of companies are making lots and lots of money off it. It not only powered Rails, but nearly every Ruby web framework, other Ruby web servers, and was even ported to other languages. Mongrel is and was a super project and I’m really proud of it.

[…] Sadly, none of Mongrel’s success mattered for me. Even though everyone was using my software, the vast majority of firms using Mongrel were startups. The last thing a startup wants to admit is that they don’t own their intellectual property. They want everyone, especially the VCs and investors, to believe that they’re all geniuses who “innovated” everything they run.

[…] Everyone is using it, and at the same time saying I can’t code.

El resto del artículo es una genialidad y esa es la razón por la que lo he enlazado arriba, para que no se olvide nunca, incluso aunque la copia ya solo esté accesible desde el Web Archive.

El caso de SQLite

SQLite es posiblemente la base de datos más usada en todo el planeta. Es lo suficientemente pequeña como para que no sea una aplicación de red, sino que se integre directamente en las tripas del software donde se usa. En otras palabras: no es una base de datos a la que te conectas, sino que es una dependencia que agregas a tu programa y que usas llamando a funciones, como cualquier otra biblioteca dinámica de programación.

SQLite está publicada en dominio público. Su código se puede usar y tomar para cualquier otro producto, abierto o cerrado, y exprimir comercialmente todo lo que se pueda. (Tangencialmente, SQLite también es ese proyecto que se metió en un drama hace varios años porque su código de conducta estaba prácticamente basado en Los 10 mandamientos, e incluso a día de hoy sigue teniendo un código ético cuya primera regla es «amarás a Dios»; sin embargo, no parece haber razón religiosa detrás del hecho por la que es dominio público.)

Que sea tan permisivo y que no tenga ningún tipo de limitaciones en cuanto a su uso y distribución ha atraído en los últimos años a muchas empresas a derivar el código y crear nuevos motores de bases de datos a partir del SQLite original y tratar de comercializarlos como la nueva idea revolucionaria que merece recibir millones de dólares de capital. DuckDB, Deno KV, Tulso… llámalo como quieras.

Lo venden como «La nueva base de datos ultra ligera para la computación moderna». Y luego resulta que lo que han hecho es «SQLite pero te conectas a través de un puerto TCP», que es justo quitar la única ventaja que tiene SQLite frente a cualquier otra base de datos del mercado. Pero pueden hacerlo porque saben que tienen permiso para hacerlo. Y no tienen miedo de, en el camino, intentar despreciar al producto original cuyo código están desguazando para beneficiarse de él, con frases como «mejor que SQLite» o «hora de dejar atrás SQLite».

La viralidad de la GPL como arma

Frente a esto, la familia de licencias GPL tiene una condición muy importante que es la viralidad. Si derivas un código GPL para transformarlo en otra cosa, eso que hagas también tiene que estar publicado bajo la GPL, salvo que ya esté publicado con una licencia compatible. Si copias un fragmento de código GPL en tu programa de internet sin prestar atención, tu programa automáticamente se vuelve GPL o está inclumpliendo la licencia.

Y esta es la razón también por la que prácticamente cualquier gran empresa no quiere saber nada de ninguna biblioteca publicada como GPL. En el momento en el que un programa se enlaza dinámicamente a nivel sistema operativo con una biblioteca GPL, o en el momento que uno de los empleados copia de internet un fragmento de código GPL y lo inserta en lo que está escribiendo, conforman una única unidad, por lo que todo el producto también se vuelve GPL.

Esto es algo que solo afecta a trozos de código copiados sin contexto y a bibliotecas. Usar un programa GPL de forma separada e independiente no va a volver el programa principal GPL. Esa es la razón por la que, por ejemplo, Apple tradicionalmente ha distribuido Bash y otros componentes GPL con su sistema operativo. Mientras estén sueltos y no combinados, no son peligrosos.

Usar una aplicación GPL en tu empresa para depurar la API del servicio HTTP que estás desarrollando no va a volver lo que estás programando como GPL. Sin embargo, algunos abogados y departamentos de informática tienen estrés postraumático y se ven obligados a prohibir cualquier traza de GPL en una empresa.

No quiero perras, sólo quiero un uso justo y honestidad

¿Estoy dando a entender que no publico con licencias permisivas porque quiero dinero? No necesariamente. He compartido estos ejemplos para probar que lo que nació como un movimiento de «creación de software en comunidad de forma abierta» se ha convertido en un método de extracción de esfuerzo donde algunas empresas poderosas, y otras personas no tan poderosas pero sí con un MBA en su pared, se aprovechan de manera sofisticada del trabajo comunitario de otras personas evitando tomar responsabilidad en las acciones que cometen.

Sobre todo cuando se trata de tomar la dependencia escrita por un programador junior y publicada con licencia permisiva e integrarla en productos de software de lo más variados. Quieren la parte positiva del código abierto (ahorrarse costes de desarrollo), sin pensar en la parte negativa (que es que, tal como dicen tanto la licencia BSD como la MIT, que ese código no tiene ninguna garantía y se ofrece tal cual, o sea, AS IS). ¡Dios mío! El código que he tomado de internet no funciona. ¡Que alguien haga algo!

De forma parecida a lo que mencionaba con SQLite, cuando publico software como GPL, lo estoy haciendo para protegerme precisamente de este tipo de casos. No tengo problema en que haya gente que modifique el código y agregue cosas en las que no había pensado. Precisamente por eso comparto el código. Sin embargo, si alguien pretende derivar el software para compartir de forma pública su versión alterada, debe publicar el código fuente para asegurarme de que actúa de forma honesta y justa.

Conclusión

Para código trivial, implementaciones de bibliotecas que ya existen y que son dificiles de superar, o para bibliotecas de 5 líneas con algoritmos que sean fáciles de replicar, no veo problema en publicar código con licencias permisivas.

Sin embargo, para cualquier otra cosa donde el código que estoy compartiendo realmente valga la pena o haga algo único y especial, no veo a día de hoy razón para usar algo que no sea la GPL. De este modo se comparte de forma mucho más justa el código de manera que nadie intente explotar a nadie, solo mejoremos a la vez de forma colectiva.

Actualizada clave GPG (edición 2025) / Updated GPG key

julio 6th, 2025

Mi clave pública GPG caducó en mayo. La renové, pero olvidé cargarla en la web. Lo hago ahora y este es el anuncio. La clave actualizada la puedes descargar desde https://danirod.es/contact/pgp.asc.

Si necesitas la vieja clave por la razón que sea, la dejo cargada aquí: https://danirod.es/contact/pgp-2022.asc. Ten en cuenta que la clave está caduca en cualquier caso. No deberías necesitarla porque es el mismo fingerprint. (Aunque probablemente esta sea la última vez que renueve la clave con el mismo fingerprint, me gustaría eliminar correos que ya no uso y la foto de perfil adjunta, así que seguramente genere una clave nueva la próxima vez que renueve.)


My GPG key expired a few months ago. I updated it, but forgot to upload it to my website. I’m doing now and this is the public announcement. The updated GPG key can be downloaded from https://danirod.es/contact/pgp.asc. It has the same fingerprint as the 2022 one.

If you need the old key for any reason, you shall find it here: https://danirod.es/contact/pgp-2022.asc. Just keep in mind that this key is expired anyway. You shouldn’t need it anyway because it’s the same fingerprint. (However, this will probably be the last time I update the expiration date, I’d like to remove emails that I don’t use anymore and remove the attached profile picture, so the next time I’ll make a new key).

Mi investigación sobre cómo se programa un feed de Bluesky

noviembre 28th, 2024

Esto no es un sustituto para la «maravillosa» experiencia que resulta de leer la documentación oficial de ATProto y Bluesky, solamente quiero dejar anotado lo que he aprendido para poder revisarlo en el futuro


¿Cómo sabe Bluesky cuál es el algoritmo que proporciona la inteligencia de un feed?

Bueno, la respuesta parece ser que un feed de Bluesky no es más que un servicio HTTP con el que Bluesky interactúa usando la API RPC con los endpoints definidos en el protocolo ATProto.

Entonces, «crear» un feed es exponer a través de un servicio web esos endpoints y prepararlos para que Bluesky pueda lanzarle peticiones cuando una persona consulta el feed.


¿Y cómo sabe Bluesky cuál es el servicio web que debe usar?

Cuando «creas» un feed, es decir, cuando lo haces público para que salga en tu perfil y para que «exista» para Bluesky, hay que darle un parámetro que codifica el hostname. De modo que cuando alguien intenta consultar tu feed, Bluesky usa el hostname para saber a qué servidor hacer las peticiones HTTP que devuelven los datos del feed y así «usar tu algoritmo».

Ejemplo: el feed Linux está creado por @mackuba.eu. El DID de esta cuenta es did:plc:oio4hkxaop4ao4wz2pp3f4cr. Si uso el endpoint RPC com.atproto.repo.listRecords para pedirle todos los app.bsky.feed.generator creados por esta cuenta, el array JSON incluye el feed Linux.

Petición RPC al endpoint com.atproto.repo.listRecords en el PDS bsky.social
https://bsky.social/xrpc/com.atproto.repo.listRecords?repo=did:plc:oio4hkxaop4ao4wz2pp3f4cr&collection=app.bsky.feed.generator

El campo did de este record tiene como valor did:web:blue.mackuba.eu. Eso significa que el feed está asociado con el hostname blue.mackuba.eu y que cuando quieras consultar el feed Linux, Bluesky le tiene que tirar las peticiones a https://blue.mackuba.eu.

La API de un feed

Leyendo la documentación del generador que he consultado, un servicio web que sirva feeds de Bluesky debe implementar tres métodos:

  • /.well-known/did.json: este tiene que validar que, efectivamente, ese servicio web es el correcto, para evitar impersonaciones.
  • /xrpc/app.bsky.feed.describeFeedGenerator: este es el que devuelve información de los feeds que se sirven desde ese servicio.
  • /xrpc/app.bsky.feed.getFeedSkeleton: este es el que devuelve el contenido del feed, para que los posts se puedan ver. Va paginado.

ericvolp12/go-bsky-feed-generator es un generador de feeds hecho por @jaz.bsky.social que está programado en Go. De aquí es de donde he sacado esta información. Todavía no lo he clonado para ver si es tan sencillo como tomar la plantilla, programar los algoritmos, y dejar que el proyecto levante el servidor web.

did.json

El endpoint de DID parece confirmar que estamos en la ubicación correcta. Imagino que validar el feed quiere decir verificar que no estás usando otro hostname diferente o que alguien se ha equivocado al poner la URL del servidor. No tengo ni idea del contexto de este endpoint.

Petición al endpoint did.json de blue.mackuba.eu.
https://blue.mackuba.eu/.well-known/did.json

app.bsky.feed.describeFeedGenerator

El endpoint app.bsky.feed.describeFeedGenerator devuelve la lista de feeds servidos desde ese servicio web. La documentación con los tipos del objeto devuelto están en la API de Bluesky.

Petición RPC al endpoint app.bsky.feed.describeFeedGenerator de blue.mackuba.eu.
https://blue.mackuba.eu/xrpc/app.bsky.feed.describeFeedGenerator

app.bsky.feed.getFeedSkeleton

El endpoint app.bsky.feed.getFeedSkeleton es el que devuelve los datos de un feed. Si le pido sin más que me hable, da un error HTTP 500, aunque supongo que esto depende del servidor.

Petición RPC al endpoint app.bsky.feed.getFeedSkeleton de blue.mackuba.eu.
https://blue.mackuba.eu/xrpc/app.bsky.feed.getFeedSkeleton

Eso es porque según la documentación de ese endpoint, le tengo que poner como queryparam feed para indicarle el record del feed que quiero que me devuelva. El feed tiene que estar en formato URL de protocolo ATProto, es decir, at://[did]/app.bsky.feed.generator/[slug], que para el feed «Linux» es at://did:plc:oio4hkxaop4ao4wz2pp3f4cr/app.bsky.feed.generator/linux, siendo el DID de la cuenta de mackuba. En cuanto hago eso, el feed empieza a hablar.

Petición RPC al endpoint app.bsky.feed.getFeedSkeleton de blue.mackuba.eu con un feed como parámetro.
https://blue.mackuba.eu/xrpc/app.bsky.feed.getFeedSkeleton?feed=at://did:plc:oio4hkxaop4ao4wz2pp3f4cr/app.bsky.feed.generator/linux

El formato de un feed tiene el siguiente tipo (voy a usar una interfaz de TypeScript por simplicidad):

interface Feed {
  cursor: string;
  feed: Array<{
    post: string;
  }>;
}

Uno de los campos de retorno es cursor, que es el que permite paginar el feed. Es un paginador un poco complejo porque como el feed se puede actualizar en tiempo real a medida que se va paginando si se agregan o se borran posts, se recomienda que lleve también un timestamp para asegurarse que se sincroniza bien.

El otro es feed, que devuelve un array de objetos con los IDs de cada post. El feed no porta el contenido de los posts, solamente sus IDs externos. Tú devuelves la URL en protocolo ATProto de un post, y ya se ocupa Bluesky de recuperar por separado el contenido de cada post a partir de la propia API del PDS.

Voy a hacer la prueba tratando de resolver desde el PDS https://bsky.social uno de los posts del feed, en este caso, at://did:plc:gxt7mot2ujgovitv6j4eo7n4/app.bsky.feed.post/3lbyn6inlds22. Puedo sacarlo mediante el endpoint RPC app.bsky.feed.getPosts. Como este endpoint requiere autenticación, voy a usar https://public.api.bsky.app, que permite acceso anónimo, para no tener que aprender ahora a crear tokens.

Petición RPC a app.bsky.feed.getPosts para este endpoint y este PDS.
https://public.api.bsky.app/xrpc/app.bsky.feed.getPosts?uris=at://did:plc:gxt7mot2ujgovitv6j4eo7n4/app.bsky.feed.post/3lbyn6inlds22

Estrategias para fabricar un algoritmo

Si quiero programar un feed estático, puedo devolver hardcodeado el array con las URLs ATProto de los posts que quiero que porte. Sin embargo, imagino que la gracia está en prestar atención a JetStream o al firehose de Bluesky directamente, que es el websocket que te trae en tiempo real los posts a medida que se publican. Para mirar a la cara a este websocket sin usar comandos de consola se pueden usar las siguientes herramientas web:

Cuando encuentre un post en el websocket que concuerde con el criterio de mi algoritmo, puedo anotar su ID para poder devolverlo más adelante cuando se pidan datos del feed. Se recomienda también descartar los posts más antiguos para no devolver un feed muy grande.

Siguientes puntos

La siguiente pregunta que me queda por hacer es cómo funciona la autenticación, porque algunos feeds son anónimos ya que solo tienen que devolver datos del firehose público. Sin embargo, si quiero filtrar para que muestre información relacionada con mi cuenta (por ejemplo, posts de la gente que sigo o posts de la gente que me sigue), supongo que el feed necesita una forma de saber quién soy. Esto es algo que dejo para investigar otro día.

Mastodon me tumba el blog

octubre 28th, 2024

Mastodon puede causar un DDoS, pero no lo hace con mala intención.

He vuelto a cometer el error de publicar una entrada de blog usando una etiqueta demasiado genérica. Al minuto de hacer eso, mi blog ha empezado a fallar, y el access.log se ha llenado de tráfico procedente de instancias de Mastodon.

NGINX recibiendo un DDoS de Mastodon
Read the rest of this entry »

Impresiones rápidas sobre TikTok, ahora en primera persona

octubre 28th, 2024

Normalmente he criticado y despreciado a TikTok en tercera persona, únicamente en base a lo que he leído por ahí. Sin embargo, hace poco abrí una cuenta para makigas, donde estoy dándole una segunda vida a los shorts que cargo en YouTube una vez que empiezan a decaer, o para intentar crear imagen de marca más allá a ver si cae algún suscriptor nuevo.

En cualquier caso, en estas semanas he podido fijarme en cómo funciona en primera persona, usándola yo mismo, y estas son mis impresiones de lo que he visto hasta el momento.

Read the rest of this entry »

Modelos experimentales de microblog

octubre 25th, 2024

Últimamente le ando dando vueltas a la idea de si la forma en la que se mantienen los blogs de notas es la óptima. Me refiero a cuando publicas en tu blog o en tu propia web un mensaje de texto corto y plano que cabría perfectamente en un tweet, pero que publicas en tu blog para poseer el control de él y no regalárselo a un multimillonario cabrón. (También me vale en un post de Mastodon o en un skeet de Bluesky).

Read the rest of this entry »

10-10-2024

octubre 10th, 2024

Me cuesta hacer que el contraste del tema que uso en mi blog se vea bien en modo oscuro.

El problema es que los temas de WordPress twenty-pico modernos ya pasan del soporte para microformatos y yo preferiría mantener esa función para poner cosas cortas.

La caída de Discord

octubre 7th, 2024

Por alguna razón estoy diciendo esto en todas partes menos en mi propia guild de Discord. Ahí dentro la gente es feliz e inocente sin saber que básicamente a finales de agosto decidí dejar de darle recursos al servidor y dejar de preocuparme por su falta de uso. Está clasificado como obsoleto, y aunque no lo voy a borrar, no me voy a preocupar ya tanto de si faltan canales, o si la gente lo está descubriendo bien.

En los últimos dos años, la interacción en el servidor de Discord de makigas había caído completamente. De ser una plaza de pueblo activa donde la gente hacía preguntas, o compartía cosas de su día, a ser un lugar vacío donde muy de vez en cuando alguien pregunta algo y donde cada vez se comparten menos cosas. Evidentemente, no puedo forzar a la gente a utilizarlo, pero sí puedo al menos entender las razones por las que ha caído en popularidad.

Read the rest of this entry »

Por qué no uso IA para la mayor parte del proceso de producción de makigas.es

septiembre 30th, 2024

Sé que este post no va a contentar a los tech-bros, pero me permite desahogarme. Además, es un buen punto al que poder citar en el futuro si surge esta pregunta y no tengo ganas de repetirme.

Sería técnicamente incorrecto decir que no uso IA en mi canal de YouTube y en makigas.es, ya que hay al menos dos instancias en las que uso IA. Por eso este post está dividido en dos partes. Primero diré las partes en las que utilizo IA en makigas.es, y las partes en las que no me planteo usar IA a pesar de que sé que son las más tediosas y las que más tiempo me toman.

Read the rest of this entry »

El widget de cabeceras HTTP por fin está hecho

abril 10th, 2024

Como dicen que una imagen vale más que mil palabras, os quiero enseñar una cosa.

Efectivamente, el widget de cabeceras HTTP por fin está programado, lo que significa que por fin se puede completar toda la información necesaria para tirar una petición HTTP mínima con Cartero. Dejad que os cuente cómo funciona por dentro.

Read the rest of this entry »