Cómo alojar Open Connector para agentes de IA
Aloja Open Connector en tu VPS con una imagen fijada, origen TLS, callbacks OAuth y copias de seguridad, sin exponer tokens SaaS a tus agentes.
Qué hace Open Connector por un agente de IA
Alojar Open Connector en su propia infraestructura coloca una puerta de enlace de autenticación entre sus agentes de IA y todas las API de software como servicio (SaaS) que utilizan. De este modo, el agente nunca almacena un token del proveedor. Es una puerta de enlace cuyo código fuente está disponible, desarrollada por OOMOL Lab. Actualmente se distribuye bajo una licencia Apache 2.0 modificada, con condiciones adicionales. Las versiones hasta v1.9.4 siguen bajo Apache 2.0; v1.9.5 introdujo el cambio. Proporcionar un servicio alojado o gestionado cuyo valor principal sea la funcionalidad de OpenConnector requiere una licencia comercial de OOMOL. Se ejecuta como un solo contenedor, conserva 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 OAuth (open authorization), su propia duración del token de actualización y sus propios nombres de ámbito. Conectar cinco proveedores a un agente manualmente implica crear 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. Además, termina en la transcripción. Este es el problema que describe cómo mantener los secretos fuera de los agentes de IA.
Una puerta de enlace de autenticación divide la credencial en dos partes. La puerta de enlace almacena la credencial del proveedor y ejecuta el flujo OAuth. El agente recibe un token de ejecución que sólo 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 inyecta en la solicitud saliente en el servidor y devuelve únicamente el cuerpo de la respuesta. El agente nunca recibe el token de acceso del proveedor. Por tanto, si se filtra la transcripción del agente, el coste es un token de ejecución revocable en lugar de su cuenta de GitHub.
El catálogo anuncia más de 1,000 proveedores y 10,000 acciones predefinidas. Estas cifras proceden del propio proyecto y no se pueden verificar desde fuera. 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. Si la parte del agente todavía es nueva y términos como llamada a una herramienta o servidor MCP aún no están consolidados, el recorrido gradual de cómo aprender sobre agentes de IA desde cero desarrolla el bucle, las herramientas y las prácticas de seguridad que una puerta de enlace como esta da por conocidas.
Por qué alojar Open Connector en su propio servidor en lugar de usar un servicio de conectores alojado
Un servicio de conectores alojado realiza el mismo trabajo y conserva los tokens de actualización de cada proveedor al que lo conecta. Un token de actualización de Google o GitHub es una credencial de larga duración que permite acceder a su correo y a sus repositorios. Si el servicio sufre una brecha, usted también queda comprometido. El alojamiento propio mueve esos registros a SQLite en una máquina que usted alquila y administra. Los protege con una clave que nunca sale de su servidor.
Considere el coste antes de empezar. Este VPS se convierte en el servidor más valioso que administra. Contiene credenciales operativas de una docena de servicios en un solo archivo. Por tanto, debe protegerlo como protegería un servidor que aloja un gestor de contraseñas: un firewall que sólo 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 pondría su almacén de contraseñas en este servidor, tampoco instale el conector allí.
Fije una versión antes de instalar nada
Open Connector es un proyecto reciente. Esta guía fija la versión v1.3.3, publicada el 30 July 2026, como instantánea de instalación del 1 August 2026. Ya no es la versión más reciente. El registro también publica una etiqueta tip, creada a partir del commit más reciente de main.
En un proyecto tan reciente, las etiquetas variables cambian con frecuencia. Un docker compose pull que avance dos versiones puede cambiar un endpoint del que dependa su agente, y puede pasar la tarde depurando el problema como si fuera un fallo del agente. Fije la imagen a una etiqueta de versión y actualícela cuando lo decida, después de leer las notas de la versión.
Implementación de Open Connector detrás de TLS en su propio VPS
Antes de iniciar el contenedor, necesita:
- Docker Engine 28.0.0 o posterior con el complemento Compose, en Ubuntu 24.04 o una versión similar
- un nombre de host cuyo registro A apunte a este VPS, por ejemplo
connect.example.com - un reverse proxy que ya gestione la terminación TLS (transport layer security) para ese nombre de host
- dos secretos aleatorios, que se generan a continuación
La guía reverse proxy Traefik para varias aplicaciones Docker Compose cubre la configuración del proxy. La guía n8n en un VPS con Docker y HTTPS muestra 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 /api. Ninguno tiene un valor predeterminado y el runtime 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 gestor de contraseñas, antes del primer inicio. La clave de cifrado no se puede recuperar. El motivo se explica en la lista de fallos más abajo.
Ahora compose.yaml. Se diferencia del ejemplo original en dos aspectos, 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 original publica 3000:3000, que enlaza todas las interfaces del host. Docker escribe los puertos publicados en la tabla NAT (network address translation) antes de que el paquete llegue a la cadena de filtrado de ufw. Por tanto, 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 sólo en la interfaz de loopback, y el reverse proxy se conecta desde el mismo host. Antes de Docker Engine 28.0.0, los hosts del mismo segmento L2 podían acceder a los puertos publicados en localhost. Por eso esta guía requiere 28.0.0 o posterior.
:? marca cada variable como obligatoria. Así, el stack no se inicia si falta .env, en lugar de iniciarse con las credenciales sin cifrar. Mantener los valores en .env en vez de incluirlos en el archivo Compose sigue el patrón de archivos env y secretos de Docker Compose. Mantenga /v1 y /mcp privados en el reverse proxy hasta que haya creado el primer token de runtime que se muestra a continuación.
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 runtime ya está activo. ss debe mostrar 127.0.0.1:3000. Una línea con 0.0.0.0:3000 indica que el listener está enlazado a todas las interfaces IPv4, pero no demuestra que sea accesible desde Internet: los firewalls externos o las reglas de la cadena DOCKER-USER de Docker todavía pueden bloquear el tráfico externo. Si la comprobación de estado devuelve «Connection refused», el contenedor todavía no está escuchando. Revise los logs 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 definido en la configuración estática de Traefik. De lo contrario, el router se inicia sin certificado.
Por qué las devoluciones de OAuth necesitan el origen correcto
OOMOL_CONNECT_ORIGIN es el ajuste que se suele omitir. Al omitirlo, OAuth falla de una forma que parece un error del proveedor. El entorno de ejecución construye el URI de redirección a partir de ese origen, con el formato <origin>/oauth/callback. Si no se establece, el origen toma de forma predeterminada el valor http://localhost:3000. Por eso, el entorno de ejecución envía al proveedor un URI de redirección http://localhost:3000/oauth/callback, mientras 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 de OAuth redirige el navegador de vuelta a ese URI, por lo que el navegador debe poder acceder a esa dirección. OAuth no exige siempre un nombre de host público: OpenConnector documenta las devoluciones de GitHub en http://localhost:3000/oauth/callback. Esta implementación en un VPS usa un nombre de host y un certificado para que el navegador llegue a la puerta de enlace mediante su origen HTTPS. Establezca el origen antes del primer arranque, porque el valor se lee al iniciar. Después de editar .env o compose.yaml, vuelva a ejecutar docker compose up -d 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 callback de autorización en https://connect.example.com/oauth/callback. Guarda el client ID y el client secret.
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"Ese listado muestra el URI de redirección que el runtime espera para cada proveedor. Es la comprobación más rápida de que el origen se ha aplicado. Si todavía muestra localhost, el contenedor se está ejecutando con el valor anterior y el flujo OAuth fallará en el último paso.
Guarda las credenciales del 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 permisos y el proveedor devolverá el navegador a /oauth/callback. Allí, el runtime intercambia el código y guarda 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 API key simple omiten todo esto: PUT /api/connections/<service> con {"authType":"api_key","values":{"apiKey":"..."}} guarda 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 la API de administración genera.
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 incluye un token que empieza por oct_. Emita uno por agente y asígnele el nombre de ese agente, porque revocar un token que no puede identificar implica revocarlos todos. Después, el agente llama a las acciones mediante HTTP normal.
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 contenedor cuyo campo success tiene el valor true, con la carga útil del proveedor en data. El token de GitHub no aparece en ningún punto de esa respuesta. Para un cliente MCP, apúntelo a https://connect.example.com/mcp con la misma cabecera bearer, y la puerta de enlace ofrecerá 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. Ejecución de servidores MCP en un VPS cubre la parte del cliente de esa configuración.
Haga una comprobación más antes de darlo por terminado. Repita la llamada a la acción después de eliminar la cabecera authorization. La guía de inicio rápido del proyecto llama a /v1 sin ningún bearer, por lo que 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 los agentes. /oauth/callback debe ser accesible para el navegador que completa la autorización; no tiene que estar abierto a todo Internet.
Reduzca la lista de acciones a las que necesita el agente
Un gateway con mil proveedores detrás ofrece una superficie amplia a un modelo de lenguaje. La superficie aumenta en cuanto el modelo empieza a leer texto que no ha generado, porque una página devuelta por su propia instancia de SearXNG al responder a las búsquedas web del agente puede contener instrucciones dirigidas a cualquiera de las acciones que el agente tenga disponibles. La misma moderación que hace que un agente de programación aplique el cambio mínimo que funciona debe aplicarse a sus permisos: conceda las pocas acciones que el trabajo necesita realmente y ninguna más. Hay dos controles que reducen el alcance.
OOMOL_CONNECT_ALLOWED_ACTIONS acepta una lista de permitidos separada por comas y entiende service.* y *. OOMOL_CONNECT_BLOCKED_ACTIONS es la lista de denegados, 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. Esa es la diferencia entre un error y un incidente. Los tokens de ejecución tienen sus propias reglas de acciones además de las globales, y su lista allowedProxies está vacía inicialmente, por lo que POST /v1/proxy/:service se rechaza hasta que se conceda. Ese endpoint del proxy reenvía una solicitud sin modificar a un proveedor con sus credenciales adjuntas, así que déjelo vacío salvo que un agente concreto lo necesite.
OOMOL_CONNECT_ALLOW_PRIVATE_NETWORK tiene false de forma predeterminada. Esto impide que una conexión a un proveedor autohospedado apunte a una dirección privada, como el servicio de metadatos de la nube en 169.254.169.254, o a su base de datos en la misma red. Déjelo desactivado. Actívelo sólo para un proveedor que aloje usted mismo.
Realice una copia de seguridad del servidor que contiene todos los tokens
Hay dos elementos importantes, y cada uno es inútil sin el otro. La base de datos de /app/data/connect.sqlite dentro del volumen connector-data contiene las credenciales selladas. La clave de cifrado de .env las abre. 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 guardarse 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. Una copia realizada durante una escritura puede restaurar 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 más _connector-data. Por eso se incluye el primer comando: pegue el nombre real en el tercero. Envíe el archivo fuera del VPS con copias de seguridad de restic desde un VPS. restic lo cifra antes de transferirlo, porque ese archivo es el almacén de credenciales.
El entorno de ejecución conserva las ejecuciones 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 revisar 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 pasar una hora revisando 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.
Todas las llamadas /api devuelven 401. Falta la cabecera del token de administrador 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 plano. Esto ocurre cuando OOMOL_CONNECT_ENCRYPTION_KEY nunca llega al contenedor, porque el runtime almacena los registros de credenciales sin cifrar en lugar de negarse a iniciar. Compruébelo en su propia instalación: conecte un proveedor con una API key que pueda reconocer y busque después 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 esté 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 lo que 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 muestra un error que menciona una acción visible en el catálogo. El descubrimiento y la ejecución son procesos 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 la etiqueta de imagen a la nueva versión y, después, docker compose pull && docker compose up -d. Supervise docker compose logs -n 50 connector para comprobar que aparezca 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 servicio. Para revertir la actualización, restaure la etiqueta anterior. Esto funciona sólo porque la fijó.
FAQ
¿Necesito un dominio público para alojar Open Connector por mi cuenta?
Para los proveedores que usan una clave de API, no: basta con una puerta de enlace en 127.0.0.1. OAuth tampoco lo exige siempre: OpenConnector documenta el callback local de GitHub como http://localhost:3000/oauth/callback. El navegador que completa la autorización debe poder acceder a la URL de callback. Para esta implementación en un VPS, configure OOMOL_CONNECT_ORIGIN con su nombre de host https:// antes del primer arranque 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 intencionada, por lo que nadie que tenga la base de datos puede leerla, ni siquiera usted. La única opción es definir una clave nueva y volver a conectar todos los proveedores. Guarde la clave en un gestor de contraseñas y la base de datos dentro de 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 las llamadas a través de la puerta de enlace. El agente se autentica con un token 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 sólo la respuesta. Hay dos situaciones que rompen esta propiedad: el endpoint /v1/proxy/:service, que reenvía solicitudes sin modificar con su credencial incluida y cuyos permisos empiezan vacíos por un motivo, 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?
El navegador que completa la autorización debe poder acceder al callback de OAuth, pero no es necesario permitir el acceso desde todo Internet. Con Docker Engine 28.0.0 o posterior y la red bridge predeterminada, publique el puerto del contenedor en 127.0.0.1 para que el puerto publicado sólo sea accesible desde el host, y coloque el proxy inverso delante. Las versiones anteriores de Docker permitían que los hosts del mismo segmento L2 accedieran a los puertos publicados en localhost. 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 sólo funcionen las llamadas autenticadas.
¿Está Open Connector preparado para producción?
Las versiones actuales usan una licencia Apache 2.0 modificada con condiciones adicionales; las versiones hasta v1.9.4, incluida la versión fijada v1.3.3, siguen usando Apache 2.0. Un servicio de conectores alojado o gestionado cuyo valor principal sea la funcionalidad de OpenConnector requiere una licencia comercial de OOMOL conforme a la licencia vigente. Los comandos de instalación de v1.3.3 siguen siendo una instantánea del 1 August 2026, y esa versión se publicó el 30 July 2026. Ejecútela fijada a una etiqueta de versión, nunca en latest ni en tip, lea las notas de la versión antes de cada actualización y conserve una copia de seguridad de un volumen que haya restaurado al menos una vez. El diseño es sólido para un sistema que usted administra, y el riesgo está en la variación de versiones, no en la arquitectura.