VPSРейтинг
Базы данныхМарт 2026 · 14 мин чтения

PostgreSQL на VPS: установка, настройка и оптимизация на Ubuntu

PostgreSQL — самая мощная реляционная СУБД с открытым кодом. Установим актуальную версию из официального репозитория, настроим параметры под ваш VPS, создадим базу и пользователей, настроим резервное копирование и научимся находить медленные запросы через pg_stat_statements.

1. Установка PostgreSQL 16 из официального репозитория

Ubuntu 22.04 по умолчанию предлагает PostgreSQL 14 — устаревшую версию. Устанавливаем из официального PGDG-репозитория, где всегда актуальные версии.

Требования к VPS

Минимум 1 ГБ RAM. Для комфортной работы — 2 ГБ и более. Диск — NVMe/SSD обязателен для хорошей производительности. Виртуализация — KVM или любая другая (PostgreSQL не требует Docker).

Шаг 1: добавить репозиторий PostgreSQL
# Установить зависимости
apt install -y curl ca-certificates

# Создать директорию для ключей
install -d /usr/share/postgresql-common/pgdg

# Скачать ключ репозитория
curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail \
  https://www.postgresql.org/media/keys/ACCC4CF8.asc

# Добавить репозиторий
sh -c 'echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] \
  https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" \
  > /etc/apt/sources.list.d/pgdg.list'
Шаг 2: установить PostgreSQL 16
apt update
apt install -y postgresql-16 postgresql-client-16

# Проверить статус
systemctl status postgresql@16-main

После установки PostgreSQL уже запущен и включён в автозапуск. Данные хранятся в /var/lib/postgresql/16/main/, конфиги — в /etc/postgresql/16/main/.

2. Первые шаги: подключение и смена пароля

После установки создаётся системный пользователь postgres и одноимённая суперпользовательская роль в PostgreSQL. Пароля по умолчанию нет — подключение только через sudo -u postgres psql.

Подключиться к PostgreSQL и сменить пароль суперпользователя
# Войти в psql от имени postgres
sudo -u postgres psql

# Внутри psql — установить пароль:
ALTER USER postgres WITH PASSWORD 'СЛОЖНЫЙ_ПАРОЛЬ_ЗДЕСЬ';

# Выйти
\q
Полезные psql-команды для ориентации
sudo -u postgres psql

\l          -- список всех баз данных
\du         -- список пользователей и ролей
\c mydb     -- переключиться на базу mydb
\dt         -- список таблиц в текущей базе
\d users    -- структура таблицы users
\q          -- выход

Метод аутентификации peer

По умолчанию подключение через sudo -u postgres psql использует метод peer — PostgreSQL доверяет системному пользователю без пароля. Это удобно для локального управления. Для приложений и удалённых клиентов используется метод scram-sha-256 с паролем.

3. Создание пользователей и баз данных

Хорошая практика — каждое приложение работает со своим пользователем и своей базой. Никогда не подключайте приложения под суперпользователем postgres.

Создать пользователя и базу

Вариант 1: через командную строку
# Создать пользователя с паролем
sudo -u postgres createuser --pwprompt appuser

# Создать базу данных, владелец — appuser
sudo -u postgres createdb --owner=appuser myapp_db
Вариант 2: через psql (SQL-командами)
sudo -u postgres psql

-- Создать пользователя
CREATE USER appuser WITH PASSWORD 'ПАРОЛЬ';

-- Создать базу данных
CREATE DATABASE myapp_db OWNER appuser ENCODING 'UTF8' LC_COLLATE 'ru_RU.UTF-8' LC_CTYPE 'ru_RU.UTF-8' TEMPLATE template0;

-- Выдать права (нужно если база создана без --owner)
GRANT ALL PRIVILEGES ON DATABASE myapp_db TO appuser;

PostgreSQL 15+: изменения в правах на схему public

Начиная с PostgreSQL 15 право CREATE в схеме public по умолчанию отозвано у всех кроме суперпользователя. После создания базы выполните:

