База данных на VPS: MySQL или PostgreSQL без утечек в интернет

Как поставить MySQL или PostgreSQL на VPS, оставить базу доступной только локально, не попасть в ловушку Docker с портами и настроить резервные копии дампом.

Команда EGN 8 мин чтения
База данных на VPS: MySQL или PostgreSQL без утечек в интернет
Содержание 19
  1. Коротко
  2. Почему база опасна наружу
  3. PostgreSQL: шаги
  4. MySQL: шаги
  5. Ловушка Docker
  6. Доступ с компьютера: туннель вместо открытого порта
  7. Резервные копии дампом
  8. Примеры
  9. Как восстановить из дампа
  10. Симптом → причина → решение
  11. Пример: отдельный пользователь с правом только чтения
  12. Как сделать в кабинете EGN
  13. Частые ошибки
  14. Итог
  15. Вопросы и ответы
  16. Какую базу выбрать: PostgreSQL или MySQL?
  17. Можно ли открыть порт базы только для своего IP?
  18. Нужен ли отдельный пользователь для каждого приложения?
  19. Как часто делать дамп?

База данных на VPS — самая частая причина утечек в игровых и веб-проектах. Люди ставят PostgreSQL или MySQL, открывают порт, чтобы подключиться с компьютера, и забывают закрыть его. Через несколько дней в логах появляются сотни попыток входа. Правило простое: база слушает только свой сервер, а доступ извне, если он нужен, идёт через туннель.

Коротко

Поставьте PostgreSQL или MySQL из репозитория Ubuntu, оставьте адрес прослушивания 127.0.0.1 и не открывайте порт 5432 или 3306 в фаерволе. Если базу запускаете в Docker, публикуйте порт с адресом 127.0.0.1:5432:5432, иначе Docker обойдёт правила ufw. Дампы делайте по расписанию командами pg_dump или mysqldump.

Почему база опасна наружу

Базы данных рассчитаны на доверенную сеть, а не на интернет. У них есть логины и пароли, но автоматические сканеры каждый день перебирают стандартные учётные записи. Если пароль слабый или его вообще нет, база попадает в ботнеты за часы.

Опасность не в том, что база открыта, а в том, что её не видно владельцу. Поэтому проверка порта — обязательный шаг после установки.

PostgreSQL: шаги

  1. Установите сервер:
Терминал
sudo apt update
sudo apt install -y postgresql
  1. Проверьте, на каких адресах слушает PostgreSQL. По умолчанию в Ubuntu это только localhost, поэтому строка listen_addresses в конфиге закомментирована (значение по умолчанию localhost). Если она раскомментирована и содержит '*', база слушает все адреса:
