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

Ubuntu 24.04 এ LAMP স্ট্যাক এবং PHP-FPM সেটআপ করার নিয়ম

Ubuntu 24.04 এ Apache, MariaDB, এবং PHP 8.3 দিয়ে LAMP স্ট্যাক তৈরির পূর্ণাঙ্গ গাইড। unix_socket অথেন্টিকেশন, ভার্চুয়াল হোস্ট কনফিগারেশন এবং Certbot দিয়ে HTTPS সেটআপ শিখুন।

আপনি যা তৈরি করছেন

একটি LAMP স্ট্যাক হলো একটি Ubuntu 24.04 সার্ভারে থাকা চারটি সচল অংশ: নিচে Linux, HTTP অনুরোধের উত্তর দেওয়ার জন্য Apache, ডেটা ধরে রাখার জন্য MariaDB এবং কোড চালানোর জন্য PHP 8.3। এই নির্দেশিকা শেষ করার পর আপনার কাছে একটি নেম-বেসড ভার্চুয়াল হোস্ট থাকবে যা একটি প্রকৃত অ্যাপ্লিকেশন ডিরেক্টরি পরিবেশন করবে, একটি ডেটাবেস থাকবে যাতে ন্যূনতম প্রিভিলেজসহ একজন ডেডিকেটেড ইউজার থাকবে, PHP-FPM এর মাধ্যমে Apache-এর সাথে যুক্ত PHP থাকবে এবং উপরে একটি ফ্রি Let's Encrypt সার্টিফিকেট থাকবে।

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

পূর্বশর্ত এবং গুরুত্বপূর্ণ সতর্কতা

ধরে নিন আপনার কাছে একটি নতুন Ubuntu 24.04 KVM VPS আছে, যেখানে sudo ব্যবহারকারী বা root অ্যাক্সেস এবং একটি পাবলিক IPv4 অ্যাড্রেস রয়েছে। 1 জিবি র‍্যামে একটি ন্যূনতম স্ট্যাক চলতে পারে; তবে এতে কোনো ডেটাবেস-চালিত অ্যাপ্লিকেশন চালানোর আগে 2 জিবি র‍্যাম বরাদ্দ করুন। কারণ MariaDB-এর ডিফল্ট বাফার এবং কিছু PHP-FPM ওয়ার্কার খুব দ্রুত প্রথম 1 জিবি র‍্যাম দখল করে নেয়।

শেষ ধাপে Certbot সঠিকভাবে কাজ করার জন্য দুটি বিষয় নিশ্চিত করতে হবে, তাই এখনই সেগুলো গুছিয়ে নিন। আপনার একটি domain name প্রয়োজন যার A রেকর্ডটি VPS-এর পাবলিক আইপি-র দিকে নির্দেশ করা থাকবে। Let's Encrypt HTTP-এর মাধ্যমে সেই নামের সত্যতা যাচাই করে, তাই শুধুমাত্র একটি আইপি অ্যাড্রেস দিয়ে সার্টিফিকেট পাওয়া সম্ভব নয়। এছাড়া ইন্টারনেট থেকে 80 এবং 443 পোর্টগুলো অবশ্যই অ্যাক্সেসযোগ্য হতে হবে। অনেক প্রোভাইডারের ক্ষেত্রে এর অর্থ হলো কন্ট্রোল প্যানেলের নেটওয়ার্ক ফায়ারওয়ালের পাশাপাশি সার্ভারের ভেতরেও ufw-তে পোর্টগুলো খুলে দেওয়া। DNS পরিবর্তন কার্যকর হতে এক ঘণ্টা পর্যন্ত সময় লাগতে পারে, তাই সবার আগে A রেকর্ড সেট করুন যাতে আপনার প্রয়োজনে সেটি কার্যকর থাকে।

ধাপ 1 - Apache ইনস্টল করুন এবং ডিফল্ট পেজটি নিশ্চিত করুন

sudo apt update
sudo apt install -y apache2

apt আপনার জন্য সার্ভিসটি চালু এবং সক্রিয় করে। এটি পরীক্ষা করুন:

systemctl status apache2

আপনার এমন একটি লাইন প্রয়োজন যেখানে active (running) লেখা আছে। এখন ব্রাউজারে http://YOUR_SERVER_IP/ খুলুন। বড় "It works!" ব্যানারসহ Apache2 Ubuntu Default Page দেখা গেলে বুঝবেন সবকিছু ঠিক আছে; এটি প্রমাণ করে যে Apache সার্ভিস দিচ্ছে এবং কোনো ভুল নেই। এই পেজটি /var/www/html/index.html পাথে থাকে এবং এটি ডিফল্ট ভার্চুয়াল হোস্ট 000-default.conf দ্বারা পরিবেশিত হয়। আপনি পরবর্তীতে উভয়ই নিষ্ক্রিয় করবেন; আপাতত এদের উপস্থিতিই আপনার দেখার কথা।

