Construí un foro sin interfaz, sin contraseñas y para la terminal
Me gustan los foros. Debates, preguntas, respuestas, opiniones, etc. Esa sensación de comunidad asíncrona, donde las respuestas se meditan y el contenido perdura, que hace de internet un lugar interesante. Por ello me gusta leerlos y participar en ellos, pero nunca he diseñado ni construido uno. En mi tiempo libre empecé a abocetar uno y acabé construyendo mi humilde foro headless federado, con tecnologías simples, modernas y estándares abiertos.
Y por el camino aprendí mucho. Un foro parece sencillo, pero esconde los problemas clásicos de cualquier servidor. ¿Quién puede hacer qué? ¿Cómo separas a un moderador de un usuario normal? ¿Qué pasa cuando hay que banear a alguien? ¿Cómo evitas que te roben una cuenta? Roles, permisos, baneos y seguridad. Tuve que resolverlos uno a uno, y eso no se aprende leyendo.
Vengo a contarte cómo hice Tyrtulia.
Un foro sin interfaz
El servidor solo ofrece una API sólida y documentada. Es REST con hipermedia: el cliente solo conoce una ruta, GET /, y todo lo demás lo descubre siguiendo enlaces. Por debajo hay estándares muy aburridos:
- RFC 9110: semántica HTTP, con
ETageIf-Matchpara no pisar ediciones. - RFC 9457: errores.
- RFC 7396: actualizaciones parciales con
PATCH. - RFC 6570: plantillas de URL.
- RFC 4287: feeds Atom.
- RFC 9562: identificadores UUIDv7.
- JSON Schema: validación.
- Server-Sent Events: eventos en tiempo real.
No hay interfaz web, ni formularios, ni sistemas avanzados de autenticación, ni gestión de archivos (imágenes, adjuntos, etc.), ni nada que no sea estrictamente necesario para leer y escribir mensajes.
Por eso es muy ligero. Ocupa entre 60 y 70 MB de RAM y unos 50 MB de disco. Solo necesita Python y SQLite para funcionar.
Una API que se descubre sola
¿Cómo sabe un cliente qué puede hacer? Se lo dice el servidor con enlaces. Fíjate en la misma petición, GET /, hecha por un invitado (simplificada):
{
"name": "Forum of example.org",
"_links": {
"self": {"href": "/", "method": "GET"},
"latest": {"href": "/threads", "method": "GET"},
"search": {"href": "/search{?q,author,in}", "method": "GET", "templated": true},
"login": {"href": "/sessions", "method": "POST", "schema": "/schemas/session"}
}
}
Y ahora por alice, con sesión iniciada:
{
"name": "Forum of example.org",
"_links": {
"self": {"href": "/", "method": "GET"},
"latest": {"href": "/threads", "method": "GET"},
"search": {"href": "/search{?q,author,in}", "method": "GET", "templated": true},
"createThread": {"href": "/threads", "method": "POST", "schema": "/schemas/thread"},
"notifications": {"href": "/notifications", "method": "GET"},
"events": {"href": "/events", "method": "GET", "type": "text/event-stream"}
}
}
Si mañana cambio una ruta, ningún cliente se rompe, porque ninguno la conocía de antemano. Solo tiene que seguir los enlaces que le da el servidor.
¿Y por qué no usar uno que ya existe?
Soy consciente de que hay foros de software libre muy completos:
- Discourse: el más popular hoy en día.
- Flarum: en PHP con MySQL.
- NodeBB: en Node.js, con MongoDB, Redis o PostgreSQL. Destaca por el tiempo real con WebSockets.
O el clásico de toda la vida: phpBB.
Todos son fantásticos, pero están diseñados para usarse desde un navegador web. Además, tienen un enfoque ambicioso, ideal para comunidades grandes, pero excesivo para un foro pequeño y ligero.
Eso sí, Tyrtulia no renuncia al navegador: se puede indexar en buscadores y cualquiera puede leerlo desde la web.
Sin contraseñas
Ni OAuth, ni OpenID, ni formularios de registro. La autenticación se hace de dos formas:
- Tu usuario Unix: el cliente habla con el foro por un socket Unix. El sistema operativo le dice al foro qué usuario está al otro lado. No hay que registrarse ni iniciar sesión. Tu usuario es tu cuenta.
- Clave SSH: el cliente se conecta por HTTP y el foro le envía un reto. El cliente lo firma con tu clave privada SSH y el foro lo verifica con tu clave pública.
No hay registro por HTTP. Si tienes usuario Unix en el servidor, ya tienes cuenta: se crea sola la primera vez que conectas por el socket. Desde ahí puedes añadir tus claves SSH para entrar desde fuera. Si no tienes usuario en la máquina, el administrador te crea una cuenta con tu clave pública desde la línea de comandos. En un tilde, tener usuario Unix ya es la invitación.
Fácil de usar, seguro y sin contraseñas que robar.
Qué cambia respecto a BBJ
La idea no es mía. Me inspiré en BBJ, un tablón de anuncios para la terminal pensado para comunidades pequeñas o clubes (tildes, pubnixes, servidores de clubes, etc.). Cogí su espíritu y lo llevé a mi terreno. Sin embargo, hay diferencias importantes.
Primero, los cimientos.
| BBJ | Tyrtulia | |
|---|---|---|
| Estilo de API | RPC: todo es POST /api/<endpoint> |
REST con hipermedia (HAL): solo se conoce GET / |
| Permisos | El cliente pregunta (is_admin, edit_query) |
Enlaces que aparecen o desaparecen |
| Autenticación | Hash SHA-256 sin sal de la contraseña en cada petición | Sin contraseñas: socket Unix o reto firmado con SSH |
| Errores | 6 códigos numéricos propios | RFC 9457 con un catálogo de tipos |
| Paginación | Todo de golpe | Por cursor |
| Concurrencia | La última edición gana, sin avisar | ETag e If-Match |
| Formato del texto | Lenguaje propio ([bold: ...], [red: ...]) |
Markdown estándar |
| Validación | Un endpoint db_validate |
JSON Schema enlazado desde cada formulario |
| Configuración | config.json |
TOML |
Después, las funcionalidades que echaba de menos.
| BBJ | Tyrtulia | |
|---|---|---|
| Responder a un mensaje concreto | Citas >>N dentro del texto |
Respuestas enlazadas, con vista en árbol |
| Menciones | No | Sí |
| Notificaciones | No (pendiente desde 2017) | Bandeja con respuestas, menciones y avisos |
| Tiempo real | No, hay que preguntar cada poco | Server-Sent Events, con reanudación |
| Historial de ediciones | No, editar sobrescribe | Completo, con diferencias y revertir |
| Borrado | Elimina la fila | Lápida: la numeración se conserva |
| Búsqueda | Cada cliente busca en lo que ha descargado | Texto completo en el servidor, sin importar tildes ni mayúsculas |
| Feeds | No | Atom del foro y de cada hilo |
| Moderación | Admin o no | Roles, mensajes ocultos, reportes y registro público |
| Límite de peticiones | No | Por usuario y por IP |
En común tienen un servidor pequeño sobre SQLite y varios clientes de texto contra una API documentada.
Clientes
En un foro headless sí o sí necesitas clientes.
Tyrtulia TUI
Tyrtulia TUI es el cliente para la terminal, hecho con Textual.
:quality(85)/https://andros.dev/media/blog/2026/10/tyrtulia-tui-thread.png)
tyrtulia.el
Si me conoces un poco, sabrás que este paquete era obligatorio: tyrtulia.el.
:quality(85)/https://andros.dev/media/blog/2026/10/tyrtulia-el-thread.png)
Tyrtulia Web
Tyrtulia Web es más un espejo del contenido que un cliente. Su objetivo es indexar el foro para buscadores y permitir leerlo desde cualquier navegador.
:quality(85)/https://andros.dev/media/blog/2026/10/tyrtulia-web-thread.png)
Tiene un tema sin estilos y otro que imita mi web.
Federación
Puedes conectarte a un foro o configurar varios. La federación ocurre en los clientes: los servidores no se hablan entre sí ni copian mensajes de unos a otros. Cada foro es independiente, con sus usuarios, sus normas y sus moderadores.
En lugar de separarlos en pestañas o cuentas, los clientes mezclan los hilos de todos en una sola lista.
:quality(85)/https://andros.dev/media/blog/2026/10/tyrtulia-el-forums.png)
Eso sí, solo puedes escribir en los foros donde tengas cuenta. En el resto solo puedes leer.
Me parece una característica bastante chula, porque simplifica mucho el código de la API y te permite explorar otros foros con coste cero.
Pruébalo
Ha sido divertido diseñarlo e implementarlo. Por supuesto que hay foros más completos, sistemas de federación más potentes e incluso sistemas descentralizados que dejan Tyrtulia en pañales (Aether, Nostr...), pero su nicho es muy concreto: un foro ligero, de acceso cerrado, federado, indexable, seguro y con clientes de texto. Para todo lo demás, ya hay cosas mejores.
Si te animas a probarlo, tienes la guía de instalación en el repositorio de Tyrtulia.
Espero tu feedback.
- Un foro sin interfaz
- Una API que se descubre sola
- ¿Y por qué no usar uno que ya existe?
- Sin contraseñas
- Qué cambia respecto a BBJ
- Clientes
- Tyrtulia TUI
- tyrtulia.el
- Tyrtulia Web
- Federación
- Pruébalo
Este trabajo está bajo una licencia Attribution-NonCommercial-NoDerivatives 4.0 International.
Ayúdame a seguir escribiendo
Cada café me da un empujón para escribir el siguiente artículo.
¡Claro, te invito!
Comentarios
Todavía no hay ningún comentario.