SSD Nodes Learn 🎉 VPS از $5.50/ماه
راهنماها Matt Connorتوسط Matt Connor · به‌روزرسانی شده 2026-08-21

آموزش میزبانی شخصی OneCLI با Docker Compose

با راهنمای گام‌به‌گام میزبانی شخصی OneCLI، برای هر کاربر یک agent اختصاصی در sandbox بسازید. برای اجرای این stack به حداقل 2 GiB رم و دیتابیس PostgreSQL نیاز دارید.

آنچه با میزبانی شخصی OneCLI به دست می‌آورید

با میزبانی شخصی OneCLI، هر فرد در تیم شما صاحب یک agent اختصاصی می‌شود که هر کدام در sandbox مخصوص به خود اجرا می‌گردند. کلیدهای API در یک gateway نگهداری می‌شوند که agentها هرگز به محتوای آن دسترسی ندارند. نصب این سرویس شامل یک stack از نوع Docker Compose به همراه PostgreSQL در پس‌زمینه است که از طریق http://localhost:10254 در دسترس قرار می‌گیرد. برای این کار یک سرور واقعی در نظر بگیرید. مقدار پیش‌فرض مستند شده برای هر sandboxِ agent برابر با 2 GiB حافظه است، بنابراین این بار کاری برای یک VPS با 1 GB رم مناسب نیست.

هفت بخش در این stack وجود دارد و شناخت هر یک از آن‌ها، مطالعهٔ ادامهٔ این راهنما را آسان‌تر می‌کند.

  • داشبورد وب (Next.js)، پورت 10254. ایجاد agent، چت، ویرایش حافظه و مهارت‌ها، اتصالات و اسرار (secrets).
  • سرور API، پورت 10256. صفحه کنترل: پایگاه داده، مدیریت گفتگوها و صف‌های کاری.
  • دروازه Rust، پورت 10255. درخواست‌های خروجی از agentها را رهگیری کرده و اعتبارنامه‌ها را تزریق می‌کند.
  • اجراکننده (Runner). در فایل README به عنوان مؤلفه‌ای توصیف شده که «sandboxهای agent را شروع، متوقف و پاکسازی می‌کند. فقط خروجی است و هرگز با پایگاه داده تماس ندارد.»
  • ناظر Sandbox. در فایل README به عنوان مؤلفه‌ای توصیف شده که «درون هر sandbox اجرا می‌شود و با یک رابط harness خنثی (vendor-neutral) صحبت می‌کند تا runtimeِ agent قابل تعویض باشد.»
  • آداپتور کانال. یک daemon که به یک برنامه Slack متصل می‌شود تا agent بتواند در کانال‌ها و پیام‌های مستقیم (DM) با نام اختصاصی خود پاسخ دهد.
  • PostgreSQL. فایل compose ارائه شده، نسخه postgres:18-alpine را با یک volume از نوع pgdata اجرا می‌کند.

نام CLI است، اما محصول یک سرور است

OneCLI یک پلتفرم سروری است. نام آن به ابزار خط فرمانی اشاره دارد که روی لپ‌تاپ نصب می‌کنید، اما این تصور برای چیزی که در این راهنما معرفی شده، اشتباه است. یک کلاینت خط فرمان مجزا در مخزن onecli/onecli-cli وجود دارد که ترافیک یک ایجنت کدنویسی محلی را از طریق یک gateway هدایت می‌کند. آنچه در اینجا مستقر می‌کنید، یک برنامه وب چندکاربره است: یک سیستم حساب کاربری که در آن اولین حساب، مالک نمونه (instance) است، یک پایگاه داده از گفتگوها و اسرار، و یک اجراکننده (runner) که کانتینرها را راه‌اندازی می‌کند.

مدل «هر نفر یک ایجنت» کل طراحی این سیستم است. در فایل README آمده است: «شما برای هر نفر یک ایجنت می‌سازید، دسترسی‌های لازم را به هر ایجنت می‌دهید و آن در یک sandbox کار می‌کند؛ ترافیکی که از طریق یک gateway هدایت می‌شود که اعتبارنامه‌ها را تزریق کرده و سیاست‌های شما را اعمال می‌کند.» هر ایجنت فایل‌سیستم و شل (shell) اختصاصی خود، صفحه گفتگوی مجزا، حافظه‌ای که پلتفرم نگهداری می‌کند و مهارت‌هایی که یک‌بار می‌نویسید را دارد. نحوه کارکرد اعتبارنامه‌ها در اینجا برعکس تنظیمات معمول است. به‌جای کپی کردن یک API key در محیط هر شخص، شما کلید را یک‌بار ذخیره می‌کنید و آن را به ایجنت‌هایی که اجازه استفاده از آن را دارند، اختصاص می‌دهید.

پیش‌نیازهای لازم برای شروع

  • Docker، به همراه افزونه Compose نسخه 2.19 یا جدیدتر. فایل compose از یک سرویس migration یک‌باره استفاده می‌کند که API منتظر پایان آن می‌ماند؛ این وابستگی به نسخه 2.19 نیاز دارد.
  • حافظه (RAM)، که محدودیت اصلی است. پیش از انتخاب پلن، بخش مربوط به تعیین اندازه (sizing) را در ادامه مطالعه کنید.
  • پورت‌های loopback آزاد شامل 10254، 10255، 10256 و 5432.

نیازی نیست PostgreSQL را شخصاً نصب کنید: فایل compose آن را به عنوان یک سرویس اجرا می‌کند. همچنین نیازی به Node.js یا Rust ندارید. این موارد فقط برای مسیر build-from-source هستند، جایی که mise زنجیره ابزار (toolchain) را تعیین می‌کند.

چند sandbox عامل (agent) روی VPS شما جای می‌گیرد؟

مستندات خودِ runner به‌جای حدس و گمان، اعداد واقعی را ارائه می‌دهد. هر sandbox دارای 2048 مگابایت حافظه (RUNNER_SANDBOX_MEMORY_MB)، یک CPU (RUNNER_SANDBOX_CPUS) و 512 پردازش (RUNNER_SANDBOX_PIDS) است. سقف هم‌زمانی (concurrency cap) برابر با 4 (RUNNER_MAX_SANDBOXES) است و مستندات توصیه می‌کنند برای پشتیبانی از این سقف، حدود 10 گیگابایت حافظه آزاد علاوه بر پشته پایه (base stack) در دسترس باشد.

ChartConcurrent agent sandboxes per box, at the documented 2 GiB default
The data behind this chart
[
  {
    "plan": "2 GB box",
    "ram_gb": 2,
    "sandbox_slots": 0
  },
  {
    "plan": "4 GB box",
    "ram_gb": 4,
    "sandbox_slots": 1
  },
  {
    "plan": "8 GB box",
    "ram_gb": 8,
    "sandbox_slots": 3
  },
  {
    "plan": "16 GB box",
    "ram_gb": 16,
    "sandbox_slots": 7
  },
  {
    "plan": "32 GB box",
    "ram_gb": 32,
    "sandbox_slots": 15
  }
]

این تعداد جایگاه‌ها یک محاسبه ریاضی است، نه یک بنچمارک: کل حافظه، منهای حدود 2 گیگابایت برای PostgreSQL و چهار سرویس طولانی‌مدت، تقسیم بر سقف 2 گیگابایتی هر sandbox. بر این اساس، 2 GB box تعداد 0 عدد sandbox را در خود جای می‌دهد، بنابراین ارزان‌ترین پلن اصلاً نمی‌تواند یک عامل میزبانی‌شده را اجرا کند. یک 16 GB box فضایی برای 7 عدد sandbox باقی می‌گذارد که به‌راحتی بالاتر از سقف پیش‌فرض چهار و بالاتر از حدود 10 گیگابایت حافظه آزادی است که مستندات runner درخواست می‌کند. پلن 32 GB box شما را به 15 عدد sandbox می‌رساند.

دو عامل این محاسبات را تغییر می‌دهند. یک sandbox که یک پردازش پس‌زمینه در حال اجرا دارد، هرگز متوقف (park) نمی‌شود، بنابراین جایگاه خود را به‌طور دائم اشغال می‌کند؛ این یعنی شما باید RUNNER_MAX_SANDBOXES را برای بار کاری پایدار تنظیم کنید، نه برای شلوغ‌ترین لحظه. همچنین حافظه پیش از CPU تمام می‌شود. هر sandbox به یک CPU محدود شده است، بنابراین چهار عامل مشغول به چهار هسته نیاز دارند، اما چهار عاملِ بیکار اما فعال، همچنان 8 گیگابایت حافظه را اشغال می‌کنند.

تنظیمات runner که ممکن است بخواهید تغییر دهید
  • RUNNER_MAX_SANDBOXES (پیش‌فرض 4): چه تعداد sandbox به‌طور هم‌زمان اجرا شوند.
  • RUNNER_SANDBOX_MEMORY_MB (پیش‌فرض 2048): سقف حافظه برای هر sandbox.
  • RUNNER_SANDBOX_CPUS (پیش‌فرض 1): سقف CPU برای هر sandbox.
  • RUNNER_SANDBOX_PIDS (پیش‌فرض 512): سقف پردازش برای هر sandbox.
  • RUNNER_NETWORK_INTERNAL (پیش‌فرض true): شبکه sandbox را بدون مسیر خروجی نگه می‌دارد. آن را فعال بگذارید.
  • RUNNER_SANDBOX_NETWORK (پیش‌فرض onecli-sandboxes): شبکه‌ای که sandboxها به آن متصل می‌شوند.
  • RUNNER_RECONCILE_SECONDS (پیش‌فرض 60): تناوب زمانی که runner وضعیت را همگام‌سازی (reconcile) می‌کند.
  • RUNNER_ORPHAN_GRACE_SECONDS (پیش‌فرض 3600): سنی که پس از آن کانتینرها و volumeهای یتیم حذف می‌شوند.
  • RUNNER_AGENT_IMAGE: تصویر (image) sandbox را بازنویسی می‌کند، که در غیر این صورت از ONECLI_VERSION پیروی می‌کند.

نصب OneCLI با Docker Compose

مستندات بالادستی برای self-hosting، این توالی دقیق را ارائه می‌دهد. این مستندات سه secret را در docker/.env در کنار فایل compose می‌نویسد و سپس stack را اجرا می‌کند.

git clone https://github.com/onecli/onecli.git && cd onecli/docker
cat > .env <<EOF
SECRET_ENCRYPTION_KEY=$(head -c 32 /dev/urandom | base64)
GATEWAY_INTERNAL_SECRET=$(head -c 32 /dev/urandom | base64)
BETTER_AUTH_SECRET=$(head -c 32 /dev/urandom | base64)
COMPOSE_PROFILES=runner
EOF
chmod 600 .env
docker compose up -d --wait

پیش از اجرای این بلوک، آن را مطالعه کنید. نشانگر heredoc بدون کوتیشن است، بنابراین shell شما هر head -c 32 /dev/urandom | base64 را اجرا کرده و نتیجه را می‌نویسد، نه متن تحت‌اللفظی را. مقدار SECRET_ENCRYPTION_KEY کلید AES-256-GCM برای تمام secretهای موجود در دیتابیس است. مقدار GATEWAY_INTERNAL_SECRET دروازه (gateway) را برای API احراز هویت می‌کند. مقدار BETTER_AUTH_SECRET کوکی‌های نشست (session cookies) را امضا می‌کند. خط COMPOSE_PROFILES=runner مهم‌ترین بخش است، زیرا سرویس runner پشت یک Compose profile قرار دارد: اگر آن را حذف کنید، stack بدون مشکل بالا می‌آید اما هیچ agent sandboxای شروع به کار نخواهد کرد.

دستور --wait تا زمانی که تمام سرویس‌ها وضعیت healthy را گزارش ندهند، shell را نگه می‌دارد، بنابراین خروجی غیر صفر اولین نشانه شما از وجود مشکل است. سپس بررسی کنید که چه چیزی واقعاً بالا آمده است.

docker compose ps
docker compose logs migrations

نسخه را ثابت (pin) کنید. مقدار ONECLI_VERSION تگ تمام سرویس‌ها را به‌طور هم‌زمان تنظیم می‌کند و image مربوط به agent sandbox نیز از آن پیروی می‌کند، مگر اینکه RUNNER_AGENT_IMAGE به جای دیگری اشاره کند. تا تاریخ 19 August 2026، نسخه فعلی v2.0.1 است که در 18 August 2026 منتشر شده است. آن را به همان فایل اضافه کنید و stack را دوباره بالا بیاورید.

echo 'ONECLI_VERSION=v2.0.1' >> .env
docker compose up -d --wait

یک نصب‌کننده به نام curl -fsSL https://onecli.sh/install | sh نیز وجود دارد که پیکربندی خود را در ~/.onecli/.env می‌نویسد و همان کار را انجام می‌دهد. مسیر Compose روشی است که در آن می‌توانید پیش از اجرای هر چیزی، تمام فایل‌ها را بخوانید و برای سروری که از قبل stackهای Compose دیگری روی آن در حال اجراست، مناسب‌تر است. ساخت از سورس (source) مسیر سوم است که در مخزن کلون‌شده به صورت pnpm install و سپس pnpm run setup مستند شده است. این مسیر در هر صورت به mise، زبان Rust برای gateway و Docker نیاز دارد و برای کسانی در نظر گرفته شده که قصد تغییر در کد را دارند.

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

هر پورتی که در فایل compose ارائه‌شده منتشر شده است، به ${ONECLI_BIND_HOST:-127.0.0.1} متصل می‌شود. در یک VPS، این یعنی داشبورد در حال اجراست اما هیچ منبعی خارج از سرور نمی‌تواند به آن دسترسی داشته باشد. این تنظیم پیش‌فرض صحیح است. آن را حفظ کنید و از تونل استفاده کنید:

ssh -N -L 10254:127.0.0.1:10254 you@your-server

