С чего начать Первые шаги трек · 15 ступеней
Linux Labs

PostgreSQL — доступ, pg_hba.conf, дамп и восстановление

12 мин Ubuntu 24.04 · PostgreSQL 16

PostgreSQL — реляционная СУБД: роли и базы, правила доступа pg_hba.conf, дамп pg_dump и восстановление pg_restore.

Шпаргалка

8 команд Версия для печати
  • sudo systemctl start postgresql в лабах служба выключена
  • pg_lsclusters версия, порт, статус
  • sudo -u postgres psql консоль суперпользователя
  • psql -h 127.0.0.1 -U appuser -d appdb вход по TCP с паролем
  • sudo -u postgres psql -c 'TABLE pg_hba_file_rules' правила доступа
  • sudo ss -tlnp | grep 5432 на каком адресе слушает
  • sudo -u postgres pg_dump -Fc -f /tmp/appdb.dump appdb
  • sudo -u postgres pg_restore -l /tmp/appdb.dump оглавление

Обзор

PostgreSQL — реляционная СУБД. Служба postgresql под systemd. В Ubuntu сервер называется кластером: 16/main — версия и имя. Данные — в /var/lib/postgresql/16/main, конфиги — в /etc/postgresql/16/main/, журнал — /var/log/postgresql/postgresql-16-main.log.

Внутри сервера свои учётные записи — роли. Роль postgres — суперпользователь. Роль и пользователь Linux — разные вещи: psql -U appuser входит ролью appuser, кем бы ты ни был в системе.

Как клиент попадает в базу

Сервер проверяет подключение по очереди, и у каждой проверки свой отказ:

Проверка Что смотрит Отказ
сеть слушает ли сервер адрес и порт или сокет Connection refused
правило есть ли строка в pg_hba.conf no pg_hba.conf entry
вход пароль или peer из этой строки authentication failed

psql без -h подключается через сокет /var/run/postgresql/.s.PGSQL.5432 — для него действуют строки local, по умолчанию peer. С -h 127.0.0.1 — по TCP, строки host и пароль.

Конфигурация

7

Два файла в /etc/postgresql/16/main/: postgresql.conf — параметры сервера, pg_hba.conf — кто и как может войти. Какие файлы и значения сервер прочитал на самом деле — SHOW hba_file;, SHOW listen_addresses;.

pg_hba.conf

pg_hba.conf — правила доступа, по строке на правило. В Ubuntu по умолчанию:

text
# TYPE  DATABASE  USER      ADDRESS        METHOD
local   all       postgres                 peer
local   all       all                      peer
host    all       all       127.0.0.1/32   scram-sha-256
host    all       all       ::1/128        scram-sha-256
Поле Что значит
TYPE local — через сокет, host — по TCP
DATABASE имя базы или all
USER роль или all
ADDRESS адрес клиента с маской; у local пусто
METHOD как проверять: peer, scram-sha-256, reject

peer пускает пользователя Linux только в роль с тем же именем, поэтому суперпользователь входит как sudo -u postgres psql. scram-sha-256 — пароль. reject — отказ без проверки.

Строки читаются сверху вниз, действует первая подходящая, остальные не смотрятся. Строка reject выше разрешающей закрывает доступ даже с верным паролем. Новое правило для конкретной базы и роли ставь выше общих.

Правку применяет sudo systemctl reload postgresql или SELECT pg_reload_conf();. Что сервер прочитал, показывает представление pg_hba_file_rules: номер строки, поля и столбец error. С ошибкой в файле сервер его не принимает и работает по старым правилам, а в журнале — pg_hba.conf was not reloaded.

Адрес и порт

По умолчанию listen_addresses = 'localhost' — только 127.0.0.1 и ::1, порт 5432. Чтобы принимать подключения из сети, нужны три вещи: адрес в listen_addresses ('*' — все), строка host для адреса клиента в pg_hba.conf и открытый порт в файрволе. listen_addresses меняется только через sudo systemctl restart postgresql: после reload параметр помечен pending_restart, а сервер слушает по-старому.

Свою настройку удобно держать отдельным файлом: postgresql.conf читает каталог conf.d рядом с собой (include_dir = 'conf.d'), и обновление пакета такой файл не трогает:

bash
echo "listen_addresses = '127.0.0.1'" \
  | sudo tee /etc/postgresql/16/main/conf.d/listen.conf
sudo systemctl restart postgresql
sudo ss -tlnp | grep 5432

conf.d читается после строки include_dir в конце postgresql.conf, и действует последнее значение. С listen_addresses = '*' в postgresql.conf и '127.0.0.1' в conf.d/listen.conf сервер слушает 127.0.0.1. Откуда взято значение и ждёт ли оно перезапуска, показывает pg_settings:

text
student@ubuntu:~$ sudo -u postgres psql -Atc "SELECT setting,
> sourcefile, sourceline, pending_restart FROM pg_settings
> WHERE name='listen_addresses'"
127.0.0.1|/etc/postgresql/16/main/conf.d/listen.conf|1|f

