EQVPS

VPS-এ MySQL কীভাবে বসাবেন: ইউজার, নিরাপদ রিমোট অ্যাক্সেস, কম RAM আর ব্যাকআপ

Ubuntu 24.04 VPS-এ MySQL 8.0 বসান, অ্যাপের জন্য একটা ডেটাবেস আর ইউজার বানান, পোর্ট 3306 না খুলেই নিজের কম্পিউটার থেকে পৌঁছান, অলস অবস্থার মেমরি 383 MB থেকে 165 MB-তে নামান, আর এমন স্ক্রিপ্টে প্রতি রাতে ব্যাকআপ নিন যা গোলমাল হলে স্পষ্টভাবে ব্যর্থ হয়।

MySQL বসানো মানে একটা কমান্ড। আসল কাজ শুরু হয় তারপর: অ্যাপের জন্য একজন ইউজার, পোর্ট 3306 ইন্টারনেটে না খুলে নিজের কম্পিউটার থেকে ডেটাবেসে পৌঁছানোর একটা উপায়, ছোট সার্ভারের জন্য মেমরি সেটিং, আর এমন ব্যাকআপ যা আপনাকে ছাড়াই চলে। এই গাইড Ubuntu 24.04-এ চারটিই দেখায়। প্রতিটি ধাপ আমাদের Ubuntu 24.04 ইমেজে চালানো হয়েছে, আর নিচের সংখ্যাগুলো সেই সার্ভার থেকেই।

কমান্ডগুলো sudo থাকা ইউজার দিয়ে চালান। Ubuntu সেট আপ গাইড একজন বানিয়ে দেয়।

1. ইনস্টল করুন

sudo apt update
sudo apt install -y mysql-server
mysql --version

আমাদের সার্ভারে ইনস্টলে 51 সেকেন্ড লেগেছে, আর এসেছে MySQL 8.0.46। এটা সঙ্গে সঙ্গে চালু হয়, প্রতিবার বুটে আবার চালু হয়, আর শুধু সার্ভারের ভেতরেই শোনে: সাধারণ সংযোগের জন্য 127.0.0.1:3306 আর MySQL-এর নতুন X প্রোটোকলের জন্য 127.0.0.1:33060। বাইরে থেকে এখনো কিছুতেই পৌঁছানো যায় না।

2. একটা ডেটাবেস আর ইউজার বানান

Ubuntu-তে MySQL-এর root অ্যাকাউন্ট সকেট অথেন্টিকেশন ব্যবহার করে, তাই sudo mysql আপনাকে পাসওয়ার্ড ছাড়াই ঢুকিয়ে দেয়। আপনার অ্যাপের জন্য একটা ডেটাবেস আর ইউজার বানান:

sudo mysql
CREATE DATABASE app CHARACTER SET utf8mb4;
CREATE USER 'app'@'localhost' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON app.* TO 'app'@'localhost';
EXIT;

অ্যাপ যেভাবে যুক্ত হবে, সেভাবেই পরীক্ষা করুন:

mysql -u app -p app -e "SELECT CURRENT_USER();"

এতে app@localhost দেখানো উচিত। ভুল পাসওয়ার্ড দিলে আসে ERROR 1045 (28000): Access denied for user 'app'@'localhost'। ইউজারটি app-এর ভেতরে সব করতে পারে, বাইরে কিছুই না।

3. নিজের কম্পিউটার থেকে যুক্ত হোন: SSH টানেল

নিজের মেশিনে DBeaver, MySQL Workbench বা mysql কমান্ড লাইনের মতো ডেস্কটপ ক্লায়েন্ট ব্যবহার করতে কোনো পোর্ট খুলবেন না। SSH দিয়ে একটা ফরোয়ার্ড করুন:

ssh -L 3307:127.0.0.1:3306 deploy@YOUR.SERVER.IP

NAT প্ল্যানে -p আর ড্যাশবোর্ডের নিজস্ব SSH পোর্ট যোগ করুন। উইন্ডোটা খোলা থাকা পর্যন্ত ক্লায়েন্টকে হোস্ট 127.0.0.1, পোর্ট 3307, ইউজার app-এ দিন। লোকাল দিকে আমরা 3307 নিয়েছি, যাতে আপনার কম্পিউটারে হয়তো চলা MySQL-এর সঙ্গে না মেলে। আমাদের পরীক্ষায় সার্ভার টানেল দিয়ে সঙ্গে সঙ্গে সাড়া দিয়েছে, অথচ তার ঠিকানায় 3306-এ সরাসরি সংযোগ প্রত্যাখ্যাত হয়েছে।

4. অন্য একটি সার্ভারের জন্য সরাসরি অ্যাক্সেস

