Files
homelab-docs/docs/backup/proxmox-phase1-backup.md
Andrey f319133cee Add notification feature to backup scripts for various services
Enhance backup scripts for Nextcloud, Gitea, Paperless, Vaultwarden, Immich, and VPS configurations by adding Telegram notifications upon completion. Include details such as backup size and objects backed up. Update backup documentation to reflect these changes and ensure clarity on backup processes and retention policies.
2026-02-27 20:42:30 +03:00

36 KiB
Raw Blame History

Фаза 1: Стратегия бэкапов Proxmox

Цель: при смерти SSD с системой или потере /etc/pve — развернуть Proxmox, восстановить контейнеры/ВМ, поднять сервисы без многочасового восстановления и угадывания паролей.

Приоритет №1. ИБП уже есть; защищаемся от смерти диска.


Что бэкапить

Объект Зачем
LXC и VM целиком (vzdump) Восстановление контейнера/ВМ из одного архива: ОС, конфиги, данные на корневом томе. Не только данные внутри — сам образ для restore.
/etc/pve Конфиги кластера, VM/LXC (ID, сеть, диски, задачи), пользователи Proxmox, права. Без этого после переустановки Proxmox не восстановить привязку дисков и настройки.

Пошаговый план

Шаг 1. Определить хранилище для бэкапов

Выбранная схема:

Место Описание Что туда
Локально: /dev/sdb1 (1 ТБ под бэкапы) Отдельный SSD 2 ТБ; под копии выделен 1 ТБ, смонтирован в /mnt/backup. Второй ТБ — в запас. Proxmox vzdump (через UI), затем те же данные (dump, etc-pve, фотки, VPS) в Yandex через restic. Фотки: оригиналы + метаданные + БД Immich; остальное пересчитать можно. VPS: Amnezia — конфиг; Миран — БД бота + контент (контент можно в S3 Мирана; копию на sdb1 — опционально). Конфигурацию серверов не бэкапим — есть Ansible.
Офсайт: Yandex Object Storage (S3) Арендованный бакет, S3-совместимый API. Yandex Object Storage. Restic с хоста (cron на ноде Proxmox): выгрузка содержимого /mnt/backup. Retention: 3 daily, 2 weekly, 2 monthly.

Принято: Вариант A — отдельный диск/раздел на хосте (sdb1, 1 ТБ в /mnt/backup). Варианты B (NFS/SMB) и C (внешний USB) в текущей схеме не используются; USB опционально для параноидального 3-2-1 (см. выше).

3-2-1: Три копии: (1) прод — система и данные на основном диске; (2) локальный бэкап — sdb1; (3) офсайт — Yandex. Два типа носителей: локальный SSD и облачное object storage. Один офсайт — да. Стратегия удовлетворяет 3-2-1. Опционально: четвёртая копия на внешнем USB/другом ПК для параноидального сценария (пожар/кража) — по желанию.

Принято: Точка монтирования — /mnt/backup. На диске 2 ТБ выделено 1 ТБ под бэкапы; второй ТБ пока в запас, назначение не определено.

Действие: Разметить 1 ТБ на /dev/sdb1, создать ФС (ext4/xfs), смонтировать в /mnt/backup. Структуру каталогов — см. раздел «Структура локального хранилища» ниже.


Шаг 2. Добавить Backup Storage в Proxmox

  1. В веб-интерфейсе: Datacenter → Storage → Add.
  2. Тип: Directory (если папка на локальном диске) или NFS/CIFS (если сетевое).
  3. Указать:
    • ID (например backup-local или backup-nfs),
    • Directory — путь, например /mnt/backup/dump,
    • Включить опции Content: VZDump backup file (и при необходимости ISO, Container template — по желанию).
  4. Сохранить. Убедиться, что storage виден и доступен для записи.

Если используешь NFS: сначала смонтировать NFS в /mnt/backup на хосте (fstab или systemd mount), затем добавить Storage с Directory /mnt/backup/dump.

