SSD Nodes Learn 🎉 VPS $5.50/মাস থেকে
নির্দেশিকা Matt Connorদ্বারা Matt Connor · আপডেট করা হয়েছে 2026-08-21

VPS-এ systemd দিয়ে headless dsh চালানোর নিয়ম

VPS-এ dsh-এর systemd service বানান: নির্দিষ্ট user, pinned version, Restart নিয়ম, journalctl log এবং SSH tunnel দিয়ে UI দেখার সম্পূর্ণ নির্দেশিকা।

টার্মিনালে নয়, VPS-এ headless অবস্থায় dsh চালান

VPS-এ headless অবস্থায় dsh চালানোর জন্য একটি systemd unit file এবং সেটির মালিকানার জন্য একটি নির্দিষ্ট user প্রয়োজন। dsh হলো DeepSeek Harness-এর command-line launcher। DeepSeek-এর এই agent runtime MIT licence-এর অধীনে August 2026-এ developer preview হিসেবে প্রকাশিত হয়েছে। quickstart-এ npx @deepseek-ai/dsh web টাইপ করতে বলা হয়েছে। এটি সঠিক। তবে SSH (secure shell) session বন্ধ করলেই এটি বন্ধ হয়ে যায়।

একটি unit file একসঙ্গে চারটি সমস্যার সমাধান করে। reboot-এর পরে service আবার চালু হয়। এর output আপনার terminal-এ স্ক্রল না হয়ে journal-এ যায়। এটি root নয় এমন একটি account হিসেবে চলে। আপনি যে version নির্বাচন করেছেন, এটিই service চালায়। এখানে এটি সাধারণের চেয়ে বেশি গুরুত্বপূর্ণ, কারণ upstream স্পষ্টভাবে জানিয়েছে:

DeepSeek Harness বর্তমানে developer preview অবস্থায় আছে এবং দ্রুত পরিবর্তিত হচ্ছে। COMPATIBILITY-BREAKING CHANGES ঘটবেই।

এই নির্দেশিকায় ধরে নেওয়া হয়েছে যে আপনি হাতে চালিয়ে dsh ইতিমধ্যে ব্যবহার করতে পারছেন। তা না হলে VPS-এ DeepSeek Harness install করা দিয়ে শুরু করুন। এরপর npx @deepseek-ai/dsh web একটি page serve করলে এখানে ফিরে আসুন।

Node আগে, কারণ npm আপনাকে সতর্ক করবে না

node -v

Ubuntu 24.04-এর নিজস্ব package হলো Node 18 (August 2026 অনুযায়ী 18.19.1)। এই বছর প্রকাশিত কোনো package-এর জন্য এটি পুরোনো। @deepseek-ai/dsh কোনো engines field প্রকাশ করে না। তাই আপনার Node সংস্করণ খুব পুরোনো হলেও npm কোনো EBADENGINE warning দেখায় না। পরিবর্তে run time-এ failure দেখা দেয়। এটি syntax error বা কোনো built-in অনুপস্থিত থাকার মতো সমস্যা হতে পারে। সমস্যা শনাক্ত করার জন্য এটি অনেক খারাপ সময়। NodeSource থেকে বর্তমান long term support (LTS) release install করুন:

curl -fsSL https://deb.nodesource.com/setup_22.x -o /tmp/nodesource_setup.sh
less /tmp/nodesource_setup.sh
sudo -E bash /tmp/nodesource_setup.sh
sudo apt install -y nodejs
node -v

এখন node -v-এর output-এ একটি v22 version দেখানোর কথা। less line-টি রাখা হয়েছে, কারণ remote script সরাসরি bash-এ pipe করলে আপনি না পড়েই code চালান।

Unit file লেখার আগে এটি চলছে কি না যাচাই করুন

npx @deepseek-ai/dsh@0.1.0-rc.7 web

এটি চলমান রাখুন। দ্বিতীয় SSH session থেকে:

curl -fsS http://127.0.0.1:3080/ -o /dev/null && echo up

up বোঝায় যে web profile loopback-এ listening করছে; ডিফল্টভাবে এটি সেখানেই bind হয়। curl: (7) Failed to connect to 127.0.0.1 port 3080: Connection refused বোঝায় যে এটি listening করছে না, এবং প্রথম terminal আপনাকে কারণ জানাচ্ছে। পরবর্তী ধাপে যাওয়ার আগে Ctrl+C দিয়ে manual run বন্ধ করুন: অন্য কোনো process ইতিমধ্যে দখল করে রাখা port-এ bind করার চেষ্টা করা unit Error: listen EADDRINUSE: address already in use 127.0.0.1:3080-এ ব্যর্থ হয়।

