SSD Nodes Learn Hosting plans →
নির্দেশিকা Matt Connorদ্বারা Matt Connor

SSH বিচ্ছিন্ন হলেও tmux-এ Claude Code চালান VPS-এ

ল্যাপটপের ঢাকনা বন্ধ বা SSH বিচ্ছিন্ন হলেও Claude Code চালু রাখুন। Linux VPS-এ tmux ইনস্টল, নিরাপত্তা শক্ত করা এবং SIGHUP-জনিত ব্যর্থতা সামলানোর বাস্তব নির্দেশনা।

সমস্যাটি CLI নয়, ল্যাপটপের ঢাকনা

ল্যাপটপে Claude Code ঠিকমতো চলে, যতক্ষণ না আপনি ঢাকনা বন্ধ করেন। তখন SSH session বিচ্ছিন্ন হয়, shell একটি SIGHUP পায়, এবং test run শুরুর তিন মিনিট পর agent-ও বন্ধ হয়ে যায়। এমন একটি মেশিনে CLI চালান, যেটি কখনও sleep mode-এ যায় না। এটি এমন একটি terminal multiplexer-এর ভিতরে চালান, যার process-গুলো আপনার SSH session-এর child process নয়। পুরো কৌশল এটুকুই। এখানে install-এর চেয়ে tmux বেশি গুরুত্বপূর্ণ।

এই পৃষ্ঠায় এমন একটি box পরিচালনার পদ্ধতি দেখানো হয়েছে, যেখানে agent চালু রেখে দেওয়া হবে। চালু অবস্থায় রেখে দেওয়া যায়—এমন কোনো Linux server না থাকলে এর কোনো অংশই প্রযোজ্য নয়। এটিই একমাত্র বাস্তব prerequisite।

tmux আসলে কী করে

আপনি SSH-এ সংযোগ করলে, sshd একটি shell fork করে এবং সেটিকে একটি pseudo-terminal দেয়; ওই shell থেকে চালু করা সবকিছু তার child process হয়। সংযোগ বিচ্ছিন্ন হলে kernel সেই pty সরিয়ে দেয়, shell SIGHUP পায়, এবং পরপর তার child process-গুলোকেও hangup signal পাঠায়। Foreground-এ চলমান দীর্ঘস্থায়ী process বন্ধ হয়ে যায়।

tmux এই ownership কাঠামো উল্টে দেয়। আপনি যে tmux command টাইপ করেন, সেটি একটি thin client; এটি unix socket-এর মাধ্যমে আপনার terminal থেকে detached অবস্থায় চলা একটি tmux server-এর সঙ্গে যোগাযোগ করে। একটি session-এর ভেতরের shell-গুলো sshd-এর নয়, ওই server-এর child process। SSH connection বন্ধ করলে client চলে যায়, কিন্তু server, session এবং কাজরত agent চলতে থাকে। আবার সংযোগ করে tmux attach চালালে আপনি একই shell-এ ফিরে যান এবং আগের scrollback-ও থাকে। nohup hangup-এর পরেও চলতে পারে, কিন্তু এতে ফিরে আসার কোনো উপায় নেই; background-এ পাঠানো TUI-তে আপনি আবার attach করতে পারবেন না। Claude Code interactive; তাই tmux (অথবা screen) সঠিক tool।

সার্ভারের আকার নির্ধারণ

CLI নিজে একটি একক নেটিভ বাইনারি; এটি মেশিন পূর্ণ করে না। মেশিন পূর্ণ হয় আপনার হয়ে এজেন্ট যা কিছু চালায় তা দিয়ে: একটি বিল্ড, একটি পূর্ণাঙ্গ টেস্ট স্যুট, tsc, একটি ল্যাঙ্গুয়েজ সার্ভার, অথবা Docker-এ চলমান কোনো ডেটাবেস। তাই CLI-এর জন্য নয়, বরং টুলচেইনের জন্য আকার নির্ধারণ করুন। swap যোগ করুন, এমনকি যদি আপনি এটি ব্যবহার করার পরিকল্পনা না-ও করেন; এটি একটি হার্ড OOM kill-কে ধীরগতির বিল্ডে রূপান্তরিত করে।

sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