Для выбранной схемы: Directory = /mnt/backup/proxmox/dump (см. структуру ниже).


Структура локального хранилища (1 ТБ на sdb1)

«Аналог S3» на одном диске — это просто понятная иерархия каталогов. MinIO не используем: лишний сервис; достаточно директорий и restic с бэкендом local (если понадобится локальный restic) и s3 для Yandex. Proxmox пишет в Directory — ему достаточно пути.

Пример структуры под /mnt/backup:

/mnt/backup/
├── proxmox/
│   ├── dump/          ← Proxmox Backup Job (VZDump) — сюда добавляем Storage в PVE
│   └── etc-pve/       ← архивы tar.gz из cron: etc-pve-*, etc-host-configs-* (backup-etc-pve.sh)
├── restic/
│   ├── local/         ← репозитории restic для локальных снапшотов (опционально)
│   └── ...            ← или restic только в Yandex, локально только сырые копии
├── photos/            ← Immich: оригиналы фото + метаданные + БД (остальное пересчитать)
├── vps/               ← Amnezia: конфиг. Миран: БД бота (+ контент при необходимости; основной контент можно в S3 Мирана)
└── other/             ← прочие важные данные (конфиги, скрипты, что ещё решите)

Квоты: при необходимости ограничить размер по каталогам (например proxmox/dump — не более 500 ГБ) через отдельные подразделы или скрипты очистки (retention).


Шифрование диска бэкапов (LUKS)

LUKS (Linux Unified Key Setup) — стандартное шифрование раздела в Linux. Если диск с бэкапами украдут или вынесут, без пароля/ключа данные не прочитать. Минусы: нужно вводить пароль при загрузке (или хранить ключ на другом носителе), небольшая нагрузка на CPU.

Принято: LUKS пока не используем. Раздел sdb1 — без шифрования. При необходимости можно добавить позже (потребуется перенос данных).


Restic и Yandex Object Storage

  • Restic поддерживает бэкенд S3. Yandex Object Storage совместим с S3 API — используешь endpoint бакета и ключи (Access Key / Secret).
  • Retention в Yandex: 3 daily, 2 weekly, 2 monthly — restic forget --keep-daily 3 --keep-weekly 2 --keep-monthly 2 и затем prune.
  • Что гнать в Yandex через restic: Proxmox dump (каталог proxmox/dump), /etc/pve (архивы из proxmox/etc-pve), фотки (оригиналы + метаданные + БД Immich), бэкапы с VPS — см. «Принятые решения: что куда» ниже.

Локально отдельной политики retention для restic не нужно: на sdb1 retention задаётся в самом Proxmox Backup Job (например «keep last 7») и в скрипте бэкапа /etc/pve (удалять архивы старше N дней). Restic используется только для отправки в Yandex с политикой 7/4/6. Локальных restic-репозиториев можно не заводить — только каталоги и выгрузка их содержимого в облако.

Документация Yandex: Object Storage S3. Нужны: bucket name, region, endpoint, Static Key (Access Key ID + Secret Access Key). Бакет создан; ключи и endpoint зафиксировать при настройке restic.


Хранилище паролей

Чтобы не терять пароли при восстановлении и держать креды в одном месте. Рассматривались варианты: Vaultwarden (self-hosted), Bitwarden Cloud, KeePass/KeePassXC, 1Password и др.

Принято и сделано: Vaultwarden развёрнут на CT 103 LXC. Домен через NPM (HTTPS), клиенты Bitwarden на ПК/телефоне. Бэкап данных Vaultwarden включён в общий план (restic → Yandex).


Где запускать бэкапы (централизация)

