Перейти к содержимому
VDS · Базы данных

Пользователи и права в базе

Как завести отдельного пользователя под каждое приложение в MySQL и PostgreSQL, выдать минимальные права и проверить, что лишнего нет.

Обновлено 23 августа 2026 г.

Приложение, работающее от root или postgres, при первой же уязвимости отдаёт злоумышленнику все базы на машине. Отдельный пользователь с правами только на свою схему ограничивает ущерб одним проектом.

MySQL и MariaDB

Пользователь здесь — это пара «имя и хост», и это главный источник путаницы:

CREATE USER 'shop'@'localhost' IDENTIFIED BY 'длинный-случайный-пароль';
GRANT SELECT, INSERT, UPDATE, DELETE ON shop.* TO 'shop'@'localhost';
FLUSH PRIVILEGES;

'shop'@'localhost' и 'shop'@'%' — два разных пользователя с разными паролями. Записи с хостом % не создавайте без необходимости: она разрешает вход с любого адреса.

Права на структуру нужны только на время миграций:

GRANT CREATE, ALTER, DROP, INDEX, REFERENCES ON shop.* TO 'shop_migrate'@'localhost';

Разделять роль приложения и роль миграций — хорошая практика: обычный запрос тогда физически не может уронить таблицу.

Проверка:

SELECT user, host FROM mysql.user;
SHOW GRANTS FOR 'shop'@'localhost';

Смена пароля и удаление:

ALTER USER 'shop'@'localhost' IDENTIFIED BY 'новый-пароль';
DROP USER 'shop'@'localhost';

PostgreSQL

Роль и её права на базу и схему:

CREATE ROLE shop WITH LOGIN PASSWORD 'длинный-случайный-пароль';
CREATE DATABASE shop OWNER shop;
REVOKE ALL ON DATABASE shop FROM PUBLIC;

Для роли только на чтение (отчёты, аналитика, панель мониторинга):

CREATE ROLE reader WITH LOGIN PASSWORD '...';
GRANT CONNECT ON DATABASE shop TO reader;
GRANT USAGE ON SCHEMA public TO reader;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO reader;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT SELECT ON TABLES TO reader;

Последняя строка обязательна: без неё роль не увидит таблицы, созданные после выдачи прав, и через месяц отчёты сломаются на новых данных.

Проверка:

\du
\l
\dp

Что должно быть закрыто

  • Ни одна прикладная роль не является суперпользователем.
  • У каждого проекта своя база и свой пользователь.
  • Пароли длинные и случайные, разные у разных проектов.
  • Вход снаружи разрешён только тем адресам, которым он нужен — удалённое подключение.
  • В MySQL нет анонимных пользователей и тестовой базы: это делает mariadb-secure-installation.

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

СимптомПричина
Access denied при верном паролеСовпало другое правило по хосту, например ''@'localhost'
Права выданы, но SELECT не работаетВ PostgreSQL нет USAGE ON SCHEMA
Новая таблица не видна ролиНе заданы DEFAULT PRIVILEGES
Приложение всё удалило при сбое миграцииУ прикладной роли были права DROP
Пароль виден в истории командЗадавайте пароли из файла, чистите ~/.mysql_history

Пароли базы храните в файле окружения службы с правами 600, а не в коде. При компрометации меняется одна строка и делается перезапуск, а не пересборка всего проекта.