SSD Nodes Learn Hosting plans →
راهنماها Matt Connorتوسط Matt Connor · به‌روزرسانی شده 2026-09-08

راهنمای راه‌اندازی HarnessRouter برای مدیریت APIها

با استفاده از HarnessRouter، مدل‌های Codex و Claude Code را در یک API واحد میزبانی کنید. این راهنما شامل دستور Docker، تنظیمات loopback، تغییر رمز عبور و پیکربندی TLS است.

آنچه HarnessRouter حذف می‌کند

شما HarnessRouter Community Edition را به‌صورت self-host اجرا می‌کنید تا یک API را در مقابل چندین agent harness روی سروری که مالک آن هستید، قرار دهید. یک agent harness برنامه خط فرمانی است که یک مدل را در یک حلقه هدایت می‌کند: این برنامه یک نشست (session) را حفظ می‌کند، فایل‌ها را ویرایش می‌کند، دستورات را اجرا می‌کند و پیشرفت کار را به هر منبعی که درخواست کار کرده است، استریم می‌کند. Codex، Claude Code و Hermes هر کدام این وظیفه را انجام می‌دهند و هر کدام با نصب مخصوص به خود، فرمت اعتبارنامه (credential) خاص خود و تعریف منحصر‌به‌فردی از آنچه یک نشست محسوب می‌شود، ارائه می‌شوند. HarnessRouter همه آن‌ها را درون یک container اجرا می‌کند و یک endpoint واحد HTTP، یک ورود (login) واحد و یک مخزن secret واحد را در مقابل آن‌ها قرار می‌دهد.

این کل ایده است و هزینه آن ارزش بیان کردن دارد. شما یک container، یک ورود، یک volume و یک مسیر ارتقا به سرور خود اضافه می‌کنید تا چندین بخش متحرک به یک بخش تبدیل شوند. اگر امروز دقیقاً یک harness را اجرا می‌کنید، این تنظیمات نسبت به نصب مستقیم آن harness، وضعیت بدتری است. این مبادله موضوع بخش آخر در اینجا است، بنابراین پیش از deploy کردن آن را مطالعه کنید.

همه موارد زیر با image tag 0.5.5 که در تاریخ 19 August 2026 دریافت شده، بررسی شده‌اند. این پروژه تقریباً هر روز تگ‌های جدیدی منتشر می‌کند، بنابراین به‌جای اعتماد به این صفحه در ماه آینده، تگی که در حال حاضر اجرا می‌کنید را بررسی کنید. دستورات از فایل README پروژه در github.com/HarnessRouter/harnessrouter گرفته شده‌اند.

پروتکل Unified Harness چیست

HarnessRouter پروتکل Unified Harness (UHP) را پیاده‌سازی می‌کند که در unifiedharnessprotocol.org منتشر شده است. UHP توصیف می‌کند که یک محصول چگونه وظیفه‌ای را روی یک harness آغاز می‌کند، آن را در حین اجرا دنبال می‌کند، نشست‌ها و فایل‌ها را مدیریت کرده و خرابی‌ها را گزارش می‌دهد. نسخهٔ این مشخصات بر اساس تاریخ تعیین می‌شود. نسخه‌ای که از تاریخ 19 August 2026 فعال است، تاریخ 2026-08-11 را دارد و سایت آن را یک پیش‌نویس استاندارد می‌نامد که «به‌اندازه کافی برای ساخت‌وساز پایدار است و به‌گونه‌ای نسخه‌بندی شده که بتواند با امنیت تغییر کند».

عبارت «استاندارد باز» را در اینجا با دقت بخوانید. همان شرکتی که مشخصات را می‌نویسد، پیاده‌سازی مرجع و مجموعه آزمون انطباق 52-check را نیز تهیه می‌کند که تعیین‌کنندهٔ انطباق است. این موضوع برای پروتکلی با این قدمت کم، امری عادی است و مجوز Apache-2.0 به این معنی است که شما می‌توانید هر بخشی از آن را fork کنید. این همچنین به این معنی است که UHP هنوز یک استاندارد چند-فروشنده‌ای (multi-vendor) نیست. با آن به‌عنوان یک پروتکل نوظهور برخورد کنید: مفید، در حال تغییر، و چیزی که کد شما باید بتواند بدون نیاز به بازنویسی کامل، استفاده از آن را متوقف کند.

