Update file 11-backup.md

This commit is contained in:
Administrator 2026-04-13 15:32:22 +05:00
parent f6f8b93443
commit fec26119d1

View File

@ -28,7 +28,7 @@
| **Расписание** | ✅ | 2 раза в день (02:30 и 22:30) |
| **Retention** | ✅ | 14 последних, 7 ежедневных, 4 недельных, 4 месячных |
| **Режим** | ✅ | Snapshot (без остановки сервисов) |
| **Уведомления** | ✅ | Telegram-бот через прокси (XRay + Redsocks) |
| **Уведомления** | ✅ | Telegram-бот через Python-реле (порт 8085) |
### 📊 Архитектура
@ -39,7 +39,8 @@ graph TD
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 -->|HTTPS via proxy| G["Telegram API<br/>api.telegram.org"]
D -->|Python Relay 8085| G["Telegram API<br/>api.telegram.org"]
G -->|SOCKS5 1080| H["XRay Proxy<br/>2.27.50.20:2054"]
```
---
@ -278,248 +279,357 @@ proxmox-backup-client verify ct/201/2026-04-11T13:19:03Z \
---
## 📦 Уведомления в Telegram
## 📦 Уведомления в Telegram (через Python-реле)
### 🎯 Цель
Получать уведомления в Telegram об успешных/неудачных бэкапах с Proxmox Backup Server, без изменений на гипервизоре.
Получать красивые уведомления в Telegram о статусе бэкапов с форматированием времени и эмодзи.
### 📋 Предварительные требования
- PBS сервер (192.168.1.199) с доступом в интернет через прокси
- Сервер с доступом в интернет через прокси (XRay SOCKS5)
- Telegram бот: токен и chat_id
- Прокси: VLESS+Reality на `2.27.50.20:2054`
- Python 3 установлен
### 🔧 Настройка прокси (XRay + Redsocks + iptables)
---
### 🔧 Настройка Python-реле (универсальный способ)
**1. Создай скрипт реле:**
**1. Установка XRay клиента**
```bash
# Установка зависимостей
apt update && apt install unzip curl iptables -y
cat > /usr/local/bin/telegram-relay.py << 'EOF'
#!/usr/bin/env python3
import socket
import subprocess
import sys
import re
# Скачиваем 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/
PORT = 8085
BOT_TOKEN = "7657027552:AAHQ6OGDRbm6wtqh_4GOQr7jd6C0BAQMyF4"
CHAT_ID = "292909723"
PROXY = "socks5://127.0.0.1:1080"
# Проверка
xray version
```
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)
**2. Конфигурация XRay**
```bash
mkdir -p /usr/local/etc/xray
def get_icon(backup):
return "💻" if backup.startswith('vm-') else "📦" if backup.startswith('ct-') else "🗄️"
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"}
]
}
}
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
```
**3. Запуск XRay как сервис**
**2. Создай systemd-сервис:**
```bash
cat > /etc/systemd/system/xray-client.service << 'EOF'
cat > /etc/systemd/system/telegram-relay.service << 'EOF'
[Unit]
Description=XRay Client
After=network.target
Description=Telegram Relay via Xray (Python+curl)
After=network.target xray-client.service
Requires=xray-client.service
[Service]
Type=simple
ExecStart=/usr/local/bin/xray run -config /usr/local/etc/xray/config.json
Restart=on-failure
RestartSec=5
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 xray-client
systemctl status xray-client
systemctl enable --now telegram-relay
```
**4. Установка и настройка Redsocks**
**3. Проверь что работает:**
```bash
# Установка
apt install redsocks -y
# Статус сервиса
systemctl status telegram-relay
# Конфигурация
cat > /etc/redsocks.conf << 'EOF'
base {
log_debug = off;
log_info = off;
log = stderr;
daemon = on;
redirector = iptables;
}
# Проверка порта
ss -tlnp | grep 8085
redsocks {
bind = "0.0.0.0:12345";
relay = "127.0.0.1:1080";
type = socks5;
autoproxy = 0;
timeout = 10;
}
EOF
# Запуск
systemctl enable --now redsocks
# Тест
curl -X POST http://127.0.0.1:8085 -d "🎉 Test message"
```
**5. Настройка iptables для Telegram**
Должно прийти сообщение в 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
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
{{ range .Alerts }}
📦 {{ .Labels.backup }}
⏱ {{ .Annotations.description }}
Status: {{ if eq .Status "firing" }}🔥{{ else }}✅{{ end }} {{ .Status }}
{{ end }}
```
**6. Проверка соединения**
**3. В Alert Rule → Annotations → Description:**
```bash
curl -s "https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getMe"
{{ .Value }}
```
*Ожидаемый результат*: JSON с информацией о боте.
### 🔧 Скрипт уведомлений
*(Python-скрипт сам превратит секунды в "11 ч 35 мин")*
**4. Протестируй:**
- Contact Point → **Test**
- Должно прийти красивое уведомление
---
### 🔧 Настройка в Proxmox Backup Server (прямые уведомления)
Если хочешь уведомления напрямую из PBS (без Grafana):
**1. Создай endpoint (webhook):**
**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
proxmox-backup-manager notification endpoint webhook create telegram \
--url "http://192.168.1.208:8085" \
--method post \
--header "Content-Type: application/json"
```
**8. Настройка Cron (каждые 5 минут)**
**2. Создай matcher для ошибок:**
```bash
echo "*/5 * * * * root /usr/local/bin/pbs-backup-notify.sh" >> /etc/cron.d/pbs-notify
proxmox-backup-manager notification matcher create backup-error \
--endpoint telegram \
--cal-filter backup \
--severity error
```
**9. Инициализация и тест**
**3. Создай matcher для успехов (опционально):**
```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
proxmox-backup-manager notification matcher create backup-success \
--endpoint telegram \
--cal-filter backup \
--severity info
```
**4. Протестируй:**
```bash
proxmox-backup-manager notification target test telegram
```
---
### 📝 Переменные для замены
| Переменная | Описание | Пример |
|------------|----------|--------|
| `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` |
| `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/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 задача |
| `/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
```
---
@ -536,7 +646,7 @@ wc -l < /var/log/proxmox-backup/tasks/archive
- **Доступ**: только из локальной сети (192.168.1.0/24)
### Рекомендации
- ✅ Включить **2FA** для `root@pam`
- ✅ Включить **2FA** для доступа к PBS
- ✅ Создать **отдельного пользователя** для бэкапов (не root)
- ✅ Настроить **firewall** на PBS сервере
- ✅ Регулярно **обновлять** систему (unattended-upgrades)
@ -605,9 +715,9 @@ pvesm update olimpbkp --password <новый_токен>
| Проблема | Решение |
|----------|---------|
| Не приходят уведомления | Проверить `curl -s https://api.telegram.org/bot<TOKEN>/getMe` |
| Ошибка iptables | Перезапустить `/usr/local/bin/telegram-proxy.sh` |
| XRay не запускается | `journalctl -u xray-client -n 20 --no-pager` |
| Дубликат уведомлений | Удалить `/var/run/pbs-notify-lastline` и пересоздать |
| Реле не работает | `journalctl -u telegram-relay -n 20 --no-pager` |
| XRay не запускается | `systemctl status xray-client` |
| Дубликат уведомлений | Проверить Max Alerts в Contact Point |
---