С хоста Proxmox (cron на ноде):

  • Proxmox Backup Job уже выполняется на хосте и пишет vzdump всех выбранных LXC/VM в /mnt/backup/proxmox/dump — это и есть «бэкапы всех контейнеров и ВМ», централизованно.
  • Restic (backup/forget/prune) тоже запускаем с хоста по cron: бэкапит каталоги на хосте (например весь /mnt/backup или выбранные подкаталоги) в Yandex S3. Данные для бэкапа — локальные пути (dump, etc-pve, а фотки и данные с VPS нужно либо копировать на хост в /mnt/backup скриптами, либо монтировать и тогда restic будет их читать с хоста). Контейнеры и ВМ целиком не бэкапим через restic — ими занимается только Proxmox Backup Job.

Шаг 3. Настроить расписание бэкапа LXC и VM

  1. Datacenter → Backup (или Backup в меню узла).

  2. Add — создаётся задача (Job).

  3. Параметры:

    • Storage — выбранное хранилище (шаг 2).
    • Schedule — например 0 2 * * * (каждую ночь в 02:00). Подстроить под окно, когда нагрузка минимальна.
    • Selection mode: включить нужные узлы (или All), затем отметить галочками конкретные LXC (100108) и VM (200). Либо выбрать "Backup all" для всех VMs/containers.
    • Mode:
      • Snapshot — контейнер/ВМ не останавливается, создаётся снимок (рекомендуется для минимизации даунтайма).
      • SuspendВМ приостанавливается на время бэкапа (более консистентно для БД, но даунтайм).
        Для LXC обычно достаточно Snapshot. Для VM 200 (PostgreSQL и др.): Snapshot не гарантирует консистентность БД — PostgreSQL может быть в середине транзакции. Правильная стратегия: внутри VM делать логический бэкап БД (pg_dump), а vzdump snapshot использовать для остального (ОС, конфиги, файлы). Итого: VM 200 — vzdump snapshot ок для образа; консистентность БД — отдельно через pg_dump внутри гостя.
    • Compression: ZSTD (хороший компромисс скорость/размер).
    • Retention: например «Keep last 7» или «Keep last 4 weekly» — чтобы не забивать диск.
  4. Сохранить job. Проверить по кнопке Backup now, что задача запускается и файлы появляются в Storage.

Важно: бэкап должен включать и LXC, и VM 200. Не только данные внутри них (те уже описаны в документации контейнеров), а именно полный dump для restore.


Шаг 4. Бэкап /etc/pve и конфигов хоста

Конфиги кластера и виртуалок лежат в /etc/pve. Плюс для восстановления хоста полезны: /etc/network/interfaces, /etc/hosts, /etc/resolv.conf. Всё это нужно копировать регулярно и хранить в безопасном месте (желательно не только на том же диске, что и система).

Принято: вариант A — cron на хосте Proxmox.

  1. Создать скрипт, например /root/scripts/backup-etc-pve.sh:
#!/bin/bash
BACKUP_ROOT="/mnt/backup/proxmox/etc-pve"   # по структуре выше
DATE=$(date +%Y%m%d-%H%M)
mkdir -p "$BACKUP_ROOT"
tar -czf "$BACKUP_ROOT/etc-pve-$DATE.tar.gz" -C / etc/pve
tar -czf "$BACKUP_ROOT/etc-host-configs-$DATE.tar.gz" -C / etc/network/interfaces etc/hosts etc/resolv.conf
# опционально: удалять бэкапы старше N дней
# find "$BACKUP_ROOT" -name 'etc-pve-*.tar.gz' -mtime +30 -delete
# find "$BACKUP_ROOT" -name 'etc-host-configs-*.tar.gz' -mtime +30 -delete
  1. Сделать исполняемым: chmod +x /root/scripts/backup-etc-pve.sh.
  2. Добавить в cron: crontab -e. Окно внутренних бэкапов 01:0003:30; пример для etc-pve: 15 2 * * * /root/scripts/backup-etc-pve.sh

Вариант B: Тот же скрипт можно вызывать из задачи в Proxmox (Script/Command в задаче типа Hook script), но проще и надёжнее — отдельный cron на хосте.