Выдать права на схему public (PostgreSQL 15+)
sudo -u postgres psql -d myapp_db

GRANT ALL ON SCHEMA public TO appuser;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO appuser;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO appuser;

Проверить подключение

Подключиться под новым пользователем
psql -h localhost -U appuser -d myapp_db

# При запросе пароля — введите пароль, заданный при создании пользователя

Connection string для приложений

# .env или конфиг приложения
DATABASE_URL=postgresql://appuser:ПАРОЛЬ@localhost:5432/myapp_db

# Python (psycopg2/SQLAlchemy)
postgresql+psycopg2://appuser:ПАРОЛЬ@localhost/myapp_db

# Node.js (pg/Prisma)
postgresql://appuser:ПАРОЛЬ@localhost:5432/myapp_db

4. Оптимизация postgresql.conf под ваш VPS

Дефолтные настройки PostgreSQL рассчитаны на сервер с 1 ГБ RAM. Подберём параметры под реальный объём памяти вашего VPS. Конфиг: /etc/postgresql/16/main/postgresql.conf.

Параметр1 ГБ RAM2 ГБ RAM4 ГБ RAMЧто делает
shared_buffers256MB512MB1GBКэш данных PostgreSQL. 25% RAM.
work_mem4MB8MB16MBПамять на сортировку/хэш на операцию. Умножать на max_connections.
maintenance_work_mem64MB128MB256MBVACUUM, CREATE INDEX. Можно побольше.
effective_cache_size512MB1GB2GBПодсказка планировщику: сколько данных в кэше ОС + PG.
wal_buffers8MB16MB16MBБуфер WAL. 1/32 от shared_buffers, но не менее 8 МБ.
max_connections100100150Максимум соединений. Используйте пул в приложении.
checkpoint_completion_target0.90.90.9Размазывает запись чекпоинта. 0.9 — всегда.

Пример конфига для VPS с 2 ГБ RAM

/etc/postgresql/16/main/postgresql.conf — добавить/изменить
# ── Память ───────────────────────────────────────────────
shared_buffers = 512MB               # 25% от 2 ГБ
work_mem = 8MB                       # на каждую операцию сортировки
maintenance_work_mem = 128MB         # VACUUM, CREATE INDEX
effective_cache_size = 1GB           # ~50% RAM

# ── Соединения ───────────────────────────────────────────
max_connections = 100

# ── WAL и чекпоинты ──────────────────────────────────────
wal_buffers = 16MB
checkpoint_completion_target = 0.9

# ── Логирование медленных запросов (рекомендуется) ───────
log_min_duration_statement = 1000    # запросы дольше 1 секунды
log_line_prefix = '%t [%p] %u@%d '  # метаданные в логе
Применить изменения
# Проверить синтаксис конфига
sudo -u postgres pg_ctlcluster 16 main status

# Перезапустить PostgreSQL (нужно при изменении shared_buffers)
systemctl restart postgresql@16-main

# Или перечитать конфиг без рестарта (для большинства параметров)
sudo -u postgres psql -c "SELECT pg_reload_conf();"

# Проверить, что параметры применились
sudo -u postgres psql -c "SHOW shared_buffers; SHOW work_mem;"

Автоматический расчёт параметров

Онлайн-калькулятор pgtune.leopard.in.ua генерирует postgresql.conf под вашу конфигурацию: укажите RAM, число CPU, тип диска (SSD/HDD) и тип нагрузки (OLTP, DWH, Web). Хорошая отправная точка.

5. Удалённый доступ: pg_hba.conf и UFW

По умолчанию PostgreSQL слушает только локальный сокет. Если приложение на другом сервере или нужно подключиться из IDE — настроим удалённый доступ безопасно.

Шаг 1: изменить listen_addresses

/etc/postgresql/16/main/postgresql.conf
# Слушать на всех интерфейсах (или укажите конкретный IP)
listen_addresses = '*'

Шаг 2: настроить pg_hba.conf

Файл /etc/postgresql/16/main/pg_hba.conf контролирует, кто и как может подключиться. Правила проверяются сверху вниз.

