结论先行:拥有 2 台以上 VPS 的独立开发者,多节点资源监控首选 Beszel。架构极简(Hub-Agent 模式),Hub 端用 Docker 一行启动(内存仅占 30MB,默认端口 8090),各节点 Agent 单二进制常驻(内存占用不到 10MB,通信端口 45876)。相比动辄消耗数百兆内存的 Prometheus + Grafana 全家桶轻量 90% 以上,又比只能探测存活的 Uptime Kuma 补齐了 CPU、内存、磁盘与 Docker 容器负载指标,配置 Telegram 机器人即可实现秒级故障与爆盘预警。
你的 VPS 数量从 1 台变成 3 台,手动逐台 SSH 敲 htop 查看负载已经力不从心。等到用户报错甚至磁盘被日志撑爆时再去排查,往往为时已晚。本篇为你梳理从零搭建 Beszel 集中化资源监控中心的完整操作。
0、写在前面
很多出海独立开发者经历过这样的尴尬时刻:
- 博客、API、数据库分散在不同区域的廉价 VPS 上;
- 某个爬虫疯狂抓取导致 CPU 持续跑满,或者某项服务内存泄漏触发 OOM 崩溃,自己却毫不知情;
- 磁盘被轮转失控的容器日志塞满,导致连 SSH 终端都无法分配 pty 登录。
传统的企业级监控方案对于独立开发者过于繁重:
- Prometheus + Grafana:功能全面,但每个组件常驻消耗数百 MB 内存,配置报警规则(Alertmanager)陡峭复杂;
- Zabbix:重度依赖传统数据库,运维负担过重;
- Uptime Kuma:优秀的 HTTP 存活探针,但不提供服务器内部的 CPU、内存和磁盘 IO 统计。
Beszel 正好切中独立开发者的甜区:轻量、优雅、原生支持 Docker 容器指标聚合,几分钟即可交付全景监控。
1、期望目标
阅读并按本指南实操后,你将达成以下目标:
- [ ] 在主控服务器上通过 Docker Compose 一键启动 Beszel Hub;
- [ ] 在被监控节点上安装轻量 Agent,并建立安全的端到端通讯;
- [ ] 挂载 Docker 套接字,实时展示各微服务容器的资源占用;
- [ ] 设定 CPU > 80%、磁盘 > 90% 以及节点心跳超时自动告警;
- [ ] 绑定 Telegram Bot,实现故障告警实时推送到手机;
- [ ] 使用 Caddy 或 Nginx 配置反向代理与 HTTPS 加密,保护监控看板。
2、技术架构与横向对比
2.1 Hub-Agent 架构模型
2.2 常见监控方案量化对比
| 指标维度 |
Prometheus + Grafana |
Netdata |
Uptime Kuma |
Beszel (推荐) |
| 主控端内存开销 |
300MB ~ 800MB |
150MB ~ 300MB |
80MB ~ 120MB |
~30MB |
| 客户端 Agent 开销 |
50MB ~ 100MB |
100MB+ |
无 Agent (外部探活) |
< 10MB |
| 监控指标深度 |
极深 (全量时序指标) |
极深 (秒级细节) |
浅 (仅 HTTP/端口存活) |
中 (聚焦 CPU/内存/磁盘/Docker) |
| 多服务器汇总看板 |
需手写 PromQL 与看板 |
需接入官方云服务 |
需手动逐个配探针 |
原生支持多机列表与卡片 |
| 部署与上手难度 |
高 (配置多层文件) |
中 |
低 |
极低 (5分钟一条命令搞定) |
3、在主控 VPS 上部署 Beszel Hub
3.1 创建部署目录与生产级编排文件
选择一台网络连通性较好的 VPS 充当 Hub。创建生产级 docker-compose.yml,配置健康检查与资源硬限制:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| version: '3.8'
services: beszel-hub: image: henrygd/beszel:latest container_name: beszel-hub restart: unless-stopped ports: - "127.0.0.1:8090:8090" volumes: - ./data:/beszel_data environment: - TZ=UTC - APP_URL=https://monitor.yourdomain.com deploy: resources: limits: cpus: '0.50' memory: 128M logging: driver: "json-file" options: max-size: "10m" max-file: "3" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:8090/api/health"] interval: 30s timeout: 5s retries: 3
|
启动主控端服务:
1 2 3 4
| mkdir -p ~/beszel/data cd ~/beszel docker compose up -d docker compose ps
|
4、在被监控节点上安装与加固 Beszel Agent
4.1 方案 A:原生 Systemd 服务配置(无 Docker 节点推荐)
在被监控的纯 Linux 主机上,推荐采用原生二进制部署。创建专用运行用户与 systemd unit 文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| [Unit] Description=Beszel Agent Monitoring Daemon After=network.target
[Service] Type=simple User=root
ExecStart=/opt/beszel-agent/beszel-agent Restart=always RestartSec=5 EnvironmentFile=/etc/beszel-agent.env
ProtectSystem=full NoNewPrivileges=true MemoryMax=40M CPUQuota=10%
[Install] WantedBy=multi-user.target
|
创建环境配置文件 /etc/beszel-agent.env:
1 2 3 4
| PORT=45876 KEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI..." FILESYSTEM=/dev/root EXTRA_FILESYSTEMS=
|
重载并启动 systemd 守护进程:
1 2 3
| sudo systemctl daemon-reload sudo systemctl enable --now beszel-agent sudo systemctl status beszel-agent
|
4.2 方案 B:容器化 Agent 部署(Docker 环境)
若目标服务器已部署 Docker 环境,采用 Compose 部署。为了避免直接暴露 root 权限的 Docker 套接字,推荐搭配只读 Socket 代理 tecnativa/docker-socket-proxy 协同运行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| version: '3.8'
services: docker-proxy: image: tecnativa/docker-socket-proxy:latest container_name: docker-socket-proxy restart: unless-stopped environment: - CONTAINERS=1 - STATS=1 - POST=0 - DELETE=0 volumes: - /var/run/docker.sock:/var/run/docker.sock:ro ports: - "127.0.0.1:2375:2375"
beszel-agent: image: henrygd/beszel-agent:latest container_name: beszel-agent restart: unless-stopped network_mode: host depends_on: - docker-proxy volumes: - /:/extra-filesystems/root:ro environment: - PORT=45876 - KEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI..." - DOCKER_HOST=tcp://127.0.0.1:2375
|
5、网络安全与防火墙收敛规则
千万不要把 Agent 通信端口 45876 对全球 IP 开放。必须严格收紧访问源:
1 2 3 4 5 6
| sudo ufw default deny incoming sudo ufw allow 22/tcp comment 'SSH' sudo ufw allow proto tcp from <HUB_PUBLIC_IP> to any port 45876 comment 'Beszel Hub Poll' sudo ufw enable sudo ufw reload
|
验证防火墙规则生效情况:
6、生产级反向代理与 HTTPS 加固配置
6.1 Caddy 反向代理配置
编辑 /etc/caddy/Caddyfile:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| monitor.yourdomain.com { encode gzip zstd
# 安全响应头 header { Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" X-Content-Type-Options "nosniff" X-Frame-Options "DENY" Referrer-Policy "strict-origin-when-cross-origin" }
reverse_proxy 127.0.0.1:8090 { # 支持长连接与实时 SSE/WebSocket 推送 header_up X-Real-IP {remote_host} header_up X-Forwarded-For {remote_host} header_up X-Forwarded-Proto {scheme} } }
|
6.2 Nginx 反向代理配置(含 WebSocket / SSE 支持)
编辑 /etc/nginx/sites-available/beszel.conf:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| server { listen 80; server_name monitor.yourdomain.com; return 301 https://$host$request_uri; }
server { listen 443 ssl http2; server_name monitor.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/monitor.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/monitor.yourdomain.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5;
location / { proxy_pass http://127.0.0.1:8090; proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";
proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 86400s; proxy_send_timeout 86400s; } }
|
7、告警规则与 Telegram 通知配置
单看图表仍属被动运维,必须建立主动通知链路。
7.1 获取 Telegram Bot Token 与 Chat ID
- 在 Telegram 搜索并打开
@BotFather,发送 /newbot,按向导命名后获取 BOT_TOKEN(形如 7123456789:AAF-xxxxxxxxxxxxxxxxxxxx);
- 打开新建的机器人对话窗口,点击 Start 发送一条初始消息;
- 搜索并打开
@userinfobot,发送任意字符获取你个人的 Id(纯数字 Chat ID,例如 123456789)。
7.2 在 Beszel 控制面板配置通知与阈值
进入 Beszel Hub 的 Settings -> Notifications:
- Provider:选择
Telegram;
- Token:填入上述
BOT_TOKEN;
- Chat ID:填入你的用户或群组
Chat ID;
- 点击 Send Test 按钮,手机端即刻收到测试告警弹窗。
接着在 Alerts 规则中配置黄金防线:
- CPU Alert:使用率持续 5 分钟超过 85% 报警;
- Memory Alert:内存使用率超过 90% 报警;
- Disk Alert:任一挂载磁盘使用率超过 88% 立即报警(留出运维缓冲期);
- Status Alert:主机失联超过 2 分钟立即报警。
8、实战排错与常用运维指令
8.1 连通性排查
在 Hub 服务器上执行网络探针,核验与目标节点 Agent 的连通性:
1 2 3 4 5 6 7 8 9
| nc -zv <AGENT_IP> 45876
sudo systemctl status beszel-agent
|
8.2 数据备份与恢复
Beszel Hub 的所有历史监控数据、节点公钥与告警规则均保存在挂载目录下的 PocketBase SQLite 数据库中。可建立每日定时快照:
1 2 3 4 5
| tar -czf ~/beszel-backup-$(date +%Y%m%d).tar.gz -C ~/beszel data
curl -fsSL https://raw.githubusercontent.com/ittinker/ittinker-scripts/main/vps-health-monitor/vps-health-monitor.sh | bash
|
8.3 自动化 SQLite WAL 检查与数据库日常维护
Beszel 底层使用 PocketBase (SQLite)。在高并发拉取多节点指标时,建议通过定时脚本检查 WAL 日志体积,防止日志文件失控:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #!/usr/bin/env bash
set -euo pipefail
DATA_DIR="$HOME/beszel/data" BACKUP_DIR="$HOME/beszel/backups" mkdir -p "$BACKUP_DIR"
WAL_FILE="$DATA_DIR/pb_data/data.db-wal" if [ -f "$WAL_FILE" ]; then WAL_SIZE_MB=$(du -m "$WAL_FILE" | cut -f1) if [ "$WAL_SIZE_MB" -gt 50 ]; then echo "[WARN] SQLite WAL file exceeded 50MB (${WAL_SIZE_MB}MB). Triggering checkpoint..." sqlite3 "$DATA_DIR/pb_data/data.db" "PRAGMA wal_checkpoint(PASSIVE);" fi fi
BACKUP_TAR="$BACKUP_DIR/beszel-backup-$(date +%Y%m%d).tar.gz" tar -czf "$BACKUP_TAR" -C "$HOME/beszel" data find "$BACKUP_DIR" -type f -name "beszel-backup-*.tar.gz" -mtime +7 -delete echo "[OK] Beszel backup complete: $BACKUP_TAR"
|
配置入 crontab 即可实现每日无人值守备份:
1 2
| (crontab -l 2>/dev/null; echo "30 3 * * * /bin/bash $HOME/beszel/scripts/db-maintenance.sh >> $HOME/beszel/maintenance.log 2>&1") | crontab -
|
至此,一套内存总占用不到 50MB 的多服务器自动化监控与告警中心已全部交付上线。