SSD Nodes Learn 🎉 VPS mula $4.99/buwan
Mga Gabay Matt ConnorNi Matt Connor · Na-update 2026-08-07

Self-host ang Open Connector para sa AI agents

I-host sa sarili mong VPS ang Open Connector auth gateway para hindi hawak ng agents ang SaaS token. May pinned image, TLS origin, OAuth callbacks, at backups.

Ano ang ginagawa ng Open Connector para sa isang AI agent

Kapag ikaw mismo ang nagho-host ng Open Connector, naglalagay ito ng isang auth gateway sa pagitan ng iyong mga AI agent at ng bawat software as a service (SaaS) API na ginagamit nila. Dahil dito, hindi kailanman nagtatago 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 iisang 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 lifetime ng refresh token, at sariling mga pangalan ng scope. Kapag manu-manong ikinonekta ang limang provider sa isang agent, kailangan ng limang redirect handler, limang credential store, at limang refresh loop na kailangang tumakbo bago mag-expire ang token. Halos walang nagsusulat ng ganoong code. Sa halip, gumagawa sila ng isang long-lived personal access token para sa bawat service at inilalagay ito sa agent config, environment file, o mismong prompt. Nababasa ng bawat tool na pinapatakbo ng agent ang token na iyon. Napupunta rin ito sa transcript. Ito ang failure na inilalarawan ng pag-iwas na mailantad ang mga secret sa AI agent.

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 access token ng provider. Kaya kung ma-leak ang transcript ng agent, isang runtime token na maaari mong i-revoke ang mawawala sa iyo, hindi ang iyong GitHub account.

Ina-advertise ng catalog ang mahigit 1,000 provider at 10,000 prebuilt action. Sariling bilang ito ng proyekto at hindi isang bagay na 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 hawak 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 ang service nila, breach na rin ito sa iyo. Sa self-hosting, inililipat ang mga record na ito sa SQLite sa isang machine na inuupahan at ina-administer mo, at pinoprotektahan gamit ang key na hindi kailanman umaalis sa iyong box.

Banggitin muna nang malinaw ang kapalit na gastos bago ka magsimula. Ang VPS na ito ang magiging pinakamahalagang server na pinapatakbo mo. Naglalaman ito ng mga gumaganang credential para sa dose-dosenang service sa iisang file, kaya dapat itong tratuhin gaya ng host ng password manager: 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 box na ito, huwag mo ring ilagay dito ang connector.

Mag-pin ng bersyon 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 latest tag din. Naglalathala rin ang registry ng tip tag, na binuo mula sa pinakabagong commit sa main.

Sa bagong proyekto, madalas magbago ang mga moving tag. Ang isang docker compose pull na lumaktaw ng dalawang release ay maaaring magbago ng endpoint na kailangan ng agent. Maaari kang magpalipas ng gabi sa pag-debug nito na para bang problema ito ng agent. I-pin ang image sa release tag. Mag-upgrade lamang kapag napagpasyahan mo na, pagkatapos basahin ang release notes.

Mag-deploy ng Open Connector sa sarili mong VPS gamit ang TLS

Bago magsimula ang container, kailangan mo ng:

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

Saklaw ng Traefik reverse proxy para sa maraming Docker Compose app ang proxy side. Nasa gabay na n8n sa VPS gamit ang Docker at HTTPS ang kumpletong certificate setup para sa isang app.

Gawin muna ang mga secret. Pinoprotektahan ng encryption key ang mga nakaimbak na credential. 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

Kopyahin agad ang dalawang value sa iyong password manager bago ang unang pagsisimula. Walang recovery path ang encryption key. Ipinaliwanag ang dahilan sa failure list sa ibaba.

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

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 pinned tag sa halip na latest. Ang pangalawa ay ang port. Ipinapublish 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. Kapag isinulat ang 127.0.0.1:3000:3000, sa loopback interface lamang ito nagpa-publish, at mula sa parehong host kumokonekta ang reverse proxy.

