SSD Nodes Learn Hosting plans →
راهنماها Matt Connorتوسط Matt Connor

نصب Open Connector روی VPS برای ایجنت‌های AI

درگاه احراز هویت Open Connector را روی VPS خود اجرا کنید تا توکن SaaS نزد ایجنت نباشد؛ با image ثابت، TLS، callbackهای OAuth و پشتیبان‌گیری از SQLite.

نقش Open Connector برای یک ایجنت هوش مصنوعی

میزبانی شخصی (self-hosting) ابزار Open Connector یک درگاه احراز هویت واحد بین ایجنت‌های هوش مصنوعی شما و تمام APIهای سرویس‌های نرم‌افزاری (SaaS) که فراخوانی می‌کنند، قرار می‌دهد تا ایجنت هرگز توکن ارائه‌دهنده را در اختیار نداشته باشد. این یک درگاه با کد منبع در دسترس (source-available) از OOMOL Lab است که در حال حاضر تحت مجوز اصلاح‌شده Apache 2.0 با شرایط اضافی ارائه می‌شود. نسخه‌های تا v1.9.4 تحت مجوز Apache 2.0 باقی می‌مانند؛ اما نسخه v1.9.5 تغییرات را اعمال کرد. ارائه یک سرویس میزبانی‌شده یا مدیریت‌شده که ارزش اصلی آن عملکرد OpenConnector باشد، نیازمند دریافت مجوز تجاری از OOMOL است. این ابزار به صورت یک کانتینر اجرا می‌شود، وضعیت خود را در یک فایل SQLite واحد نگه می‌دارد و اقدامات ارائه‌دهنده را از طریق HTTP و پروتکل MCP (مدل کانتکست پروتکل) ارائه می‌دهد.

مشکلات از دومین یکپارچه‌سازی شروع می‌شود. هر ارائه‌دهنده، جریان OAuth (احراز هویت باز) خاص خود، طول عمر توکن رفرش متفاوت و نام‌های محدوده (scope) مختص به خود را دارد. اتصال دستی پنج ارائه‌دهنده به یک ایجنت به معنای پیاده‌سازی پنج هندلر تغییر مسیر، پنج ذخیره‌گاه اعتبارنامه و پنج حلقه رفرش است که باید پیش از انقضای توکن اجرا شوند. تقریباً هیچ‌کس چنین کدی را نمی‌نویسد. آن‌ها برای هر سرویس یک توکن دسترسی شخصی با طول عمر بالا ایجاد کرده و آن را در پیکربندی ایجنت، یک فایل محیطی (environment file) یا خودِ پرامپت قرار می‌دهند. آن توکن سپس توسط هر ابزاری که ایجنت اجرا می‌کند قابل خواندن است و در متن گفتگو (transcript) ثبت می‌شود، که این همان شکستی است که در جلوگیری از نشت اسرار در ایجنت‌های هوش مصنوعی توضیح داده شده است.

یک درگاه احراز هویت، اعتبارنامه را به دو بخش تقسیم می‌کند. درگاه، اعتبارنامه ارائه‌دهنده را ذخیره کرده و جریان OAuth را اجرا می‌کند. ایجنت یک توکن زمان اجرا (runtime token) دریافت می‌کند که فقط برای درگاه معتبر است. هنگامی که ایجنت یک عملیات را فراخوانی می‌کند، درگاه اعتبارنامه ذخیره‌شده را بارگذاری کرده، آن را در سمت سرور به درخواست خروجی تزریق می‌کند و فقط بدنه پاسخ را برمی‌گرداند. ایجنت هرگز توکن دسترسی ارائه‌دهنده را دریافت نمی‌کند، بنابراین نشت متن گفتگوی ایجنت تنها هزینه یک توکن زمان اجرای قابل ابطال را برای شما خواهد داشت، نه دسترسی به حساب GitHub شما.

کاتالوگ این ابزار بیش از 1,000 ارائه‌دهنده و 10,000 عملیات از پیش ساخته‌شده را تبلیغ می‌کند که این آمار متعلق به خود پروژه است و از بیرون قابل راستی‌آزمایی نیست. آنچه می‌توانید تأیید کنید، ساختار آن است: یک نقطه پایانی HTTP برای هر عملیات، یک اتصال ذخیره‌شده برای هر ارائه‌دهنده و یک توکن برای هر ایجنت. اگر سمت ایجنت این موضوع هنوز جدید است و اصطلاحاتی مانند tool call یا MCP server هنوز تثبیت نشده‌اند، مسیر مرحله‌بندی‌شده در چگونه ایجنت‌های هوش مصنوعی را از صفر یاد بگیریم، حلقه، ابزارها و عادت‌های امنیتی را ایجاد می‌کند که درگاهی مانند این ابزار فرض می‌کند شما از قبل آن‌ها را دارید.

