Skip to content

Instantly share code, notes, and snippets.

@leonjza
Last active July 9, 2023 11:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save leonjza/360c942d4d257b35a492d5445b236f14 to your computer and use it in GitHub Desktop.
Save leonjza/360c942d4d257b35a492d5445b236f14 to your computer and use it in GitHub Desktop.
Tailscale Webhook to Telegram

Tailscale Webhook to Telegram

These files are an example setup to have Tailscale webhooks deliver to a Telegram channel with https://github.com/adnanh/webhook fronted with Traefik, protected with an HTTP basic authentication setup.

Setup

Get a set of credentials to populate in the in the traefik.http.middlewares.basic-auth.basicauth.users label with htpasswd -Bn user. Remember to double escape the $ sign.

Then, in the Tailscale administrator console, add a new webhook endpoint that would point to something like https://user:pass@webhook.domain.com/hooks/tailscale after configuring your docker-compose.yml file appropriately.

Example file layout should be:

./docker-compose.yml
./hooks
./hooks/hooks.yml
./hooks/scripts
./hooks/scripts/include
./hooks/scripts/include/telegram.sh
./hooks/scripts/tailscale.sh
version: '3'
services:
webhook:
image: ghcr.io/leonjza/webhook-docker:master
container_name: webhook
environment:
TELEGRAM_TOKEN: <bot token>
TELEGRAM_CHANNEL: <telegram channel>
volumes:
- ./hooks:/etc/webhook
restart: unless-stopped
labels:
traefik.enable: true
traefik.http.routers.webhook.rule: Host(`webhook.domain.com`)
traefik.http.routers.webhook.entrypoints: web-secure # or whatever your entrypoint is
traefik.http.routers.webhook.tls.certResolver: primary
traefik.http.routers.webhook.middlewares: basic-auth
traefik.http.middlewares.basic-auth.basicauth.users: <htpass>
networks:
- web
networks:
web:
external: true
# tailscale events
- id: tailscale
http-methods:
- POST
execute-command: scripts/tailscale.sh
command-working-directory: /etc/webhook
pass-arguments-to-command:
- source: payload
name: root.0.tailnet
- source: payload
name: root.0.type
- source: payload
name: root.0.message
#!/bin/sh
. $(dirname "$0")/include/telegram.sh
tailnet="$1"
message_type="$2"
message_text="$3"
bot_message="*Tailscale Alert*\n\nTailnet: $tailnet\nType: $message_type\nMessage: $message_text"
send_telegram "$bot_message"
# check that we have the token
if [ -z "${TELEGRAM_TOKEN}" ]
then
echo "TELEGRAM_TOKEN is not set"
exit 1
fi
# check for that channel we sending to
if [ -z "${TELEGRAM_CHANNEL}" ]
then
echo "TELEGRAM_CHANNEL is not set"
exit 1
fi
# check for curl
if ! command -v curl &> /dev/null
then
echo "curl could not be found"
exit
fi
# send a telegram message
function send_telegram {
# lol, .'s are reserved?
message=$(echo $1 | sed 's/\./\\\\./g')
curl -s -X POST \
-H 'Content-Type: application/json' \
--data "{\"chat_id\": \"$TELEGRAM_CHANNEL\", \"text\": \"$message\"}" \
"https://api.telegram.org/bot$TELEGRAM_TOKEN/sendMessage?parse_mode=MarkdownV2" \
-o /dev/null
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment