SSD Nodes Learn Hosting plans →
নির্দেশিকা Matt Connorদ্বারা Matt Connor · আপডেট করা হয়েছে 2026-09-08

HarnessRouter সেলফ-হোস্ট করার নিয়ম ও গাইড

Codex, Claude Code এবং Hermes-এর জন্য একটি একক API সেটআপ করুন। Docker ডেপ্লয়মেন্ট, লুপব্যাক বাইন্ডিং, ডিফল্ট পাসওয়ার্ড পরিবর্তন এবং TLS কনফিগারেশনের সঠিক ধাপগুলো এখানে দেখুন।

HarnessRouter যা দূর করে

আপনি আপনার নিজস্ব সার্ভারে একাধিক agent harness-এর সামনে একটি API বসানোর জন্য HarnessRouter Community Edition সেলফ-হোস্ট করেন। একটি agent harness হলো এমন একটি কমান্ড লাইন প্রোগ্রাম যা একটি লুপের মাধ্যমে মডেল পরিচালনা করে: এটি একটি সেশন বজায় রাখে, ফাইল এডিট করে, কমান্ড চালায় এবং কাজের অগ্রগতি যে অনুরোধ করেছে তার কাছে স্ট্রিম করে। Codex, Claude Code এবং Hermes প্রত্যেকেই এই কাজটি করে এবং প্রত্যেকের নিজস্ব ইনস্টলেশন পদ্ধতি, নিজস্ব ক্রেডেনশিয়াল ফরম্যাট এবং সেশন সম্পর্কে নিজস্ব ধারণা রয়েছে। HarnessRouter এদের সবাইকে একটি কন্টেইনারের ভেতরে চালায় এবং সামনে একটি একক HTTP endpoint, একটি একক লগইন এবং একটি একক সিক্রেট স্টোর প্রদান করে।

মূল ধারণাটি এটাই, এবং এর খরচ সম্পর্কে স্পষ্টভাবে বলা প্রয়োজন। আপনি আপনার সার্ভারে একটি কন্টেইনার, একটি লগইন, একটি ভলিউম এবং একটি আপগ্রেড পাথ যোগ করছেন যাতে একাধিক চলমান অংশ একটিতে পরিণত হয়। আপনি যদি বর্তমানে শুধুমাত্র একটি harness ব্যবহার করেন, তবে সরাসরি সেই harness ইনস্টল করার তুলনায় এটি একটি খারাপ সেটআপ। এই বিনিময় বা ট্রেড-অফ সম্পর্কে শেষ সেকশনে আলোচনা করা হয়েছে, তাই ডেপ্লয় করার আগে সেটি পড়ে নিন।

নিচের সবকিছু 0.5.5 ইমেজ ট্যাগের বিপরীতে যাচাই করা হয়েছে, যা 19 আগস্ট 2026 তারিখে পুল করা হয়েছিল। প্রজেক্টটি প্রায় প্রতিদিনই নতুন ট্যাগ প্রকাশ করে, তাই এক মাস পর এই পৃষ্ঠার ওপর নির্ভর না করে আপনি বর্তমানে যে ট্যাগটি চালাচ্ছেন তা যাচাই করে নিন। কমান্ডগুলো github.com/HarnessRouter/harnessrouter-এ থাকা প্রজেক্টের README থেকে নেওয়া হয়েছে।

Unified Harness Protocol আসলে কী

HarnessRouter, Unified Harness Protocol (UHP) বাস্তবায়ন করে, যা unifiedharnessprotocol.org-এ প্রকাশিত হয়েছে। UHP বর্ণনা করে কীভাবে একটি পণ্য harness-এ টাস্ক শুরু করে, টাস্ক চলার সময় তা অনুসরণ করে, সেশন ও ফাইল ব্যবস্থাপনা করে এবং ব্যর্থতার রিপোর্ট দেয়। এই স্পেসিফিকেশন তারিখ অনুযায়ী ভার্সন করা হয়। 19 আগস্ট 2026 পর্যন্ত কার্যকর ভার্সনটির তারিখ 2026-08-11 এবং সাইটটি একে একটি ড্রাফট স্ট্যান্ডার্ড হিসেবে উল্লেখ করে, যা "নির্মাণের জন্য যথেষ্ট স্থিতিশীল, এবং ভার্সন করা হয়েছে যাতে এটি নিরাপদে পরিবর্তিত হতে পারে"।

