SSD Nodes Learn 8GB RAM — $66/taon
Mga Gabay Matt ConnorNi Matt Connor · Na-update 2026-08-02

Self-host ang Open Connector para sa AI agents

Patakbuhin sa sariling VPS ang Open Connector auth gateway para hindi humawak ng SaaS token ang agents, gamit ang pinned image, TLS origin, OAuth callbacks, at backups.

Open Connector para sa isang AI agent

Ang self-hosting ng Open Connector ay naglalagay ng isang auth gateway sa pagitan ng iyong mga AI agent at ng bawat software as a service (SaaS) API na tinatawag nila. Dahil dito, hindi kailanman humahawak ang agent ng provider token. Isa itong open source gateway mula sa OOMOL Lab at lisensyado sa ilalim ng Apache 2.0. Tumatakbo ito bilang isang container, iniimbak ang state nito sa isang SQLite file, at inilalantad ang mga action ng provider sa HTTP at sa MCP (model context protocol).

Nagsisimula ang problema sa ikalawang integration. May sariling OAuth (open authorization) flow ang bawat provider, sariling tagal ng bisa ng refresh token, at sariling pangalan ng scope. Ang manu-manong pag-wire ng limang provider sa isang agent ay nangangailangan ng limang redirect handler, limang credential store, at limang refresh loop na kailangang tumakbo bago mag-expire ang token. Halos walang nagsusulat ng code na iyon. Sa halip, gumagawa sila ng tig-isang matagalang personal access token para sa bawat serbisyo at inilalagay ito sa agent config, environment file, o mismong prompt. Nababasa ang token na iyon ng bawat tool na pinapatakbo ng agent, at napupunta rin ito sa transcript. Ito ang problemang inilalarawan ng pag-iwas na mailantad ang mga secret sa AI agents.

Hinahati ng auth gateway sa dalawa ang credential. Iniimbak ng gateway ang credential ng provider at pinapatakbo nito ang OAuth flow. Nakakakuha ang agent ng runtime token na valid lamang laban sa gateway. Kapag tumawag ang agent ng isang action, nilo-load ng gateway ang nakaimbak na credential, ini-inject ito sa outbound request sa server side, at ibinabalik lamang ang response body. Hindi kailanman natatanggap ng agent ang provider access token. Kaya kapag na-leak ang transcript ng agent, isang nare-revoke na runtime token lamang ang kailangang palitan sa halip na ang iyong GitHub account.

Ipinapakita ng catalog ang mahigit 1,000 provider at 10,000 prebuilt action. Sariling bilang ito ng proyekto at hindi mo mabe-verify mula sa labas. Ang mabe-verify mo ay ang istruktura: isang HTTP endpoint para sa bawat action, isang nakaimbak na connection para sa bawat provider, at isang token para sa bawat agent.

Bakit mag-self-host ng Open Connector sa halip na gumamit ng hosted connector service

Pareho ang ginagawa ng hosted connector service, at iniimbak nito ang refresh token para sa bawat provider na ikinokonekta mo rito. Ang refresh token para sa Google o GitHub ay isang pangmatagalang cryptographic key para sa iyong mail at repositories, at karaniwan itong nananatiling valid kahit magpalit ka ng password. Kapag na-breach sila, breach din ito sa iyo. Sa self-hosting, inililipat ang mga record na iyon sa SQLite sa isang machine na inuupahan at ina-administer mo, at pinoprotektahan ito ng key na hindi kailanman umaalis sa iyong machine.

Banggitin muna nang malinaw ang gastos bago ka magsimula. Ang VPS na ito ang magiging pinakamahalagang server na pinapatakbo mo. Naglalaman ito ng aktibong credentials para sa isang dosenang service sa iisang file, kaya dapat itong pangasiwaan tulad ng isang password manager host: firewall na 443 lang ang inilalantad, walang shared login, backup na aktuwal mong na-restore kahit isang beses, at alert kapag hindi na ito sumasagot. Kung hindi mo ilalagay ang iyong password vault sa machine na ito, huwag mo ring ilagay dito ang connector.

Mag-pin ng version bago mag-install ng anuman

Bago pa ang Open Connector. Unang lumitaw ang repository noong 29 June 2026. Noong 1 August 2026, ang pinakabagong tagged release ay v1.3.3, na inilabas noong 30 July 2026 at may tag na latest. Naglalabas din ang registry ng tag na tip, na binuo mula sa pinakabagong commit sa main.

