+7 (920) 556-26-91 пн–пт: 10:00–19:00 (МСК)
Проконсультироваться

Инструкции

Как установить PostgreSQL 18 на VPS (Ubuntu 24.04)

Apt Ubuntu даёт 16-ю ветку. Для 18.6 подключаем PGDG, слушаем localhost, 5432 в интернет не открываем, бэкап — pg_dump.

Как установить PostgreSQL 18 на VPS (Ubuntu 24.04)

Короткий ответ: на Ubuntu 24.04 команда apt install postgresql ставит 16-ю ветку (на 13–14 сентября 2026 в noble-updates это 16.15). Актуальный стабильный мажор PostgreSQL — 18, патч 18.6 (релиз обновлений 13 августа 2026). Чтобы получить 18, подключаете официальный PGDG apt.postgresql.org и ставите пакет postgresql-18. Слушайте только localhost, порт 5432 в интернет не открывайте. Пользователя и базу создаёте через createuser/createdb. Бэкап — pg_dump по cron на диск сервера.

Сервер должен быть уже закреплён: обновления, sudo, SSH, firewall — см. первую настройку Ubuntu 24.04. Этот гайд не про «Postgres в Docker»: контейнер — отдельная история в установке Docker, здесь — системный пакет и systemd-кластер, как его собирает PostgreSQL на Debian/Ubuntu.

16 из Ubuntu или 18 с PGDG

Ubuntu «замораживает» мажор Postgres на весь срок жизни релиза. Noble заморожен на 16. Это нормально для приложений, которые сами требуют 16, и неправильно, если вам нужна текущая стабильная 18. Не ставьте оба мажора «на всякий случай» без понимания портов: второй кластер уйдёт на 5433, и клиенты начнут подключаться не туда.

Источник Пакет Что получите Когда выбирать
Архив Ubuntu 24.04 postgresql (метапакет) сервер 16, сейчас 16.15-0ubuntu0.24.04.1 нужна именно 16 «как в дистрибутиве»
PGDG, noble-pgdg postgresql-18 сервер 18, патч 18.6 нужна текущая стабильная ветка
listen postgresql.conf localhost всегда на одиночном VPS без реплики
Порт 5432/tcp не публиковать в ufw/security group клиент на этой же машине

Проверьте, что сейчас предлагает архив Ubuntu, до подключения PGDG:

apt-cache policy postgresql postgresql-16 postgresql-18
apt-cache show postgresql | grep -E '^(Package|Version|Depends):'

Метапакет postgresql зависит от 16-й ветки. Кандидата postgresql-18 в архиве noble нет — он появится только после PGDG. Документация подключения репозитория: postgresql.org/download/linux/ubuntu.

Подключить PGDG и поставить postgresql-18

Официальный путь — скрипт из пакета postgresql-common. Он кладёт ключ в /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc и добавляет sources. На noble сюита называется noble-pgdg, не копируйте примеры с resolute с сайта, если у вас 24.04.

sudo apt update
sudo apt install -y postgresql-common curl ca-certificates
sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh
. /etc/os-release
grep -R . /etc/apt/sources.list.d/*pgdg* 2>/dev/null || true
sudo apt update
apt-cache policy postgresql-18
sudo apt install -y postgresql-18 postgresql-client-18
sudo systemctl enable --now postgresql
sudo systemctl status postgresql --no-pager

Скрипт спросит подтверждение — читайте, что он пишет про дистрибутив. Если предпочитаете ручную запись (тот же ключ, без скрипта):

sudo apt install -y curl ca-certificates
sudo install -d /usr/share/postgresql-common/pgdg
sudo curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail \
  https://www.postgresql.org/media/keys/ACCC4CF8.asc
. /etc/os-release
sudo tee /etc/apt/sources.list.d/pgdg.sources >/dev/null <<EOF
Types: deb
URIs: https://apt.postgresql.org/pub/repos/apt
Suites: ${VERSION_CODENAME}-pgdg
Architectures: $(dpkg --print-architecture)
Components: main
Signed-By: /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc
EOF
sudo apt update
sudo apt install -y postgresql-18 postgresql-client-18

Версию сервера проверяйте не по psql --version клиента, а запросом к кластеру:

sudo -u postgres psql -c 'SELECT version();'
pg_lsclusters

В version() должна быть строка PostgreSQL 18.6. pg_lsclusters покажет кластер 18 main в состоянии online, порт 5432, data directory /var/lib/postgresql/18/main. Конфиги Debian-кластера лежат не внутри data directory, а в /etc/postgresql/18/main/.

Слушать только localhost

На одиночном VPS база не должна быть видна из интернета. Даже «правильный пароль» на открытом 5432 — это сканер на следующем шаге. Значение по умолчанию у пакета обычно уже localhost; его нужно подтвердить, а не предположить.

sudo -u postgres psql -c "SHOW listen_addresses;"
sudo -u postgres psql -c "SHOW port;"
ss -lntp | grep 5432 || true
sudo ufw status verbose

listen_addresses должен быть localhost. В ss допустимы 127.0.0.1:5432 и/или [::1]:5432 — это loopback, не «мир». Если видите 0.0.0.0:5432 или *:5432, исправляйте.

sudo sed -n 's/^listen_addresses.*/&/p' /etc/postgresql/18/main/postgresql.conf
sudo nano /etc/postgresql/18/main/postgresql.conf