18 August 2026-এ 0.1.0-rc.7-এ published version ছিল। npm view @deepseek-ai/dsh version দিয়ে বর্তমান version পরীক্ষা করুন, তারপর যে version চালানোর সিদ্ধান্ত নেন সেটি নির্দিষ্ট করে দিন।

আপনি নির্ধারিত version-টি globally install করুন

একটি unit file-এর ভিতরে npx ব্যবহার করা সঠিক পদ্ধতি নয়। Process শুরু হওয়ার সময় এটি package version resolve করে। তাই আপনার পক্ষ থেকে কোনো পরিবর্তন না হলেও, 3 মাস পরে restart হলে preview-stage agent-এর ভিন্ন build চালু হতে পারে। Boot-এর সময় npm registry-তে পৌঁছানোও প্রয়োজন হয়। Registry ধীর থাকলে কাজ করা মেশিনেও সেদিন unit ব্যর্থ হবে। একবার install করুন এবং version লিখে রাখুন:

sudo npm install -g @deepseek-ai/dsh@0.1.0-rc.7
command -v dsh
npm ls -g --depth=0 @deepseek-ai/dsh

NodeSource থেকে npm এলে command -v dsh `/usr/bin/dsh দেখায়, আর Ubuntu-এর নিজস্ব package থেকে এলে /usr/local/bin/dsh দেখায়। Unit file-এ যে path এটি বাস্তবে দেখিয়েছে, সেটিই ব্যবহার করুন। npm ls -g` সঠিক version দেখায়। 6 সপ্তাহ পরে আচরণ পরিবর্তিত হলে এবং আপনি কী install করেছিলেন তা মনে না থাকলে এই version-ই আপনার প্রয়োজন হবে।

A user that owns the service and nothing else

The agent runs shell commands. That is its job. Running it as root makes every tool call a root tool call, so give it its own account with no login shell.

sudo useradd --system --create-home --home-dir /var/lib/dsh --shell /usr/sbin/nologin dsh
sudo install -d -o dsh -g dsh -m 750 /var/lib/dsh/harness /var/lib/dsh/workspace
id dsh

/var/lib/dsh/harness becomes DSH_HOME, the directory dsh keeps profiles in. A profile is a named stack of plugin bundles with your own patch layer on top, and the web and headless profiles build themselves from shipped templates the first time you boot them. That first boot writes files and may fetch bundles, so do it by hand where you can watch it.

sudo -u dsh env HOME=/var/lib/dsh DSH_HOME=/var/lib/dsh/harness /usr/bin/dsh --profile web

Set HOME explicitly rather than trusting what sudo does with it, because whether sudo rewrites HOME for a non-login command depends on the set_home setting in /etc/sudoers. Get it wrong and the first run drops cache directories into your home directory owned by dsh, and the service later cannot find its own state. Stop it with Ctrl+C once the curl check returns up.

ইউনিট ফাইল

/etc/systemd/system/dsh.service লিখুন:

[Unit]
Description=DeepSeek Harness (dsh) web profile
Documentation=https://github.com/deepseek-ai/deepseek-harness
After=network-online.target
Wants=network-online.target
StartLimitIntervalSec=300
StartLimitBurst=5

[Service]
Type=exec
User=dsh
Group=dsh
WorkingDirectory=/var/lib/dsh/workspace
Environment=HOME=/var/lib/dsh
Environment=DSH_HOME=/var/lib/dsh/harness
ExecStart=/usr/bin/dsh --profile web
Restart=on-failure
RestartSec=5s
TimeoutStopSec=30s
SyslogIdentifier=dsh
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=true

[Install]
WantedBy=multi-user.target

ExecStart=-এ command -v dsh থেকে পাওয়া absolute path দিন। systemd একটি bare command name-এর জন্য নির্দিষ্ট path list অনুসন্ধান করে। তবে সেই list আপনার shell-এর PATH নয়। তাই absolute path ব্যবহার করলে অনুমানের প্রয়োজন থাকে না।