Sa bagong project na ganito, madalas magbago ang mga moving tag. Maaaring magbago ang isang docker compose pull na lumaktaw ng dalawang release sa endpoint na kailangan ng iyong agent. Dahil dito, maaari mong gugulin ang buong gabi sa pag-debug at mapagkamalang problema ito ng agent. I-pin ang image sa isang release tag. Mag-upgrade lamang kapag napagpasyahan mo na, pagkatapos basahin ang release notes.

I-deploy ang Open Connector sa likod ng TLS sa sarili mong VPS

Bago magsimula ang container, kailangan mo ng:

  • Docker na may Compose plugin, sa Ubuntu 24.04 o katulad na bersyon
  • isang hostname na ang A record ay nakaturo sa VPS na ito, halimbawa connect.example.com
  • isang reverse proxy na nagte-terminate na ng TLS (transport layer security) para sa hostname na iyon
  • dalawang random secret na bubuuin sa ibaba

Sinasaklaw ng Traefik reverse proxy para sa maraming Docker Compose app ang bahagi ng proxy. Makikita naman sa gabay na n8n sa VPS gamit ang Docker at HTTPS ang buong certificate setup, mula simula hanggang dulo, para sa isang app.

Buuin muna ang mga secret. Pinoprotektahan ng encryption key ang nakaimbak na credentials. Pinoprotektahan naman ng admin token ang web console at ang buong /api surface. Walang default ang alinman sa mga ito, at maayos na nagsisimula ang runtime kahit wala ang mga ito.

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

I-copy ang dalawang value sa iyong password manager ngayon, bago ang unang start. Walang recovery path ang encryption key, at ipinaliliwanag ang dahilan sa failure list sa ibaba.

Ngayon, compose.yaml. Naiiba ito sa upstream example sa dalawang bahagi, at parehong mahalaga ang mga ito.

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:

Ang unang pagbabago ay ang naka-pin na tag sa halip na latest. Ang ikalawa ay ang port. Ipinopublish ng upstream file ang 3000:3000, na nagbi-bind sa bawat interface ng host. Isinusulat ng Docker ang mga published port nito sa NAT (network address translation) table bago pa makita ng ufw filter chain ang packet, kaya hindi isinasara ng ufw deny 3000 ang port na iyon; ito ang trap na inilalarawan sa kung bakit nilalampasan ng Docker ports ang ufw. Sa paggamit ng 127.0.0.1:3000:3000, sa loopback interface lamang nagpa-publish, at kumokonekta ang reverse proxy mula sa parehong host.

Minamarkahan ng :? ang bawat variable bilang required, kaya tumatangging mag-start ang stack kapag nawawala ang .env sa halip na magsimula na hindi naka-encrypt ang credentials. Ang pagpapanatili ng mga value sa .env sa halip na sa compose file ang pattern mula sa Docker Compose env files at 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

Sinasagot ng /health ang { "ok": true } kapag umaandar na ang runtime. Kailangang mag-print ang ss ng 127.0.0.1:3000. Ang linyang 0.0.0.0:3000 ay nangangahulugang upstream pa rin ang port mapping, at direktang sumasagot ang gateway sa buong internet. Ang connection refused sa health check ay nangangahulugang hindi pa nakikinig ang container, kaya basahin muna ang logs bago galawin ang proxy.

Mga Traefik label para sa parehong 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"

Kapag tumatakbo ang Traefik sa Docker sa parehong host, ikonekta ang service na ito sa Traefik network at tanggalin ang ports: block, dahil ina-access ng Traefik ang container sa internal network at walang kailangang i-publish sa host. Kailangang tumugma ang certresolver=le sa resolver name sa iyong Traefik static config; kung hindi, umaandar ang router nang walang certificate.

Bakit kailangang may totoong hostname ang OAuth

OOMOL_CONNECT_ORIGIN ang setting na madalas nilalaktawan, at kapag nilaktawan ito, nasisira ang OAuth sa paraang mukhang bug ng provider. Binubuo ng runtime ang redirect URI mula sa origin na iyon, sa anyong <origin>/oauth/callback. Kapag hindi ito itinakda, nagde-default ang origin sa http://localhost:3000. Dahil dito, nagpapadala ang runtime sa provider ng redirect URI na http://localhost:3000/oauth/callback, habang nakarehistro sa iyong OAuth app ang https://connect.example.com/oauth/callback. Magkaiba ang dalawang string, kaya ganito ang sagot ng GitHub:

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

