Docs/docs/11-backup.md
2026-04-13 15:32:22 +05:00

794 lines
25 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 11. Резервное копирование
## Обзор
Резервное копирование критически важно для защиты данных и возможности восстановления после сбоев, ошибок или атак.
**Текущий статус (апрель 2026)**: ✅ **Настроена полнофункциональная система резервного копирования на базе Proxmox Backup Server**
- Отдельный физический сервер PBS (192.168.1.199)
- Хранилище 1 TB с дедупликацией и компрессией
- Автоматические бэкапы всех критичных систем
- Протестированное восстановление
- ✅ Настроены уведомления в Telegram о статусе задач
---
## Текущее состояние
### ✅ Настроено и работает
| Компонент | Статус | Описание |
|-----------|--------|----------|
| **Proxmox Backup Server** | ✅ | Отдельный сервер (Olimpbs, 192.168.1.199) |
| **Хранилище** | ✅ | 1 TB (LVM), datastore `olimpbkp` |
| **Бэкапы ВМ/LXC** | ✅ | Автоматические, по расписанию |
| **Дедупликация** | ✅ | Встроена в PBS |
| **Компрессия** | ✅ | ZSTD (fast and good) |
| **Расписание** | ✅ | 2 раза в день (02:30 и 22:30) |
| **Retention** | ✅ | 14 последних, 7 ежедневных, 4 недельных, 4 месячных |
| **Режим** | ✅ | Snapshot (без остановки сервисов) |
| **Уведомления** | ✅ | Telegram-бот через Python-реле (порт 8085) |
### 📊 Архитектура
```mermaid
graph TD
A["Proxmox VE Host<br/>Olimp 192.168.1.200"] --> B["LXC Containers<br/>201-211"]
A --> C["Virtual Machines<br/>205, 213"]
A -->|Network| D["Proxmox Backup Server<br/>Olimpbs 192.168.1.199"]
D --> E["Datastore: olimpbkp<br/>1 TB LVM"]
E --> F["/var/lib/proxmox-backup/olimpbkp"]
D -->|Python Relay 8085| G["Telegram API<br/>api.telegram.org"]
G -->|SOCKS5 1080| H["XRay Proxy<br/>2.27.50.20:2054"]
```
---
## Что бэкапится
### LXC Контейнеры (10 шт.)
| ID | Имя | Тип данных | Примерный размер |
|----|-----|------------|------------------|
| **201** | gateway | Конфигурации, прокси | ~5 GB |
| **202** | data | Базы данных (BookStack, Mealie) | ~10 GB |
| **203** | media | Конфигурации Jellyfin, метаданные | ~60 GB* |
| **204** | photo | Immich конфиги | ~20 GB |
| **206** | talk | Matrix, XMPP конфиги | ~10 GB |
| **207** | games | Конфигурации игровых серверов | ~20 GB |
| **208** | manage | Grafana, Loki, мониторинг | ~15 GB |
| **209** | git | GitLab репозитории | ~30 GB |
| **210** | ansible | Ansible конфиги, vault | ~5 GB |
| **211** | torrent | qBittorrent настройки | ~5 GB |
*Без медиафайлов (исключены из бэкапа)
### Виртуальные машины (2 шт.)
| ID | Имя | Тип данных | Примерный размер |
|----|-----|------------|------------------|
| **205** | Nextcloud | Файлы, БД PostgreSQL | ~10 GB |
| **213** | VPN | OpenVPN/WireGuard конфиги | ~12 GB |
### Исключено из бэкапа
- **Большие диски** (16 TB RAID6): медиафайлы, игры, загрузки
- **Причина**: занимают слишком много места, можно восстановить из источников
- **Что включено**: только конфигурации и метаданные (через `backup=1`)
---
## Расписание бэкапов
### Автоматическое расписание
**Два раза в день**:
- **02:30** — ночной бэкап
- **22:30** — вечерний бэкап
**Proxmox Backup Server автоматически определяет**:
- Первый бэкап — **полный**
- Последующие — **инкрементальные** (только изменения)
- Периодически — **полный** для целостности данных
### Retention политика
| Тип хранения | Количество | Фактический срок |
|--------------|------------|------------------|
| **Keep Last** | 14 | Минимум 14 последних бэкапов |
| **Keep Daily** | 7 | 7 ежедневных копий |
| **Keep Weekly** | 4 | 4 недельных копии |
| **Keep Monthly** | 4 | 4 месячных копии |
**Итого**: ~1-2 месяца истории бэкапов
---
## Текущая конфигурация
### На Proxmox VE (Olimp)
**Хранилище подключено**:
- **ID**: `olimpbkp`
- **Тип**: Proxmox Backup Server
- **Server**: 192.168.1.199:8007
- **Datastore**: `olimpbkp`
- **Content**: Backup
- **Status**: ✅ Enabled
**Backup Job**:
```text
Node: Olimp
Storage: olimpbkp
Schedule: 02:30, 22:30 (daily)
Mode: Snapshot
Compression: ZSTD
VM/CT: 201-211, 205, 213
Retention: keep-last=14, keep-daily=7, keep-weekly=4, keep-monthly=4
```
### На PBS (Olimpbs)
**Datastore**:
```text
Name: olimpbkp
Path: /var/lib/proxmox-backup/olimpbkp
Size: 1 TB (912 GB available)
GC Schedule: daily
Prune Schedule: daily
```
**Пользователи**:
- `root@pam` — администратор (веб-интерфейс)
- `pve@pbs` — для Proxmox VE (API токен)
---
## Управление бэкапами
### Просмотр бэкапов
**Через веб-интерфейс PBS**:
```text
https://192.168.1.199:8007
→ Datastore → olimpbkp → Content
```
**Через Proxmox VE**:
```text
https://192.168.1.220:8006
→ Datacenter → Storage → olimpbkp → Content
```
**Через CLI**:
```bash
# Список бэкапов
proxmox-backup-client list --repository root@pam@192.168.1.199:8007:olimpbkp
# Детальная информация
proxmox-backup-client show-backup --repository root@pam@192.168.1.199:8007:olimpbkp ct/201
# Статистика datastore
proxmox-backup-client datastore stats olimpbkp
```
### Ручной запуск бэкапа
**Один контейнер/ВМ**:
```bash
vzdump 201 --storage olimpbkp --mode snapshot --compress zstd
```
**Все бэкапируемые системы**:
```bash
for id in 201 202 203 204 205 206 207 208 209 210 211 213; do
vzdump $id --storage olimpbkp --mode snapshot --compress zstd &
done
wait
```
### Восстановление из бэкапа
**Через веб-интерфейс Proxmox VE**:
1. Datacenter → Storage → olimpbkp → Content
2. Выбрать бэкап → Restore
3. Указать:
- **Storage**: целевое хранилище (local-lvm, vmsystem)
- **VMID**: новый ID (или существующий для перезаписи)
4. Start
**Через CLI**:
```bash
# LXC контейнер
pct restore 216 olimpbkp:backup/ct/201/2026-04-11T13:19:03Z --storage local-lvm
# Виртуальная машина
qm restore 216 olimpbkp:backup/vm/205/2026-04-11T13:19:03Z --storage vmsystem
```
### Восстановление отдельных файлов
**Через File Restore**:
1. PBS веб-интерфейс → Datastore → Content
2. Выбрать бэкап → **File Restore**
3. Смонтировать бэкап
4. Скачать нужные файлы
5. Unmount
**Через CLI**:
```bash
# Смонтировать бэкап
mkdir -p /mnt/restore
proxmox-backup-client mount ct/201/2026-04-11T13:19:03Z /mnt/restore \
--repository root@pam@192.168.1.199:8007:olimpbkp
# Скопировать файлы
cp /mnt/restore/root.pxar/etc/config/file.conf /tmp/
# Размонтировать
proxmox-backup-client unmount /mnt/restore
```
---
## Мониторинг и обслуживание
### Проверка статуса бэкапов
**Ежедневная проверка**:
```bash
# Последние задачи
pvesm status olimpbkp
# Логи бэкапов
tail -f /var/log/pve/tasks/*
# Проверка места на PBS
ssh root@192.168.1.199 "df -h /var/lib/proxmox-backup/olimpbkp"
```
### Garbage Collection (очистка)
PBS автоматически запускает GC ежедневно. Вручную:
```bash
# На PBS сервере
proxmox-backup-manager garbage-collection start olimpbkp
# Проверка статуса
proxmox-backup-manager garbage-collection status olimpbkp
```
### Prune (удаление старых бэкапов)
Автоматически по retention политике. Вручную:
```bash
proxmox-backup-manager prune-job run <job-id>
```
### Проверка целостности (Verify)
```bash
# Проверить все бэкапы
proxmox-backup-manager verify olimpbkp
# Проверить конкретный бэкап
proxmox-backup-client verify ct/201/2026-04-11T13:19:03Z \
--repository root@pam@192.168.1.199:8007:olimpbkp
```
---
## 📦 Уведомления в Telegram (через Python-реле)
### 🎯 Цель
Получать красивые уведомления в Telegram о статусе бэкапов с форматированием времени и эмодзи.
### 📋 Предварительные требования
- Сервер с доступом в интернет через прокси (XRay SOCKS5)
- Telegram бот: токен и chat_id
- Python 3 установлен
---
### 🔧 Настройка Python-реле (универсальный способ)
**1. Создай скрипт реле:**
```bash
cat > /usr/local/bin/telegram-relay.py << 'EOF'
#!/usr/bin/env python3
import socket
import subprocess
import sys
import re
PORT = 8085
BOT_TOKEN = "7657027552:AAHQ6OGDRbm6wtqh_4GOQr7jd6C0BAQMyF4"
CHAT_ID = "292909723"
PROXY = "socks5://127.0.0.1:1080"
def format_duration(seconds):
try:
sec = float(seconds)
if sec < 60:
return f"{int(sec)} сек"
elif sec < 3600:
return f"{int(sec // 60)} мин"
elif sec < 86400:
hours = int(sec // 3600)
mins = int((sec % 3600) // 60)
return f"{hours} ч {mins} мин" if mins > 0 else f"{hours} ч"
else:
return f"{int(sec // 86400)} дн"
except:
return str(seconds)
def get_icon(backup):
return "💻" if backup.startswith('vm-') else "📦" if backup.startswith('ct-') else "🗄️"
def send_telegram(text):
try:
cmd = [
'curl', '-sx', PROXY, '-s',
f'https://api.telegram.org/bot{BOT_TOKEN}/sendMessage',
'-H', 'Content-Type: application/json',
'-d', f'{{"chat_id":"{CHAT_ID}","text":"{text}","parse_mode":"Markdown"}}'
]
subprocess.run(cmd, timeout=10, capture_output=True)
return True
except:
return False
def handle_client(client_socket, addr):
try:
data = b""
client_socket.settimeout(2)
while True:
try:
chunk = client_socket.recv(4096)
if not chunk:
break
data += chunk
except socket.timeout:
break
data = data.decode('utf-8', errors='ignore')
body = data.split('\r\n\r\n', 1)[1] if '\r\n\r\n' in data else data
backups = re.findall(r'"backup"\s*:\s*"([^"]+)"', body)
statuses = re.findall(r'"status"\s*:\s*"([^"]+)"', body)
values = re.findall(r'value=([\d.]+)', body)
if not backups:
client_socket.send(b"HTTP/1.1 200 OK\r\n\r\nOK")
return
# Отправляем порциями по 5 (чтобы влезло в лимит Telegram)
CHUNK = 5
for i in range(0, len(backups), CHUNK):
chunk_backups = backups[i:i+CHUNK]
text = "🚨 *Backup Alert*\n\n"
for j, backup in enumerate(chunk_backups):
idx = i + j
status = statuses[idx] if idx < len(statuses) else "unknown"
icon = get_icon(backup)
if len(values) >= (idx * 2 + 1):
seconds = float(values[idx * 2])
human_time = format_duration(seconds)
desc = f"Последний бэкап: {human_time} назад"
else:
desc = "Нет данных"
status_emoji = "🔥" if status == "firing" else "✅"
text += f"{icon} *{backup}*\n⏱ {desc}\nStatus: {status_emoji} *{status}*\n\n"
send_telegram(text)
client_socket.send(b"HTTP/1.1 200 OK\r\nContent-Length: 2\r\nConnection: close\r\n\r\nOK")
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
try:
client_socket.send(b"HTTP/1.1 500 Error\r\n\r\n")
except:
pass
finally:
try:
client_socket.close()
except:
pass
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(('0.0.0.0', PORT))
server.listen(10)
print(f"▶ Relay on {PORT}", file=sys.stderr)
while True:
client, addr = server.accept()
handle_client(client, addr)
EOF
chmod +x /usr/local/bin/telegram-relay.py
```
**2. Создай systemd-сервис:**
```bash
cat > /etc/systemd/system/telegram-relay.service << 'EOF'
[Unit]
Description=Telegram Relay via Xray (Python+curl)
After=network.target xray-client.service
Requires=xray-client.service
[Service]
Type=simple
ExecStart=/usr/bin/python3 /usr/local/bin/telegram-relay.py
Restart=always
RestartSec=3
User=root
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now telegram-relay
```
**3. Проверь что работает:**
```bash
# Статус сервиса
systemctl status telegram-relay
# Проверка порта
ss -tlnp | grep 8085
# Тест
curl -X POST http://127.0.0.1:8085 -d "🎉 Test message"
```
Должно прийти сообщение в Telegram!
---
### 🔧 Настройка в Grafana (если используешь мониторинг)
**1. Contact Points → Add new:**
| Поле | Значение |
|------|----------|
| **Name** | `Telegram Relay` |
| **Type** | `Webhook` |
| **URL** | `http://192.168.1.208:8085` |
| **HTTP Method** | `POST` |
| **Max Alerts** | `0` (без лимита) |
**2. Сообщение (Message):**
```bash
{{ range .Alerts }}
📦 {{ .Labels.backup }}
{{ .Annotations.description }}
Status: {{ if eq .Status "firing" }}🔥{{ else }}{{ end }} {{ .Status }}
{{ end }}
```
**3. В Alert Rule → Annotations → Description:**
```bash
{{ .Value }}
```
*(Python-скрипт сам превратит секунды в "11 ч 35 мин")*
**4. Протестируй:**
- Contact Point → **Test**
- Должно прийти красивое уведомление
---
### 🔧 Настройка в Proxmox Backup Server (прямые уведомления)
Если хочешь уведомления напрямую из PBS (без Grafana):
**1. Создай endpoint (webhook):**
```bash
proxmox-backup-manager notification endpoint webhook create telegram \
--url "http://192.168.1.208:8085" \
--method post \
--header "Content-Type: application/json"
```
**2. Создай matcher для ошибок:**
```bash
proxmox-backup-manager notification matcher create backup-error \
--endpoint telegram \
--cal-filter backup \
--severity error
```
**3. Создай matcher для успехов (опционально):**
```bash
proxmox-backup-manager notification matcher create backup-success \
--endpoint telegram \
--cal-filter backup \
--severity info
```
**4. Протестируй:**
```bash
proxmox-backup-manager notification target test telegram
```
---
### 📝 Переменные для замены
| Переменная | Описание | Пример |
|------------|----------|--------|
| `BOT_TOKEN` | Токен Telegram бота | `7657027552:AAHQ6OGDRbm6wtqh_4GOQr7jd6C0BAQMyF4` |
| `CHAT_ID` | ID чата для уведомлений | `292909723` |
| `PROXY` | SOCKS5 прокси (XRay) | `socks5://127.0.0.1:1080` |
| `PORT` | Порт реле (локальный) | `8085` |
| `GRAFANA_HOST` | IP сервера с Grafana | `192.168.1.208` |
---
### 📁 Файлы конфигурации
| Файл | Назначение |
|------|------------|
| `/usr/local/bin/telegram-relay.py` | Python-скрипт реле |
| `/etc/systemd/system/telegram-relay.service` | systemd-юнит |
| `/var/log/syslog` | Логи (через journalctl) |
---
### 🧪 Тестирование
**1. Проверка соединения с Telegram:**
```bash
curl -sx socks5://127.0.0.1:1080 \
https://api.telegram.org/bot$BOT_TOKEN/getMe
```
**2. Проверка реле:**
```bash
curl -X POST http://127.0.0.1:8085 \
-H "Content-Type: application/json" \
-d '{"text":"✅ Relay is working!"}'
```
**3. Просмотр логов:**
```bash
journalctl -u telegram-relay -f
```
---
### 🔍 Troubleshooting
| Проблема | Решение |
|----------|---------|
| Не приходит сообщение | Проверь `journalctl -u telegram-relay -n 20` |
| Ошибка 400 от Telegram | Убери `parse_mode` или экранируй спецсимволы |
| Реле не слушает порт | `systemctl restart telegram-relay` |
| XRay не подключается | Проверь `systemctl status xray-client` |
| Сообщение обрезается | Скрипт разбивает на части по 5 бэкапов — это норма |
---
### 🎨 Формат уведомления
Пример того, что придёт в Telegram:
```mermaid
🚨 Backup Alert
📦 ct-201
⏱ Последний бэкап: 11 ч 35 мин назад
Status: 🔥 firing
📦 ct-202
⏱ Последний бэкап: 11 ч 34 мин назад
Status: 🔥 firing
💻 vm-205
⏱ Последний бэкап: 11 ч 30 мин назад
Status: ✅ resolved
```
**Эмодзи:**
- 💻 — виртуальные машины (vm-*)
- 📦 — LXC контейнеры (ct-*)
- 🔥 — статус firing (проблема)
- ✅ — статус resolved (всё ок)
---
### 🔄 Обновление скрипта
Если нужно изменить формат или логику:
```bash
# Останови сервис
systemctl stop telegram-relay
# Отредактируй скрипт
nano /usr/local/bin/telegram-relay.py
# Запусти снова
systemctl start telegram-relay
# Проверь статус
systemctl status telegram-relay
```
---
## Безопасность
### Аутентификация
- **PBS пользователи**: `root@pam`, `pve@pbs`
- **API токены**: для автоматизации (без паролей)
- **Fingerprint**: SHA-256 отпечаток сертификата
### Сетевая безопасность
- **Порт**: 8007 (TCP)
- **Шифрование**: TLS 1.3
- **Доступ**: только из локальной сети (192.168.1.0/24)
### Рекомендации
- ✅ Включить **2FA** для доступа к PBS
- ✅ Создать **отдельного пользователя** для бэкапов (не root)
- ✅ Настроить **firewall** на PBS сервере
- ✅ Регулярно **обновлять** систему (unattended-upgrades)
---
## Планы на будущее
### 🔵 Краткосрочные (1-2 месяца)
- [x] Настроить **уведомления** (Telegram) о статусе бэкапов
- [ ] Включить **2FA** для доступа к PBS
- [ ] Настроить **репликацию** в облако (Backblaze B2 / Wasabi)
- [ ] Провести **тестовое восстановление** всех критичных ВМ
### 🔵 Долгосрочные (3-6 месяцев)
- [ ] Добавить **второй PBS** для репликации
- [ ] Настроить **оффсайт-копии** (внешний диск + облако)
- [ ] Внедрить **шифрование** бэкапов на стороне клиента
- [ ] Автоматизировать **тестирование восстановления**
---
## Troubleshooting
### Бэкап не запускается
```bash
# Проверить хранилище
pvesm status | grep olimpbkp
# Проверить подключение к PBS
ping 192.168.1.199
nc -zv 192.168.1.199 8007
# Переподключить хранилище
pvesm remove olimpbkp
pvesm add proxmox-backup olimpbkp \
--server 192.168.1.199 \
--datastore olimpbkp \
--username pve@pbs
```
### Закончилось место на PBS
```bash
# Проверить занятое место
proxmox-backup-client datastore stats olimpbkp
# Запустить GC
proxmox-backup-manager garbage-collection start olimpbkp
# Удалить старые бэкапы вручную
proxmox-backup-client prune \
--repository root@pam@192.168.1.199:8007:olimpbkp \
--max-daily 7 --max-weekly 2
```
### Ошибка аутентификации PBS
```bash
# Сгенерировать новый токен
proxmox-backup-manager user generate-token pve@pbs backup-token
# Обновить в Proxmox VE
pvesm update olimpbkp --password <новый_токен>
```
### Проблемы с уведомлениями в Telegram
| Проблема | Решение |
|----------|---------|
| Не приходят уведомления | Проверить `curl -s https://api.telegram.org/bot<TOKEN>/getMe` |
| Реле не работает | `journalctl -u telegram-relay -n 20 --no-pager` |
| XRay не запускается | `systemctl status xray-client` |
| Дубликат уведомлений | Проверить Max Alerts в Contact Point |
---
## Полезные команды
### На Proxmox VE
```bash
# Список хранилищ
pvesm list
# Статус бэкап хранилища
pvesm status olimpbkp
# Запустить бэкап
vzdump <vmid> --storage olimpbkp --mode snapshot
# Восстановить
pct restore <new-vmid> olimpbkp:backup/ct/<ctid>/<timestamp>
qm restore <new-vmid> olimpbkp:backup/vm/<vmid>/<timestamp>
```
### На PBS
```bash
# Список datastore
proxmox-backup-manager datastore list
# Статистика
proxmox-backup-client datastore stats olimpbkp
# Список бэкапов
proxmox-backup-client list --repository root@pam@192.168.1.199:8007:olimpbkp
# Информация о бэкапе
proxmox-backup-client show-backup ct/201 --repository root@pam@192.168.1.199:8007:olimpbkp
# Проверка целостности
proxmox-backup-manager verify olimpbkp
# Garbage collection
proxmox-backup-manager garbage-collection start olimpbkp
```
---
## Метрики и отчётность
### Ежедневная проверка
```bash
# Размер бэкапов за сегодня
du -sh /var/lib/proxmox-backup/olimpbkp/data/*
# Количество бэкапов
proxmox-backup-client list --repository root@pam@192.168.1.199:8007:olimpbkp | wc -l
# Свободное место
df -h /var/lib/proxmox-backup/olimpbkp
```
### Еженедельный отчёт
```bash
# Дедупликация
proxmox-backup-client datastore stats olimpbkp | grep "Deduplication"
# Прирост за неделю
# Сравнить размер datastore с прошлой неделей
```
---
**Связанные разделы:**
- [Гипервизор Proxmox](02-hypervisor.md)
- [Виртуальные машины и LXC](03-vms-lxcs.md)
- [Безопасность](10-security.md)
- [Мониторинг и логирование](08-monitoring.md)