WorkingDirectory=-এ relative path resolve হয়। কোনো argument ছাড়া ls চালানো tool call-ও এখান থেকেই শুরু হয়। agent-কে দেওয়া workspace-এর path এখানে উল্লেখ করুন। Directory না থাকলে, অথবা service user সেটিতে প্রবেশ করতে না পারলে, dsh চালুর আগেই unit status=200/CHDIR-সহ ব্যর্থ হয়।

ProtectHome=true process থেকে /home এবং /root আড়াল করে। এখানে এটি নিরাপদ, কারণ service যে সবকিছু ব্যবহার করে সেগুলো /var/lib/dsh-এর অধীনে থাকে। Workspace-এর জন্য /home-এর অধীনে কোনো path ব্যবহার করলে agent জানাবে যে directory-টি বিদ্যমান নয়। এই line-টি মনে না থাকলে বিষয়টি বিভ্রান্তিকর মনে হতে পারে। ProtectSystem=full-এর ফলে /usr, /boot এবং /etc read-only হয়। Service-এর এগুলোতে লেখার প্রয়োজন নেই।

আরও কঠোর isolation ব্যবহার করা আকর্ষণীয় মনে হতে পারে, কিন্তু সাধারণত এটি ভুল। ProtectSystem=strict kernel pseudo-filesystem ছাড়া পুরো filesystem-কে read-only করে। ফলে প্রথম tool call কোনো file-এ লেখার চেষ্টা করলেই EROFS: read-only file system-এ ব্যর্থ হয়। এই স্তরের isolation চাইলে একই edit-এ ReadWritePaths=/var/lib/dsh যোগ করুন।

এখানে কোন Type= ব্যবহার করবেন

Type=exec, কারণ dsh foreground-এ থাকে এবং কখনো fork করে না। ডিফল্টের তুলনায় এর সুবিধা হলো, আপনি একটি প্রকৃত error message পান। Type=simple ব্যবহার করলে systemd process fork হওয়ার সঙ্গে সঙ্গে start সফল হয়েছে বলে ধরে নেয়। তখন binary আদৌ আছে কি না, তা systemd জানে না। ফলে systemctl start dsh সফলভাবে শেষ হয়, আর ব্যর্থতা শুধু journal-এ দেখা যায়। Type=exec ব্যবহার করলে systemd execve() সফল হওয়া পর্যন্ত অপেক্ষা করে। তাই ExecStart=-এ একটি typo থাকলে আপনি যে command লিখেছেন সেটিই ব্যর্থ হয়, এবং সেখানেই আপনি তা দেখতে পান।

ভুল দুটি উত্তরই আটকে থাকে। Type=forking systemd-কে একটি parent process শেষ হওয়া পর্যন্ত অপেক্ষা করতে বলে। dsh কখনো শেষ হয় না। তাই start আটকে থাকে, যতক্ষণ না TimeoutStartSec শেষ হয় (ডিফল্টভাবে 90 seconds), এবং এরপর Job for dsh.service failed because a timeout was exceeded. জানায়। Type=notify READY=1 message-এর জন্য sd_notify-এ অপেক্ষা করে। কোনো Node process এমন message না পাঠালে একইভাবে start আটকে যায়। systemd service type-এর পূর্ণ তুলনা-এ বাকি বিষয়গুলোও ব্যাখ্যা করা হয়েছে। এর মধ্যে কখন notify সেটআপ করার অতিরিক্ত কাজ করা যুক্তিযুক্ত, সেটিও রয়েছে।

যে restart rule ব্যর্থতা স্পষ্টভাবে জানায়

Restart=on-failure non-zero exit বা fatal signal-এর পরে restart হয় এবং clean exit হলে unit-টিকে অপরিবর্তিত রাখে। Preview build-এর জন্য এটাই প্রত্যাশিত আচরণ। dsh যদি অপছন্দের configuration পড়ে কোনোভাবে 0 exit করে, unit থেমে যায় এবং stopped অবস্থায় থাকে। systemctl status dsh-এ inactive (dead) দেখা যায়, যেখানে এই তথ্য পরীক্ষা করতে পারবেন। Restart=always একই ঘটনাকে এমন একটি restart loop-এ পরিণত করে, যা দূর থেকে স্বাভাবিক মনে হয়।