এখানে "open standard" বা উন্মুক্ত স্ট্যান্ডার্ড শব্দগুচ্ছটি সতর্কতার সাথে পড়ুন। একই কোম্পানি স্পেসিফিকেশন, রেফারেন্স ইমপ্লিমেন্টেশন এবং 52-চেক কনফরমেন্স স্যুট লেখে, যা নির্ধারণ করে কারা মানদণ্ড মেনে চলছে। এত নতুন একটি প্রোটোকলের জন্য এটি সাধারণ বিষয়, এবং Apache-2.0 লাইসেন্সের অর্থ হলো আপনি এর যেকোনো অংশ ফর্ক করতে পারবেন। এর মানে এটিও যে, UHP এখনো মাল্টি-ভেন্ডর স্ট্যান্ডার্ড হয়ে ওঠেনি। একে একটি উদীয়মান প্রোটোকল হিসেবে বিবেচনা করুন: এটি কার্যকর, পরিবর্তনশীল এবং এমন কিছু যা আপনার নিজের কোড থেকে কোনো বড় ধরনের পুনর্লিখন ছাড়াই বাদ দেওয়ার সক্ষমতা থাকা উচিত।

শুরু করার আগে আপনার যা প্রয়োজন

Docker এবং প্রায় 4 GB খালি ডিস্ক স্পেস। এছাড়া আপনার এমন একটি মডেল প্রোভাইডারের API key প্রয়োজন যার জন্য আপনি ইতিমধ্যে অর্থ প্রদান করেছেন। ইমেজটির সাইজ প্রায় 700 MB, এবং বাকি ডিস্ক স্পেস এজেন্ট CLI এবং তাদের ওয়ার্কস্পেসের জন্য ব্যবহৃত হয়। ইমেজটির ভেতরে কোনো মডেল বা ট্রায়াল কি (trial key) দেওয়া নেই, তাই আপনি কোনো প্রোভাইডারের সাথে সংযোগ না করা পর্যন্ত টাস্কগুলো ব্যর্থ হবে। HarnessRouter নিজে Apache-2.0 লাইসেন্সের অন্তর্ভুক্ত। এজেন্ট CLI-গুলো এই লাইসেন্সের আওতায় পড়ে না, যে কারণে এগুলো ইমেজে অন্তর্ভুক্ত না করে প্রথমবার চালু করার সময় ডাউনলোড করা হয়।

একটি docker run কমান্ডের মাধ্যমে HarnessRouter সেলফ-হোস্ট করা

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 আসা পর্যন্ত অপেক্ষা করুন। এই ইনস্টলেশনটি প্রতিটি ভলিউমের জন্য একবারই ঘটে, তাই পরবর্তী প্রতিটি স্টার্ট মাত্র কয়েক সেকেন্ড সময় নেয় এবং কোনো ইনস্টলেশন লাইন দেখায় না।

এই ডাউনলোড থেকে দুটি বিষয় স্পষ্ট হয়, যা একটি VPS-এর ক্ষেত্রে গুরুত্বপূর্ণ। প্রথমত, প্রথমবার বুট করার সময় আউটবাউন্ড নেটওয়ার্ক অ্যাক্সেস প্রয়োজন। ইমেজটি স্বয়ংসম্পূর্ণ নয়, তাই কোনো egress ফিল্টারের পেছনে থাকা সার্ভার বা যেটির বাইরে যাওয়ার কোনো রুট নেই, সেটি এখানে আটকে যাবে এবং কখনোই ready on :3000 প্রিন্ট করবে না। এটি প্রথম স্টার্টেই ব্যর্থ হয়, docker pull-এ নয়, যা সমস্যাটি খুঁজে বের করার জন্য বিভ্রান্তিকর হতে পারে। দ্বিতীয়ত, আপনি তৃতীয় পক্ষের শর্তাবলির অধীনে তৃতীয় পক্ষের সফটওয়্যার ইনস্টল করছেন। Claude Code আসে Anthropic-এর শর্তাবলির অধীনে এবং Hermes আসে এর আপস্ট্রিম প্রোভাইডারের শর্তাবলির অধীনে, তাই বাণিজ্যিকভাবে ব্যবহারের আগে উভয়ই যাচাই করে নিন।