Minamarkahan ng :? ang bawat variable bilang required, kaya tumatangging magsimula ang stack kapag nawawala ang .env sa halip na magsimula nang hindi naka-encrypt ang mga credential. 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 gumagana na ang runtime. Dapat 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. Kapag connection refused ang health check, 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, idagdag 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 static config ng Traefik; kung hindi, magsisimula ang router nang walang certificate.

Bakit kailangan ng OAuth ng totoong hostname

OOMOL_CONNECT_ORIGIN ang setting na madalas nilalaktawan, at kapag nilaktawan ito, masisira ang OAuth sa paraang magmumukhang 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, samantalang nakarehistro sa OAuth app mo 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.

Nagre-redirect ang OAuth provider ng browser pabalik sa URI na iyon. Ibig sabihin, dapat itong address na maaabot mula sa labas, at hindi tumatanggap ang mga provider ng plain http:// maliban kung localhost ang gamit. Iyan 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 una mong 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. Itabi ang client ID at client secret.

Dala ng bawat /api call ang 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 paraan upang tingnan kung nagkabisa ang iyong origin. Kung localhost pa rin ang ipinapakita, tumatakbo ang container gamit ang dating 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"}'

Nagbabalik ang ikalawang call ng authorizationUrl. Buksan ito sa browser, aprubahan ang scopes, at ibabalik ng provider ang browser sa /oauth/callback. Doon ipinagpapalit ng runtime ang code at ini-store ang credential. Ginagabayan ka rin ng web console sa iyong origin sa parehong mga hakbang gamit ang isang form, sa ilalim ng parehong admin token. Nilalaktawan ng mga provider na plain API key ang lahat ng ito: direktang ini-store ng PUT /api/connections/<service> gamit ang {"authType":"api_key","values":{"apiKey":"..."}} ang key.

Bigyan ang 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-issue ng tig-iisang token para sa bawat agent at pangalanan ito batay sa agent na gagamit nito. Kapag nag-revoke ka ng token na hindi mo matukoy, kailangan mong i-revoke ang lahat ng token. Pagkatapos, tumatawag ang agent sa 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 valid na sagot ay isang envelope na ang success field ay true, habang nasa data ang payload mula sa provider. 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 tig-iisang tool para sa bawat API. Dahil dito, nananatiling maliit ang tool list ng agent. Sinasaklaw ng Pagpapatakbo ng mga MCP server sa isang VPS ang bahagi ng client sa setup na ito.

Magsagawa pa ng isang check bago mo ituring na tapos na ang setup. Ulitin ang action call nang tanggalin ang authorization header. Sa sariling quickstart ng proyekto, tinatawag ang /v1 nang walang bearer. Ibig sabihin, kung walang naka-configure na runtime auth ang installation, makakapag-execute ng actions ang sinumang makakaabot sa port. Kung magtagumpay ang unauthenticated call, may dalawang paraan para ayusin ito: mag-configure ng runtime tokens at tiyaking nabibigo na ang anonymous call, o limitahan ang /api, /v1 at /mcp sa reverse proxy para lamang sa mga address na pinanggagalingan ng iyong mga agent. /oauth/callback lamang ang kailangang manatiling bukas sa buong internet, dahil ito ang tanging 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 malaking attack surface para sa isang language model. Dalawang control ang nagpapaliit nito.

OOMOL_CONNECT_ALLOWED_ACTIONS tumatanggap ng comma-separated allowlist at kumikilala sa service.* at *. Ang OOMOL_CONNECT_BLOCKED_ACTIONS ang denylist, at nangingibabaw 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 pagkakaiba ng simpleng pagkakamali at security incident. May sarili ring action rules ang runtime token bukod sa mga global rule, at walang laman sa simula ang kanilang allowedProxies list. Dahil dito, tatanggihan ang POST /v1/proxy/:service hanggang sa bigyan mo ito ng pahintulot. Ang proxy endpoint na iyon ay nagpapasa ng raw request sa provider kasama ang iyong credential, kaya panatilihin itong walang laman maliban kung kailangan ito ng isang partikular na agent.

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

I-backup ang server na naglalaman ng lahat ng token

