SSD Nodes Learn Hosting plans →
Panduan Matt ConnorOleh Matt Connor · Diperbarui 2026-08-29

Cara Self-Host Open Connector untuk Agen AI

Jalankan gateway auth Open Connector di VPS sendiri agar agen tidak menyimpan token SaaS. Gunakan image yang dipatok, TLS origin, callback OAuth, dan backup SQLite.

Fungsi Open Connector bagi agen AI

Self-hosting Open Connector menempatkan satu gateway autentikasi di antara agen AI dan setiap API software as a service (SaaS) yang dipanggilnya, sehingga agen tidak pernah menyimpan token provider. Open Connector adalah gateway open source dari OOMOL Lab dengan lisensi Apache 2.0. Gateway ini berjalan sebagai satu container, menyimpan statusnya dalam satu file SQLite, serta menyediakan action provider melalui HTTP dan MCP (model context protocol).

Masalah mulai muncul pada integrasi kedua. Setiap provider memiliki flow OAuth (open authorization), masa berlaku refresh token, dan nama scope sendiri. Menghubungkan lima provider ke agen secara manual berarti membuat lima redirect handler, lima penyimpanan kredensial, dan lima loop refresh yang harus berjalan sebelum token kedaluwarsa. Hampir tidak ada yang menulis kode tersebut. Mereka membuat satu personal access token berumur panjang untuk setiap service, lalu menempelkannya ke konfigurasi agen, file environment, atau prompt itu sendiri. Token tersebut kemudian dapat dibaca oleh setiap tool yang dijalankan agen dan masuk ke transcript. Inilah kegagalan yang dijelaskan oleh menjaga rahasia tetap di luar agen AI.

Gateway autentikasi memisahkan kredensial menjadi dua bagian. Gateway menyimpan kredensial provider dan menjalankan flow OAuth. Agen menerima runtime token yang hanya valid terhadap gateway. Saat agen memanggil sebuah action, gateway memuat kredensial yang tersimpan, menyisipkannya ke dalam request keluar di sisi server, lalu hanya mengembalikan response body. Agen tidak pernah menerima access token provider. Karena itu, transcript agen yang bocor hanya membahayakan satu runtime token yang dapat dicabut, bukan akun GitHub Anda.

Katalog tersebut mencantumkan lebih dari 1,000 provider dan 10,000 action siap pakai. Angka ini berasal dari pihak proyek sendiri dan tidak dapat Anda verifikasi dari luar. Hal yang dapat diverifikasi adalah strukturnya: satu endpoint HTTP untuk setiap action, satu koneksi tersimpan untuk setiap provider, dan satu token untuk setiap agen. Jika sisi agen AI ini masih baru dan istilah seperti tool call atau MCP server belum sepenuhnya dipahami, jalur bertahap dalam cara mempelajari agen AI dari awal membangun pemahaman tentang loop, tool, dan kebiasaan keamanan yang diasumsikan oleh gateway seperti ini.

Mengapa melakukan self-host Open Connector, bukan menggunakan layanan connector terkelola

Layanan connector terkelola melakukan pekerjaan yang sama dan menyimpan refresh token untuk setiap provider yang Anda hubungkan. Refresh token untuk Google atau GitHub adalah kunci jangka panjang ke email dan repository Anda, dan biasanya tetap berlaku setelah perubahan password. Jika layanan tersebut dibobol, Anda juga ikut terdampak. Dengan self-hosting, data tersebut dipindahkan ke SQLite pada mesin yang Anda sewa dan kelola, lalu diamankan dengan key yang tidak pernah meninggalkan mesin Anda.

Pertimbangkan risikonya sebelum memulai. VPS ini akan menjadi server paling bernilai yang Anda jalankan. Server ini menyimpan kredensial aktif untuk selusin layanan dalam satu file, sehingga harus diperlakukan seperti host password manager: firewall yang hanya membuka port 443, tanpa login bersama, backup yang benar-benar pernah Anda pulihkan, serta alert saat server berhenti merespons. Jika Anda tidak bersedia menempatkan password vault di mesin ini, jangan tempatkan connector di mesin ini juga.

Sematkan versi sebelum menginstal apa pun

