EQVPS

نصب MySQL روی VPS: کاربران، دسترسی امن از راه دور، رم کمتر و پشتیبان‌گیری

MySQL 8.0 را روی VPS با Ubuntu 24.04 نصب کنید، یک پایگاه داده و کاربر برای برنامه بسازید، بدون باز کردن پورت 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 برای اتصال‌های معمولی و 127.0.0.1:33060 برای پروتکل جدیدتر X در MySQL. هنوز هیچ چیز از بیرون در دسترس نیست.

2. یک پایگاه داده و کاربر بسازید

حساب root در MySQL روی Ubuntu از احراز هویت سوکت استفاده می‌کند، پس 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. رم کمتری مصرف کنید

در حالت بیکار و بدون دادهٔ خودش، 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 داده‌ها و ایندکس‌های شما را کش می‌کند و 256 MB برای سرور 2 GB که برنامه را هم اجرا می‌کند مناسب است. اگر پایگاه داده کار اصلی سرور است و از اندازهٔ کش بزرگ‌تر شده، آن را بالا ببرید. 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 تنظیم‌شده مثل بالا را به‌علاوهٔ یک برنامهٔ وب جا می‌دهد. اگر خود پایگاه داده از چند گیگابایت بیشتر شود، Small با 4 GB و 35 GB و ماهی $8 به شما اجازه می‌دهد 1 GB یا بیشتر به buffer pool بدهید. هر دو پلن NAT هستند و تونل SSH قدم 3 روی آن‌ها کار می‌کند. قدم 4 به IPv4 اختصاصی نیاز دارد: Micro-IP ماهی $10 است.

PostgreSQL را ترجیح می‌دهید؟ راهنمای PostgreSQL همین نقشه را دنبال می‌کند. همهٔ پلن‌ها در VPS هستند و پرداخت با USDT، USDC یا ETH روی شبکه‌های Base، Ethereum یا Polygon انجام می‌شود.

پرسش‌های متداول

MySQL یا MariaDB؟

هر دو در مخزن‌های خود Ubuntu 24.04 هستند: mysql-server نسخهٔ MySQL 8.0 و mariadb-server نسخهٔ MariaDB 10.11 را نصب می‌کند. بیشتر برنامه‌هایی که «MySQL» می‌خواهند با هر دو کار می‌کنند. همان را به کار ببرید که مستندات برنامه‌تان می‌گوید، و اگر فرقی ندارد MySQL 8.0 را. این راهنما از MySQL استفاده می‌کند.

رمز root در MySQL چیست؟

رمزی ندارد. در Ubuntu حساب root در MySQL از احراز هویت سوکت استفاده می‌کند: sudo mysql شما را به‌عنوان root وارد می‌کند و هیچ‌کس نمی‌تواند از راه شبکه با root وارد شود. همین‌طور بگذارید و برای برنامه‌ها کاربرهای جداگانه بسازید.

آیا پورت 3306 را به روی اینترنت باز کنم؟

نه. پورت‌های باز پایگاه داده مدام اسکن می‌شوند و زیر حدس رمز قرار می‌گیرند. از کامپیوتر خودتان با تونل SSH وصل شوید. اگر سرور دیگری باید مستقیم وصل شود، فقط IP همان سرور را، هم در MySQL و هم در فایروال، مجاز کنید.

MySQL چقدر رم لازم دارد؟

درست بعد از نصب، MySQL 8.0 روی سرور آزمایشی ما بدون هیچ پایگاه داده‌ای 383 MB مصرف می‌کرد. با خاموش کردن Performance Schema و یک buffer pool متوسط به 165 MB رسید. پلن Micro با 2 GB، MySQL و یک برنامه را راحت اجرا می‌کند؛ بعد از این تنظیم برای یک سایت کوچک 1 GB هم کافی است.

آیا لازم است mysql_secure_installation را اجرا کنم؟

در Ubuntu 24.04 بیشتر کارهای آن از قبل انجام شده است. نصب تازهٔ ما نه کاربر ناشناس داشت و نه پایگاه دادهٔ آزمایشی، و root فقط از راه سوکت محلی وارد می‌شود. اگر بخش بررسی قدرت رمز آن را می‌خواهید اجرایش کنید؛ در غیر این صورت می‌توانید از آن بگذرید.

نظرات

هنوز نظری نیست. اولین نفر باشید.

یک نظر بگذارید

نظرات پیش از نمایش بررسی می‌شوند.