چرا به‌جای استفاده از سرویس‌های میزبانی‌شده، Open Connector را خودتان میزبانی کنید

یک سرویس کانکتور میزبانی‌شده همان کار را انجام می‌دهد و refresh tokenهای مربوط به هر ارائه‌دهنده‌ای که به آن متصل می‌کنید را نزد خود نگه می‌دارد. یک refresh token برای Google یا GitHub، کلیدی با طول عمر زیاد برای دسترسی به ایمیل‌ها و مخازن شماست. رخنه در آن‌ها، به معنای رخنه در حساب شماست. خودمیزبانی (self-hosting)، این رکوردها را به یک دیتابیس SQLite روی ماشینی که اجاره کرده و مدیریت می‌کنید منتقل می‌کند و آن‌ها را با کلیدی که هرگز از دستگاه شما خارج نمی‌شود، مهر و موم می‌کند.

پیش از شروع، هزینهٔ آن را در نظر بگیرید. این VPS به ارزشمندترین سروری تبدیل می‌شود که اجرا می‌کنید. این سرور اعتبارنامه‌های فعال برای 12 سرویس را در یک فایل نگه می‌دارد، بنابراین باید همان رفتاری را با آن داشته باشید که با میزبانِ مدیریت رمز عبور خود دارید: فایروالی که فقط پورت 443 را باز می‌گذارد، عدم استفاده از لاگین‌های اشتراکی، بک‌آپی که حداقل یک‌بار آن را بازیابی کرده‌اید، و سیستمی برای هشدار در زمانی که سرور پاسخ نمی‌دهد. اگر حاضر نیستید مخزن رمز عبور خود را روی این دستگاه قرار دهید، کانکتور را نیز روی آن نصب نکنید.

پیش از نصب هر چیزی، نسخه را ثابت (Pin) کنید

Open Connector پروژه نوپایی است. این راهنما نسخه v1.3.3 را که در تاریخ 30 July 2026 منتشر شده است، به عنوان snapshot نصب برای تاریخ 1 August 2026 ثابت نگه می‌دارد. این نسخه دیگر جدیدترین release موجود نیست. رجیستری یک تگ tip نیز منتشر می‌کند که از جدیدترین commit در main ساخته شده است.

در پروژه‌ای به این تازگی، تگ‌های متغیر به‌سرعت تغییر می‌کنند. یک docker compose pull که دو نسخه را پشت سر می‌گذارد، می‌تواند endpoint مورد نیاز agent شما را تغییر دهد؛ در نتیجه مجبور خواهید شد تمام شب را صرف عیب‌یابی آن به عنوان یک مشکل در agent کنید. image را روی یک تگ release ثابت کنید و پس از مطالعه یادداشت‌های انتشار (release notes)، هر زمان که خودتان تصمیم گرفتید، آن را ارتقا دهید.

استقرار Open Connector پشت TLS روی VPS شخصی

پیش از شروع container به موارد زیر نیاز دارید:

  • Docker Engine 28.0.0 یا جدیدتر به همراه پلاگین Compose، روی Ubuntu 24.04 یا توزیع‌های مشابه
  • یک نام دامنه که رکورد A آن به این VPS اشاره می‌کند، برای مثال connect.example.com
  • یک reverse proxy که در حال حاضر TLS (امنیت لایه انتقال) را برای آن نام دامنه مدیریت می‌کند
  • دو عبارت امنیتی تصادفی که در ادامه تولید می‌شوند