پیش‌نیازهای شروع کار

به Docker و حدود 4 GB فضای دیسک خالی نیاز دارید. همچنین باید یک API key از ارائه‌دهنده مدلی که اشتراک آن را دارید، تهیه کنید. حجم image حدود 700 MB است و باقی فضای دیسک به agent CLIها و محیط‌های کاری (workspaces) که در آن می‌نویسند، اختصاص می‌یابد. هیچ مدلی به‌صورت پیش‌فرض همراه برنامه نیست و هیچ کلید آزمایشی درون image وجود ندارد؛ بنابراین تا زمانی که یک ارائه‌دهنده را متصل نکنید، وظایف (tasks) با شکست مواجه می‌شوند. خود HarnessRouter تحت مجوز Apache-2.0 است. agent CLIها تحت پوشش این مجوز نیستند و به همین دلیل، به‌جای اینکه در image گنجانده شوند، در اولین اجرا دانلود می‌شوند.

میزبانی HarnessRouter با یک دستور docker run

docker pull harnessrouter/harnessrouter
docker run -d --name harnessrouter \
  -p 127.0.0.1:3000:3000 \
  -v harnessrouter:/data \
  harnessrouter/harnessrouter

سپس بالا آمدن کانتینر را نظارت کنید. اولین اجرا کند است و لاگ‌ها دلیل آن را به شما می‌گویند.

docker logs -f harnessrouter

در حین انجام عملیات، خطوطی مشابه موارد زیر مشاهده خواهید کرد:

installing Claude Code (Anthropic's terms apply)…
installing Codex (Apache-2.0)…
installing Hermes (check its upstream license before use)…

منتظر ready on :3000 بمانید. این نصب فقط یک‌بار برای هر volume انجام می‌شود، بنابراین تمام دفعات بعدی اجرا، تنها چند ثانیه طول می‌کشد و هیچ خط مربوط به نصب نمایش داده نمی‌شود.

دو نکته از این دانلود استنتاج می‌شود که هر دو در یک VPS اهمیت دارند. نخست، بوت اول به دسترسی شبکه خروجی نیاز دارد. این image به‌صورت کامل و مستقل نیست، بنابراین سروری که پشت یک egress filter قرار دارد یا مسیری به اینترنت ندارد، در این مرحله متوقف می‌شود و هرگز ready on :3000 را چاپ نمی‌کند. این وضعیت در اولین اجرا شکست می‌خورد، نه در docker pull، که تشخیص آن در آن مرحله گیج‌کننده است. دوم، شما در حال نصب نرم‌افزار شخص ثالث تحت شرایط استفاده همان شخص ثالث هستید. Claude Code تحت شرایط Anthropic و Hermes تحت شرایطی که منبع اصلی آن تعیین کرده ارائه می‌شوند، بنابراین پیش از استفاده تجاری از آن‌ها، هر دو را بررسی کنید.

-v harnessrouter:/data یک Docker volume با نام ایجاد می‌کند. تمام داده‌های ماندگار در /data قرار می‌گیرند: دیتابیس‌های SQLite، فایل‌های ذخیره‌شده، مخزن کلیدهای امنیتی و محیط‌های کاری agent. اگر این volume را حذف کنید، کل instance از جمله کلیدهای ارائه‌دهنده و تمام تاریخچه‌ها پاک می‌شوند. برای تهیه نسخه پشتیبان، ابتدا کانتینر را متوقف کنید، زیرا کپی کردن دیتابیس SQLite در حالی که در حال نوشتن است، فایلی ایجاد می‌کند که ممکن است باز نشود. همین قاعده «توقف و سپس کپی» برای تمام کانتینرهای دارای state در سرور صدق می‌کند، اگرچه جزئیات آن بسته به سرویس متفاوت است، چرا که PhotoPrism و Immich هر کدام به دستورات پشتیبان‌گیری خاص خود نیاز دارند.

docker stop harnessrouter
docker run --rm -v harnessrouter:/data -v "$PWD":/backup alpine \
  tar czf /backup/harnessrouter-data.tgz -C / data
docker start harnessrouter

نسخه compose و خطی که باید تغییر دهید

این مخزن یک فایل compose ارائه می‌دهد. این فایل "3000:3000" را منتشر می‌کند که به معنای در دسترس قرار گرفتن روی تمام اینترفیس‌های میزبان است. پیش از بالا آوردن آن روی یک سرور عمومی، این خط را تغییر دهید.

services:
  harnessrouter:
    image: harnessrouter/harnessrouter:0.5.5
    ports:
      - "127.0.0.1:3000:3000"
    env_file:
      - .env
    volumes:
      - harnessrouter-data:/data
    restart: unless-stopped

volumes:
  harnessrouter-data:

دو مورد نسبت به نسخه اصلی (upstream) متفاوت است: آدرس bind و استفاده از یک تگ نسخه ثابت (pinned) به‌جای latest. ثابت کردن نسخه اهمیت دارد، زیرا بین 9 و 18 اوت 2026 شانزده تگ نسخه منتشر شد و عیب‌یابی runtime عاملی که مدام تغییر می‌کند، دشوار است. سپس فایل محیطی (environment file) را کپی کنید، دسترسی‌های آن را محدود کنید و سرویس را استارت بزنید.

cp .env.example .env
chmod 600 .env
docker compose up -d
docker compose logs -f

فایل .env کلید ارائه‌دهنده شما را به‌صورت متن ساده نگه می‌دارد، بنابراین حالت 600 حداقل سطح دسترسی لازم است. اگر زیردستور docker compose برای شما ناآشنا است، راهنمای سریع دستورات Docker Compose افعال پرکاربرد روزانه را پوشش می‌دهد.

چرا پورت روی 127.0.0.1 منتشر می‌شود و نه 0.0.0.0

-p 3000:3000 پورت را روی تمام اینترفیس‌های موجود در میزبان منتشر می‌کند. -p 127.0.0.1:3000:3000 آن را فقط روی loopback منتشر می‌کند، که به این معنی است که تنها راه دسترسی، از داخل خود VPS است. کانتینر همیشه در داخل روی پورت 3000 گوش می‌دهد، بنابراین بخش سمت چپ همان قسمتی است که باید تغییر دهید. بررسی کنید چه چیزی دارید:

docker port harnessrouter
sudo ss -ltnp | grep 3000

ss چاپ کردن 127.0.0.1:3000 صحیح است. 0.0.0.0:3000 به این معنی است که کنسول روی اینترنت عمومی قرار دارد. این وضعیت در اینجا نسبت به اکثر برنامه‌های self-hosted خطرناک‌تر است، زیرا کنسول وظیفه ایجاد محیط‌های تست (harnesses)، خواندن تمام رونوشت‌ها، اجرای عامل‌ها (agents) و ارائه یک shell و فایل‌سیستم واقعی به آن‌ها در فضای کاری‌شان را بر عهده دارد. همچنین کلید ارائه‌دهنده‌ای که متصل کرده‌اید را نگه می‌دارد. هر کسی که به یک کنسول محافظت‌نشده دسترسی پیدا کند، می‌تواند کارهای شما را بخواند، دستورات را اجرا کند و از کلید شما استفاده کند.

فایروال میزبان شما را از این خطر نجات نمی‌دهد. Docker پورت‌ها را با نوشتن قوانین اختصاصی خود در جدول nat هسته منتشر می‌کند و این قوانین پیش از زنجیره‌ای که ufw مدیریت می‌کند ارزیابی می‌شوند، بنابراین یک پورت منتشرشده حتی زمانی که sudo ufw status آن را مسدود نشان می‌دهد، همچنان در دسترس باقی می‌ماند. تست را از یک ماشین دیگر انجام دهید، نه از داخل خود VPS، در غیر این صورت چیزی را تست نکرده‌اید. این همان درسی است که در اجرای dsh بدون رابط کاربری روی پورت 3080 آموختیم: سرویس را به loopback متصل کنید، سپس آگاهانه تصمیم بگیرید که چگونه می‌خواهید به آن دسترسی پیدا کنید.

تغییر ورود پیش‌فرض پیش از هر اقدام دیگر

با نام کاربری harnessrouter و رمز عبور harnessrouter در http://localhost:3000 وارد شوید. این اعتبارنامه‌ها در فایل README چاپ شده‌اند زیرا صرفاً جای‌نگهدار هستند و نه رمز عبور واقعی؛ به همین دلیل کانتینر تا زمانی که آن‌ها را تغییر ندهید، در هر بار اجرا به شما هشدار می‌دهد:

using the DEFAULT password. Set HR_AUTH_PASSWORD, or change it from the profile page, before exposing this instance.

آن را از صفحه Profile تغییر دهید، یا برای استقرار اسکریپت‌نویسی‌شده، در زمان شروع تنظیم کنید. HR_AUTH_USER و HR_AUTH_PASSWORD مقادیر پیش‌فرض را بازنویسی می‌کنند.

docker run -d --name harnessrouter \
  -p 127.0.0.1:3000:3000 \
  -v harnessrouter:/data \
  -e HR_AUTH_USER='you' \
  -e HR_AUTH_PASSWORD='the-password-you-chose' \
  harnessrouter/harnessrouter

هیچ ایمیل بازیابی وجود ندارد، زیرا سیستم حساب کاربری و سرور ایمیلی در کار نیست. اگر رمز عبور را فراموش کردید، فایل auth را در volume حذف کرده و سرویس را restart کنید، سپس دوباره با مقادیر پیش‌فرض وارد شوید.

docker stop harnessrouter
docker run --rm -v harnessrouter:/data alpine rm -f /data/selfhost-auth.json
docker start harnessrouter

HR_AUTH_DISABLED=1 دروازه ورود را به‌طور کامل حذف می‌کند. فایل README محدوده استفاده از آن را «سیستمی که هیچ‌کس دیگری به آن دسترسی ندارد» تعیین کرده است. یک VPS با IP عمومی چنین سیستمی نیست، بنابراین مگر اینکه این سرویس را روی لپ‌تاپ شخصی اجرا می‌کنید، دروازه ورود را فعال نگه دارید.

نسخه خود را بررسی کنید، زیرا نسخه‌های قدیمی فاقد درگاه امنیتی هستند

این بخشی است که باید جدی گرفته شود. نسخه‌های 0.1.x و 0.2.0 بدون هیچ‌گونه درگاه احراز هویت عرضه شدند: هر کسی که به پورت 3000 دسترسی داشت، از قبل وارد کنسول شده بود. نسخه 0.3.0 اولین نسخه‌ای بود که با قابلیت ورود (login) ارائه شد. آن تگ‌های قدیمی همچنان منتشر شده و قابل دریافت (pull) هستند، بنابراین یک تگ قدیمیِ ثابت‌شده (pinned) یا یک فایل compose که از همکار خود کپی کرده‌اید، می‌تواند امروز یک کنسول بدون محافظت را روی یک پورت عمومی قرار دهد.

از تاریخ 19 اوت 2026، جدیدترین تگ منتشرشده 0.5.5 است که تاریخ 18 اوت 2026 را دارد و latest به آن اشاره می‌کند. بررسی کنید چه نسخه‌ای دارید و سپس آن را با لیست تگ‌ها در Docker Hub مقایسه کنید:

docker image ls harnessrouter/harnessrouter

هر نسخه‌ای پایین‌تر از 0.3.0 باید همین حالا جایگزین شود، نه اینکه برای آن برنامه‌ریزی شود. برای هر نسخه در سطح 0.3.0 یا بالاتر از آن نیز همچنان باید رمز عبور را تغییر دهید، زیرا برای کسی که پورت 3000 را اسکن می‌کند، رمز عبور پیش‌فرض با نداشتن رمز عبور تفاوتی ندارد. شماره نسخه‌های موجود در این صفحه را به عنوان نسخه جاری در نظر نگیرید. این شماره‌ها در تاریخ ذکر شده در بالا صحیح بودند و این پروژه با سرعت زیادی به‌روزرسانی می‌شود.

اتصال یک ارائه‌دهنده

تا زمانی که یک ارائه‌دهنده مدل متصل نشود، هیچ‌چیز اجرا نخواهد شد. یک ارائه‌دهنده را از صفحه Integrations در کنسول اضافه کنید یا آن را از طریق docker run در محیط (environment) ارسال کنید. مقدار آن JSON است، بنابراین در shell آن را داخل کوتیشن قرار دهید:

-e HR_SECRET_GLOBAL_HARNESS_CONN_ANTHROPIC='{"name":"anthropic","provider":"anthropic","api_key":"sk-ant-…"}'

.env.example برای هر خانواده از ارائه‌دهنده‌ها یک متغیر اتصال نام‌گذاری می‌کند: HR_SECRET_GLOBAL_HARNESS_CONN_ANTHROPIC برای بک‌اند claude-code، HR_SECRET_GLOBAL_HARNESS_CONN_OPENAI برای بک‌اند codex، و HR_SECRET_GLOBAL_HARNESS_CONN_CUSTOM برای هر endpoint سازگار با OpenAI که محل قرارگیری یک aggregator یا سرور استنتاج (inference server) شخصی شماست. متغیرهای متناظر HR_SECRET_GLOBAL_HARNESS_POLICY_CLAUDE، HR_SECRET_GLOBAL_HARNESS_POLICY_CODEX و HR_SECRET_GLOBAL_HARNESS_POLICY_HERMES مشخص می‌کنند که هر بک‌اند به‌طور پیش‌فرض از کدام اتصال استفاده می‌کند. HR_SECRET_KEY یک مورد مجزا است و تنها زمانی مورد نیاز است که یک دیتابیس را به یک عامل (agent) متصل کنید.

HR_BACKENDS انتخاب می‌کند که کدام بک‌اندها بارگذاری شوند، همان‌طور که در HR_BACKENDS=claude,codex,hermes آمده است. یک مشکل شناخته‌شده وجود دارد که بهتر است پیش از مواجهه با آن بدانید: هر مقداری که hermes را حذف کند، باعث می‌شود کانتینر بلافاصله با وضعیت 1 و بدون هیچ پیام خطایی خارج شود. شما Exited (1) را در docker ps -a یک ثانیه پس از شروع مشاهده می‌کنید و docker logs نیز هیچ اطلاعات مفیدی نشان نمی‌دهد. تا زمانی که upstream این مشکل را برطرف نکرده است، hermes را در لیست نگه دارید. اگر Hermes تنها harness مورد نظر شماست، اجرای عامل Hermes روی یک VPS مجزا استقرار سبک‌تری محسوب می‌شود.

فراخوانی API بدون استفاده از کنسول

استفاده از کنسول اختیاری است. هر دو روش از یک API واحد استفاده می‌کنند که از قرارداد Responses-style پیروی می‌کند. ابتدا برای دریافت session cookie وارد سیستم شوید:

curl -c hr.cookies http://localhost:3000/api/selfhost/login \
  -H 'content-type: application/json' \
  -d '{"username":"harnessrouter","password":"your-password"}'

سپس یک task ارسال کنید و harness را در metadata.harness_id و مدلی که ارائه‌دهندهٔ متصل شما واقعاً پشتیبانی می‌کند، مشخص نمایید:

curl -s -b hr.cookies http://localhost:3000/api/harness/v1/responses \
  -H 'content-type: application/json' \
  -d '{"input":"Reply with exactly this and nothing else: it works.",
       "metadata":{"harness_id":"codex"},
       "model":"gpt-5.4-mini",
       "stream":false}'