-v harnessrouter:/data একটি নামযুক্ত Docker ভলিউম তৈরি করে। সমস্ত স্থায়ী ডেটা /data-এ থাকে: SQLite ডেটাবেস, সংরক্ষিত ফাইল, সিক্রেট স্টোর এবং এজেন্টের ওয়ার্কস্পেস। এই ভলিউমটি মুছে ফেললে আপনার ইনস্ট্যান্সটিও মুছে যাবে, যার মধ্যে প্রোভাইডার কি (keys) এবং সমস্ত ট্রান্সক্রিপ্ট অন্তর্ভুক্ত। কন্টেইনারটি বন্ধ থাকা অবস্থায় এর ব্যাকআপ নিন, কারণ SQLite ডেটাবেস লেখার সময় কপি করলে ফাইলটি আর ওপেন নাও হতে পারে। একই নিয়ম (প্রথমে বন্ধ করা, তারপর কপি করা) সার্ভারের প্রতিটি স্টেটফুল কন্টেইনারের ক্ষেত্রে প্রযোজ্য, যদিও পরিষেবার ধরন অনুযায়ী বিস্তারিত প্রক্রিয়া ভিন্ন হতে পারে, কারণ 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:

আপস্ট্রিম থেকে দুটি বিষয় ভিন্ন: bind address এবং latest-এর পরিবর্তে একটি নির্দিষ্ট version tag ব্যবহার করা। ভার্সন পিন করা জরুরি কারণ 9 থেকে 18 আগস্ট 2026-এর মধ্যে ষোলটি ভার্সন রিলিজ হয়েছে, এবং আপনার অজান্তে পরিবর্তিত হওয়া এজেন্ট রানটাইম ডিবাগ করা কঠিন। এরপর environment ফাইলটি কপি করুন, এর পারমিশন লক করুন এবং শুরু করুন।

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

.env-এ আপনার প্রোভাইডার কি (key) প্লেইন টেক্সটে থাকে, তাই এর জন্য mode 600 হলো ন্যূনতম প্রয়োজনীয় পারমিশন। যদি docker compose সাবকমান্ডটি আপনার অপরিচিত হয়, তবে Docker Compose কমান্ড চিট শিট-এ দৈনন্দিন প্রয়োজনীয় কমান্ডগুলো দেখে নিতে পারেন।

কেন পোর্টটি 0.0.0.0-এর পরিবর্তে 127.0.0.1-এ পাবলিশ করা হয়

-p 3000:3000 হোস্টের প্রতিটি ইন্টারফেসে পোর্ট পাবলিশ করে। -p 127.0.0.1:3000:3000 শুধুমাত্র লুপব্যাকে এটি পাবলিশ করে, যার অর্থ হলো শুধুমাত্র VPS-এর ভেতর থেকেই এতে প্রবেশ করা সম্ভব। কন্টেইনারটি সবসময় ভেতরে 3000 পোর্টে লিসেন করে, তাই বামদিকের অংশটিই আপনি পরিবর্তন করবেন। আপনার কনফিগারেশন যাচাই করুন:

docker port harnessrouter
sudo ss -ltnp | grep 3000

ss প্রিন্ট করা 127.0.0.1:3000 সঠিক। 0.0.0.0:3000 মানে হলো কনসোলটি পাবলিক ইন্টারনেটে উন্মুক্ত। বেশিরভাগ self-hosted অ্যাপের তুলনায় এটি এখানে অনেক বেশি ঝুঁকিপূর্ণ, কারণ কনসোলটি হার্নেস তৈরি করে, প্রতিটি ট্রান্সক্রিপ্ট পড়ে, এজেন্ট চালায় এবং সেই এজেন্টদের একটি শেল ও তাদের ওয়ার্কস্পেসে একটি বাস্তব ফাইলসিস্টেম ব্যবহারের সুযোগ দেয়। এটি আপনার কানেক্ট করা প্রোভাইডার কি (key)-ও সংরক্ষণ করে। যে কেউ এই অরক্ষিত কনসোলে পৌঁছাতে পারলে আপনার কাজ পড়তে পারবে, কমান্ড চালাতে পারবে এবং আপনার কি (key) ব্যবহার করে খরচ করতে পারবে।

একটি হোস্ট ফায়ারওয়াল আপনাকে এই ঝুঁকি থেকে রক্ষা করবে না। ডকার তার নিজস্ব রুলগুলো কার্নেল nat টেবিলে লিখে পোর্ট পাবলিশ করে, এবং ufw যে চেইনগুলো ম্যানেজ করে তার আগেই এগুলো মূল্যায়ন করা হয়। তাই একটি পাবলিশ করা পোর্ট সবসময়ই অ্যাক্সেসযোগ্য থাকে, এমনকি sudo ufw status-এ সেটি ডিনাই (denied) হিসেবে থাকলেও। অন্য কোনো মেশিন থেকে পরীক্ষা করুন, VPS থেকে নয়, অন্যথায় আপনার পরীক্ষাটি কার্যকর হবে না। এটি 3080 পোর্টে dsh headless চালানো-এর মতোই একটি শিক্ষা: সার্ভিসটিকে লুপব্যাকে বাইন্ড করুন, তারপর আপনি কীভাবে এটি অ্যাক্সেস করবেন তা ভেবেচিন্তে সিদ্ধান্ত নিন।