Бэкапы (etc-pve-*.tar.gz, etc-host-configs-*.tar.gz) хранить локально (/mnt/backup/proxmox/etc-pve) и в Yandex — включить этот каталог в источники restic (мало весит, критично при потере хоста). Файлы с ограниченными правами (chmod 600); /etc/pve содержит секреты — не выкладывать в открытый доступ.


Шаг 5. Хранить секреты отдельно (пароли, ключи)

Чтобы «не вспоминать пароли 3 часа» после восстановления:

Секретное хранилище — Vaultwarden на CT 103 (см. выше). Туда: root Proxmox, пользователи PVE, пароли БД и сервисов (Nextcloud, Gitea, Paperless, Immich, NPM, Galene и т.д.), API-ключи (Beget, certbot, Wallos и др.). Полный список кредов по контейнерам — в статьях container-100 … container-200; свести в один список в Vaultwarden и обновлять при смене паролей.

Это не «шаг бэкапа», но обязательная часть восстановления: без паролей восстановленные контейнеры не войдут в сервисы.

Инвентаризация секретов для переноса в Vaultwarden — ниже сводная таблица: где лежат креды сейчас и какой объект в Vaultwarden им соответствует. Команды для получения значений из Vaultwarden и переключение скриптов — в разделе «Получение секретов из Vaultwarden» ниже.

Хост / CT / VM Текущее место Объект Vaultwarden
Proxmox (хост) root, пользователи PVE (в менеджере вручную)
Proxmox (хост) /root/.restic-yandex.env, /root/.restic-password RESTIC (поля: RESTIC_BACKUP_KEY, RESTIC_REPOSITORY, AWS_ACCESS_KEY_ID, AWS_DEFAULT_REGION, AWS_SECRET_ACCESS_KEY, TELEGRAM_SELF_CHAT_ID)
Proxmox (хост) /root/.telegram-notify.env HOME_BOT_TOKEN (пароль = токен бота), RESTIC (поле TELEGRAM_SELF_CHAT_ID = chat_id)
CT 100 /root/.secrets/certbot/beget.ini beget (логин, пароль)
CT 100 NPM админка (в менеджере вручную)
CT 100 VPN Route Check compose localhost (логин admin, пароль, поле ROUTER_TELNET_HOST)
CT 100 custom_ssl / letsencrypt (восстановление из /etc/letsencrypt; в Vaultwarden не храним)
CT 101 Nextcloud compose, config.php NEXTCLOUD (логин nextcloud, пароль; поля: NEXTCLOUD_TRUSTED_DOMAINS, instanceid, passwordsalt, secret, dbpassword)
CT 103 Gitea compose, .env, app.ini GITEA (логин gitea, пароль; поля: GITEA__database__DB_TYPE, GITEA__database__HOST, GITEA_RUNNER_REGISTRATION_TOKEN, LFS_JWT_SECRET, INTERNAL_TOKEN)
CT 103 CouchDB local.ini OBSIDIAN (логин obsidian, пароль)
CT 103 Vaultwarden .env VAULTWARDEN (пароль = ADMIN_TOKEN, поле SIGNUPS_ALLOWED)
CT 104 Paperless compose, docker-compose.env PAPERLESS (логин paperless, пароль; поля: PAPERLESS_URL, PAPERLESS_SECRET_KEY, PAPERLESS_TIME_ZONE, PAPERLESS_OCR_LANGUAGE, PAPERLESS_OCR_LANGUAGES)
CT 107 Invidious compose INVIDIOUS (логин kemal, пароль; поля: SERVER_SECRET_KEY, test)
CT 108 ice-servers.json GALENE (поле config — JSON TURN)
VM 200 /opt/immich/.env IMMICH (логин/пароль и поля по .env)
VM 200 /opt/immich-deduper/.env IMMICH_DEDUPER (логин postgres, пароль; поля: DEDUP_PORT, DEDUP_DATA, DEDUP_IMAGE, IMMICH_PATH, PSQL_HOST, PSQL_PORT, PSQL_DB)
Proxmox (хост) /root/.vps-miran-s3.env MIRAN_S3 (поля: S3_ACCESS_KEY, S3_SECRET_KEY, S3_BUCKET_NAME)