یک شیء JSON که شامل یک بلوک خروجی و تعداد توکن‌ها باشد، به معنای اجرای موفقیت‌آمیز harness است. تغییر harness_id از codex به claude، همان درخواست را به یک harness متفاوت ارسال می‌کند و همین جابه‌جایی، دلیل اصلی وجود این نرم‌افزار است. اتصال سفارشی در بالا، روشی است که با آن یک harness را به سمت یک endpoint سازگار با OpenAI که از قبل میزبانی کرده‌اید هدایت می‌کنید، مشابه روشی که در یک harness خودمیزبان DeepSeek روی VPS پیکربندی می‌شود.

دسترسی به آن از لپ‌تاپ بدون انتشار پورت

دو روش وجود دارد و هیچ‌کدام از آن‌ها شامل باز کردن مستقیم پورت روی 0.0.0.0 نیست.

تونل SSH کم‌هزینه‌ترین روش است و نیازی به نصب هیچ‌چیز روی سرور ندارد. این روش یک پورت محلی روی دستگاه شما را به آدرس loopback در VPS فوروارد می‌کند.

ssh -N -L 3000:127.0.0.1:3000 you@your-vps

آن را در حال اجرا بگذارید و http://localhost:3000 را در مرورگر خود باز کنید. اگر SSH پیام bind: Address already in use را چاپ کرد، یعنی برنامه‌ای روی لپ‌تاپ شما قبلاً پورت 3000 را اشغال کرده است؛ بنابراین با استفاده از -L 3100:127.0.0.1:3000 یک پورت محلی دیگر انتخاب کنید و به پورت 3100 بروید.