Open Connector masih baru. Repository ini pertama kali muncul pada 29 June 2026, dan per 1 August 2026 rilis terbaru yang diberi tag adalah v1.3.3, diterbitkan pada 30 July 2026 dan juga memiliki tag latest. Registry juga menerbitkan tag tip, yang dibuat dari commit terbaru pada main.

Pada proyek yang masih baru seperti ini, tag yang dapat berubah sering diperbarui. docker compose pull yang melompati dua rilis dapat mengubah endpoint yang diandalkan agent Anda. Akibatnya, Anda dapat menghabiskan waktu untuk men-debug masalah tersebut sebagai masalah agent. Sematkan image ke tag rilis, lalu lakukan upgrade saat Anda memutuskan untuk meng-upgrade, setelah membaca catatan rilis.

Deploy Open Connector di balik TLS pada VPS milik sendiri

Sebelum container dijalankan, Anda memerlukan:

  • Docker dengan plugin Compose, pada Ubuntu 24.04 atau distribusi yang serupa
  • hostname dengan A record yang mengarah ke VPS ini, misalnya connect.example.com
  • reverse proxy yang sudah melakukan terminasi TLS (transport layer security) untuk hostname tersebut
  • dua secret acak yang dibuat di bawah

Panduan Reverse proxy Traefik untuk beberapa aplikasi Docker Compose membahas sisi proxy. Konfigurasi sertifikat yang sama, dari awal hingga selesai untuk satu aplikasi, tersedia dalam panduan n8n pada VPS dengan Docker dan HTTPS.

Buat secret terlebih dahulu. Kunci enkripsi melindungi kredensial yang tersimpan. Token admin melindungi konsol web dan seluruh permukaan /api. Keduanya tidak memiliki nilai default, tetapi runtime tetap dapat berjalan tanpa keduanya.

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

Salin kedua nilai tersebut ke password manager sekarang, sebelum proses start pertama. Kunci enkripsi tidak memiliki jalur pemulihan. Alasannya dijelaskan dalam daftar kegagalan di bawah.

Sekarang compose.yaml. Konfigurasi ini berbeda dari contoh upstream pada dua bagian, dan keduanya penting.

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:

Perubahan pertama adalah tag yang dipatok, bukan latest. Perubahan kedua adalah port. File upstream memublikasikan 3000:3000, yang mengikat semua interface pada host. Docker menulis port yang dipublikasikan ke tabel NAT (network address translation) sebelum paket mencapai rantai filter ufw. Karena itu, ufw deny 3000 tidak menutup port tersebut. Perangkap ini dijelaskan dalam alasan port Docker melewati ufw. Penulisan 127.0.0.1:3000:3000 hanya memublikasikan port pada interface loopback, dan reverse proxy Anda terhubung dari host yang sama.

:? menandai setiap variabel sebagai wajib. Dengan demikian, stack menolak start ketika .env tidak ada, alih-alih berjalan dengan kredensial yang tidak terenkripsi. Menyimpan nilai di .env, bukan di file compose, mengikuti pola dalam file env dan secret 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 menjawab { "ok": true } setelah runtime berjalan. ss harus menampilkan 127.0.0.1:3000. Baris yang berisi 0.0.0.0:3000 berarti pemetaan port masih menggunakan konfigurasi upstream, dan gateway menjawab langsung ke seluruh Internet. Jika pemeriksaan kesehatan menghasilkan connection refused, berarti container belum melakukan listening. Baca log sebelum mengubah konfigurasi proxy.

Label Traefik untuk service yang sama
    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"

Jika Traefik berjalan dalam Docker pada host yang sama, hubungkan service ini ke network Traefik dan hapus blok ports:. Traefik dapat menjangkau container melalui network internal, sehingga tidak ada port yang perlu dipublikasikan ke host. certresolver=le harus sama dengan nama resolver dalam konfigurasi statis Traefik. Jika tidak, router berjalan tanpa sertifikat.

Mengapa OAuth mengharuskan hostname nyata

OOMOL_CONNECT_ORIGIN adalah pengaturan yang sering dilewati. Jika dilewati, OAuth gagal dengan cara yang tampak seperti bug pada provider. Runtime menyusun URI pengalihan dari origin tersebut, dalam format <origin>/oauth/callback. Jika tidak diatur, origin default menjadi http://localhost:3000. Akibatnya, runtime mengirimkan URI pengalihan http://localhost:3000/oauth/callback kepada provider, sedangkan aplikasi OAuth Anda mendaftarkan https://connect.example.com/oauth/callback. Kedua string tersebut berbeda, sehingga GitHub merespons:

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