حالا http://localhost:10254 را در لپ‌تاپ خود باز کنید. ترافیک از طریق اتصال SSH منتقل می‌شود، بنابراین هیچ داشبورد رمزنگاری‌نشده‌ای روی اینترنت عمومی وجود ندارد و نیازی به باز کردن پورت اضافی در فایروال نیست.

تنظیم ONECLI_BIND_HOST=0.0.0.0 داشبورد را از طریق HTTP ساده منتشر می‌کند و PostgreSQL را نیز در کنار آن در دسترس قرار می‌دهد. اگر چندین نفر به داشبورد نیاز دارند، یک reverse proxy با TLS (امنیت لایه انتقال) جلوی پورت 10254 قرار دهید و bind host را تغییر ندهید. این کار را پیش از آنکه instance صاحب داشته باشد انجام دهید. مستندات بالادستی در مورد دلیل این کار صریح هستند: «تا زمانی که این کار را انجام ندهید، instance صاحب ندارد و روی یک میزبان قابل‌دسترسی، هر کسی که زودتر به آن برسد، مالک آن خواهد شد.» اگر آن پروکسی در حال حاضر جلوی سایر برنامه‌های self-hosted شما قرار دارد، هدایت احراز هویت از طریق یک لایه single sign-on خودمیزبان، داشبورد را پشت همان سیستم ورودی قرار می‌دهد که تیم شما از قبل دارد؛ بنابراین حذف دسترسی یک فرد در آن نقطه، این در را نیز می‌بندد.

ایجاد اولین حساب کاربری و سپس اعطای کلید مدل

داشبورد را باز کرده و بلافاصله حساب کاربری را ایجاد کنید. آن حساب مالک نمونه (instance) است و پس از ایجاد آن، عضویت در سیستم نیازمند دعوت‌نامه خواهد بود.

سپس پیش از ایجاد یک agent، یک کلید مدل ذخیره کنید. یک agent میزبانی‌شده (hosted agent) به یک کلید مدل اعطا شده نیاز دارد و ترتیب انجام این کار مهم است: ابتدا کلید را در داشبورد ذخیره کنید، سپس آن را به agent اعطا کنید و تنها پس از آن گفتگو را آغاز نمایید. اگر مرحله اعطای کلید را نادیده بگیرید، sandbox هرگز اجرا نمی‌شود که نتیجه آن agentای است که بدون انجام هیچ کاری متوقف می‌ماند.

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

نحوه محافظت گیت‌وی از کلیدها در برابر ایجنت‌ها

گیت‌وی یک پروکسی HTTPS است که با زبان Rust نوشته شده و روی پورت 10255 گوش می‌دهد. کلاینت HTTP ایجنت به سمت این گیت‌وی تنظیم شده و ایجنت به‌جای اعتبارنامه واقعی، یک اعتبارنامه جایگزین (placeholder) حمل می‌کند. گیت‌وی درخواست خروجی را با مجوزهای آن ایجنت مطابقت می‌دهد، رمز واقعی را رمزگشایی کرده، آن را در درخواست جای‌گذاری می‌کند و سپس درخواست را ارسال می‌نماید. رمزها در PostgreSQL با استاندارد AES-256-GCM (استاندارد رمزنگاری پیشرفته، 256 بیتی، حالت Galois/counter) ذخیره شده و تنها در زمان درخواست رمزگشایی می‌شوند. هر فراخوانی به همراه هویت ایجنت و مقصد آن ثبت می‌شود؛ این یک مسیر حسابرسی (audit trail) است که وقتی کلیدها در پروفایل shell ده نفر مختلف پخش باشند، به آن دسترسی نخواهید داشت.

دو مکانیسم نحوه استقرار آن را تعیین می‌کنند:

  • رهگیری HTTPS در واقع یک حمله مرد میانی (man-in-the-middle) است. گیت‌وی یک مرجع صدور گواهی (CA) محلی تولید می‌کند، ایجنت به آن اعتماد می‌کند و گیت‌وی اتصال TLS ایجنت را خاتمه داده و یک اتصال جدید به سرویس بالادستی (upstream) باز می‌کند. به همین دلیل است که اگر کلاینت HTTP یک ایجنت به مرجع صدور گواهی گیت‌وی اعتماد نداشته باشد، با خطای تایید گواهی (certificate verification error) مواجه می‌شود، نه خطای احراز هویت.
  • ایجنت خود را با هدر Proxy-Authorization شناسایی می‌کند. روی یک ماشین واحد، جایی که ایجنت‌ها و گیت‌وی در یک شبکه داخلی Docker مشترک هستند، این هدر هرگز از شبکه‌ای که تحت کنترل شما نیست عبور نمی‌کند. اگر یک ایجنت خارج از ماشین را به سمت گیت‌وی هدایت می‌کنید، پورت پروکسی به TLS اختصاصی خود نیاز دارد، زیرا آن هدر یک توکن حامل (bearer token) است.