কখনো অ্যাপ দ্বিতীয় একটা সার্ভারে চলে আর সরাসরি যুক্ত হতে হয়। তার জন্য ডেটাবেসের দরকার নিজস্ব IPv4 থাকা প্ল্যান, কারণ NAT প্ল্যান শুধু আপনার SSH পোর্ট ফরোয়ার্ড করে। তিনটি পরিবর্তন, সবগুলো অ্যাপ সার্ভারের ঠিকানায় (এখানে 203.0.113.20) সীমিত:

sudo sed -i 's/^bind-address.*/bind-address = 0.0.0.0/' /etc/mysql/mysql.conf.d/mysqld.cnf
sudo systemctl restart mysql
sudo ufw allow from 203.0.113.20 to any port 3306 proto tcp
CREATE USER 'app'@'203.0.113.20' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON app.* TO 'app'@'203.0.113.20';

ufw এখনো চালু না থাকলে আগে SSH-এর অনুমতি দিন (sudo ufw allow OpenSSH), তারপর sudo ufw enable চালান। বিস্তারিত ufw গাইডে।

আমরা দুটো তালাই আলাদা করে পরীক্ষা করেছি। ফায়ারওয়ালের নিয়ম ছিল কিন্তু মিলে যাওয়া MySQL ইউজার ছিল না, তখন সার্ভার error 1130: Host '…' is not allowed to connect to this MySQL server দিয়ে ফিরিয়ে দিয়েছে। ইউজার যোগ করার পর সংযোগ হয়েছে। ফায়ারওয়ালের নিয়ম সরানোর পর সংযোগ শুধু টাইমআউট হয়েছে। ইন্টারনেটের অন্য যেকোনো ঠিকানাও এই একই টাইমআউট পায়।

5. কম RAM ব্যবহার করুন

অলস অবস্থায়, নিজস্ব ডেটা ছাড়া, MySQL 8.0 আমাদের সার্ভারে 383 MB নিচ্ছিল। এর বেশিরভাগই Performance Schema-র, একটা ডায়াগনস্টিক সুবিধা যা আগে থেকেই মেমরি আটকে রাখে। ছোট VPS-এ এটা বন্ধ করুন আর মূল ক্যাশের আকার নিজেই ঠিক করুন:

sudo tee /etc/mysql/mysql.conf.d/zz-small-vps.cnf >/dev/null <<'EOF'
[mysqld]
performance_schema = OFF
innodb_buffer_pool_size = 256M
max_connections = 50
EOF
sudo systemctl restart mysql
ps -o rss= -C mysqld

রিস্টার্টের পরে এটা 165 MB নিচ্ছিল। buffer pool আপনার ডেটা আর ইনডেক্স ক্যাশ করে, আর অ্যাপও চালায় এমন 2 GB সার্ভারের জন্য 256 MB উপযুক্ত। ডেটাবেসই যদি সার্ভারের মূল কাজ হয় আর ক্যাশের চেয়ে বড় হয়ে যায়, তাহলে বাড়ান। max_connections = 50 কানেকশন পুলওয়ালা একটা অ্যাপের জন্য যথেষ্টর চেয়েও বেশি। আপনি performance_schema-এর পরিসংখ্যান হারান। কখনো ধীর কোয়েরি খুঁটিয়ে দেখার দরকার হলে আবার চালু করুন।

6. রাতের ব্যাকআপ

mysqldump --single-transaction অ্যাপ আটকে না রেখেই InnoDB টেবিলের একটা সামঞ্জস্যপূর্ণ কপি নেয়। এটা একটা ছোট স্ক্রিপ্টে রাখুন:

sudo tee /usr/local/bin/mysql-backup >/dev/null <<'EOF'
#!/bin/bash
set -euo pipefail
umask 077
mkdir -p /var/backups/mysql
mysqldump --single-transaction --routines --triggers app | gzip > /var/backups/mysql/app-$(date +%F).sql.gz
find /var/backups/mysql -name 'app-*.sql.gz' -mtime +14 -delete
EOF
sudo chmod 755 /usr/local/bin/mysql-backup
echo '0 3 * * * root /usr/local/bin/mysql-backup' | sudo tee /etc/cron.d/mysql-backup
sudo /usr/local/bin/mysql-backup && sudo ls -l /var/backups/mysql

প্রতিটি লাইনের একটা কারণ আছে:

  • umask 077 ডাম্পটাকে শুধু root-এর পড়ার যোগ্য করে (-rw-------), কারণ এতে আপনার সব ডেটা আছে।
  • pipefail-এর ফলে mysqldump ব্যর্থ হলে পুরো স্ক্রিপ্টই ব্যর্থ হয়। এটা না থাকলে gzip একটা ছোট্ট ফাঁকা আর্কাইভ লিখে সফল বলে জানাত। আমরা ইচ্ছে করে কমান্ড ভেঙেছি, আর স্ক্রিপ্ট ঠিক যেমন হওয়া উচিত, কোড 2 দিয়ে শেষ হয়েছে।
  • find … -mtime +14 -delete দুই সপ্তাহের কপি রাখে।
  • স্ক্রিপ্ট root হিসেবে চলে, তাই mysqldump সকেট দিয়ে লগ ইন করে আর কোনো ফাইলে পাসওয়ার্ড রাখতে হয় না।