/etc/postgresql/16/main/pg_hba.conf — добавить строку
# Формат: TYPE  DATABASE  USER  ADDRESS  METHOD

# Локальные соединения (без изменений):
local   all       postgres                    peer
local   all       all                         md5

# Удалённый доступ — только с конкретного IP приложения:
host    myapp_db  appuser   1.2.3.4/32        scram-sha-256

# Если нужен доступ из подсети (например, все серверы в 10.0.0.0/24):
# host  myapp_db  appuser   10.0.0.0/24       scram-sha-256

Шаг 3: открыть порт в UFW

Открыть порт 5432 только для конкретного IP
# Только для IP приложения:
ufw allow from 1.2.3.4 to any port 5432

# Проверить правила:
ufw status

# Перезапустить PostgreSQL:
systemctl restart postgresql@16-main
scram-sha-256Рекомендуется

Современный метод с хэшированием пароля. Используйте его по умолчанию.

md5Устарел

MD5-хэш пароля. Поддерживается для совместимости, но слабее scram-sha-256.

trustТолько localhost

Без пароля. Допустимо только для локального сокета. Никогда для удалённых.

6. Резервные копии: pg_dump и автобэкап

PostgreSQL поставляется с утилитами pg_dump и pg_dumpall — больше ничего устанавливать не нужно.

Разовый бэкап базы

pg_dump: сжатый дамп в custom-формате
# Бэкап одной базы (рекомендуемый формат -Fc — сжатый, поддерживает выборочный restore)
sudo -u postgres pg_dump -Fc myapp_db -f /backup/myapp_db_$(date +%Y%m%d).dump

# Бэкап в читаемом SQL (удобен для переноса данных)
sudo -u postgres pg_dump myapp_db > /backup/myapp_db_$(date +%Y%m%d).sql
pg_restore: восстановить из custom-формата
# Восстановить в существующую (пустую) базу
pg_restore -h localhost -U postgres -d myapp_db /backup/myapp_db_20260305.dump

# Восстановить из SQL-дампа
psql -U postgres -d myapp_db -f /backup/myapp_db_20260305.sql

Автоматический бэкап через cron

/usr/local/bin/pg_backup.sh — создать скрипт
#!/bin/bash
BACKUP_DIR="/backup/postgres"
KEEP_DAYS=14    # хранить 14 дней

mkdir -p "$BACKUP_DIR"

# Бэкап всех баз по отдельности
for DB in $(sudo -u postgres psql -tAc "SELECT datname FROM pg_database WHERE datistemplate = false AND datname != 'postgres'"); do
  sudo -u postgres pg_dump -Fc "$DB" -f "$BACKUP_DIR/${DB}_$(date +%Y%m%d_%H%M).dump"
  echo "$(date): Backed up $DB"
done

# Удалить бэкапы старше KEEP_DAYS дней
find "$BACKUP_DIR" -name "*.dump" -mtime +$KEEP_DAYS -delete
Установить права и добавить в cron
chmod +x /usr/local/bin/pg_backup.sh

# Добавить в crontab (запуск каждый день в 3:00)
crontab -e
# Добавить строку:
0 3 * * * /usr/local/bin/pg_backup.sh >> /var/log/pg_backup.log 2>&1
pg_dumpall: бэкап всего кластера (пользователи + все базы)
# Полный бэкап кластера — нужен при миграции сервера
sudo -u postgres pg_dumpall -f /backup/cluster_$(date +%Y%m%d).sql

# Только роли и пользователи (без данных баз)
sudo -u postgres pg_dumpall --roles-only -f /backup/roles_$(date +%Y%m%d).sql

Проверяйте бэкапы

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

sudo -u postgres createdb myapp_db_test
pg_restore -U postgres -d myapp_db_test /backup/myapp_db_latest.dump
sudo -u postgres psql -d myapp_db_test -c "SELECT COUNT(*) FROM your_main_table;"

7. Анализ запросов: pg_stat_statements