যদি পেজটি লোড না হয় কিন্তু systemctl বলে যে প্রসেসটি চলছে, তবে একটি ফায়ারওয়াল বাধা সৃষ্টি করছে। এটি পরবর্তী ধাপ।

ধাপ 2 - HTTP এবং HTTPS-এর জন্য ফায়ারওয়াল উন্মুক্ত করা

apache2 প্যাকেজটি তিনটি ufw অ্যাপ্লিকেশন প্রোফাইল রেজিস্টার করে। সেগুলোর তালিকা দেখুন:

sudo ufw app list

আপনি Apache, Apache Full, এবং Apache Secure দেখতে পাবেন। Apache শুধুমাত্র 80 নম্বর পোর্টের জন্য, Apache Secure শুধুমাত্র 443 নম্বর পোর্টের জন্য, এবং Apache Full উভয় পোর্টের জন্য। আপনি এটিই বেছে নেবেন, কারণ আপনি শেষে TLS যোগ করছেন।

sudo ufw allow OpenSSH
sudo ufw allow "Apache Full"
sudo ufw enable

ufw enable চালানোর আগে OpenSSH অনুমতি দিন। ufw ডিফল্টভাবে সমস্ত ইনকামিং ট্রাফিক ব্লক করে রাখে। SSH রুল ছাড়া এটি সক্রিয় করলে সক্রিয় হওয়ার সাথে সাথেই আপনার সংযোগ বিচ্ছিন্ন হয়ে যাবে; আপনি বর্তমান সেশনে থাকতে পারবেন কিন্তু পুনরায় সংযোগ করতে পারবেন না। sudo ufw status দিয়ে নিশ্চিত করুন; আপনি চাইবেন যেন OpenSSH, Apache Full এবং তাদের v6 সমতুল্য রুলগুলো ALLOW হিসেবে দেখায়।

ধাপ 3 - MariaDB ইনস্টল করা এবং সুরক্ষিত করা

sudo apt install -y mariadb-server
systemctl status mariadb

Ubuntu 24.04-এ MariaDB 10.11 অন্তর্ভুক্ত থাকে, যা একটি দীর্ঘমেয়াদী সাপোর্ট (LTS) রিলিজ, তাই আপনার কোনো এক্সটার্নাল রিপোজিটরির প্রয়োজন নেই। সার্ভিসটি চালু হওয়ার পর, এটিকে সুরক্ষিত করুন:

sudo mysql_secure_installation

প্রম্পটগুলোতে Enter চাপার আগে সেগুলো পড়ে নেওয়া ভালো। যখন এটি current root password চাইবে, তখন Enter চাপুন, কারণ এখন পর্যন্ত কোনো পাসওয়ার্ড সেট করা হয়নি। যখন এটি "Switch to unix_socket authentication?" জিজ্ঞাসা করবে, তখন উত্তরটি কোনো পরিবর্তন আনবে না কারণ এই প্যাকেজে এটি আগে থেকেই এনাবল করা আছে, তাই n চাপুন। "Change the root password?"-এর উত্তরে n দিন, কারণটি পরবর্তী অনুচ্ছেদে ব্যাখ্যা করা হয়েছে, এরপর বাকিগুলোর জন্য Y উত্তর দিন: অ্যানোনিমাস ইউজার রিমুভ করা, রিমোট রুট লগইন ডিসঅ্যালাউ করা, টেস্ট ডাটাবেস ড্রপ করা এবং প্রিভিলেজ টেবিল রিলোড করা।

এই অংশটি সবাইকে বিভ্রান্ত করে। Ubuntu-এর MariaDB-তে root ডাটাবেস অ্যাকাউন্ট পাসওয়ার্ডের পরিবর্তে unix_socket অথেন্টিকেশন ব্যবহার করে। এর মানে হলো, ডাটাবেস সেই অপারেটিং-সিস্টেম ইউজারকে বিশ্বাস করে যার মাধ্যমে আপনি ইতিমধ্যে অথেন্টিকেট করেছেন। তাই রুট শেল থেকে এটি কাজ করে:

sudo mysql

...এবং এটি আপনাকে কোনো পাসওয়ার্ড ছাড়াই MariaDB [(none)]> প্রম্পটে নিয়ে যাবে। একজন সাধারণ ইউজার হিসেবে একই কমান্ড চালালে তা প্রত্যাখ্যান করা হবে, আর এটাই এর মূল উদ্দেশ্য: ডাটাবেস রুটের অ্যাক্সেস মেশিনের sudo-এর সাথে যুক্ত এবং এখানে চুরি করার, ফিশিং করার বা ব্রুট-ফোর্স করার মতো কোনো পাসওয়ার্ড নেই। এটি পাসওয়ার্ডের চেয়ে বেশি নিরাপদ, তাই এটি পরিবর্তন করবেন না। এর থেকে যে নিয়মটি আসে তা হলো: কখনোই কোনো অ্যাপ্লিকেশনকে root অ্যাকাউন্টের সাথে যুক্ত করবেন না। প্রতিটি অ্যাপ্লিকেশনের জন্য আলাদা ইউজার তৈরি করুন (ধাপ 7), কারণ TCP-এর মাধ্যমে ইউজারনেম এবং পাসওয়ার্ড দিয়ে কানেক্ট করা অ্যাপ সকেট অথেন্টিকেশন ব্যবহার করতে পারে না এবং আপনি চাইবেন প্রতিটি অ্যাপ যেন শুধুমাত্র তার নিজস্ব ডাটাবেসের মধ্যেই সীমাবদ্ধ থাকে।