Терминал
sudo grep -n "listen_addresses" /etc/postgresql/*/main/postgresql.conf
sudo ss -tlnp | grep 5432

Ожидаемый результат — адрес 127.0.0.1:5432 или [::1]:5432. Если там 0.0.0.0:5432, исправьте listen_addresses и перезапустите сервер.

  1. Создайте пользователя и базу. Пароль замените на свой длинный, в примере он условный:
SQL
CREATE USER app WITH PASSWORD 'замените-на-длинный-пароль';
CREATE DATABASE app OWNER app;

Выполняется от имени пользователя postgres: sudo -u postgres psql.

  1. Приложение подключается по строке вида:
server.properties
DATABASE_URL=postgresql://app:замените-на-длинный-пароль@127.0.0.1:5432/app

MySQL: шаги

  1. Установите сервер:
Терминал
sudo apt update
sudo apt install -y mysql-server
  1. Проверьте адрес прослушивания в конфиге. Откройте /etc/mysql/mysql.conf.d/mysqld.cnf и найдите строку bind-address. Для локальной базы она должна быть 127.0.0.1. Затем перезапустите сервер:
Терминал
sudo systemctl restart mysql
sudo ss -tlnp | grep 3306
  1. Создайте базу и пользователя, которому доступ разрешён только с localhost:
SQL
CREATE DATABASE app;
CREATE USER 'app'@'localhost' IDENTIFIED BY 'замените-на-длинный-пароль';
GRANT ALL PRIVILEGES ON app.* TO 'app'@'localhost';
Схема: база доступна только локально, опубликованный порт Docker обходит ufw
Схема: база доступна только локально, опубликованный порт Docker обходит ufw

Ловушка Docker

Docker записывает свои правила в iptables раньше, чем их применяет ufw. Поэтому правило ufw deny 3306 не спасает, если контейнер опубликовал порт командой -p 3306:3306. Порт открывается на всех адресах, и база оказывается в интернете.

Исправление одно: указывать адрес в публикации портов. В docker-compose.yml это выглядит так:

YAML
services:
  db:
    image: postgres:16
    ports:
      - "127.0.0.1:5432:5432"

Тогда порт доступен только с самого VPS, а приложение, которое живёт в той же сети Docker, подключается по имени сервиса. Подробнее про связку контейнеров в статье Docker Compose на VPS для нескольких сервисов.

Если базе снаружи не нужен доступ, лучше не публиковать порт вовсе. Уберите блок ports полностью. В режиме «Свои правила» облачного фаервола (вкладка «Фаервол» карточки VPS) порт базы тоже не нужно разрешать, но не полагайтесь только на него и проверяйте ss -tlnp.

Доступ с компьютера: туннель вместо открытого порта

Если нужно подключиться к базе со своего компьютера, не открывайте порт. Используйте SSH-туннель:

Терминал
ssh -L 5432:127.0.0.1:5432 user@ваш-vps

После этого в клиенте БД подключайтесь к 127.0.0.1:5432 на своём компьютере. Трафик пойдёт через защищённое SSH-соединение.

Резервные копии дампом

Сначала определите, что вы защищаете: данные или структуру. Для ежедневных копий подойдёт дамп:

Терминал
sudo -u postgres pg_dump app | gzip | sudo tee /var/backups/db/app-$(date +%F).sql.gz > /dev/null

Для MySQL используйте --single-transaction, чтобы дамп InnoDB-таблиц был согласованным без остановки записи:

Терминал
sudo mysqldump --single-transaction app | gzip | sudo tee /var/backups/db/app-$(date +%F).sql.gz > /dev/null

Каталог для дампов заранее создайте и закройте от чужих (sudo mkdir -p /var/backups/db && sudo chmod 700 /var/backups/db). Перенаправление > выполняет ваша оболочка, а не sudo, поэтому запись идёт через sudo tee. Копии храните не на том же диске, а в S3 или через restic, как описано в статье Бэкапы VPS: снапшоты, S3 и restic.

Снапшот VPS тоже защищает базу, но он снимается на работающем сервере, как после внезапного отключения питания. Для баз данных надёжнее ненадолго остановить запись или использовать дамп: об этом прямо сказано в подсказке на вкладке «Бэкапы» кабинета EGN (ниже).

Примеры

Приложение и база на одном VPS. Самый частый вариант. База слушает 127.0.0.1, приложение подключается локально, снаружи открыты только 80 и 443.

Статистика игрового сервера. Плагин или скрипт пишет данные в базу локально, а сайт статистики читает их через то же приложение. Порт базы не нужен наружу.

Разработчик хочет работать с базой. Используйте SSH-туннель, как описано выше, и не открывайте порт для всех.

Как восстановить из дампа

Копия без проверки восстановления — это не резерв. Восстановите дамп на отдельной базе и сравните количество строк в главных таблицах. Для PostgreSQL:

Терминал
sudo -u postgres createdb app_test
gunzip -c /var/backups/db/app-2026-11-13.sql.gz | sudo -u postgres psql app_test
sudo -u postgres psql -d app_test -c "SELECT count(*) FROM users;"

Для MySQL:

Терминал
sudo mysql -e "CREATE DATABASE app_test;"
gunzip -c /var/backups/db/app-2026-11-13.sql.gz | sudo mysql app_test
sudo mysql -e "SELECT COUNT(*) FROM app_test.users;"

Имя таблицы users подставьте своё. Если числа совпадают с основной базой на момент дампа, копия пригодна. После проверки удалите тестовую базу, чтобы не занимать место.

Симптом → причина → решение

Симптом Частая причина Что сделать
FATAL: password authentication failed Неверный пароль или пользователь не имеет доступа к базе Проверьте строку DATABASE_URL, при необходимости задайте пароль через ALTER USER
Connection refused на 5432 или 3306 Сервер не запущен или слушает другой адрес systemctl status postgresql или mysql, затем ss -tlnp
База работает медленно после роста данных Нет индексов или таблица без ограничения выборки Смотрите медленные запросы в журнале и добавляйте индексы
Диск заполнился Логи и дампы хранятся на системном диске Перенесите дампы в S3 и настройте ротацию логов
Docker-контейнер базы не виден извне, хотя должен Порт опубликован только на 127.0.0.1 Это правильная схема: подключайтесь через туннель или из той же сети Docker
После перезагрузки база не стартует Служба не включена в автозапуск sudo systemctl enable postgresql или mysql

Пример: отдельный пользователь с правом только чтения

Для отчётов или аналитики создайте отдельного пользователя, который не может менять данные. В PostgreSQL это выглядит так:

SQL
CREATE USER reporter WITH PASSWORD 'замените-на-длинный-пароль';
GRANT CONNECT ON DATABASE app TO reporter;
GRANT USAGE ON SCHEMA public TO reporter;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO reporter;

Такой пользователь подключается через SSH-туннель и не может удалить данные, даже если его строка подключения утекла.

Как сделать в кабинете EGN

Резервные копии VPS в кабинете EGN находятся на вкладке «Бэкапы» карточки сервера. Там есть два вида копий: «Горячее» с быстрым восстановлением и «Холодное», которое дешевле, но восстанавливается медленнее. Ниже указано, что копия снимается на работающем сервере и поэтому для базы лучше дополнительно сделать дамп.

Вкладка «Бэкапы» в кабинете: горячее и холодное хранение копий
Вкладка «Бэкапы» в кабинете: горячее и холодное хранение копий

На этой же вкладке есть блок «Копии по расписанию». Пока он выключен, копии делаются только вручную, о них легко забыть. Проверьте этот пункт сразу после заказа, а не через месяц.

Частые ошибки

  • Порт 5432 или 3306 открыт в ufw. Закройте его: sudo ufw status покажет правила. Если доступ нужен одному IP, разрешайте только его.
  • Слабый или пустой пароль пользователя базы. Задайте длинный пароль и ограничьте пользователя только его базой, не выдавайте ALL PRIVILEGES на всё.
  • -p 3306:3306 в Docker. Порт публикуется на все адреса и обходит ufw. Указывайте 127.0.0.1:.
  • Дамп без проверки. Раз в неделю восстанавливайте копию на тестовой базе. Непроверенный дамп — это надежда, а не резерв.
  • Дамп хранится на том же VPS. При потере сервера он пропадает вместе с базой.
  • Пароль в git. Держите строку подключения в файле окружения с правами 600.

Итог

База данных на VPS работает безопасно, если слушает только локальный адрес, порт не публикуется наружу, а дампы уходят за пределы сервера. Проверяйте ss -tlnp после каждой установки и каждой правки Docker-файла. Если база нужна вашим друзьям или внешнему сервису, используйте туннель или отдельный VPS с ограниченным доступом, а не открытый порт.

Вопросы и ответы

Какую базу выбрать: PostgreSQL или MySQL?

Для нового проекта чаще берут PostgreSQL за строгость типов и расширения. MySQL подходит, если приложение или хостинг уже ориентированы на него.

Можно ли открыть порт базы только для своего IP?

Можно правилом ufw с указанием адреса, например sudo ufw allow from 203.0.113.10 to any port 5432 proto tcp. Но проще и безопаснее SSH-туннель.

Нужен ли отдельный пользователь для каждого приложения?

Да. Каждому приложению выдавайте свою учётную запись с правами только на свою базу.

Как часто делать дамп?

Для активного проекта раз в сутки, для редко меняющихся данных раз в неделю. Частоту выбирайте так, чтобы потеря одного дня не была катастрофой.

Сервер под игры за пару минут — egnetwork.ru

Читать далее

Вся рубрика →