SSD Nodes Learn 8GB de RAM — $66/an
Guides Matt ConnorPar Matt Connor · Mis à jour le 2026-08-02

Auto-héberger Open Connector pour vos agents IA

Déployez Open Connector sur votre VPS pour isoler vos agents des tokens SaaS, avec image épinglée, TLS, callbacks OAuth et sauvegardes SQLite.

Ce que fait Open Connector pour un agent IA

L'auto-hébergement d'Open Connector place une passerelle d'authentification entre vos agents IA et chaque API de software as a service (SaaS) qu'ils appellent. L'agent ne détient donc jamais de token de fournisseur. Il s'agit d'une passerelle open source développée par OOMOL Lab et distribuée sous licence Apache 2.0. Elle s'exécute dans un seul conteneur, conserve son état dans un fichier SQLite unique et expose les actions des fournisseurs via HTTP et MCP (model context protocol).

Les difficultés commencent dès la deuxième intégration. Chaque fournisseur possède son propre flux OAuth (open authorization), sa propre durée de validité des refresh tokens et ses propres noms de scopes. Connecter manuellement cinq fournisseurs à un agent signifie écrire cinq redirect handlers, cinq credential stores et cinq refresh loops qui doivent s'exécuter avant l'expiration d'un token. Presque personne n'écrit ce code. À la place, les utilisateurs créent un personal access token à longue durée par service et le copient dans la configuration de l'agent, un fichier d'environnement ou le prompt lui-même. Chaque outil exécuté par l'agent peut alors lire ce token. Il se retrouve aussi dans la transcription, ce que décrit la protection des secrets dans les agents IA.

Une passerelle d'authentification sépare le credential en deux. La passerelle stocke le credential du fournisseur et exécute le flux OAuth. L'agent reçoit un runtime token valide uniquement auprès de la passerelle. Lorsque l'agent appelle une action, la passerelle charge le credential stocké, l'injecte côté serveur dans la requête sortante et renvoie uniquement le corps de la réponse. L'agent ne reçoit jamais l'access token du fournisseur. Une transcription d'agent divulguée vous coûte donc un seul runtime token révocable, et non votre compte GitHub.

Le catalogue annonce plus de 1,000 fournisseurs et 10,000 actions prédéfinies. Ces chiffres viennent du projet lui-même et vous ne pouvez pas les vérifier de l'extérieur. Ce que vous pouvez vérifier, c'est la structure : un endpoint HTTP par action, une connexion stockée par fournisseur et un token par agent.

Pourquoi auto-héberger Open Connector au lieu d’utiliser un service de connecteur hébergé

Un service de connecteur hébergé effectue le même travail et conserve les refresh tokens de chaque provider que vous lui connectez. Un refresh token Google ou GitHub est une clé longue durée donnant accès à vos e-mails et à vos dépôts. Il reste généralement valide après une modification du mot de passe. Si ce service est compromis, vous l’êtes aussi. L’auto-hébergement déplace ces données dans SQLite, sur une machine que vous louez et administrez. Elles sont protégées par une clé qui ne quitte jamais votre serveur.

Évaluez clairement le coût avant de commencer. Ce VPS devient le serveur le plus sensible que vous administrez. Il contient, dans un seul fichier, des identifiants actifs pour une douzaine de services. Vous devez donc le traiter comme un serveur hébergeant un gestionnaire de mots de passe : un pare-feu qui n’expose que le port 443, aucun compte partagé, une sauvegarde que vous avez réellement restaurée au moins une fois et une alerte lorsqu’il ne répond plus. Si vous n’hébergeriez pas votre coffre de mots de passe sur cette machine, n’y hébergez pas non plus le connecteur.

Épinglez une version avant toute installation

Open Connector est récent. Le dépôt est apparu pour la première fois le 29 juin 2026. Au 1 août 2026, la version la plus récente identifiée par un tag est v1.3.3, publiée le 30 juillet 2026 et portant également le tag latest. Le registry publie aussi un tag tip, généré à partir du commit le plus récent sur main.