ধাপ 4 - PHP 8.3 এবং PHP-FPM ইনস্টল করা

Ubuntu 24.04-এর ডিফল্ট PHP সংস্করণ হলো 8.3। FPM প্রসেস ম্যানেজার এবং একটি সাধারণ অ্যাপ্লিকেশনের জন্য প্রয়োজনীয় এক্সটেনশনগুলো ইনস্টল করুন:

sudo apt install -y php8.3-fpm php8.3-mysql php8.3-cli \
  php8.3-curl php8.3-xml php8.3-mbstring php8.3-zip

লক্ষ্য করুন যে এই তালিকায় কী নেই: libapache2-mod-php। এই পুরোনো প্যাকেজটি প্রতিটি Apache প্রসেসের ভেতরে একটি PHP ইন্টারপ্রেটার যুক্ত করে। এটি সহজ হলেও, প্রতিটি ওয়ার্কার প্রসেস একটি স্ক্রিপ্ট বা একটি স্ট্যাটিক ইমেজ—যা-ই সার্ভ করুক না কেন, তার সাথে একটি করে PHP কপি বহন করে। এদের জীবনচক্র একই থাকে এবং এটি শুধুমাত্র Apache-এর prefork MPM-এর সাথে কাজ করে, যা সবচেয়ে কম কার্যকর। এর পরিবর্তে PHP-FPM PHP-কে নিজস্ব প্রসেস পুল হিসেবে চালায়, যার সাথে Apache একটি সকেটের মাধ্যমে যোগাযোগ করে। ফলে Apache স্ট্যাটিক ফাইলের জন্য থ্রেডেড event MPM ব্যবহার করতে পারে এবং শুধুমাত্র PHP রিকোয়েস্টগুলো FPM-এর কাছে পাঠাতে পারে। এই পুলটি ওয়েব সার্ভার থেকে আলাদাভাবে টিউন করা যায় এবং পরবর্তীতে আপনি যদি সামনে nginx ব্যবহার করেন, তবে একই FPM সেটআপ কাজ করবে। এটি বর্তমান সময়ে ডিফল্ট হিসেবে ব্যবহারের পেছনে যথেষ্ট কারণ রয়েছে।

Apache proxy_fcgi মডিউলের মাধ্যমে FPM-এর সাথে যোগাযোগ করে। এটি সক্রিয় করুন, FPM প্যাকেজ যে কনফিগারেশন ফাইলটি যুক্ত করেছে তা সক্রিয় করুন এবং রিস্টার্ট দিন:

sudo a2enmod proxy_fcgi setenvif
sudo a2enconf php8.3-fpm
sudo systemctl restart apache2

a2enconf php8.3-fpm ফাইলটি /etc/apache2/conf-available/php8.3-fpm.conf সক্রিয় করে, যার মধ্যে এমন নিয়ম রয়েছে যা PHP ফাইলগুলোকে FPM সকেটে রাউট করে। এর মূল অংশটি যেকোনো .php ফাইলের সাথে মিলে যায় এবং সেটিকে /run/php/php8.3-fpm.sock সকেটে পাঠিয়ে দেয়:

<FilesMatch ".+\.ph(ar|p|tml)$">
    SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost"
</FilesMatch>

আপনাকে এই ফাইলটি এডিট করতে হবে না; এটি সঠিকভাবেই থাকে। তবে সকেটের পাথ জানা থাকলে আপনি পরবর্তীতে "PHP downloads instead of running" এবং "Primary script unknown" ত্রুটিগুলো নির্ণয় করতে পারবেন। এই সমস্যাগুলো মূলত Apache এবং FPM-এর মধ্যে এই সকেট বা এর পেছনের ফাইলটি নিয়ে মতপার্থক্যের কারণে ঘটে।

ধাপ 5 - আপনার অ্যাপের জন্য একটি নাম-ভিত্তিক ভার্চুয়াল হোস্ট

নাম-ভিত্তিক ভার্চুয়াল হোস্টিং একটি IP ঠিকানা দিয়ে একাধিক সাইট পরিচালনা করতে দেয়; Apache অনুরোধের মধ্যে থাকা Host: হেডার দেখে সাইটটি নির্বাচন করে। ডিফল্ট /var/www/html থেকে দূরে অ্যাপটির জন্য একটি ডিরেক্টরি তৈরি করুন:

sudo mkdir -p /var/www/testapp
sudo chown -R www-data:www-data /var/www/testapp
sudo chmod -R 755 /var/www/testapp