ডিস্কের দিকেও নজর রাখুন: রিপোজিটরি, node_modules এবং Docker ইমেজ দ্রুত জায়গা দখল করে। আর যদি টুলচেইন কন্টেইনার ছাড়িয়ে পূর্ণাঙ্গ ভার্চুয়াল মেশিন, KVM গেস্ট বা লোকাল Kubernetes নোড পর্যন্ত বিস্তৃত হয়, তবে নিশ্চিত করুন যে আপনার পরিকল্পনা অনুযায়ী CPU ভার্চুয়ালাইজেশন এক্সটেনশনগুলো সক্রিয় আছে। কারণ VPS-এ নেস্টেড ভার্চুয়ালাইজেশন চালানো এমন একটি বিষয় যা আপনার প্রোভাইডারকে সক্রিয় করে দিতে হয়, এটি গেস্টের ভেতর থেকে চালু করা সম্ভব নয়।

প্রথমে root-বহির্ভূত একজন ব্যবহারকারী

নিজস্ব home-সহ একটি dedicated user তৈরি করুন এবং তার public key সঠিক স্থানে রাখুন:

sudo adduser --disabled-password --gecos "" agent
sudo install -d -m 700 -o agent -g agent /home/agent/.ssh
sudo cp ~/.ssh/authorized_keys /home/agent/.ssh/authorized_keys
sudo chown agent:agent /home/agent/.ssh/authorized_keys
sudo chmod 600 /home/agent/.ssh/authorized_keys

আর কোনো কাজ করার আগে দ্বিতীয় terminal থেকে login পরীক্ষা করুন। তখনও fallback হিসেবে password authentication চালু থাকবে। যদি publickey দিয়ে Permission denied বার্তা আসে, তাহলে সাধারণত key-এর সমস্যা নয়; ওই .ssh directory-র ownership বা mode-এ সমস্যা থাকে।

ইচ্ছাকৃতভাবে, agent sudo group-এর সদস্য নয়। কোনো system package প্রয়োজন হলে আপনি সেটি install করবেন। এই এক সিদ্ধান্তের ফলে ভুল করে চালানো shell command-এর মাধ্যমে host নষ্ট হওয়ার সম্ভাবনার অধিকাংশই দূর হয়।

চালু রাখা সার্ভারের জন্য SSH hygiene