Sur un projet aussi récent, les tags mobiles changent souvent. Un docker compose pull qui avance de deux versions peut modifier un endpoint dont dépend votre agent. Vous passerez alors la soirée à chercher un problème dans l’agent. Épinglez l’image sur un tag de version. Effectuez la mise à niveau quand vous le décidez, après avoir lu les notes de version.

Déployer Open Connector derrière TLS sur votre propre VPS

Avant de démarrer le conteneur, vous avez besoin des éléments suivants :

  • Docker avec le plugin Compose, sur Ubuntu 24.04 ou une version proche
  • un hostname dont l’enregistrement A pointe vers ce VPS, par exemple connect.example.com
  • un reverse proxy qui termine déjà TLS (Transport Layer Security) pour ce hostname
  • deux secrets aléatoires, générés ci-dessous

Le guide Reverse proxy Traefik pour plusieurs applications Docker Compose couvre la configuration du proxy. La configuration complète des certificats, du début à la fin pour une seule application, se trouve dans le guide n8n sur un VPS avec Docker et HTTPS.

Générez d’abord les secrets. La clé de chiffrement protège les identifiants stockés. Le token d’administration protège la console web et toute la surface /api. Aucun des deux n’a de valeur par défaut, et le runtime démarre sans problème s’ils sont absents.

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 .env

Copiez maintenant les deux valeurs dans votre gestionnaire de mots de passe, avant le premier démarrage. Il n’existe aucune procédure de récupération pour la clé de chiffrement. La liste des échecs plus loin explique pourquoi.

Créez maintenant compose.yaml. Il diffère de l’exemple upstream sur deux points, et ces deux points sont importants.

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:

Le premier changement est le tag épinglé à la place de latest. Le second concerne le port. Le fichier upstream publie 3000:3000, ce qui lie le port à toutes les interfaces de l’hôte. Docker inscrit les ports publiés dans la table NAT (Network Address Translation) avant que le paquet n’atteigne la chaîne de filtrage ufw. Par conséquent, ufw deny 3000 ne ferme pas ce port. C’est le piège décrit dans pourquoi les ports Docker contournent ufw. L’écriture de 127.0.0.1:3000:3000 publie le port sur l’interface loopback uniquement, et votre reverse proxy se connecte depuis le même hôte.

:? indique que chaque variable est obligatoire. La stack refuse donc de démarrer si .env est absent, au lieu de démarrer avec des identifiants non chiffrés. Conserver les valeurs dans .env plutôt que dans le fichier Compose est la méthode décrite dans les fichiers d’environnement et les secrets 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 répond { "ok": true } une fois le runtime démarré. ss doit afficher 127.0.0.1:3000. Une ligne contenant 0.0.0.0:3000 indique que le mapping de port est toujours celui de l’upstream et que la gateway répond directement à l’ensemble d’Internet. Une erreur « connection refused » lors du health check signifie que le conteneur n’écoute pas encore. Consultez donc les logs avant de modifier le proxy.

Libellés Traefik pour le même service
    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"

Lorsque Traefik s’exécute dans Docker sur le même hôte, connectez ce service au réseau Traefik et supprimez le bloc ports:. Traefik atteint alors le conteneur via le réseau interne et aucun élément ne doit être publié sur l’hôte. certresolver=le doit correspondre au nom du resolver dans votre configuration statique Traefik. Sinon, le router démarre sans certificat.

Pourquoi OAuth vous oblige à utiliser un vrai nom d’hôte

OOMOL_CONNECT_ORIGIN est le paramètre que l’on oublie souvent. Cet oubli fait échouer OAuth d’une manière qui ressemble à un bug du fournisseur. Le runtime construit son URI de redirection à partir de cette origine, sous la forme <origin>/oauth/callback. Si elle n’est pas définie, l’origine prend par défaut la valeur http://localhost:3000. Le runtime envoie donc au fournisseur l’URI de redirection http://localhost:3000/oauth/callback, alors que votre application OAuth a enregistré https://connect.example.com/oauth/callback. Les deux chaînes diffèrent. GitHub répond donc :

The redirect_uri MUST match the registered callback URL for this application.

