Open Connector zelf hosten voor AI-agents
Host de Open Connector authenticatie-gateway op uw eigen VPS. Voorkom dat AI-agents SaaS-tokens beheren door gebruik te maken van TLS, OAuth callbacks en SQLite-backups.
Wat Open Connector doet voor een AI-agent
Het zelf hosten van Open Connector plaatst één authenticatie-gateway tussen uw AI-agents en elke software-as-a-service (SaaS) API die zij aanroepen, zodat de agent nooit een provider-token in beheer heeft. Het is een open-source gateway van OOMOL Lab, gelicentieerd onder Apache 2.0. Het draait als één container, houdt de status bij in één enkel SQLite-bestand en stelt provider-acties beschikbaar via HTTP en via MCP (model context protocol).
De problemen beginnen bij de tweede integratie. Elke provider heeft zijn eigen OAuth-flow (open authorization), zijn eigen levensduur voor refresh-tokens en zijn eigen scope-namen. Het handmatig koppelen van vijf providers aan een agent betekent vijf redirect-handlers, vijf credential-stores en vijf refresh-loops die moeten draaien voordat een token verloopt. Vrijwel niemand schrijft die code zelf. Men maakt één langdurig geldig personal access token per service aan en plakt dit in de agent-configuratie, een omgevingsbestand of de prompt zelf. Dat token is vervolgens leesbaar voor elke tool die de agent uitvoert en het belandt in het transcript, wat de fout is die het geheimhouden van gegevens in AI-agents beschrijft.
Een authenticatie-gateway splitst de inloggegevens in tweeën. De gateway slaat de provider-inloggegevens op en voert de OAuth-flow uit. De agent krijgt een runtime-token dat alleen geldig is voor de gateway. Wanneer de agent een actie aanroept, laadt de gateway de opgeslagen inloggegevens, injecteert deze aan de serverzijde in het uitgaande verzoek en retourneert alleen de antwoordtekst. De agent ontvangt nooit het provider-toegangstoken, waardoor een gelekt agent-transcript u slechts één intrekbaar runtime-token kost in plaats van uw volledige GitHub-account.
De catalogus adverteert met meer dan 1.000 providers en 10.000 vooraf gebouwde acties; dit is het cijfer van het project zelf en niet iets dat u van buitenaf kunt verifiëren. Wat u wel kunt verifiëren is de structuur: één HTTP-endpoint per actie, één opgeslagen verbinding per provider, één token per agent. Als de agent-kant hiervan nog nieuw is en termen als tool call of MCP-server nog niet zijn ingeburgerd, bouwt het stapsgewijze pad in hoe u AI-agents vanaf nul leert de loop, de tools en de veiligheidsgewoonten op waarvan een gateway zoals deze uitgaat dat u ze al beheerst.
Waarom Open Connector zelf hosten in plaats van een gehoste connector-service te gebruiken
Een gehoste connector-service voert hetzelfde werk uit en beheert de refresh tokens voor elke provider waarmee u verbinding maakt. Een refresh token voor Google of GitHub is een langdurige sleutel tot uw e-mail en repositories, die doorgaans blijft werken na een wachtwoordwijziging. Een inbreuk bij hen wordt daarmee uw inbreuk. Door zelf te hosten verplaatst u deze gegevens naar een SQLite-bestand op een machine die u huurt en beheert, beveiligd met een sleutel die uw server nooit verlaat.
Wees u bewust van de verantwoordelijkheid voordat u begint. Deze VPS wordt de meest waardevolle server die u beheert. Het bevat werkende inloggegevens voor een dozijn services in één bestand; behandel het daarom zoals u een host voor een wachtwoordmanager zou behandelen: een firewall die alleen poort 443 openstelt, geen gedeelde logins, een back-up die u daadwerkelijk een keer heeft teruggezet en een melding wanneer de server niet meer reageert. Als u uw wachtwoordkluis niet op deze machine zou plaatsen, doe dat dan ook niet met de connector.
Pin een versie voordat u iets installeert
Open Connector is nog jong. De repository verscheen voor het eerst op 29 juni 2026 en op 1 augustus 2026 is de nieuwste getagde release v1.3.3, gepubliceerd op 30 juli 2026 en tevens voorzien van de latest tag. De registry publiceert ook een tip tag, gebouwd op basis van de nieuwste commit op main.
Bij een project dat zo nieuw is, veranderen de bewegende tags vaak. Een docker compose pull die twee releases verspringt, kan een endpoint wijzigen waar uw agent afhankelijk van is, waardoor u de hele avond kwijt bent aan het debuggen van een vermeend agent-probleem. Pin de image vast op een release-tag en voer een upgrade uit wanneer u dat besluit, nadat u de release notes heeft gelezen.
Open Connector achter TLS implementeren op uw eigen VPS
Voordat de container start, heeft u het volgende nodig:
- Docker met de Compose-plugin, op Ubuntu 24.04 of een vergelijkbare distributie
- een hostnaam waarvan het A-record naar deze VPS wijst, bijvoorbeeld
connect.example.com - een reverse proxy die reeds TLS (transport layer security) voor die hostnaam afhandelt
- twee willekeurige geheimen, hieronder gegenereerd
De Traefik reverse proxy voor meerdere Docker Compose-applicaties behandelt de kant van de proxy. De volledige procedure voor certificaatbeheer voor een enkele applicatie staat in de handleiding n8n op een VPS met Docker en HTTPS.
Genereer eerst de geheimen. De encryptiesleutel verzegelt de opgeslagen inloggegevens. Het admin-token beveiligt de webconsole en het gehele /api-oppervlak. Geen van beide heeft een standaardwaarde, en de runtime start zonder problemen zonder deze waarden.
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 .envKopieer beide waarden nu naar uw wachtwoordmanager, vóór de eerste start. De encryptiesleutel heeft geen herstelmethode; de reden hiervoor staat in de onderstaande lijst met fouten.
Nu compose.yaml. Dit verschilt op twee punten van het upstream-voorbeeld, en beide zijn van belang.
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:De eerste wijziging is de vastgezette tag in plaats van latest. De tweede is de poort. Het upstream-bestand publiceert 3000:3000, wat bindt aan elke interface op de host. Docker schrijft zijn gepubliceerde poorten naar de NAT-tabel (network address translation) voordat de ufw-filterketen het pakket ooit ziet, waardoor ufw deny 3000 die poort niet sluit; dit is de valstrik die wordt beschreven in waarom Docker-poorten ufw omzeilen. Het schrijven van 127.0.0.1:3000:3000 publiceert alleen op de loopback-interface, en uw reverse proxy maakt verbinding vanaf dezelfde host.
De :? markeert elke variabele als verplicht, waardoor de stack weigert te starten wanneer .env ontbreekt, in plaats van te starten met onversleutelde inloggegevens. Het bewaren van de waarden in .env in plaats van in het compose-bestand is het patroon uit Docker Compose env-bestanden en secrets.
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 beantwoordt { "ok": true } zodra de runtime actief is. ss moet 127.0.0.1:3000 weergeven. Een regel met 0.0.0.0:3000 betekent dat de poorttoewijzing nog steeds de upstream-versie is, en de gateway direct antwoordt aan het hele internet. "Connection refused" bij de health check betekent dat de container nog niet luistert; lees dus de logs voordat u de proxy aanpast.
Traefik-labels voor dezelfde 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"Wanneer Traefik in Docker op dezelfde host draait, koppelt u deze service aan het Traefik-netwerk en verwijdert u het ports:-blok, omdat Traefik de container bereikt via het interne netwerk en er niets op de host gepubliceerd hoeft te worden. certresolver=le moet overeenkomen met de resolvernaam in uw statische Traefik-configuratie, anders start de router zonder certificaat.
Waarom OAuth een echte hostnaam vereist
OOMOL_CONNECT_ORIGIN is de instelling die vaak wordt overgeslagen. Het overslaan hiervan zorgt ervoor dat OAuth niet werkt, wat ten onrechte lijkt op een bug bij de provider. De runtime bouwt de redirect URI op basis van die origin, in de vorm <origin>/oauth/callback. Als deze niet is ingesteld, valt de origin terug op http://localhost:3000. Hierdoor stuurt de runtime een redirect URI van http://localhost:3000/oauth/callback naar de provider, terwijl uw OAuth-app https://connect.example.com/oauth/callback heeft geregistreerd. Omdat deze twee strings verschillen, antwoordt GitHub als volgt:
The redirect_uri MUST match the registered callback URL for this application.Een OAuth-provider stuurt een browser terug naar die URI. Dit betekent dat het een adres moet zijn dat bereikbaar is voor de buitenwereld. Providers weigeren een standaard http:// voor alles behalve localhost. Dit is de enige reden waarom deze implementatie een hostnaam en een certificaat vereist. Stel de origin in vóór de eerste start, aangezien de waarde bij het opstarten wordt ingelezen. Nadat u .env of compose.yaml heeft bewerkt, voert u docker compose up -d opnieuw uit om de wijzigingen toe te passen.
Verbind uw eerste provider via OAuth
Maak eerst de OAuth-app aan bij de provider. Op GitHub volgt u het pad Settings, vervolgens Developer settings, dan OAuth Apps en tot slot New OAuth App. Stel de authorization callback URL in op https://connect.example.com/oauth/callback. Bewaar de client ID en de client secret.
Elke /api-aanroep bevat het admin token, dus exporteer dit eenmalig voor de shell-sessie.
export ADMIN_TOKEN='paste-the-admin-token'
curl -s https://connect.example.com/api/oauth/configs \
-H "authorization: Bearer $ADMIN_TOKEN"Deze lijst toont de redirect URI die de runtime voor elke provider verwacht. Dit is de snelste manier om te controleren of uw wijziging aan de origin effect heeft gehad. Als er nog steeds localhost staat, draait de container met de oude waarde en zal de OAuth-flow bij de laatste stap falen.
Sla de client-inloggegevens op en start vervolgens een autorisatie.
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"}'De tweede aanroep retourneert een authorizationUrl. Open deze in een browser, keur de scopes goed en de provider stuurt de browser terug naar /oauth/callback, waar de runtime de code uitwisselt en de inloggegevens opslaat. De webconsole op uw origin doorloopt dezelfde stappen via een formulier, beveiligd met hetzelfde admin token. Providers die een eenvoudige API-sleutel gebruiken, slaan dit proces over: PUT /api/connections/<service> met {"authType":"api_key","values":{"apiKey":"..."}} slaat de sleutel direct op.
Geef elke agent een runtime token, nooit de inloggegevens
De agent authenticeert zich bij de gateway met een runtime token, dat door de admin API wordt aangemaakt.
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"}'Het antwoord bevat een token dat begint met oct_. Geef één token uit per agent en noem dit naar de betreffende agent; als u een token intrekt dat u niet kunt identificeren, moet u ze namelijk allemaal intrekken. De agent voert vervolgens acties uit via standaard HTTP.
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":{}}'Een correct antwoord is een envelop waarvan het success-veld true is, met de provider-payload onder data. Het GitHub-token staat nergens in dat antwoord. Voor een MCP-client wijst u naar https://connect.example.com/mcp met dezelfde bearer-header, en de gateway biedt dan discovery-tools zoals search_actions en execute_action in plaats van één tool per API, wat de toollijst van de agent beperkt houdt. MCP-servers draaien op een VPS behandelt de client-kant van deze configuratie.
Voer nog één controle uit voordat u dit als voltooid beschouwt. Herhaal de actie-aanroep terwijl de authorization-header is verwijderd. De quickstart van het project roept /v1 aan zonder enige bearer-header; een installatie zonder geconfigureerde runtime-authenticatie voert dus acties uit voor iedereen die de poort kan bereiken. Als uw niet-geauthenticeerde aanroep slaagt, heeft u twee opties: configureer runtime tokens en bevestig dat de anonieme aanroep nu faalt, of beperk /api, /v1 en /mcp bij de reverse proxy tot de adressen waar uw agents vandaan komen. Alleen /oauth/callback moet openblijven voor de wereld, omdat dit het enige pad is dat de browser-redirect van een provider nodig heeft.
Beperk de actielijst tot wat de agent nodig heeft
Een gateway met duizenden providers erachter vormt een groot aanvalsoppervlak voor een taalmodel. Dit oppervlak wordt groter zodra het model tekst leest die het niet zelf heeft geschreven, omdat een pagina die wordt geretourneerd door uw eigen SearXNG-instantie die de zoekopdrachten van de agent beantwoordt instructies kan bevatten die gericht zijn op de acties waarover de agent beschikt. Dezelfde terughoudendheid die ervoor zorgt dat een programmeer-agent de kleinste wijziging doorvoert die werkt is van toepassing op de rechten: verleen alleen de handvol acties die voor de taak noodzakelijk zijn, en niets meer. Twee instellingen beperken dit.
OOMOL_CONNECT_ALLOWED_ACTIONS accepteert een door komma's gescheiden allowlist en begrijpt service.* en *. OOMOL_CONNECT_BLOCKED_ACTIONS is de denylist, en de denylist heeft voorrang. Het instellen van de allowlist op github.get_current_user,github.list_issues betekent dat elke andere actie wordt geweigerd, ongeacht waar de agent om vraagt; dit is het verschil tussen een fout en een incident. Runtime-tokens hanteren hun eigen actieregels bovenop de globale regels, en hun allowedProxies-lijst is standaard leeg, waardoor POST /v1/proxy/:service wordt geweigerd totdat u dit expliciet toestaat. Dat proxy-eindpunt stuurt een onbewerkte aanvraag door naar een provider met uw inloggegevens bijgevoegd, dus laat dit leeg tenzij een specifieke agent het nodig heeft.
OOMOL_CONNECT_ALLOW_PRIVATE_NETWORK staat standaard op false, wat voorkomt dat een zelfgehoste providerverbinding verwijst naar een privèadres, zoals de cloud-metadataservice op 169.254.169.254 of uw database op hetzelfde netwerk. Laat dit uitgeschakeld. Schakel het alleen in voor een provider die u zelf host.
Maak een back-up van de box die alle tokens bevat
Twee zaken zijn van belang, en beide zijn nutteloos zonder de andere. De database op /app/data/connect.sqlite in het connector-data volume bevat de verzegelde inloggegevens. De encryptiesleutel in .env ontsleutelt deze. Een volumeback-up zonder de sleutel herstelt niets, en de sleutel zonder het volume herstelt eveneens niets. Bewaar de sleutel daarom in uw wachtwoordmanager en neem het volume op in uw reguliere back-uprotatie.
Stop de container terwijl u het SQLite-bestand kopieert, omdat een kopie die tijdens een schrijfactie wordt gemaakt, kan resulteren in een corrupte database bij herstel.
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 connectorDe volumenaam is uw projectmap plus _connector-data. Daarom staat het eerste commando daar: plak de werkelijke naam in het derde commando. Verstuur het archief vanaf de VPS met restic backups from a VPS, wat het archief versleutelt voordat het de server verlaat, aangezien dit archief de opslagplaats voor inloggegevens is.
De runtime bewaart recente actie-uitvoeringen als auditrecords, standaard 5.000 stuks, zodat de console kan aangeven welke agent wat en wanneer heeft uitgevoerd. Dat logboek is het eerste wat u moet raadplegen wanneer een agent zich vreemd gedraagt. Koppel ook an Uptime Kuma status page aan https://connect.example.com/health. Wanneer de gateway niet meer reageert, falen agents op verwarrende wijze. Weten dat de gateway offline is, bespaart u een uur aan het lezen van agent-output.
Wat er misgaat en de foutmeldingen die u zult zien
redirect_uri_mismatch bij de provider. De oorsprong en de geregistreerde callback-URL komen niet overeen. Vergelijk de exacte tekenreeks uit /api/oauth/configs met de applicatie-instellingen van de provider, inclusief https tegenover http en eventuele afsluitende slashes.
Elke /api-aanroep geeft een 401-fout. De header voor het admin-token ontbreekt of is onjuist gespeld. De header is Authorization: Bearer <token> en de webconsole vraagt om hetzelfde token.
De container draait en de inloggegevens staan in platte tekst. Dit gebeurt wanneer OOMOL_CONNECT_ENCRYPTION_KEY de container nooit bereikt, omdat de runtime inloggegevens onversleuteld opslaat in plaats van te weigeren op te starten. Controleer dit op uw eigen installatie: verbind een provider met een API-sleutel die u kunt herkennen en doorzoek vervolgens de database hierop.
docker compose cp connector:/app/data/connect.sqlite /tmp/connect.sqlite
grep -c 'github_pat_' /tmp/connect.sqlite
shred -u /tmp/connect.sqliteEen resultaat hoger dan 0 betekent dat de sleutel niet actief is. Controleer of .env zich in dezelfde map bevindt als compose.yaml en of docker compose config de waarde toont. Als de sleutel correct is ingesteld, geeft dezelfde zoekopdracht 0 resultaten, omdat het record is verzegeld met AES-256-GCM (Advanced Encryption Standard, 256-bit sleutel, Galois/Counter Mode).
Niets wordt ontsleuteld na een herstel. De encryptiesleutel is gewijzigd of verloren gegaan. Deze wordt volgens het ontwerp nooit naast de data opgeslagen, dus er is geen herstelpad en geen supportticket dat kan helpen. Verbind alle providers opnieuw. Rotatie wordt ondersteund via een afzonderlijke sleutelvariabele en een datacommando in de runtime; lees daarom de huidige release notes voordat u iets roteert.
De agent krijgt een foutmelding over een actie die in de catalogus staat. Ontdekking en uitvoering zijn gescheiden. Een actie kan voorkomen in search_actions en alsnog worden geweigerd door OOMOL_CONNECT_ALLOWED_ACTIONS, door de denylist of door de specifieke regels van dat runtime-token.
Upgrades. Maak een back-up van het volume, wijzig de image-tag naar de nieuwe release en voer daarna docker compose pull && docker compose up -d uit. Monitor docker compose logs -n 50 connector voor een migratieregel en voer de health check en één echte actie uit voordat u het systeem weer vertrouwt. Rollen naar een vorige versie betekent de oude tag terugplaatsen; dit werkt alleen als u de versie heeft vastgezet (pinned).
FAQ
Heb ik een publiek domein nodig om Open Connector zelf te hosten?
Voor providers die een API key gebruiken niet: een gateway op 127.0.0.1 volstaat. Voor OAuth is dit in de praktijk wel vereist. De provider stuurt een browser door naar uw callback URL, dus die URL moet vanaf het publieke internet kunnen worden opgelost. Bovendien weigeren providers doorgaans een platte http:// buiten localhost. Stel OOMOL_CONNECT_ORIGIN in op uw https:// hostnaam vóór de eerste start en registreer <origin>/oauth/callback in de OAuth-applicatie van de provider.
Wat gebeurt er als ik de encryptiesleutel van Open Connector verlies?
De opgeslagen inloggegevens kunnen niet meer worden ontsleuteld en er is geen herstelmethode. De sleutel wordt bewust nooit samen met de data opgeslagen, zodat niemand die de database in handen krijgt deze kan lezen, inclusief uzelf. Uw enige optie is een nieuwe sleutel instellen en elke provider opnieuw koppelen. Bewaar de sleutel in een wachtwoordmanager en de database in uw back-uprotatie, aangezien een restore beide vereist.
Kan mijn AI-agent het toegangstoken van de provider inzien?
Niet wanneer deze via de gateway aanroept. De agent authenticeert met een runtime token dat begint met oct_, en de gateway injecteert de inloggegevens van de provider in het uitgaande verzoek op de server, waarbij alleen het antwoord wordt geretourneerd. Twee zaken doorbreken dit principe: het /v1/proxy/:service eindpunt, dat onbewerkte verzoeken doorstuurt met uw inloggegevens (en waarvan de rechten niet voor niets standaard leeg zijn), en het zelf plakken van een API key in de agent, waardoor de gateway volledig wordt omzeild.
Moet de gateway bereikbaar zijn vanaf het publieke internet?
Alleen /oauth/callback hoeft dat te zijn. Publiceer de containerpoort op 127.0.0.1 zodat de NAT-regels van Docker deze niet voorbij uw firewall kunnen blootstellen, en plaats de reverse proxy ervoor. Test vervolgens één actie-aanroep zonder authorization header. Als dit slaagt, beperk dan /api, /v1 en /mcp bij de proxy tot de adressen die uw agents gebruiken, totdat alleen geauthenticeerde aanroepen nog werken.
Is Open Connector klaar voor productiegebruik?
Het is gelicentieerd onder Apache 2.0 en ontwikkelt zich snel: de repository verscheen op 29 juni 2026 en v1.3.3 werd uitgebracht op 30 juli 2026. Beschouw elk versienummer in deze handleiding daarom als een momentopname van 1 augustus 2026. Draai de software vastgepind op een release tag, nooit op latest of tip, lees de release notes vóór elke upgrade en behoud een volume-back-up die u minimaal één keer succesvol heeft teruggezet. Het ontwerp is solide voor een server die u in eigen beheer heeft; het risico zit in de snelheid van de updates, niet in de architectuur.