মালিকানা গুরুত্বপূর্ণ। Ubuntu-তে Apache এবং PHP-FPM উভয়ই www-data ব্যবহারকারী হিসেবে চলে, তাই যেসব ফাইল ওয়েব সার্ভারকে পড়তে হয় এবং যেসব ডিরেক্টরিতে অ্যাপকে লিখতে হয়, যেমন আপলোড ফোল্ডার, সেগুলোর মালিকানা www-data-এর হওয়া উচিত। আপনি যদি আপনার লগইন ব্যবহারকারী হিসেবে ফাইলগুলো সম্পাদনা করতে চান, তবে একটি সাধারণ নিয়ম হলো ফাইলগুলোর মালিকানা নিজের কাছে রাখা এবং আপনার ব্যবহারকারীকে www-data গ্রুপে যুক্ত করা; সাধারণ ডেপ্লয়মেন্টের জন্য www-data:www-data ব্যবহার করাই সবচেয়ে সহজ।

/etc/apache2/sites-available/testapp.conf-এ ভার্চুয়াল হোস্ট তৈরি করুন:

<VirtualHost *:80>
    ServerName app.example.com
    DocumentRoot /var/www/testapp

    <Directory /var/www/testapp>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/testapp-error.log
    CustomLog ${APACHE_LOG_DIR}/testapp-access.log combined
</VirtualHost>

ServerName-কে আপনার আসল ডোমেইনের সাথে সেট করুন। Options -Indexes অপশনটি কোনো ইনডেক্স ফাইল না থাকলে Apache-কে ডিরেক্টরি তালিকা প্রদর্শন করা থেকে বিরত রাখে, অন্যথায় দর্শকরা আপনার সোর্স ট্রি ব্রাউজ করতে পারবে। AllowOverride All অপশনটি একটি .htaccess ফাইলকে কাজ করতে দেয়, যা বেশিরভাগ PHP অ্যাপ্লিকেশনের সুন্দর URL-এর জন্য প্রয়োজন; যদি আপনার অ্যাপের এটি প্রয়োজন না হয়, তবে সামান্য গতি বৃদ্ধির জন্য এটিকে None-এ নামিয়ে আনুন। এই সাইটটি সক্রিয় করুন, ডিফল্ট সাইটটি নিষ্ক্রিয় করুন, কনফিগারেশন পরীক্ষা করুন এবং রিলোড করুন:

sudo a2ensite testapp
sudo a2dissite 000-default
sudo apache2ctl configtest
sudo systemctl reload apache2

apache2ctl configtest কমান্ডটি Syntax OK প্রিন্ট করবে। a2dissite 000-default লাইনটি মানুষ প্রায়ই ভুলে যায়, এবং এই কারণেই পরবর্তীতে ডিফল্ট পেজটি আটকে আছে বলে মনে হয়, যা ব্যর্থতার অংশে আলোচনা করা হয়েছে।

ধাপ 6 - PHP চলছে কিনা তা যাচাই করুন, তারপর প্রমাণটি মুছে ফেলুন

অ্যাপের রুট ডিরেক্টরিতে একটি এক লাইনের PHP ফাইল তৈরি করুন:

echo "<?php phpinfo();" | sudo tee /var/www/testapp/info.php

http://app.example.com/info.php ভিজিট করুন। একটি সঠিক ফলাফলে আপনি লম্বা বেগুনি এবং ধূসর রঙের PHP Version 8.3.x টেবিল দেখতে পাবেন যেখানে আপনার লোড করা মডিউলগুলোর তালিকা থাকবে এবং Server API লাইনে FPM/FastCGI লেখা থাকবে। এই শেষ লাইনটি নিশ্চিত করে যে রিকোয়েস্টগুলো mod_php এর পরিবর্তে PHP-FPM এর মাধ্যমে যাচ্ছে।

এখন এটি অবিলম্বে মুছে ফেলুন:

sudo rm /var/www/testapp/info.php

phpinfo() আপনার সঠিক PHP ভার্সন, প্রতিটি লোড করা এক্সটেনশন, ফাইলের পাথ এবং এনভায়রনমেন্টের বিস্তারিত তথ্য প্রকাশ করে, যা সার্ভারে পরিচিত দুর্বলতা খুঁজছে এমন যে কারো জন্য একটি উপহার। এটি একটি পরীক্ষা, কোনো ফিচার নয়। পেজটি দেখার সাথে সাথেই এটি মুছে ফেলুন। যদি টেবিলের পরিবর্তে আপনার ব্রাউজার info.php ফাইলটি ডাউনলোড করার প্রস্তাব দেয়, তবে বুঝতে হবে PHP এর সাথে Apache সঠিকভাবে সংযুক্ত হয়নি; অন্য কিছু করার আগে ফেইলিয়র বা ব্যর্থতার সেকশনে যান।

ধাপ 7 - অ্যাপ ডেটাবেস এবং ন্যূনতম সুবিধাসম্পন্ন ব্যবহারকারী তৈরি করুন