راهنمای Traefik reverse proxy for multiple Docker Compose apps بخش مربوط به پروکسی را پوشش می‌دهد. جزئیات کامل پیاده‌سازی گواهی برای یک برنامه، از ابتدا تا انتها، در راهنمای n8n on a VPS with Docker and 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 را ایجاد کنید. این فایل در دو مورد با نمونه اصلی تفاوت دارد و هر دو مورد اهمیت دارند.

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 است. تغییر دوم مربوط به پورت است. فایل اصلی پورت 3000:3000 را منتشر می‌کند که به تمام اینترفیس‌های میزبان متصل می‌شود. Docker پورت‌های منتشرشده را پیش از آنکه زنجیره فیلتر ufw بسته‌ها را ببیند، در جدول NAT (ترجمه آدرس شبکه) می‌نویسد، بنابراین ufw deny 3000 آن پورت را نمی‌بندد؛ این همان دامی است که در why Docker ports bypass ufw توضیح داده شده است. نوشتن 127.0.0.1:3000:3000 باعث می‌شود پورت فقط روی اینترفیس loopback منتشر شود و reverse proxy شما از همان میزبان به آن متصل شود. پیش از Docker Engine 28.0.0، میزبان‌های موجود در همان بخش L2 می‌توانستند به پورت‌های منتشرشده روی localhost دسترسی داشته باشند، به همین دلیل این راهنما به نسخه 28.0.0 یا جدیدتر نیاز دارد.

عبارت :? هر متغیر را به‌عنوان الزامی علامت‌گذاری می‌کند، بنابراین اگر .env موجود نباشد، stack از اجرا خودداری می‌کند تا از شروع برنامه با اعتبارنامه‌های رمزنگاری‌نشده جلوگیری شود. نگهداری مقادیر در .env به‌جای فایل compose، الگوی پیشنهادی در Docker Compose env files and secrets است. تا زمانی که اولین توکن runtime را در ادامه ایجاد نکرده‌اید، /v1 و /mcp را در reverse proxy خصوصی نگه دارید.

docker compose up -d
docker compose logs -n 30 connector
curl -s http://127.0.0.1:3000/health
sudo ss -tlnp | grep 3000

پس از بالا آمدن runtime، /health به { "ok": true } پاسخ می‌دهد. ss باید 127.0.0.1:3000 را چاپ کند. خطی که 0.0.0.0:3000 را نشان می‌دهد به این معنی است که listener به تمام اینترفیس‌های IPv4 متصل شده است، اما این به معنای دسترسی از اینترنت نیست: فایروال‌های بالادستی یا قوانین موجود در زنجیره DOCKER-USER داکر همچنان می‌توانند ترافیک خارجی را مسدود کنند. خطای Connection refused در بررسی سلامت (health check) به این معنی است که container هنوز در حال گوش دادن نیست، بنابراین پیش از دست زدن به پروکسی، لاگ‌ها را بخوانید.

برچسب‌های 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 در داکر روی همان میزبان اجرا می‌شود، این سرویس را به شبکه Traefik متصل کنید و بلوک ports: را حذف کنید، زیرا Traefik از طریق شبکه داخلی به container دسترسی پیدا می‌کند و نیازی به انتشار هیچ پورتی روی میزبان نیست. certresolver=le باید با نام resolver در پیکربندی استاتیک Traefik مطابقت داشته باشد، در غیر این صورت router بدون گواهی بالا می‌آید.

چرا callbackهای OAuth به origin صحیح نیاز دارند

OOMOL_CONNECT_ORIGIN تنظیمی است که کاربران از آن غافل می‌شوند و نادیده گرفتن آن باعث می‌شود OAuth به شکلی از کار بیفتد که گویی با یک باگ در سمت سرویس‌دهنده مواجه هستید. محیط اجرا (runtime)، آدرس redirect URI خود را بر اساس آن origin و به فرم <origin>/oauth/callback می‌سازد. اگر این مقدار تنظیم نشود، origin به‌صورت پیش‌فرض http://localhost:3000 در نظر گرفته می‌شود؛ بنابراین محیط اجرا، یک redirect 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 بازمی‌گرداند، بنابراین آن آدرس باید برای مرورگر قابل دسترس باشد. OAuth لزوماً به یک hostname عمومی نیاز ندارد: مستندات OpenConnector، آدرس callbackهای GitHub را در http://localhost:3000/oauth/callback توضیح داده است. این استقرار روی VPS از یک hostname و گواهی استفاده می‌کند تا مرورگر بتواند از طریق origin مبتنی بر HTTPS به gateway برسد. origin را پیش از اولین اجرا تنظیم کنید، زیرا این مقدار در زمان شروع برنامه خوانده می‌شود: پس از ویرایش .env یا compose.yaml، برای اعمال تغییرات، docker compose up -d را دوباره اجرا کنید.

اتصال اولین ارائه‌دهنده از طریق OAuth