Reverse proxy با قابلیت TLS termination پاسخی است که وقتی افراد دیگر نیاز به دسترسی دارند، باید از آن استفاده کنید. پروکسی گواهی TLS (امنیت لایه انتقال) را نگه می‌دارد و درخواست‌ها را به loopback فوروارد می‌کند. فایل README یک پیکربندی برای Caddy ارائه می‌دهد:

console.example.com {
    encode zstd gzip
    reverse_proxy 127.0.0.1:3000 {
        flush_interval -1      # agent turns stream for minutes; never buffer them
    }
}

flush_interval -1 خطی است که افراد معمولاً فراموش می‌کنند. Agent توکن‌های استریم را برای چند دقیقه تولید می‌کند و پروکسی که پاسخ را بافر می‌کند، این توکن‌ها را تا پایان نوبت نگه می‌دارد؛ در نتیجه کنسول منجمد به نظر می‌رسد و سپس همه چیز را یک‌جا چاپ می‌کند. معادل این تنظیم در Nginx عبارت proxy_buffering off; در داخل بلوک location است. هر کدام را که انتخاب می‌کنید، نام DNS را به سمت پروکسی و کانتینر را روی loopback نگه دارید. مطلب مقایسه Nginx، Caddy و Traefik به عنوان reverse proxy بررسی می‌کند که کدام‌یک برای سرور شما مناسب‌تر است.