Получение секретов из Vaultwarden

Требования: установлены bw (Bitwarden CLI) и jq; настроен сервер: bw config server https://vault.katykhin.ru. Мастер-пароль задаётся через переменную BW_MASTER_PASSWORD или через файл с доступом только для текущего пользователя (chmod 600), например /root/.bw-master; файл не хранить в репозитории. Перед запросами: bw sync и разблокировка: export BW_SESSION=$(bw unlock --passwordenv BW_MASTER_PASSWORD --raw) или bw unlock --passwordfile /path/to/file --raw.

Команды по объектам (выполнять после bw unlock в той же сессии):

Объект Логин / пароль Кастомное поле
beget bw get username "beget", bw get password "beget"
GALENE bw get item "GALENE" | jq -r '.fields[] | select(.name=="config") | .value'
GITEA bw get username "GITEA", bw get password "GITEA" bw get item "GITEA" | jq -r '.fields[] | select(.name=="ИМЯ_ПОЛЯ") | .value' — подставить GITEA_RUNNER_REGISTRATION_TOKEN, LFS_JWT_SECRET, INTERNAL_TOKEN, GITEA__database__DB_TYPE, GITEA__database__HOST
HOME_BOT_TOKEN пароль = токен: bw get password "HOME_BOT_TOKEN"
IMMICH по структуре в Vaultwarden bw get item "IMMICH" | jq '.fields'
IMMICH_DEDUPER bw get username "IMMICH_DEDUPER", bw get password "IMMICH_DEDUPER" поля DEDUP_, IMMICH_PATH, PSQL_ — через jq -r '.fields[] | select(.name=="X") | .value'
INVIDIOUS bw get username "INVIDIOUS", bw get password "INVIDIOUS" bw get item "INVIDIOUS" | jq -r '.fields[] | select(.name=="SERVER_SECRET_KEY") | .value'
localhost bw get username "localhost", bw get password "localhost" bw get item "localhost" | jq -r '.fields[] | select(.name=="ROUTER_TELNET_HOST") | .value'
MIRAN_S3 S3_ACCESS_KEY: bw get item "MIRAN_S3" | jq -r '.fields[] | select(.name=="S3_ACCESS_KEY") | .value'; аналогично S3_SECRET_KEY, S3_BUCKET_NAME
NEXTCLOUD bw get username "NEXTCLOUD", bw get password "NEXTCLOUD" secret: bw get item "NEXTCLOUD" | jq -r '.fields[] | select(.name=="secret") | .value'; dbpassword, passwordsalt, instanceid, NEXTCLOUD_TRUSTED_DOMAINS — то же с .name=="..."
OBSIDIAN bw get username "OBSIDIAN", bw get password "OBSIDIAN"
PAPERLESS bw get username "PAPERLESS", bw get password "PAPERLESS" PAPERLESS_SECRET_KEY, PAPERLESS_URL и др. — bw get item "PAPERLESS" | jq -r '.fields[] | select(.name=="PAPERLESS_SECRET_KEY") | .value'
RESTIC RESTIC_BACKUP_KEY: bw get item "RESTIC" | jq -r '.fields[] | select(.name=="RESTIC_BACKUP_KEY") | .value'; RESTIC_REPOSITORY, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION, TELEGRAM_SELF_CHAT_ID — то же с нужным .name
VAULTWARDEN пароль = ADMIN_TOKEN: bw get password "VAULTWARDEN"; SIGNUPS_ALLOWED — из полей