ابتدا برنامه OAuth را در پنل ارائه‌دهنده ایجاد کنید. در GitHub، مسیر Settings، سپس Developer settings، سپس OAuth Apps و در نهایت New OAuth App را دنبال کنید. آدرس بازگشت (callback URL) احراز هویت را روی https://connect.example.com/oauth/callback تنظیم کنید. شناسه کلاینت (client ID) و رمز کلاینت (client secret) را نزد خود نگه دارید.

هر فراخوانی /api شامل توکن مدیریت (admin token) است، بنابراین آن را یک‌بار برای نشست (session) فعلی shell صادر (export) کنید.

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

این لیست، URI تغییر مسیر (redirect URI) مورد انتظار runtime برای هر ارائه‌دهنده را نشان می‌دهد؛ این سریع‌ترین راه برای بررسی اعمال شدن تنظیمات شماست. اگر همچنان مقدار 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 برمی‌گرداند. آن را در مرورگر باز کنید، دامنه‌های دسترسی (scopes) را تأیید کنید تا ارائه‌دهنده مرورگر را به /oauth/callback بازگرداند؛ جایی که runtime کد را مبادله کرده و اعتبارنامه را ذخیره می‌کند. کنسول وب در مبدأ شما، همین مراحل را از طریق یک فرم و با استفاده از همان توکن مدیریت انجام می‌دهد. ارائه‌دهندگانی که از کلید API ساده استفاده می‌کنند، از تمام این مراحل عبور می‌کنند: PUT /api/connections/<service> به همراه {"authType":"api_key","values":{"apiKey":"..."}} کلید را مستقیماً ذخیره می‌کند.

به هر ایجنت یک توکن زمان اجرا اختصاص دهید، نه اعتبارنامه اصلی

ایجنت با استفاده از یک توکن زمان اجرا (runtime token) که توسط 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 باشد و payload ارائه‌دهنده در زیر data قرار گیرد. توکن GitHub در هیچ کجای این پاسخ وجود ندارد. برای یک کلاینت MCP، آن را به https://connect.example.com/mcp با همان هدر bearer اشاره دهید؛ گیت‌وی به جای ارائه یک ابزار به ازای هر API، ابزارهای کشف مانند search_actions و execute_action را ارائه می‌دهد که باعث می‌شود لیست ابزارهای ایجنت کوچک باقی بماند. بخش اجرای سرورهای MCP روی یک VPS به نیمه کلاینتی این اتصال می‌پردازد.

پیش از آنکه کار را تمام‌شده تلقی کنید، یک بررسی دیگر انجام دهید. فراخوانی عملیات را با حذف هدر authorization تکرار کنید. راهنمای شروع سریع خود پروژه، /v1 را بدون هیچ‌گونه bearer فراخوانی می‌کند؛ بنابراین نصبی که در آن احراز هویت زمان اجرا پیکربندی نشده باشد، عملیات را برای هر کسی که به پورت دسترسی داشته باشد، اجرا خواهد کرد. اگر فراخوانی بدون احراز هویت شما موفقیت‌آمیز بود، دو راه پیش رو دارید: توکن‌های زمان اجرا را پیکربندی کنید و تأیید کنید که فراخوانی ناشناس اکنون با شکست مواجه می‌شود، یا دسترسی به /api، /v1 و /mcp را در reverse proxy به آدرس‌هایی که ایجنت‌های شما از آنجا می‌آیند، محدود کنید. /oauth/callback باید توسط مرورگری که فرآیند احراز هویت را تکمیل می‌کند قابل دسترسی باشد؛ نیازی نیست که این مسیر برای کل اینترنت باز باشد.

فهرست عملیات را به آنچه عامل نیاز دارد محدود کنید

یک درگاه (gateway) با هزاران ارائه‌دهنده در پشت آن، سطح حمله گسترده‌ای را در اختیار یک مدل زبانی قرار می‌دهد. این سطح زمانی گسترده‌تر می‌شود که مدل شروع به خواندن متنی کند که خودش ننوشته است؛ زیرا صفحه‌ای که توسط نمونه SearXNG شخصی شما که به جستجوهای وب عامل پاسخ می‌دهد بازگردانده می‌شود، می‌تواند حاوی دستورالعمل‌هایی باشد که هر عملیاتی را که عامل در اختیار دارد، هدف قرار دهد. همان خویشتن‌داری که باعث می‌شود یک عامل کدنویسی کوچک‌ترین تغییرِ کارآمد را اعمال کند، باید در مجوزهای آن نیز رعایت شود: تنها تعداد انگشت‌شماری از عملیاتی را که برای انجام کار ضروری هستند به آن اعطا کنید و فراتر از آن چیزی ندهید. دو کنترل این دسترسی را محدود می‌کنند.

