Identidad, acceso y seguridad
Donde se decide quién entra, cómo y con qué dolor.
- Authentik
- Actualizar el fondo de todos los flows en Authentik (vía SQL)
- Cloudflare Turnstile en Authentik - Captcha previo a la autenticación
- Creación de aplicaciones, providers y outposts en Authentik
- Directiva de Authentik para Caddy
- Evitar MFA en casa con Authentik
- Forzar MFA en todos los usuarios de Authentik
- Login sin contraseña en Authentik usando WebAuthn
- Gitea
- Añadir una llave física en Gitea
- Personalización de Gitea: Temas y otros ajustes
- YubiKey en Gitea: Error al registrar llave
- RustDesk
- Wazuh
Authentik
Parcheando lo que Authentik no explica hasta que ya estás logueado fuera y cagándote en todo.
Actualizar el fondo de todos los flows en Authentik (vía SQL)
Cambiar los fondos de todos los flows de Authentik (pantalla de login, registro, recuperación de contraseña, etc.) desde la interfaz puede ser lento y tedioso si se hace uno a uno. Para evitar ese paseo clic por clic, lo más práctico es lanzar una consulta SQL que los actualice todos de golpe.
Características
- Cambia el fondo de todos los flows de Authentik de una sola vez.
- No hace falta reiniciar contenedores ni hacer magia negra.
- Ideal para dejarlo bonito con una sola línea SQL.
Paso a paso
1. Entra en el contenedor de la base de datos
Asumiendo que usas Docker, el primer paso es meterse dentro del contenedor de PostgreSQL:
docker exec -it <nombre_del_contenedor_postgres> bash
Sustituye <nombre_del_contenedor_postgres> por el nombre real de tu contenedor. Si usas docker ps, lo verás fácil.
2. Conéctate a PostgreSQL
Normalmente, el usuario y la base de datos se llaman igual: authentik. Si no has tocado nada raro, este comando debería bastar:
psql -U authentik -d authentik
Cuando te lo pida, mete la contraseña. Es la misma que tienes en el .env, bajo PG_PASS.
3. Cambia los fondos de todos los flows
Aquí viene la línea mágica:
UPDATE authentik_flows_flow SET background = 'https://w.wallhaven.cc/full/2y/wallhaven-2yp6gg.png';
Obviamente, puedes poner cualquier URL de imagen que te guste. Yo suelo usar Wallhaven, clic derecho en la imagen y “copiar enlace”.
4. Sal de la base de datos
Cuando termines, escribe:
\q
Y luego exit para salir del contenedor.
5. Prueba si ha funcionado
Abre una ventana en modo incógnito (para evitar cacheos raros) y accede a tu pantalla de login. Si todo ha ido bien, el cambio es instantáneo. No hace falta reiniciar nada.
Conclusión
Así de fácil es dejar tu Authentik con estilo. Este truco no está en la documentación oficial, pero funciona perfecto si sabes por dónde meterle mano. Y si un día te aburres del fondo… repite el proceso con otra URL.
Referencias
Cloudflare Turnstile en Authentik - Captcha previo a la autenticación
Introducción
Este artículo documenta la integración de Cloudflare Turnstile como etapa de captcha previa al proceso de autenticación en Authentik, con el objetivo de filtrar tráfico automatizado antes incluso de mostrar el formulario de login.
La integración se sitúa directamente dentro del authentication flow de Authentik, actuando como una barrera inicial que reduce ruido, ataques de fuerza bruta y automatización maliciosa sin introducir fricción innecesaria para usuarios legítimos. No sustituye otros mecanismos (MFA, rate‑limit, CrowdSec), sino que los refuerza desde el primer punto de entrada.
Enfoque general / Arquitectura
El enfoque se basa en insertar una Captcha Stage como primera etapa del default-authentication-flow:
Cliente → Captcha (Cloudflare Turnstile) → Formulario de login → MFA / resto de etapas
Características clave del enfoque:
- El captcha se presenta antes de solicitar credenciales.
- No se depende de puntuaciones de riesgo (Turnstile no las expone).
- Compatible con modos Managed e Invisible.
- Integración nativa en Authentik, sin proxies intermedios ni JS personalizado.
Este planteamiento reduce carga en Authentik y en servicios posteriores, descartando tráfico basura desde el primer renderizado de la página.
Requisitos previos
- Instancia funcional de Authentik con acceso al Admin Interface.
- Dominio gestionado en Cloudflare.
- Acceso a la sección Turnstile en Cloudflare.
- Flujo de autenticación estándar (
default-authentication-flow) sin modificaciones incompatibles.
Desarrollo
Qué se hizo y por qué
Se opta por Cloudflare Turnstile frente a reCAPTCHA por varios motivos:
- No requiere interacción explícita en la mayoría de escenarios.
- No depende de tracking invasivo ni cookies de terceros.
- Integración directa soportada por Authentik.
- Menor fricción para usuarios humanos reales.
La decisión de colocarlo antes del login es deliberada: cualquier captcha posterior ya implica haber servido HTML sensible (formularios, endpoints, lógica de sesión).
Configuración utilizada (solo enlaces)
-
Documentación oficial de Turnstile: Widgets Turnstile
-
Widget Turnstile (Cloudflare Dashboard): Creación del widget desde el dominio correspondiente para obtener:
- Site Key
- Secret Key
Configuración en Authentik (conceptual)
-
Crear una Captcha Stage desde: Admin → Flows and Stages → Stages → Create → Captcha Stage
-
Parámetros relevantes de la etapa:
- Public Key → Turnstile Site Key
- Private Key → Turnstile Secret Key
- Enable Interactive → Activado si el widget está en modo Managed o Invisible
- JS URL
https://challenges.cloudflare.com/turnstile/v0/api.js - API URL
https://challenges.cloudflare.com/turnstile/v0/siteverify
Las opciones de score se dejan por defecto, ya que no aplican a Turnstile.
-
Inserción en el flujo: Admin → Flows and Stages → Flows →
default-authentication-flowEn Stage Bindings:
- Añadir la Captcha Stage.
- Asignarle el orden más bajo del flujo para que se ejecute antes que cualquier otra etapa.
Validación
Comprobaciones mínimas tras la integración:
-
Acceso al endpoint de login:
- El captcha aparece antes del formulario.
-
Tráfico humano normal:
- No se presentan desafíos visibles en la mayoría de casos.
-
Bots y escáneres:
- No alcanzan el formulario de autenticación.
-
Logs de Authentik:
- Sin errores de validación contra la API de Cloudflare.
-
Dashboard de Cloudflare:
- Métricas de Turnstile registrando solicitudes correctamente.
Decisiones importantes o problemas detectados
- Turnstile no soporta puntuaciones, por lo que cualquier lógica basada en umbrales debe descartarse.
- El orden de la etapa es crítico: si no es la primera, pierde sentido.
- No interfiere con MFA ni con autenticación por WebAuthn: actúa antes de todo.
Resumen breve
- Captcha basado en Cloudflare Turnstile.
- Integrado como primera etapa del
default-authentication-flow. - Filtrado de bots antes del login.
- Sin fricción visible para usuarios legítimos.
- Implementación nativa, limpia y mantenible.
Referencias
Creación de aplicaciones, providers y outposts en Authentik
Introducción
Authentik es una plataforma open source pensada para gestionar la autenticación y los accesos de usuarios en sistemas multiusuario, ya sea en entornos personales, empresariales o mixtos. Su enfoque modular y flexible permite centralizar la seguridad y el control de quién entra, cuándo y a qué aplicaciones. En esta guía, vamos a ver cómo crear una aplicación dentro de Authentik, configurarle su provider correspondiente y enlazarla con un outpost para dejarla operativa. Todo explicado paso a paso y sin rodeos.
Crear aplicación + provider con el asistente
-
Accede al panel de administración de Authentik.
-
En la sección lateral, ve a Applications.
-
Si tienes una versión reciente, verás este mensaje:
You can now configure both an application and its authentication provider at the same time with our new Application Wizard.
-
Pulsa en Create with wizard. Este asistente te permitirá crear la aplicación y su provider en una misma secuencia, ahorrándote tiempo y errores.
Paso 1: Configurar la aplicación
- En el campo Name, escribe un nombre claro para tu aplicación, por ejemplo:
test. - El slug se autocompleta con base en el nombre, pero puedes editarlo si lo necesitas.
- En UI Settings, rellena el campo Launch URL con la dirección pública de la app, como
https://test.dominio.es. - Pulsa Next para continuar.
Paso 2: Elegir el tipo de provider
- Selecciona Proxy provider como método de autenticación.
- Este tipo es el más habitual para forward authentication con proxies como Caddy o Traefik.
- Pulsa Next.
Paso 3: Configurar el provider
Paso 4: Asignar permisos de acceso
- Aquí puedes definir quién puede acceder a la aplicación. Pulsa Bind existing policy/group/user.
- Selecciona Group y luego escoge el grupo que quieras permitir. Por ejemplo:
authentik Admins. - Puedes añadir más grupos o usuarios si lo necesitas más adelante.
- Pulsa Save o Next para continuar.
Paso 5: Finalizar creación
- Revisa que todo esté correcto y pulsa Submit.
- Con esto, tanto la aplicación como su provider quedarán listos y configurados.
Asociar la app a un outpost
Ahora toca vincular la aplicación a un outpost, que es el componente de Authentik encargado de hacer de "puente" entre las apps y el sistema de autenticación.
- Desde el menú lateral, entra en Outposts.
- Verás uno ya creado por defecto llamado authentik Embedded Outpost. Haz clic en el lápiz para editarlo.
- Asegúrate de que el Type esté en
Proxy, que es el necesario para apps con forward authentication. - Baja a la sección Applications. Allí verás dos columnas: una con aplicaciones disponibles y otra con asignadas.
- Busca tu app (
test) en la lista de disponibles y haz doble clic sobre ella para moverla a la columna de asignadas. - Pulsa Update para guardar todos los cambios.
Conclusión
¡Ya está! Acabas de crear y configurar tu primera aplicación en Authentik, junto con su provider correspondiente y asignación al outpost. Esto te da control centralizado sobre qué usuarios pueden acceder, desde qué grupos y con qué reglas. Si en el futuro necesitas añadir más aplicaciones, usuarios o personalizar políticas, ya conoces la base para moverte con soltura por Authentik. Todo desde una única interfaz, sin complicaciones y con una arquitectura limpia.
Directiva de Authentik para Caddy
Si estás utilizando Authentik como solución de autenticación y quieres integrarlo en tu configuración de Caddy, puedes usar la siguiente directiva lista para funcionar (o al menos, funcional en mi caso):
# Directiva de Authentik (mostrando la IP real del cliente, por si usas Cloudflare o similar)
(authentik) {
reverse_proxy /outpost.goauthentik.io/* http://192.168.1.90:19000
forward_auth http://192.168.1.90:19000 {
uri /outpost.goauthentik.io/auth/caddy
copy_headers X-Authentik-Username X-Authentik-Email X-Authentik-Groups X-Authentik-Name X-Authentik-Uid
header_up X-Real-IP {client_ip}
header_up X-Client-IP {client_ip}
}
}
Personalización de la configuración
Para adaptar esta directiva a tu entorno, sustituye:
192.168.1.90por la IP de tu servidor donde se ejecuta Authentik.19000por el puerto que hayas configurado.
Si has desplegado Authentik mediante Docker, asegúrate de que el puerto configurado en docker-compose.yml coincide con el utilizado en esta directiva. Puedes encontrar o definir este puerto en el archivo .env que se usa al desplegar Authentik:
AUTHENTIK_PORT_HTTP=19000
Importando la directiva en Caddy
Una vez configurada la directiva de Authentik, solo queda importarla dentro de la configuración de Caddy para proteger las aplicaciones deseadas. Un ejemplo práctico para una biblioteca digital con Calibre sería:
# Biblioteca Digital
calibre.example.com {
reverse_proxy http://192.168.1.90:20980
import authentik
}
Notas finales
- Asegúrate de que las aplicaciones en Authentik están correctamente configuradas antes de importar la directiva.
- Si estás usando Docker, revisa que los contenedores estén corriendo y que los puertos sean accesibles.
- Caddy debe ser reiniciado o recargado (
caddy reload) después de cualquier cambio en la configuración.
Con esto, Authentik debería empezar a proteger las aplicaciones configuradas en Caddy de manera efectiva.
Evitar MFA en casa con Authentik
Introducción
Evitar que Authentik pida el segundo factor en casa, donde es una molestia constante. Se aplica solo bajo una IP fija, y sin comprometer la seguridad externa.
Características
- Login sin MFA desde casa (o IP elegida).
- Flujo normal para el resto del mundo.
- Compatible con Cloudflare como proxy.
- Logs limpios con IP y usuario reales.
- Reversible en segundos.
Requisitos previos
- IP pública fija o semiestable (por rango).
- Caddy como reverse proxy.
- Outpost de Authentik funcionando.
- Dominio configurado en Cloudflare con API activa.
Flujo general
Navegador ─▶ Cloudflare ─▶ Caddy ─▶ Authentik Outpost ─▶ App
▲ IP real via X-Forwarded-For ▲
└─────────────────────────────────┘
- Caddy extrae la IP real con
{client_ip}y la pasa como cabecera. - Authentik la lee en
ak_client_ipy salta el MFA si coincide con la IP marcada.
Caddyfile adaptado
Importante: este ejemplo solo aplica a aplicaciones que estén protegidas por Authentik. Si una app no utiliza Authentik como sistema de autenticación, este snippet no tendrá efecto sobre ella.
Antes de modificar nada, se recomienda hacer una copia de seguridad de tu
Caddyfileactual. Por la naturaleza de los cambios (cabeceras, autenticación, DNS...), un error puede dejarte sin acceso a tus servicios.
Antes de modificar nada, se recomienda hacer una copia de seguridad de tu
Caddyfileactual. Por la naturaleza de los cambios (cabeceras, autenticación, DNS...), un error puede dejarte sin acceso a tus servicios.
Ejemplo con datos falsos para documentar el flujo.
{
email ejemplo@dominio.com
acme_dns cloudflare "API_KEY_FAKE123"
servers {
trusted_proxies static private_ranges \
203.0.113.0/24 198.51.100.0/24 192.0.2.0/24
}
}
(authentik) {
reverse_proxy /outpost.goauthentik.io/* http://10.0.0.3:15500
forward_auth http://10.0.0.3:15500 {
uri /outpost.goauthentik.io/auth/caddy
copy_headers {
X-Authentik-Username
X-Authentik-Email
X-Authentik-Groups
X-Authentik-Name
X-Authentik-Uid
}
header_up X-Real-IP {client_ip}
header_up X-Client-IP {client_ip}
}
}
# Cada app que requiera autenticación debe seguir este mismo patrón.
# Primero importamos el snippet de Authentik, luego definimos el reverse_proxy de la app.
app.midominio.com {
log {
output file /var/log/caddy/app-access.log
format transform "{request>headers>X-Forwarded-For>[0]:request>remote_ip} - {user_id} [{ts}] \"{request>method} {request>uri} {request>proto}\" {status} {size}" {
time_format "02/Jan/2006:15:04:05 -0700"
}
}
route {
# 1) Llama al snippet que gestiona la autenticación
import authentik
# 2) Redirige a la app protegida
reverse_proxy http://10.0.0.3:8080
}
}
Policy en Authentik
-
Expression Policy Nombre:
Skip-Home-IPfrom ipaddress import ip_address return ak_client_ip == ip_address("203.0.113.42") -
Aplica la policy Ruta: Flows and Stages → Flows →
default-authentication-flow→ Stage Bindings →default-authentication-mfa-validationBindea: la policySkip-Home-IPOrden:0Negate: desactivado
Si tienes IP dinámica pero dentro de un rango:
from ipaddress import ip_network
return ak_client_ip in ip_network("203.0.113.0/24")
Verificación
| Prueba | Esperado |
|---|---|
| Desde casa | Sin MFA. |
| Fuera de casa | MFA/login normal. |
| Audit → Requests | ALLOW (policy) y IP correcta en Client-IP. |
caddy validate |
Configuración válida. |
Ventajas
| Qué | Por qué |
|---|---|
| Sin MFA en casa | Nada de abrir el móvil cada dos por tres. |
| IP real protegida | trusted_proxies evita que te cuelen cabeceras falsas. |
| Mantenimiento mínimo | Solo un snippet + una policy. |
| Logs decentes | Se ve quién accedió, desde dónde, sin cosas raras. |
| Reversible fácil | Borra la policy o el import, y listo. |
Resumen breve
trusted_proxies+{client_ip}→ IP real segura.- Policy de tipo Expression comparando
ak_client_ip. - Todo controlado desde Caddy con un solo snippet.
- Flujo transparente, sin MFA en casa pero con seguridad fuera.
Referencias
- Rangos IP de Cloudflare — Para configurar
trusted_proxiessegún los saltos reales desde el proxy.
Caddy:
- Implementación de Cloudflare en Caddy
- Caddy: gestionar dominios fácilmente
- Directiva de Authentik para Caddy
Authentik:
- Authentik: proteger nuestras aplicaciones web
- Authentik: plataforma de autenticación y autorización centralizada
- Creación de aplicaciones, providers y outposts en Authentik
Forzar MFA en todos los usuarios de Authentik
Pequeña nota para dejar claro cómo obligar a que todos los usuarios de Authentik (ya existentes o nuevos) activen y usen un segundo factor de autenticación.
Requisitos previos
- Authentik ya desplegado y funcionando.
- Acceso como administrador a la interfaz web.
Pasos
1. Editar el stage de MFA
En Flows and Stages → Stages, buscar default-authentication-mfa-validation.
-
En el campo Not configured action, cambiarlo a:
- Force the user to configure an authenticator.
-
Elegir la etapa de configuración que corresponda (ejemplo:
default-authenticator-totp-setup).
Con esto, cualquier usuario sin MFA configurado será obligado a activarlo.
2. Insertar el stage en el flow de autenticación
-
Ir a Flows → default-authentication-flow.
-
En la pestaña Bind existing stage, añadir
default-authentication-mfa-validation. -
Colocarlo en el orden adecuado:
- Después de
default-authentication-identification(orden 10). - Antes de
default-authentication-password(orden 20). - Ejemplo: asignar 15 a
default-authentication-mfa-validation.
- Después de
Resultado
Con esa configuración, cualquier usuario que intente iniciar sesión sin MFA configurado se verá obligado a hacerlo antes de poder acceder.
Login sin contraseña en Authentik usando WebAuthn
Introducción
Este artículo documenta la habilitación de autenticación passwordless en Authentik mediante WebAuthn, utilizando llaves físicas (YubiKey u otras compatibles).
La integración se realiza a nivel de flujos de autenticación, sin eliminar el login tradicional, sino añadiendo una vía alternativa controlada desde el flujo principal. El resultado es un inicio de sesión donde Authentik detecta que el usuario dispone de un autenticador WebAuthn y ofrece iniciar sesión sin contraseña.
Requisito previo imprescindible: dispositivo WebAuthn registrado
Antes de modificar cualquier flujo, el usuario debe tener registrada una llave WebAuthn.
Este paso se realiza desde la interfaz de usuario, no desde el panel de administración:
- Acceso al perfil de usuario.
- Ajustes → Dispositivos de MFA.
- Añadir un nuevo dispositivo de tipo WebAuthn device.
- Registrar la llave física (YubiKey u otro autenticador compatible).
Sin este requisito, el flujo passwordless no tendrá ningún dispositivo que validar y el login no funcionará.
Enfoque general
El esquema que se construye es el siguiente:
-
El flujo de autenticación por defecto identifica al usuario.
-
Si el usuario dispone de dispositivos WebAuthn registrados:
- Se ofrece un flujo alternativo passwordless.
-
Dicho flujo valida el autenticador WebAuthn.
-
Tras la validación, se continúa con el login estándar de Authentik.
No se sustituye el login clásico: se complementa.
En usuarios con WebAuthn configurado, el proceso de autenticación se resuelve únicamente mediante la llave, sin interacción adicional ni validación de contraseña.
Desarrollo
Creación del flujo passwordless
En la interfaz de administración:
- Flows & Stages → Flows → Create
- Nombre:
Authentik Passwordless Flow - Title: el mismo nombre (o uno descriptivo equivalente)
- Designation:
Authentication
Este flujo se utilizará exclusivamente para la autenticación sin contraseña.
Validación de dispositivos WebAuthn
Dentro del flujo recién creado:
- Pestaña Stage Bindings
- Create & bind Stage
- Tipo de etapa: Authenticator Validation Stage
Configuración relevante:
-
Name:
Authentik Passwordless WebAuthn -
Allowed devices: WebAuthn Authenticators
-
Configuration Stages:
- Seleccionar el flujo de configuración de WebAuthn
- Por defecto:
default-authenticator-webauthn-setup
Order:
0(primer paso del flujo)
Esta etapa es la encargada de validar los dispositivos WebAuthn ya configurados por el usuario.
Continuación con el login estándar
Dentro del mismo flujo:
- Stage Bindings → Bind existing stage
- Stage:
default-authentication-login - Order: un valor superior al anterior (por ejemplo
10)
De este modo:
- Primero se valida la llave WebAuthn.
- A continuación, Authentik ejecuta su lógica estándar de inicio de sesión (gestión de sesión, cookies, etc.).
Enlace del flujo passwordless al flujo principal
Para que Authentik ofrezca este método de autenticación:
- Flows & Stages → Flows
- Abrir el flujo
default-authentication-flow - Ir a la pestaña Stage Bindings
- Editar la etapa
default-authentication-identification
En Flow settings:
- Campo Passwordless Flow
- Seleccionar:
Authentik Passwordless Flow
Guardar los cambios con Update.
Este paso vincula el flujo passwordless con el proceso de autenticación principal.
Validación
- Cerrar sesión o abrir una ventana en modo incógnito.
- Acceder de nuevo a Authentik.
- Tras introducir el usuario, debe aparecer la opción de iniciar sesión con una llave de seguridad.
Si el usuario tiene WebAuthn configurado correctamente, el login se realizará sin contraseña.
Decisiones importantes y consideraciones
- WebAuthn requiere HTTPS válido (certificados reales y funcionales).
- El navegador debe soportar WebAuthn (la mayoría de navegadores modernos lo hacen).
- Si el usuario no tiene un dispositivo WebAuthn registrado, Authentik recurrirá al login tradicional.
- No se recomienda eliminar el uso de contraseñas sin validar previamente este flujo.
Resumen breve
- Registro previo de una llave WebAuthn por usuario.
- Creación de un flujo de autenticación passwordless.
- Validación de WebAuthn antes del login estándar.
- Integración del flujo en el proceso de autenticación principal.
Referencias
Gitea
Notas personales sobre Gitea: no es una guía, es una vacuna contra perder tiempo.
Añadir una llave física en Gitea
Introducción
Configuración del inicio de sesión en Gitea mediante una llave física compatible con WebAuthn (YubiKey 5C NFC en este caso), manteniendo el método TOTP activo como respaldo en caso de pérdida o fallo de la llave.
Requisitos previos
- Gitea actualizado (≥ 1.21) con soporte WebAuthn.
- Navegador compatible con FIDO2/WebAuthn.
- Llave física (YubiKey, SoloKey, etc.).
- Método TOTP ya configurado (por ejemplo con Aegis o Authy) para disponer de acceso alternativo.
- Variable
ROOT_URLcorrectamente definida en el archivoapp.inicon la URL pública real de la instancia.
Desarrollo / pasos
1. Acceder a la configuración de seguridad
Desde el perfil de usuario: Perfil → Configuración → Seguridad.
2. Añadir la llave física
En el apartado Two-Factor Authentication (Security Keys):
- Introducir un nombre identificativo para la llave (por ejemplo:
YubiKey 5C NFC). - Pulsar Añadir llave de seguridad y seguir las instrucciones del navegador para completar el registro.
3. Confirmar el registro
La llave quedará listada con el nombre asignado. Se puede verificar su funcionamiento cerrando sesión y volviendo a iniciar con la llave insertada o aproximada (en caso de NFC).
4. Mantener TOTP como respaldo
No eliminar el método TOTP. Servirá para acceder si la llave se pierde, se rompe o deja de funcionar.
Errores comunes o decisiones importantes
- Error
Error validating origin: revisar que la variableROOT_URLenapp.inicoincide con la URL pública (por ejemplohttps://gitea.tudominio.org). - Algunas configuraciones de proxy (Caddy, Nginx) pueden alterar cabeceras y provocar fallos en WebAuthn.
- Recomendable registrar más de una llave si se dispone de varias.
Resumen breve
- Añadir la llave desde Configuración → Seguridad.
- Verificar
ROOT_URL. - Mantener TOTP como respaldo.
- Probar inicio de sesión con la llave.
Referencias o enlaces de interés
- Documentación oficial de Gitea sobre autenticación multifactor
- YubiKey en Gitea: error al registrar llave
Personalización de Gitea: Temas y otros ajustes
Introducción
Este artículo recoge los pasos necesarios para personalizar Gitea mediante temas, logos, favicons y plantillas. Todo con Docker, sin complicaciones raras. Asume que tienes los datos montados como /mnt/data:/data en el contenedor.
Estructura de carpetas
Asegúrate de tener creada la carpeta public dentro del volumen de datos. Por ejemplo:
drwxr-xr-x user user 4.0 KB ... public
Temas personalizados
- Crea tu CSS personalizado, por ejemplo
mi-tema.css. - Copia el archivo a:
/mnt/data/public/assets/css/mi-tema.css
- Edita el archivo
app.ini(en/mnt/data/conf/app.ini) y añade en[ui]:
[ui]
THEMES = gitea,arc-green,mi-tema
DEFAULT_THEME = mi-tema
- Reinicia Gitea:
docker-compose restart gitea
- Desde la interfaz, ve a
Configuración > Cuentay selecciona el tema.
Cambiar logo y favicon
-
Prepara los archivos:
logo.svgfavicon.png
-
Copia a:
/mnt/data/public/assets/img/logo.svg
/mnt/data/public/assets/img/favicon.png
- Reinicia el contenedor:
docker-compose restart gitea
Personalizar plantillas
- Crea o copia las plantillas a:
/mnt/data/public/templates
- Edita con cuidado (usa sintaxis de Go templates).
- Reinicia Gitea para aplicar los cambios.
Buenas prácticas
- Haz cambios primero en un entorno de pruebas.
- Guarda copia de los archivos originales.
- Asegúrate de que todo lo que modifiques sea compatible con tu versión actual de Gitea.
Referencias
YubiKey en Gitea: Error al registrar llave
Descripción
Al intentar añadir una YubiKey como método 2FA en Gitea, puede aparecer el error:
Could not read your security key.
An unknown error occurred. Please retry.
Y en los logs:
Unable to finish registration due to error: Error validating origin
DevInfo: Expected Values: [http+unix://gitea.tudominio.org], Received: https://gitea.tudominio.org
CreateCredential: Error validating origin
Este error ocurre cuando Gitea genera automáticamente la variable ROOT_URL de forma incorrecta (por ejemplo, con el prefijo http+unix://).
Solución
Editar el archivo de configuración dentro del contenedor:
nano /data/gitea/conf/app.ini
o, según la ruta interna del contenedor:
nano /gitea/conf/app.ini
Modificar la línea correspondiente a la URL base de la instancia:
ROOT_URL = https://gitea.tudominio.org/
Importante: asegúrate de incluir la barra final
/.
Con esto, Gitea podrá validar correctamente el origen (origin) durante el registro de la YubiKey y permitirá añadirla sin errores. Probado con una Yubikey 5C NFC.
Referencias
RustDesk
Cosas que fallaron en RustDesk justo cuando más lo necesitaba. Aquí dejo los trucos que me salvaron.
RustDesk, conexión no cifrada
Introducción
Este artículo documenta un tip técnico para asegurar correctamente las conexiones en RustDesk, evitando sesiones sin cifrar o conexiones forzadas a través de relay cuando no es necesario.
En determinados escenarios, una instalación funcional de RustDesk puede mostrar conexiones relayed o unencrypted, lo que implica mayor latencia y menor control sobre el tráfico. El objetivo de este ajuste es garantizar cifrado extremo a extremo y uso preferente de conexiones directas.
Contexto del problema
RustDesk separa los roles de HBBS (ID Server) y HBBR (Relay Server), y ambos utilizan claves para asegurar la comunicación. Si estas claves no están alineadas correctamente, pueden producirse los siguientes síntomas:
- Conexiones marcadas como relayed incluso en redes compatibles con P2P.
- Avisos de conexión no cifrada en el cliente.
- Indicador de seguridad ausente o incorrecto en la interfaz.
El problema no suele ser de red, sino de desajuste de claves entre servicios.
Requisitos previos
Condiciones necesarias antes de aplicar este ajuste:
- Servidor RustDesk operativo.
- Acceso a la configuración de despliegue (contenedores).
- Clientes capaces de conectarse al servidor propio.
La instalación base de RustDesk se documenta en un artículo independiente.
Enfoque general de la solución
La solución se basa en dos acciones clave:
- Forzar la generación y uso de claves por parte del servidor.
- Garantizar que HBBS y HBBR comparten exactamente las mismas claves.
Esto asegura que ambas piezas confían entre sí y permiten sesiones cifradas de extremo a extremo.
Limitación de acceso mediante clave pública
RustDesk permite restringir el acceso al servidor mediante claves públicas. Para ello, los servicios deben arrancar con el parámetro de clave activado.
En un despliegue basado en Docker, es necesario modificar el comando de arranque de HBBS y HBBR.
Ejemplo de configuración:
hbbr:
command: hbbr -k _
hbbs:
command: hbbs -r <IP_DEL_SERVIDOR>:21117 -k _
El carácter _ indica que RustDesk debe generar y gestionar automáticamente las claves, sin intervención manual. A partir de este momento, todas las conexiones que pasen por el servidor estarán asociadas a este par de claves.
Este ajuste es imprescindible para habilitar cifrado extremo a extremo real.
Sincronización de claves entre HBBS y HBBR
En algunos despliegues, RustDesk genera las claves en directorios distintos para cada servicio. Si estas claves no coinciden, el cliente mostrará conexiones unencrypted o forzará el uso de relay.
Pasos habituales para resolver el problema:
- Localizar el volumen persistente donde RustDesk almacena sus datos. Por ejemplo:
/docker/rustdesk/
- Identificar el directorio asociado a HBBS, donde se generan las claves:
/docker/rustdesk/hbbs/
- Copiar las claves generadas hacia el directorio utilizado por HBBR:
cp /docker/rustdesk/hbbs/id_ed25519* /docker/rustdesk/hbbr/
Con esto se garantiza que ambos servicios utilizan exactamente el mismo par de claves.
Este paso corrige el conocido key mismatch y es crítico para que el cifrado funcione correctamente.
Aplicación de cambios
Una vez aplicados los ajustes anteriores:
- Reiniciar los servicios de RustDesk para que carguen las nuevas claves.
- Verificar que los contenedores arrancan sin errores relacionados con claves o certificados.
No es necesario realizar cambios adicionales en los clientes, más allá de volver a conectar.
Verificación
Para confirmar que la configuración es correcta:
- Conectar un cliente RustDesk al servidor.
- Verificar que aparece el icono de escudo verde en la interfaz.
- Confirmar que la conexión se establece como directa cuando la red lo permite.
Si alguno de estos puntos no se cumple, revisar nuevamente la generación y sincronización de claves.
Consideraciones importantes
- Cada regeneración de claves requiere repetir la sincronización entre servicios.
- Las claves públicas solo deben compartirse con clientes de confianza.
- Este ajuste no elimina el relay, pero evita su uso innecesario.
Resumen breve
Una instalación correcta de RustDesk puede funcionar sin cifrado completo si las claves no están alineadas. Forzar la generación de claves y sincronizarlas entre HBBS y HBBR garantiza conexiones cifradas, reduce latencia y evita dependencias innecesarias del relay.
Referencias
Wazuh
Mis notas de supervivencia para que Wazuh no se convierta en spam. Ajustes de alertas, reglas y demás magia para que solo me moleste cuando realmente hay fuego.
Políticas que uso hoy en día en Wazuh
Introducción
Apunte rápido para tener recogidas las políticas que uso en Wazuh. Si añado más en el futuro, irán aquí. La idea es mantener un equilibrio entre conservar información útil para análisis forense y no saturar el almacenamiento de la máquina virtual donde corre Wazuh.
Retención de índices en OpenSearch
Alerts — 90 días
Política que elimina índices wazuh-alerts-* con más de 90 días de antigüedad. Se prioriza así mantener alertas recientes para correlaciones o revisiones rápidas, pero sin almacenar indefinidamente los índices que ya no aportan valor.
"policy_id": "wazuh-alerts-90d",
"description": "Eliminar índices wazuh-alerts-* mayores de 90 días"
Archives — 180 días
Política que elimina índices wazuh-archives-* con más de 180 días de antigüedad. En este caso, la retención es más amplia porque los archives contienen un histórico completo de eventos que pueden ser útiles para investigaciones más largas o revisiones de cumplimiento.
"policy_id": "wazuh-archives-180d",
"description": "Eliminar índices wazuh-archives-* mayores de 180 días"
Métricas — 30 días
Política que elimina índices wazuh-monitoring-* y wazuh-stats-* con más de 30 días de antigüedad. Las métricas tienen un valor más inmediato (estado de agentes, consumo de recursos, estadísticas de uso) y rara vez son necesarias más allá de un mes.
"policy_id": "wazuh-metrics-30d",
"description": "Eliminar índices wazuh-monitoring-* y wazuh-stats-* mayores de 30 días"
Limpieza en disco con crontab
Además de la limpieza de índices en OpenSearch, aplico un borrado periódico en disco dentro de la VM de Wazuh. El espacio de esta máquina es limitado (~60 GB), así que conviene eliminar también los ficheros crudos que se van acumulando en /var/ossec/logs/. De no hacerlo, podrían saturar el disco aunque los índices ya estén rotados.
# Elimina alertas con más de 90 días de antigüedad
0 0 * * * find /var/ossec/logs/alerts/ -type f -mtime +90 -exec rm -f {} \;
# Elimina archivos de archivo (archives) con más de 90 días de antigüedad
0 0 * * * find /var/ossec/logs/archives/ -type f -mtime +90 -exec rm -f {} \;
- alerts/ → se borran logs de alertas activas con más de 90 días.
- archives/ → se borran logs de archivo con más de 90 días.
Esta doble estrategia (índices en OpenSearch + ficheros en disco) asegura que los datos no se acumulen por duplicado en dos capas distintas.
Resumen breve
- Indices en OpenSearch: 90 días para alerts, 180 para archives, 30 para métricas.
- Limpieza en disco: borrado de ficheros de alerts y archives >90 días en la VM.
- Justificación: mantener información útil a corto/medio plazo sin comprometer el espacio limitado de la máquina virtual.