সকেট-অথেন্টিকেটেড root হিসেবে ডেটাবেসটি ওপেন করুন:

sudo mysql

এরপর একটি ডেটাবেস এবং শুধুমাত্র সেই ডেটাবেসের জন্য সীমাবদ্ধ একটি ব্যবহারকারী তৈরি করুন:

CREATE DATABASE appdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON appdb.* TO 'appuser'@'localhost';
FLUSH PRIVILEGES;
EXIT;

এখানে তিনটি সুচিন্তিত সিদ্ধান্ত নেওয়া হয়েছে। utf8mb4 হলো প্রকৃত চার-বাইট বিশিষ্ট UTF-8, পুরনো utf8 অ্যালিয়াসটি নীরবে ইমোজি এবং কিছু CJK ক্যারেক্টার কেটে ফেলে, তাই সবসময় utf8mb4 ব্যবহার করুন। গ্র্যান্টটি appdb.*-এর ওপর দেওয়া হয়েছে, *.*-এর ওপর নয়: এই ব্যবহারকারী শুধুমাত্র তার নিজস্ব ডেটাবেস অ্যাক্সেস করতে পারবে এবং অন্য কিছু নয়, ফলে অ্যাপে কোনো SQL-injection ত্রুটি থাকলেও তা অন্য কোনো সাইটের টেবিল পড়তে পারবে না। এবং 'appuser'@'localhost' অ্যাকাউন্টটিকে শুধুমাত্র সেই সার্ভার থেকে আসা সংযোগের মধ্যে সীমাবদ্ধ রাখে।

সেই ব্যবহারকারী হিসেবে এটি পরীক্ষা করুন:

mysql -u appuser -p appdb

এটি পাসওয়ার্ড চাইবে এবং আপনাকে একটি MariaDB [appdb]> প্রম্পটে নিয়ে যাবে। লক্ষ্য করুন যে এখানে কোনো -h ফ্ল্যাগ নেই, এটি বাদ দিন এবং ক্লায়েন্ট লোকাল Unix সকেটের মাধ্যমে সংযোগ স্থাপন করবে, যা MariaDB-তে localhost হিসেবে গণ্য হয়। একটি গুরুত্বপূর্ণ বিষয় জেনে রাখা ভালো: MySQL এবং MariaDB-এর কাছে, localhost মানে হলো Unix সকেট এবং 127.0.0.1 মানে হলো TCP সংযোগ। একটি সাধারণ Ubuntu 24.04 MariaDB-তে সার্ভার এখনো 127.0.0.1 থেকে আসা TCP সংযোগকে localhost হিসেবে রেজলভ করে, তাই উভয়ই অ্যাকাউন্টের সাথে মিলে যায়। কিন্তু যেসব সার্ভারে skip-name-resolve সক্রিয় থাকে (এটি একটি সাধারণ পারফরম্যান্স টিউন এবং অনেক কন্টেইনার ইমেজে এটিই নিয়ম), সেখানে এই দুটিকে ভিন্ন হোস্ট হিসেবে ধরা হয়। ফলে কোনো অ্যাপ যদি 127.0.0.1 ব্যবহার করে সংযোগ করতে চায়, তবে পাসওয়ার্ড সঠিক হওয়া সত্ত্বেও ERROR 1045 (28000): Access denied for user 'appuser'@'127.0.0.1' (using password: YES) ত্রুটির কারণে তা প্রত্যাখ্যান করা হয়।

তাই আপনার অ্যাপ্লিকেশনকে localhost হোস্ট, appuser ব্যবহারকারী এবং appdb ডেটাবেসের দিকে নির্দেশ করুন, কখনোই root ব্যবহার করবেন না। PHP-এর mysqli এবং PDO উভয়ই Unix সকেটে সুইচ করে যখন হোস্ট হিসেবে আক্ষরিক স্ট্রিং localhost ব্যবহার করা হয়, যা আপনার তৈরি করা অ্যাকাউন্টের সাথে মিলে যায়। যদি কোনো ফ্রেমওয়ার্ক সংখ্যাসূচক TCP হোস্ট ব্যবহার করতে বাধ্য করে, তবে ব্যবহারকারীকে সেই অনুযায়ী তৈরি করুন, যেমন 'appuser'@'127.0.0.1', অথবা শুধুমাত্র তখনই @'%' ব্যবহার করুন (ফায়ারওয়াল রুলের সাথে) যদি অন্য কোনো মেশিন থেকে ডেটাবেসে পৌঁছানোর প্রয়োজন হয়।

Step 8 - Certbot দিয়ে HTTPS যোগ করা

প্লেইন HTTP-এর মাধ্যমে লগইন ফর্ম সার্ভ করলে পাসওয়ার্ড প্লেইন টেক্সট হিসেবে আদান-প্রদান হয় এবং প্রতিটি আধুনিক ব্রাউজার এই পেজটিকে "Not secure" হিসেবে চিহ্নিত করে। Certbot একটি কমান্ডের মাধ্যমেই এই সমস্যার সমাধান করে। Apache প্লাগইনসহ এটি ইনস্টল করুন:

sudo apt install -y certbot python3-certbot-apache
sudo certbot --apache

Certbot এখানে দুটি প্লাগইন ব্যবহার করে। apache authenticator আপনার চলমান Apache-এর মাধ্যমে একটি চ্যালেঞ্জ ফাইল সার্ভ করে প্রমাণ করে যে ডোমেইনটির নিয়ন্ত্রণ আপনার কাছে আছে এবং apache installer এরপর আপনার ভার্চুয়াল হোস্টকে নতুন করে লিখে 443 ব্লক যোগ করে, সেটিকে নতুন সার্টিফিকেটের দিকে নির্দেশ করে এবং ডিফল্টভাবে সমস্ত HTTP ট্রাফিককে HTTPS-এ রিডাইরেক্ট করে। Certbot 2.0 থেকে রিডাইরেক্ট সংক্রান্ত কোনো প্রশ্ন করা হয় না; যদি আপনি প্লেইন HTTP সার্ভ করা চালিয়ে যেতে চান তবে --no-redirect পাস করুন। যেহেতু আপনি Step 5-এ একটি সঠিক ServerName সেট করেছেন, তাই Certbot স্বয়ংক্রিয়ভাবে ডোমেইনটি শনাক্ত করতে পারে। সার্টিফিকেটগুলো 90 দিন পর্যন্ত কার্যকর থাকে এবং প্যাকেজটি একটি systemd টাইমার ইনস্টল করে যা সেগুলোকে রিনিউ করে; sudo certbot renew --dry-run দিয়ে টাইমারটি যাচাই করুন, যা Congratulations, all simulated renewals succeeded দিয়ে শেষ হওয়া উচিত।

চ্যালেঞ্জ, রিনিউয়াল টাইমার এবং DNS ও ফায়ারওয়ালের প্রয়োজনীয়তা সম্পর্কে বিস্তারিত জানতে, Apache-তে Certbot দিয়ে বিনামূল্যে Let's Encrypt TLS সার্টিফিকেট ইস্যু করা বিষয়ক সহায়ক নির্দেশিকাটি দেখুন।

ব্যাকআপ, আপগ্রেড এবং হার্ডেনিং

আপনার সার্ভারের স্টেট ধরে রাখে এমন দুটি জিনিস ব্যাকআপ নিন: ডাটাবেস এবং ওয়েব রুট। প্রতিদিন রাতে একটি লজিক্যাল ডাম্প নেওয়া সবচেয়ে সহজ এবং নির্ভরযোগ্য পদ্ধতি, sudo sh -c 'mysqldump --all-databases --single-transaction | gzip > /root/db-$(date +%F).sql.gz', যা পরবর্তীতে সার্ভার থেকে কপি করে অন্য কোথাও সরিয়ে নিতে হবে। পুরো পাইপলাইনটিকে sudo sh -c দিয়ে র‍্যাপ করা জরুরি: এটি ছাড়া শেল > /root/... রিডাইরেক্টটিকে আপনার নিজস্ব ইউজার হিসেবে চালায় এবং Permission denied এর কারণে ব্যর্থ হয়, কারণ শুধুমাত্র mysqldumpsudo ইনহেরিট করে। --single-transaction ব্যবহার করলে InnoDB টেবিলগুলোকে লক না করেই একটি সামঞ্জস্যপূর্ণ স্ন্যাপশট পাওয়া যায়। এর সাথে /var/www এবং /etc/apache2/sites-available এর একটি tar যুক্ত করুন, তাহলে আপনি সেই ফাইলগুলো থেকে একটি নতুন VPS-এ পুরো স্ট্যাকটি পুনরায় তৈরি করতে পারবেন।

আপগ্রেড হলো একটি সাধারণ sudo apt update && sudo apt upgrade। যে বিষয়টি সমস্যা তৈরি করতে পারে তা হলো PHP version bump, যখন ভবিষ্যতের কোনো Ubuntu ডিফল্ট হিসেবে PHP 8.4 এ চলে যায়, তখন apt হয়তো 8.3 এর পাশাপাশি php8.4-fpm ইনস্টল করবে, সকেটটি /run/php/php8.4-fpm.sock হয়ে যাবে এবং আপনার Apache কনফিগারেশন তখনও 8.3 সকেটকেই নির্দেশ করবে। নতুন কনফিগটি এনাবল করুন (sudo a2enconf php8.4-fpm) এবং পুরনোটি ডিসেবল করুন, অন্যথায় রুটিন আপগ্রেডের পর আপনার সাইট Primary script unknown এরর দেখাতে শুরু করবে। যেহেতু PHP রিলিজ LTS ডিস্ট্রোর চেয়ে দ্রুত আপডেট হয়, তাই প্যাচ ভার্সন পিন না করে বর্তমান PHP রিলিজ নোটগুলো চেক করুন।

