СУБД PostgreSQL
В Памир конфигурация и накопленные данные приложения хранятся в СУБД PostgreSQL,
запущенной в контейнере Docker (сервис database). База данных приложения называется srm
и принадлежит пользователю приложения; кроме неё в кластере PostgreSQL присутствуют
служебная БД postgres и роли (пользователи).
Для PostgreSQL рекомендуется логическое резервное копирование утилитами pg_dump /
pg_dumpall с восстановлением через pg_restore / psql. Этот способ даёт
application-consistent копию, переносимую между версиями и инсталляциями, и не требует
остановки сервиса.
Параметры подключения
| Параметр | Значение | Источник |
|---|---|---|
| Сервис / контейнер | database | docker-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).
Дамп ролей (глобальных объектов)
Роли и права не входят в дамп отдельной БД, поэтому их выгружают отдельно:
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"
Восстановление
Восстановление выполняется при работающем сервисе 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:
#!/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
Служба и таймер:
[Unit]
Description=Pamir PostgreSQL logical backup
[Service]
Type=oneshot
ExecStart=%h/.local/bin/pamir-backup-postgres.sh
[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