অন্য যেকোনো কিছু করার আগে ডিফল্ট লগইন পরিবর্তন করুন

http://localhost:3000-এ harnessrouter ইউজারনেম এবং harnessrouter পাসওয়ার্ড ব্যবহার করে সাইন ইন করুন। এই ক্রেডেনশিয়ালগুলো 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 ফাইলটি ডিলিট করে রিস্টার্ট দিন, তারপর আবার ডিফল্ট ক্রেডেনশিয়াল দিয়ে সাইন ইন করুন।

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

HR_AUTH_DISABLED=1 সাইন-ইন গেটটিকে পুরোপুরি সরিয়ে ফেলে। README-তে এটিকে এমন একটি "বক্স যা অন্য কেউ অ্যাক্সেস করতে পারে না" হিসেবে সীমাবদ্ধ করা হয়েছে। পাবলিক IP অ্যাড্রেসযুক্ত একটি VPS এমন বক্স নয়, তাই আপনি যদি এটি ল্যাপটপে না চালান তবে গেটটি চালু রাখুন।

আপনার ভার্সন চেক করুন, কারণ পুরনো ভার্সনে কোনো গেট নেই

এই অংশটি গুরুত্বের সাথে দেখুন। 0.1.x এবং 0.2.0 ভার্সনগুলোতে কোনো অথেন্টিকেশন গেট ছিল না: যে কেউ পোর্ট 3000-এ অ্যাক্সেস করতে পারলেই সরাসরি কনসোলে ঢুকে পড়তে পারত। 0.3.0 ছিল প্রথম রিলিজ যেখানে লগইন ব্যবস্থা যুক্ত করা হয়। সেই পুরনো ট্যাগগুলো এখনো পাবলিশ করা আছে এবং সেগুলো পুল করা সম্ভব, তাই কোনো পুরনো পিন করা ট্যাগ বা সহকর্মীর কাছ থেকে কপি করা compose ফাইল ব্যবহার করলে বর্তমানে পাবলিক পোর্টে একটি অরক্ষিত কনসোল চালু হয়ে যেতে পারে।

19 আগস্ট 2026 অনুযায়ী সর্বশেষ পাবলিশ করা ট্যাগ হলো 0.5.5, যার তারিখ 18 আগস্ট 2026 এবং latest সেটিকে নির্দেশ করে। আপনার কাছে কোনটি আছে তা চেক করুন এবং Docker Hub-এর ট্যাগ তালিকার সাথে মিলিয়ে দেখুন:

docker image ls harnessrouter/harnessrouter

0.3.0-এর নিচের যেকোনো ভার্সন এখনই পরিবর্তন করা উচিত, এটি পরে করার জন্য ফেলে রাখবেন না। এর সমান বা তার উপরের ভার্সনগুলোতেও পাসওয়ার্ড পরিবর্তন করা প্রয়োজন, কারণ পোর্ট 3000 স্ক্যান করা কারো কাছে ডিফল্ট পাসওয়ার্ড থাকা আর পাসওয়ার্ড না থাকা একই কথা। এই পৃষ্ঠায় থাকা ভার্সন নম্বরগুলোকে বর্তমান হিসেবে ধরবেন না। উপরের তারিখে এগুলো সঠিক ছিল, কিন্তু এই প্রজেক্ট খুব দ্রুত আপডেট হয়।

প্রোভাইডার সংযুক্ত করুন

একটি মডেল প্রোভাইডার সংযুক্ত না করা পর্যন্ত কোনো কিছুই কাজ করবে না। কনসোলের Integrations পৃষ্ঠা থেকে একটি প্রোভাইডার যোগ করুন, অথবা এনভায়রনমেন্টে docker run-এর মাধ্যমে এটি পাস করুন। এর মান JSON ফরম্যাটে থাকে, তাই শেলের মধ্যে এটিকে কোটেশনের ভেতরে রাখুন:

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