প্রথম দিনেই দুটি হার্ডেনিং পদক্ষেপ নেওয়া উচিত। প্রথমত, বক্সে Fail2Ban watching SSH সেটআপ করুন, একটি পাবলিক VPS-এ কয়েক মিনিটের মধ্যেই স্বয়ংক্রিয় লগইন প্রচেষ্টা শুরু হয় এবং একটি ছোট জেল হাজার হাজার প্রচেষ্টাকে কমিয়ে হাতেগোনা কয়েকটিতে নিয়ে আসে। দ্বিতীয়ত, আপনি যদি ফাইল হাতে এডিট করার পরিবর্তে ব্রাউজারের মাধ্যমে Apache ভার্চুয়াল হোস্ট, MariaDB ডাটাবেস এবং ইউজার ম্যানেজ করতে চান, তবে the Webmin web-based control panel এই স্ট্যাকের উপরেই কাজ করে এবং আপনার তৈরি করা কনফিগারেশন ফাইলগুলোই নিয়ন্ত্রণ করে। এগুলো কোনোটিই মূল বিষয়গুলো বোঝার বিকল্প নয়, তবে উভয়ই দৈনন্দিন কাজের জটিলতা কমিয়ে দেয়।

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

ডিফল্ট পেজটি সরছে না। আপনি আপনার ভার্চুয়াল হোস্ট এডিট করেছেন, রিলোড করেছেন, কিন্তু ব্রাউজারে এখনও "Apache2 Ubuntu Default Page" এবং এর "It works!" ব্যানারটি দেখাচ্ছে। Apache প্রথম ম্যাচ করা ভার্চুয়াল হোস্টটি পরিবেশন করে। যখন কোনো ServerName অনুরোধের সাথে মেলে না, তখন বর্ণানুক্রমিকভাবে প্রথম কনফিগারেশনটি কার্যকর হয়; 000-default.conf, testapp.conf-এর আগে আসে। হয় অনুরোধের হোস্ট নেম আপনার ServerName-এর সাথে মিলছে না, অথবা আপনি কখনোই sudo a2dissite 000-default চালাননি। ডিফল্ট কনফিগারেশনটি নিষ্ক্রিয় করতে sudo systemctl reload apache2 ব্যবহার করুন এবং apache2ctl -S দিয়ে নিশ্চিত করুন, যা ভিহোস্ট ম্যাপ প্রিন্ট করে দেখাবে কোন কনফিগারেশনটি ডিফল্ট হিসেবে কাজ করছে। ব্রাউজারের ক্যাশও পরিষ্কার করুন; পুরনো পেজের একটি ক্যাশ করা 200 রেসপন্স থেকে যেতে পারে।

একটি .php ফাইল রান না হয়ে ডাউনলোড হচ্ছে। আপনি info.php ওপেন করলে ব্রাউজারটি raw <?php সোর্স কোডসহ একটি ফাইল ডাউনলোড করে অথবা তা প্লেইন টেক্সট হিসেবে দেখায়, কিন্তু রান করে না। Apache ফাইলটিকে স্ট্যাটিক অ্যাসেট হিসেবে পরিবেশন করছে কারণ PHP হ্যান্ডলার সংযুক্ত নেই, আপনি sudo a2enmod proxy_fcgi অথবা sudo a2enconf php8.3-fpm বাদ দিয়েছেন, অথবা এর পরে Apache রিস্টার্ট করেননি। তিনটিই রান করুন (ধাপ 4) এবং রিলোড করুন। apache2ctl -M | grep fcgi দিয়ে নিশ্চিত করুন যে মডিউলটি লোড হয়েছে, যা proxy_fcgi_module তালিকাভুক্ত করবে। এটি একটি সোর্স-কোড লিক, কোনো সাধারণ বাগ নয়, তাই সার্ভারে কোনো গুরুত্বপূর্ণ তথ্য রাখার আগে এটি ঠিক করুন।

ERROR 1698 (28000): Access denied for user 'root'@'localhost' আপনি sudo ছাড়া mysql -u root অথবা mariadb -u root রান করেছেন। রুট অ্যাকাউন্ট unix_socket অথেন্টিকেশন ব্যবহার করে, তাই এটি কেবল তখনই আপনাকে গ্রহণ করবে যখন আপনার ওএস ইউজার প্রকৃতপক্ষে root। এর সমাধান হলো sudo mysql, কোনো -u root বা পাসওয়ার্ডের প্রয়োজন নেই। এই বার্তাটি সকেট অথেন্টিকেশন সঠিকভাবে কাজ করার প্রত্যাশিত আচরণ, কোনো ত্রুটিপূর্ণ ইনস্টলেশন নয়।