Nire-redirect ng OAuth provider ang browser pabalik sa URI na iyon. Ibig sabihin, dapat itong address na maaabot mula sa labas, at tinatanggihan ng mga provider ang plain http:// maliban kung localhost ang gamit. Ito ang buong dahilan kung bakit kailangan ng deployment na ito ng hostname at certificate. Itakda ang origin bago ang unang start, dahil binabasa ang value sa startup. Pagkatapos i-edit ang .env o compose.yaml, patakbuhin muli ang docker compose up -d para mailapat ito.

Ikonekta ang iyong unang provider gamit ang OAuth

Gawin muna ang OAuth app sa provider. Sa GitHub, pumunta sa Settings, pagkatapos ay Developer settings, OAuth Apps, at New OAuth App. Itakda ang authorization callback URL sa https://connect.example.com/oauth/callback. Itago ang client ID at client secret.

Ang bawat /api call ay may dalang admin token, kaya i-export ito nang isang beses para sa shell session.

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

Ipinapakita ng listing na iyon ang redirect URI na inaasahan ng runtime para sa bawat provider. Ito ang pinakamabilis na pagsusuri kung nailapat ang iyong origin. Kung localhost pa rin ang ipinapakita, tumatakbo ang container gamit ang lumang value at mabibigo ang OAuth flow sa huling hakbang.

I-store ang client credentials, pagkatapos ay magsimula ng authorization.

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

Ang ikalawang call ay nagbabalik ng authorizationUrl. Buksan ito sa browser, aprubahan ang scopes, at ibabalik ng provider ang browser sa /oauth/callback. Doon, ie-exchange ng runtime ang code at ise-save ang credential. Ginagabayan ka ng web console sa iyong origin sa parehong mga hakbang gamit ang isang form at kaparehong admin token. Laktawan ang lahat ng ito ng mga provider na gumagamit ng plain API key: direktang ini-store ng PUT /api/connections/<service> kasama ang {"authType":"api_key","values":{"apiKey":"..."}} ang key.

Magbigay sa bawat agent ng runtime token, hindi ng credential

Nag-a-authenticate ang agent sa gateway gamit ang runtime token, na ginagawa ng admin API.

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

May token ang response na nagsisimula sa oct_. Mag-isyu ng tig-iisang token para sa bawat agent at pangalanan ito ayon sa agent na gagamit nito. Kapag nag-revoke ka ng token na hindi mo matukoy, lahat ng token ang mare-revoke. Pagkatapos, tumatawag ang agent ng mga action gamit ang karaniwang 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":{}}'

Ang maayos na sagot ay isang envelope na ang field na success ay true, at ang payload ng provider ay nasa ilalim ng data. Hindi kasama saanman sa response na iyon ang GitHub token. Para sa MCP client, ituro ito sa https://connect.example.com/mcp gamit ang parehong bearer header. Nag-aalok ang gateway ng mga discovery tool gaya ng search_actions at execute_action, sa halip na isang tool para sa bawat API. Pinananatili nitong maliit ang listahan ng mga tool ng agent. Saklaw ng Pagpapatakbo ng MCP server sa isang VPS ang bahagi ng client sa setup na ito.

Magsagawa ng isa pang pagsusuri bago mo ituring na tapos na ito. Ulitin ang action call na tinanggal ang authorization header. Tinatawag ng sariling quickstart ng proyekto ang /v1 nang walang bearer, kaya ang installation na walang naka-configure na runtime authentication ay magsasagawa ng mga action para sa sinumang makakaabot sa port. Kung magtagumpay ang unauthenticated call, mayroon kang dalawang paraan: i-configure ang runtime token at kumpirmahing nabibigo na ang anonymous call, o paghigpitan ang /api, /v1 at /mcp sa reverse proxy upang mga address lamang na pinagmumulan ng iyong mga agent ang makagamit nito. /oauth/callback lamang ang kailangang manatiling bukas sa buong mundo, dahil iyon ang nag-iisang path na kailangan ng browser redirect ng provider.

Bawasan ang action list sa kailangan lamang ng agent

Ang gateway na may isang libong provider sa likod nito ay napakalawak na surface area para ibigay sa isang language model. Dalawang control ang nagpapaliit nito.