معامله صادقانه این است: گیت‌وی طبق طراحی، تمام درخواست‌هایی که ایجنت‌های شما ارسال می‌کنند را به صورت متن ساده (plaintext) می‌خواند. این حساس‌ترین فرآیند روی ماشین است. با میزبان آن مطابق با همین حساسیت رفتار کنید و تعداد افرادی که اجازه ورود به سیستم را دارند، با استفاده از کاربران لینوکس با حداقل دسترسی محدود نگه دارید.

چرا runner به هیچ پورت ورودی نیاز ندارد

عملکرد runner صرفاً خروجی (outbound) است. طبق مستندات آن: «این برنامه هیچ پورتی را که دنیای خارج بتواند به آن دسترسی داشته باشد باز نمی‌کند؛ بنابراین یک لپ‌تاپ، یک homelab یا یک VPC پشت NAT، همگی بدون نیاز به ingress، تونل یا پیکربندی TLS termination کار می‌کنند.» NAT همان ترجمه آدرس شبکه است که روترهای خانگی انجام می‌دهند. runner با برقراری ارتباط خروجی با control plane، کارها را از آن دریافت می‌کند؛ بنابراین نیازی به forward کردن پورت یا باز کردن هیچ مسیری نیست.

این طراحی در شبکه sandbox نتیجه‌بخش است. فایل compose یک شبکه دوم را با نام internal: true تعریف می‌کند که در Docker به معنای نبود هیچ مسیری به خارج از host است. sandboxها به این شبکه متصل می‌شوند. gateway در هر دو شبکه حضور دارد (dual-homed) و تنها راه خروج است. مستندات runner این موضوع را به‌وضوح بیان می‌کند: «یک شبکه internal که gateway در آن dual-homed باشد، باعث می‌شود خروج فقط از طریق gateway یک مرز قطعی باشد، نه یک پیشنهاد.» عاملی که بخواهد کد منبع شما را به آدرسی دلخواه ارسال کند، هیچ مسیری برای انجام این کار ندارد.

به‌جای اعتماد به پاراگراف بالا، این موضوع را روی سیستم خود تأیید کنید.

docker network ls
docker network inspect onecli-sandboxes | grep -i internal

شما باید "Internal": true را مشاهده کنید. اگر خروجی false باشد، کنترل خروجی غیرفعال است و gateway دوباره تنها یک پیشنهاد محسوب می‌شود. از هر نام شبکه sandbox که دستور docker network ls چاپ می‌کند استفاده کنید، زیرا onecli-sandboxes فقط مقدار پیش‌فرض است.

امنیت sandbox در OneCLI چقدر است؟

این بخش را با دقت مطالعه کنید، زیرا واژه «sandboxed» در توضیحات پروژه بار معنایی سنگینی دارد، در حالی که مکانیزم آن تنها در یک نقطه مستند شده است.

در فایل README ذکر شده که هر agent «یک sandbox ایزوله با فایل‌سیستم و shell اختصاصی خود» دارد و از Sandbox Supervisor به عنوان مؤلفه‌ای نام برده شده که «درون هر sandbox اجرا می‌شود و با یک رابط استاندارد (vendor-neutral) ارتباط برقرار می‌کند تا runtime مربوط به agent قابل جایگزینی باشد». هیچ‌کدام از این جملات مشخص نمی‌کنند که این ایزولاسیون دقیقاً از چه چیزی تشکیل شده است. مستندات runner این موضوع را روشن می‌کند: backend پیش‌فرض Docker است (RUNNER_BACKEND=docker) و هر sandbox در واقع یک Docker container است که دارای محدودیت حافظه (memory cap)، محدودیت CPU و محدودیت تعداد پردازش (process cap) بوده و به شبکه داخلی متصل است. کد پروژه برای backendهای دیگر نیز انعطاف‌پذیر است و مستندات به مواردی مانند Kubernetes و microVM اشاره می‌کنند که در صورت نیاز باید توسط توسعه‌دهندگان پیاده‌سازی شوند. در حال حاضر، روی سیستم شما، هر sandbox یک container است.

آنچه در مستندات ذکر نشده نیز به همان اندازه اهمیت دارد. هیچ مدل تهدیدی (threat model) وجود ندارد. هیچ بیانیه‌ای درباره اجرای Docker daemon به صورت rootless، نگاشت فضای نام کاربری (user namespace remapping)، پروفایل‌های seccomp یا AppArmor فراتر از تنظیمات پیش‌فرض Docker وجود ندارد و هیچ ادعایی مبنی بر وجود مرز هسته (kernel boundary) مانند gVisor یا microVM مطرح نشده است. بنابراین، برداشت محدود را در نظر بگیرید: محدودیت‌ها صرفاً محدودیت منابع هستند. شبکه داخلی یک کنترل خروجی (egress control) واقعی است. ایزولاسیون بین یک agent و میزبان (host) شما، همان چیزی است که یک Docker container استاندارد ارائه می‌دهد و یک container، هسته سیستم‌عامل میزبان را به اشتراک می‌گذارد.