Нужная строка:

listen_addresses = 'localhost'

Перечитайте кластер и снова снимите ss:

sudo systemctl reload postgresql
ss -lntp | grep 5432

Firewall: не делайте ufw allow 5432. Если правило уже есть — уберите. Клиенты (приложение, psql, бэкап) работают на этой же машине через UNIX-сокет или TCP на 127.0.0.1. Если когда-нибудь понадобится доступ с другого хоста — это SSH-туннель или отдельная сеть, не дырка в ufw «на 5432/tcp from anywhere».

Аутентификация локальных TCP-клиентов задаётся в /etc/postgresql/18/main/pg_hba.conf. Для приложений на localhost типично:

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

Не добавляйте host all all 0.0.0.0/0. После правок pg_hba.conf достаточно sudo systemctl reload postgresql. Строки читаются сверху вниз — первая подходящая срабатывает.

Роль приложения: createuser и createdb

Суперпользователь postgres — для админки и бэкапов, не для PHP/Node/Java. Приложению нужна отдельная роль с паролем и база, владельцем которой эта роль является. Имена ниже замените на свои; пароль сгенерируйте (openssl rand -base64 24) и храните в конфиге приложения, не в git.

sudo -u postgres createuser -P --pwprompt appuser
sudo -u postgres createdb -O appuser -E UTF8 -l en_US.UTF-8 appdb
sudo -u postgres psql -c '\du'
sudo -u postgres psql -c '\l+'

-P спросит пароль дважды. Если локаль en_US.UTF-8 не установлена, либо поставьте sudo locale-gen en_US.UTF-8, либо уберите -l и оставьте локаль кластера по умолчанию (на Ubuntu обычно уже UTF-8).

Проверка входа так, как будет входить приложение — по TCP с паролем, не peer:

psql "host=127.0.0.1 port=5432 dbname=appdb user=appuser sslmode=disable"
# внутри:
SELECT current_user, current_database(), inet_server_addr(), inet_server_port();
\q

Должны увидеть appuser / appdb / 127.0.0.1 / 5432. Если пароль отвергается — смотрите, какая строка pg_hba сработала, и не подключаетесь ли вы через UNIX-сокет под системным пользователем (тогда сработает peer и роль должна совпасть с OS-пользователем).

Права сверх владельца базы обычно не нужны. Не выдавайте SUPERUSER, CREATEDB, REPLICATION роли приложения. Расширения (CREATE EXTENSION) ставит postgres, затем объекты принадлежат тому, кто их создал — планируйте это до деплоя миграций.

Бэкап pg_dump по cron

Для одной базы на одном диске достаточно pg_dump в custom-формате (-Fc): его потом удобно частично восстанавливать через pg_restore. Не выдумывайте выгрузку в объектное хранилище «из этой статьи» — сначала дамп должен стабильно появляться локально. Каталог бэкапов не в data directory.

sudo mkdir -p /var/backups/pg
sudo chown postgres:postgres /var/backups/pg
sudo chmod 750 /var/backups/pg
sudo -u postgres pg_dump -Fc -f /var/backups/pg/appdb-test.dump appdb
ls -l /var/backups/pg/
sudo -u postgres pg_restore -l /var/backups/pg/appdb-test.dump | head

