Перейти к основному содержимому
Версия: 2.5

СУБД PostgreSQL

В Памир конфигурация и накопленные данные приложения хранятся в СУБД PostgreSQL, запущенной в контейнере Docker (сервис database). База данных приложения называется srm и принадлежит пользователю приложения; кроме неё в кластере PostgreSQL присутствуют служебная БД postgres и роли (пользователи).

Рекомендованная стратегия

Для PostgreSQL рекомендуется логическое резервное копирование утилитами pg_dump / pg_dumpall с восстановлением через pg_restore / psql. Этот способ даёт application-consistent копию, переносимую между версиями и инсталляциями, и не требует остановки сервиса.

Параметры подключения​

ПараметрЗначениеИсточник
Сервис / контейнерdatabasedocker-compose.deps.yml
Суперпользователь$POSTGRES_USER (по умолчанию postgres).postgres.env
Пароль суперпользователя$POSTGRES_PASSWORD.postgres.env
Пользователь приложения$POSTGRES_APP_USER.postgres.env
БД приложения$POSTGRES_APP_DB (по умолчанию srm).postgres.env
Каталог данных (PGDATA)/var/lib/postgresql/dataтом pamir_database-data
примечание

Переменные окружения (POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_APP_DB и др.) уже заданы внутри контейнера database из файла .postgres.env. Поэтому в примерах ниже на них можно ссылаться напрямую внутри sh -c '…', не подставляя значения вручную.

Все команды выполняются из каталога приложения ($HOME/.pamir или /opt/pamir).

Флаг -T при перенаправлении вывода

Для команд, вывод которых перенаправляется в файл на хосте (> backup.dump), используйте docker compose exec -T (без выделения псевдотерминала). Псевдотерминал (-it) искажает двоичный поток и делает дамп непригодным для восстановления. Флаг -it уместен только для интерактивных сессий (psql).

Резервное копирование​

Дамп базы данных приложения​

Дамп БД srm в пользовательском (custom) формате — наиболее гибкий вариант: позволяет выборочное восстановление и сжимается «на лету».

cd "$HOME/.pamir"
mkdir -p "$HOME/pamir-backups"

docker compose exec -T database \
sh -c 'PGPASSWORD="$POSTGRES_PASSWORD" pg_dump \
-U "$POSTGRES_USER" -d "$POSTGRES_APP_DB" -Fc' \
> "$HOME/pamir-backups/srm-$(date +%F).dump"

где:

  • -Fc — custom-формат (сжатый, для pg_restore);
  • -d "$POSTGRES_APP_DB" — БД приложения (srm).
Перенос в PostgreSQL без мандатных меток

Контейнер СУБД собран на базе Astra Linux, и в дамп попадают команды мандатных меток. Внутри Памир это не мешает, но при восстановлении на сервер, который меток не поддерживает (например, PostgreSQL из репозитория РЕД ОС), загрузка прерывается на MAC LABEL. Для такого переноса дамп снимается с дополнительным флагом --disable-macs:

docker compose exec -T database \
sh -c 'PGPASSWORD="$POSTGRES_PASSWORD" pg_dump \
-U "$POSTGRES_USER" -d "$POSTGRES_APP_DB" -Fc --disable-macs' \
> "$HOME/pamir-backups/srm-$(date +%F).dump"

Флаг нужен при переводе системы на внешний сервер PostgreSQL; для обычного резервного копирования внутри той же инсталляции он не требуется.

Дамп ролей (глобальных объектов)​

Роли и права не входят в дамп отдельной БД, поэтому их выгружают отдельно:

cd "$HOME/.pamir"

docker compose exec -T database \
sh -c 'PGPASSWORD="$POSTGRES_PASSWORD" pg_dumpall \
-U "$POSTGRES_USER" --globals-only' \
> "$HOME/pamir-backups/globals-$(date +%F).sql"

Полный дамп кластера (альтернатива)​

Если нужно сохранить весь кластер PostgreSQL единым файлом (все БД + роли) в текстовом формате:

cd "$HOME/.pamir"

docker compose exec -T database \
sh -c 'PGPASSWORD="$POSTGRES_PASSWORD" pg_dumpall -U "$POSTGRES_USER"' \
| gzip > "$HOME/pamir-backups/cluster-$(date +%F).sql.gz"

Восстановление​

warning

Восстановление выполняется при работающем сервисе database, но остановленных сервисах приложения Памир, чтобы исключить запись в БД во время восстановления.

Команда pamirctl start <сервис> поднимает весь стек, поэтому для запуска только СУБД используйте напрямую docker compose:

docker compose stop          # остановить все сервисы
docker compose start database # поднять только СУБД (и её зависимости)

Восстановление из custom-дампа​

Сначала восстановите роли (если восстанавливаете на чистый кластер), затем — БД приложения:

cd "$HOME/.pamir"

# 1. Роли (при необходимости)
docker compose exec -T database \
sh -c 'PGPASSWORD="$POSTGRES_PASSWORD" psql -U "$POSTGRES_USER" -d postgres' \
< "$HOME/pamir-backups/globals-2026-06-08.sql"

# 2. БД приложения: пересоздать схему и загрузить данные
docker compose exec -T database \
sh -c 'PGPASSWORD="$POSTGRES_PASSWORD" pg_restore \
-U "$POSTGRES_USER" -d "$POSTGRES_APP_DB" \
--clean --if-exists' \
< "$HOME/pamir-backups/srm-2026-06-08.dump"

где:

  • --clean --if-exists — удалить существующие объекты перед загрузкой.
Не используйте --no-owner

Восстановление выполняется от суперпользователя postgres, а объекты БД srm принадлежат пользователю приложения app_postgres. Флаг --no-owner назначил бы всем объектам владельца postgres, и приложение потеряло бы доступ (permission denied).

Поэтому роли восстанавливают первым шагом (чтобы роль app_postgres существовала), а pg_restore запускают без --no-owner — тогда исходное владение (app_postgres) сохраняется.

Восстановление «с нуля»

Если БД srm нужно создать заново, выполните перед загрузкой:

docker compose exec -T database \
sh -c 'PGPASSWORD="$POSTGRES_PASSWORD" psql -U "$POSTGRES_USER" -d postgres \
-c "DROP DATABASE IF EXISTS \"$POSTGRES_APP_DB\";" \
-c "CREATE DATABASE \"$POSTGRES_APP_DB\" OWNER \"$POSTGRES_APP_USER\";"'

После восстановления запустите приложение:

pamirctl start

Восстановление из полного дампа кластера​

cd "$HOME/.pamir"

gunzip -c "$HOME/pamir-backups/cluster-2026-06-08.sql.gz" | \
docker compose exec -T database \
sh -c 'PGPASSWORD="$POSTGRES_PASSWORD" psql -U "$POSTGRES_USER" -d postgres'

Проверка резервных копий​

Поверхностная проверка по размеру и дате, а также целостности дампа:

# Размер и дата
ls -lh "$HOME/pamir-backups/"*.dump "$HOME/pamir-backups/"*.sql* 2>/dev/null

# Просмотр оглавления custom-дампа (TOC) — подтверждает читаемость файла
docker compose exec -T database pg_restore -l \
< "$HOME/pamir-backups/srm-2026-06-08.dump" | head

# Проверка целостности сжатого SQL-дампа
gzip -t "$HOME/pamir-backups/cluster-2026-06-08.sql.gz" && echo "OK"

Если pg_restore -l возвращает оглавление без ошибок, а размер файла соответствует ожидаемому — дамп корректен.

Автоматизация (systemd timer)​

Скрипт резервного копирования ~/.local/bin/pamir-backup-postgres.sh:

~/.local/bin/pamir-backup-postgres.sh
#!/usr/bin/env bash
set -euo pipefail

cd "$HOME/.pamir"
DEST="$HOME/pamir-backups"
RETENTION_DAYS=14
mkdir -p "$DEST"
STAMP="$(date +%F_%H-%M)"

# Роли
docker compose exec -T database \
sh -c 'PGPASSWORD="$POSTGRES_PASSWORD" pg_dumpall -U "$POSTGRES_USER" --globals-only' \
> "$DEST/globals-$STAMP.sql"

# БД приложения
docker compose exec -T database \
sh -c 'PGPASSWORD="$POSTGRES_PASSWORD" pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_APP_DB" -Fc' \
> "$DEST/srm-$STAMP.dump"

# Ротация
find "$DEST" -name 'srm-*.dump' -mtime +"$RETENTION_DAYS" -delete
find "$DEST" -name 'globals-*.sql' -mtime +"$RETENTION_DAYS" -delete
chmod +x ~/.local/bin/pamir-backup-postgres.sh

Служба и таймер:

~/.config/systemd/user/pamir-backup-postgres.service
[Unit]
Description=Pamir PostgreSQL logical backup

[Service]
Type=oneshot
ExecStart=%h/.local/bin/pamir-backup-postgres.sh
~/.config/systemd/user/pamir-backup-postgres.timer
[Unit]
Description=Pamir PostgreSQL backup every 6 hours

[Timer]
OnCalendar=*-*-* 00/6:00:00
Persistent=true

[Install]
WantedBy=timers.target

Активация:

systemctl --user daemon-reload
systemctl --user enable --now pamir-backup-postgres.timer
loginctl enable-linger "$USER" # работа таймера без активной сессии
systemctl --user list-timers pamir-backup-postgres.timer

Связанные разделы​