Provider OAuth mengarahkan browser kembali ke URI tersebut. Karena itu, URI tersebut harus berupa alamat yang dapat dijangkau dari luar, dan provider menolak http:// biasa untuk apa pun selain localhost. Itulah alasan deployment ini memerlukan hostname dan sertifikat. Atur origin sebelum start pertama, karena nilainya dibaca saat startup. Setelah mengedit .env atau compose.yaml, jalankan docker compose up -d lagi untuk menerapkan perubahan.

Hubungkan provider pertama melalui OAuth

Buat aplikasi OAuth terlebih dahulu di provider. Di GitHub, buka Settings, lalu Developer settings, kemudian OAuth Apps, dan pilih New OAuth App. Tetapkan URL callback otorisasi ke https://connect.example.com/oauth/callback. Simpan client ID dan client secret.

Setiap panggilan /api membawa admin token, jadi ekspor token tersebut sekali untuk sesi shell.

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

Daftar tersebut menampilkan URI pengalihan yang diharapkan runtime untuk setiap provider. Ini adalah pemeriksaan tercepat untuk memastikan origin Anda sudah diterapkan. Jika masih menampilkan localhost, container berjalan dengan nilai lama dan alur OAuth akan gagal pada langkah terakhir.

Simpan kredensial client, lalu mulai proses otorisasi.

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

Panggilan kedua mengembalikan authorizationUrl. Buka URL tersebut di browser, setujui scope, lalu provider mengarahkan browser kembali ke /oauth/callback. Pada tahap ini, runtime menukar code dan menyimpan kredensial. Web console pada origin Anda menjalankan langkah yang sama melalui formulir dengan admin token yang sama. Provider yang menggunakan API key biasa tidak memerlukan semua langkah ini: PUT /api/connections/<service> dengan {"authType":"api_key","values":{"apiKey":"..."}} menyimpan key secara langsung.

Berikan setiap agent token runtime, bukan kredensial

Agent melakukan autentikasi ke gateway menggunakan token runtime yang diterbitkan oleh 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"}'

Respons tersebut membawa token yang diawali dengan oct_. Terbitkan satu token untuk setiap agent dan beri nama sesuai agent tersebut, karena pencabutan token yang tidak dapat Anda identifikasi berarti mencabut semuanya. Agent kemudian memanggil action melalui HTTP biasa.

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

Respons yang sehat adalah envelope dengan field success bernilai true, sedangkan payload provider berada di bawah data. Token GitHub tidak ada di mana pun dalam respons tersebut. Untuk klien MCP, arahkan klien ke https://connect.example.com/mcp menggunakan header bearer yang sama. Gateway menyediakan tool discovery seperti search_actions dan execute_action, bukan satu tool untuk setiap API, sehingga daftar tool agent tetap kecil. Menjalankan server MCP pada VPS membahas sisi klien dari konfigurasi tersebut.

Lakukan satu pemeriksaan lagi sebelum menganggap konfigurasi ini selesai. Ulangi pemanggilan action setelah menghapus header authorization. Quickstart proyek itu sendiri memanggil /v1 tanpa bearer sama sekali. Artinya, instalasi yang tidak mengonfigurasi autentikasi runtime akan menjalankan action untuk siapa pun yang dapat menjangkau port tersebut. Jika pemanggilan tanpa autentikasi berhasil, ada dua solusi: konfigurasikan token runtime dan pastikan pemanggilan anonim kini gagal, atau batasi /api, /v1, dan /mcp di reverse proxy hanya ke alamat asal agent Anda. Hanya /oauth/callback yang harus tetap terbuka untuk publik, karena itulah satu-satunya jalur yang diperlukan browser provider untuk melakukan redirect.

Batasi daftar tindakan sesuai kebutuhan agent

Gateway dengan seribu provider di belakangnya memberikan permukaan akses yang terlalu luas kepada language model. Permukaan ini menjadi lebih luas ketika model mulai membaca teks yang tidak ditulisnya sendiri, karena halaman yang dikembalikan oleh instance SearXNG Anda sendiri yang menjawab pencarian web agent dapat berisi instruksi yang ditujukan untuk tindakan apa pun yang diizinkan agent. Prinsip pembatasan yang membuat coding agent melakukan perubahan terkecil yang berfungsi juga berlaku untuk izinnya: berikan hanya beberapa tindakan yang benar-benar diperlukan oleh tugas tersebut, tanpa izin tambahan. Dua kontrol dapat mempersempit akses ini.