واقعیت دومی نیز وجود دارد که باید در نظر گرفته شود. سرویس runner، مسیر /var/run/docker.sock را mount می‌کند، زیرا این روشی است که از طریق آن sandboxها ایجاد می‌شوند. دسترسی به Docker socket معادل دسترسی root روی میزبان است، زیرا هر کسی که بتواند آن API را فراخوانی کند، می‌تواند containerای را با فایل‌سیستم میزبان که درون آن mount شده است، اجرا کند. تمام runnerهایی که از Docker استفاده می‌کنند به همین شکل عمل می‌کنند. نتیجه این است که پروسه runner به اندازه gateway حساس است.

تا زمانی که مستندات رسمی از سوی توسعه‌دهندگان ارائه نشده، این مرز را اثبات‌نشده تلقی کنید. در عمل، این یعنی سه عادت زیر را رعایت کنید:

  1. OneCLI را روی سیستمی اجرا کنید که هیچ کار دیگری انجام نمی‌دهد. هیچ سرویس تولیدی (production) نامرتبط، دیتابیس مشترک یا داده‌های تیم‌های دیگر روی آن نباشد.
  2. فرض کنید agentای که به اجرای کد دلخواه (arbitrary code execution) درون sandbox خود دست یافته، می‌تواند به میزبان نفوذ کند؛ بنابراین شرایط را طوری مدیریت کنید که با داشتن بک‌آپ‌های خارج از سرور، این اتفاق قابل‌جبران باشد.
  3. پیش از آنکه به همکار خود بگویید agent ایزوله است، apps/runner/src را بخوانید یا از توسعه‌دهندگان بالادستی (upstream) سؤال کنید.

برای مشاهده تصویری از اینکه یک مرز مستندشده چگونه تعریف می‌شود و چه سؤالاتی ارزش پرسیدن از توسعه‌دهندگان بالادستی را دارد، این مورد را با آنچه یک مرز واقعی برای sandbox agent به نظر می‌رسد مقایسه کنید. تفاوت در این است که آیا کسی مکانیزم را مکتوب کرده است و اینکه آن مکانیزم چه چیزی را متوقف نمی‌کند.

تفکیک مجوز و دلایل بررسی پیش از ساخت

هسته اصلی OneCLI تحت مجوز Apache-2.0 است و میزبانی شخصی (self-hosting) آن در محیط عملیاتی مجاز است. دایرکتوری‌هایی که با نام ee/ مشخص شده‌اند، تحت یک مجوز جداگانه به نام OneCLI Enterprise License قرار می‌گیرند: این بخش برای توسعه، تست و ارزیابی رایگان است، اما برای استفاده در محیط عملیاتی نیاز به اشتراک دارد. یادداشت‌های انتشار نسخه v2.0.1 در تاریخ 18 August 2026 به بازگردانی یک فایل مجوز Apache-2.0 که توسط GitHub قابل شناسایی است اشاره دارند، بنابراین نشان (badge) موجود در صفحه مخزن اخیراً تغییر کرده است. تگی را که واقعاً مستقر (deploy) می‌کنید بررسی کنید و به خلاصه‌ای که در تاریخ دیگری نوشته شده است، اکتفا نکنید.

cd onecli && find . -type d -name ee -not -path '*/node_modules/*'

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

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

ارتقاها شامل افزایش نسخه و راه‌اندازی مجدد هستند. یک سرویس مهاجرت یک‌باره (one-shot) پیش از API در هر up اجرا می‌شود و اگر مهاجرت با شکست مواجه شود، stack از اجرا امتناع می‌کند تا از سرویس‌دهی با شمای نیمه‌مهاجرت‌شده جلوگیری شود. این رفتاری است که شما به آن نیاز دارید، زیرا یک ارتقای ناموفق در این حالت به‌صورت قطعی سرویس (outage) دیده می‌شود و نه خرابی خاموش داده‌ها، و docker compose logs migrations دلیل آن را توضیح می‌دهد.

cd onecli/docker
docker compose pull
docker compose up -d --wait
docker compose logs migrations

اگر به‌جای آن از اسکریپت نصب استفاده کرده‌اید، به‌جای pull کردن دستی، همان اسکریپت را دوباره اجرا کنید تا فایل compose با imageهایی که به آن‌ها ارجاع می‌دهد، هماهنگ باقی بماند.