OOMOL_CONNECT_ALLOWED_ACTIONS یک لیست مجاز (allowlist) با جداکننده کاما می‌پذیرد و service.* و * را درک می‌کند. OOMOL_CONNECT_BLOCKED_ACTIONS لیست سیاه (denylist) است و اولویت با لیست سیاه است. تنظیم لیست مجاز روی github.get_current_user,github.list_issues به این معنی است که هر عملیات دیگری صرف‌نظر از درخواست عامل، رد می‌شود؛ این همان تفاوتی است که یک اشتباه را از یک حادثه امنیتی متمایز می‌کند. توکن‌های زمان اجرا (Runtime tokens) قوانین عملیاتی خاص خود را علاوه بر قوانین سراسری اعمال می‌کنند و لیست allowedProxies آن‌ها در ابتدا خالی است، بنابراین POST /v1/proxy/:service تا زمانی که آن را صراحتاً اعطا نکنید، رد می‌شود. آن نقطه پایانی پروکسی (proxy endpoint)، یک درخواست خام را به همراه اعتبارنامه شما به ارائه‌دهنده ارسال می‌کند، بنابراین آن را خالی بگذارید مگر اینکه یک عامل خاص به آن نیاز داشته باشد.

OOMOL_CONNECT_ALLOW_PRIVATE_NETWORK به‌صورت پیش‌فرض روی false تنظیم شده است که مانع از آن می‌شود که اتصال به یک ارائه‌دهنده میزبانی‌شده توسط خودتان (self-hosted)، به یک آدرس خصوصی مانند سرویس متادیتای ابری در 169.254.169.254 یا پایگاه داده شما در همان شبکه اشاره کند. آن را غیرفعال بگذارید. فقط برای ارائه‌دهنده‌ای که خودتان میزبانی می‌کنید، آن را فعال کنید.

پشتیبان‌گیری از سروری که تمام توکن‌ها را نگهداری می‌کند

دو مورد اهمیت دارند و هر کدام بدون دیگری بی‌فایده است. پایگاه داده در /app/data/connect.sqlite داخل volume مربوط به connector-data، اعتبارنامه‌های مهر و موم شده را نگه می‌دارد. کلید رمزنگاری در .env آن‌ها را از حالت مهر و موم خارج می‌کند. پشتیبان‌گیری از volume بدون کلید، چیزی را بازیابی نمی‌کند و کلید بدون volume نیز کارایی ندارد؛ بنابراین کلید باید در مدیریت رمز عبور شما ذخیره شود و volume باید در چرخه پشتیبان‌گیری معمول شما قرار گیرد.

هنگام کپی کردن فایل 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

نام volume برابر است با دایرکتوری پروژه شما به اضافه _connector-data، به همین دلیل دستور اول در آنجا قرار دارد: نام واقعی را در دستور سوم جای‌گذاری کنید. آرشیو را با استفاده از پشتیبان‌گیری restic از یک VPS از روی VPS خارج کنید؛ این ابزار پیش از خروج داده‌ها، آن‌ها را رمزنگاری می‌کند، زیرا آن آرشیو در واقع مخزن اعتبارنامه‌ها است.

محیط اجرا (runtime)، آخرین عملیات‌های انجام شده را به عنوان سوابق حسابرسی (audit records) نگه می‌دارد که به‌طور پیش‌فرض 5,000 مورد است، بنابراین کنسول می‌تواند به شما بگوید کدام عامل (agent) چه کاری را در چه زمانی انجام داده است. آن لاگ اولین چیزی است که هنگام رفتار غیرعادی یک عامل باید مطالعه شود. همچنین یک صفحه وضعیت Uptime Kuma را به https://connect.example.com/health متصل کنید. هنگامی که gateway پاسخ‌دهی را متوقف می‌کند، عامل‌ها به شیوه‌های گیج‌کننده‌ای دچار خطا می‌شوند و اطلاع از اینکه gateway از دسترس خارج شده است، یک ساعت از زمان شما را برای خواندن خروجی عامل‌ها ذخیره می‌کند.