Tumatanggap ang OOMOL_CONNECT_ALLOWED_ACTIONS ng comma-separated allowlist at nauunawaan nito ang service.* at *. Ang OOMOL_CONNECT_BLOCKED_ACTIONS ang denylist, at nangunguna ang denylist. Kapag itinakda ang allowlist sa github.get_current_user,github.list_issues, tatanggihan ang lahat ng iba pang action anuman ang hilingin ng agent. Ito ang kaibahan ng pagkakamali sa isang incident. May sarili ring action rules ang runtime tokens bukod sa global rules. Nagsisimula sa walang laman ang allowedProxies list ng mga ito, kaya tatanggihan ang POST /v1/proxy/:service hanggang sa pahintulutan mo ito. Ipinapasa ng proxy endpoint na iyon ang raw request sa isang provider gamit ang iyong credential. Panatilihin itong walang laman maliban kung kailangan ito ng isang partikular na agent.

Naka-default ang OOMOL_CONNECT_ALLOW_PRIVATE_NETWORK sa false. Pinipigilan nito ang koneksyon sa isang self-hosted provider na tumuro sa isang private address, gaya ng cloud metadata service sa 169.254.169.254, o sa database mo sa parehong network. Panatilihin itong naka-off. I-on lamang ito para sa provider na ikaw mismo ang nagho-host.

I-back up ang box na naglalaman ng bawat token

Dalawang bagay ang mahalaga, at walang silbi ang bawat isa kung wala ang isa pa. Nasa database sa /app/data/connect.sqlite sa loob ng connector-data volume ang mga naka-seal na credential. Nasa .env ang encryption key na nag-a-unseal sa mga ito. Walang mare-restore ang volume backup kung wala ang key, at walang mare-restore ang key kung wala ang volume. Kaya dapat nasa password manager mo ang key, at dapat kasama ang volume sa regular mong backup rotation.

I-stop ang container habang kinokopya mo ang SQLite file. Maaaring ma-restore bilang corrupt na database ang kopyang ginawa habang may write.

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

Ang pangalan ng volume ay directory ng project mo kasama ang _connector-data. Kaya naroon ang unang command: i-paste ang totoong pangalan sa ikatlong command. Ipadala ang archive palabas ng VPS gamit ang restic backups mula sa VPS. Ine-encrypt nito ang archive bago ito umalis, dahil credential store ang archive na iyon.

Pinananatili ng runtime ang mga kamakailang action run bilang audit record, 5,000 ang default na bilang ng mga ito, kaya makikita sa console kung aling agent ang nagpatakbo ng alin at kailan. Ang log na iyon ang unang dapat basahin kapag kakaiba ang pagkilos ng isang agent. Ituro rin ang isang Uptime Kuma status page sa https://connect.example.com/health. Kapag hindi na sumasagot ang gateway, nakakaranas ang mga agent ng mga failure na mahirap ipaliwanag. Kung alam mong down ang gateway, makakatipid ka ng isang oras sa pagbasa ng agent output.

Mga nasisira at mensaheng makikita mo

redirect_uri_mismatch sa provider. Magkaiba ang origin at ang nakarehistrong callback URL. Ikumpara ang eksaktong string mula sa /api/oauth/configs sa mga setting ng app ng provider, kasama ang https sa http at anumang trailing slash.

Bawat tawag sa /api ay nagbabalik ng 401. Nawawala o mali ang spelling ng admin token header. Ang header ay Authorization: Bearer <token>, at hinihingi rin ng web console ang parehong token.

Tumatakbo ang container, at plain text ang pagkakaimbak ng credentials. Nangyayari ito kapag hindi nakakarating ang OOMOL_CONNECT_ENCRYPTION_KEY sa container, dahil iniimbak ng runtime ang mga credential record nang hindi naka-encrypt sa halip na tumangging magsimula. Patunayan ito sa sarili mong install: kumonekta sa isang provider gamit ang API key na makikilala mo, pagkatapos ay hanapin ito sa database.

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

Ang bilang na higit sa 0 ay nangangahulugang hindi ginagamit ang key, kaya tingnan kung nasa parehong directory ang .env at compose.yaml at kung ipinapakita ng docker compose config ang value. Kapag naitakda ang key, nagbabalik ng 0 ang parehong paghahanap dahil naka-seal ang record gamit ang AES-256-GCM (advanced encryption standard, 256-bit key, Galois/counter mode).

