EQVPS
КабінетПочати

Як встановити MySQL на VPS: користувачі, безпечний віддалений доступ, менше пам'яті та бекапи

Ставимо MySQL 8.0 на VPS з Ubuntu 24.04, створюємо базу й користувача для застосунку, підключаємося зі свого комп'ютера, не відкриваючи порт 3306, знижуємо споживання пам'яті в простої з 383 МБ до 165 МБ і щоночі робимо бекап скриптом, який гучно падає в разі помилки.

Встановлення 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 МБ. Більшу частину забирає 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

Після перезапуску MySQL займав 165 МБ. Буферний пул кешує дані й індекси, і 256 МБ підходять серверу на 2 ГБ, на якому працює й застосунок. Збільште його, якщо база — головне на сервері й виросла більшою за кеш. 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 ГБ, 25 ГБ, $5/міс) тримає MySQL з таким налаштуванням плюс вебзастосунок. Якщо сама база виросте за кілька гігабайтів, Small з 4 ГБ і 35 ГБ за $8/міс дасть змогу віддати буферному пулу 1 ГБ і більше. Обидва тарифи з 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 МБ без власних баз. Після вимкнення Performance Schema і скромного буферного пулу — 165 МБ. Тариф Micro на 2 ГБ спокійно тягне MySQL і застосунок, а після такого налаштування й 1 ГБ вистачить для невеликого сайту.

Чи потрібно запускати mysql_secure_installation?

В Ubuntu 24.04 більшу частину його роботи вже зроблено. У нашому свіжому встановленні не було анонімних користувачів і тестової бази, а root може входити лише через локальний сокет. Запускайте його, якщо потрібен компонент перевірки складності паролів, інакше можна пропустити.

Коментарі

Поки немає коментарів. Будьте першим.

Залишити коментар

Коментарі проходять модерацію перед публікацією.