.env.example প্রতিটি প্রোভাইডার ফ্যামিলির জন্য একটি করে কানেকশন ভেরিয়েবল নির্ধারণ করে: claude-code ব্যাকএন্ডের জন্য HR_SECRET_GLOBAL_HARNESS_CONN_ANTHROPIC, codex ব্যাকএন্ডের জন্য HR_SECRET_GLOBAL_HARNESS_CONN_OPENAI, এবং যেকোনো OpenAI-সামঞ্জস্যপূর্ণ এন্ডপয়েন্টের জন্য HR_SECRET_GLOBAL_HARNESS_CONN_CUSTOM, যেখানে একটি এগ্রিগেটর বা আপনার নিজস্ব ইনফারেন্স সার্ভার যুক্ত করা হয়। সংশ্লিষ্ট HR_SECRET_GLOBAL_HARNESS_POLICY_CLAUDE, HR_SECRET_GLOBAL_HARNESS_POLICY_CODEX এবং HR_SECRET_GLOBAL_HARNESS_POLICY_HERMES ভেরিয়েবলগুলো নির্দেশ করে যে প্রতিটি ব্যাকএন্ড ডিফল্টভাবে কোন কানেকশন ব্যবহার করবে। HR_SECRET_KEY একটি আলাদা বিষয় এবং এটি শুধুমাত্র তখনই প্রয়োজন যখন আপনি কোনো এজেন্টের সাথে ডেটাবেস সংযুক্ত করেন।

HR_BACKENDS নির্বাচন করে কোন ব্যাকএন্ডগুলো লোড হবে, যেমনটি HR_BACKENDS=claude,codex,hermes-এ দেখা যায়। একটি পরিচিত সমস্যা সম্পর্কে আগে থেকেই জেনে রাখা ভালো: এমন কোনো মান যা hermes-কে বাদ দেয়, তা কন্টেইনারটিকে কোনো এরর মেসেজ ছাড়াই তাৎক্ষণিকভাবে status 1-এ এক্সিট করিয়ে দেয়। শুরু করার এক সেকেন্ডের মধ্যেই আপনি docker ps -a-এ Exited (1) দেখতে পাবেন এবং docker logs কোনো কার্যকর তথ্য দেখাবে না। আপস্ট্রিম থেকে এটি ঠিক না করা পর্যন্ত hermes-কে তালিকার মধ্যে রাখুন। যদি Hermes-ই আপনার একমাত্র কাঙ্ক্ষিত হারনেস হয়, তবে Hermes এজেন্টকে নিজস্ব VPS-এ চালানো ছোট আকারের ডেপ্লয়মেন্টের জন্য উপযুক্ত।

কনসোল ছাড়া API কল করা

কনসোল ব্যবহার করা ঐচ্ছিক। একই API উভয় ক্ষেত্রেই কাজ করে এবং এটি Responses-স্টাইলের চুক্তি অনুসরণ করে। সেশন কুকি পেতে প্রথমে সাইন ইন করুন:

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

এরপর একটি টাস্ক পাঠান, যেখানে 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_id-এর মান codex থেকে পরিবর্তন করে claude করলে একই অনুরোধ ভিন্ন একটি হার্নেসে পাঠানো হয়, এবং এই অদলবদল করার সক্ষমতাই এই সফটওয়্যারটির মূল উদ্দেশ্য। উপরের কাস্টম কানেকশনটি ব্যবহার করে আপনি আপনার হোস্ট করা OpenAI-সামঞ্জস্যপূর্ণ এন্ডপয়েন্টে হার্নেস নির্দেশ করতে পারেন, ঠিক যেভাবে VPS-এ একটি self-hosted DeepSeek হার্নেস কনফিগার করা হয়।

পাবলিক পোর্ট ওপেন না করেই আপনার ল্যাপটপ থেকে এটি অ্যাক্সেস করুন

দুটি উপায় আছে, এবং এর কোনোটিই 0.0.0.0-এ সরাসরি পোর্ট ওপেন করে না।

একটি SSH tunnel হলো সবচেয়ে সহজ উপায়, এবং এর জন্য সার্ভারে বাড়তি কিছু ইনস্টল করার প্রয়োজন নেই। এটি আপনার মেশিনের একটি লোকাল পোর্টকে VPS-এর লুপব্যাক (loopback) ঠিকানায় ফরোয়ার্ড করে।

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 পোর্টে ব্রাউজ করুন।