Walang nade-decrypt pagkatapos ng restore. Nagbago o nawala ang encryption key. Hindi ito kailanman isinusulat katabi ng data, ayon sa disenyo, kaya walang recovery path at walang support ticket na makakatulong. Ikonekta muli ang bawat provider. Sinusuportahan ang rotation sa pamamagitan ng hiwalay na key variable at data command sa runtime, kaya basahin ang kasalukuyang release notes bago ka mag-rotate ng anuman.

Nagkakaroon ng error ang agent na tumutukoy sa action na nakikita nito sa catalog. Magkahiwalay ang discovery at execution. Maaaring lumitaw ang isang action sa search_actions ngunit tanggihan pa rin ng OOMOL_CONNECT_ALLOWED_ACTIONS, ng denylist, o ng sariling mga panuntunan ng runtime token na iyon.

Mga upgrade. I-back up ang volume, i-edit ang image tag sa bagong release, pagkatapos ay docker compose pull && docker compose up -d. I-monitor ang docker compose logs -n 50 connector para sa migration line, at muling patakbuhin ang health check at isang aktuwal na action bago mo itong pagkatiwalaang muli. Ang rollback ay nangangahulugang ibalik ang dating tag, na gumagana lamang dahil naka-pin ito.

FAQ

Kailangan ko ba ng public domain para mag-self-host ng Open Connector?

Para sa mga provider na gumagamit ng API key, hindi: sapat na ang gateway sa 127.0.0.1. Para sa OAuth, oo sa praktika. Nire-redirect ng provider ang browser sa iyong callback URL, kaya dapat ma-resolve ang URL na iyon mula sa public internet, at tinatanggihan ng mga provider ang plain http:// maliban sa localhost. Itakda ang OOMOL_CONNECT_ORIGIN sa iyong https:// hostname bago ang unang pagsisimula, at i-register ang <origin>/oauth/callback sa OAuth app ng provider.

Ano ang mangyayari kung mawala ang Open Connector encryption key?

Hindi na made-decrypt ang mga naka-store na credential, at walang recovery. Sadyang hindi sine-save ang key kasama ng data, kaya walang makakabasa nito na may hawak ng database, kasama ka. Ang tanging opsyon mo ay magtakda ng bagong key at muling ikonekta ang bawat provider. Itago ang key sa isang password manager at isama ang database sa backup rotation mo, dahil kailangan ng restore ang pareho.

Makikita ba ng AI agent ko ang provider access token?

Hindi kapag dumadaan ito sa gateway. Nag-a-authenticate ang agent gamit ang runtime token na nagsisimula sa oct_, at ini-inject ng gateway ang provider credential sa outbound request sa server. Ang ibinabalik lamang nito ay ang response. Dalawang bagay ang sumisira sa property na ito: ang /v1/proxy/:service endpoint, na nagfo-forward ng raw requests na nakakabit ang iyong credential at sadyang walang laman ang mga grant nito, at ang pag-paste mo mismo ng API key sa agent, na ganap na lumalampas sa gateway.

Dapat bang maabot ang gateway mula sa public internet?

/oauth/callback lamang ang kailangang maabot. I-publish ang container port sa 127.0.0.1 upang hindi ito ma-expose ng Docker NAT rules lampas sa iyong firewall, at ilagay ang reverse proxy sa harapan nito. Pagkatapos, subukan ang isang action call na walang authorization header. Kung magtagumpay ito, paghigpitan sa proxy ang /api, /v1 at /mcp upang ang mga address lamang na ginagamit ng iyong mga agent ang makagamit ng mga ito, hanggang authenticated calls na lamang ang gumagana.

Handa na ba ang Open Connector para sa production use?

Lisensyado ito sa ilalim ng Apache 2.0 at mabilis ang pag-unlad nito: lumitaw ang repository noong 29 June 2026 at inilabas ang v1.3.3 noong 30 July 2026, kaya ituring ang bawat version number sa gabay na ito bilang snapshot noong 1 August 2026. Patakbuhin ito na naka-pin sa isang release tag, hindi kailanman sa latest o tip, basahin ang release notes bago ang bawat upgrade, at magpanatili ng volume backup na minsan mo nang na-restore. Matibay ang disenyo para sa server na pagmamay-ari mo. Ang panganib ay ang mabilis na pagbabago ng version, hindi ang architecture.