Dalawang bagay ang mahalaga, at walang silbi ang bawat isa kung wala ang isa pa. Ang database sa /app/data/connect.sqlite sa loob ng connector-data volume ang naglalaman ng mga sealed credential. Ang encryption key sa .env ang nagbubukas sa mga ito. Walang maibabalik ang volume backup kung wala ang key, at walang maibabalik ang key kung wala ang volume. Kaya ilagay ang key sa iyong password manager, at isama ang volume sa regular mong backup rotation.

I-stop ang container habang kinokopya ang SQLite file, dahil maaaring maging corrupt ang database kapag kinopya ito habang may isinusulat.

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 volume name ay ang iyong project directory na sinusundan ng _connector-data. Kaya naroon ang unang command: i-paste ang aktuwal na 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 sa server, dahil credential store ang archive na iyon.

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

Mga nasisira, at ang mensaheng makikita mo

redirect_uri_mismatch sa provider. Magkaiba ang origin at ang nakarehistrong callback URL. Ihambing ang eksaktong string mula sa /api/oauth/configs sa app settings ng provider, kasama ang https laban 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 pagkaka-store ng credentials. Nangyayari ito kapag hindi nakakarating ang OOMOL_CONNECT_ENCRYPTION_KEY sa container, dahil ini-store ng runtime ang credential records 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 count na higit sa 0 ay nangangahulugang hindi ginagamit ang key, kaya tiyaking nasa parehong directory ang .env at compose.yaml at ipinapakita ng docker compose config ang value. Kapag nakatakda ang key, 0 ang ibinabalik ng parehong search, dahil sealed ang record gamit ang AES-256-GCM (advanced encryption standard, 256-bit key, Galois/counter mode).

Walang nade-decrypt matapos ang restore. Nagbago o nawala ang encryption key. Hindi ito kailanman isinusulat sa tabi ng data, ayon sa disenyo, kaya walang recovery path at walang support ticket na makakatulong. Ikonekta muli ang bawat provider. Sinusuportahan ang key rotation sa pamamagitan ng hiwalay na key variable at data command sa runtime, kaya basahin muna ang kasalukuyang release notes bago 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 ito ng OOMOL_CONNECT_ALLOWED_ACTIONS, ng denylist, o ng sariling rules ng runtime token na iyon.

Mga upgrade. I-back up ang volume, i-edit ang image tag para 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 patakbuhin muli ang health check at isang totoong action bago ito muling pagkatiwalaan. Ang pag-rollback ay nangangahulugang ibalik ang dating tag, na gagana 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 callback URL mo, kaya kailangang 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 hostname ng iyong https:// bago ang unang pagsisimula, at i-register ang <origin>/oauth/callback sa OAuth app ng provider.

Ano ang mangyayari kung mawala ang encryption key ng Open Connector?

Hindi ma-decrypt ang mga naka-store na credential, at walang recovery. Sadyang hindi ini-store ang key kasama ng data, kaya walang makakabasa nito kahit sino pa ang 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 ang dalawa kapag nag-restore.

Nakikita ba ng AI agent ko ang access token ng provider?

Hindi kapag dumadaan ang tawag nito sa gateway. Nag-a-authenticate ang agent gamit ang runtime token na nagsisimula sa oct_, at ini-inject ng gateway ang credential ng provider sa outbound request sa server, saka ibinabalik ang response lamang. Dalawang bagay ang sumisira sa property na ito: ang /v1/proxy/:service endpoint, na nagpapasa ng raw request na may kalakip na credential mo at sadyang walang laman sa simula 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 mailantad ng Docker NAT rules lampas sa firewall mo, at ilagay sa unahan nito ang reverse proxy. Pagkatapos, subukan ang isang action call nang walang authorization header. Kung magtagumpay ito, paghigpitan sa proxy ang /api, /v1 at /mcp upang mga address lamang na ginagamit ng iyong mga agent ang makagamit nito, hanggang authenticated calls na lamang ang gumana.

Handa na ba ang Open Connector para sa production use?

May Apache 2.0 license ito at mabilis ang development: 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 gamit ang naka-pin na 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 isang server na pagmamay-ari mo; ang panganib ay nasa pagbabago-bago ng version, hindi sa architecture.