সারাদিন public Internet-এ থাকা কোনো মেশিনে password authentication চালু রাখা নিরাপদ নয়, বিশেষ করে সেখানে agent ও আপনার source code থাকলে। এটি বন্ধ করুন। Ubuntu 24.04 এবং Debian 13-এ /etc/ssh/sshd_config-এর মধ্যে /etc/ssh/sshd_config.d/*.conf অন্তর্ভুক্ত থাকে। তাই মূল configuration সম্পাদনা না করে একটি ফাইল যোগ করুন:

# /etc/ssh/sshd_config.d/10-hardening.conf
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin no

নির্দিষ্ট কারণ না থাকলে key exchange ওই ফাইলে রাখবেন না: পুরোনো hardening guide থেকে কপি করা একটি KexAlgorithms line প্রায়ই শুধু classical algorithm নির্ধারণ করে দেয়। এর ফলে সাম্প্রতিক ssh client সংযোগে post-quantum key exchange ব্যবহৃত হচ্ছে না—এমন warning দেখাতে পারে।

Validation করে reload করুন। পরীক্ষা করার সময় বর্তমান session খোলা রাখুন এবং দ্বিতীয় terminal থেকে একটি নতুন session দিয়ে পরীক্ষা করুন:

sudo sshd -t && sudo systemctl restart ssh

Ubuntu 24.04-এ একটি বিষয় মনে রাখুন: sshd socket-activated। Authentication settings systemctl restart ssh-এ প্রয়োগ হয়। তবে listening Port পরিবর্তন করলে systemctl daemon-reload এবং ssh.socket restart করাও প্রয়োজন।

এরপর firewall configuration করুন। এটি enable করার আগে SSH অনুমোদন করুন। তা না হলে আপনি নিজেকেই system থেকে বিচ্ছিন্ন করে ফেলবেন:

sudo ufw allow OpenSSH
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw enable

fail2ban install করার আগে এটি কী সুবিধা দেয় তা পরিষ্কারভাবে বুঝে নিন: password authentication বন্ধ থাকলে brute-force আক্রমণ এমনিতেই সফল হতে পারে না। এটি শুধু ব্যর্থ প্রচেষ্টাগুলো journal-এ জমা হওয়া থেকে বিরত রাখে।

# /etc/fail2ban/jail.local
[sshd]
enabled = true
backend = systemd
maxretry = 5
bantime = 1h

সবশেষে sudo apt install unattended-upgrades এবং sudo dpkg-reconfigure -plow unattended-upgrades ব্যবহার করে স্বয়ংক্রিয়ভাবে patch করুন। tmux-এর সঙ্গে এর পারস্পরিক প্রভাব মনে রাখুন: Unattended-Upgrade::Automatic-Reboot চালু করলে kernel update-এর পরে system reboot হয় এবং এর সঙ্গে সব session বন্ধ হয়ে যায়। এটি বন্ধ রাখলে নিজের সময়সূচি অনুযায়ী reboot করতে পারবেন, যখন কোনো কাজ মাঝপথে চলবে না। একই সতর্কতা release upgrade-এর ক্ষেত্রেও প্রযোজ্য: Ubuntu 24.04 থেকে 26.04-এ system সরানো হলে sshd এবং kernel restart হয়। তাই এমন maintenance window বেছে নিন, যখন কোনো tmux session-এ গুরুত্বপূর্ণ কাজ চলমান নেই।

Ubuntu-তে Node.js এবং Claude Code ইনস্টল করা

npm রুট ব্যবহার করার জন্য Node.js 22 বা তার পরবর্তী সংস্করণ প্রয়োজন। (প্যাকেজটি এখন একটি নেটিভ বাইনারি নিয়ে আসে যা Node-এ চলে না, তবে npm এখনও ইঞ্জিনের সংস্করণ পরীক্ষা করে এবং এজেন্টের নিজস্ব টুলচেইনের জন্য সাধারণত একটি বর্তমান Node সংস্করণ প্রয়োজন হয়।) ডিস্ট্রো প্যাকেজগুলো প্রায়ই পিছিয়ে থাকে; Ubuntu এবং Debian-এ NodeSource সাধারণত ব্যবহৃত হয় এবং এটি একটি সাইন করা রিপো প্রদান করে (কোনো apt-key নেই, যা Ubuntu 24.04-এ ডেপ্রিকেটেড এবং Debian 13 থেকে ইতিমধ্যে সরিয়ে ফেলা হয়েছে):

curl -fsSL https://deb.nodesource.com/setup_24.x | sudo -E bash -
sudo apt install -y nodejs
node --version

এখন সেই অংশটি যা মানুষ ভুল করে: CLI-কে আপনার agent ব্যবহারকারী হিসেবে ইনস্টল করুন, কখনোই sudo npm -g দিয়ে নয়। রুট-মালিকানাধীন গ্লোবাল প্রিফিক্স পরবর্তীতে পারমিশন ত্রুটি তৈরি করে এবং npm ক্যাশে রুট-মালিকানাধীন ফাইল রেখে দেয়। প্রথমে npm-এর প্রিফিক্স ব্যবহারকারীর হোম ডিরেক্টরিতে নির্দেশ করুন:

mkdir -p ~/.npm-global
npm config set prefix ~/.npm-global
echo 'export PATH="$HOME/.npm-global/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
npm install -g @anthropic-ai/claude-code
claude --version

এই এক্সপোর্টটি ~/.bashrc-এ রাখতে হবে এবং এটি ফাইলের উপরের দিকে "If not running interactively, don't do anything" গার্ডের উপরে থাকা উচিত। একটি ডিফল্ট tmux প্যান একটি লগইন শেল হিসেবে চলে: tmux default-command-কে খালি রাখে, যা এটিকে একটি লগইন শেল হিসেবে default-shell শুরু করতে বলে এবং একটি লগইন bash ~/.profile পড়ে, যা Ubuntu-তে ~/.bashrc সোর্স করে। নন-লগইন শেলগুলো, উদাহরণস্বরূপ যদি আপনি নিজে default-command সেট করেন, সরাসরি ~/.bashrc পড়ে। তাই ~/.bashrc উভয় ক্ষেত্রেই কাজ করে, যেখানে শুধুমাত্র ~/.profile দ্বিতীয় ক্ষেত্রটি মিস করবে। একটি বিষয় খেয়াল রাখবেন: bash ~/.profile এড়িয়ে যায় যদি ~/.bash_profile বা ~/.bash_login বিদ্যমান থাকে, তাই যদি আপনি এমন কোনো ফাইল তৈরি করে থাকেন, তবে সেটিতেও ~/.bashrc সোর্স করুন। nvm-এর মতো ভার্সন ম্যানেজার ব্যবহার করে প্রতি-ব্যবহারকারী Node ইনস্টল করলেও একই ফলাফল পাওয়া যায়; উভয় ক্ষেত্রেই লক্ষ্য হলো যেন npm install -g-এর কখনোই sudo-এর প্রয়োজন না হয়। npm ঠিকঠাক কাজ করে, তবে Anthropic-এর ডকুমেন্টেশনে নেটিভ ইনস্টল স্ক্রিপ্টকে প্রস্তাবিত উপায় হিসেবে উল্লেখ করা হয়েছে এবং সাইন করা apt, dnf ও apk রিপোজিটরিগুলো অন্য একটি বিকল্প। পেস্ট করার আগে Anthropic-এর ইনস্টল ডকুমেন্টেশন চেক করুন, কারণ ইনস্টল পদ্ধতি পরিবর্তিত হতে পারে।

এটি শুরু করতে একটি রিপোর ভেতরে claude চালান। প্রথমবার চালানোর সময় এটি আপনাকে অথেন্টিকেশনের ধাপগুলো দেখাবে; একটি হেডলেস বক্সে ব্রাউজার থাকে না, তাই এই প্রক্রিয়ায় আপনাকে একটি URL দেওয়া হবে যা আপনার নিজের মেশিনে খুলতে হবে এবং একটি কোড টার্মিনালে নিয়ে আসতে হবে। (এনভায়রনমেন্টে একটি API key ব্যবহার করা অন্য একটি উপায়।) যেভাবেই হোক, সেই ক্রেডেনশিয়াল এখন সার্ভারে থাকবে, যা আমাদের সেই অংশে নিয়ে আসে যা মানুষ এড়িয়ে যায়।

ব্লাস্ট রেডিয়াস বা প্রভাবের পরিধি নিয়ে আলোচনা

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

  • ডেডিকেটেড, আনপ্রিভিলেজড ইউজার: কোনো sudo গ্রুপ থাকবে না, আপনার নিজের অ্যাকাউন্টের সাথে কোনো হোম ডিরেক্টরি শেয়ার করা থাকবে না।
  • বক্সে কোনো প্রোডাকশন ক্রেডেনশিয়াল রাখবেন না: কোনো ~/.aws/credentials-এ প্রোডাকশন কি (key) রাখবেন না, প্রোডাকশন থেকে কোনো .env কপি করবেন না, এবং গুরুত্বপূর্ণ কোনো কিছুতে রাইট অ্যাক্সেস আছে এমন ডেটাবেস পাসওয়ার্ড ব্যবহার করবেন না। এজেন্টকে শুধুমাত্র স্টেজিং বা রিড-অনলি ক্রেডেনশিয়াল দিন।
  • স্কোপড টোকেন: একটি নির্দিষ্ট রিপোজিটরিতে সীমাবদ্ধ ফাইন-গ্রেইনড GitHub টোকেন ব্যবহার করুন; যখন শুধুমাত্র রিড অ্যাক্সেস যথেষ্ট, তখন deploy key ব্যবহার করুন।

Claude Code-এ --dangerously-skip-permissions নামে একটি ফ্ল্যাগ আছে, যা এর প্রায় সব পারমিশন প্রম্পট এড়িয়ে যায়। ল্যাপটপে বা কোনো অস্থায়ী প্রজেক্টে এটি ব্যবহার করা আপনার ব্যক্তিগত সিদ্ধান্ত। কিন্তু টোকেন আছে এমন কোনো সার্ভারে এটি ব্যবহার করলে, ভুল নির্দেশ এবং git push --force-এর মধ্যে থাকা শেষ বাধাটিও সরে যায়। যে প্রম্পটগুলো আপনি এড়িয়ে যাচ্ছেন সেগুলো সব বা কিছুই নয়—এমন নয়। auto mode now the default starting mode (Claude Code v2.1.283 থেকে) আসার পর, আপনি যখন সার্ভারের সামনে নেই তখন কোন পারমিশন মোডে এটি থাকা উচিত তা জানা জরুরি। এই ফ্ল্যাগটি আসলে কী পরিবর্তন করে এবং বিল্ট-ইন স্যান্ডবক্স থেকে শুরু করে ডিসপোজেবল VPS পর্যন্ত কীভাবে একটি এজেন্টকে নিয়ন্ত্রণ করা যায়, তা running Claude Code safely on a server-এ বিস্তারিত আলোচনা করা হয়েছে।

Deploy key বনাম SSH agent forwarding

আপনার ল্যাপটপের কি (key) যাতে git ব্যবহার করতে পারে, সেজন্য ssh -A ব্যবহার করার প্রলোভন হতে পারে। এটি কী সুবিধা দেয় তা বুঝুন: এজেন্ট ফরওয়ার্ডিং আপনার লোকাল SSH এজেন্টের সকেটকে ওই বক্সে থাকা ব্যবহারকারীর অধীনে চলা প্রসেসগুলোর কাছে উন্মুক্ত করে দেয়। agent হিসেবে চলা যেকোনো কিছু, এমনকি এজেন্টও, আপনার কি-কে যেকোনো হোস্টের জন্য সাইন করতে বলতে পারে, যতক্ষণ আপনি কানেক্টেড আছেন। এটি "git-কে শুধু একটি রিপো পুল করতে দাও"-এর চেয়ে অনেক বেশি ক্ষমতা দেয়।

এর পরিবর্তে সার্ভারেই একটি কি (key) তৈরি করুন, সেটিকে প্রতি-রিপোজিটরি deploy key হিসেবে রেজিস্টার করুন (যদি এজেন্টের পুশ করার প্রয়োজন হয় তবেই রাইট অ্যাক্সেস দিন), এবং একটি git identity সেট করুন যাতে বক্স থেকে করা কমিটগুলো শনাক্ত করা যায়:

ssh-keygen -t ed25519 -C "agent deploy key" -f ~/.ssh/id_ed25519_repo
cat ~/.ssh/id_ed25519_repo.pub   # paste into the repo's Deploy Keys
git config --global user.name "Agent (build box)"
git config --global user.email "agent@example.com"

tmux workflow

এটি ইনস্টল করুন (sudo apt install tmux), তারপর একটি ন্যূনতম ~/.tmux.conf তৈরি করুন:

set -g mouse on
set -g history-limit 50000
set -g default-terminal "tmux-256color"

প্রতিদিনের ব্যবহারের জন্য চারটি command যথেষ্ট:

tmux new -A -s claude     # attach to session "claude", creating it if absent
# ...run `claude` inside it, work normally...
# Ctrl-b then d           -> detach; everything keeps running
tmux ls                   # list sessions
tmux attach -t claude     # reattach, from this machine or any other
tmux kill-session -t claude

tmux new -A -s claude মনে রাখার মতো প্রধান command। session থাকলে এটি সেটিতে সংযুক্ত হয়, আর না থাকলে session তৈরি করে। তাই দিনের কাজ শুরু করা এবং সংযোগ বিচ্ছিন্ন হওয়ার পরে কাজ চালিয়ে যাওয়া—দুই ক্ষেত্রেই একই command ব্যবহার করা যায়। এটিকে alias হিসেবে সেট করুন। session-এর মধ্যে Ctrl-b c নতুন window খোলে, Ctrl-b n এবং Ctrl-b p window পরিবর্তন করে, আর Ctrl-b [ copy mode চালু করে পিছনের output দেখার জন্য (q চাপলে বের হওয়া যায়)।

যে session কখনো বন্ধ করেন না, সেগুলো সম্পর্কে একটি বিষয় জানা দরকার: agent প্রতিটি turn-এ পুরো conversation আবার পাঠায়। তাই কোনো session এক সপ্তাহ চালু রেখে যাওয়ার আগে দীর্ঘস্থায়ী Claude Code session কোন কাজে তার token খরচ করে তা পড়ুন।

ব্যর্থতার ধরন

"আমার সেশন হারিয়ে গেছে।" tmux ls প্রিন্ট করে no server running on /tmp/tmux-1000/default। এর অর্থ প্রায় সবসময়ই এই যে, প্রসেসটি কখনোই tmux-এর ভেতরে ছিল না। আপনি SSH করেছেন, সরাসরি claude চালিয়েছেন এবং সংযোগ বিচ্ছিন্ন হওয়ার সাথে সাথে সেটি বন্ধ হয়ে গেছে। এটি পুনরুদ্ধার করার কোনো উপায় নেই। যে অভ্যাসটি এটি প্রতিরোধ করে: প্রতিবার লগইনের পর tmux new -A -s <project> হলো প্রথম কমান্ড।

পেইন (pane) ছোট হয়ে একটি ক্ষুদ্র বাক্সে পরিণত হয়। window-size অপশনটি নির্ধারণ করে কোন সংযুক্ত ক্লায়েন্ট সাইজ ঠিক করবে। tmux 3.1 (Ubuntu 24.04-এ 3.4 ভার্সন থাকে) থেকে ডিফল্ট হলো latest, অর্থাৎ যে ক্লায়েন্টে সবচেয়ে সাম্প্রতিক অ্যাক্টিভিটি হয়েছে। কিন্তু কোনো কনফিগারেশনে window-size smallest থাকলে সেটি সবচেয়ে ছোট সংযুক্ত ক্লায়েন্টের সাইজ অনুযায়ী নিজেকে মানিয়ে নেয়, ফলে অন্য কোনো মেশিন থেকে সংযুক্ত থাকা পুরনো ক্লায়েন্ট ডিসপ্লেটিকে সংকুচিত করে ফেলে। সংযুক্ত হওয়ার সময় অন্যদের জোরপূর্বক বিচ্ছিন্ন করতে ব্যবহার করুন: tmux attach -d -t claude।

বিল্ড করার সময় Killed প্রিন্ট হয়। একটি শব্দ, কোনো স্ট্যাক ট্রেস নেই। sudo dmesg -T | grep -i -E 'out of memory|killed process' দিয়ে নিশ্চিত হোন, কার্নেল OOM killer সবচেয়ে বড় প্রসেসটিকে বেছে নিয়েছে। Node-এর ক্ষেত্রে আপনি হয়তো এর পরিবর্তে FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory দেখতে পারেন। সমাধানের ক্রম: সোয়াপ (swap) যোগ করুন (উপরে দেখুন), টেস্ট এবং কম্পাইলারের প্যারালালিজম সীমিত করুন, NODE_OPTIONS=--max-old-space-size=... দিয়ে Node-এর হিপ (heap) বাড়ান, অথবা VPS-এর সাইজ বড় করুন। OOM killer বিল্ডের পরিবর্তে tmux server-কেও বেছে নিতে পারে, যার ফলে আপনার সেশনটি বন্ধ হয়ে যাবে; যদি systemd-oomd চলমান থাকে, তবে এটি একই প্রভাবে পুরো ইউজার স্লাইসকে বন্ধ করে দিতে পারে।

npm error code EACCES / permission denied, mkdir '/usr/lib/node_modules/...'। রুট-মালিকানাধীন প্রিফিক্সে গ্লোবাল ইন্সটল। উপরে উল্লিখিত ~/.npm-global প্রিফিক্স ব্যবহার করুন। যদি আপনি ইতিমধ্যে কোনো এক সময় sudo npm চালিয়ে থাকেন, তবে আপনি Your cache folder contains root-owned files দেখতে পারেন, এটি ঠিক করতে sudo chown -R $(id -u):$(id -g) ~/.npm ব্যবহার করুন।

claude: command not found, তবে মাঝে মাঝে। আপনার PATH এক্সপোর্টটি ~/.bashrc-এ "If not running interactively, don't do anything" গার্ডের নিচে থাকে, তাই নন-ইন্টারেক্টিভ শেলগুলো এটিকে এড়িয়ে যায়। এক্সপোর্টটিকে ওই গার্ডের উপরে সরিয়ে নিন এবং এটিকে ~/.bashrc-এ রাখুন: একটি ডিফল্ট tmux পেইন হলো লগইন শেল যা Ubuntu-এর ~/.profile-এর মাধ্যমে ~/.bashrc-এ পৌঁছায়, এবং যেকোনো নন-লগইন শেল সরাসরি ~/.bashrc পড়ে, তাই এই একটি ফাইল উভয় ক্ষেত্রেই কাজ করে।

সংযুক্ত হওয়ার পর রঙের অসামঞ্জস্যতা। একটি TERM অমিল, উপরের default-terminal লাইনটি এর সমাধান।

রিবুটের পর সেশন হারিয়ে যায়। এটি কোনো বাগ নয়: tmux সার্ভার একটি প্রসেস এবং রিবুট করলে এটি বন্ধ হয়ে যায়। uptime দেখুন।

বাড়ার সঙ্গে কী সমস্যা হয়

আরও বেশি project। প্রতিটি repo-এর জন্য একটি করে tmux session নিন এবং session-এর নাম repo-এর নামে রাখুন; tmux ls তখন আপনার dashboard হিসেবে কাজ করবে। নাম দেওয়ার এই নিয়ম না মানলে 0, 1, 2-এর মতো session তৈরি হবে। একসঙ্গে কয়েকটি session চললে সেগুলোকে আলাদা করে কাজ করাতে হবে না, কারণ একই box-এ একটি session অন্য session-এ message পাঠাতে পারে। দীর্ঘ refactor চালানো agent-কে দ্বিতীয় agent দিয়ে test চালাতে হলে এটি কার্যকর। Port-ও একইভাবে ছড়িয়ে পড়ে। ছয়টি repo যদি :3000 চায়, তখন হাতে port বরাদ্দ বন্ধ করে Docker Compose-এর অধীনে একাধিক app-এ hostname অনুযায়ী route করতে Traefik reverse proxy ব্যবহার করুন।

আরও বেশি মানুষ। tmux socket প্রতি user-এর জন্য আলাদা। তাই একই box-এ থাকা দুই developer নিজ নিজ tmux server পান এবং একে অপরের session দেখতে পারেন না। Shared socket ব্যবহার করে একটি session ভাগ করলে সবাই একই Unix user হিসেবে একই shell-এ input দেন। এর ফলে audit ও permission-সংক্রান্ত যে প্রভাব তৈরি হয়, তা মেনে নিতে হয়। আলাদা user ব্যবহার করাই সহজ এবং সঠিক সমাধান।

তদারকিবিহীন কাজ। tmux এমন interactive session-এর জন্য, যেখানে আপনি attach করেন। কোনো তদারকি ছাড়াই schedule অনুযায়ী চলা job-এর জন্য systemd unit ও timer ব্যবহার করুন। এতে logging, restart policy এবং boot-এর পর কাজ চালু থাকার সুবিধা স্বাভাবিকভাবেই পাওয়া যায়। cron-এর মতো job চালাতে tmux ব্যবহার করতে চাওয়া সাধারণত বোঝায় যে job-টিকে service হিসেবে চালানো উচিত।

আরও একটি বিষয়: agent যে dev server চালু করে, সেগুলো 127.0.0.1-এ bind করুন, 0.0.0.0-এ নয়। Port ufw-তে খুলে দেওয়ার পরিবর্তে SSH tunnel (ssh -L 3000:127.0.0.1:3000 agent@your-server) দিয়ে সেগুলোতে সংযোগ করুন। যখন প্রায় আধা ডজন port forward করছেন, অথবা একটি phone ও একটি laptop একই preview-তে একসঙ্গে access করতে চায়, তখন এর সামনে VPS-এ self-hosted WireGuard VPN বসান। Dev server-গুলো একটি private interface-এ bind থাকবে, আর ufw public interface থেকে আসা সবকিছু deny করতে থাকবে। Firewall তখনই সাহায্য করে, যখন আপনি এতে বারবার নতুন hole তৈরি করা বন্ধ করেন।

Claude Code একমাত্র বিকল্প নয়: VPS-এ coding AI agent চালানোর ক্ষেত্রে Aider এবং Goose-ও বিবেচনা করা যায়।

FAQ

Claude Code কি SSH connection বিচ্ছিন্ন হওয়ার পরও চলতে থাকে?

শুধু তখনই, যদি আপনি এটিকে tmux-এর ভিতরে শুরু করে থাকেন। SSH shell থেকে সরাসরি চালু করা process ওই shell-এর child এবং link বিচ্ছিন্ন হলে pty-এর সঙ্গে বন্ধ হয়ে যায়। tmux-এর ভিতরে shell-টি detached tmux server-এর অধীন থাকে। তাই agent কাজের মাঝেও চলতে থাকে এবং tmux attach আপনাকে একই scrollback-এ ফিরিয়ে দেয়। প্রতিটি login-এর পর tmux new -A -s <project>-কে প্রথম command করুন। তাহলে সমস্যাটি আর হবে না।

sudo npm install -g দিয়ে CLI install করা উচিত কি?

না। root-owned global prefix পরবর্তী install-এ EACCES error এবং npm cache-এ root-owned file তৈরি করে। npm-এর prefix ~/.npm-global-এ সেট করুন অথবা nvm-এর মতো একটি version manager ব্যবহার করুন। unprivileged agent user হিসেবে install করুন। এরপর ~/.bashrc থেকে PATH-এ ~/.npm-global/bin export করুন, interactive guard-এর উপরে। আগে একবার sudo npm চালিয়ে থাকলে sudo chown -R $(id -u):$(id -g) ~/.npm দিয়ে cache মেরামত করুন।

agent চলমান একটি box-এ ssh -A agent forwarding কি নিরাপদ?

এটি কাজটির প্রয়োজনের তুলনায় অনেক বেশি access দেয়। Forwarding আপনার local SSH agent-এর socket-টি ওই user হিসেবে চলা প্রতিটি process-এর কাছে উন্মুক্ত করে। ফলে box-এর যেকোনো process আপনার key ব্যবহার করে, আপনি সংযুক্ত থাকা পর্যন্ত, process-টি যেসব host-এ পৌঁছাতে পারে সেগুলোর জন্য signature চাইতে পারে। Server-এ একটি ed25519 key তৈরি করুন এবং সেটিকে প্রতি-repository deploy key হিসেবে register করুন। Agent-কে সত্যিই push করতে হলে তবেই write access দিন।

আমার build শুধু Killed print করে কেন?

Stack trace ছাড়া একটি মাত্র শব্দ দেখালে কারণটি kernel OOM killer হওয়ার সম্ভাবনা বেশি। sudo dmesg -T | grep -i -E 'out of memory|killed process' দিয়ে এটি নিশ্চিত করুন। Node থেকে এর পরিবর্তে JavaScript heap out of memory দেখতে পারেন। সমাধানগুলো ক্রমানুসারে প্রয়োগ করুন: একটি swapfile যোগ করুন, test ও compiler-এর parallelism সীমিত করুন, NODE_OPTIONS=--max-old-space-size=... বাড়ান, তারপর VPS-এর আকার বাড়ান। মনে রাখবেন, OOM killer build-এর পরিবর্তে tmux server-কে বেছে নিতে পারে। এতে আপনার পুরো session বন্ধ হয়ে যেতে পারে।

tmux নাকি systemd service?

যেসব interactive session-এ আপনি সংযুক্ত হন, দেখেন এবং command টাইপ করেন, সেগুলোর জন্য tmux উপযুক্ত। Agent session ঠিক এই ধরনের। নির্ধারিত সময়ে চলে এবং যাকে কেউ monitor করে না, এমন কাজ systemd unit ও timer-এর অধীনে থাকা উচিত। সেখানে logging, restart policy এবং boot-এর পর চালু থাকার সুবিধা স্বয়ংক্রিয়ভাবে পাওয়া যায়। cron-এর মতো কাজ চালাতে যদি tmux ব্যবহার করতে হয়, তাহলে সেটি আসলে একটি service হিসেবে চালানো উচিত।