اجرای آن با کاربر اختصاصی، نه به عنوان root

Docker daemon با دسترسی root اجرا می‌شود و عضویت در گروه docker معادل دسترسی root است، زیرا یک عضو می‌تواند containerای را اجرا کند که فایل‌سیستم میزبان را mount می‌کند. بنابراین، «افزودن تیم به گروه docker» به معنای اعطای دسترسی root روی سروری است که کلید provider شما در آن قرار دارد.

نسخه ساده: یک service account ایجاد کنید که مالک فایل compose و .env باشد و این فایل‌ها را خارج از هرگونه دایرکتوری home اشتراکی نگه دارید.

sudo adduser --disabled-password --gecos "" harness
sudo install -d -o harness -g harness -m 750 /srv/harnessrouter

نسخه قوی‌تر، Rootless Docker است که در آن خودِ daemon با همان کاربر بدون دسترسی ویژه (unprivileged) اجرا می‌شود. این حالت به بسته uidmap برای newuidmap و newgidmap، و حداقل 65536 شناسه کاربری فرعی (subordinate UIDs) در /etc/subuid و /etc/subgid برای کاربر نیاز دارد. uidmap در مخازن Ubuntu موجود است، اما docker-ce-rootless-extras خیر؛ این بسته از مخزن apt خودِ Docker در download.docker.com عرضه می‌شود که نصب Docker engine آن را اضافه می‌کند. اگر engine را از آن مخزن نصب نکرده باشید، grep -rl download.docker.com /etc/apt/sources.list.d/ خروجی نخواهد داشت و دستور نصب زیر بسته را پیدا نخواهد کرد.