Rate limit অংশটি অনেকে বাদ দেন। systemd-এর default হলো দশ সেকেন্ডের মধ্যে পাঁচটি start। RestartSec=5s থাকলে দশ সেকেন্ডের একটি window-তে পাঁচটি start কখনো পূর্ণ হয় না। তাই startup-এর সময় crash করা unit অনন্তকাল restart হতে থাকে, আর বিষয়টি শুধু journal-এ দেখা যায়। StartLimitIntervalSec=300-এর সঙ্গে StartLimitBurst=5 ব্যবহার করলে পাঁচ মিনিটে পাঁচটি failure-ই যথেষ্ট। systemd এরপর হাল ছেড়ে unit-টিকে failed অবস্থায় রেখে দেয় এবং Start request repeated too quickly. log করে। কারণ ঠিক করার পরে sudo systemctl reset-failed dsh দিয়ে ওই state পরিষ্কার করুন। উভয় setting [Unit]-এ থাকতে হবে, [Service]-এ নয়। ভুল section-এ থাকলে systemd এগুলো নীরবে উপেক্ষা করে।

চালু করুন, তারপর পরীক্ষা করুন

sudo systemctl daemon-reload
sudo systemctl enable --now dsh
systemctl status dsh

enable --now দুটি কাজ করে। enable reboot-এর পরে service আবার চালু করে, আর --now বর্তমান boot-এ service চালু করে। শুধু systemctl start চালালে পরবর্তী reboot-এর পরে তা আর কার্যকর থাকে না, আর kernel update-এর জন্য reboot প্রয়োজন হয়।

systemctl status dsh-এর আউটপুটে Active: active (running), একটি Main PID এবং একটি Memory: লাইন দেখা উচিত। এরপর service কোন address-এ listening করছে তা নিশ্চিত করুন:

sudo ss -lntp | grep 3080

আপনার 127.0.0.1:3080 দেখা উচিত। 0.0.0.0:3080 দেখা গেলে কোনো configuration bind address পরিবর্তন করেছে এবং আপনার agent public internet-এ listening করছে। ওই আউটপুটে process-এর নাম node, dsh নয়, কারণ dsh binary একটি Node script; তাই pgrep -x dsh কিছু খুঁজে পায় না। এর পরিবর্তে systemctl show -p MainPID dsh ব্যবহার করুন।

এরপর একবার reboot করুন। কোনো service reboot-এর পরে কখনো সচল না থাকলে, সেটিকে এখনো service বলা যায় না।

sudo reboot

আবার সংযোগ করে systemctl is-active dsh চালান। এটি active দেখায়।

journalctl দিয়ে লগ পড়া

dsh stdout এবং stderr-এ যা লিখে, সবই unit name-এর অধীনে journal-এ জমা হয়।

journalctl -u dsh -f
journalctl -u dsh -n 200 --no-pager
journalctl -u dsh --since "10 min ago" -p err

-f নতুন line অনুসরণ করে, -n সর্বশেষ Nটি line দেখায়, আর -p err priority অনুযায়ী filter করে। unit-এ SyslogIdentifier=dsh থাকার কারণে ওই line-গুলো dsh হিসেবে tag হয়, node হিসেবে নয়। unit দিয়ে filter না করা journal output প্রথমবার পড়ার সময় এই পার্থক্যটি গুরুত্বপূর্ণ।

প্রয়োজন হওয়ার আগেই পরীক্ষা করুন যে reboot-এর পরেও journal সংরক্ষিত থাকে:

journalctl -u dsh -b -1

যদি এটি Specifying boot ID or boot offset has no effect, no persistent journal was found দেখায়, journal /run-এ থাকে এবং প্রতিটি reboot-এর সময় মুছে যায়। directory তৈরি করে daemon restart করুন:

sudo mkdir -p /var/log/journal
sudo systemctl restart systemd-journald

SSH tunnel ব্যবহার করে UI-তে প্রবেশ করুন, public port ব্যবহার করবেন না

dsh 127.0.0.1:3080-এ web UI (user interface) চালায় এবং অন্য কোনো জায়গায় এটি পরিবেশন করতে অস্বীকার করে। --host 0.0.0.0 চাইলে এটি নিচের বার্তা দিয়ে বন্ধ হয়ে যায়:

error: --host 0.0.0.0 is intentionally not supported yet for safety: it would expose remote code execution to the network; use 127.0.0.1 instead