একটি টার্মিনেটিং রিভার্স প্রক্সি (terminating reverse proxy) হলো সেই সমাধান যখন অন্যদেরও অ্যাক্সেসের প্রয়োজন হয়। প্রক্সিটি TLS (transport layer security) সার্টিফিকেট ধরে রাখে এবং লুপব্যাক ঠিকানায় ট্রাফিক ফরোয়ার্ড করে। 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 হলো সেই লাইনটি যা অনেকেই মিস করেন। এজেন্ট কয়েক মিনিট ধরে স্ট্রিম টোকেন পাঠাতে থাকে, আর যে প্রক্সি রেসপন্স বাফার করে, সেটি টার্ন শেষ না হওয়া পর্যন্ত টোকেনগুলো আটকে রাখে। ফলে কনসোলটি জমে গেছে বলে মনে হয় এবং পরে সব তথ্য একসাথে প্রদর্শিত হয়। Nginx-এর ক্ষেত্রে এর সমতুল্য হলো লোকেশন ব্লকের ভেতরে proxy_buffering off;। আপনি যেটাই বেছে নিন না কেন, DNS নামটি প্রক্সির দিকে পয়েন্ট করে রাখুন এবং কন্টেইনারটিকে লুপব্যাকে রাখুন। রিভার্স প্রক্সি হিসেবে Nginx, Caddy এবং Traefik-এর তুলনা অংশে আপনার সার্ভারের জন্য কোনটি উপযুক্ত তা বিস্তারিত আলোচনা করা হয়েছে।

root হিসেবে নয়, নিজস্ব ইউজার হিসেবে চালান

Docker daemon root হিসেবে চলে এবং docker গ্রুপের সদস্যপদ root হিসেবে থাকার সমতুল্য, কারণ একজন সদস্য এমন একটি কন্টেইনার চালু করতে পারে যা হোস্ট ফাইলসিস্টেমকে মাউন্ট করে। তাই "টিমকে docker গ্রুপে যোগ করা" মানে আপনার প্রোভাইডার কি (provider key) থাকা বক্সে root অ্যাক্সেস দিয়ে দেওয়া।

সহজ সংস্করণ: একটি সার্ভিস অ্যাকাউন্ট তৈরি করুন যা compose ফাইল এবং .env-এর মালিক হবে, এবং এই ফাইলগুলোকে কোনো শেয়ার্ড হোম ডিরেক্টরি থেকে দূরে রাখুন।

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

আরও শক্তিশালী সংস্করণ হলো rootless Docker, যেখানে daemon নিজেই সেই আনপ্রিভিলেজড (unprivileged) ইউজার হিসেবে চলে। এর জন্য newuidmap এবং newgidmap-এর জন্য uidmap প্যাকেজ প্রয়োজন, এবং ইউজারের জন্য /etc/subuid/etc/subgid-এ অন্তত 65536টি সাবঅর্ডিনেট UID থাকতে হবে। uidmap উবুন্টু আর্কাইভে আছে, কিন্তু docker-ce-rootless-extras নেই: এটি Docker-এর নিজস্ব apt রিপোজিটরি download.docker.com থেকে আসে, যা Docker ইঞ্জিন ইনস্টল করার সময় যোগ করা হয়। আপনি যদি সেই রিপোজিটরি থেকে ইঞ্জিন ইনস্টল না করে থাকেন, তবে 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 ঐচ্ছিক নয়। এটি ছাড়া ইউজারের systemd ইনস্ট্যান্স শেষ সেশন বন্ধ হওয়ার সাথে সাথে থেমে যায়, ফলে আপনি লগ আউট করলে কন্টেইনারটিও বন্ধ হয়ে যায়। docker info দিয়ে ফলাফল নিশ্চিত করুন, যা Security Options-এর অধীনে rootless তালিকাভুক্ত করে। Rootless মোড অতিরিক্ত কনফিগারেশন ছাড়া 1024-এর নিচের পোর্টগুলোতে বাইন্ড করতে পারে না, তবে এখানে তা কোনো সমস্যা নয় কারণ পোর্ট 3000 সেই সীমার উপরে। অ্যাকাউন্ট সেটআপ করার বিষয়টি VPS-এ ন্যূনতম প্রিভিলেজড ইউজার তৈরি অংশে আলোচনা করা হয়েছে।

কী কী সমস্যা হতে পারে এবং আপনি কী দেখবেন

কন্টেইনারটি চালু হওয়ার এক সেকেন্ড পরেই বন্ধ হয়ে যায় এবং লগ খালি থাকে। docker ps -a-এ Exited (1) দেখাচ্ছে। এটি উপরের HR_BACKENDS সমস্যা: আপনার ভ্যালু থেকে hermes বাদ পড়েছে। এটি পুনরায় যোগ করুন।

