An open API service indexing awesome lists of open source software.

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.

Awesome Lists containing this project

README

          

[![Release](https://img.shields.io/github/v/release/getpusk/pusk)](https://github.com/getpusk/pusk/releases)
[![CI](https://github.com/getpusk/pusk/actions/workflows/ci.yml/badge.svg)](https://github.com/getpusk/pusk/actions/workflows/ci.yml)
[![Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/devitway/54c1b0a766ce24cb97ac0134c59212c7/raw/pusk-coverage.json)](https://github.com/getpusk/pusk/actions/workflows/ci.yml)
[![Go Report Card](https://goreportcard.com/badge/github.com/getpusk/pusk)](https://goreportcard.com/report/github.com/getpusk/pusk)
[![Go](https://img.shields.io/badge/Go-1.26+-00ADD8?logo=go&logoColor=white)](https://go.dev)
[![Bot API](https://img.shields.io/badge/Bot_API-13_methods-2CA5E0?logo=telegram)](https://core.telegram.org/bots/api)
[![SQLite](https://img.shields.io/badge/SQLite-per_tenant-003B57?logo=sqlite)](https://www.sqlite.org)

🌐 [Русский](README.md)

Pusk β€” interface

# 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

Pusk β€” alert channel

Pusk β€” team chat

## 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.