Aloja Open Connector para agentes de IA
Ejecuta Open Connector en tu VPS y evita que tus agentes guarden tokens SaaS: imagen fijada, origen TLS, callbacks OAuth y copias de seguridad.
Qué hace Open Connector para un agente de IA
Alojar Open Connector por cuenta propia coloca una puerta de enlace de autenticación entre los agentes de IA y cada API de software como servicio (SaaS) que usan. De este modo, el agente nunca almacena un token del proveedor. Es una puerta de enlace de código abierto de OOMOL Lab, con licencia Apache 2.0. Se ejecuta como un solo contenedor, guarda su estado en un único archivo SQLite y expone las acciones de los proveedores mediante HTTP y MCP (model context protocol).
El problema empieza con la segunda integración. Cada proveedor tiene su propio flujo de OAuth (open authorization), su propio periodo de validez del token de actualización y sus propios nombres de ámbito. Conectar manualmente cinco proveedores a un agente implica cinco controladores de redirección, cinco almacenes de credenciales y cinco bucles de actualización que deben ejecutarse antes de que caduque un token. Casi nadie escribe ese código. En su lugar, generan un token de acceso personal de larga duración para cada servicio y lo pegan en la configuración del agente, en un archivo de entorno o incluso en el prompt. Entonces, todas las herramientas que ejecuta el agente pueden leer ese token, y este termina en la transcripción. Este es el fallo que describe evitar que los secretos lleguen a los agentes de IA.
Una puerta de enlace de autenticación divide la credencial en dos. La puerta de enlace almacena la credencial del proveedor y ejecuta el flujo de OAuth. El agente recibe un token de ejecución que solo es válido frente a la puerta de enlace. Cuando el agente llama a una acción, la puerta de enlace carga la credencial almacenada, la inserta en la solicitud saliente desde el servidor y devuelve únicamente el cuerpo de la respuesta. El agente nunca recibe el token de acceso del proveedor. Por tanto, una transcripción del agente filtrada solo expone un token de ejecución revocable, no tu cuenta de GitHub.
El catálogo anuncia más de 1,000 proveedores y 10,000 acciones precompiladas. Esa cifra procede del propio proyecto y no se puede verificar desde el exterior. Lo que sí se puede verificar es la estructura: un endpoint HTTP por acción, una conexión almacenada por proveedor y un token por agente.
Por qué alojar Open Connector en su propio servidor en lugar de usar un servicio de conectores alojado
Un servicio de conectores alojado hace el mismo trabajo y almacena los tokens de actualización de cada proveedor que conecte. Un token de actualización de Google o GitHub es una credencial criptográfica de larga duración para acceder a su correo y sus repositorios, y normalmente sigue siendo válido después de cambiar la contraseña. Si el servicio sufre una intrusión, sus credenciales también quedan expuestas. El alojamiento propio mueve esos registros a SQLite en una máquina que alquila y administra, protegida con una clave que nunca sale de su servidor.
Calcule el coste antes de empezar. Esta VPS se convierte en el servidor más valioso que administra. Contiene credenciales operativas de una docena de servicios en un solo archivo. Por eso debe protegerla como protegería el servidor de un gestor de contraseñas: un firewall que solo exponga 443, ninguna cuenta compartida, una copia de seguridad que haya restaurado al menos una vez y una alerta cuando deje de responder. Si no almacenaría su bóveda de contraseñas en esta máquina, tampoco instale el conector en ella.
Fija una versión antes de instalar nada
Open Connector es reciente. El repositorio apareció por primera vez el 29 de junio de 2026 y, al 1 de agosto de 2026, la versión etiquetada más reciente es v1.3.3, publicada el 30 de julio de 2026 y con la etiqueta latest. El registro también publica una etiqueta tip, compilada a partir del commit más reciente de main.
En un proyecto tan reciente, las etiquetas móviles cambian con frecuencia. Un docker compose pull que avance dos versiones puede cambiar un endpoint del que depende el agente, y pasarás la tarde depurando el problema como si fuera un fallo del agente. Fija la imagen a una etiqueta de versión y actualízala cuando decidas hacerlo, después de leer las notas de la versión.
Implementar Open Connector detrás de TLS en su propio VPS
Antes de iniciar el contenedor, necesita:
- Docker con el complemento Compose, en Ubuntu 24.04 o una distribución similar
- un nombre de host cuyo registro A apunte a este VPS, por ejemplo
connect.example.com - un proxy inverso que ya termine TLS (seguridad de la capa de transporte) para ese nombre de host
- dos secretos aleatorios, que se generan a continuación
La guía Proxy inverso Traefik para varias aplicaciones de Docker Compose cubre la configuración del proxy. La guía n8n en un VPS con Docker y HTTPS describe la misma configuración de certificados, de principio a fin, para una sola aplicación.
Genere primero los secretos. La clave de cifrado protege las credenciales almacenadas. El token de administrador protege la consola web y toda la superficie de /api. Ninguno tiene un valor predeterminado, y el entorno de ejecución se inicia correctamente aunque no estén definidos.
mkdir -p ~/open-connector && cd ~/open-connector
umask 077
printf 'OOMOL_CONNECT_ENCRYPTION_KEY=%s\n' "$(openssl rand -base64 32)" > .env
printf 'OOMOL_CONNECT_ADMIN_TOKEN=%s\n' "$(openssl rand -base64 32)" >> .env
chmod 600 .envCopie ahora ambos valores en su administrador de contraseñas, antes del primer inicio. La clave de cifrado no se puede recuperar. El motivo se explica en la lista de errores más abajo.
Ahora compose.yaml. Difiere del ejemplo de origen en dos puntos, y ambos son importantes.
services:
connector:
image: ghcr.io/oomol-lab/open-connector:v1.3.3
restart: unless-stopped
ports:
- "127.0.0.1:3000:3000"
volumes:
- connector-data:/app/data
environment:
OOMOL_CONNECT_DATA_DIR: /app/data
OOMOL_CONNECT_ORIGIN: "https://connect.example.com"
OOMOL_CONNECT_ENCRYPTION_KEY: "${OOMOL_CONNECT_ENCRYPTION_KEY:?set this in .env}"
OOMOL_CONNECT_ADMIN_TOKEN: "${OOMOL_CONNECT_ADMIN_TOKEN:?set this in .env}"
volumes:
connector-data:El primer cambio es la etiqueta fijada en lugar de latest. El segundo es el puerto. El archivo de origen publica 3000:3000, que enlaza todas las interfaces del host. Docker escribe los puertos publicados en la tabla NAT (traducción de direcciones de red) antes de que el paquete llegue a la cadena de filtrado de ufw. Por eso, ufw deny 3000 no cierra ese puerto. Esta es la trampa descrita en por qué los puertos de Docker omiten ufw. Escribir 127.0.0.1:3000:3000 publica el puerto solo en la interfaz de loopback, y el proxy inverso se conecta desde el mismo host.
:? marca cada variable como obligatoria. Por tanto, la pila se niega a iniciar si falta .env, en lugar de iniciarse con las credenciales sin cifrar. Mantener los valores en .env, en vez de incluirlos en el archivo de Compose, sigue el patrón de archivos env y secretos de Docker Compose.
docker compose up -d
docker compose logs -n 30 connector
curl -s http://127.0.0.1:3000/health
sudo ss -tlnp | grep 3000/health responde { "ok": true } cuando el entorno de ejecución ya está activo. ss debe mostrar 127.0.0.1:3000. Una línea que muestre 0.0.0.0:3000 indica que la asignación de puertos sigue siendo la del origen y que la puerta de enlace responde directamente a todo Internet. Si la comprobación de estado devuelve «conexión rechazada», el contenedor todavía no está escuchando. Consulte los registros antes de modificar el proxy.
Etiquetas de Traefik para el mismo servicio
labels:
- "traefik.enable=true"
- "traefik.http.routers.connector.rule=Host(`connect.example.com`)"
- "traefik.http.routers.connector.entrypoints=websecure"
- "traefik.http.routers.connector.tls.certresolver=le"
- "traefik.http.services.connector.loadbalancer.server.port=3000"Cuando Traefik se ejecuta en Docker en el mismo host, conecte este servicio a la red de Traefik y elimine el bloque ports:, porque Traefik accede al contenedor mediante la red interna y no es necesario publicar nada en el host. certresolver=le debe coincidir con el nombre del resolver en la configuración estática de Traefik. De lo contrario, el router se inicia sin certificado.
Por qué OAuth requiere un nombre de host real
OOMOL_CONNECT_ORIGIN es el ajuste que se suele omitir, y omitirlo rompe OAuth de una forma que parece un error del proveedor. El entorno de ejecución crea el URI de redirección a partir de ese origen, con el formato <origin>/oauth/callback. Si no se establece, el origen toma el valor predeterminado http://localhost:3000. Por tanto, el entorno de ejecución envía al proveedor un URI de redirección http://localhost:3000/oauth/callback, mientras que la aplicación OAuth tiene registrado https://connect.example.com/oauth/callback. Las dos cadenas son diferentes, así que GitHub responde:
The redirect_uri MUST match the registered callback URL for this application.Un proveedor OAuth redirige el navegador a ese URI. Por tanto, debe ser una dirección accesible desde el exterior. Los proveedores rechazan http:// sin cifrado para cualquier destino que no sea localhost. Por eso esta implementación necesita un nombre de host y un certificado. Establece el origen antes del primer inicio, porque el valor se lee durante el arranque. Después de editar .env o compose.yaml, ejecuta docker compose up -d de nuevo para aplicar el cambio.
Conecta tu primer proveedor mediante OAuth
Crea primero la aplicación OAuth en el proveedor. En GitHub, la ruta es Settings, después Developer settings, luego OAuth Apps y, por último, New OAuth App. Establece la URL de devolución de autorización en https://connect.example.com/oauth/callback. Conserva el ID de cliente y el secreto de cliente.
Cada llamada a /api incluye el token de administrador, así que expórtalo una vez para la sesión del shell.
export ADMIN_TOKEN='paste-the-admin-token'
curl -s https://connect.example.com/api/oauth/configs \
-H "authorization: Bearer $ADMIN_TOKEN"Esa lista muestra el URI de redirección que el entorno de ejecución espera para cada proveedor. Es la comprobación más rápida de que el origen se aplicó correctamente. Si todavía muestra localhost, el contenedor se está ejecutando con el valor anterior y el flujo OAuth fallará en el último paso.
Almacena las credenciales de cliente y, después, inicia una autorización.
curl -s -X PUT https://connect.example.com/api/oauth/configs/github \
-H "authorization: Bearer $ADMIN_TOKEN" \
-H 'content-type: application/json' \
-d '{"clientId":"...","clientSecret":"..."}'
curl -s -X POST https://connect.example.com/api/oauth/authorizations \
-H "authorization: Bearer $ADMIN_TOKEN" \
-H 'content-type: application/json' \
-d '{"service":"github"}'La segunda llamada devuelve un authorizationUrl. Ábrelo en un navegador, aprueba los ámbitos y el proveedor devuelve el navegador a /oauth/callback. Allí, el entorno de ejecución intercambia el código y almacena la credencial. La consola web en tu origen guía los mismos pasos mediante un formulario y usa el mismo token de administrador. Los proveedores que utilizan una clave de API simple omiten todo esto: PUT /api/connections/<service> con {"authType":"api_key","values":{"apiKey":"..."}} almacena la clave directamente.
Asigne a cada agente un token de ejecución, nunca la credencial
El agente se autentica en la puerta de enlace con un token de ejecución que emite la API de administración.
curl -s -X POST https://connect.example.com/api/runtime-tokens \
-H "authorization: Bearer $ADMIN_TOKEN" \
-H 'content-type: application/json' \
-d '{"name":"research-agent"}'La respuesta contiene un token que comienza por oct_. Emita uno por agente y asígnele el nombre de ese agente. Si revoca un token que no puede identificar, tendrá que revocarlos todos. Después, el agente llama a las acciones mediante HTTP estándar.
curl -s -X POST https://connect.example.com/v1/actions/github.get_current_user \
-H "authorization: Bearer oct_..." \
-H 'content-type: application/json' \
-d '{"input":{}}'Una respuesta correcta es un sobre cuyo campo success es true, con la carga útil del proveedor en data. El token de GitHub no aparece en ningún lugar de esa respuesta. Para un cliente MCP, configúrelo para usar https://connect.example.com/mcp con el mismo encabezado de bearer. La puerta de enlace ofrece herramientas de descubrimiento como search_actions y execute_action en lugar de una herramienta por API. Esto mantiene reducida la lista de herramientas del agente. Ejecutar servidores MCP en un VPS explica la parte del cliente de esa configuración.
Realice una comprobación más antes de dar el proceso por terminado. Repita la llamada a la acción después de eliminar el encabezado authorization. La guía de inicio rápido del proyecto llama a /v1 sin ningún bearer. Por tanto, una instalación sin autenticación de ejecución configurada ejecutará acciones para cualquiera que pueda acceder al puerto. Si la llamada sin autenticación tiene éxito, tiene dos opciones: configurar tokens de ejecución y confirmar que la llamada anónima falla, o restringir /api, /v1 y /mcp en el proxy inverso a las direcciones desde las que se conectan sus agentes. Solo /oauth/callback debe permanecer abierto al mundo, porque es la única ruta que necesita la redirección del navegador de un proveedor.
Reduzca la lista de acciones a lo que necesita el agente
Una puerta de enlace con mil proveedores detrás ofrece una superficie de exposición amplia para un modelo de lenguaje. Dos controles la reducen.
OOMOL_CONNECT_ALLOWED_ACTIONS acepta una lista de permitidos separada por comas y admite service.* y *. OOMOL_CONNECT_BLOCKED_ACTIONS es la lista de bloqueados, y esta tiene prioridad. Establecer la lista de permitidos en github.get_current_user,github.list_issues significa que se rechaza cualquier otra acción, independientemente de lo que solicite el agente. Esta es la diferencia entre un error y un incidente. Los tokens de tiempo de ejecución tienen sus propias reglas de acciones, además de las reglas globales, y su lista allowedProxies está vacía inicialmente. Por eso POST /v1/proxy/:service se rechaza hasta que se conceda explícitamente. Ese endpoint proxy reenvía una solicitud sin modificar a un proveedor con sus credenciales adjuntas. Déjelo vacío salvo que un agente específico lo necesite.
OOMOL_CONNECT_ALLOW_PRIVATE_NETWORK tiene el valor predeterminado false. Esto impide que la conexión con un proveedor autohospedado apunte a una dirección privada, como el servicio de metadatos de la nube en 169.254.169.254 o su base de datos en la misma red. Déjelo desactivado. Actívelo únicamente para un proveedor que aloje usted mismo.
Haga una copia de seguridad del sistema que contiene todos los tokens
Hay dos elementos importantes, y cada uno es inútil sin el otro. La base de datos ubicada en /app/data/connect.sqlite dentro del volumen connector-data contiene las credenciales selladas. La clave de cifrado en .env las desbloquea. Una copia de seguridad del volumen sin la clave no restaura nada, y la clave sin el volumen tampoco restaura nada. Por eso, la clave debe estar en el gestor de contraseñas y el volumen debe incluirse en la rotación normal de copias de seguridad.
Detenga el contenedor mientras copia el archivo SQLite, porque una copia realizada durante una escritura puede restaurarse como una base de datos dañada.
docker volume ls | grep connector-data
docker compose stop connector
docker run --rm -v open-connector_connector-data:/data -v "$PWD":/backup alpine \
tar czf /backup/connector-data.tgz -C /data .
docker compose start connectorEl nombre del volumen es el directorio del proyecto seguido de _connector-data. Por eso existe el primer comando: pegue el nombre real en el tercero. Envíe el archivo comprimido fuera del VPS con copias de seguridad restic desde un VPS. restic lo cifra antes de transferirlo, porque ese archivo contiene el almacén de credenciales.
El entorno de ejecución conserva las ejecuciones de acciones recientes como registros de auditoría, 5,000 de forma predeterminada. Así, la consola puede indicar qué agente ejecutó cada acción y cuándo. Ese registro es lo primero que debe consultar cuando un agente se comporta de forma extraña. Configure también una página de estado de Uptime Kuma para https://connect.example.com/health. Cuando la puerta de enlace deja de responder, los agentes fallan de formas confusas. Saber que la puerta de enlace está caída evita dedicar una hora a revisar la salida de los agentes.
Qué falla y qué mensaje verá
redirect_uri_mismatch en el proveedor. El origen y la URL de callback registrada no coinciden. Compare la cadena exacta de /api/oauth/configs con la configuración de la aplicación en el proveedor, incluido https frente a http y cualquier barra final.
Cada llamada a /api devuelve 401. Falta la cabecera del token de administración o está mal escrita. La cabecera es Authorization: Bearer <token>, y la consola web solicita el mismo token.
El contenedor se ejecuta y las credenciales quedan en texto sin formato. Esto ocurre cuando OOMOL_CONNECT_ENCRYPTION_KEY nunca llega al contenedor, porque el runtime almacena los registros de credenciales sin cifrar en lugar de impedir el inicio. Compruébelo en su propia instalación: conecte un proveedor con una API key que pueda reconocer y, después, busque esa clave en la base de datos.
docker compose cp connector:/app/data/connect.sqlite /tmp/connect.sqlite
grep -c 'github_pat_' /tmp/connect.sqlite
shred -u /tmp/connect.sqliteUn recuento superior a 0 significa que la clave no está activa. Compruebe que .env se encuentre en el mismo directorio que compose.yaml y que docker compose config muestre el valor. Con la clave configurada, la misma búsqueda devuelve 0, porque el registro está protegido con AES-256-GCM (advanced encryption standard, clave de 256 bits, modo Galois/counter).
Nada se descifra después de una restauración. La clave de cifrado cambió o se perdió. Por diseño, nunca se escribe junto a los datos. Por tanto, no existe una vía de recuperación ni un ticket de soporte que pueda resolverlo. Vuelva a conectar todos los proveedores. La rotación se admite mediante una variable de clave independiente y un comando de datos en el runtime. Consulte las notas de la versión actual antes de rotar nada.
El agente devuelve un error que menciona una acción visible en el catálogo. El descubrimiento y la ejecución son independientes. Una acción puede aparecer en search_actions y aun así ser rechazada por OOMOL_CONNECT_ALLOWED_ACTIONS, por la lista de denegación o por las reglas propias del token de ese runtime.
Actualizaciones. Haga una copia de seguridad del volumen, cambie el tag de la imagen a la nueva release y, después, docker compose pull && docker compose up -d. Supervise docker compose logs -n 50 connector para detectar una línea de migración y vuelva a ejecutar la comprobación de estado y una acción real antes de volver a confiar en el sistema. Para revertir la actualización, restaure el tag anterior. Esto funciona únicamente porque lo fijó.
FAQ
¿Necesito un dominio público para alojar Open Connector?
Para los proveedores que usan una clave de API, no: una puerta de enlace en 127.0.0.1 es suficiente. Para OAuth, en la práctica sí. El proveedor redirige un navegador a la URL de devolución de llamada, por lo que esa URL debe resolverse desde Internet público, y los proveedores rechazan http:// sin cifrado fuera de localhost. Configure OOMOL_CONNECT_ORIGIN con su nombre de host https:// antes del primer inicio y registre <origin>/oauth/callback en la aplicación OAuth del proveedor.
¿Qué ocurre si pierdo la clave de cifrado de Open Connector?
Las credenciales almacenadas no se pueden descifrar y no existe ningún método de recuperación. La clave nunca se almacena junto con los datos de forma deliberada, por lo que nadie que tenga la base de datos puede leerla, incluido usted. La única opción es establecer una clave nueva y volver a conectar todos los proveedores. Guarde la clave en un gestor de contraseñas y la base de datos en su rotación de copias de seguridad, porque una restauración necesita ambos elementos.
¿Puede mi agente de IA ver el token de acceso del proveedor?
No cuando realiza llamadas a través de la puerta de enlace. El agente se autentica con un token de tiempo de ejecución que empieza por oct_, y la puerta de enlace inyecta la credencial del proveedor en la solicitud saliente en el servidor y devuelve únicamente la respuesta. Dos situaciones rompen esta propiedad: el endpoint /v1/proxy/:service, que reenvía solicitudes sin procesar con su credencial adjunta y cuyos permisos empiezan vacíos por una razón, y pegar usted mismo una clave de API en el agente, lo que omite por completo la puerta de enlace.
¿Debe poder accederse a la puerta de enlace desde Internet público?
Solo debe poder accederse a /oauth/callback. Publique el puerto del contenedor en 127.0.0.1 para que las reglas NAT de Docker no puedan exponerlo más allá del firewall, y coloque el proxy inverso delante. Después, pruebe una llamada de acción sin la cabecera authorization. Si funciona, restrinja /api, /v1 y /mcp en el proxy a las direcciones que usan sus agentes, hasta que solo funcionen las llamadas autenticadas.
¿Está Open Connector listo para usarse en producción?
Tiene licencia Apache 2.0 y evoluciona rápidamente: el repositorio apareció el 29 de junio de 2026 y v1.3.3 se publicó el 30 de julio de 2026, por lo que debe tratar cada número de versión de esta guía como una instantánea del 1 de agosto de 2026. Ejecútelo fijado a una etiqueta de versión, nunca en latest ni tip, lea las notas de la versión antes de cada actualización y conserve una copia de seguridad del volumen que haya restaurado al menos una vez. El diseño es sólido para un equipo que controla, y el riesgo está en los cambios frecuentes de versión, no en la arquitectura.