از دو مورد نسخه پشتیبان تهیه کنید. PostgreSQL شامل agentها، گفتگوها، حافظه و secretهای رمزنگاری‌شده است. فایل docker/.env شامل SECRET_ENCRYPTION_KEY است و بدون آن کلید، secretهای رمزنگاری‌شده غیرقابل خواندن هستند؛ بنابراین یک dump از پایگاه داده به‌تنهایی هیچ چیز قابل استفاده‌ای را بازیابی نمی‌کند.

cd onecli/docker
docker compose exec -T postgres pg_dump -U onecli onecli | gzip > ~/onecli-db.sql.gz
install -m 600 .env ~/onecli-env.backup

هر دو نسخه را خارج از سرور نگهداری کنید. این روال مشابه هر stack مبتنی بر Compose است که دارای state است؛ بنابراین اگر از قبل نحوه پشتیبان‌گیری و ارتقای یک Docker Compose stack را طبق برنامه انجام می‌دهید، این دو مسیر را نیز به آن اضافه کنید و دیگر نگران آن نباشید.

هنگامی که کار نمی‌کند

  • استک هرگز به وضعیت سالم نمی‌رسد و docker compose up -d --wait با کد خروجی غیر صفر متوقف می‌شود. ابتدا docker compose logs migrations را بخوانید، زیرا API عمداً منتظر آن سرویس می‌ماند.
  • یک agent بیکار می‌ماند و هیچ sandbox ظاهر نمی‌شود. بررسی کنید که COMPOSE_PROFILES=runner در docker/.env موجود باشد و docker compose ps یک runner را فهرست کند. سپس بررسی کنید که agent دارای یک model key معتبر باشد، زیرا sandboxها بدون آن اجرا نمی‌شوند.
  • هیچ اسلاتی باقی نمانده است. مقدار پیش‌فرض RUNNER_MAX_SANDBOXES برابر با 4 است و یک sandbox که پردازش پس‌زمینه در حال اجرا دارد، اسلات خود را به‌طور دائم اشغال می‌کند. docker ps نشان می‌دهد چه چیزی واقعاً فعال است.
  • کانتینرها ناپدید می‌شوند یا هاست کند می‌شود. حافظه شما تمام شده است. dmesg -T | grep -i oom موارد OOM (خروج از حافظه) کرنل را ثبت می‌کند و یک sandbox به تنهایی می‌تواند 2048 MB حافظه اشغال کند.
  • فراخوانی‌های HTTPS یک agent به جای خطاهای احراز هویت، با خطاهای تأیید گواهی مواجه می‌شوند. کلاینت HTTP آن به مرجع گواهی (CA) گیت‌وی اعتماد ندارد.
  • کانتینرها یا volumeهای قدیمی پس از حذف یک agent باقی می‌مانند. runner هر 60 ثانیه عملیات تطبیق را انجام می‌دهد و یتیم‌هایی که قدیمی‌تر از RUNNER_ORPHAN_GRACE_SECONDS باشند را از بین می‌برد؛ مقدار پیش‌فرض این پارامتر 3600 است، بنابراین پیش از آنکه آن را نشت حافظه یا فایل بنامید، یک ساعت صبر کنید.

آیا این ابزار مناسب نیاز شماست؟

تست تناسب بسیار کوتاه است. OneCLI زمانی ارزشمند است که چندین نفر به یک agent نیاز داشته باشند و بخواهید اعتبارنامه‌ها را در یک مکان متمرکز کنید: یک مخزن برای چرخش کلیدها، یک لاگ حسابرسی برای بررسی، و یک داشبورد که در آن لغو دسترسی یک شخص، واقعاً دسترسی او را قطع کند. این یک چالش عملیاتی واقعی است و کپی کردن یک API key در شش لپ‌تاپ، راهکار بدتری برای آن محسوب می‌شود.

برای یک نفر، این حجم از زیرساخت بدون بهره‌وری است. شما باید PostgreSQL، یک control plane، یک gateway و یک runner را اجرا کنید تا فقط یک agent داشته باشید؛ در حالی که مشکل اعتبارنامه‌ای که gateway حل می‌کند، زمانی که تنها دارنده کلید خودتان هستید، عملاً وجود ندارد. در عوض، یک harness تکی روی یک سرور کوچک‌تر اجرا کنید: یک agent harness تکی روی VPS این کار را با کسری از حافظه انجام می‌دهد. اگر هنوز هیچ مسیری را انتخاب نکرده‌اید، بررسی مقایسه agentهای هوش مصنوعی self-hosted گام اول ارزان‌تری است.

FAQ

حداقل نیازمندی‌های سرور برای میزبانی شخصی OneCLI چیست؟