OOMOL_CONNECT_ALLOWED_ACTIONS menerima allowlist yang dipisahkan dengan koma serta memahami service.* dan *. OOMOL_CONNECT_BLOCKED_ACTIONS adalah denylist, dan denylist memiliki prioritas. Jika allowlist diatur ke github.get_current_user,github.list_issues, semua tindakan lainnya akan ditolak, apa pun permintaan agent. Inilah perbedaan antara kesalahan dan insiden. Token runtime memiliki aturan tindakan sendiri di atas aturan global, dan daftar allowedProxies miliknya kosong secara default. Karena itu, POST /v1/proxy/:service ditolak sampai Anda memberikan izin. Endpoint proxy tersebut meneruskan request mentah ke provider dengan kredensial Anda terlampir. Biarkan daftar ini kosong kecuali ada agent tertentu yang memerlukannya.

OOMOL_CONNECT_ALLOW_PRIVATE_NETWORK default-nya adalah false. Pengaturan ini mencegah koneksi ke provider yang di-host sendiri mengarah ke alamat privat, seperti layanan metadata cloud pada 169.254.169.254 atau database Anda di jaringan yang sama. Biarkan pengaturan ini nonaktif. Aktifkan hanya untuk provider yang Anda host sendiri.

Cadangkan server yang menyimpan semua token

Ada dua hal yang penting, dan masing-masing tidak berguna tanpa yang lain. Database di /app/data/connect.sqlite dalam volume connector-data menyimpan kredensial yang disegel. Kunci enkripsi di .env membukanya. Cadangan volume tanpa kunci tidak dapat memulihkan apa pun, dan kunci tanpa volume juga tidak dapat memulihkan apa pun. Karena itu, simpan kunci di password manager dan masukkan volume ke dalam rotasi pencadangan rutin.

Hentikan container saat menyalin file SQLite. Salinan yang dibuat saat proses penulisan berlangsung dapat dipulihkan sebagai database yang rusak.

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

Nama volume adalah direktori proyek Anda ditambah _connector-data. Karena itu, perintah pertama ada di sini: tempel nama sebenarnya ke dalam perintah ketiga. Kirim arsip keluar dari VPS menggunakan pencadangan restic dari VPS. Arsip tersebut dienkripsi sebelum meninggalkan VPS karena berisi penyimpanan kredensial.

Runtime menyimpan proses tindakan terbaru sebagai catatan audit, secara default sebanyak 5,000 catatan. Dengan demikian, konsol dapat menunjukkan agen mana yang menjalankan tindakan apa dan kapan. Baca log tersebut terlebih dahulu ketika agen berperilaku tidak semestinya. Arahkan halaman status Uptime Kuma ke https://connect.example.com/health juga. Ketika gateway berhenti merespons, agen gagal dengan cara yang membingungkan. Mengetahui bahwa gateway sedang tidak aktif dapat menghemat waktu satu jam untuk membaca output agen.

Hal-hal yang mengalami kegagalan dan pesan yang akan ditampilkan

redirect_uri_mismatch di provider. Origin dan URL callback yang terdaftar berbeda. Bandingkan string persis dari /api/oauth/configs dengan pengaturan aplikasi provider, termasuk https terhadap http dan slash di bagian akhir.

Setiap pemanggilan /api mengembalikan 401. Header token admin tidak ada atau salah eja. Header tersebut adalah Authorization: Bearer <token>, dan konsol web meminta token yang sama.

Container berjalan, dan kredensial tersimpan dalam teks biasa. Ini terjadi ketika OOMOL_CONNECT_ENCRYPTION_KEY tidak pernah sampai ke container, karena runtime menyimpan catatan kredensial tanpa enkripsi, bukan menolak untuk start. Buktikan pada instalasi Anda sendiri: hubungkan provider dengan API key yang dapat Anda kenali, lalu cari key tersebut di database.

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

