Webhook service that sends UniFi Protect snapshots to Telegram.
991
Send a snapshot from your UniFi Protect camera to Telegram whenever an Automation (motion, AI/person, doorbell ring, etc.) fires. One container exposes webhook endpoints; paste those URLs into Protect Automations.
zalaghi/protectgramlatest, 1.1.2-hotfix58080/tcp# Create a shared token for your webhook URLs
TOKEN=$(openssl rand -hex 16)
# Run the container (edit values on the right)
docker rm -f protectgram 2>/dev/null || true
docker run -d --name protectgram --restart unless-stopped -p 8080:8080 -e UNIFI_ADDR="https://10.0.0.5" -e UNIFI_USERNAME="unifi_user_readonly" -e UNIFI_PASSWORD="your_password" -e TELEGRAM_TOKEN="123456:ABCDEF" -e TELEGRAM_CHAT="123456789" -e WEBHOOK_TOKEN="$TOKEN" -e STAMP_TZ="Europe/Madrid" zalaghi/protectgram:1.1.2-hotfix5
# Health check → should return {"ok":true}
curl -fsS http://127.0.0.1:8080/health | jq
Tip: Use a dedicated UniFi user with read-only access to the camera(s) you want.
List cameras (name, id, model):
curl -fsS "http://127.0.0.1:8080/cameras?token=${TOKEN}" | jq
Generate ready-to-paste URLs (saves to webhook_urls.txt):
PORT=8080
STAMP_TZ="Europe/Madrid"
LOCAL_IP=$(hostname -I 2>/dev/null | awk '{print $1}')
BASE_URL="http://${LOCAL_IP:-127.0.0.1}:${PORT}"
curl -fsS "http://127.0.0.1:${PORT}/cameras?token=${TOKEN}" | jq -r --arg base "$BASE_URL" --arg tok "$TOKEN" --arg tz "$STAMP_TZ" '
.cameras[] as $c |
"• \($c.name)
" +
" By ID (recommended): \($base)/hook/by-id/\($c.id)?token=\($tok)&hq=true&stamp=1&stamp_tz=\($tz|@uri)&caption=\("Motion on \($c.name)"|@uri)
" +
" By Name : \($base)/hook/\($c.name|@uri)?token=\($tok)&hq=true&stamp=1&stamp_tz=\($tz|@uri)&caption=\("Motion on \($c.name)"|@uri)
"
' | tee webhook_urls.txt
Wire it in UniFi Protect:
webhook_urls.txtGET /health → {"ok": true}GET /cameras?token=... → list of { id, name, model }GET /test/text?token=...&text=Hello → send a text message to TelegramPOST /hook/by-id/<camera_id>?token=...&hq=1&stamp=1&stamp_tz=Europe/Madrid&caption=...POST /hook/<camera_name>?token=...&...Query params: token, hq, stamp, stamp_tz, stamp_fmt, caption
| Var | Required | Example | Notes |
|---|---|---|---|
UNIFI_ADDR | ✅ | https://unvr.local | Controller/NVR URL |
UNIFI_USERNAME | ✅ | unifi_user_readonly | Use a read-only account |
UNIFI_PASSWORD | ✅ | •••••••• | — |
TELEGRAM_TOKEN | ✅ | 123456:ABCDEF | From @BotFather |
TELEGRAM_CHAT | ✅ | 123456789 | Your chat or group ID |
WEBHOOK_TOKEN | ✅ | random hex | Shared secret in every URL |
STAMP_TZ | ⚙️ | Europe/Madrid | Timezone for overlay |
Security tips: Always set a strong WEBHOOK_TOKEN. Limit the UniFi account’s permissions. If exposing publicly, put the service behind HTTPS and IP allowlists.
services:
webhook:
image: zalaghi/protectgram:1.1.2-hotfix5
container_name: protectgram
restart: unless-stopped
ports: ["8080:8080"]
environment:
UNIFI_ADDR: "https://10.0.0.5"
UNIFI_USERNAME: "unifi_user_readonly"
UNIFI_PASSWORD: "your_password"
TELEGRAM_TOKEN: "123456:ABCDEF"
TELEGRAM_CHAT: "123456789"
WEBHOOK_TOKEN: "${TOKEN}"
STAMP_TZ: "Europe/Madrid"
Bring up:
docker compose up -d
# Upgrade
docker pull zalaghi/protectgram:latest
docker rm -f protectgram
# re-run with your env values
# Uninstall
docker rm -f protectgram
License: MIT
Source: https://github.com/zalaghi/protectgram
Content type
Image
Digest
sha256:5b4488275…
Size
61.9 MB
Last updated
about 1 year ago
docker pull zalaghi/protectgram