যে ব্যাকআপ আপনি কখনো রিস্টোর করেননি, সেটা এখনো গোনার মধ্যে পড়ে না। একটা অস্থায়ী ডেটাবেসে রিস্টোর করে ডেটা দেখুন:

sudo mysql -e "CREATE DATABASE app_restore"
gunzip -c /var/backups/mysql/app-2026-10-25.sql.gz | sudo mysql app_restore
sudo mysql -e "SHOW TABLES FROM app_restore"
sudo mysql -e "DROP DATABASE app_restore"

আমাদের পরীক্ষায় রিস্টোর করা টেবিলে মূলটির মতোই একই সারি ছিল। একই ডিস্কের কপি সার্ভার হারালে আপনাকে রক্ষা করে না, তাই মাঝে মাঝে সেগুলো scp বা restic দিয়ে অন্য মেশিনে নিয়ে যান। Managed Backups এর ওপর পুরো সার্ভারের দৈনিক রিস্টোর পয়েন্ট যোগ করে।

কোন প্ল্যান

Micro (2 vCPU, 2 GB, 25 GB, $5/মাস) ওপরের মতো টিউন করা MySQL আর একটা ওয়েব অ্যাপ ধরে রাখে। ডেটাবেস নিজেই কয়েক গিগাবাইট ছাড়ালে 4 GB আর 35 GB-এর Small $8/মাসে buffer pool-কে 1 GB বা বেশি দিতে দেয়। দুটোই NAT প্ল্যান, আর ধাপ 3-এর SSH টানেল এগুলোতে চলে। ধাপ 4-এর জন্য নিজস্ব IPv4 লাগে: Micro-IP-এর দাম $10/মাস।

PostgreSQL পছন্দ? PostgreSQL গাইড একই ছকে লেখা। সব প্ল্যান VPS-এ আছে, আর পেমেন্ট হয় Base, Ethereum বা Polygon নেটওয়ার্কে USDT, USDC বা ETH-এ।

FAQ

MySQL নাকি MariaDB?

দুটোই Ubuntu 24.04-এর নিজস্ব রিপোজিটরিতে আছে: mysql-server দেয় MySQL 8.0, আর mariadb-server দেয় MariaDB 10.11। যেসব অ্যাপ "MySQL" চায়, তাদের বেশিরভাগই দুটোতেই চলে। আপনার অ্যাপের ডকুমেন্টেশনে যেটা বলা আছে সেটা নিন, আর কিছু না বলা থাকলে MySQL 8.0। এই গাইডে MySQL ব্যবহার হয়েছে।

MySQL-এর root পাসওয়ার্ড কী?

নেই। Ubuntu-তে MySQL-এর root অ্যাকাউন্ট সকেট অথেন্টিকেশন ব্যবহার করে: sudo mysql আপনাকে root হিসেবে ঢুকিয়ে দেয়, আর নেটওয়ার্ক দিয়ে কেউ root হিসেবে লগ ইন করতে পারে না। এভাবেই রাখুন আর অ্যাপগুলোর জন্য আলাদা ইউজার বানান।

পোর্ট 3306 কি ইন্টারনেটে খুলব?

না। খোলা ডেটাবেস পোর্ট সারাক্ষণ স্ক্যান হয় আর তাতে পাসওয়ার্ড আন্দাজের চেষ্টা চলে। নিজের কম্পিউটার থেকে SSH টানেল দিয়ে যুক্ত হোন। অন্য কোনো সার্ভারকে সরাসরি যুক্ত হতে হলে শুধু সেটার IP, MySQL আর ফায়ারওয়াল দুই জায়গাতেই, অনুমতি দিন।

MySQL-এর কতটা RAM লাগে?

ইনস্টলের ঠিক পরে নিজস্ব কোনো ডেটাবেস ছাড়াই MySQL 8.0 আমাদের টেস্ট সার্ভারে 383 MB নিচ্ছিল। Performance Schema বন্ধ করে আর মাঝারি buffer pool দিয়ে এটা 165 MB-তে নেমেছে। 2 GB-এর Micro প্ল্যান MySQL আর একটা অ্যাপ আরামে চালায়; এই টিউনিংয়ের পর ছোট সাইটের জন্য 1 GB-ও যথেষ্ট।

mysql_secure_installation কি চালাতেই হবে?

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

মন্তব্য

এখনো কোনো মন্তব্য নেই। প্রথম হোন।

একটি মন্তব্য দিন

মন্তব্য প্রকাশের আগে মডারেট করা হয়।