https://github.com/getpusk/pusk
Self-hosted alert platform for ops teams. Telegram Bot API compatible. ACK, push, team chat.
https://github.com/getpusk/pusk
bot-api bot-platform chatbot golang inline-keyboard open-source pwa self-hosted telegram-api webhook
Last synced: about 1 month ago
JSON representation
Self-hosted alert platform for ops teams. Telegram Bot API compatible. ACK, push, team chat.
- Host: GitHub
- URL: https://github.com/getpusk/pusk
- Owner: getpusk
- License: other
- Created: 2026-03-17T13:02:50.000Z (2 months ago)
- Default Branch: main
- Last Pushed: 2026-04-09T12:40:33.000Z (about 2 months ago)
- Last Synced: 2026-04-09T14:31:48.780Z (about 2 months ago)
- Topics: bot-api, bot-platform, chatbot, golang, inline-keyboard, open-source, pwa, self-hosted, telegram-api, webhook
- Language: Go
- Homepage:
- Size: 10.9 MB
- Stars: 14
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.en.md
- Changelog: CHANGELOG.md
- License: LICENSE
- Codeowners: .github/CODEOWNERS
- Security: SECURITY.md
Awesome Lists containing this project
README
[](https://github.com/getpusk/pusk/releases)
[](https://github.com/getpusk/pusk/actions/workflows/ci.yml)
[](https://github.com/getpusk/pusk/actions/workflows/ci.yml)
[](https://goreportcard.com/report/github.com/getpusk/pusk)
[](https://go.dev)
[](https://core.telegram.org/bots/api)
[](https://www.sqlite.org)
π [Π ΡΡΡΠΊΠΈΠΉ](README.md)

# Pusk β self-hosted alerts for ops teams
**Pusk** β self-hosted alert platform with team coordination. Webhooks from any monitoring, one-click ACK, push to phone. Single binary, zero dependencies.
## Why?
**Problem:** alert fires. Who picked it up? Silence.
- Alerts get lost in group chats among discussions
- No acknowledgment (ACK) β unclear who is handling it
- No escalation β if on-call is asleep, the alert dies
- Data on third-party servers β compliance fails
**Solution β Pusk:**
- Alerts from Grafana, Zabbix, Alertmanager, Uptime Kuma β into dedicated channels
- One-click ACK β automatic silence in Alertmanager
- Push notifications to phone even with browser closed
- Team chat built in β channels, @mentions, file uploads
- Telegram Bot API compatible β existing bots work with a one-line change


## Who is it for
- **DevOps/SRE teams** β monitoring alerts + incident coordination
- **Companies with compliance needs** β data on your server, no external dependencies
- **Anyone who needs autonomy** β works without external dependencies
## Features
| Feature | Description |
|---------|-------------|
| **Alerts** | Webhooks from Alertmanager, Grafana, Zabbix, Uptime Kuma. Color indicators, ACK, automatic silence |
| **Push** | Web Push notifications to phone and desktop (even with browser closed) |
| **Bots** | 13 Telegram Bot API methods. Inline buttons, webhook, long polling |
| **Channels** | Team channels, @mentions with push, reply, pin, editing |
| **Files** | Photos, videos, voice messages, documents β upload and view |
| **Online status** | Real-time online/away usernames, typing indicator |
| **Multi-tenant** | Isolated organizations (separate SQLite per tenant) |
| **Simple** | Single binary (23 MB), SQLite, ~2 MB RAM, 1-second startup |
## Use Cases: connect monitoring in 5 minutes
Ready-to-use docker-compose files β download, run, done:
| Use case | What you get | Time |
|----------|-------------|------|
| [Alertmanager](docs/use-cases.en.md#-alertmanager) | Prometheus β Alertmanager β Pusk, ACK with auto-silence | 5 min |
| [Grafana](docs/use-cases.en.md#-grafana) | Grafana Contact Point β Pusk | 5 min |
| [Zabbix](docs/use-cases.en.md#-zabbix) | Zabbix Media Type β Pusk | 5 min |
| [Uptime Kuma](docs/use-cases.en.md#-uptime-kuma) | Uptime Kuma β Pusk | 3 min |
| [All-in-one](docs/use-cases.en.md#-all-in-one) | Full stack to try everything | 5 min |
**[Go to use cases β](docs/use-cases.en.md)**
## FAQ
Is this yet another messenger?
No. It is an alert platform with team chat. Closer to PagerDuty and Opsgenie than to Slack β but self-hosted and free.
How is it different from PagerDuty?
Self-hosted, free, single binary. No on-call scheduling (yet), but has team chat and Telegram Bot API compatibility.
Do I need to install an app?
No. Pusk works in your browser β just open the link. You can add it to your home screen as a PWA icon, but it is optional. Chrome, Firefox, Edge supported.
How do phone notifications work?
Via Web Push β a browser standard, like Slack and Discord. Works even when the browser is closed. Great on Android, iOS with Safari 16.4+.
## Quick start
### Docker (recommended)
```bash
docker run -d --name pusk \
-p 8443:8443 \
-v pusk-data:/app/data \
ghcr.io/getpusk/pusk:latest
```
Open `http://localhost:8443` β register and get started.
### First run
1. First user creates an **organization** β becomes admin
2. Go to Settings β **Invite** β copy the link and share with your team
3. Teammates follow the link, register β and they are in
4. New members are automatically subscribed to all channels
> Assign at least 2 admins so you do not depend on a single person.
### Connect monitoring
#### Alertmanager
```yaml
receivers:
- name: pusk
webhook_configs:
- url: 'https://your-pusk/hook/BOT-TOKEN?format=alertmanager'
```
#### Grafana
Alerting β Contact points β New β Type: **Webhook**
URL: `https://your-pusk/hook/BOT-TOKEN?format=grafana`
#### Zabbix
Administration β Media types β Create: **Webhook**
URL: `https://your-pusk/hook/BOT-TOKEN?format=zabbix`
#### Uptime Kuma
Notifications β Add β Type: **Webhook**
URL: `https://your-pusk/hook/BOT-TOKEN?format=raw&channel=alerts`
#### Any system with curl
```bash
curl -X POST 'https://your-pusk/hook/BOT-TOKEN?format=raw' \
-H 'Content-Type: application/json' \
-d '{"status":"down","name":"my-service"}'
```
### From source
```bash
git clone https://github.com/getpusk/pusk.git
cd pusk
go build -o pusk ./cmd/pusk/
./pusk
```
### Docker Compose
```yaml
version: '3'
services:
pusk:
image: ghcr.io/getpusk/pusk:latest
ports:
- "8443:8443"
volumes:
- ./data:/app/data
environment:
- PUSK_ADMIN_TOKEN=your-secret
restart: unless-stopped
```
## Telegram Bot API compatibility
If you already have a Telegram Bot API bot β it works in Pusk with a one-line change:
```python
# Python (aiogram)
bot = Bot(token="TOKEN", base_url="https://your-pusk:8443/bot")
# Python (python-telegram-bot)
app = Application.builder().token(TOKEN).base_url("https://your-pusk:8443/bot").build()
```
```javascript
// Node.js (Telegraf)
bot.telegram.options.apiRoot = "https://your-pusk:8443";
```
Supports 13 of 80+ methods β enough for alerts, notifications and simple bots.
## VPS installation
### Systemd
```bash
sudo tee /etc/systemd/system/pusk.service << EOF
[Unit]
Description=Pusk
After=network.target
[Service]
User=pusk
WorkingDirectory=/opt/pusk
ExecStart=/opt/pusk/pusk
Restart=always
Environment=PUSK_ADDR=:8443
Environment=PUSK_ADMIN_TOKEN=your-secret
# Environment=PUSK_JWT_SECRET=your-jwt-secret
# Environment=VAPID_PUBLIC_KEY=...
# Environment=VAPID_PRIVATE_KEY=...
# Environment=VAPID_EMAIL=admin@example.com
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable --now pusk
```
### Reverse proxy (Caddy)
```
pusk.example.com {
reverse_proxy localhost:8443
}
```
### Reverse proxy (Nginx)
```nginx
server {
listen 443 ssl;
server_name pusk.example.com;
location / {
proxy_pass http://127.0.0.1:8443;
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-Forwarded-Proto $scheme;
}
}
```
## Configuration
| Variable | Default | Description |
|----------|---------|-------------|
| `PUSK_ADDR` | `:8443` | Server address |
| `PUSK_ADMIN_TOKEN` | β | Admin API token |
| `PUSK_MAX_ORGS` | `1` | Max user-created organizations. `0` β unlimited. Admin token bypasses the limit |
| `PUSK_DEMO` | β | `1` β enable demo mode |
| `PUSK_MSG_RETENTION_DAYS` | `30` | Auto-delete messages older than N days. `0` β keep all |
| `PUSK_FILE_QUOTA_MB` | `1024` | File storage limit per organization (MB) |
| `PUSK_WEBHOOK_DEBOUNCE` | `10s` | Deduplicate identical webhooks. `0` β disable |
| `PUSK_ALERTMANAGER_URL` | β | Alertmanager URL for auto-silence on ACK |
| `VAPID_PUBLIC_KEY` | β | VAPID key for Web Push |
| `VAPID_PRIVATE_KEY` | β | VAPID private key |
| `VAPID_EMAIL` | β | Email for push service |
| `PUSK_JWT_SECRET` | auto | JWT secret. Auto-generated and saved to `data/jwt.secret` if not set |
| `PUSK_LOG_FORMAT` | `text` | `json` β JSON logs for production |
| `PUSK_OPEN_USER_REGISTRATION` | `true` | `false` β disable self-registration (invite-only) |
| `PUSK_WEBHOOK_RATE_LIMIT` | `60` | Webhook requests per minute per bot |
| `PUSK_TPL_ALERTMANAGER` | β | Path to custom Go template file for Alertmanager webhook |
| `PUSK_TPL_GRAFANA` | β | Path to custom Go template file for Grafana webhook |
| `PUSK_TPL_ZABBIX` | β | Path to custom Go template file for Zabbix webhook |
| `PUSK_TPL_RAW` | β | Path to custom Go template file for raw webhook |
## Admin API
All endpoints require `Authorization: Bearer ` or a JWT with admin role.
| Method | Path | Description |
|--------|------|-------------|
| `POST` | `/admin/bots` | Register a bot (`token`, `name`) |
| `POST` | `/admin/channel` | Create channel (`name`, `description`, `bot_id`) |
| `DELETE` | `/admin/channel/{id}` | Delete channel (except #general) |
| `PUT` | `/admin/channel/{id}` | Rename channel (`name`) |
| `PUT` | `/admin/bots/{id}` | Rename bot (`name`) |
| `POST` | `/admin/reset-password` | Reset password (`org`, `username`, `new_pin`). ADMIN_TOKEN only |
| `POST` | `/admin/set-role` | Set role (`org`, `user_id`, `role`: admin/member). ADMIN_TOKEN only |
| `GET` | `/api/org/info` | Organization limit info |
| `POST` | `/api/org/register` | Create organization (`slug`, `name`, `username`, `pin`) |
## Backup
All data is in the `data/` directory:
```bash
# Hot backup
sqlite3 data/orgs/my-org/pusk.db ".backup backup.db"
# Full backup
tar czf pusk-backup-$(date +%Y%m%d).tar.gz data/
```
## Architecture
```
pusk (23 MB, ~8400 lines Go, 110 tests)
βββ Bot API β /bot// (Telegram compatible)
βββ Client API β /api/* (PWA backend)
βββ WebSocket β /api/ws (real-time status, typing)
βββ Files β /file/ (media)
βββ PWA β / (web client)
βββ SQLite β data/orgs/*/pusk.db (database)
```
## Demo
Try it: [getpusk.ru](https://getpusk.ru) β click "Demo", no registration.
## Security
- JWT with 7-day TTL, bcrypt password hashing
- Organization owner (first admin) protected from deletion and demotion
- #general channel protected from deletion and renaming
- Rate limiting on auth, registration, messaging
- SSRF protection for webhook URLs
- Multi-tenant with full data isolation (separate SQLite per organization)
## License
BSL 1.1 β Copyright (c) 2026 Volkov Pavel | DevITWay
See [LICENSE](LICENSE) for details.