অ্যাপ্লিকেশন থেকে ERROR 1045 (28000): Access denied for user 'appuser'@'127.0.0.1', সঠিক পাসওয়ার্ড থাকা সত্ত্বেও। অ্যাকাউন্টটি 'appuser'@'localhost' হিসেবে বিদ্যমান, কিন্তু আপনার অ্যাপ TCP-এর মাধ্যমে 127.0.0.1-এ সংযোগ করার চেষ্টা করছে এমন একটি সার্ভারে যেখানে হোস্ট-নেম রেজোলিউশন নিষ্ক্রিয় (skip-name-resolve)। তাই MariaDB এই দুটিকে ভিন্ন হোস্ট হিসেবে গণ্য করে; localhost হলো ইউনিক্স সকেট এবং 127.0.0.1 হলো TCP। অ্যাপটিকে localhost হোস্টের দিকে নির্দেশ করুন যাতে এটি সকেট ব্যবহার করে এবং অ্যাকাউন্টের সাথে মেলে, অথবা যদি ফ্রেমওয়ার্কটি কেবল TCP-তে কাজ করে তবে একটি দ্বিতীয় অ্যাকাউন্ট 'appuser'@'127.0.0.1' তৈরি করুন।

/var/log/apache2/testapp-error.log-এ AH01071: Got error 'Primary script unknown', ব্রাউজারে File not found. দেখাচ্ছে। Apache অনুরোধটি PHP-FPM-এর কাছে পাঠিয়েছে, কিন্তু FPM Apache-এর দেওয়া পাথে স্ক্রিপ্টটি খুঁজে পায়নি। দুটি সাধারণ কারণ: আপনার কনফিগারেশনের FPM সকেট এমন একটি PHP ভার্সনের দিকে নির্দেশ করছে যা ইনস্টল করা নেই (আপগ্রেডের পর একটি php8.4 সকেট যখন কেবল 8.3 রান করছে), অথবা ফাইলটি প্রকৃতপক্ষে সেখানে নেই কারণ DocumentRoot এবং আসল ডিরেক্টরি ভিন্ন। ls -l /run/php/ দিয়ে সকেটটি বিদ্যমান কিনা তা পরীক্ষা করুন, DocumentRoot ফাইলটির অবস্থানের সাথে মিলছে কিনা নিশ্চিত করুন এবং php8.3-fpmapache2 উভয়ই রিস্টার্ট করুন।

প্রতিবার রিস্টার্টে AH00558: apache2: Could not reliably determine the server's fully qualified domain name এটি একটি ক্ষতিকারক সতর্কবার্তা, কোনো ত্রুটি নয়। Apache আপনাকে জানাচ্ছে যে কোনো গ্লোবাল ServerName সেট করা নেই। /etc/apache2/conf-available/servername.conf-এ ServerName your.domain লিখে এবং sudo a2enconf servername রান করে এটি বন্ধ করুন।

Apache স্টার্ট করার সময় (98)Address already in use: AH00072: make_sock: could not bind to address 0.0.0.0:80 অন্য কোনো ওয়েব সার্ভার ইতিমধ্যে পোর্ট 80 দখল করে রেখেছে, যা প্রায়ই আগের কোনো পরীক্ষার ফেলে রাখা nginx হতে পারে। sudo ss -ltnp | grep :80 দিয়ে সেটিকে খুঁজে বের করুন, তারপর Apache স্টার্ট করার আগে অন্য সার্ভিসটি বন্ধ এবং নিষ্ক্রিয় করুন।

FAQ

mod_php or PHP-FPM - which should I use?

Use PHP-FPM. mod_php embeds an interpreter in every Apache process and forces the slow prefork MPM, so Apache carries PHP overhead even when serving a static image. PHP-FPM runs PHP as a separate, independently tuned pool that Apache reaches over a socket, works with the faster threaded event MPM, and moves unchanged to nginx later. It is the modern default; mod_php only makes sense for a legacy app that depends on some in-process behaviour.

Why does my browser download the PHP file instead of running it?

Apache is treating the .php file as a static download because no PHP handler is attached to it. On Ubuntu 24.04 with FPM that means you missed one of sudo a2enmod proxy_fcgi, sudo a2enconf php8.3-fpm, or the Apache restart afterwards. Run all three and reload, then verify with apache2ctl -M | grep fcgi that proxy_fcgi_module is listed. Until you fix it the server is leaking source code, so treat it as urgent.

Why is root access denied in MariaDB even with the right password?

Because there is no password, Ubuntu's MariaDB authenticates the root account by unix_socket, tying it to the operating-system root user. mysql -u root from a normal shell returns ERROR 1698 (28000): Access denied for user 'root'@'localhost' by design. Connect with sudo mysql instead, and create a separate password-authenticated user for any application rather than reusing root.

How do I add HTTPS to my LAMP site?

Install certbot and python3-certbot-apache, point a domain's A record at the server, then run sudo certbot --apache. The apache authenticator proves domain control through your running Apache and the installer rewrites the virtual host for port 443 and sets up automatic renewal. The full Certbot and Apache walk-through covers the challenge, the renewal timer, and the common failure modes.

#lamp#apache#mariadb#php-fpm#ubuntu