Un fournisseur OAuth redirige le navigateur vers cette URI. Elle doit donc être accessible depuis l’extérieur. Les fournisseurs refusent également le protocole http:// en dehors de localhost. C’est la seule raison pour laquelle ce déploiement nécessite un nom d’hôte et un certificat. Définissez l’origine avant le premier démarrage, car sa valeur est lue au démarrage. Après avoir modifié .env ou compose.yaml, exécutez de nouveau docker compose up -d pour appliquer la modification.

Connecter votre premier fournisseur via OAuth

Créez d’abord l’application OAuth chez le fournisseur. Sur GitHub, accédez à Settings, puis Developer settings, puis OAuth Apps, puis New OAuth App. Définissez l’URL de callback d’autorisation sur https://connect.example.com/oauth/callback. Conservez le client ID et le client secret.

Chaque appel /api transmet le token d’administration. Exportez-le donc une seule fois pour la session shell.

export ADMIN_TOKEN='paste-the-admin-token'
curl -s https://connect.example.com/api/oauth/configs \
  -H "authorization: Bearer $ADMIN_TOKEN"

Cette liste affiche l’URI de redirection attendue par le runtime pour chaque fournisseur. C’est le moyen le plus rapide de vérifier que votre origin a bien été prise en compte. Si la valeur affichée est toujours localhost, le conteneur utilise l’ancienne valeur et le flux OAuth échouera à la dernière étape.

Enregistrez les identifiants client, puis démarrez une autorisation.

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"}'

Le deuxième appel renvoie une authorizationUrl. Ouvrez-la dans un navigateur, approuvez les scopes, puis le fournisseur renvoie le navigateur vers /oauth/callback. Le runtime échange alors le code et stocke l’identifiant. La console web sur votre origin guide les mêmes étapes avec un formulaire, derrière le même token d’administration. Les fournisseurs qui utilisent une simple clé API ignorent toutes ces étapes : PUT /api/connections/<service> avec {"authType":"api_key","values":{"apiKey":"..."}} stocke directement la clé.

Attribuez à chaque agent un jeton d’exécution, jamais l’identifiant d’authentification

L’agent s’authentifie auprès de la passerelle avec un jeton d’exécution généré par l’API d’administration.

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 réponse contient un jeton commençant par oct_. Attribuez-en un à chaque agent et nommez-le d’après cet agent, car révoquer un jeton que vous ne pouvez pas identifier revient à tous les révoquer. L’agent appelle ensuite les actions via HTTP standard.

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":{}}'

Une réponse correcte est une enveloppe dont le champ success vaut true, avec la charge utile du fournisseur dans data. Le jeton GitHub n’apparaît nulle part dans cette réponse. Pour un client MCP, configurez-le avec https://connect.example.com/mcp et le même en-tête bearer. La passerelle fournit alors des outils de découverte tels que search_actions et execute_action, au lieu d’un outil par API, ce qui limite la taille de la liste d’outils de l’agent. Exécuter des serveurs MCP sur un VPS couvre la partie client de cette configuration.

Effectuez encore une vérification avant de considérer la configuration comme terminée. Répétez l’appel d’action après avoir supprimé l’en-tête authorization. Le guide de démarrage rapide du projet appelle /v1 sans aucun bearer. Une installation sans authentification d’exécution configurée exécutera donc les actions pour toute personne pouvant atteindre le port. Si votre appel non authentifié réussit, deux solutions sont possibles : configurez les jetons d’exécution et vérifiez que l’appel anonyme échoue désormais, ou restreignez /api, /v1 et /mcp au niveau du reverse proxy aux adresses utilisées par vos agents. Seul /oauth/callback doit rester ouvert au monde entier, car il s’agit de l’unique chemin dont la redirection du navigateur d’un fournisseur a besoin.

Réduire la liste des actions à ce dont l’agent a besoin

Une gateway qui donne accès à un millier de providers offre une surface trop large à un modèle de langage. Deux contrôles permettent de la réduire.

