# 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-бот через прокси (XRay + Redsocks) | ### 📊 Архитектура ```mermaid graph TD A["Proxmox VE Host
Olimp 192.168.1.200"] --> B["LXC Containers
201-211"] A --> C["Virtual Machines
205, 213"] A -->|Network| D["Proxmox Backup Server
Olimpbs 192.168.1.199"] D --> E["Datastore: olimpbkp
1 TB LVM"] E --> F["/var/lib/proxmox-backup/olimpbkp"] D -->|HTTPS via proxy| G["Telegram API
api.telegram.org"] ``` --- ## Что бэкапится ### 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 ``` ### Проверка целостности (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 ### 🎯 Цель Получать уведомления в Telegram об успешных/неудачных бэкапах с Proxmox Backup Server, без изменений на гипервизоре. В системе настроено **два независимых канала** уведомлений в Telegram: | Тип | Источник | Сервер | Порт реле | Что уведомляет | |-----|----------|--------|-----------|----------------| | **PBS Backup Notifications** | Proxmox Backup Server | 192.168.1.199 | 8085 | ✅ Успешные/❌ неудачные бэкапы | | **Grafana Alerts** | VictoriaMetrics + Grafana | 192.168.1.208 | 8085 | ⚠️ Бэкапы старше 24 часов | ### 📋 Предварительные требования - PBS сервер (192.168.1.199) с доступом в интернет через прокси - Telegram бот: токен и chat_id - Прокси: VLESS+Reality на `2.27.50.20:2054` ### 🔧 Настройка прокси (XRay + Redsocks + iptables) **1. Установка XRay клиента** ```bash # Установка зависимостей apt update && apt install unzip curl iptables -y # Скачиваем XRay cd /tmp curl -L -o xray.zip https://github.com/XTLS/Xray-core/releases/latest/download/Xray-linux-64.zip unzip xray.zip chmod +x xray mv xray geoip.dat geosite.dat /usr/local/bin/ # Проверка xray version ``` **2. Конфигурация XRay** ```bash mkdir -p /usr/local/etc/xray cat > /usr/local/etc/xray/config.json << 'EOF' { "log": {"loglevel": "warning"}, "inbounds": [{"port": 1080, "listen": "127.0.0.1", "protocol": "socks", "settings": {"auth": "noauth", "udp": true}}], "outbounds": [ { "protocol": "vless", "settings": { "vnext": [{ "address": "2.27.50.20", "port": 2054, "users": [{"id": "68f44a38-396d-48da-b832-79b5dc5716ab", "encryption": "none", "level": 8}] }] }, "streamSettings": { "network": "xhttp", "security": "reality", "realitySettings": { "serverName": "cloud.zailon.ru", "publicKey": "TOyddQCTdSpycmO20uiLOqMABuKabpwVhw57tWmvJws", "shortId": "174fc0", "spiderX": "/" }, "xhttpSettings": { "host": "", "path": "/remote.php/dav/upload", "mode": "stream-one" } }, "tag": "proxy" }, {"protocol": "freedom", "tag": "direct"} ], "routing": { "rules": [ {"type": "field", "ip": ["geoip:private"], "outboundTag": "direct"}, {"type": "field", "domain": ["api.telegram.org"], "outboundTag": "proxy"} ] } } EOF ``` **3. Запуск XRay как сервис** ```bash cat > /etc/systemd/system/xray-client.service << 'EOF' [Unit] Description=XRay Client After=network.target [Service] Type=simple ExecStart=/usr/local/bin/xray run -config /usr/local/etc/xray/config.json Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable --now xray-client systemctl status xray-client ``` **4. Установка и настройка Redsocks** ```bash # Установка apt install redsocks -y # Конфигурация cat > /etc/redsocks.conf << 'EOF' base { log_debug = off; log_info = off; log = stderr; daemon = on; redirector = iptables; } redsocks { bind = "0.0.0.0:12345"; relay = "127.0.0.1:1080"; type = socks5; autoproxy = 0; timeout = 10; } EOF # Запуск systemctl enable --now redsocks ``` **5. Настройка iptables для Telegram** ```bash cat > /usr/local/bin/telegram-proxy.sh << 'EOF' #!/bin/bash iptables -t nat -F TELEGRAM_PROXY 2>/dev/null iptables -t nat -X TELEGRAM_PROXY 2>/dev/null iptables -t nat -N TELEGRAM_PROXY # Telegram IP ranges iptables -t nat -A TELEGRAM_PROXY -p tcp -d 149.154.160.0/20 -j REDIRECT --to-ports 12345 iptables -t nat -A TELEGRAM_PROXY -p tcp -d 91.108.4.0/22 -j REDIRECT --to-ports 12345 iptables -t nat -A OUTPUT -p tcp --dport 443 -j TELEGRAM_PROXY EOF chmod +x /usr/local/bin/telegram-proxy.sh /usr/local/bin/telegram-proxy.sh ``` **6. Проверка соединения** ```bash curl -s "https://api.telegram.org/bot/getMe" ``` *Ожидаемый результат*: JSON с информацией о боте. ### 🔧 Скрипт уведомлений **7. Создание скрипта** ```bash cat > /usr/local/bin/pbs-backup-notify.sh << 'EOF' #!/bin/bash TOKEN="YOUR_BOT_TOKEN" CHAT="YOUR_CHAT_ID" ARCHIVE="/var/log/proxmox-backup/tasks/archive" STATE="/var/run/pbs-notify-lastline" # Получаем последнюю обработанную строку LAST_LINE=$(cat $STATE 2>/dev/null || echo 0) CURR_LINE=$(wc -l < $ARCHIVE) # Если файл уменьшился - начинаем сначала if [ "$CURR_LINE" -lt "$LAST_LINE" ]; then LAST_LINE=0 fi # Читаем новые строки if [ "$CURR_LINE" -gt "$LAST_LINE" ]; then tail -n +$((LAST_LINE + 1)) $ARCHIVE | while IFS= read -r line; do # Только backup задачи if echo "$line" | grep -q ":backup:"; then # Извлекаем имя бэкапа (конвертируем \x3a в :) BACKUP=$(echo "$line" | grep -oP 'backup:\K[^:]+' | sed 's/\\x3a/:/g') STATUS=$(echo "$line" | grep -oP 'OK|FAILED|ERROR') TIME=$(date '+%Y-%m-%d %H:%M:%S') if [ "$STATUS" = "OK" ]; then curl -s -X POST "https://api.telegram.org/bot$TOKEN/sendMessage" \ -H "Content-Type: application/json" \ -d "{\"chat_id\":\"$CHAT\",\"text\":\"✅ *Backup Success*\\n📦 $BACKUP\\n⏰ $TIME\",\"parse_mode\":\"Markdown\"}" > /dev/null else curl -s -X POST "https://api.telegram.org/bot$TOKEN/sendMessage" \ -H "Content-Type: application/json" \ -d "{\"chat_id\":\"$CHAT\",\"text\":\"❌ *Backup Failed*\\n📦 $BACKUP\\n⏰ $TIME\\n📝 Status: $STATUS\",\"parse_mode\":\"Markdown\"}" > /dev/null fi fi done fi # Сохраняем позицию echo $CURR_LINE > $STATE EOF chmod +x /usr/local/bin/pbs-backup-notify.sh ``` **8. Настройка Cron (каждые 5 минут)** ```bash echo "*/5 * * * * root /usr/local/bin/pbs-backup-notify.sh" >> /etc/cron.d/pbs-notify ``` **9. Инициализация и тест** ```bash # Сброс состояния для теста echo "0" > /var/run/pbs-notify-lastline # Запуск вручную /usr/local/bin/pbs-backup-notify.sh # Проверка состояния cat /var/run/pbs-notify-lastline wc -l < /var/log/proxmox-backup/tasks/archive ``` ### 📝 Переменные для замены | Переменная | Описание | Пример | |------------|----------|--------| | `YOUR_BOT_TOKEN` | Токен Telegram бота | `7657027552:AAHQ6OGDRbm6wtqh_4GOQr7jd6C0BAQMyF4` | | `YOUR_CHAT_ID` | ID чата для уведомлений | `292909723` | | `address` | Адрес прокси-сервера | `2.27.50.20` | | `port` | Порт прокси | `2054` | | `id` | UUID пользователя VLESS | `68f44a38-396d-48da-b832-79b5dc5716ab` | | `publicKey` | Публичный ключ Reality | `TOyddQCTdSpycmO20uiLOqMABuKabpwVhw57tWmvJws` | | `serverName` | Домен для Reality | `cloud.zailon.ru` | ### 📁 Файлы конфигурации | Файл | Назначение | |------|------------| | `/usr/local/etc/xray/config.json` | Конфиг XRay прокси | | `/etc/redsocks.conf` | Конфиг Redsocks | | `/usr/local/bin/telegram-proxy.sh` | Правила iptables для Telegram | | `/usr/local/bin/pbs-backup-notify.sh` | Скрипт уведомлений | | `/var/run/pbs-notify-lastline` | Позиция последнего прочитанного лога | | `/etc/cron.d/pbs-notify` | Cron задача | ## 📦 Настройка уведомлений из Grafana в Telegram ### 🎯 Цель Настроить отправку алертов из Grafana в Telegram с красивым форматированием, эмодзи и автоматическим преобразованием времени. ### 📋 Архитектура ```mermaid graph LR A["Grafana
192.168.1.208"] -->|HTTP POST| B["Python Relay
localhost:8085"] B -->|SOCKS5| C["XRay Client
127.0.0.1:1080"] C -->|HTTPS| D["Telegram API
api.telegram.org"] ``` --- ### 🔧 Шаг 0: Установка XRay (если не установлен) **XRay нужен для проксирования запросов в Telegram.** **1. Установи зависимости:** ```bash apt update && apt install unzip curl iptables -y ``` **2. Скачай и установи XRay:** ```bash cd /tmp curl -L -o xray.zip https://github.com/XTLS/Xray-core/releases/latest/download/Xray-linux-64.zip unzip xray.zip chmod +x xray mv xray geoip.dat geosite.dat /usr/local/bin/ # Проверка xray version ``` **3. Создай конфигурацию:** ```bash mkdir -p /usr/local/etc/xray cat > /usr/local/etc/xray/config.json << 'EOF' { "log": {"loglevel": "warning"}, "inbounds": [ { "port": 1080, "listen": "127.0.0.1", "protocol": "socks", "settings": {"auth": "noauth", "udp": true} } ], "outbounds": [ { "protocol": "vless", "settings": { "vnext": [{ "address": "2.27.50.20", "port": 2054, "users": [{"id": "68f44a38-396d-48da-b832-79b5dc5716ab", "encryption": "none", "level": 8}] }] }, "streamSettings": { "network": "xhttp", "security": "reality", "realitySettings": { "serverName": "cloud.zailon.ru", "publicKey": "TOyddQCTdSpycmO20uiLOqMABuKabpwVhw57tWmvJws", "shortId": "174fc0", "spiderX": "/" }, "xhttpSettings": { "host": "", "path": "/remote.php/dav/upload", "mode": "stream-one" } }, "tag": "proxy" }, {"protocol": "freedom", "tag": "direct"} ], "routing": { "rules": [ {"type": "field", "ip": ["geoip:private"], "outboundTag": "direct"}, {"type": "field", "domain": ["api.telegram.org"], "outboundTag": "proxy"} ] } } EOF ``` **4. Создай systemd-сервис:** ```bash cat > /etc/systemd/system/xray-client.service << 'EOF' [Unit] Description=XRay Client After=network.target [Service] Type=simple ExecStart=/usr/local/bin/xray run -config /usr/local/etc/xray/config.json Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable --now xray-client ``` **5. Проверь работу:** ```bash systemctl status xray-client # Тест соединения curl -sx socks5://127.0.0.1:1080 \ https://api.telegram.org/bot7657027552:AAHQ6OGDRbm6wtqh_4GOQr7jd6C0BAQMyF4/getMe ``` Должен вернуться JSON с информацией о боте. --- ### 🔧 Шаг 2: Установка 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 # Парсим JSON от Grafana backups = re.findall(r'"backup"\s*:\s*"([^"]+)"', body) statuses = re.findall(r'"status"\s*:\s*"([^"]+)"', body) values = re.findall(r'value=([\d.]+)', body) # Если нашли бэкапы — форматируем как алерт if backups: 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) else: # Если не JSON от Grafana — отправляем как есть (для тестов) # Очищаем от служебных символов clean_text = body.strip().replace('\r', '').replace('\n', ' ') if clean_text and len(clean_text) < 4000: send_telegram(clean_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"▶ Telegram Relay on {PORT}", file=sys.stderr) while True: client, addr = server.accept() print(f"← {addr}", file=sys.stderr) 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! --- ### 🔧 Шаг 2: Настройка Contact Point в Grafana **1. Открой Grafana:** - Перейди: **Alerting** → **Contact points** - Нажми **+ Add contact point** **2. Заполни поля:** | Поле | Значение | |------|----------| | **Name** | `Telegram Relay` | | **Integration** | `Webhook` | | **URL** | `http://127.0.0.1:8085` | | **HTTP Method** | `POST` | | **Max Alerts** | `0` (без лимита) | **3. Сообщение (Message):** ```text {{ range .Alerts }} 📦 {{ .Labels.backup }} ⏱ {{ .Annotations.description }} Status: {{ if eq .Status "firing" }}🔥{{ else }}✅{{ end }} {{ .Status }} --- {{ end }} ``` **4. Сохрани:** - Нажми **Save contact point** - Нажми **Test** — должно прийти сообщение --- ### 🔧 Шаг 3: Создание Alert Rule **1. Перейди:** **Alerting** → **Alert rules** → **+ New alert rule** **2. Query и условие:** | Поле | Значение | |------|----------| | **Query** | `time() - last_over_time(pbs_backup_timestamp[1h])/1000` | | **Alert condition** | `A is above 86400` | | **Evaluation group** | `Backup alerts` (создать новый) | | **Evaluation interval** | `1m` | | **Pending period** | `1m` | **3. Annotations → Description:** ```text {{ .Value }} ``` *(Python-скрипт сам превратит секунды в "11 ч 35 мин")* **4. Notifications:** - Выбери Contact Point: `Telegram Relay` **5. Сохрани правило** --- ### 🔧 Шаг 4: Проверка **1. Проверка реле:** ```bash # Логи реле journalctl -u telegram-relay -f # Тестовый запрос curl -X POST http://127.0.0.1:8085 \ -H "Content-Type: application/json" \ -d '{"text":"✅ Grafana relay test"}' ``` **2. Проверка XRay:** ```bash # Статус XRay systemctl status xray-client # Тест соединения с Telegram curl -sx socks5://127.0.0.1:1080 \ https://api.telegram.org/bot7657027552:AAHQ6OGDRbm6wtqh_4GOQr7jd6C0BAQMyF4/getMe ``` **3. Тест алерта:** - В Grafana: Contact Point → **Test** - Должно прийти сообщение в Telegram --- ### 📝 Переменные для замены | Переменная | Описание | Значение | |------------|----------|----------| | `BOT_TOKEN` | Токен Telegram бота | `7657027552:AAHQ6OGDRbm6wtqh_4GOQr7jd6C0BAQMyF4` | | `CHAT_ID` | ID чата для уведомлений | `292909723` | | `PROXY` | SOCKS5 прокси | `socks5://127.0.0.1:1080` | | `PORT` | Порт реле | `8085` | --- ### 📁 Файлы конфигурации | Файл | Назначение | |------|------------| | `/usr/local/bin/telegram-relay.py` | Python-скрипт реле | | `/etc/systemd/system/telegram-relay.service` | systemd-юнит | | `/etc/grafana/provisioning/alerting/` | Конфиги алертов Grafana | --- ### 🔍 Troubleshooting | Проблема | Решение | |----------|---------| | Не приходит сообщение | `journalctl -u telegram-relay -n 20` | | Ошибка 400 от Telegram | Убери `parse_mode` или экранируй спецсимволы | | Реле не слушает порт | `systemctl restart telegram-relay` | | XRay не подключается | `systemctl status xray-client` | | Сообщение обрезается | Скрипт разбивает на части по 5 бэкапов — это норма | | Grafana не шлёт | Проверь что Alert Rule в состоянии "Firing" | --- ### 🎨 Пример уведомления ```text 🚨 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** для `root@pam` - ✅ Создать **отдельного пользователя** для бэкапов (не 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/getMe` | | Ошибка iptables | Перезапустить `/usr/local/bin/telegram-proxy.sh` | | XRay не запускается | `journalctl -u xray-client -n 20 --no-pager` | | Дубликат уведомлений | Удалить `/var/run/pbs-notify-lastline` и пересоздать | --- ## Полезные команды ### На Proxmox VE ```bash # Список хранилищ pvesm list # Статус бэкап хранилища pvesm status olimpbkp # Запустить бэкап vzdump --storage olimpbkp --mode snapshot # Восстановить pct restore olimpbkp:backup/ct// qm restore olimpbkp:backup/vm// ``` ### На 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)