После правки файла и reload значение прежнее, pending_restart — t, а в журнале /var/log/postgresql/postgresql-16-main.log:

text
LOG:  parameter "listen_addresses" cannot be changed without restarting
  the server
LOG:  configuration file "/etc/postgresql/16/main/conf.d/listen.conf"
  contains errors; unaffected changes were applied

Каждую строку каждого файла с её судьбой показывает pg_file_settings (applied, error — например, setting could not be applied).

Директива Что делает Пример
listen_addresses postgresql.conf На каких адресах принимать TCP-подключения; '*' — на всех. Меняется только через restart. listen_addresses = '*'
port postgresql.conf Порт TCP и номер в имени сокета .s.PGSQL.5432. Меняется через restart. port = 5432
password_encryption postgresql.conf Как хранить новые пароли ролей; пара к методу scram-sha-256 в pg_hba.conf. password_encryption = scram-sha-256
max_connections postgresql.conf Сколько подключений разом; лишние получают too many clients. Меняется через restart. max_connections = 100
log_connections postgresql.conf Писать в журнал каждое подключение — видно, с какого адреса и какой ролью входили. log_connections = on
local / host pg_hba.conf Тип строки — подключение через сокет или по TCP. host appdb appuser 10.0.0.5/32 scram-sha-256
peer / scram-sha-256 / reject pg_hba.conf Метод проверки: имя пользователя Linux, пароль или отказ без проверки. local all postgres peer

Ничего не найдено. Попробуй запрос короче.

Рецепты

5

Роль и база для приложения

bash
sudo -u postgres psql -c "CREATE ROLE appuser LOGIN PASSWORD 'apppass'"
sudo -u postgres createdb -O appuser appdb
psql -h 127.0.0.1 -U appuser -d appdb -c 'SELECT current_user'

Новый пароль — ALTER ROLE appuser PASSWORD '…';, список ролей — \du в psql, баз — \l.

Пароль без ввода: ~/.pgpass

bash
echo '127.0.0.1:5432:appdb:appuser:apppass' > ~/.pgpass
chmod 600 ~/.pgpass
psql -h 127.0.0.1 -U appuser -d appdb

Строка — адрес:порт:база:роль:пароль, * подходит к любому значению. Режим — только 600: иначе psql пишет password file … has group or world access и файл пропускает. Переменная PGPASSWORD важнее файла.

Дамп: форматы

Логический дамп снимает pg_dump — команды и данные, из которых база создаётся заново. Роли в него не входят: их сохраняет pg_dumpall --globals-only.

Формат Команда Восстанавливает
простой SQL pg_dump -f appdb.sql appdb psql -f
custom pg_dump -Fc -f appdb.dump appdb pg_restore
каталог pg_dump -Fd -j 4 -f appdb.dir appdb pg_restore -j 4

Простой SQL читается глазами: CREATE TABLE, COPY с данными, setval для счётчиков. В начале и в конце — строки \restrict и \unrestrict со случайным ключом: защита psql от чужих команд в данных, так и должно быть. Формат custom сжат, начинается с байтов PGDMP и позволяет посмотреть оглавление и восстановить часть:

bash
sudo -u postgres pg_restore -l /tmp/appdb.dump
text
216; 1259 16387 TABLE public orders appuser
215; 1259 16386 SEQUENCE public orders_id_seq appuser
3396; 0 16387 TABLE DATA public orders appuser
3404; 0 0 SEQUENCE SET public orders_id_seq appuser

Над оглавлением — шапка архива: Archive created at 2026-10-20 10:05:53 UTC, dbname: appdb и версии сервера. По ней видно, какая это копия и откуда. Данные одной таблицы без восстановления печатает pg_restore -f - -t orders /tmp/appdb.dump — определение таблицы и строки COPY.

Восстановить в новую базу

bash
sudo -u postgres createdb -O appuser appdb_copy
sudo -u postgres pg_restore -d appdb_copy /tmp/appdb.dump
sudo -u postgres psql -d appdb_copy -c 'SELECT count(*) FROM orders'

Новая пустая база — без конфликтов: код 0. Счётчик id дамп восстанавливает строкой setval('public.orders_id_seq', 3, true) — следующая вставка получит id 4.

Владельцы. createdb -O appuser задаёт владельца самой базы. Владельцев таблиц pg_restore от postgres берёт из архива — строками ALTER TABLE … OWNER TO appuser, и такая роль должна существовать. С --no-owner владельцем станет тот, кто восстанавливает, а с --no-owner --role=r — роль r.

Ключ pg_restore Что делает
-l только оглавление архива
-L список восстановить строки оглавления из файла
-f - напечатать SQL вместо записи в базу
--exit-on-error остановиться на первой ошибке
--single-transaction всё или ничего: при ошибке откат
--clean --if-exists удалить объекты перед созданием
--create -d postgres создать базу с именем из дампа
--no-owner --role=r владельцем объектов станет роль r