OOMOL_CONNECT_ALLOWED_ACTIONS accepte une allowlist séparée par des virgules et comprend service.* et *. OOMOL_CONNECT_BLOCKED_ACTIONS est la denylist, et la denylist est prioritaire. Définir l’allowlist sur github.get_current_user,github.list_issues signifie que toutes les autres actions sont refusées, quelles que soient les actions demandées par l’agent. C’est ce qui fait la différence entre une erreur et un incident. Les runtime tokens ont leurs propres règles d’action, en plus des règles globales. Leur liste allowedProxies est vide par défaut. POST /v1/proxy/:service est donc refusée tant que vous ne l’avez pas autorisée. Cet endpoint de proxy transmet une requête brute à un provider avec vos credentials. Laissez-le donc vide, sauf si un agent précis en a besoin.

OOMOL_CONNECT_ALLOW_PRIVATE_NETWORK vaut false par défaut. Cela empêche une connexion à un provider auto-hébergé de pointer vers une adresse privée, comme le service de métadonnées cloud sur 169.254.169.254 ou votre base de données sur le même réseau. Laissez cette option désactivée. Activez-la uniquement pour un provider que vous hébergez vous-même.

Sauvegarder le serveur qui contient tous les tokens

Deux éléments sont importants, et chacun est inutilisable sans l’autre. La base de données située dans /app/data/connect.sqlite, à l’intérieur du volume connector-data, contient les identifiants scellés. La clé de chiffrement située dans .env permet de les désceller. Une sauvegarde du volume sans la clé ne permet aucune restauration, et la clé sans le volume ne permet aucune restauration non plus. La clé doit donc être stockée dans votre gestionnaire de mots de passe, et le volume doit être inclus dans votre rotation normale de sauvegardes.

Arrêtez le conteneur pendant la copie du fichier SQLite. Une copie effectuée pendant une écriture peut restaurer une base de données corrompue.

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 connector

Le nom du volume correspond à votre répertoire de projet suivi de _connector-data. C’est pourquoi la première commande est présente : collez le nom réel dans la troisième. Envoyez l’archive hors du VPS avec des sauvegardes restic depuis un VPS, qui la chiffre avant son transfert, car cette archive contient le magasin d’identifiants.

Le runtime conserve les exécutions récentes sous forme d’enregistrements d’audit, 5,000 par défaut. La console peut ainsi indiquer quel agent a exécuté quelle action et à quel moment. Consultez d’abord ce journal lorsqu’un agent se comporte de manière inhabituelle. Configurez également une page d’état Uptime Kuma pour surveiller https://connect.example.com/health. Lorsque la gateway ne répond plus, les agents échouent de manière difficile à diagnostiquer. Savoir que la gateway est hors service évite de passer une heure à lire la sortie des agents.

Ce qui peut échouer et le message affiché

redirect_uri_mismatch chez le fournisseur. L’origine et l’URL de callback enregistrée diffèrent. Comparez la chaîne exacte de /api/oauth/configs avec les paramètres de l’application chez le fournisseur, notamment https avec http et avec tout slash final.

Chaque appel /api renvoie 401. L’en-tête contenant le token d’administration est absent ou mal orthographié. Cet en-tête est Authorization: Bearer <token>, et la console web demande le même token.

Le conteneur s’exécute et les identifiants sont stockés en clair. Cela se produit lorsque OOMOL_CONNECT_ENCRYPTION_KEY n’atteint jamais le conteneur, car le runtime stocke les enregistrements d’identifiants sans chiffrement au lieu de refuser de démarrer. Vérifiez-le sur votre propre installation : connectez un fournisseur avec une clé API que vous pouvez reconnaître, puis recherchez cette clé dans la base de données.

docker compose cp connector:/app/data/connect.sqlite /tmp/connect.sqlite
grep -c 'github_pat_' /tmp/connect.sqlite
shred -u /tmp/connect.sqlite

Un nombre supérieur à 0 signifie que la clé n’est pas appliquée. Vérifiez donc que .env se trouve dans le même répertoire que compose.yaml et que docker compose config affiche la valeur. Une fois la clé définie, la même recherche renvoie 0, car l’enregistrement est chiffré avec AES-256-GCM (Advanced Encryption Standard, clé de 256 bits, mode Galois/counter).