pg_stat_statements — встроенное расширение, которое собирает статистику по всем запросам: время выполнения, количество вызовов, операции с диском. Это первое, что нужно включить на продакшен-сервере.

Установка и активация

Шаг 1: установить пакет contrib (если не установлен)
apt install -y postgresql-contrib-16
Шаг 2: добавить в postgresql.conf
shared_preload_libraries = 'pg_stat_statements'

# Дополнительные параметры (опционально):
pg_stat_statements.max = 10000   # хранить топ-10000 запросов
pg_stat_statements.track = all   # отслеживать вложенные запросы тоже
Шаг 3: перезапустить PostgreSQL и создать расширение
systemctl restart postgresql@16-main

# Создать расширение в нужной базе (нужно для каждой базы отдельно)
sudo -u postgres psql -d myapp_db -c "CREATE EXTENSION IF NOT EXISTS pg_stat_statements;"

Полезные запросы

Топ-10 самых медленных запросов (по среднему времени)
sudo -u postgres psql -d myapp_db -c "
SELECT
  round(mean_exec_time::numeric, 2) AS avg_ms,
  calls,
  round(total_exec_time::numeric, 2) AS total_ms,
  left(query, 80) AS query
FROM pg_stat_statements
ORDER BY mean_exec_time DESC
LIMIT 10;
"
Топ по суммарному времени (самые дорогие в сумме)
sudo -u postgres psql -d myapp_db -c "
SELECT
  round(total_exec_time::numeric, 2) AS total_ms,
  calls,
  round(mean_exec_time::numeric, 2) AS avg_ms,
  left(query, 80) AS query
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;
"
Запросы с большим числом чтений с диска (признак отсутствия индексов)
sudo -u postgres psql -d myapp_db -c "
SELECT
  shared_blks_read AS disk_reads,
  shared_blks_hit  AS cache_hits,
  calls,
  left(query, 80) AS query
FROM pg_stat_statements
WHERE shared_blks_read > 1000
ORDER BY shared_blks_read DESC
LIMIT 10;
"
Сбросить статистику (начать накапливать заново)
sudo -u postgres psql -d myapp_db -c "SELECT pg_stat_statements_reset();"

Что делать с медленными запросами

  1. 1Скопируйте медленный запрос и выполните EXPLAIN ANALYZE ваш_запрос — увидите план выполнения
  2. 2Если в плане есть Seq Scan на большой таблице — нужен индекс
  3. 3Создайте индекс: CREATE INDEX CONCURRENTLY idx_users_email ON users(email);
  4. 4CONCURRENTLY создаёт индекс без блокировки таблицы — используйте его на проде

8. Шпаргалка psql-команд

ЗадачаКоманда
Войти в psqlsudo -u postgres psql
Войти в конкретную базуsudo -u postgres psql -d myapp_db
Список баз\l
Список пользователей\du
Список таблиц\dt
Переключить базу\c myapp_db
Структура таблицы\d users
Размер баз данныхSELECT pg_size_pretty(pg_database_size(datname)), datname FROM pg_database ORDER BY 1 DESC;
Размер таблицSELECT pg_size_pretty(pg_total_relation_size(relname::text)), relname FROM pg_stat_user_tables ORDER BY pg_total_relation_size(relname::text) DESC;
Активные соединенияSELECT count(*), state FROM pg_stat_activity GROUP BY state;
Версия PostgreSQLSELECT version();
Перезагрузить конфигSELECT pg_reload_conf();
Выйти из psql\q
Управление PostgreSQL через systemctl
# Статус
systemctl status postgresql@16-main

# Запустить / остановить / перезапустить
systemctl start postgresql@16-main
systemctl stop postgresql@16-main
systemctl restart postgresql@16-main

# Перечитать конфиг без перезапуска
systemctl reload postgresql@16-main

# Лог ошибок (последние 50 строк)
tail -50 /var/log/postgresql/postgresql-16-main.log

Частые вопросы

Нужен VPS для PostgreSQL? Смотрите наш рейтинг

Топ VPS хостингов →

Смотрите также