Сверить копию с источником

sql
SELECT count(*) FROM orders;
SELECT md5(string_agg(t::text, ',' ORDER BY id)) FROM orders t;
SELECT last_value FROM orders_id_seq;

Одинаковые число строк, сумма выборки и значение счётчика в источнике и копии — данные совпадают. Владельца таблиц покажет \dt.

Неполадки

7

Connection refused

connection to server at "127.0.0.1", port 5432 failed: Connection refused и Is the server running on that host and accepting TCP/IP connections?. Служба не запущена (pg_lsclusters, systemctl status postgresql) или не слушает этот адрес: sudo ss -tlnp | grep 5432, SHOW listen_addresses;. Через сокет то же выглядит как No such file or directory и Is the server running locally….

no pg_hba.conf entry

FATAL: no pg_hba.conf entry for host "127.0.0.1", user "appuser", database "appdb", no encryption — ни одна строка не подошла к этому адресу, базе и роли. Сообщение приходит дважды: psql пробует подключиться с SSL, потом без. Добавь строку host appdb appuser <адрес>/32 scram-sha-256, reload и проверь pg_hba_file_rules.

pg_hba.conf rejects connection for host … — подошла строка reject, она стоит выше разрешающей.

password authentication failed

Правило нашлось, пароль не подошёл. Для роли, которой нет, сервер пишет то же самое — проверь \du. Пароль задаёт ALTER ROLE … PASSWORD; помни, что PGPASSWORD перекрывает ~/.pgpass. fe_sendauth: no password supplied — пароль спросили, а взять его неоткуда.

Peer authentication failed

psql -U appuser без -h идёт через сокет, а там правило peer: пользователь Linux должен называться как роль. Подключайся с -h 127.0.0.1 и паролем или sudo -u postgres psql. role "student" does not exist — psql без -U берёт роль по имени пользователя Linux.

Правка pg_hba.conf не действует

Файл не перечитан или перечитан с ошибкой — тогда работают старые правила, а pg_reload_conf() всё равно возвращает t. Ошибку покажет SELECT line_number, error FROM pg_hba_file_rules WHERE error IS NOT NULL;, в журнале — pg_hba.conf was not reloaded.

pg_restore: relation "…" already exists

Восстановление в базу, где объекты уже есть: ошибка на каждом, в конце pg_restore: warning: errors ignored on restore: 4, код 1, и часть данных могла лечь поверх. Восстанавливай в новую пустую базу. --single-transaction при первой ошибке откатывает всё. --create -d postgres при живой базе с тем же именем — database "appdb" already exists.

input file appears to be a text format dump

pg_restore получил простой SQL — восстанавливай его psql -f. Обратная ошибка: psql -f на custom-дампе — The input is a PostgreSQL custom-format dump. Use the pg_restore command-line client….

Опасно

2

trust в pg_hba.conf

trust пускает без пароля любого, кто подходит под строку. host all all 0.0.0.0/0 trust открывает все базы каждому, кто дотянется до порта.

pg_restore --clean в рабочую базу

--clean удаляет объекты перед созданием. В рабочей базе это замена живых данных старыми из дампа. Сначала восстанови в отдельную базу и сверь.

Термины

7
pg_hba.conf
Файл правил доступа PostgreSQL: тип подключения, база, роль, адрес и способ проверки. Действует первая подходящая строка; нет подходящей — отказ «no pg_hba.conf entry». Ещё встречается в: Unix-сокеты
роль PostgreSQL PostgreSQL role
Учётная запись внутри PostgreSQL; роль с правом LOGIN — пользователь базы. С пользователями Linux не связана, кроме проверки peer.
peer-проверка peer authentication
Вход в PostgreSQL через локальный сокет: сервер узнаёт у ядра, какой пользователь Linux подключился, и пускает его только в роль с тем же именем. Отсюда sudo -u postgres psql.
логический дамп logical dump
Копия базы в виде команд и данных (CREATE, COPY), которую снимает pg_dump; восстанавливается в базу той же или более новой версии. Роли в него не входят.
формат custom (-Fc) custom format (-Fc)
Сжатый архив pg_dump, который читает только pg_restore: можно посмотреть оглавление (-l) и восстановить выборочно. Файл начинается с байтов PGDMP.
последовательность (sequence)
Счётчик PostgreSQL, из которого берутся новые id столбца serial; дамп хранит его значение через setval. Отставший счётчик после восстановления даёт duplicate key на следующей вставке.
файл ~/.pgpass ~/.pgpass file
Пароли PostgreSQL для клиента: строки адрес:порт:база:роль:пароль, режим 0600 — иначе файл пропускается с предупреждением. Переменная PGPASSWORD важнее файла.

См. также

Загрузка…