প্রথমবার চালু হওয়ার প্রক্রিয়া শেষ হয় না। লগটি একটি installing লাইনের পর থেমে যায় এবং ready on :3000 কখনোই আসে না। বক্সটি এজেন্ট CLI ডাউনলোড করার জন্য নেটওয়ার্কে পৌঁছাতে পারছে না, কারণ সেগুলো ইমেজের মধ্যে নেই। আউটবাউন্ড রুট বা প্রক্সি সেটিংস ঠিক করুন, তারপর পুনরায় চালু করুন।

কনসোল লোড হয় কিন্তু প্রতিটি টাস্ক ব্যর্থ হয়। কোনো প্রোভাইডার সংযুক্ত নেই। ইমেজের ভেতরে কোনো বান্ডেল করা মডেল বা ফ্রি টায়ার নেই, তাই একটি নতুন ইনস্ট্যান্স আপনাকে সাইন-ইন করতে দিলেও কোনো কিছু চালাতে পারবে না।

প্রক্সির পেছনে কনসোল উত্তরের মাঝপথে ফ্রিজ হয়ে যায়। টার্ন শেষ হলে আউটপুটটি একবারে একটি ব্লকে প্রদর্শিত হয়। এটি রেসপন্স বাফারিংয়ের কারণে হয়। Caddy-তে flush_interval -1 সেট করুন, অথবা Nginx-এ proxy_buffering off; সেট করুন।

আপনার ল্যাপটপ থেকে এটিতে পৌঁছানো যাচ্ছে না অথচ টানেল চালু আছে। সার্ভারে docker port harnessrouter চালান। যদি এটি কিছু না দেখায়, তবে কন্টেইনারটি কিছুই পাবলিশ করছে না, অর্থাৎ এটি -p ছাড়াই চালু করা হয়েছে।

এটি কি চালানো লাভজনক?

আপনি যদি সত্যিই একাধিক harness ব্যবহার করেন এবং প্রতিটির জন্য তিনটি আলাদা endpoint ও credential store-এর পরিবর্তে একটিই ব্যবহার করতে চান, তবে এটি চালানো লাভজনক। আপনি যদি এর ওপর ভিত্তি করে কোনো পণ্য তৈরি করেন এবং harness-কে কোড পুনর্লিখন না করে একটি configuration value হিসেবে রাখতে চান, তবে এটি চালানো কার্যকর। UHP আপনাকে এই সুবিধাটিই দেয়, তবে প্রোটোকলটি নতুন হওয়ার কারণে উপরে উল্লিখিত সতর্কতাটি মাথায় রাখতে হবে।

আপনি যদি কেবল একটি harness ব্যবহার করেন, তবে এটি চালানো লাভজনক নয়। সার্ভারে সরাসরি সেই CLI ইনস্টল করা অনেক সহজ এবং আপনার ও সেটির মাঝে কোনো login প্রক্রিয়ার প্রয়োজন হয় না। এছাড়া, আপনি যদি এমন কিছু চান যেখানে একাধিক agent একটি কাজে সহযোগিতা করবে, তবে এটি সঠিক সমাধান নয়; কারণ এটি একাধিক harness-এর সামনে একটি API হিসেবে কাজ করে। সেই ধরনের কাজের জন্য ভিন্ন টুল প্রয়োজন: এই প্যাটার্নের জন্য Omnigent-এর মতো একটি multi-agent harness দেখুন। যাই হোক না কেন, deployment-এর নিয়মগুলো একই থাকে। Loopback bind, পরিবর্তিত password, 0.3.0 বা তার পরবর্তী pinned tag এবং নিজস্ব user ব্যবহার করুন।

FAQ

HarnessRouter-কে পোর্ট 3000-এ পাবলিশ করা কি নিরাপদ?

না। কনসোলটি হার্নেস তৈরি করে, প্রতিটি ট্রান্সক্রিপ্ট পড়ে, শেল ও ফাইলসিস্টেম অ্যাক্সেসসহ এজেন্ট চালায় এবং আপনার সংযুক্ত প্রোভাইডার কি (key) সংরক্ষণ করে। তাই পোর্টটি খোলা রাখলে এই সবকিছুই উন্মুক্ত হয়ে যায়। এটিকে -p 127.0.0.1:3000:3000 ব্যবহার করে লুপব্যাক ইন্টারফেসে পাবলিশ করুন এবং SSH টানেল বা TLS-টার্মিনেটিং রিভার্স প্রক্সির মাধ্যমে অ্যাক্সেস করুন। শুধুমাত্র হোস্ট ফায়ারওয়াল যথেষ্ট নয়: Docker নিজেই কার্নেলের nat টেবিলে নিজস্ব রুল লেখে, তাই ufw-এ ডিনাইড দেখালেও পাবলিশ করা পোর্ট ইন্টারনেট থেকে রেসপন্স করতে পারে। sudo ss -ltnp | grep 3000 দিয়ে যাচাই করুন, যা থেকে 127.0.0.1:3000 আউটপুট আসা উচিত।