Универсальный шаблон для поля по имени:
bw get item "ИМЯ_ОБЪЕКТА" | jq -r '.fields[] | select(.name=="ИМЯ_ПОЛЯ") | .value'


Переключение скриптов на секреты из Vaultwarden

Ниже — как перейти с чтения из файлов на подстановку из bw на хосте Proxmox. Мастер-пароль хранить только в файле с доступом для текущего пользователя: chmod 600 /root/.bw-master (владелец root — только root читает/пишет); в репозиторий файл не коммитить. Либо задавать переменную окружения при запуске по крону.

1. Restic (backup-restic-yandex.sh, backup-restic-yandex-photos.sh, restore-one-vzdump-from-restic.sh)

Сейчас: source /root/.restic-yandex.env, пароль из /root/.restic-password.

Переключение: в начале скрипта (после set -e) разблокировать BW и выставить переменные из объекта RESTIC:

# Разблокировать Vaultwarden (мастер-пароль из файла с chmod 600 или env)
BW_MASTER_PASSWORD_FILE="${BW_MASTER_PASSWORD_FILE:-/root/.bw-master}"
if [ -f "$BW_MASTER_PASSWORD_FILE" ]; then
  export BW_SESSION=$(bw unlock --passwordfile "$BW_MASTER_PASSWORD_FILE" --raw)
fi
# Подставить секреты из RESTIC
ITEM=$(bw get item "RESTIC")
export RESTIC_REPOSITORY=$(echo "$ITEM" | jq -r '.fields[] | select(.name=="RESTIC_REPOSITORY") | .value')
export AWS_ACCESS_KEY_ID=$(echo "$ITEM" | jq -r '.fields[] | select(.name=="AWS_ACCESS_KEY_ID") | .value')
export AWS_SECRET_ACCESS_KEY=$(echo "$ITEM" | jq -r '.fields[] | select(.name=="AWS_SECRET_ACCESS_KEY") | .value')
export AWS_DEFAULT_REGION=$(echo "$ITEM" | jq -r '.fields[] | select(.name=="AWS_DEFAULT_REGION") | .value')
RESTIC_PASSWORD=$(echo "$ITEM" | jq -r '.fields[] | select(.name=="RESTIC_BACKUP_KEY") | .value')
export RESTIC_PASSWORD_FILE=$(mktemp -u)
echo -n "$RESTIC_PASSWORD" > "$RESTIC_PASSWORD_FILE"
chmod 600 "$RESTIC_PASSWORD_FILE"
trap 'rm -f "$RESTIC_PASSWORD_FILE"' EXIT

Убрать из скрипта: проверку/чтение ENV_FILE и RESTIC_PASSWORD_FILE из файлов; оставить использование переменных RESTIC_REPOSITORY, AWS_*, RESTIC_PASSWORD_FILE как выше. Для restore-one-vzdump-from-restic.sh — тот же блок в начале.

2. Telegram (notify-telegram.sh)

Сейчас: source /root/.telegram-notify.env, переменные TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID.

Переключение: читать токен из HOME_BOT_TOKEN (пароль), chat_id из объекта RESTIC (поле TELEGRAM_SELF_CHAT_ID). В начале скрипта (если нет уже разблокировки):

BW_MASTER_PASSWORD_FILE="${BW_MASTER_PASSWORD_FILE:-/root/.bw-master}"
if [ -f "$BW_MASTER_PASSWORD_FILE" ]; then
  export BW_SESSION=$(bw unlock --passwordfile "$BW_MASTER_PASSWORD_FILE" --raw)
fi
TELEGRAM_BOT_TOKEN=$(bw get password "HOME_BOT_TOKEN")
TELEGRAM_CHAT_ID=$(bw get item "RESTIC" | jq -r '.fields[] | select(.name=="TELEGRAM_SELF_CHAT_ID") | .value')

Дальше в скрипте использовать TELEGRAM_BOT_TOKEN и TELEGRAM_CHAT_ID как раньше (проверка на пустоту, вызов curl). Файл /root/.telegram-notify.env можно не использовать.