چه چیزی از کار می‌افتد و پیامی که مشاهده خواهید کرد

redirect_uri_mismatch در سمت ارائه‌دهنده. مبدأ (origin) و URL بازگشتی (callback URL) ثبت‌شده با هم تفاوت دارند. رشته دقیق را از /api/oauth/configs با تنظیمات برنامه در پنل ارائه‌دهنده مقایسه کنید؛ این بررسی شامل https در برابر http و هرگونه اسلش انتهایی (trailing slash) می‌شود.

هر فراخوانی /api با خطای 401 مواجه می‌شود. هدر توکن مدیریت (admin token) وجود ندارد یا اشتباه نوشته شده است. نام هدر Authorization: Bearer <token> است و کنسول وب نیز همان توکن را درخواست می‌کند.

کانتینر اجرا می‌شود و اعتبارنامه‌ها به صورت متن ساده (plain text) ذخیره شده‌اند. این اتفاق زمانی رخ می‌دهد که OOMOL_CONNECT_ENCRYPTION_KEY هرگز به کانتینر نمی‌رسد، زیرا runtime به جای امتناع از شروع کار، رکوردهای اعتبارنامه را بدون رمزنگاری ذخیره می‌کند. این موضوع را در نصب خود آزمایش کنید: یک ارائه‌دهنده را با یک API key که می‌شناسید متصل کنید، سپس پایگاه داده را برای یافتن آن جستجو کنید.

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

تعداد (count) بزرگ‌تر از 0 به این معنی است که کلید اعمال نشده است؛ بنابراین بررسی کنید که .env در همان دایرکتوری compose.yaml قرار داشته باشد و docker compose config مقدار آن را نشان دهد. با تنظیم صحیح کلید، همان جستجو باید مقدار 0 را برگرداند، زیرا رکورد با استاندارد AES-256-GCM (استاندارد رمزنگاری پیشرفته، کلید 256 بیتی، حالت Galois/counter) مهر و موم شده است.

پس از بازیابی (restore)، هیچ‌چیز رمزگشایی نمی‌شود. کلید رمزنگاری تغییر کرده یا گم شده است. طبق طراحی، این کلید هرگز در کنار داده‌ها ذخیره نمی‌شود، بنابراین هیچ مسیر بازیابی و هیچ تیکت پشتیبانی برای آن وجود ندارد. تمام ارائه‌دهنده‌ها را دوباره متصل کنید. چرخش کلید (rotation) از طریق یک متغیر کلید مجزا و یک دستور داده در runtime پشتیبانی می‌شود، بنابراین پیش از هرگونه چرخش، یادداشت‌های انتشار (release notes) فعلی را مطالعه کنید.

ایجنت (agent) خطایی دریافت می‌کند که به عملیاتی اشاره دارد که در کاتالوگ قابل مشاهده است. کشف (discovery) و اجرا (execution) دو فرایند مجزا هستند. یک عملیات ممکن است در search_actions ظاهر شود اما همچنان توسط OOMOL_CONNECT_ALLOWED_ACTIONS، لیست سیاه (denylist) یا قوانین مربوط به همان توکن runtime رد شود.

ارتقاها. از volume نسخه پشتیبان تهیه کنید، تگ image را به نسخه جدید تغییر دهید و سپس docker compose pull && docker compose up -d را اجرا کنید. docker compose logs -n 50 connector را برای مشاهده خط مربوط به migration زیر نظر بگیرید و پیش از اعتماد مجدد به سیستم، بررسی سلامت (health check) و یک عملیات واقعی را اجرا کنید. بازگشت به نسخه قبلی (rollback) به معنای بازگرداندن تگ قدیمی است که تنها در صورتی کار می‌کند که آن را از قبل ثابت (pin) کرده باشید.

FAQ

آیا برای میزبانی شخصی Open Connector به یک دامنه عمومی نیاز دارم؟

برای ارائه‌دهندگانی که از API key استفاده می‌کنند، خیر: یک gateway روی 127.0.0.1 کافی است. OAuth نیز لزوماً به دامنه عمومی نیاز ندارد: OpenConnector برای callback محلی GitHub از http://localhost:3000/oauth/callback استفاده می‌کند. مرورگری که عملیات احراز هویت را تکمیل می‌کند باید به URL مربوط به callback دسترسی داشته باشد. برای این استقرار روی VPS، پیش از اولین اجرا، OOMOL_CONNECT_ORIGIN را روی hostname مربوط به https:// خود تنظیم کنید و <origin>/oauth/callback را در اپلیکیشن OAuth ارائه‌دهنده ثبت نمایید.