Если listing дампа читается, cron можно вешать. Скрипт от пользователя postgres, абсолютные пути, ротация старше семи дней:

sudo tee /usr/local/sbin/pg-dump-appdb.sh >/dev/null <<'EOF'
#!/bin/sh
set -eu
DIR=/var/backups/pg
STAMP=$(date +%F)
DUMP="$DIR/appdb-$STAMP.dump"
/usr/bin/pg_dump -Fc -f "$DUMP" appdb
find "$DIR" -name 'appdb-*.dump' -type f -mtime +7 -delete
EOF
sudo chmod 700 /usr/local/sbin/pg-dump-appdb.sh
sudo chown postgres:postgres /usr/local/sbin/pg-dump-appdb.sh
sudo crontab -u postgres -e

Строка cron (ежедневно в 03:15 по часовому поясу машины):

15 3 * * * /usr/local/sbin/pg-dump-appdb.sh

Проверка пояса: timedatectl. После первой ночи — ls -l /var/backups/pg. Восстановление на пустую базу (уже после аварии, не «для проверки на проде» без копии):

sudo -u postgres createdb -O appuser appdb_restore
sudo -u postgres pg_restore --no-owner --role=appuser -d appdb_restore \
  /var/backups/pg/appdb-YYYY-MM-DD.dump

Кластер 18 управляется systemd-шаблоном postgresql@18-main. Перезапуск всего Postgres на машине: sudo systemctl restart postgresql. Логи: journalctl -u postgresql@18-main -n 100 --no-pager и файлы в /var/log/postgresql/.

Итог, который должен получиться на VPS: pg_lsclusters показывает 18/main online, SHOW listen_addresses = localhost, в ufw нет 5432, роль appuser владеет appdb, в /var/backups/pg лежит свежий -Fc дамп. Это и есть рабочая установка PostgreSQL 18.6 на Ubuntu 24.04.

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

Можно ли остаться на PostgreSQL 16 из apt?

Да. Метапакет postgresql в Ubuntu 24.04 ставит 16-ю ветку; в noble-updates на дату этого текста это 16.15. Это поддерживаемый мажор, просто не самый новый. Гайд про 18 нужен тем, кто хочет текущий стабильный мажор с apt.postgresql.org. Не смешивайте «непонятно какой» 16 и 18 на одном порту.

Почему 5432 нельзя открыть «только для моего IP»?

Можно технически, но это уже другой контур (VPN, SSH-туннель, firewall-ограничение), и его нет в минимальной установке. Ошибка новичков — listen_addresses = '*' плюс ufw allow 5432. Для приложения на том же VPS это не нужно: подключайтесь на 127.0.0.1. Если база торчит в интернет, пароля роли недостаточно как единственной защиты.

createuser спрашивает пароль, а peer всё равно пускает без него

Это ожидаемо. Подключения через UNIX-сокет идут по local ... peer: системный пользователь должен совпасть с ролью Postgres. Пароль проверяется на host ... 127.0.0.1/32 scram-sha-256. Приложение должно использовать TCP host=127.0.0.1 (или явно прописанный unix socket + отдельная роль), а не надеяться, что «пароль в URL» сработает на peer.

Куда девать дамп, если диск маленький?

Сначала убедитесь, что pg_dump -Fc вообще создаётся и восстанавливается локально. Сжатый custom-формат обычно заметно меньше SQL. Ротация -mtime +7 обязательна. Вынос на другой сервер — отдельная задача (второй диск, rsync по SSH). Не копируйте в статью несуществующий «S3-бакет проекта»: его у вас нет, пока вы сами его не завели.

Скрипт PGDG перезапишет мой Postgres 16?

Подключение репозитория само по себе кластер не удаляет. apt install postgresql-18 поднимает новый кластер 18/main. Если 16 уже слушает 5432, 18 может встать на 5433 — смотрите pg_lsclusters. Миграция данных 16→18 — это pg_dump/pg_restore или pg_upgrade, не «apt dist-upgrade сам всё перенесёт». Пока не мигрировали — клиенты должны явно знать порт.

Ещё гайды