From 48cd3642633994f9498555ef22cb8c7bba2c0a5d Mon Sep 17 00:00:00 2001 From: Administrator Date: Mon, 13 Apr 2026 16:21:41 +0500 Subject: [PATCH] Update file 11-backup.md --- docs/11-backup.md | 438 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 346 insertions(+), 92 deletions(-) diff --git a/docs/11-backup.md b/docs/11-backup.md index f514617..05991b5 100644 --- a/docs/11-backup.md +++ b/docs/11-backup.md @@ -28,7 +28,7 @@ | **Расписание** | ✅ | 2 раза в день (02:30 и 22:30) | | **Retention** | ✅ | 14 последних, 7 ежедневных, 4 недельных, 4 месячных | | **Режим** | ✅ | Snapshot (без остановки сервисов) | -| **Уведомления** | ✅ | Telegram-бот через Python-реле (порт 8085) | +| **Уведомления** | ✅ | Telegram-бот через прокси (XRay + Redsocks) | ### 📊 Архитектура @@ -39,8 +39,7 @@ graph TD 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 -->|Python Relay 8085| G["Telegram API
api.telegram.org"] - G -->|SOCKS5 1080| H["XRay Proxy
2.27.50.20:2054"] + D -->|HTTPS via proxy| G["Telegram API
api.telegram.org"] ``` --- @@ -279,19 +278,272 @@ proxmox-backup-client verify ct/201/2026-04-11T13:19:03Z \ --- -## 📦 Уведомления в Telegram (через Python-реле) +## 📦 Уведомления в Telegram ### 🎯 Цель -Получать красивые уведомления в 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 часов | ### 📋 Предварительные требования -- Сервер с доступом в интернет через прокси (XRay SOCKS5) +- PBS сервер (192.168.1.199) с доступом в интернет через прокси - Telegram бот: токен и chat_id -- Python 3 установлен +- Прокси: 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"] +``` --- -### 🔧 Настройка Python-реле (универсальный способ) +### 🔧 Шаг 1: Установка Python-реле **1. Создай скрипт реле:** @@ -309,6 +561,7 @@ CHAT_ID = "292909723" PROXY = "socks5://127.0.0.1:1080" def format_duration(seconds): + """Преобразует секунды в читаемый формат""" try: sec = float(seconds) if sec < 60: @@ -325,9 +578,11 @@ def format_duration(seconds): return str(seconds) def get_icon(backup): + """Выбирает эмодзи по имени бэкапа""" return "💻" if backup.startswith('vm-') else "📦" if backup.startswith('ct-') else "🗄️" def send_telegram(text): + """Отправляет текст в Telegram через прокси""" try: cmd = [ 'curl', '-sx', PROXY, '-s', @@ -342,6 +597,7 @@ def send_telegram(text): def handle_client(client_socket, addr): try: + # Читаем запрос частями data = b"" client_socket.settimeout(2) while True: @@ -356,6 +612,7 @@ def handle_client(client_socket, addr): 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) @@ -375,6 +632,7 @@ def handle_client(client_socket, addr): 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) @@ -401,14 +659,16 @@ def handle_client(client_socket, addr): 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) +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 @@ -440,10 +700,10 @@ systemctl daemon-reload systemctl enable --now telegram-relay ``` -**3. Проверь что работает:** +**3. Проверь работу:** ```bash -# Статус сервиса +# Проверка статуса systemctl status telegram-relay # Проверка порта @@ -457,88 +717,107 @@ curl -X POST http://127.0.0.1:8085 -d "🎉 Test message" --- -### 🔧 Настройка в Grafana (если используешь мониторинг) +### 🔧 Шаг 2: Настройка Contact Point в Grafana -**1. Contact Points → Add new:** +**1. Открой Grafana:** +- Перейди: **Alerting** → **Contact points** +- Нажми **+ Add contact point** + +**2. Заполни поля:** | Поле | Значение | |------|----------| | **Name** | `Telegram Relay` | -| **Type** | `Webhook` | -| **URL** | `http://192.168.1.208:8085` | +| **Integration** | `Webhook` | +| **URL** | `http://127.0.0.1:8085` | | **HTTP Method** | `POST` | | **Max Alerts** | `0` (без лимита) | -**2. Сообщение (Message):** -```bash +**3. Сообщение (Message):** + +```text {{ range .Alerts }} 📦 {{ .Labels.backup }} ⏱ {{ .Annotations.description }} Status: {{ if eq .Status "firing" }}🔥{{ else }}✅{{ end }} {{ .Status }} +--- {{ end }} ``` -**3. В Alert Rule → Annotations → Description:** -```bash +**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. Протестируй:** -- Contact Point → **Test** -- Должно прийти красивое уведомление +**4. Notifications:** +- Выбери Contact Point: `Telegram Relay` + +**5. Сохрани правило** --- -### 🔧 Настройка в Proxmox Backup Server (прямые уведомления) +### 🔧 Шаг 4: Проверка -Если хочешь уведомления напрямую из PBS (без Grafana): - -**1. Создай endpoint (webhook):** +**1. Проверка реле:** ```bash -proxmox-backup-manager notification endpoint webhook create telegram \ - --url "http://192.168.1.208:8085" \ - --method post \ - --header "Content-Type: application/json" +# Логи реле +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. Создай matcher для ошибок:** +**2. Проверка XRay:** ```bash -proxmox-backup-manager notification matcher create backup-error \ - --endpoint telegram \ - --cal-filter backup \ - --severity error +# Статус XRay +systemctl status xray-client + +# Тест соединения с Telegram +curl -sx socks5://127.0.0.1:1080 \ + https://api.telegram.org/bot7657027552:AAHQ6OGDRbm6wtqh_4GOQr7jd6C0BAQMyF4/getMe ``` -**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 -``` +**3. Тест алерта:** +- В Grafana: Contact Point → **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` | +| `PROXY` | SOCKS5 прокси | `socks5://127.0.0.1:1080` | +| `PORT` | Порт реле | `8085` | --- @@ -548,32 +827,7 @@ proxmox-backup-manager notification target test telegram |------|------------| | `/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 -``` +| `/etc/grafana/provisioning/alerting/` | Конфиги алертов Grafana | --- @@ -581,25 +835,28 @@ journalctl -u telegram-relay -f | Проблема | Решение | |----------|---------| -| Не приходит сообщение | Проверь `journalctl -u telegram-relay -n 20` | +| Не приходит сообщение | `journalctl -u telegram-relay -n 20` | | Ошибка 400 от Telegram | Убери `parse_mode` или экранируй спецсимволы | | Реле не слушает порт | `systemctl restart telegram-relay` | -| XRay не подключается | Проверь `systemctl status xray-client` | +| XRay не подключается | `systemctl status xray-client` | | Сообщение обрезается | Скрипт разбивает на части по 5 бэкапов — это норма | +| Grafana не шлёт | Проверь что Alert Rule в состоянии "Firing" | --- -### 🎨 Формат уведомления +### 🎨 Пример уведомления -Пример того, что придёт в Telegram: -```mermaid +```text 🚨 Backup Alert + 📦 ct-201 ⏱ Последний бэкап: 11 ч 35 мин назад Status: 🔥 firing + 📦 ct-202 ⏱ Последний бэкап: 11 ч 34 мин назад Status: 🔥 firing + 💻 vm-205 ⏱ Последний бэкап: 11 ч 30 мин назад Status: ✅ resolved @@ -615,8 +872,6 @@ Status: ✅ resolved ### 🔄 Обновление скрипта -Если нужно изменить формат или логику: - ```bash # Останови сервис systemctl stop telegram-relay @@ -630,7 +885,6 @@ systemctl start telegram-relay # Проверь статус systemctl status telegram-relay ``` - --- ## Безопасность @@ -646,7 +900,7 @@ systemctl status telegram-relay - **Доступ**: только из локальной сети (192.168.1.0/24) ### Рекомендации -- ✅ Включить **2FA** для доступа к PBS +- ✅ Включить **2FA** для `root@pam` - ✅ Создать **отдельного пользователя** для бэкапов (не root) - ✅ Настроить **firewall** на PBS сервере - ✅ Регулярно **обновлять** систему (unattended-upgrades) @@ -715,9 +969,9 @@ pvesm update olimpbkp --password <новый_токен> | Проблема | Решение | |----------|---------| | Не приходят уведомления | Проверить `curl -s https://api.telegram.org/bot/getMe` | -| Реле не работает | `journalctl -u telegram-relay -n 20 --no-pager` | -| XRay не запускается | `systemctl status xray-client` | -| Дубликат уведомлений | Проверить Max Alerts в Contact Point | +| Ошибка iptables | Перезапустить `/usr/local/bin/telegram-proxy.sh` | +| XRay не запускается | `journalctl -u xray-client -n 20 --no-pager` | +| Дубликат уведомлений | Удалить `/var/run/pbs-notify-lastline` и пересоздать | ---