HarnessRouter-এর কোন ভার্সনে লগইন গেট যুক্ত করা হয়েছে?

0.3.00.1.x এবং 0.2.0 ভার্সনগুলোতে কোনো অথেন্টিকেশন ছিল না। উভয় ট্যাগই এখনো পাবলিশ করা আছে এবং পুল করা সম্ভব, তাই যারা এগুলো ব্যবহার করছেন তারা কেবল পোর্টের নিরাপত্তা গোপন থাকার ওপর নির্ভর করছেন। 19 আগস্ট 2026 অনুযায়ী নতুন ট্যাগ হলো 0.5.5, যার তারিখ 18 আগস্ট 2026। আপনার কাছে কোনটি আছে তা দেখতে docker image ls harnessrouter/harnessrouter চালান, এই পৃষ্ঠার পরিবর্তে Docker Hub-এর ট্যাগ তালিকার সাথে তা মিলিয়ে দেখুন এবং বর্তমান ভার্সনেও ডিফল্ট পাসওয়ার্ড পরিবর্তন করুন।

HR_BACKENDS সেট করার পরপরই কন্টেইনারটি এক্সিট হয়ে যায় কেন?

যেকোনো HR_BACKENDS ভ্যালু যাতে hermes বাদ দেওয়া হয়েছে, তা কন্টেইনারটিকে কোনো এরর মেসেজ ছাড়াই স্ট্যাটাস 1-এ এক্সিট করিয়ে দেয়। এটি প্রজেক্টের README-তে উল্লিখিত একটি পরিচিত সমস্যা। এর লক্ষণ হলো এক বা দুই সেকেন্ডের মধ্যে docker ps -a-এ Exited (1) দেখা দেওয়া এবং docker logs-এ কোনো কার্যকর তথ্য না থাকা। আপস্ট্রিম থেকে এটি ঠিক না করা পর্যন্ত HR_BACKENDS=claude,codex,hermes-এর মতো তালিকায় hermes বজায় রাখুন।

প্রথমবার স্টার্ট করার সময় কি HarnessRouter-এর ইন্টারনেট অ্যাক্সেস প্রয়োজন?

হ্যাঁ। এজেন্ট CLI-গুলো ইমেজের সাথে না দিয়ে প্রথমবার স্টার্ট করার সময় ডাউনলোড করা হয়, কারণ প্রতিটির নিজস্ব লাইসেন্স থাকে। আউটবাউন্ড রুট নেই এমন বক্সে installing লাইনগুলো প্রিন্ট হয় এবং এরপর এটি কখনোই ready on :3000-এ পৌঁছাতে পারে না। ডাউনলোডটি প্রতি ভলিউমে একবারই ঘটে, তাই পরবর্তী স্টার্টগুলো কয়েক সেকেন্ড সময় নেয় এবং আপনার সংযুক্ত মডেল প্রোভাইডার ছাড়া অন্য কোনো নেটওয়ার্কের প্রয়োজন হয় না।

কনসোলের পাসওয়ার্ড হারিয়ে ফেলেছি। কীভাবে পুনরায় প্রবেশ করব?

এখানে কোনো রিসেট ইমেইল নেই, কারণ কোনো অ্যাকাউন্ট সিস্টেম বা মেইল সার্ভার নেই। কন্টেইনারটি স্টপ করুন, ভলিউম থেকে /data/selfhost-auth.json ডিলিট করুন, পুনরায় স্টার্ট করুন, তারপর ডিফল্ট ক্রেডেনশিয়াল দিয়ে সাইন ইন করে প্রোফাইল পেজ থেকে নতুন পাসওয়ার্ড সেট করুন। কন্টেইনার এবং ভলিউমের নাম harnessrouter হলে, কমান্ডগুলো হবে docker stop harnessrouter, তারপর docker run --rm -v harnessrouter:/data alpine rm -f /data/selfhost-auth.json, এবং সবশেষে docker start harnessrouter