Nilai di atas 0 berarti key belum diterapkan. Pastikan .env berada di direktori yang sama dengan compose.yaml dan docker compose config menampilkan nilainya. Setelah key ditetapkan, pencarian yang sama mengembalikan 0 karena catatan tersebut disegel dengan AES-256-GCM (advanced encryption standard, kunci 256-bit, mode Galois/counter).

Tidak ada yang dapat didekripsi setelah pemulihan. Kunci enkripsi berubah atau hilang. Kunci tersebut memang tidak pernah ditulis di sebelah data, sehingga tidak ada jalur pemulihan dan tidak ada tiket dukungan yang dapat membantu. Hubungkan kembali setiap provider. Rotasi didukung melalui variabel key terpisah dan perintah data di runtime. Baca catatan rilis saat ini sebelum melakukan rotasi.

Agent menampilkan error yang menyebut action yang dapat dilihatnya di katalog. Discovery dan eksekusi merupakan proses terpisah. Action dapat muncul di search_actions, tetapi tetap ditolak oleh OOMOL_CONNECT_ALLOWED_ACTIONS, denylist, atau aturan milik token runtime tersebut.

Upgrade. Cadangkan volume, edit image tag ke rilis baru, lalu docker compose pull && docker compose up -d. Pantau docker compose logs -n 50 connector untuk mencari baris migrasi, lalu jalankan kembali health check dan satu action nyata sebelum menggunakannya kembali. Rollback berarti mengembalikan tag lama. Hal ini hanya berfungsi karena tag tersebut dipin.

FAQ

Apakah saya memerlukan domain publik untuk melakukan self-hosting Open Connector?

Untuk provider yang menggunakan API key, tidak: gateway pada 127.0.0.1 sudah cukup. Untuk OAuth, dalam praktiknya ya. Provider mengarahkan browser ke URL callback Anda, sehingga URL tersebut harus dapat di-resolve dari Internet publik, dan provider menolak http:// biasa di luar localhost. Tetapkan OOMOL_CONNECT_ORIGIN ke hostname https:// Anda sebelum start pertama, lalu daftarkan <origin>/oauth/callback di aplikasi OAuth provider.

Apa yang terjadi jika saya kehilangan encryption key Open Connector?

Credential yang tersimpan tidak dapat didekripsi, dan tidak ada pemulihan. Key tersebut sengaja tidak pernah disimpan bersama data, sehingga tidak seorang pun yang memegang database dapat membacanya, termasuk Anda. Satu-satunya pilihan adalah menetapkan key baru dan menghubungkan kembali setiap provider. Simpan key di password manager dan database dalam rotasi backup, karena pemulihan memerlukan keduanya.

Apakah AI agent saya dapat melihat access token provider?

Tidak jika agent memanggil melalui gateway. Agent melakukan autentikasi menggunakan runtime token yang diawali oct_, lalu gateway menyisipkan credential provider ke dalam outbound request di server dan hanya mengembalikan respons. Dua hal dapat merusak batasan ini: endpoint /v1/proxy/:service, yang meneruskan raw request dengan credential Anda terlampir dan sengaja memiliki grant kosong, serta menempelkan API key langsung ke agent, yang sepenuhnya melewati gateway.

Apakah gateway harus dapat diakses dari Internet publik?

Hanya /oauth/callback yang harus dapat diakses. Publish port container pada 127.0.0.1 agar aturan NAT Docker tidak dapat mengeksposnya melewati firewall Anda, lalu tempatkan reverse proxy di depannya. Setelah itu, uji satu action call tanpa header authorization. Jika berhasil, batasi /api, /v1, dan /mcp pada proxy hanya ke alamat yang digunakan agent Anda sampai hanya authenticated call yang dapat berfungsi.

Apakah Open Connector siap digunakan di production?

Open Connector berlisensi Apache 2.0 dan berkembang cepat: repository muncul pada 29 June 2026, sedangkan v1.3.3 dirilis pada 30 July 2026. Karena itu, anggap setiap nomor versi dalam panduan ini sebagai snapshot per 1 August 2026. Jalankan dengan release tag yang dipin, jangan pernah menggunakan latest atau tip, baca release notes sebelum setiap upgrade, dan simpan backup volume yang sudah pernah Anda restore. Desainnya cukup baik untuk server yang Anda miliki. Risiko utamanya adalah perubahan versi yang cepat, bukan arsitekturnya.