sudo apt install -y uidmap docker-ce-rootless-extras
sudo loginctl enable-linger harness
sudo -iu harness
dockerd-rootless-setuptool.sh install
export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock
systemctl --user enable --now docker

loginctl enable-linger در اینجا اختیاری نیست. بدون آن، instance مربوط به systemd کاربر با بستن آخرین session متوقف می‌شود و در نتیجه با خروج شما (logout)، container از بین می‌رود. نتیجه را با docker info تأیید کنید که rootless را در بخش Security Options فهرست می‌کند. حالت Rootless نمی‌تواند بدون پیکربندی اضافی به پورت‌های زیر 1024 متصل شود، که در اینجا اهمیتی ندارد زیرا پورت 3000 بالاتر از این محدوده است. راه‌اندازی خودِ حساب کاربری در ایجاد کاربران با حداقل دسترسی در VPS توضیح داده شده است.

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

کانتینر یک ثانیه پس از شروع متوقف می‌شود و لاگ‌ها خالی هستند. docker ps -a مقدار Exited (1) را نشان می‌دهد. این همان مشکل HR_BACKENDS در بالا است: مقدار شما فاقد hermes است. آن را بازگردانید.

اولین اجرا هرگز به پایان نمی‌رسد. لاگ پس از یک خط installing متوقف می‌شود و ready on :3000 هرگز ظاهر نمی‌شود. سیستم نمی‌تواند برای دریافت CLIهای agent به شبکه متصل شود، زیرا آن‌ها در image موجود نیستند. مسیر خروجی (outbound route) یا تنظیمات proxy را اصلاح کرده و سپس سرویس را restart کنید.

کنسول بارگذاری می‌شود اما تمام وظایف با خطا مواجه می‌شوند. هیچ provider متصل نیست. هیچ مدل پیش‌فرضی و هیچ طرح رایگانی درون image وجود ندارد، بنابراین یک instance تازه می‌تواند شما را وارد سیستم کند اما همچنان هیچ کاری انجام ندهد.

کنسول هنگام پاسخ‌دهی پشت proxy فریز می‌شود. خروجی در پایان نوبت به‌صورت یکجا ظاهر می‌شود. این مشکل مربوط به response buffering است. در Caddy مقدار flush_interval -1 و در Nginx مقدار proxy_buffering off; را تنظیم کنید.

با وجود برقرار بودن tunnel، نمی‌توانید از لپ‌تاپ خود به آن دسترسی پیدا کنید. دستور docker port harnessrouter را روی سرور اجرا کنید. اگر خروجی خالی است، یعنی کانتینر چیزی را منتشر (publish) نمی‌کند؛ بنابراین بدون -p راه‌اندازی شده است.

آیا اجرای این سرویس ارزشش را دارد؟

اگر واقعاً از بیش از یک harness استفاده می‌کنید و می‌خواهید به‌جای سه نقطهٔ پایانی و سه مخزن اعتبارنامه، فقط یکی از هر کدام داشته باشید، اجرای آن ارزشمند است. همچنین اگر در حال ساخت محصولی بر پایهٔ آن هستید و می‌خواهید harness یک مقدار پیکربندی باشد تا یک بازنویسی کد، این کار منطقی است. این همان چیزی است که UHP برای شما فراهم می‌کند، البته با در نظر گرفتن هشداری که پیش‌تر دربارهٔ نوپا بودن این پروتکل ذکر شد.

اگر فقط از یک harness استفاده می‌کنید، اجرای آن ارزشش را ندارد. نصب آن CLI روی سرور قطعات متحرک کمتری دارد و هیچ لاگینی بین شما و آن قرار نمی‌گیرد. همچنین اگر هدف شما همکاری چندین عامل (agent) روی یک وظیفه است، نه یک API واحد در مقابل چندین harness، این ابزار گزینهٔ مناسبی نیست؛ برای آن الگو، به یک harness چندعاملی مانند Omnigent مراجعه کنید. در هر صورت، قوانین استقرار تغییر نمی‌کنند: bind روی loopback، تغییر رمز عبور، استفاده از یک tag ثابت در نسخهٔ 0.3.0 یا بالاتر، و اختصاص یک کاربر مجزا.

FAQ