3. Дампы БД (backup-ct101-pgdump.sh, backup-ct104-pgdump.sh, backup-ct103-gitea-pgdump.sh)

Скрипты уже берут PGPASSWORD из Vaultwarden: в начале разблокировка bw unlock --passwordfile "$BW_MASTER_PASSWORD_FILE" --raw, затем для pg_dump передаётся -e PGPASSWORD=... в docker exec. Источники паролей:

  • Nextcloud (CT 101): объект NEXTCLOUD — поле dbpassword или пароль записи (bw get password "NEXTCLOUD").
  • Paperless (CT 104): объект PAPERLESS — пароль (bw get password "PAPERLESS").
  • Gitea (CT 103): объект GITEA — пароль (bw get password "GITEA").

Требования на хосте: bw, для Nextcloud — jq; файл /root/.bw-master с мастер-паролем (chmod 600). При ошибке (дамп < 512 байт) скрипт завершается с кодом 1 и выводит stderr; уведомление в Telegram при ошибке не отправляется.

4. Остальные места

Конфиги сервисов (Nextcloud config.php, Gitea compose, Paperless .env, Immich .env и т.д.) подставлять вручную при восстановлении или написать небольшие скрипты-обёртки, которые один раз получают нужные значения через bw get item / bw get password и пишут в .env или конфиг. Имена объектов и полей — по таблице выше.

После переключения: обновить чек-лист (отметить «Секреты перенесены в Vaultwarden») и при необходимости добавить в cron установку BW_MASTER_PASSWORD_FILE или вызов разблокировки в общем wrapperе.


Шаг 6. Тестовое восстановление одного контейнера

Без проверки восстановления нельзя считать стратегию рабочей.

  1. Выбрать некритичный контейнер (например 105 — RAG, или 107 — Invidious), для которого краткий даунтайм допустим.
  2. Убедиться, что есть свежий backup этого контейнера в Storage (после шага 3).
  3. Восстановление:
    • В Proxmox UI: Datacenter → Backup → выбрать storage → найти backup нужного CT → Restore. Указать new VMID (например 999 для теста) и Storage для дисков.
    • Или с CLI:
      qmrestore для VM, для LXC — через GUI или pct restore (см. справку pct restore). Для LXC типично: Backup → Restore → задать новый ID (например 999), node, storage.
  4. Запустить восстановленный контейнер (ID 999), проверить:
    • заходит по SSH/консоль;
    • сервисы внутри запускаются (docker/ systemd);
    • с хоста пинг и при необходимости один сервис по порту.
  5. После проверки удалить тестовый контейнер (999), освободить место.

Если что-то пошло не так (не находится диск, ошибка прав, сеть) — зафиксировать и поправить стратегию (пути storage, режим backup, права).


Шаг 7. Документировать процедуру восстановления «с нуля»

Кратко зафиксировать в отдельном разделе (здесь или в architecture):

  1. Установка Proxmox на новое железо (или новый диск).
  2. Восстановление конфигов: распаковать последний etc-pve-*.tar.gz в /etc/pve (с учётом того, что нужно корректно подставить ноды и storage; при одномузловой установке обычно достаточно скопировать файлы).
  3. Подключение storage с backup (или копирование последних vzdump на новый storage).
  4. Восстановление контейнеров и ВМ из backup по одному (Restore с указанием VMID и storage).
  5. Запуск контейнеров/ВМ, проверка сети и сервисов.
  6. Использование сохранённых паролей/ключей для входа и проверки сервисов.

После первого успешного тестового восстановления (шаг 6) эту процедуру можно уточнить и дописать по факту.