এটি পাশ কাটানোর মতো কোনো সীমাবদ্ধতা নয়। web API (application programming interface) agent-কে পরিচালনা করে, আর agent shell command চালায়। তাই যে কেউ port-টি খুঁজে পেলে সেটি আপনার VPS-এ shell access পাওয়ার সমতুল্য। Maintainer-রা remote authentication এখনো তৈরি না থাকাকেই bind loopback-এ স্থির রাখার কারণ হিসেবে উল্লেখ করেছেন। আপনার নিজের machine থেকে port forward করুন:

ssh -N -L 3080:127.0.0.1:3080 you@203.0.113.10

-L 3080:127.0.0.1:3080 আপনার laptop-এ port 3080 খোলে এবং সেখানে আসা সবকিছু 127.0.0.1:3080-এ পাঠায়, যা VPS-এ resolve করা হয়। -N-এর অর্থ হলো কোনো remote command চালানো হবে না। তাই session-টি শুধু tunnel খোলা রাখে। এটি চালু রাখুন এবং browser-এ http://127.0.0.1:3080/ খুলুন। DeepSeek API key Settings, তারপর Models-এর অধীনে এখানে প্রবেশ করাবেন। workspace directory-ও এখানে নির্বাচন করবেন। workspace-কে /var/lib/dsh/workspace-এ নির্ধারণ করুন। এটি সেই directory, যার মালিক service user। তা না হলে agent-এর file tools EACCES: permission denied-সহ ব্যর্থ হবে।

আপনার laptop-এ port 3080 ব্যস্ত থাকলে ssh তা জানায়:

bind [127.0.0.1]:3080: Address already in use
channel_setup_fwd_listener_tcpip: cannot listen to port: 3080

ssh -N -L 3081:127.0.0.1:3080 you@203.0.113.10 ব্যবহার করে ভিন্ন local port বেছে নিন। তারপর http://127.0.0.1:3081/-এ যান। নিজের machine-এ ~/.ssh/config-এ এই command-টি সংরক্ষণ করুন:

Host dsh-vps
  HostName 203.0.113.10
  User you
  LocalForward 3080 127.0.0.1:3080

এরপর ssh -N dsh-vps-ই সম্পূর্ণ command। এখন এই tunnel-ই আপনার agent-এ প্রবেশের একমাত্র পথ। তাই এটিকে সুরক্ষিত রাখার দায়িত্ব SSH daemon-এর: শুধু key ব্যবহার করুন, password authentication বন্ধ রাখুন, এবং আপনার VPS-এ SSH hardening-এর বাকি নির্দেশনাগুলো এখানে আরও কঠোরভাবে প্রয়োগ করুন।

key-টি unit file-এ রাখা যাবে না। Environment= value systemctl show dsh -p Environment দ্বারা প্রদর্শিত হয়, যা box-এর যেকোনো user চালাতে পারে। আপনার ইনস্টল করা কোনো plugin-এর environment-এ key প্রয়োজন হলে সেটি /etc/dsh.env-এ রাখুন। file-টির mode 600 নির্ধারণ করুন এবং মালিক root রাখুন। এরপর EnvironmentFile=/etc/dsh.env দিয়ে সেটি reference করুন। systemd exec সময় root হিসেবে file-টি পড়ে, আর systemctl show এর contents প্রদর্শন করে না।

চালানোর খরচ

Inference DeepSeek-এর API-তে হয়, আপনার VPS-এ নয়। আপনার সার্ভারের খরচ হয় Node process, এটি যে UI পরিবেশন করে, এবং agent যে প্রতিটি command চালানোর সিদ্ধান্ত নেয় সেগুলোর জন্য। প্রথম দুটি খরচ স্থির এবং কম। তৃতীয়টির ওপর এই unit file কোনো সীমা নির্ধারণ করে না।

অন্য কারও দেওয়া হিসাবের ওপর নির্ভর না করে নিজের সার্ভারে ন্যূনতম খরচ মাপুন:

systemctl show dsh -p MemoryCurrent
systemd-cgtop -1 --depth 2

MemoryCurrent bytes-এ মান দেখায়। agent কাজ করার সময় এটি monitor করুন, idle অবস্থায় নয়।

Tool call-গুলো service-এর child process হিসেবে চলে। তাই সেগুলো একই control group-এ থাকে এবং একই limit-এর বিপরীতে গণনা হয়। কোনো agent workspace-এর ভেতরে npm install বা একটি test suite চালালে harness-এর তুলনায় অনেক বেশি memory ব্যবহার করতে পারে। 1 GB VPS-এ সাধারণত এখানেই সমস্যা হয়: kernel একটি process বেছে নিয়ে সেটি kill করে, আর journalctl -k | grep -i "out of memory"-এ Out of memory: Killed process line দেখা যায়, যেখানে বেছে নেওয়া process-এর নাম থাকে। সমস্যা সৃষ্টি করা process-টি প্রায়ই সেটি হয় না।

