EBSOFT HMS · cPanel Node.js

প্রথমবার Deploy করা
— ধাপে ধাপে

Vite + React frontend আর Express server (bundled হয়ে dist/server.cjs হিসেবে চলে) — এই গাইড অনুসরণ করে cPanel এর Node.js Selector দিয়ে প্রথমবার লাইভ করুন। নিচে একটা recurring সমস্যার সমাধানও দেওয়া আছে, যা msh.ebsoftbd.com ও hms.ebsoftbd.com দুটো app এই দেখা গিয়েছিল।

স্ট্যাক: Vite + Express হোস্টিং: cPanel Node.js Selector সার্ভার: LiteSpeed + Passenger
ধাপ ০১

Zip আপলোড ও Extract

cPanel File Manager দিয়ে project zip আপলোড করুন ~/msh.ebsoftbd.com ফোল্ডারে — যেখানে Application Root সেট করা আছে সেই একই জায়গায়। আপলোড শেষে zip ফাইলে right-click করে Extract করুন।

এই সার্ভারে Application Root আর Document Root একই ফোল্ডার — এই কারণে পরের ধাপগুলোয় কিছু নিয়ম একটু ভিন্ন হবে, যা এই গাইডের শেষে ব্যাখ্যা করা আছে।
ধাপ ০২

Terminal খুলে Virtualenv Activate করুন

cPanel Terminal খুলুন। Setup Node.js App পেজে আপনার app এর এন্ট্রিতে যে কমান্ডটা দেওয়া থাকে, সেটা কপি করে পেস্ট করুন — এটা সঠিক Node ভার্সন ও virtualenv লোড করে দেয়।

TERMINAL
source /home/ebsoftbd/nodevenv/msh.ebsoftbd.com/20/bin/activate && cd /home/ebsoftbd/msh.ebsoftbd.com
ধাপ ০৩

Dependencies Install করুন

--legacy-peer-deps ফ্ল্যাগটা দরকার, কারণ একটা test-only dependency (@firebase/rules-unit-testing) firebase v12 আশা করে যেখানে প্রজেক্ট firebase v11 ব্যবহার করে। এটা শুধু peer-dependency ওয়ার্নিং, production build-এ প্রভাব ফেলে না।

TERMINAL
npm install --legacy-peer-deps
ধাপ ০৪

Production Build চালান

একটা কমান্ডে দুটো কাজ হয়: Vite দিয়ে frontend বান্ডেল হয়, আর esbuild দিয়ে server.ts কম্পাইল হয়ে dist/server.cjs তৈরি হয় — এটাই প্রোডাকশনে চলবে।

TERMINAL
npm run build
ধাপ ০৫

Startup File নিশ্চিত করুন

cPanel → Setup Node.js App → আপনার app এ ক্লিক করুন। দুটো ফিল্ড চেক করুন:

SETUP NODE.JS APP
Application startup file  → dist/server.cjs
Application mode          → Production
ধাপ ০৬

SAVE করুন

SAVE বাটনে ক্লিক করুন — এমনকি কিছু পরিবর্তন না করলেও। এটা cPanel কে .htaccess ফাইলে সঠিক Passenger routing directive লিখে দিতে বাধ্য করে, যেটা ছাড়া Apache/LiteSpeed request গুলো Node app পর্যন্ত পাঠাতে পারে না।

ধাপ ০৭

RESTART করুন

একই পেজে RESTART বাটনে ক্লিক করুন। এটা Node process পুনরায় চালু করে নতুন build ও environment variables লোড করবে।

ধাপ ০৮

Live Site চেক করুন

ব্রাউজারে msh.ebsoftbd.com খুলে hard refresh করুন (Ctrl+Shift+R) — সাধারণ refresh এ পুরনো cache থেকে যেতে পারে। কোনো error দেখলে cPanel Node.js App পেজে Logs চেক করুন, বা browser এ F12 চেপে Console দেখুন।

⚠ COMMON ISSUE

সাইট লোড হচ্ছে না? — Blank Page + "application/octet-stream" Error

উপরের সব ধাপ ঠিকমতো করার পরও যদি সাইট blank দেখায় এবং browser console এ এই error আসে:

ধাপ ০৯

Console এ কী দেখাচ্ছে চেক করুন

F12 চেপে Console ট্যাবে গিয়ে দেখুন এরকম error আছে কিনা:

BROWSER CONSOLE
Failed to load module script: Expected a JavaScript-or-Wasm module script
but the server responded with a MIME type of "application/octet-stream"
এই error মানে browser /src/main.tsx ফাইলটা raw/অপরিবর্তিত অবস্থায় পাচ্ছে — অর্থাৎ built dist/index.html এর বদলে project root এর কাঁচা (dev) index.html সরাসরি সার্ভ হচ্ছে, Node app পর্যন্ত request পৌঁছাচ্ছেই না।
ধাপ ১০

.htaccess চেক করুন

Terminal এ গিয়ে (নিচে <domain> এর জায়গায় আপনার আসল domain বসান, যেমন hms.ebsoftbd.com বা msh.ebsoftbd.com):

TERMINAL
cat ~/<domain>/.htaccess
যদি ফাইলে শুধু SetEnv লাইনগুলো (environment variables) আর PHP handler ব্লক থাকে — কিন্তু PassengerAppRoot, PassengerStartupFile এই ধরনের লাইন না থাকে — সেটাই আসল সমস্যা। এই লাইন ছাড়া Apache/LiteSpeed কখনো request Node app এ পাঠাবে না, নিজে থেকেই static file সার্ভ করে দেবে।
ধাপ ১১

