Як розгорнути Open Connector для AI-агентів
Запустіть Open Connector на власному VPS: закріпіть image, налаштуйте TLS origin і OAuth callbacks, а стан збережіть у резервних копіях SQLite.
Що Open Connector робить для AI-агента
Самостійне розгортання Open Connector створює один шлюз автентифікації між вашими AI-агентами та кожним API програмного забезпечення як послуги (SaaS), до якого вони звертаються. Тому агент ніколи не зберігає токен постачальника. Це шлюз із відкритим вихідним кодом від OOMOL Lab, ліцензований за Apache 2.0. Він працює як один контейнер, зберігає стан в одному файлі SQLite і надає дії постачальників через HTTP та MCP (протокол контексту моделі).
Проблеми починаються з другої інтеграції. Кожен постачальник має власний процес OAuth (відкритої авторизації), власний термін дії токена оновлення та власні назви областей доступу. Ручне підключення п’яти постачальників до агента означає п’ять обробників перенаправлення, п’ять сховищ облікових даних і п’ять циклів оновлення, які мають виконуватися до завершення терміну дії токена. Майже ніхто не пише такий код. Замість цього створюють один довгоживучий персональний токен доступу для кожної служби й вставляють його в конфігурацію агента, файл середовища або сам prompt. Тоді цей токен може читати кожен інструмент, який запускає агент, і він потрапляє до транскрипту. Саме цю проблему описує запобігання витоку секретів із AI-агентів.
Шлюз автентифікації розділяє облікові дані на дві частини. Шлюз зберігає облікові дані постачальника та виконує процес OAuth. Агент отримує токен виконання, дійсний лише для звернень до шлюзу. Коли агент викликає дію, шлюз завантажує збережені облікові дані, додає їх до вихідного запиту на стороні сервера та повертає лише тіло відповіді. Агент ніколи не отримує токен доступу постачальника. Тому витік транскрипту агента коштує вам одного токена виконання, який можна відкликати, а не облікового запису GitHub.
Каталог заявляє про понад 1,000 постачальників і 10,000 готових дій. Це власні дані проєкту, які неможливо перевірити ззовні. Натомість можна перевірити структуру: одна кінцева точка HTTP для кожної дії, одне збережене підключення для кожного постачальника та один токен для кожного агента.
Навіщо розгортати Open Connector самостійно, а не використовувати керований сервіс конекторів
Керований сервіс конекторів виконує ту саму роботу та зберігає токени оновлення для кожного підключеного постачальника. Токен оновлення для Google або GitHub — це довготривалий ключ до вашої пошти та репозиторіїв. Зазвичай він залишається дійсним навіть після зміни пароля. Якщо такий сервіс буде зламано, буде скомпрометовано і ваші дані. Самостійне розгортання переносить ці записи до SQLite на сервері, який ви орендуєте та адмініструєте. Дані захищено ключем, який ніколи не залишає ваш сервер.
Перед початком оцініть витрати та ризики. Цей VPS стане найціннішим сервером у вашій інфраструктурі. В одному файлі він зберігатиме чинні облікові дані для десятка сервісів. Тому ставтеся до нього так само, як до хоста менеджера паролів: налаштуйте firewall, який відкриває лише 443, не використовуйте спільні облікові записи, створіть резервну копію та хоча б один раз перевірте її відновлення. Також налаштуйте сповіщення, якщо сервер перестане відповідати. Якщо ви не розмістили б на цьому сервері сховище паролів, не розміщуйте на ньому й конектор.
Закріпіть версію перед інсталяцією будь-чого
Open Connector — молодий проєкт. Репозиторій уперше з’явився 29 June 2026, а станом на 1 August 2026 найновішим позначеним випуском є v1.3.3, опублікований 30 July 2026 і також позначений тегом latest. Реєстр також публікує тег tip, зібраний із найновішого коміту в main.
У такого нового проєкту змінні теги часто оновлюються. docker compose pull, який перескакує через два випуски, може змінити кінцеву точку, від якої залежить ваш агент, і ви витратите вечір на налагодження проблеми, помилково вважаючи її проблемою агента. Закріпіть образ за тегом випуску та оновлюйте його, коли вирішите це зробити, попередньо ознайомившись із нотатками до випуску.
Розгортання Open Connector за TLS на власному VPS
Перш ніж запускати контейнер, потрібно:
- Docker із плагіном Compose на Ubuntu 24.04 або близькій до неї системі
- ім’я хоста, A-запис якого вказує на цей VPS, наприклад
connect.example.com - зворотний проксі, який уже завершує TLS (безпеку транспортного рівня) для цього імені хоста
- два випадкові секрети, згенеровані нижче
У посібнику Зворотний проксі Traefik для кількох застосунків Docker Compose описано налаштування проксі. Повний процес налаштування сертифікатів для одного застосунку наведено в посібнику n8n на VPS із Docker і HTTPS.
Спочатку згенеруйте секрети. Ключ шифрування захищає збережені облікові дані. Токен адміністратора захищає вебконсоль і весь інтерфейс /api. Для жодного з них немає значення за замовчуванням, але середовище виконання без них запускається без помилок.
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Збережіть обидва значення у менеджері паролів зараз, до першого запуску. Ключ шифрування неможливо відновити. Причину наведено нижче у списку помилок.
Тепер compose.yaml. Він відрізняється від прикладу з upstream у двох місцях, і обидві зміни важливі.
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:Перша зміна — зафіксований тег замість latest. Друга — порт. Файл upstream публікує 3000:3000, що прив’язує порт до всіх інтерфейсів хоста. Docker записує опубліковані порти до таблиці NAT (трансляції мережевих адрес) ще до того, як пакет потрапляє до ланцюжка фільтрації ufw. Тому ufw deny 3000 не закриває цей порт. Цю проблему описано в чому порти Docker обходять ufw. Запис 127.0.0.1:3000:3000 публікує порт лише на інтерфейсі loopback, а зворотний проксі підключається з цього самого хоста.
:? позначає кожну змінну як обов’язкову. Тому стек відмовляється запускатися, якщо .env відсутня, замість запуску зі незашифрованими обліковими даними. Зберігання значень у .env, а не у файлі compose — це підхід із файли середовища та секрети 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 повертає { "ok": true } після запуску середовища виконання. ss має вивести 127.0.0.1:3000. Рядок із текстом 0.0.0.0:3000 означає, що зіставлення портів досі відповідає upstream-варіанту, а шлюз напряму відповідає всьому Інтернету. Відмова в підключенні під час перевірки стану означає, що контейнер ще не прослуховує порт. Перед зміною конфігурації проксі перегляньте журнали.
Мітки Traefik для того самого сервісу
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"Якщо Traefik працює в Docker на тому самому хості, під’єднайте цей сервіс до мережі Traefik і видаліть блок ports:. Traefik підключається до контейнера через внутрішню мережу, тому публікувати порт на хості не потрібно. certresolver=le має відповідати назві resolver у статичній конфігурації Traefik. Інакше маршрутизатор запуститься без сертифіката.
Чому OAuth вимагає справжнього імені хоста
OOMOL_CONNECT_ORIGIN — це параметр, який часто пропускають. Через це OAuth не працює, і проблему легко помилково сприйняти як помилку провайдера. Середовище виконання формує URI перенаправлення на основі цього джерела у форматі <origin>/oauth/callback. Якщо параметр не задано, джерелом за замовчуванням стає http://localhost:3000. Тому середовище виконання надсилає провайдеру URI перенаправлення http://localhost:3000/oauth/callback, тоді як у вашому OAuth-застосунку зареєстровано https://connect.example.com/oauth/callback. Ці два рядки відрізняються, тому GitHub відповідає:
The redirect_uri MUST match the registered callback URL for this application.Провайдер OAuth перенаправляє браузер назад на цей URI. Отже, це має бути адреса, доступна із зовнішньої мережі. Провайдери відхиляють звичайний http:// для всіх адрес, крім localhost. Саме тому для цього розгортання потрібні ім’я хоста та сертифікат. Задайте джерело до першого запуску, оскільки значення зчитується під час запуску. Після редагування .env або compose.yaml знову виконайте docker compose up -d, щоб застосувати зміни.
Підключіть свого першого постачальника через OAuth
Спочатку створіть OAuth-застосунок у постачальника. У GitHub відкрийте Settings, потім Developer settings, далі OAuth Apps і виберіть New OAuth App. Укажіть URL зворотного виклику авторизації: https://connect.example.com/oauth/callback. Збережіть client ID і client secret.
Кожен виклик /api містить токен адміністратора, тому експортуйте його один раз для сеансу shell.
export ADMIN_TOKEN='paste-the-admin-token'
curl -s https://connect.example.com/api/oauth/configs \
-H "authorization: Bearer $ADMIN_TOKEN"У цьому списку показано URI перенаправлення, який runtime очікує для кожного постачальника. Це найшвидший спосіб перевірити, що origin застосовано. Якщо там і далі зазначено localhost, контейнер працює зі старим значенням, тому потік OAuth завершиться помилкою на останньому кроці.
Збережіть облікові дані клієнта та розпочніть авторизацію.
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"}'Другий виклик повертає authorizationUrl. Відкрийте його у браузері та підтвердьте дозволи. Після цього постачальник поверне браузер до /oauth/callback, де runtime обміняє код і збереже облікові дані. Вебконсоль за вашим origin виконує ті самі кроки через форму, використовуючи той самий токен адміністратора. Постачальники, які використовують звичайний API-ключ, пропускають усі ці кроки: PUT /api/connections/<service> з {"authType":"api_key","values":{"apiKey":"..."}} безпосередньо зберігає ключ.
Надавайте кожному агенту токен часу виконання, а не облікові дані
Агент автентифікується на шлюзі за допомогою токена часу виконання, який створює адміністративний 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"}'У відповіді міститься токен, що починається з oct_. Створюйте окремий токен для кожного агента та називайте його на честь цього агента. Якщо токен неможливо ідентифікувати, його відкликання означатиме відкликання всіх токенів. Після цього агент викликає дії через звичайний 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":{}}'Коректна відповідь — це конверт, у якому поле success має значення true, а корисне навантаження провайдера міститься в data. Токена GitHub у цій відповіді немає. Для клієнта MCP укажіть https://connect.example.com/mcp і використовуйте той самий bearer-заголовок. Шлюз надає інструменти виявлення, зокрема search_actions і execute_action, а не окремий інструмент для кожного API. Це зменшує розмір списку інструментів агента. У розділі Запуск MCP-серверів на VPS описано налаштування клієнта.
Перед завершенням виконайте ще одну перевірку. Повторіть виклик дії, видаливши заголовок authorization. У власному короткому посібнику проєкт викликає /v1 взагалі без bearer-токена. Отже, інсталяція без налаштованої автентифікації часу виконання виконуватиме дії для будь-кого, хто має доступ до порту. Якщо неавтентифікований виклик завершується успішно, є два варіанти: налаштувати токени часу виконання та перевірити, що анонімний виклик тепер завершується помилкою, або обмежити /api, /v1 і /mcp на reverse proxy адресами, з яких підключаються ваші агенти. Відкритим для всього світу має залишатися лише /oauth/callback, оскільки це єдиний шлях, потрібний для перенаправлення браузера провайдера.
Скоротіть список дій до необхідного агенту
Шлюз із тисячею постачальників створює для мовної моделі надто широку поверхню доступу. Два елементи керування дають змогу її звузити.
OOMOL_CONNECT_ALLOWED_ACTIONS приймає список дозволених дій через кому та підтримує service.* і *. OOMOL_CONNECT_BLOCKED_ACTIONS — це список заборонених дій, який має пріоритет. Якщо встановити список дозволених дій у значення github.get_current_user,github.list_issues, усі інші дії буде відхилено незалежно від запиту агента. Саме це відрізняє помилку від інциденту. Токени часу виконання мають власні правила дій поверх глобальних правил, а їхній список allowedProxies за замовчуванням порожній. Тому дію POST /v1/proxy/:service буде відхилено, доки ви явно не надасте для неї дозвіл. Ця кінцева точка проксі пересилає необроблений запит постачальнику, додаючи ваші облікові дані. Залиште її порожньою, якщо вона не потрібна конкретному агенту.
OOMOL_CONNECT_ALLOW_PRIVATE_NETWORK має значення false за замовчуванням. Це не дає підключенню до розгорнутого власноруч постачальника звертатися до приватної адреси, наприклад до служби метаданих хмари на 169.254.169.254 або до вашої бази даних у тій самій мережі. Залиште цей параметр вимкненим. Увімкніть його лише для постачальника, який ви розміщуєте самостійно.
Створіть резервну копію системи, у якій зберігаються всі токени
Важливі дві речі, і кожна з них без іншої непридатна. База даних у /app/data/connect.sqlite всередині тому connector-data містить зашифровані облікові дані. Криптографічний ключ у .env розшифровує їх. Резервна копія тому без ключа нічого не відновить, а ключ без тому також нічого не відновить. Тому ключ слід зберігати в менеджері паролів, а том — у звичайному циклі резервного копіювання.
Зупиніть контейнер, перш ніж копіювати файл SQLite. Копія, створена під час запису, може відновитися як пошкоджена база даних.
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Назва тому складається з назви каталогу проєкту та _connector-data. Саме тому потрібна перша команда: вставте фактичну назву в третю команду. Передайте архів за межі VPS за допомогою резервних копій restic із VPS. Ця команда шифрує архів перед передаванням, оскільки архів містить сховище облікових даних.
Середовище виконання зберігає останні запуски операцій як записи аудиту — за замовчуванням 5,000 записів. Тому консоль може показати, який агент і що саме запускав та коли. Цей журнал потрібно читати насамперед, коли агент працює незвично. Також налаштуйте сторінку стану Uptime Kuma для https://connect.example.com/health. Коли шлюз перестає відповідати, агенти завершуються з незрозумілими помилками. Якщо відомо, що шлюз не працює, не доведеться витрачати годину на аналіз виводу агента.
Що виходить з ладу та яке повідомлення ви побачите
redirect_uri_mismatch у постачальника. Джерело та зареєстрована URL-адреса зворотного виклику відрізняються. Порівняйте точний рядок із /api/oauth/configs із налаштуваннями застосунку в постачальника, зокрема https із http, а також перевірте кінцеву косу риску.
Кожен виклик /api повертає 401. Заголовок із токеном адміністратора відсутній або містить помилку. Заголовок має назву Authorization: Bearer <token>, і вебконсоль запитує той самий токен.
Контейнер запускається, а облікові дані зберігаються у відкритому тексті. Це відбувається, коли OOMOL_CONNECT_ENCRYPTION_KEY не передається до контейнера, оскільки середовище виконання зберігає записи облікових даних без шифрування, замість того щоб відмовитися від запуску. Перевірте це у власному розгортанні: підключіть постачальника за допомогою API-ключа, який можна розпізнати, а потім знайдіть його в базі даних.
docker compose cp connector:/app/data/connect.sqlite /tmp/connect.sqlite
grep -c 'github_pat_' /tmp/connect.sqlite
shred -u /tmp/connect.sqliteЗначення, більше за 0, означає, що ключ не застосовується. Перевірте, чи .env розташований у тому самому каталозі, що й compose.yaml, і чи docker compose config показує це значення. Якщо ключ задано, той самий пошук повертає 0, оскільки запис зашифровано за допомогою AES-256-GCM (advanced encryption standard, 256-bit key, Galois/counter mode).
Після відновлення нічого не розшифровується. Ключ шифрування змінено або втрачено. За задумом його ніколи не записують поруч із даними, тому шляху відновлення немає, і звернення до служби підтримки не допоможе. Повторно підключіть усіх постачальників. Ротація підтримується через окрему змінну ключа та команду роботи з даними в середовищі виконання, тому перед ротацією ознайомтеся з поточними примітками до випуску.
Агент повертає помилку із зазначенням дії, яку він бачить у каталозі. Виявлення та виконання є окремими процесами. Дія може відображатися в search_actions, але все одно бути відхиленою через OOMOL_CONNECT_ALLOWED_ACTIONS, denylist або власні правила цього токена середовища виконання.
Оновлення. Створіть резервну копію тому, змініть тег образу на тег нового випуску, а потім виконайте docker compose pull && docker compose up -d. Перевірте docker compose logs -n 50 connector на наявність повідомлення про міграцію. Після цього повторно виконайте перевірку стану та одну реальну дію, перш ніж знову вважати систему надійною. Відкат означає повернення старого тега. Це працює лише тому, що ви зафіксували його.
FAQ
Чи потрібен мені публічний домен для самостійного розгортання Open Connector?
Для провайдерів, які використовують API key, ні: достатньо шлюзу на 127.0.0.1. Для OAuth — фактично так. Провайдер перенаправляє браузер на вашу URL-адресу зворотного виклику, тому ця URL-адреса має бути доступною з публічного інтернету, а провайдери не приймають звичайний http:// поза localhost. Установіть OOMOL_CONNECT_ORIGIN на ім’я вашого хоста https:// до першого запуску та зареєструйте <origin>/oauth/callback в OAuth-застосунку провайдера.
Що станеться, якщо я втрачу ключ шифрування Open Connector?
Збережені облікові дані неможливо розшифрувати, і відновлення не передбачено. Ключ навмисно не зберігається разом із даними, тому ніхто, хто має базу даних, не зможе їх прочитати, зокрема й ви. Єдиний варіант — установити новий ключ і повторно підключити кожного провайдера. Зберігайте ключ у менеджері паролів, а базу даних включіть до циклу резервного копіювання, оскільки для відновлення потрібні обидва компоненти.
Чи може мій AI-агент бачити токен доступу провайдера?
Ні, якщо він виконує виклики через шлюз. Агент автентифікується за допомогою токена середовища виконання, що починається з oct_, а шлюз додає облікові дані провайдера до вихідного запиту на сервері та повертає лише відповідь. Цю властивість порушують дві речі: кінцева точка /v1/proxy/:service, яка пересилає необроблені запити з доданими вашими обліковими даними, і дозволи для якої спочатку порожні не без причини; а також самостійне вставлення API key в агент, що повністю обходить шлюз.
Чи має шлюз бути доступним із публічного інтернету?
Доступною має бути лише /oauth/callback. Опублікуйте порт контейнера на 127.0.0.1, щоб правила NAT Docker не могли відкрити його за межі вашого брандмауера, і розмістіть reverse proxy перед ним. Потім перевірте один виклик дії без заголовка authorization. Якщо він успішний, обмежте /api, /v1 і /mcp на reverse proxy адресами, які використовують ваші агенти, доки єдиними робочими не залишаться автентифіковані виклики.
Чи готовий Open Connector до використання в production?
Він ліцензований за Apache 2.0 і швидко розвивається: репозиторій з’явився 29 June 2026, а v1.3.3 було випущено 30 July 2026, тому сприймайте кожен номер версії в цьому посібнику як знімок станом на 1 August 2026. Запускайте його з фіксацією на release tag, ніколи не використовуйте latest або tip, перед кожним оновленням читайте примітки до випуску та зберігайте резервну копію volume, яку ви вже одного разу відновили. Архітектура придатна для сервера, що належить вам. Основний ризик — часті зміни версій, а не архітектура.