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 может входить только через локальный сокет. Запускайте его, если нужен предлагаемый компонент проверки сложности паролей, иначе можно пропустить.

Комментарии

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

Оставить комментарий

Комментарии проходят модерацию перед публикацией.