Rien ne peut être déchiffré après une restauration. La clé de chiffrement a changé ou a été perdue. Elle n’est volontairement jamais écrite à côté des données. Il n’existe donc aucun moyen de récupération et aucun ticket de support ne peut résoudre le problème. Reconnectez chaque fournisseur. La rotation est prise en charge avec une variable de clé distincte et une commande de données dans le runtime. Consultez donc les notes de version actuelles avant toute rotation.

L’agent renvoie une erreur concernant une action visible dans le catalogue. La découverte et l’exécution sont distinctes. Une action peut apparaître dans search_actions et être refusée par OOMOL_CONNECT_ALLOWED_ACTIONS, par la denylist ou par les propres règles du token du runtime.

Mises à niveau. Sauvegardez le volume, modifiez le tag de l’image pour utiliser la nouvelle release, puis docker compose pull && docker compose up -d. Surveillez docker compose logs -n 50 connector pour repérer une ligne de migration, puis relancez le health check et une action réelle avant de considérer le système comme opérationnel. Pour revenir à la version précédente, remettez l’ancien tag. Cela fonctionne uniquement parce que vous l’avez épinglé.

FAQ

Ai-je besoin d’un domaine public pour auto-héberger Open Connector ?

Pour les fournisseurs qui utilisent une clé d’API, non : une gateway sur 127.0.0.1 suffit. Pour OAuth, oui en pratique. Le fournisseur redirige un navigateur vers votre URL de callback. Cette URL doit donc être résolue depuis l’Internet public. Les fournisseurs refusent les URL simples en http:// en dehors de localhost. Définissez OOMOL_CONNECT_ORIGIN sur votre nom d’hôte https:// avant le premier démarrage, puis enregistrez <origin>/oauth/callback dans l’application OAuth du fournisseur.

Que se passe-t-il si je perds la clé de chiffrement d’Open Connector ?

Les identifiants enregistrés ne peuvent plus être déchiffrés. Il n’existe aucune récupération possible. La clé n’est volontairement jamais stockée avec les données. Personne qui possède la base de données ne peut donc la lire, pas même vous. Votre seule option consiste à définir une nouvelle clé et à reconnecter chaque fournisseur. Conservez la clé dans un gestionnaire de mots de passe et la base de données dans votre rotation de sauvegardes. Une restauration nécessite les deux.

Mon agent IA peut-il voir le token d’accès du fournisseur ?

Pas lorsqu’il passe par la gateway. L’agent s’authentifie avec un token d’exécution commençant par oct_. La gateway injecte l’identifiant du fournisseur dans la requête sortante sur le serveur, puis renvoie uniquement la réponse. Deux situations rompent cette isolation : le endpoint /v1/proxy/:service, qui transmet les requêtes brutes avec votre identifiant et dont les droits sont volontairement vides au départ, et le fait de coller vous-même une clé d’API dans l’agent, ce qui contourne entièrement la gateway.

La gateway doit-elle être accessible depuis l’Internet public ?

Seul /oauth/callback doit l’être. Publiez le port du conteneur sur 127.0.0.1 afin que les règles NAT de Docker ne puissent pas l’exposer au-delà de votre firewall, puis placez le reverse proxy devant. Testez ensuite un appel d’action sans en-tête authorization. S’il réussit, restreignez /api, /v1 et /mcp au niveau du proxy aux adresses utilisées par vos agents, jusqu’à ce que seuls les appels authentifiés fonctionnent.

Open Connector est-il prêt pour la production ?

Il est distribué sous licence Apache 2.0 et son développement avance rapidement : le dépôt est apparu le 29 June 2026 et la version v1.3.3 est sortie le 30 July 2026. Considérez donc chaque numéro de version de ce guide comme un état au 1 August 2026. Exécutez-le en le verrouillant sur un release tag, jamais sur latest ou tip. Lisez les release notes avant chaque mise à niveau et conservez une sauvegarde du volume que vous avez déjà restaurée une fois. La conception est fiable pour une machine que vous contrôlez. Le risque vient de l’évolution rapide des versions, pas de l’architecture.