نیاز به Docker با افزونه Compose نسخه 2.19 یا جدیدتر و حافظه کافی دارید. PostgreSQL همراه فایل compose ارائه می‌شود، بنابراین نیازی به نصب جداگانه آن نیست. حافظه تعیین‌کننده پلن شماست: هر sandbox عامل (agent) به‌صورت پیش‌فرض 2048 مگابایت حافظه اشغال می‌کند. مستندات آن پیشنهاد می‌دهد برای سرویس‌دهی به سقف پیش‌فرض چهار sandbox، حدود 10 گیگابایت فضای آزاد علاوه بر پشته پایه در نظر بگیرید؛ حدود 2 گیگابایت نیز صرف PostgreSQL و چهار سرویس اصلی می‌شود. یک سرور 4 گیگابایتی می‌تواند همزمان یک عامل را اجرا کند. یک سرور 16 گیگابایتی سقف پیش‌فرض را به‌راحتی پوشش می‌دهد. یک VPS با 1 یا 2 گیگابایت رم اصلاً قادر به اجرای عامل میزبانی‌شده نیست.

آیا OneCLI به PostgreSQL نیاز دارد یا می‌تواند از SQLite استفاده کند؟

این سرویس به PostgreSQL نیاز دارد. DATABASE_URL به‌عنوان رشته اتصال PostgreSQL مستند شده است، فایل compose ارائه‌شده، postgres:18-alpine را با یک volume از نوع pgdata اجرا می‌کند و یک سرویس مهاجرت (migrations) جداگانه، پیش از شروع API، طرح‌واره (schema) را اعمال می‌کند. هیچ گزینه‌ای برای SQLite مستند نشده است. اگر از قبل PostgreSQL را در جای دیگری اجرا می‌کنید، DATABASE_URL را به آن اشاره دهید و سرویس مهاجرت را حفظ کنید، زیرا شکست در مهاجرت باعث توقف پشته می‌شود و از سرویس‌دهی با طرح‌واره ناقص جلوگیری می‌کند.

آیا sandbox عامل OneCLI یک مرز امنیتی واقعی است؟

مکانیزم مستندشده، یک کانتینر Docker با محدودیت‌های حافظه، CPU و پردازش است که به شبکه‌ای با برچسب internal: true متصل شده تا به‌جز از طریق gateway، هیچ مسیر خروجی نداشته باشد. کنترل خروجی واقعی است و می‌توانید آن را با docker network inspect تأیید کنید. ایزوله‌سازی میزبان در حد قدرت کانتینر است و توسعه‌دهنده هیچ مدل تهدیدی، ادعای اجرای بدون root یا فضای نام کاربری، و هیچ مرز هسته‌ای مانند gVisor یا microVM منتشر نکرده است. همچنین runner مسیر /var/run/docker.sock را mount می‌کند که معادل دسترسی root روی میزبان است. مرز بین عامل و میزبان را تا زمانی که توسعه‌دهنده خلاف آن را اعلام نکرده، اثبات‌نشده در نظر بگیرید، OneCLI را روی یک سرور اختصاصی اجرا کنید و نسخه‌های پشتیبان را خارج از آن سرور نگه دارید.

آیا نیاز است پورت ورودی برای OneCLI باز کنم؟

خیر. runner فقط خروجی است و هیچ پورتی را که دنیای خارج بتواند به آن دسترسی داشته باشد باز نمی‌کند، بنابراین پشت NAT و بدون نیاز به تونل کار می‌کند. فایل compose به‌صورت پیش‌فرض dashboard، gateway، API و PostgreSQL را به 127.0.0.1 متصل می‌کند. برای دسترسی به dashboard از تونل SSH استفاده کنید، یا اگر چندین نفر به آن نیاز دارند، یک reverse proxy با TLS جلوی پورت 10254 قرار دهید. gateway روی پورت 10255 برای عامل‌ها است و در یک سرور واحد، عامل‌ها از طریق شبکه داخلی Docker به آن دسترسی پیدا می‌کنند.

آیا استفاده از OneCLI در شرکت رایگان است؟

هسته اصلی تحت مجوز Apache-2.0 است و استفاده تولیدی با میزبانی شخصی بدون نیاز به مجوز تجاری مجاز است. دایرکتوری‌های با نام ee/ تحت مجوز OneCLI Enterprise هستند که برای توسعه، تست و ارزیابی رایگان است اما در محیط تولید نیاز به اشتراک دارد. مرز این بخش‌بندی بین نسخه‌ها تغییر می‌کند و یادداشت‌های نسخه v2.0.1 مورخ 18 August 2026 به بازگرداندن فایل مجوز Apache-2.0 قابل شناسایی در GitHub اشاره دارند؛ بنابراین پیش از ساخت workflow روی هر ویژگی خاص، LICENSE و دایرکتوری‌های ee/ را در تگ دقیق نسخه‌ای که مستقر می‌کنید، بررسی کنید.