Cara Menjalankan Open Connector di VPS Sendiri
Jalankan gateway autentikasi Open Connector di VPS sendiri agar agen tidak menyimpan token SaaS. Gunakan image yang dipatok, TLS origin, callback OAuth, dan cadangan.
Fungsi Open Connector bagi agen AI
Menjalankan Open Connector sendiri menempatkan satu gateway autentikasi di antara agen AI Anda dan setiap API software as a service (SaaS) yang dipanggilnya. Dengan demikian, agen tidak pernah menyimpan token penyedia. Open Connector adalah gateway sumber terbuka dari OOMOL Lab dengan lisensi Apache 2.0. Open Connector berjalan sebagai satu container, menyimpan statusnya dalam satu file SQLite, serta menyediakan tindakan penyedia melalui HTTP dan MCP (model context protocol).
Masalah mulai muncul pada integrasi kedua. Setiap penyedia memiliki alur OAuth (open authorization), masa berlaku refresh token, dan nama scope sendiri. Menghubungkan lima penyedia ke agen secara manual berarti membuat lima handler pengalihan, 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 layanan, lalu menempelkannya ke konfigurasi agen, file lingkungan, atau prompt itu sendiri. Token tersebut kemudian dapat dibaca oleh setiap alat yang dijalankan agen dan masuk ke transkrip. Inilah kegagalan yang dijelaskan dalam menjaga rahasia agar tidak masuk ke agen AI.
Gateway autentikasi membagi kredensial menjadi dua bagian. Gateway menyimpan kredensial penyedia dan menjalankan alur OAuth. Agen memperoleh token runtime yang hanya valid untuk gateway. Saat agen memanggil suatu tindakan, gateway memuat kredensial yang tersimpan, menyisipkannya ke dalam permintaan keluar di sisi server, lalu hanya mengembalikan isi respons. Agen tidak pernah menerima access token penyedia. Karena itu, jika transkrip agen bocor, kerugiannya hanya berupa satu token runtime yang dapat dicabut, bukan akun GitHub Anda.
Katalog tersebut menyatakan memiliki lebih dari 1,000 penyedia dan 10,000 tindakan siap pakai. Angka ini berasal dari proyek itu sendiri dan tidak dapat Anda verifikasi dari luar. Hal yang dapat diverifikasi adalah strukturnya: satu endpoint HTTP untuk setiap tindakan, satu koneksi tersimpan untuk setiap penyedia, dan satu token untuk setiap agen.
Mengapa meng-host Open Connector sendiri, bukan menggunakan layanan konektor ter-host
Layanan konektor ter-host 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 repositori Anda, dan biasanya tetap berlaku setelah perubahan password. Jika layanan tersebut mengalami kebocoran, Anda juga terdampak. Dengan meng-host sendiri, catatan tersebut dipindahkan ke SQLite pada mesin yang Anda sewa dan administrasikan, lalu dilindungi dengan kunci yang tidak pernah meninggalkan mesin Anda.
Pertimbangkan biayanya secara langsung sebelum memulai. VPS ini akan menjadi server paling berharga yang Anda jalankan. VPS ini menyimpan kredensial aktif untuk selusin layanan dalam satu file. Karena itu, perlakukan VPS ini seperti host password manager: gunakan firewall yang hanya membuka 443, jangan gunakan login bersama, buat backup yang sudah pernah Anda pulihkan, dan siapkan peringatan ketika VPS berhenti merespons. Jika Anda tidak bersedia menyimpan password vault di mesin ini, jangan simpan konektor di mesin ini.
Tetapkan versi sebelum memasang apa pun
Open Connector masih baru. Repositori ini pertama kali muncul pada 29 June 2026. 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 terus berubah dapat sering diperbarui. docker compose pull yang melompati dua rilis dapat mengubah endpoint yang diandalkan agen Anda. Akibatnya, Anda dapat menghabiskan waktu untuk menelusuri masalah yang sebenarnya berasal dari agen. Tetapkan image ke tag rilis. Lakukan upgrade saat Anda memutuskan untuk melakukannya, setelah membaca catatan rilis.
Menerapkan Open Connector di balik TLS pada VPS Anda sendiri
Sebelum container dimulai, Anda memerlukan:
- Docker dengan plugin Compose, pada Ubuntu 24.04 atau versi yang mendekatinya
- nama host dengan A record yang mengarah ke VPS ini, misalnya
connect.example.com - reverse proxy yang sudah mengakhiri TLS (transport layer security) untuk nama host tersebut
- dua secret acak yang dibuat di bawah
Reverse proxy Traefik untuk beberapa aplikasi Docker Compose membahas sisi proxy. Konfigurasi sertifikat yang sama, dari awal hingga akhir 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, dan runtime dapat dimulai 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 .envSalin kedua nilai tersebut ke password manager sekarang, sebelum memulai untuk pertama kalinya. Kunci enkripsi tidak memiliki jalur pemulihan. Alasannya dijelaskan dalam daftar kegagalan di bawah.
Sekarang compose.yaml. Konfigurasi ini berbeda dari contoh upstream di dua tempat, 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 dikunci versinya, bukan latest. Perubahan kedua adalah port. File upstream memublikasikan 3000:3000, yang mengikat semua interface pada host. Docker menulis port yang dipublikasikannya ke tabel NAT (network address translation) sebelum paket mencapai rantai filter ufw. Karena itu, ufw deny 3000 tidak menutup port tersebut. Jebakan ini dijelaskan dalam mengapa port Docker melewati ufw. Penulisan 127.0.0.1:3000:3000 memublikasikan port hanya pada interface loopback, dan reverse proxy Anda terhubung dari host yang sama.
:? menandai setiap variabel sebagai wajib. Dengan demikian, stack menolak untuk dimulai ketika .env tidak ada, alih-alih dimulai dengan kredensial yang tidak terenkripsi. Menyimpan nilainya dalam .env, bukan dalam file compose, mengikuti pola dari 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 aktif. ss harus menampilkan 127.0.0.1:3000. Baris yang berbunyi 0.0.0.0:3000 berarti pemetaan port masih menggunakan pemetaan upstream, dan gateway menjawab langsung ke seluruh internet. Jika pemeriksaan kesehatan menghasilkan connection refused, berarti container belum listening. Baca log sebelum mengubah konfigurasi proxy.
Label Traefik untuk layanan 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"Saat Traefik berjalan di Docker pada host yang sama, hubungkan layanan ini ke network Traefik dan hapus blok ports:. Traefik menjangkau container melalui network internal, sehingga tidak ada yang perlu dipublikasikan ke host. certresolver=le harus sama dengan nama resolver dalam konfigurasi statis Traefik. Jika tidak, router aktif tanpa sertifikat.
Mengapa OAuth mengharuskan Anda memiliki hostname yang valid
OOMOL_CONNECT_ORIGIN adalah pengaturan yang sering dilewati. Jika pengaturan ini dilewati, OAuth gagal dengan cara yang tampak seperti bug pada provider. Runtime membangun 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. Provider menolak http:// biasa untuk semua alamat selain localhost. Inilah alasan deployment ini memerlukan hostname dan sertifikat. Atur origin sebelum proses start pertama, karena nilainya dibaca saat startup. Setelah mengedit .env atau compose.yaml, jalankan docker compose up -d lagi untuk menerapkan perubahan.
Hubungkan penyedia pertama melalui OAuth
Buat aplikasi OAuth terlebih dahulu di penyedia. Di GitHub, buka Settings, lalu Developer settings, kemudian OAuth Apps, dan pilih New OAuth App. Atur URL callback otorisasi ke https://connect.example.com/oauth/callback. Simpan client ID dan client secret.
Setiap panggilan /api membawa token admin. Karena itu, ekspor token tersebut satu kali 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 penyedia. 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 alamat tersebut di browser, setujui cakupan akses, lalu penyedia mengarahkan browser kembali ke /oauth/callback. Di sana, runtime menukar kode dan menyimpan kredensial. Konsol web pada origin Anda memandu langkah yang sama melalui formulir dengan token admin yang sama. Penyedia yang menggunakan API key biasa melewati semua langkah ini: PUT /api/connections/<service> dengan {"authType":"api_key","values":{"apiKey":"..."}} menyimpan key tersebut secara langsung.
Beri setiap agen token runtime, jangan pernah berikan kredensial
Agen melakukan autentikasi ke gateway dengan token runtime yang dibuat oleh API admin.
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 agen dan beri nama sesuai nama agen tersebut. Jika tidak dapat mengidentifikasi token, pencabutannya akan mencabut semua token. Setelah itu, agen 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 dari provider berada di bawah data. Token GitHub tidak terdapat di mana pun dalam respons tersebut. Untuk klien MCP, arahkan klien ke https://connect.example.com/mcp dengan header bearer yang sama. Gateway menyediakan tool discovery seperti search_actions dan execute_action, bukan satu tool untuk setiap API. Hal ini menjaga daftar tool agen tetap kecil. Menjalankan server MCP pada VPS membahas sisi klien dari konfigurasi tersebut.
Lakukan satu pemeriksaan lagi sebelum menyatakan konfigurasi ini selesai. Ulangi pemanggilan action setelah menghapus header authorization. Quickstart proyek tersebut memanggil /v1 tanpa bearer sama sekali. Artinya, instalasi tanpa 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 sekarang gagal, atau batasi /api, /v1, dan /mcp pada reverse proxy ke alamat asal agen Anda. Hanya /oauth/callback yang harus tetap terbuka untuk publik, karena itulah satu-satunya jalur yang diperlukan oleh pengalihan browser provider.
Kurangi daftar tindakan hingga hanya yang diperlukan agen
Gateway dengan seribu provider di belakangnya memberikan permukaan akses yang terlalu luas bagi model bahasa. Dua kontrol dapat mempersempitnya.
OOMOL_CONNECT_ALLOWED_ACTIONS menerima daftar izin yang dipisahkan koma serta memahami service.* dan *. OOMOL_CONNECT_BLOCKED_ACTIONS adalah daftar penolakan, dan daftar penolakan memiliki prioritas. Menetapkan daftar izin ke github.get_current_user,github.list_issues berarti semua tindakan lainnya ditolak, apa pun yang diminta agen. Inilah perbedaan antara kesalahan dan insiden. Token runtime memiliki aturan tindakannya sendiri selain aturan global, dan daftar allowedProxies miliknya kosong secara default. Karena itu, POST /v1/proxy/:service ditolak hingga Anda mengizinkannya. Endpoint proxy tersebut meneruskan permintaan mentah ke provider dengan kredensial Anda terlampir. Biarkan daftar itu kosong kecuali agen tertentu memang memerlukannya.
OOMOL_CONNECT_ALLOW_PRIVATE_NETWORK secara default bernilai 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 setiap 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 membuka segelnya. Cadangan volume tanpa kunci tidak dapat memulihkan apa pun, dan kunci tanpa volume juga tidak dapat memulihkan apa pun. Karena itu, simpan kunci di pengelola kata sandi dan masukkan volume ke dalam rotasi pencadangan rutin Anda.
Hentikan container saat menyalin file SQLite, karena salinan yang dibuat saat proses penulisan berlangsung dapat dipulihkan sebagai database yang korup.
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 connectorNama volume adalah direktori proyek Anda ditambah _connector-data. Karena itu, perintah pertama dicantumkan di sana: tempelkan nama sebenarnya ke dalam perintah ketiga. Kirim arsip keluar dari VPS menggunakan cadangan restic dari VPS, yang mengenkripsinya sebelum arsip meninggalkan VPS, karena arsip tersebut adalah penyimpanan kredensial.
Runtime menyimpan eksekusi tindakan terbaru sebagai catatan audit, secara default sebanyak 5,000 catatan. Dengan demikian, konsol dapat menunjukkan agent mana yang menjalankan tindakan tertentu dan kapan. Baca log tersebut terlebih dahulu saat agent berperilaku aneh. Arahkan halaman status Uptime Kuma ke https://connect.example.com/health juga. Saat gateway berhenti merespons, agent gagal dengan cara yang membingungkan. Mengetahui bahwa gateway sedang tidak aktif dapat menghemat waktu hingga satu jam yang seharusnya digunakan untuk membaca output agent.
Hal yang gagal dan pesan yang akan Anda lihat
redirect_uri_mismatch di penyedia. Asal dan URL callback terdaftar berbeda. Bandingkan string persis dari /api/oauth/configs dengan pengaturan aplikasi di penyedia, termasuk https dengan http dan garis miring di akhir, jika ada.
Setiap panggilan /api menghasilkan 401. Header token admin tidak ada atau salah eja. Header tersebut adalah Authorization: Bearer <token>, dan konsol web meminta token yang sama.
Kontainer berjalan, dan kredensial tersimpan dalam teks biasa. Hal ini terjadi ketika OOMOL_CONNECT_ENCRYPTION_KEY tidak pernah diteruskan ke kontainer, karena runtime menyimpan catatan kredensial tanpa enkripsi alih-alih menolak untuk memulai. Buktikan pada instalasi Anda sendiri: hubungkan penyedia dengan kunci API yang dapat Anda kenali, lalu cari kunci 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.sqliteJumlah di atas 0 berarti kunci tidak diterapkan. Periksa apakah .env berada di direktori yang sama dengan compose.yaml dan apakah docker compose config menampilkan nilainya. Setelah kunci ditetapkan, pencarian yang sama menghasilkan 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. Berdasarkan desain, kunci tersebut tidak pernah ditulis di dekat data. Karena itu, tidak ada jalur pemulihan dan tidak ada tiket dukungan yang dapat membantu. Hubungkan kembali setiap penyedia. Rotasi didukung melalui variabel kunci terpisah dan perintah data dalam runtime. Baca catatan rilis saat ini sebelum melakukan rotasi.
Agen mendapatkan kesalahan yang menyebut tindakan yang terlihat dalam katalog. Penemuan dan eksekusi merupakan proses terpisah. Tindakan dapat muncul di search_actions, tetapi tetap ditolak oleh OOMOL_CONNECT_ALLOWED_ACTIONS, oleh daftar penolakan, atau oleh aturan token runtime tersebut.
Pembaruan. Cadangkan volume, ubah tag image ke rilis baru, lalu docker compose pull && docker compose up -d. Pantau docker compose logs -n 50 connector untuk baris migrasi, lalu jalankan kembali pemeriksaan kesehatan dan satu tindakan nyata sebelum mempercayainya lagi. Pengembalian ke versi sebelumnya berarti mengembalikan tag lama. Hal ini hanya berfungsi karena tag tersebut ditetapkan secara eksplisit.
FAQ
Apakah saya memerlukan domain publik untuk meng-host Open Connector sendiri?
Untuk provider yang menggunakan kunci API, tidak: gateway pada 127.0.0.1 sudah cukup. Untuk OAuth, secara praktik, ya. Provider mengarahkan browser ke URL callback Anda, sehingga URL tersebut harus dapat diakses dari internet publik, dan provider menolak http:// biasa di luar localhost. Tetapkan OOMOL_CONNECT_ORIGIN ke hostname https:// Anda sebelum memulai untuk pertama kali, lalu daftarkan <origin>/oauth/callback di aplikasi OAuth provider.
Apa yang terjadi jika saya kehilangan kunci enkripsi Open Connector?
Kredensial yang tersimpan tidak dapat didekripsi, dan tidak ada pemulihan. Kunci tersebut sengaja tidak pernah disimpan bersama data, sehingga tidak seorang pun yang memegang database dapat membacanya, termasuk Anda. Satu-satunya pilihan adalah menetapkan kunci baru dan menghubungkan ulang setiap provider. Simpan kunci di pengelola kata sandi dan database dalam rotasi pencadangan Anda, karena pemulihan memerlukan keduanya.
Apakah agen AI saya dapat melihat token akses provider?
Tidak jika agen memanggil melalui gateway. Agen melakukan autentikasi dengan token runtime yang diawali oct_, lalu gateway menyisipkan kredensial provider ke dalam request keluar di server dan hanya mengembalikan respons. Dua hal dapat menghilangkan perlindungan ini: endpoint /v1/proxy/:service, yang meneruskan request mentah dengan kredensial Anda terlampir dan memiliki grant yang sejak awal kosong karena alasan tertentu, serta menempelkan kunci API langsung ke agen, yang sepenuhnya melewati gateway.
Apakah gateway harus dapat diakses dari internet publik?
Hanya /oauth/callback yang harus dapat diakses. Publikasikan 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 pemanggilan action tanpa header authorization. Jika berhasil, batasi /api, /v1, dan /mcp pada proxy hanya ke alamat yang digunakan agen Anda sampai hanya pemanggilan yang terautentikasi yang berhasil.
Apakah Open Connector siap digunakan dalam produksi?
Open Connector menggunakan lisensi Apache 2.0 dan berkembang dengan cepat: repositori tersebut muncul pada 29 June 2026 dan v1.3.3 dirilis pada 30 July 2026, sehingga anggap setiap nomor versi dalam panduan ini sebagai snapshot per 1 August 2026. Jalankan dengan menetapkan release tag, jangan pernah menggunakan latest atau tip, baca catatan rilis sebelum setiap upgrade, dan simpan cadangan volume yang pernah Anda pulihkan setidaknya satu kali. Desainnya baik untuk sistem yang Anda miliki, dan risikonya terletak pada perubahan versi, bukan pada arsitekturnya.