Pusk:一款仅16 MB的Go语言自托管告警服务器
Pusk是一款自托管解决方案,无需依赖外部消息平台进行监控。单个16 MB可执行文件支持13种Telegram Bot API方法、WebSocket、Web Push和PWA客户端。它无需PostgreSQL或其他数据库,仅使用纯Go编写的SQLite。专为因限制、封锁或隔离导致外部API不可用的场景设计。
架构上排除了外部服务。选择Go语言是因为其快速构建(7秒)和内置的net/http。数据库使用modernc.org/sqlite,无需CGO,启动时RSS约为4 MB。日志通过slog以JSON或文本格式处理。
为何不选用标准消息平台?
替代方案需要迁移、数据库和大量资源:
| 平台 | 依赖项 | 机器人兼容性 | ACK | 内存 |
|-----------|-------------|---------------------|-----|-----|
| Mattermost | PostgreSQL、SMTP | 需重写 | 插件 | 500+ MB |
| Matrix | Synapse、PostgreSQL | 需重写 | 否 | 500+ MB |
| Telegram | 云端 | — | 否 | — |
Gotify/ntfy仅提供推送通知,无聊天或ACK功能。使用VPN连接Telegram会增加故障点。Pusk模拟Bot API:只需更改机器人中的base_url,即可与您的基础设施协同工作。
二进制结构
pusk (16 MB,约6600行Go代码,110个测试)
├── Bot API — /bot/<token>/<method> (支持13种Telegram Bot API方法,共80+种)
├── Client API — /api/* (PWA后端)
├── WebSocket — /api/ws (实时状态、输入提示)
├── Web Push — FCM / Mozilla (无需轮询的通知)
├── Files — /file/<id> (媒体文件)
├── PWA — / (Web客户端)
└── SQLite — data/orgs/*/pusk.db (每个组织独立的数据库)
支持的方法:sendMessage、editMessageText、deleteMessage、answerCallbackQuery、sendPhoto、sendDocument、sendVoice、sendVideo、setWebhook、deleteWebhook、getWebhookInfo、getMe、getUpdates。
兼容性中间件:
func TelegramCompat(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
p := r.URL.Path
if strings.HasPrefix(p, "/bot") && !strings.HasPrefix(p, "/bot/") {
r.URL.Path = "/bot/" + p[4:]
}
next.ServeHTTP(w, r)
})
}
从python-telegram-bot迁移:
# 之前:
app = ApplicationBuilder().token(TOKEN).build()
# 之后:
app = ApplicationBuilder().token(TOKEN).base_url("https://pusk.internal/bot").build()
长轮询与更新推送
/getUpdates在超时秒数内保持连接,考虑偏移量,使用内存队列(每个机器人100条更新)。重启后,机器人可接收后续告警,无需持久化。
对于NAT后的机器人——WebSocket中继:
import websockets, json, asyncio
async def relay():
async with websockets.connect("wss://pusk.internal/bot/TOKEN/relay") as ws:
async for msg in ws:
update = json.loads(msg)
print(update["message"]["text"])
asyncio.run(relay())
自动选择:webhook(带SSRF防护)、中继(限速30条/分钟)或getUpdates。
按组织SQLite与热备份
每个组织在WAL模式下有独立的pusk.db。写入时不阻塞读取。备份:sqlite3 pusk.db ".backup backup.db"。适用于每分钟数十条消息的场景,无需PostgreSQL JOIN。
工作流程
- 管理员启动服务器(docker run或二进制文件),创建组织——生成#general频道和系统机器人。
- 通过链接邀请(7天有效期,最多50人),聊天中自动通知。
- 创建#alerts频道,从Zabbix/Grafana/Alertmanager设置webhook(?format=alertmanager)。
- 值班:推送/WebSocket、ACK按钮,整个团队可见状态。
角色:
- 管理员:完全权限 + 用户/频道管理。
- 成员:聊天、ACK、文件、@提及。
告警增强功能
- ACK → 静默:通过PUSK_ALERTMANAGER_URL向Alertmanager发送POST /api/v2/silences。
- 颜色标识:红色/绿色条纹表示触发/已解决。
- 推送优化:如果WebSocket活跃且频道开放,跳过推送。
- 隔离:前端嵌入,无CDN。Web Push需要FCM/Mozilla。
核心特性
- 单个16 MB二进制文件,无外部依赖,Go语言SQLite。
- 部分模拟Telegram Bot API,迁移无需重写。
- ACK带自动静默Alertmanager,颜色编码状态指示器。
- WebSocket中继支持NAT、速率限制、SSRF防护。
- PWA带推送、管理员/成员角色、按组织隔离。
— Editorial Team
暂无评论。