# Бэкапы: как устроены и как восстанавливать Краткая справка: что бэкапится, куда, когда и как восстановить. --- ## Где хранятся бэкапы Все локальные бэкапы лежат на отдельном диске хоста Proxmox: **/dev/sdb1**, смонтирован в **/mnt/backup**. ``` /mnt/backup/ ├── proxmox/ │ ├── dump/ ← vzdump (LXC и VM целиком) │ └── etc-pve/ ← конфиги хоста (etc/pve, interfaces, hosts, resolv.conf) ├── databases/ ← логические дампы БД (pg_dump) │ ├── ct101-nextcloud/ │ ├── ct103-gitea/ │ ├── ct104-paperless/ │ └── vm200-immich/ ├── photos/ │ └── library/ ← копия библиотеки Immich (оригиналы фото) с VM 200 ├── other/ │ ├── vaultwarden/ ← архив данных Vaultwarden (пароли); для restic → Yandex │ └── ct105-vectors/ ← векторы RAG (vectors.npz) из CT 105 ├── restic/ ← (опционально) └── vps/ ├── miran/ ← VPS Миран: БД бота, voice_users, копия S3 (telegram-helper-bot) └── mtproto-germany/ ← VPS Германия: конфиги MTProto + сайт katykhin.store (mtg, nginx, certs) ``` --- ## Что, откуда, куда, когда | Что | Откуда | Куда (локально) | Когда | Хранение | Уведомление | |-----|--------|------------------|------|----------|--------------| | **VPS Миран (telegram-helper-bot)** | VPS 185.147.80.190: БД `tg-bot-database.db`, каталог `voice_users`, бакет S3 (Miran) | `/mnt/backup/vps/miran/` (db/, voice_users/, s3/) | **01:00** (cron: `backup-vps-miran.sh`) | БД: 14 дней; voice_users и S3 — перезапись | 🖥️ VPS Миран | | **БД Nextcloud (PostgreSQL)** | CT 101, контейнер `nextcloud-db-1` в `/opt/nextcloud` | `/mnt/backup/databases/ct101-nextcloud/` | **01:15** (cron: `backup-ct101-pgdump.sh`) | 14 дней | 🗄️ Nextcloud (БД) | | **Оригиналы фото Immich** | VM 200, `/mnt/data/library/` | `/mnt/backup/photos/library/` | **01:30** (cron: `backup-immich-photos.sh`, rsync) | Все копии (без автоудаления) | 📷 Фото Immich (rsync) | | **Конфиги MTProto (VPS Германия)** | VPS 185.103.253.99: mtg.service, nginx (katykhin.store), Let's Encrypt, `/var/www/katykhin.store` | `/mnt/backup/vps/mtproto-germany/` (архивы mtproto-config-*.tar.gz) | **01:45** (cron: `backup-vps-mtproto.sh`) | 14 дней | 🌐 VPS MTProto (DE) | | **LXC и VM** | Все выбранные контейнеры (100–109) и VM 200 | `/mnt/backup/proxmox/dump/` | **02:00** (задание в Proxmox UI) | По настройкам задания (7 daily, 4 weekly, 6 monthly) | 💾 Backup local (cron 03:00) | | **Конфиги хоста** | `/etc/pve`, `/etc/network/interfaces`, `/etc/hosts`, `/etc/resolv.conf` | `/mnt/backup/proxmox/etc-pve/` | **02:15** (cron: `backup-etc-pve.sh`) | 30 дней | ⚙️ Конфиги хоста | | **БД Paperless (PostgreSQL)** | CT 104, контейнер `paperless-db-1` в `/opt/paperless` | `/mnt/backup/databases/ct104-paperless/` | **02:30** (cron: `backup-ct104-pgdump.sh`) | 14 дней | 🗄️ Paperless (БД) | | **Данные Vaultwarden (пароли)** | CT 103, `/opt/docker/vaultwarden/data` | `/mnt/backup/other/vaultwarden/`; каталог в restic → Yandex | **02:45** (cron: `backup-vaultwarden-data.sh`) | 14 дней | 🔐 Vaultwarden | | **БД Gitea (PostgreSQL)** | CT 103, контейнер `gitea-db-1` в `/opt/gitea` | `/mnt/backup/databases/ct103-gitea/` | **03:00** (cron: `backup-ct103-gitea-pgdump.sh`) | 14 дней | 🗄️ Gitea (БД) | | **БД Immich (PostgreSQL)** | VM 200, контейнер `database` в `/opt/immich` | `/mnt/backup/databases/vm200-immich/` | **03:15** (cron: `backup-vm200-pgdump.sh`) | 14 дней | 🗄️ Immich (БД) | | **Векторы RAG (CT 105)** | CT 105, `/home/rag-service/data/vectors/` (vectors.npz) | `/mnt/backup/other/ct105-vectors/` | **03:30** (cron: `backup-ct105-vectors.sh`) | 14 дней | 📐 Векторы RAG | | **Выгрузка в Yandex (restic)** | `/mnt/backup` без photos | Yandex Object Storage | **04:00** (cron: `backup-restic-yandex.sh`) | 3 daily, 2 weekly, 2 monthly | ☁️ Restic Yandex | | **Выгрузка в Yandex (restic, фото)** | `/mnt/backup/photos` | Yandex Object Storage (тот же репо) | **04:10** (cron: `backup-restic-yandex-photos.sh`) | 3 daily, 2 weekly, 2 monthly | 📷 Restic Yandex (photos) | **Окно бэкапов:** внутренние копии — **01:00–03:30**; выгрузка в облако — **04:00** (основной restic), **04:10** (restic фото). **05:00** зарезервировано под плановую перезагрузку сервера. Задание vzdump — из веб-интерфейса Proxmox (Центр обработки данных → Резервная копия). --- ## Восстановление ### 1. Восстановление контейнера (LXC) или виртуальной машины (VM) из vzdump **Когда нужно:** потеря или поломка одной/нескольких гостевых систем. **Через веб-интерфейс:** 1. **Центр обработки данных → Резервная копия** (или узел → Резервная копия). 2. Выбрать хранилище **backup** (или то, куда пишет задание). 3. Найти нужный бэкап по VMID и дате. 4. **Восстановить** → указать новый VMID (если восстанавливаем как копию) или тот же (если заменяем сломанный), узел и storage для дисков. 5. Запустить ВМ/контейнер и проверить доступность. **С CLI (на хосте Proxmox):** Путь к файлам бэкапа: `/mnt/backup/proxmox/dump/dump/` (имя вида `vzdump-lxc-100-YYYY_MM_DD-HH_MM_SS.tar.zst` или `vzdump-qemu-200-...`). - **LXC** — восстановить в новый VMID (например 999) на storage `local-lvm`: ```bash pct create 999 /mnt/backup/proxmox/dump/dump/vzdump-lxc-107-2026_02_26-02_03_14.tar.zst --restore 1 --storage local-lvm ``` Если восстанавливаем поверх существующего контейнера: сначала удалить его (`pct destroy 107`), затем в команде указать тот же VMID (107). Доп. опции: `pct create --help` (режим restore). - **VM (KVM)** — порядок аргументов: сначала архив, потом VMID: ```bash qm restore /mnt/backup/proxmox/dump/dump/vzdump-qemu-200-YYYY_MM_DD-HH_MM_SS.vma.zst 200 --storage local-lvm ``` У VM файлы бэкапа обычно с расширением `.vma.zst` или `.vma`. Подробнее: `qm restore --help`. **После восстановления (пример для LXC):** - Если восстановили в новый слот (например 999) и не нужен конфликт IP с оригиналом — сменить IP: `pct set 999 --net0 name=eth0,bridge=vmbr0,gw=192.168.1.1,ip=192.168.1.199/24,type=veth` - Запуск: `pct start 999` (LXC) или `qm start 200` (VM). - Проверка: пинг, консоль (`pct exec 999 -- bash`), при необходимости сервисы и порты внутри контейнера. Если vzdump есть только в Yandex (локального диска нет) — см. раздел **Восстановление из restic (Yandex)** → «Восстановление одного контейнера (vzdump)». --- ### 2. Восстановление конфигов хоста (/etc/pve и сеть) **Когда нужно:** переустановка Proxmox или потеря конфигов узла (при этом диск с бэкапами доступен). Если конфигов нет локально, но есть в Yandex — см. раздел **Восстановление из restic** → «Восстановление конфигов хоста (/etc/pve)». 1. Скопировать нужный архив с хоста, например: `etc-pve-YYYYMMDD-HHMM.tar.gz` и/или `etc-host-configs-YYYYMMDD-HHMM.tar.gz` из `/mnt/backup/proxmox/etc-pve/`. 2. **Восстановление /etc/pve** (на переустановленном хосте, от root): ```bash tar -xzf etc-pve-YYYYMMDD-HHMM.tar.gz -C / ``` При одномузловой установке обычно достаточно распаковать в `/`. При кластере — аккуратно с нодами и storage. 3. **Восстановление конфигов сети/хоста** (interfaces, hosts, resolv.conf): ```bash tar -xzf etc-host-configs-YYYYMMDD-HHMM.tar.gz -C / ``` При необходимости поправить под текущее железо (интерфейсы, IP) и перезапустить сеть. После восстановления конфигов — заново добавить storage для бэкапов (если переустанавливали с нуля) и восстанавливать гостей из vzdump по шагу 1. --- ### 3. Восстановление БД Immich (PostgreSQL) на VM 200 **Когда нужно:** повреждение или потеря базы Immich при рабочей ВМ (образ VM можно не трогать, восстанавливаем только БД). 1. Скопировать нужный дамп на VM 200, например: `immich-db-YYYYMMDD-HHMM.sql.gz` из `/mnt/backup/databases/vm200-immich/`. 2. На VM 200 (ssh [admin@192.168.1.200](mailto:admin@192.168.1.200)): ```bash cd /opt/immich gunzip -c /path/to/immich-db-YYYYMMDD-HHMM.sql.gz | docker compose exec -T database psql -U -d ``` Или распаковать `.sql.gz`, затем: `` и `` — из `/opt/immich/.env` (обычно `postgres` и `immich`). Перед восстановлением лучше остановить приложение Immich (или как минимум не писать в БД). При полной пересоздании БД — очистить каталог данных PostgreSQL в контейнере и затем загрузить дамп. --- ### 4. Восстановление библиотеки фото Immich **Когда нужно:** потеря данных на диске VM 200 (например `/mnt/data/library`). **Требование для бэкапа:** на VM 200 должен быть установлен rsync (`sudo apt install rsync`), т.к. скрипт запускает rsync по SSH с хоста. На VM 200 (или с хоста через rsync в обратную сторону): скопировать содержимое `/mnt/backup/photos/library/` обратно в каталог библиотеки Immich на VM 200 (в .env указан `UPLOAD_LOCATION`, обычно `/mnt/data/library`). Пример с хоста Proxmox: ```bash rsync -av /mnt/backup/photos/library/ admin@192.168.1.200:/mnt/data/library/ ``` После копирования на VM 200 выставить владельца/права под контейнер Immich (если нужно) и перезапустить сервисы. Если фото есть только в Yandex — см. раздел **Восстановление из restic** → «Восстановление фото (библиотека Immich)». --- ### 5. Восстановление БД Paperless (CT 104), Gitea (CT 103) **Paperless:** дамп из `/mnt/backup/databases/ct104-paperless/paperless-db-*.sql.gz`. На CT 104: остановить приложение, `gunzip -c backup.sql.gz | docker exec -i paperless-db-1 psql -U paperless -d paperless`, запустить стек. **Gitea:** дамп из `/mnt/backup/databases/ct103-gitea/gitea-db-*.sql.gz`. На CT 103: остановить Gitea, восстановить в контейнер `gitea-db-1` (psql -U gitea -d gitea), запустить стек. Если дампов нет локально — см. раздел **Восстановление из restic** → «Восстановление дампов БД». --- ### 6. Восстановление данных Vaultwarden (CT 103) Архив из `/mnt/backup/other/vaultwarden/vaultwarden-data-*.tar.gz`. На CT 103: остановить Vaultwarden, распаковать в `/opt/docker/vaultwarden/` (получится каталог `data/`), выставить владельца/права под контейнер, запустить Vaultwarden. Если архива нет локально (есть только в Yandex) — см. раздел **Восстановление из restic** → «Восстановление данных Vaultwarden (пароли)». --- ### 7. Восстановление бэкапа VPS Миран (telegram-helper-bot) **Когда нужно:** потеря данных на VPS или перенос бота на другой хост. В бэкапе есть: - **БД:** `/mnt/backup/vps/miran/db/tg-bot-database-YYYYMMDD.db` — копии SQLite. - **Голосовые сообщения:** `/mnt/backup/vps/miran/voice_users/` — каталог .ogg. - **S3 (контент бота):** `/mnt/backup/vps/miran/s3/` — полная копия бакета (photos, videos, voice и т.д.). **Восстановление на VPS:** 1. Скопировать выбранный файл БД на VPS: `scp -P 15722 /mnt/backup/vps/miran/db/tg-bot-database-YYYYMMDD.db deploy@185.147.80.190:/home/prod/bots/telegram-helper-bot/database/tg-bot-database.db` 2. Восстановить `voice_users`: `rsync -avz -e "ssh -p 15722" /mnt/backup/vps/miran/voice_users/ deploy@185.147.80.190:/home/prod/bots/telegram-helper-bot/voice_users/` 3. При потере данных в S3 — загрузить из бэкапа в бакет Miran (через aws s3 sync или панель), используя endpoint `https://api.s3.miran.ru` и креды из [VPS Миран](vps-miran-bots.md). **Требования для бэкапа:** на хосте Proxmox — SSH-ключ root → [deploy@185.147.80.190](mailto:deploy@185.147.80.190) (порт 15722); для S3 — установленный `aws` cli и файл `/root/.vps-miran-s3.env` с переменными S3_ACCESS_KEY, S3_SECRET_KEY, S3_BUCKET_NAME (см. [VPS Миран](../vps/vps-miran-bots.md)). --- ### 8. Восстановление конфигов MTProto (VPS Германия) **Когда нужно:** потеря конфигов на VPS 185.103.253.99 или перенос MTProto и сайта-заглушки на другой хост. В архиве `mtproto-config-YYYYMMDD-HHMM.tar.gz` из `/mnt/backup/vps/mtproto-germany/` лежат: - **mtg:** `etc/systemd/system/mtg.service` (в т.ч. секрет и cloak-port). - **nginx:** `etc/nginx/sites-available/`, `etc/nginx/sites-enabled/` (конфиг для katykhin.store на порту 993). - **Let's Encrypt:** `etc/letsencrypt/live/katykhin.store/`, `archive/katykhin.store/`, `renewal/katykhin.store.conf`. - **Сайт:** `var/www/katykhin.store/`. **Восстановление на VPS (от root):** скопировать архив на сервер и распаковать в корень: ```bash scp /mnt/backup/vps/mtproto-germany/mtproto-config-YYYYMMDD-HHMM.tar.gz root@185.103.253.99:/tmp/ ssh root@185.103.253.99 "tar -xzf /tmp/mtproto-config-YYYYMMDD-HHMM.tar.gz -C /" ``` После распаковки: `systemctl daemon-reload && systemctl restart mtg nginx`. На новом хосте дополнительно установить mtg, nginx, certbot и настроить ufw (см. [план MTProto + сайт](../vps/vpn-vps-mtproto-site-plan.md)). **Требования для бэкапа:** на хосте Proxmox — SSH по ключу root → [root@185.103.253.99](mailto:root@185.103.253.99) (порт 22). Ключ хоста должен быть добавлен в `authorized_keys` на VPS. --- ### 9. Восстановление векторов RAG (CT 105) Архив из `/mnt/backup/other/ct105-vectors/vectors-*.tar.gz`. Распаковать на хосте и скопировать в контейнер: `tar -xzf vectors-*.tar.gz` → затем `pct push 105 ./vectors /home/rag-service/data/` или распаковать внутри CT 105 в `/home/rag-service/data/` (получится каталог `vectors/` с `vectors.npz`). --- ### 10. Восстановление VM 200 (Immich) с нуля VM 200 **не входит** в задание vzdump (образ ~380 ГБ, не помещается в политику 7 копий). В бэкапе есть: **конфиг ВМ** (в архивах `/etc/pve`), **БД** (pg_dump), **фото** (rsync в `photos/library`). Восстановление — создание новой ВМ с теми же параметрами и перенос данных. **Что есть после восстановления хоста:** - Из бэкапа `etc-pve`: файл `/etc/pve/qemu-server/200.conf` — полное описание ВМ (CPU, память, диски, **hostpci для GPU**, сеть). Его можно использовать как образец при создании новой ВМ. - Дамп БД: `/mnt/backup/databases/vm200-immich/immich-db-*.sql.gz`. - Фото: `/mnt/backup/photos/library/`. **Ключевые параметры VM 200** (если восстанавливать вручную без конфига): - **Ресурсы:** 3 ядра, 10 GB RAM. - **GPU:** проброс видеокарты (hostpci) — в Proxmox: Hardware → Add → PCI Device → выбрать VGA/NVIDIA, поставить «All Functions» и «ROM-Bar» при необходимости. В конфиге это выглядит как `hostpci0: 0000:xx:00.0` и т.п. - **Диски:** первый — системный (~~35 GB), второй — данные (~~350 GB) под `/mnt/data` (библиотека, PostgreSQL, Docker). - **Сеть:** статический IP 192.168.1.200/24, шлюз 192.168.1.1. - **ОС:** Debian 13 (trixie), пользователь **admin**, SSH. **Порядок восстановления:** 1. **Создать ВМ 200** в Proxmox с теми же параметрами (скопировать из восстановленного `200.conf` или задать вручную: CPU, RAM, hostpci для GPU, два диска, сеть с IP 192.168.1.200). 2. **Установить ОС** (Debian 13), создать пользователя admin, настроить SSH. 3. **Разметить второй диск** и смонтировать в `/mnt/data` (как в [container-200](../containers/container-200.md)). 4. **Установить Docker**, склонировать/восстановить каталоги Immich: `/opt/immich/` (docker-compose.yml, .env — из своих заметок или копии; секреты из Vaultwarden). 5. **Создать каталоги** `/mnt/data/library`, `/mnt/data/postgres` (и др. по .env). 6. **Скопировать фото** с хоста бэкапов на ВМ: `rsync -av /mnt/backup/photos/library/ admin@192.168.1.200:/mnt/data/library/` 7. **Запустить только контейнер БД** (database), восстановить дамп (см. раздел 3 выше), затем поднять весь стек Immich. 8. Проверить NPM (прокси на 192.168.1.200:2283), при необходимости заново включить ML и настройки в Immich. Подробное описание сервисов, образов и портов — в [container-200](../containers/container-200.md). --- ## Restic и Yandex Два задания в одном репозитории: `**backup-restic-yandex.sh`** выгружает `/mnt/backup` **без** каталога `photos`; `**backup-restic-yandex-photos.sh`** выгружает только `/mnt/backup/photos` (отдельный снимок, больше всего данных). Retention у обоих: **3 daily, 2 weekly, 2 monthly**. Пароли и дампы — чувствительные данные; не выкладывать в открытый доступ. --- ## Восстановление из restic (Yandex) **Когда нужно:** локальных бэкапов нет (потеря диска, другой хост), данные есть только в Yandex Object Storage. ### Подготовка на хосте - Те же креды, что для бэкапа: `**/root/.restic-yandex.env`** (RESTIC_REPOSITORY, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY), `**/root/.restic-password**`. - Установлены **restic** и **FUSE** (для `restic mount`): `apt install restic fuse`. - Восстановление делаем **на раздел с достаточным местом** (например `/mnt/backup/restore-...`), не в `/tmp`. ### Два типа снимков в одном репо В репозитории два вида снимков (различаются по полю **Paths** в `restic snapshots`): | Paths в снимке | Откуда | Что внутри | | -------------------- | ------------------------------ | ------------------------------------------------------------------------- | | `/mnt/backup` | backup-restic-yandex.sh | Всё кроме photos: proxmox/dump, proxmox/etc-pve, databases/, other/, vps/ | | `/mnt/backup/photos` | backup-restic-yandex-photos.sh | Только каталог photos (библиотека Immich) | При восстановлении **конфигов, паролей, дампов БД, vzdump** — брать снимок с path **/mnt/backup**. При восстановлении **фото** — брать снимок с path **/mnt/backup/photos**. ```bash # Список снимков (указать нужный по Paths и дате) set -a; source /root/.restic-yandex.env; set +a export RESTIC_PASSWORD_FILE=/root/.restic-password export AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION:-ru-central1} restic snapshots ``` ### Сводка: что откуда восстанавливать | Что восстановить | Путь в снимке (основной репо) | Снимок | Способ | | -------------------- | --------------------------------- | ---------------------- | ------------------------------- | | Один LXC/VM (vzdump) | /mnt/backup/proxmox/dump/dump/... | /mnt/backup | Скрипт mount + cp (см. ниже) | | Конфиги /etc/pve | /mnt/backup/proxmox/etc-pve/ | /mnt/backup | restic restore --path ... | | Vaultwarden (пароли) | /mnt/backup/other/vaultwarden/ | /mnt/backup | restic restore --path ... | | Дампы БД | /mnt/backup/databases/... | /mnt/backup | restic restore --path ... | | VPS, other | /mnt/backup/vps/, other/ | /mnt/backup | restic restore --path ... | | Фото Immich | /mnt/backup/photos/ | **/mnt/backup/photos** | restic restore из снимка photos | --- ### Восстановление одного контейнера (vzdump) из restic Чтобы не выкачивать весь репо, используется **mount** и копирование одного файла. 1. Узнать имя нужного архива в снимке (например CT 107): ```bash restic ls latest --path /mnt/backup/proxmox/dump/dump | grep vzdump-lxc-107 ``` Использовать снимок с path `/mnt/backup` (не photos). 2. Запустить скрипт (он сам монтирует, копирует файл, размонтирует): ```bash /root/scripts/restore-one-vzdump-from-restic.sh latest /mnt/backup/proxmox/dump/dump/vzdump-lxc-107-YYYY_MM_DD-HH_MM_SS.tar.zst /mnt/backup ``` Файл появится в `/mnt/backup/vzdump-lxc-107-....tar.zst`. 3. Восстановить контейнер из файла (как в разделе 1 выше): ```bash pct create 999 /mnt/backup/vzdump-lxc-107-....tar.zst --restore 1 --storage local-lvm pct set 999 --net0 name=eth0,bridge=vmbr0,gw=192.168.1.1,ip=192.168.1.199/24,type=veth pct start 999 ``` Если скрипта нет — вручную: `restic mount /mnt/backup/restic-mount &`, подождать, скопировать из `.../restic-mount/ids//mnt/backup/proxmox/dump/dump/vzdump-lxc-107-....tar.zst` в нужное место, затем `fusermount -u /mnt/backup/restic-mount`. --- ### Восстановление конфигов хоста (/etc/pve) из restic 1. Выбрать снимок с path **/mnt/backup** (по дате): `restic snapshots`. 2. Восстановить только каталог etc-pve: ```bash restic restore SNAPSHOT_ID --target /mnt/backup/restore-etc-pve --path /mnt/backup/proxmox/etc-pve ``` Файлы появятся в `/mnt/backup/restore-etc-pve/mnt/backup/proxmox/etc-pve/` (архивы `etc-pve-*.tar.gz`, `etc-host-configs-*.tar.gz`). 3. Распаковать нужный архив в корень (как в разделе 2 выше): ```bash tar -xzf /mnt/backup/restore-etc-pve/mnt/backup/proxmox/etc-pve/etc-pve-YYYYMMDD-HHMM.tar.gz -C / tar -xzf /mnt/backup/restore-etc-pve/mnt/backup/proxmox/etc-pve/etc-host-configs-YYYYMMDD-HHMM.tar.gz -C / ``` 4. При необходимости поправить сеть и перезапустить сервисы. --- ### Восстановление данных Vaultwarden (пароли) из restic 1. Снимок с path **/mnt/backup**. 2. Восстановить каталог vaultwarden: ```bash restic restore SNAPSHOT_ID --target /mnt/backup/restore-vw --path /mnt/backup/other/vaultwarden ``` Результат: `/mnt/backup/restore-vw/mnt/backup/other/vaultwarden/vaultwarden-data-*.tar.gz`. 3. Скопировать архив на хост, откуда можно отправить на CT 103, либо распаковать во временный каталог и скопировать каталог `data/` на CT 103 в `/opt/docker/vaultwarden/` (остановив Vaultwarden). Детали — раздел 6 выше. --- ### Восстановление фото (библиотека Immich) из restic Фото лежат в **отдельном снимке** (path `/mnt/backup/photos`). Сначала выбрать этот снимок: ```bash restic snapshots | grep photos ``` Затем восстановить в каталог с достаточным местом: ```bash restic restore SNAPSHOT_ID --target /mnt/backup/restore-photos --path /mnt/backup/photos ``` Фото окажутся в `/mnt/backup/restore-photos/mnt/backup/photos/library/`. Дальше — скопировать на VM 200 (раздел 4 выше): `rsync -av /mnt/backup/restore-photos/mnt/backup/photos/library/ admin@192.168.1.200:/mnt/data/library/` --- ### Восстановление дампов БД из restic Снимок с path **/mnt/backup**. Восстановить нужный подкаталог, например только ct104-paperless: ```bash restic restore SNAPSHOT_ID --target /mnt/backup/restore-db --path /mnt/backup/databases/ct104-paperless ``` Файлы появятся в `/mnt/backup/restore-db/mnt/backup/databases/ct104-paperless/`. Дальше — восстановление БД по разделам 3 или 5 выше (скопировать дамп на контейнер и загрузить в PostgreSQL). Аналогично для других БД: `--path /mnt/backup/databases/ct101-nextcloud`, `ct103-gitea`, `vm200-immich`. --- ### Восстановление прочего (VPS, векторы RAG) из restic - **VPS Миран / MTProto:** `restic restore SNAPSHOT_ID --target /mnt/backup/restore-vps --path /mnt/backup/vps` Дальше — копировать нужные файлы на VPS по разделам 7–8. - **Векторы RAG (ct105-vectors):** `restic restore SNAPSHOT_ID --target /mnt/backup/restore-other --path /mnt/backup/other/ct105-vectors` Дальше — по разделу 9. --- ## Скрипты на хосте Proxmox | Скрипт | Назначение | Cron | |--------|------------|------| | `/root/scripts/backup-vps-miran.sh` | Бэкап VPS Миран: БД бота, voice_users, S3 (Miran) | 0 1 * * * | | `/root/scripts/backup-ct101-pgdump.sh` | Логический дамп БД Nextcloud из CT 101 | 15 1 * * * | | `/root/scripts/backup-immich-photos.sh` | Копирование библиотеки фото Immich (rsync с VM 200) | 30 1 * * * | | `/root/scripts/backup-vps-mtproto.sh` | Копирование конфигов MTProto + сайт с VPS Германия (185.103.253.99) | 45 1 * * * | | `/root/scripts/backup-etc-pve.sh` | Бэкап /etc/pve и конфигов хоста | 15 2 * * * | | `/root/scripts/backup-ct104-pgdump.sh` | Логический дамп БД Paperless из CT 104 | 30 2 * * * | | `/root/scripts/backup-vaultwarden-data.sh` | Копирование данных Vaultwarden (пароли) из CT 103 | 45 2 * * * | | `/root/scripts/backup-ct103-gitea-pgdump.sh` | Логический дамп БД Gitea из CT 103 | 0 3 * * * | | `/root/scripts/notify-vzdump-success.sh` | Проверка локального vzdump за последние 2 ч, отправка сводки в Telegram | 0 3 * * * | | `/root/scripts/backup-vm200-pgdump.sh` | Логический дамп БД Immich с VM 200 | 15 3 * * * | | `/root/scripts/backup-ct105-vectors.sh` | Копирование векторов RAG (vectors.npz) из CT 105 | 30 3 * * * | | `/root/scripts/backup-restic-yandex.sh` | Выгрузка /mnt/backup (без photos) в Yandex S3 (restic), retention 3/2/2 | 0 4 * * * | | `/root/scripts/backup-restic-yandex-photos.sh` | Выгрузка только /mnt/backup/photos в Yandex S3 (тот же репо), retention 3/2/2 | 10 4 * * * | | `/root/scripts/notify-telegram.sh` | Шлюз отправки уведомлений в Telegram (вызывают скрипты бэкапов) | — | Задание vzdump (LXC/VM) настраивается в Proxmox UI (расписание 02:00). **05:00** оставлено свободным для плановой перезагрузки сервера. ### Диагностика пустых дампов БД и архива Vaultwarden Если дампы БД (Nextcloud, Paperless, Gitea), архив Vaultwarden или векторы RAG (CT 105) получаются по 20 байт — в копию попал только пустой gzip/tar, команда внутри контейнера не отдала данные. Скрипты при размере < 512 байт завершаются с ошибкой и выводят stderr. Для векторов проверьте путь `/home/rag-service/data/vectors` в CT 105: `pct exec 105 -- ls -la /home/rag-service/data/vectors`. **Частая причина дампов БД:** PostgreSQL в контейнере требует пароль (md5/scram). Скрипты берут пароль из **Vaultwarden** (Bitwarden CLI `bw`): объекты **NEXTCLOUD** (поле `dbpassword` или пароль), **PAPERLESS**, **GITEA**. На хосте нужны: `bw`, при необходимости `jq`, разблокировка по мастер-паролю из файла `/root/.bw-master` (см. [Переключение скриптов на секреты из Vaultwarden](proxmox-phase1-backup.md#переключение-скриптов-на-секреты-из-vaultwarden) в proxmox-phase1-backup.md). **Проверка вручную (без подавления stderr):** зайти в контейнер и выполнить дамп, чтобы увидеть сообщение об ошибке: ```bash # CT 101 (Nextcloud) pct exec 101 -- docker exec nextcloud-db-1 pg_dump -U nextcloud nextcloud | head -5 # CT 104 (Paperless) pct exec 104 -- docker exec paperless-db-1 pg_dump -U paperless paperless | head -5 # CT 103 (Gitea) pct exec 103 -- docker exec gitea-db-1 pg_dump -U gitea gitea | head -5 # CT 103 (Vaultwarden) — каталог data pct exec 103 -- ls -la /opt/docker/vaultwarden/data pct exec 103 -- tar cf - -C /opt/docker/vaultwarden data | wc -c ``` **Запуск из cron и доступ к Vaultwarden (bw):** В cron окружение ограничено: часто `PATH` не содержит `/usr/local/bin`, где обычно установлен `bw`. Скрипты дампов БД (ct101, ct104, ct103) в начале задают `export PATH="/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:${PATH}"`, поэтому при запуске из cron `bw` и `jq` находятся без правки crontab. Нужно: 1) файл с мастер-паролем, например `/root/.bw-master` (chmod 600), и при необходимости переменная `BW_MASTER_PASSWORD_FILE=/root/.bw-master`; 2) один раз с интерактивной сессии: `bw config server https://vault.katykhin.ru`, `bw login` (сохранит сессию в конфиг); 3) при каждом запуске скрипт делает `bw unlock --passwordfile "$BW_MASTER_PASSWORD_FILE" --raw` и подставляет пароль БД. Если вручную дамп идёт, а из cron — нет, проверьте: наличие `/root/.bw-master`, права доступа, что `bw` доступен по этому PATH (запустите скрипт через `env -i PATH=/usr/local/bin:/usr/bin:/bin /root/scripts/backup-ct103-gitea-pgdump.sh` для имитации cron). ### Почему размер дампа меньше размера БД на диске `pg_database_size()` показывает **размер БД на диске**: данные таблиц + **индексы** + TOAST (сжатые длинные значения) + свободное место и bloat. **pg_dump** выводит только логические данные в виде SQL: самих данных индексов в дампе нет (только команды `CREATE INDEX`), поэтому несжатый дамп часто **меньше** размера БД. После gzip сжатие даёт ещё примерно 2,5–4×. Итог: БД 2 GB на диске → несжатый дамп 200–600 MB → сжатый 50–200  MB нормален (особенно для Nextcloud с большими индексами по `oc_filecache`). Если сомневаетесь, проверьте несжатый размер и число таблиц: ```bash # Несжатый размер дампа (на хосте) gunzip -c /mnt/backup/databases/ct101-nextcloud/nextcloud-db-YYYYMMDD-HHMM.sql.gz | wc -c # Таблиц в дампе gunzip -c /mnt/backup/databases/ct101-nextcloud/nextcloud-db-YYYYMMDD-HHMM.sql.gz | grep -c '^CREATE TABLE ' # Таблиц в живой БД (в контейнере) pct exec 101 -- docker exec nextcloud-db-1 psql -U nextcloud -d nextcloud -t -c "SELECT count(*) FROM information_schema.tables WHERE table_schema = 'public';" ``` Числа таблиц должны совпадать. Несжатый размер для Nextcloud 2 GB на диске обычно 200–600  MB. При необходимости запустите бэкап с проверкой: `VERIFY_BACKUP=1 /root/scripts/backup-ct101-pgdump.sh` — скрипт выведет несжатый размер и число таблиц в дампе. --- ## Уведомления в Telegram После **успешного** выполнения каждого бэкапа в Telegram отправляется короткое сообщение (заголовок с эмодзи + краткая сводка). Уведомления приходят по завершении соответствующего скрипта; для локального vzdump — по cron в **03:00** (проверка файлов за последние 2 часа). | Заголовок | Когда | Тело сообщения | |-----------|------|----------------| | 🖥️ VPS Миран | после 01:00 | Резервное копирование завершено. БД, voice_users, S3 (telegram-helper-bot). Размер копии: X. | | 🗄️ Nextcloud (БД) | после 01:15 | Резервное копирование завершено. Дамп БД Nextcloud. Размер: X. | | 📷 Фото Immich (rsync) | после 01:30 | Резервное копирование завершено. Библиотека фото синхронизирована. Размер: X. | | 🌐 VPS MTProto (DE) | после 01:45 | Резервное копирование завершено. Конфиги MTProto и сайт (VPS DE). Размер архива: X. | | 💾 Backup local | 03:00 | Резервное копирование завершено. Локальный vzdump (LXC/VM). Контейнеров/ВМ: N, объём: X ГБ. Время завершения: HH:MM. | | ⚙️ Конфиги хоста | после 02:15 | Резервное копирование завершено. Архивы /etc/pve и конфигов сети. Размер: X. | | 🗄️ Paperless (БД) | после 02:30 | Резервное копирование завершено. Дамп БД Paperless. Размер: X. | | 🔐 Vaultwarden | после 02:45 | Резервное копирование завершено. Данные Vaultwarden. Размер архива: X. | | 🗄️ Gitea (БД) | после 03:00 | Резервное копирование завершено. Дамп БД Gitea. Размер: X. | | 🗄️ Immich (БД) | после 03:15 | Резервное копирование завершено. Дамп БД Immich. Размер: X. | | 📐 Векторы RAG | после 03:30 | Резервное копирование завершено. Архив векторов RAG. Размер: X. | | ☁️ Restic Yandex | после 04:00 | Резервное копирование завершено. Снимок в Yandex: N файлов, размер X. | | 📷 Restic Yandex (photos) | после 04:10 | Резервное копирование завершено. Снимок фото в Yandex: N файлов, размер X. | **Размер в сообщениях** — фактический размер файла (apparent size), а не занятое место на диске. Если видите **4.0K** или **8.0K** у дампа БД или архива Vaultwarden — копия может быть пустой или почти пустой (ошибка доступа к контейнеру, пустая БД, неверный путь). Скрипты при размере ниже порога (10 KB для дампов БД и Vaultwarden, 1 KB для MTProto) добавляют в сообщение строку: *«⚠️ Подозрительно малый размер — проверьте…»*. В этом случае проверьте на хосте: имя контейнера БД, путь к данным, логи скрипта. **Единая точка отправки (шлюз):** скрипт **`/root/scripts/notify-telegram.sh`**. Все источники уведомлений вызывают только его и не обращаются к Telegram API напрямую. Токен и chat_id хранятся в одном конфиге на хосте Proxmox. **Конфиг на хосте:** `/root/.telegram-notify.env` с переменными `TELEGRAM_BOT_TOKEN` и `TELEGRAM_CHAT_ID`. В репозитории лежит пример: **`scripts/telegram-notify.env.example`** — скопируйте его на хост в `/root/.telegram-notify.env` и подставьте свои значения: ```bash cp /path/to/scripts/telegram-notify.env.example /root/.telegram-notify.env chmod 600 /root/.telegram-notify.env ``` **Как получить креды:** 1. **Токен бота:** в Telegram написать [@BotFather](https://t.me/BotFather), команда `/newbot`, следовать подсказкам — получите токен вида `123456789:ABCdef...`. 2. **Chat ID:** отправить боту любое сообщение, затем в браузере открыть `https://api.telegram.org/bot/getUpdates` В ответе в `updates[].message.chat.id` — ваш chat_id (число; для групп — отрицательное). Если конфига или кредов нет, шлюз тихо выходит с 0 и не ломает вызывающие скрипты. **Позже** тот же шлюз можно вызывать с VM 200 или с VPS (например по SSH на хост Proxmox) — отдельно не реализовано, архитектура это допускает. --- ## Связанные документы - [Стратегия бэкапов (фаза 1)](proxmox-phase1-backup.md) — общий план и принятые решения. - [Архитектура](../architecture/architecture.md) — хост, IP, доступ. - [VM 200 (Immich)](../containers/container-200.md) — сервисы, пути, .env.