Cómo guardar credenciales en n8n sin dejarlas en texto plano
Clave de cifrado, variables de entorno y el fallo típico del nodo Code, explicados con un caso real de secretos expuestos.
Por Carlos Ruiz · Director Comercial
Un docker-compose.yml con diez secretos en texto plano, subido sin querer a un repositorio compartido. Claves de API de facturación, un token de WhatsApp, la contraseña de un servidor SMTP. Todo ahí, legible por cualquiera que abriera el archivo. Ese es el punto de partida de este artículo: un caso propio, no uno ajeno.
Pasó por prisa. El proyecto necesitaba levantarse rápido, las credenciales se metieron como variables de entorno directamente en el docker-compose.yml para probar, y esa prueba se quedó ahí meses. Nadie lo hizo con mala intención. Es lo que pasa cuando “ya lo arreglo luego” se convierte en la configuración definitiva.
Vamos a ver por qué pasó, qué falla exactamente y cómo se guarda esto bien en n8n.
Cómo guarda n8n las credenciales (cuando se hace bien)
n8n tiene un sistema propio de credenciales. Cuando conectas un nodo a Gmail, a una base de datos o a una API, no escribes la clave dentro del workflow: la guardas en el gestor de credenciales, y n8n la cifra antes de meterla en su base de datos.
Ese cifrado depende de una clave de cifrado (N8N_ENCRYPTION_KEY), una variable de entorno que actúa como la llave maestra. Si no la defines tú, n8n genera una automáticamente la primera vez que arranca y la guarda en un archivo de configuración local.
Aquí está el primer problema práctico: si esa clave se genera sola y luego pierdes el contenedor o el volumen donde vivía (por ejemplo, al recrear un contenedor Docker sin volumen persistente), todas las credenciales guardadas quedan cifradas e ilegibles. No hay forma de recuperarlas. Hay que volver a introducirlas una por una.
La solución es simple pero hay que hacerla a propósito:
- Define tú mismo el valor de
N8N_ENCRYPTION_KEYcomo variable de entorno, con una cadena larga y aleatoria. Al menos 32 caracteres; se genera en un segundo conopenssl rand -base64 32. - Guarda esa clave en un sitio aparte del proyecto (un gestor de contraseñas, no un archivo del repositorio).
- Usa siempre la misma clave en todos los entornos donde muevas esa instancia de n8n, porque si cambia, las credenciales antiguas dejan de descifrarse.
Este tema tiene relación directa con lo que contamos en qué hacer cuando un workflow de n8n falla de madrugada: muchos fallos “raros” después de mover o restaurar una instancia vienen de aquí, de una clave de cifrado que cambió sin que nadie se diera cuenta.
El error de pegar la API key en un nodo Code
n8n tiene un nodo llamado Code, donde puedes escribir JavaScript directamente dentro del workflow. Es muy útil para transformar datos. Es tentador, cuando estás probando algo rápido, pegar ahí mismo una clave de API para no complicarte con el gestor de credenciales.
El problema es que ese código se guarda como parte del JSON del workflow. Eso significa que:
- Si exportas el workflow para compartirlo o hacer una copia de seguridad, la clave viaja con él, en texto plano.
- Si otra persona del equipo tiene acceso a editar workflows, ve la clave sin necesidad de pedirla.
- Si el workflow queda en el historial de versiones de n8n, la clave queda ahí también, aunque la borres después del código.
Por eso, desde hace tiempo, n8n bloquea por defecto el acceso a las variables de entorno dentro del nodo Code. No es un capricho: es para que nadie use ese nodo como atajo para meter secretos sueltos.
La forma correcta de usar un dato sensible dentro de un flujo es siempre la misma: crear una credencial en el gestor de n8n, asociarla al nodo que la necesita (HTTP Request, por ejemplo) y dejar que el nodo la use internamente. El valor cifrado nunca aparece en el JSON del workflow, ni se ve al exportarlo.
Si de verdad necesitas una variable de entorno dentro de una expresión (no dentro de un nodo Code), n8n permite referenciarla con $env en los campos que sí lo soportan, siempre que el administrador de la instancia lo haya habilitado explícitamente. Es una decisión consciente, no el comportamiento por defecto, y con razón.
Variables de entorno: para qué sirven y para qué no
Las variables de entorno son el sitio correcto para configuración de la instancia: la clave de cifrado, la URL pública, el usuario de la base de datos de n8n. No son el sitio para guardar la API key de cada proveedor con el que trabajas en tus workflows.
La diferencia importa:
- Variables de entorno: configuran cómo funciona n8n como aplicación. Se definen una vez, en el servidor o en el archivo de arranque.
- Credenciales de n8n: configuran cómo se conecta un workflow concreto a un servicio externo. Se gestionan desde la interfaz, con cifrado propio, y pueden cambiar sin tocar el servidor.
Meter las claves de proveedores como variables de entorno del contenedor (que es justo lo que pasó en el caso del docker-compose) mezcla ambas cosas. Y trae un problema añadido: cualquiera con acceso al archivo de despliegue —o al repositorio donde vive ese archivo— ve las claves sin pasar por n8n en absoluto.
Cómo se solucionó el caso del docker-compose
Estos fueron los pasos, en orden:
- Revocar todas las claves expuestas. No basta con borrarlas del archivo: si estuvieron en texto plano y el repositorio se compartió aunque fuera brevemente, hay que asumir que pudieron verse. Se regeneraron las diez claves desde cada proveedor.
- Sacar los secretos del
docker-compose.yml. Se movieron a un archivo.envseparado, que no se sube al repositorio (añadido a.gitignoredesde el primer commit, esta vez de verdad). - Migrar lo que eran credenciales de workflow al gestor de n8n. Las claves que se usaban dentro de nodos HTTP Request o similares dejaron de ser variables de entorno del contenedor y pasaron a ser credenciales cifradas gestionadas desde la interfaz.
- Fijar una
N8N_ENCRYPTION_KEYpropia y documentarla aparte, en el gestor de contraseñas del equipo, no en ningún archivo del proyecto. - Revisar el historial de Git para confirmar en qué commits habían quedado expuestas las claves antiguas, y así saber exactamente cuáles había que revocar sin dejarse ninguna.
Este último paso es el que más se salta la gente con prisa: piensan que borrar el archivo actual soluciona el problema, y el historial de commits sigue guardando la versión anterior con las claves visibles.
Cuándo esto es demasiado para una empresa pequeña
Si tienes una sola persona trabajando en n8n, con acceso controlado y sin repositorios compartidos con terceros, montar una gestión de secretos muy sofisticada (vaults externos, rotación automática de claves) es más esfuerzo del que compensa. Con fijar bien la clave de cifrado, no tocar el docker-compose para secretos de proveedores, y usar siempre el gestor de credenciales de n8n, cubres la mayoría de los problemas reales.
Donde sí merece la pena invertir más tiempo es cuando varias personas tocan el mismo servidor, cuando se trabaja con datos de clientes (como en flujos de automatización de facturas con n8n, donde las credenciales del proveedor contable son sensibles de verdad) o cuando el despliegue pasa por un repositorio con más de una persona con acceso. El mismo criterio vale para el token permanente de la API de WhatsApp: con ese token cualquiera puede escribir a tus clientes en nombre de tu empresa, así que no es un secreto más.
En resumen
Guarda las claves de proveedores en el gestor de credenciales de n8n, no en nodos Code ni en archivos de despliegue. Fija tú mismo la clave de cifrado y guárdala aparte. Y si alguna vez un secreto llega a estar en texto plano en un repositorio, aunque sea un momento, trátalo como comprometido: revócalo y genera uno nuevo. Es más rápido que confiar en que nadie lo vio.
Por los flujos de un proyecto de automatización de procesos circulan datos de los clientes de tu cliente, así que esto no es una recomendación opcional: es la parte que hay que dejar cerrada antes de poner nada en producción.
Preguntas frecuentes
¿Dónde hay que guardar las claves de API que usan los workflows de n8n?
En el gestor de credenciales de n8n, no dentro del workflow. Al crear la credencial y asociarla al nodo que la necesita, n8n la cifra antes de guardarla y el valor no aparece en el JSON del flujo ni al exportarlo. Las variables de entorno son para configurar la instancia, no para las claves de cada proveedor.
¿Por qué no se debe pegar una API key en un nodo Code?
Porque ese código se guarda como parte del JSON del workflow. La clave viaja en cualquier exportación o copia de seguridad, la ve cualquiera del equipo que pueda editar flujos y se queda en el historial de versiones aunque luego la borres del código. Por eso n8n bloquea por defecto las variables de entorno en ese nodo.
¿Qué pasa si se pierde la clave de cifrado de n8n?
Que todas las credenciales guardadas quedan cifradas e ilegibles y hay que volver a introducirlas una por una. Si no defines tú N8N_ENCRYPTION_KEY, n8n genera una la primera vez que arranca y la deja en un archivo local: al recrear el contenedor sin volumen persistente, desaparece con él.
¿Qué hago si una clave ha estado en texto plano en un repositorio?
Tratarla como comprometida y revocarla, aunque solo estuviera expuesta un momento: es más rápido que confiar en que nadie la vio. Después se sacan los secretos del fichero de despliegue a un archivo aparte fuera del repositorio, y se revisa el historial de Git para saber exactamente qué claves hay que regenerar.