홈으로 돌아가기

Go 기반 16 MB Pusk 알림 서버

Pusk — 16 MB 크기의 컴팩트한 Go 자체 호스팅 알림 서버. Telegram 봇 마이그레이션, Alertmanager 침묵 ACK, NAT용 WebSocket 지원. 외부 DB 없이 작동하며 PWA와 푸시 알림 포함.

Pusk: 종속성 없는 16 MB 알림 서버
Advertisement 728x90

Pusk: Go로 구축된 16MB 자체 호스팅 알림 서버

Pusk는 모니터링을 위한 외부 메시징 플랫폼 의존성을 제거하는 자체 호스팅 솔루션입니다. 단일 16MB 실행 파일로 13개의 Telegram Bot API 메서드, WebSocket, Web Push 및 PWA 클라이언트를 지원합니다. PostgreSQL이나 다른 데이터베이스 없이 순수 Go의 SQLite만으로 실행됩니다. 제한, 차단 또는 격리로 인해 외부 API를 사용할 수 없는 시나리오를 위해 설계되었습니다.

아키텍처는 외부 서비스를 배제합니다. Go는 빠른 빌드(7초)와 내장 net/http를 위해 선택되었습니다. 데이터베이스는 CGO 없이 modernc.org/sqlite를 사용하며, 시작 시 RSS는 약 4MB입니다. 로깅은 slog를 통해 JSON 또는 텍스트 형식으로 처리됩니다.

표준 메신저를 사용하지 않는 이유

대안들은 마이그레이션, 데이터베이스 및 상당한 리소스를 요구합니다:

Google AdInline article slot

| 플랫폼 | 의존성 | 봇 호환성 | ACK | RAM |

|-----------|-------------|---------------------|-----|-----|

| Mattermost | PostgreSQL, SMTP | 재작성 필요 | 플러그인 | 500+ MB |

Google AdInline article slot

| Matrix | Synapse, PostgreSQL | 재작성 필요 | 없음 | 500+ MB |

| Telegram | 클라우드 | — | 없음 | — |

Gotify/ntfy는 채팅이나 ACK 없이 푸시 알림만 제공합니다. Telegram에 VPN을 사용하면 장애 지점이 추가됩니다. Pusk는 Bot API를 에뮬레이션합니다: 봇의 base_url을 변경하면 인프라와 함께 작동합니다.

Google AdInline article slot

바이너리 구조

pusk (16 MB, Go 코드 약 6600줄, 테스트 110개)
├── Bot API    — /bot/<token>/<method>  (Telegram Bot API 80+ 메서드 중 13개 지원)
├── Client API — /api/*                 (PWA 백엔드)
├── WebSocket  — /api/ws                (실시간 상태, 입력 중 표시)
├── Web Push   — FCM / Mozilla          (폴링 없이 알림)
├── Files      — /file/<id>             (미디어)
├── PWA        — /                      (웹 클라이언트)
└── SQLite     — data/orgs/*/pusk.db    (조직별 별도 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는 timeout 초 동안 연결을 유지하며, 오프셋을 고려하고 인메모리 큐(봇당 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())

자동 선택: 웹훅(SSRF 보호 포함), 릴레이(분당 30개 메시지로 제한), 또는 getUpdates.

조직별 SQLite 및 핫 백업

각 조직은 WAL 모드의 별도 pusk.db를 가집니다. 쓰기 중에도 리더를 차단하지 않습니다. 백업: sqlite3 pusk.db ".backup backup.db". PostgreSQL JOIN 없이 분당 수십 개 메시지에 적합합니다.

워크플로

  • 관리자가 서버를 시작(docker run 또는 바이너리), 조직 생성 — #general 및 시스템 봇 생성.
  • 링크를 통한 초대(7일, 최대 50명), 채팅에서 자동 알림.
  • #alerts 생성, Zabbix/Grafana/Alertmanager에서 웹훅(?format=alertmanager).
  • 온콜: 푸시/WebSocket, ACK 버튼, 전체 팀이 상태 확인.

역할:

  • 관리자: 전체 권한 + 사용자/채널 관리.
  • 멤버: 채팅, ACK, 파일, @멘션.

알림을 위한 개선 사항

  • ACK → 무음: PUSK_ALERTMANAGER_URL를 통해 Alertmanager에 POST /api/v2/silences.
  • 색상: 발화/해결에 대한 빨간색/녹색 줄.
  • 푸시 최적화: WebSocket이 활성화되고 채널이 열려 있으면 푸시 건너뜀.
  • 격리: 프론트엔드 내장, CDN 없음. Web Push는 FCM/Mozilla 필요.

주요 기능

  • 외부 의존성 없는 단일 16MB 바이너리, Go의 SQLite.
  • 재작성 없이 마이그레이션을 위한 Telegram Bot API 부분 에뮬레이션.
  • Alertmanager 자동 무음을 위한 ACK, 색상 코딩 상태 표시기.
  • NAT, 속도 제한, SSRF 보호를 위한 WebSocket 릴레이.
  • 푸시, 관리자/멤버 역할, 조직별 DB 격리를 갖춘 PWA.

— Editorial Team

Advertisement 728x90

다음 읽기