اگر کلید رمزنگاری Open Connector را گم کنم چه می‌شود؟

اعتبارنامه‌های ذخیره‌شده قابل رمزگشایی نیستند و هیچ راهی برای بازیابی آن‌ها وجود ندارد. این کلید عمداً هرگز در کنار داده‌ها ذخیره نمی‌شود تا هیچ‌کس، حتی شما، نتواند با در اختیار داشتن دیتابیس آن را بخواند. تنها گزینه شما تنظیم یک کلید جدید و اتصال مجدد تمامی ارائه‌دهندگان است. کلید را در یک password manager و دیتابیس را در چرخه پشتیبان‌گیری خود نگه دارید، زیرا بازیابی به هر دو نیاز دارد.

آیا ایجنت هوش مصنوعی من می‌تواند به access token ارائه‌دهنده دسترسی داشته باشد؟

خیر، زمانی که از طریق gateway فراخوانی انجام می‌شود، این‌طور نیست. ایجنت با یک runtime token که با oct_ شروع می‌شود احراز هویت می‌کند و gateway اعتبارنامه ارائه‌دهنده را در درخواست خروجی روی سرور تزریق کرده و تنها پاسخ را برمی‌گرداند. دو مورد این ویژگی را نقض می‌کنند: endpoint مربوط به /v1/proxy/:service که درخواست‌های خام را با اعتبارنامه پیوست‌شده شما ارسال می‌کند (و به همین دلیل دسترسی‌های آن به‌صورت پیش‌فرض خالی است)، و وارد کردن دستی API key توسط خود شما در ایجنت که باعث می‌شود gateway کاملاً دور زده شود.

آیا gateway باید از طریق اینترنت عمومی در دسترس باشد؟

callback مربوط به OAuth باید توسط مرورگری که احراز هویت را تکمیل می‌کند قابل دسترسی باشد، که این لزوماً به معنای دسترسی از کل اینترنت نیست. با Docker Engine 28.0.0 یا جدیدتر و شبکه bridge پیش‌فرض، پورت کانتینر را روی 127.0.0.1 منتشر کنید تا پورت منتشرشده فقط از روی host قابل دسترسی باشد و سپس یک reverse proxy در مقابل آن قرار دهید. نسخه‌های قدیمی‌تر Docker به hostهای موجود در همان segment لایه 2 اجازه می‌دادند به پورت‌های منتشرشده روی localhost دسترسی پیدا کنند. سپس یک فراخوانی عملیاتی را بدون هدر authorization تست کنید. اگر موفقیت‌آمیز بود، /api، /v1 و /mcp را در proxy به آدرس‌هایی که ایجنت‌های شما استفاده می‌کنند محدود کنید تا زمانی که فقط درخواست‌های احراز هویت‌شده کار کنند.

آیا Open Connector برای استفاده در محیط عملیاتی (production) آماده است؟

نسخه‌های فعلی از یک لایسنس اصلاح‌شده Apache 2.0 با شرایط اضافی استفاده می‌کنند؛ نسخه‌های تا v1.9.4، شامل نسخه ثابت‌شده v1.3.3، همچنان تحت لایسنس Apache 2.0 باقی می‌مانند. یک سرویس connector میزبانی‌شده یا مدیریت‌شده که ارزش اصلی آن عملکرد OpenConnector است، تحت لایسنس فعلی به یک لایسنس تجاری از OOMOL نیاز دارد. دستورات نصب v1.3.3 همچنان یک snapshot از تاریخ 1 August 2026 هستند و آن نسخه در تاریخ 30 July 2026 عرضه شده است. آن را روی یک release tag ثابت نگه دارید، هرگز روی latest یا tip اجرا نکنید، پیش از هر ارتقا یادداشت‌های انتشار (release notes) را بخوانید و یک نسخه پشتیبان از volume داشته باشید که حداقل یک بار آن را بازیابی کرده‌اید. طراحی برای سروری که مالک آن هستید مناسب است و ریسک اصلی، تغییرات سریع نسخه‌هاست، نه معماری آن.

آیا این مقاله مفید بود؟

#ai-agents#oauth#self-hosting#integrations#source-available