Passenger Directive রিজেনারেট করুন

cPanel → Setup Node.js App → আপনার app এ ক্লিক করুন। কিছু পরিবর্তন না করেও SAVE বাটনে ক্লিক করুন — এটা cPanel কে বাধ্য করবে .htaccess এ সঠিক Passenger ব্লক আবার লিখে দিতে:

.HTACCESS (expected after SAVE)
# DO NOT REMOVE. CLOUDLINUX PASSENGER CONFIGURATION BEGIN
PassengerAppRoot "/home/ebsoftbd/<domain>"
PassengerBaseURI "/"
PassengerNodejs "/home/ebsoftbd/nodevenv/<domain>/20/bin/node"
PassengerAppType node
PassengerStartupFile dist/server.cjs
# DO NOT REMOVE. CLOUDLINUX PASSENGER CONFIGURATION END
SAVE করার পরও না এলে app STOP করে আবার START করুন — cPanel তখন পুরো config আবার fresh সেটাপ করবে।
ধাপ ১২

Root এ Raw index.html থাকলে সরান

এই সার্ভারে Application Root ও Document Root একই ফোল্ডার হওয়ায়, যদি project root এ raw (dev-mode) index.html ফাইলটা থেকে যায়, তাহলে Passenger config ঠিক থাকলেও Apache সেই physical ফাইলটাই সরাসরি সার্ভ করে দেবে, কখনো dist/index.html পর্যন্ত পৌঁছাবে না। build হওয়ার পর সবসময় এটা সরিয়ে দিন:

TERMINAL
cd ~/<domain>
ls index.html 2>/dev/null && mv index.html index.source.html
পরের বার rebuild করার আগে mv index.source.html index.html দিয়ে আবার ফেরত আনতে হবে — নাহলে npm run build ফেল করবে (vite index.html খুঁজে পাবে না)।
ধাপ ১৩

Restart করে চেক করুন

cPanel → Setup Node.js App → RESTART। তারপর সাইট hard refresh করুন (Ctrl+Shift+R) — সাধারণ refresh এ পুরনো cache থেকে যেতে পারে।

◆ CSS ও PHP HANDLER

Static Asset (CSS) ও PHP Handler নিয়ে জেনে রাখা ভালো

এই দুটো সরাসরি "সমস্যা" না, কিন্তু বিভ্রান্তি তৈরি করতে পারে — তাই আলাদা করে ব্যাখ্যা করা হলো।

ধাপ ১৪

Build এর পর CSS/Styling মিসিং দেখাচ্ছে

Site লোড হচ্ছে, JS ও কাজ করছে, কিন্তু পুরো পেজ unstyled/plain HTML এর মতো দেখাচ্ছে। Vite প্রতিটা build এ CSS/JS ফাইলের নামে নতুন hash যোগ করে (যেমন index-8P2N.css → index-Qk91.css), তাই এটা সাধারণত দুটো কারণে হয়:

CHECK
ls -la dist/assets/*.css
grep -o 'assets/index-[a-zA-Z0-9]*\.css' dist/index.html

দুটো কমান্ডের আউটপুটে ফাইলের নাম (hash সহ) মিলছে কিনা দেখুন। না মিললে বুঝবেন পুরোনো build এখনো সার্ভ হচ্ছে অথবা browser পুরোনো index.html cache করে রেখেছে।

সমাধান: (১) npm run build আবার ঠিকভাবে চালানো হয়েছে কিনা নিশ্চিত করুন, (২) browser এ hard refresh (Ctrl+Shift+R) করুন, (৩) মোবাইলে দেখলে ব্রাউজারের cache/site data আলাদাভাবে clear করতে হতে পারে।
ধাপ ১৫

.htaccess এ PHP Handler ব্লক দেখে চিন্তার কিছু নেই

.htaccess ফাইলে Passenger config এর নিচে cPanel নিজে থেকেই এই ব্লকটা যোগ করে:

.HTACCESS (cPanel-generated, unrelated to Node)
# php -- BEGIN cPanel-generated handler, do not edit
# Set the "ea-php81" package as the default "PHP" programming language.
<IfModule mime_module>
  AddHandler application/x-httpd-ea-php81 .php .php8 .phtml
</IfModule>
# php -- END cPanel-generated handler, do not edit

এটা শুধু .php/.php8/.phtml এক্সটেনশনের ফাইলের জন্য প্রযোজ্য — আপনার Vite/React/Express অ্যাপের কোনো ফাইলে এই এক্সটেনশন নেই, তাই এটা Node app এর সাথে কখনো সংঘর্ষ করে না।

এই ব্লক এডিট বা ডিলিট করবেন না — cPanel এটা নিজে থেকে ম্যানেজ করে ("do not edit" কমেন্ট অনুযায়ী), এবং domain এর জন্য PHP ভার্সন সেটিং এর সাথে যুক্ত। শুধু দেখে অবাক হওয়ার দরকার নেই যে Node app এর .htaccess এ PHP এর কথা লেখা আছে কেন — এটা normal, প্রতিটা cPanel domain এর .htaccess এ এটা থাকে।
✓

Deploy সম্পূর্ণ

সাইট লোড হলে deployment সফল। ৯–১৩ নম্বর ধাপ Passenger routing সমস্যার জন্য, আর ১৪–১৫ নম্বর ধাপ CSS/asset এবং PHP handler সংক্রান্ত বিভ্রান্তি দূর করার জন্য — যেকোনো নতুন domain/app এ কাজে লাগবে।

EBSOFT HMS · deployment reference