آیا انتشار HarnessRouter روی پورت 3000 امن است؟

خیر. کنسول، هارنس‌ها (harnesses) را ایجاد می‌کند، تمام رونوشت‌ها را می‌خواند، ایجنت‌ها را با دسترسی به shell و سیستم فایل اجرا می‌کند و کلید ارائه‌دهنده‌ای که متصل کرده‌اید را نگه می‌دارد؛ بنابراین باز بودن پورت، تمام این موارد را در معرض خطر قرار می‌دهد. آن را روی loopback با -p 127.0.0.1:3000:3000 منتشر کنید و از طریق یک تونل SSH یا یک reverse proxy با قابلیت TLS termination به آن دسترسی پیدا کنید. فایروال میزبان به‌تنهایی کافی نیست: Docker قوانین خاص خود را در جدول nat هسته می‌نویسد، بنابراین یک پورت منتشرشده حتی زمانی که ufw آن را مسدود نشان می‌دهد، از اینترنت پاسخ می‌دهد. با sudo ss -ltnp | grep 3000 بررسی کنید که باید 127.0.0.1:3000 را چاپ کند.

کدام نسخه از HarnessRouter قابلیت login gate را اضافه کرد؟

0.3.0. نسخه‌های 0.1.x و 0.2.0 بدون هیچ‌گونه احراز هویتی عرضه شدند و هر دو تگ همچنان منتشر شده و قابل دریافت هستند، بنابراین هر کسی که از آن‌ها استفاده می‌کند، متکی بر این است که کسی پورت او را پیدا نکند. تا تاریخ 19 August 2026، جدیدترین تگ 0.5.5 است که در تاریخ 18 August 2026 منتشر شده است. برای مشاهده نسخه فعلی خود docker image ls harnessrouter/harnessrouter را اجرا کنید، آن را با لیست تگ‌ها در Docker Hub (نه با این صفحه) مقایسه کنید و حتی در نسخه فعلی نیز رمز عبور پیش‌فرض را تغییر دهید.

چرا کانتینر بلافاصله پس از تنظیم HR_BACKENDS خارج می‌شود؟

هر مقدار HR_BACKENDS که hermes را حذف کند، باعث می‌شود کانتینر بلافاصله با وضعیت 1 و بدون پیام خطا خارج شود که یک مشکل شناخته‌شده در README پروژه است. نشانه آن Exited (1) در docker ps -a در عرض یک یا دو ثانیه است و هیچ چیز مفیدی در docker logs وجود ندارد. تا زمانی که upstream این مشکل را برطرف کند، hermes را طبق HR_BACKENDS=claude,codex,hermes در لیست نگه دارید.

آیا HarnessRouter در اولین شروع به دسترسی اینترنت نیاز دارد؟

بله. CLIهای ایجنت در اولین شروع دانلود می‌شوند و در ایمیج گنجانده نشده‌اند، زیرا هر کدام مجوز خاص خود را دارند. سیستمی که مسیر خروجی ندارد، خطوط installing را چاپ می‌کند و هرگز به ready on :3000 نمی‌رسد. دانلود یک بار برای هر volume انجام می‌شود، بنابراین شروع‌های بعدی چند ثانیه طول می‌کشند و به هیچ شبکه‌ای فراتر از ارائه‌دهنده مدلی که متصل کرده‌اید، نیاز ندارند.

رمز عبور کنسول را فراموش کرده‌ام. چگونه دوباره وارد شوم؟

هیچ ایمیل بازنشانی وجود ندارد، زیرا سیستم حساب کاربری و سرور ایمیلی وجود ندارد. کانتینر را متوقف کنید، /data/selfhost-auth.json را از volume حذف کنید، دوباره آن را شروع کنید، سپس با اعتبارنامه‌های پیش‌فرض وارد شوید و از صفحه Profile رمز عبور جدیدی تنظیم کنید. با فرض اینکه نام کانتینر و volume هر دو harnessrouter باشد، دستورات به ترتیب docker stop harnessrouter، سپس docker run --rm -v harnessrouter:/data alpine rm -f /data/selfhost-auth.json و در نهایت docker start harnessrouter هستند.