Чек-лист фазы 1

  • Разметка: 1 ТБ на sdb1, ФС, монтирование в /mnt/backup (без LUKS). (скрипт scripts/backup-setup-sdb1-mount.sh, каталоги созданы.)
  • В Proxmox добавлен Storage для VZDump → /mnt/backup/proxmox/dump.
  • Настроена регулярная задача Backup: LXC (100108), расписание ночь (02:00), retention задан. VM 200 исключена из задания (образ ~380 ГБ); восстановление VM 200 — по инструкции «с нуля» в backup-howto.
  • Проверен ручной запуск Backup now — файлы появляются в storage. (рекомендуется проверить разово.)
  • Настроен бэкап /etc/pve (скрипт + cron) → /mnt/backup/proxmox/etc-pve. (backup-etc-pve.sh, 02:15, 30 дней.)
  • Restic: cron на хосте, выгрузка каталогов из /mnt/backup в Yandex S3. (backup-restic-yandex.sh 04:00, backup-restic-yandex-photos.sh 04:10, retention 3 daily / 2 weekly / 2 monthly.)
  • Yandex: ключи и endpoint зафиксированы в /root/.restic-yandex.env, restic пишет в бакет.
  • Vaultwarden развёрнут (CT 103).
  • Секреты перенесены в Vaultwarden. (на усмотрение: root PVE, пароли БД, API и т.д.)
  • Бэкап данных Vaultwarden включён в restic (Yandex S3). Локально: backup-vaultwarden-data.sh → /mnt/backup/other/vaultwarden/; restic выгружает весь /mnt/backup (кроме photos), каталог vaultwarden входит в снимок.
  • Выполнено тестовое восстановление одного контейнера (другой VMID), проверена работоспособность. (26.02.2026: восстановлен CT 107 в слот 999 из /mnt/backup/proxmox/dump/dump/vzdump-lxc-107-*.tar.zst, проверены консоль, пинг, Docker, Invidious на 3000; тестовый CT удалён.)
  • В документации зафиксирована процедура полного восстановления Proxmox «с нуля». backup-howto.md: восстановление из vzdump, конфигов, БД, VM 200 с нуля, Vaultwarden, VPS и др.

Ссылки


Принятые решения (сводка)

Вопрос Решение
Точка монтирования, второй ТБ /mnt/backup; второй ТБ на sdb1 — в запас, назначение позже.
Шифрование (LUKS) Пока не делаем; раздел без шифрования.
Proxmox vzdump Локально в proxmox/dump + дублировать в Yandex через restic.
Фотки Оригиналы + метаданные + БД Immich; остальное пересчитать.
VPS Amnezia — конфиг. Миран — БД бота + контент (контент можно в S3 Мирана; копия на sdb1 — по желанию). Конфиг серверов не бэкапим — Ansible.
Где запускать бэкапы Cron на хосте Proxmox: Backup Job (vzdump) + restic в Yandex.
Retention локально Только в Proxmox Job и в скрипте etc-pve; отдельного restic-репозитория локально не делаем.
/etc/pve + конфиги хоста (interfaces, hosts, resolv.conf) Вариант A: cron на хосте → etc-pve и etc-host-configs в /mnt/backup/proxmox/etc-pve; локально и в Yandex (restic).
Пароли Vaultwarden на CT 103.
VM 200 (БД PostgreSQL) vzdump snapshot — для образа ВМ; консистентность БД — отдельно: внутри VM логический бэкап (pg_dump).
Yandex Бакет создан; ключи и endpoint зафиксировать при настройке restic.
MinIO Не используем; директории + restic (s3 для Yandex).

Осталось сделать

  • Проверка ручного Backup: один раз запустить «Backup now» в Proxmox UI (Datacenter → Backup) и убедиться, что файлы появляются в /mnt/backup/proxmox/dump/dump/.
  • Секреты (по желанию): перенести пароли/ключи (root PVE, БД, API) в Vaultwarden и обновлять при смене.

Выполнено ранее: Yandex + Restic (cron, retention 3/2/2), тестовое восстановление CT 107 → 999 (26.02.2026).