সমাধান হলো ইচ্ছাকৃতভাবে একটি limit নির্ধারণ করা। [Service] section-এ MemoryMax= এবং CPUQuota= unit-এর ভেতরে ক্ষতি সীমাবদ্ধ রাখে। ফলে পুরো সার্ভার lock up না করে runaway build kill হয়। সংখ্যাগুলো এবং failure behavior সম্পর্কে systemd দিয়ে memory ও CPU সীমাবদ্ধ করা দেখুন। DSH_HOME-এর অধীনে session history এবং workspace-এ agent-এর লেখা ফাইল থেকেও disk usage বাড়ে। তাই disk monitor করার জন্য আপনি যে পদ্ধতি ইতিমধ্যে ব্যবহার করেন, সেখানে du -sh /var/lib/dsh যুক্ত করুন।

আপনি যদি এমন একটি interactive agent চান, যার সঙ্গে attach এবং detach করা যায়, তাহলে service উপযুক্ত পদ্ধতি নয়। সে ক্ষেত্রে persistent tmux session-এ agent চালানো বেশি উপযোগী। agent সবসময় চালু রাখতে এবং tunnel-এর মাধ্যমে reachable করতে চাইলে dsh-কে unit হিসেবে চালান।

ব্যর্থতার ধরন এবং যে বার্তাগুলো আপনি দেখতে পাবেন

status=203/EXEC systemd ফাইলটি চালাতে পারেনি এবং লগে Failed to locate executable /usr/local/bin/dsh: No such file or directory দেখা গেছে। ExecStart=-এর path, command -v dsh যা দেখিয়েছে তার সঙ্গে মেলে না। এটি সেই ব্যর্থতা, যা Type=exec systemctl start সময়ে জানায়; এটি গোপন করে না।

status=217/USER User=-এ থাকা account-টি বিদ্যমান নয়। id dsh দিয়ে নিশ্চিত করুন।

status=200/CHDIR WorkingDirectory= অনুপস্থিত, অথবা service user সেখানে প্রবেশ করতে পারে না। sudo -u dsh ls /var/lib/dsh/workspace সরাসরি একই সমস্যা পুনরায় তৈরি করে।

Error: listen EADDRINUSE: address already in use 127.0.0.1:3080 অন্য কিছু ইতিমধ্যে port-টি দখল করে রেখেছে। সাধারণত অন্য terminal-এ খোলা থাকা npx run-এর কারণে এটি ঘটে। sudo ss -lntp | grep 3080 process-টির নাম দেখায়।

EACCES: permission denied-এর পরে একটি path। /var/lib/dsh-এর অধীনে ownership ভুল। সাধারণত প্রথমবার root হিসেবে বা ভুল HOME দিয়ে চালানোর কারণে এটি ঘটে। sudo chown -R dsh:dsh /var/lib/dsh এটি ঠিক করে।

Start request repeated too quickly. unit start rate limit-এ পৌঁছে থেমে গেছে। প্রকৃত error তার আগের লাইনগুলোতে আছে। আবার চেষ্টা করার আগে sudo systemctl reset-failed dsh চালান।

Unit হলো active (running), কিন্তু browser-এ কিছু দেখা যাচ্ছে না। VPS-এ পরীক্ষা চালান। সেখানে curl -fsS http://127.0.0.1:3080/ -o /dev/null && echo up যদি up দেখায়, তাহলে service সচল আছে এবং সমস্যা port forward-এ।

ইচ্ছাকৃতভাবে আপগ্রেড করা

Pinning-এর অর্থ হলো আপগ্রেড আপনার নিয়ন্ত্রণে করা হয়; এটি নিজে থেকে ঘটে না। প্রথমে release notes পড়ুন, কারণ compatibility নষ্ট করতে পারে এমন পরিবর্তন সম্পর্কে upstream-এর সতর্কবার্তাই pin করার মূল কারণ। state directory-এর backup নিন। এরপর version পরিবর্তন করুন:

sudo systemctl stop dsh
sudo tar czf /root/dsh-home-$(date +%F).tgz -C /var/lib/dsh harness
sudo npm install -g @deepseek-ai/dsh@0.1.0-rc.7
sudo systemctl start dsh
journalctl -u dsh -n 50 --no-pager

Rollback একই npm install -g পদ্ধতিতে পুরনো version-এ ফিরে যাওয়া। এর সঙ্গে সেই tarball পুনরুদ্ধার করতে হবে। তবে tarball আগে সংরক্ষণ করে থাকলেই এটি কাজ করবে। Preview-stage agent runtime এমন software, যার আপগ্রেড আপনার অজান্তে config format নতুনভাবে লিখে দিতে পারে।

FAQ

dsh বন্ধ করলে আমার SSH session কেন বন্ধ হয়ে যায়?

কারণ npx @deepseek-ai/dsh web আপনার login session-এর মালিকানাধীন একটি foreground process। তাই session শেষ হলে এটিও বন্ধ হয়ে যায়। অন্যদিকে systemd unit-এর মালিক init system। এ কারণে disconnect করার পরও এটি চলতে থাকে এবং reboot-এর পর আবার শুরু হয়। sudo systemctl enable --now dsh হলো এমন দুটি ধাপের সমষ্টি, যা আপনাকে দুটিই দেয়: reboot-এর জন্য enable এবং এই boot-এর জন্য --now

dsh-এর জন্য কি Type=simple নাকি Type=exec ব্যবহার করা উচিত?

Type=exec। dsh foreground-এ চলে এবং কখনও fork করে না, তাই দুটিই কাজ করে। তবে Type=exec systemd-কে execve() সফল হওয়া পর্যন্ত অপেক্ষা করায়, তারপর start সফল বলে গণ্য করে। ফলে ExecStart=-এ ভুল path থাকলে systemctl start আপনার সামনে status=203/EXEC দেখিয়ে ব্যর্থ হয়। Type=simple ব্যবহার করলে একই ভুল success ফেরত দেয় এবং journal-এ আড়ালে থেকে যায়। এখানে Type=forking এবং Type=notify দুটিই ভুল, এবং TimeoutStartSec 90 seconds পরে expire না হওয়া পর্যন্ত দুটিই আটকে থাকে।

আমার laptop থেকে dsh web UI কীভাবে খুলব?

SSH-এর মাধ্যমে port forward করুন: ssh -N -L 3080:127.0.0.1:3080 you@your-vps। এরপর browser-এ http://127.0.0.1:3080/ খুলুন। Service-টিকে public address-এ bind করার চেষ্টা করবেন না। dsh --host 0.0.0.0-কে error: --host 0.0.0.0 is intentionally not supported yet for safety: it would expose remote code execution to the network; use 127.0.0.1 instead দিয়ে প্রত্যাখ্যান করে, কারণ web API agent-কে shell command চালাতে পারে এবং এর সামনে কোনো remote authentication নেই।

Permission সহজ রাখতে কি dsh-কে root হিসেবে চালাতে পারি?

না। এই harness command চালানো এবং file লেখার জন্য ব্যবহৃত হয়। তাই service-এর যত privilege থাকে, agent-এরও তত privilege থাকে। useradd --system --shell /usr/sbin/nologin dsh দিয়ে একটি system account তৈরি করুন, সেটি দিয়ে /var/lib/dsh-এর মালিকানা নিন, এবং unit-এ NoNewPrivileges=true যোগ করুন। এরপর EACCES: permission denied দেখা দিলে সাধারণত কারণটি হলো আগে root হিসেবে চালানোর ফলে root-owned file রেখে যাওয়া। sudo chown -R dsh:dsh /var/lib/dsh এটি পরিষ্কার করে।

Unit-এ dsh-এর কোন version pin করা উচিত?

Service সেটআপ করার সময় npm view @deepseek-ai/dsh version যে version report করে, সেটিই ব্যবহার করুন। এটি npm install -g @deepseek-ai/dsh@<that version> দিয়ে install করুন এবং এমন জায়গায় record করুন যেখানে পরে খুঁজে পাবেন। 18 August 2026-এ 0.1.0-rc.7 বর্তমান ছিল। এখানে মূল বিষয় number নয়। বিষয়টি হলো, version ছাড়া npx start time-এ package resolve করে। ফলে unattended restart নীরবে আপনাকে ভিন্ন config format-যুক্ত build-এ নিয়ে যেতে পারে।