Debian - Send your Server Notifications thru Telegram


dropcap debian telegram

As a system administrator, you must be receiving your important server notifications by emails. Email has been used since decades, but it is slowly replaced in everydays life by social networks. With social network clients, messages are usually displayed as thread and get instant notification on your smartphone.

So, why not receiving your main server notifications on one of your favorite social network client ?

Telegram is becoming a very popular social network as it is free and multi-platforms. It has also a unique feature : it's allowing the use of bots. Bots are very interesting as they can be seen as an application account associated to a real person's account. They are able to send or receive messages to/from either an individual account or a group.

So, instead of sending a mail, it could be very interesting for your Debian/Ubuntu server to be able to send you Telegram notification. You can for example create an administrator group and send all your server notifications to this group. Any administrator belonging to this Telegram group will get instant notification from the server.

This article explains how to setup a server environment to very easily send Telegram notifications from any of your server script or service. It also provides a script that allows you to send Telegram messages including text, photos, documents, logs, …

It has been tested on a Debian 8.5 server but it should work on any modern Linux distribution.

1. Pre-Requisite

1.1. Create your Telegram Bot

Telegram allows you to easily create your own Bot with the help of @BotFather.

This page explain very clearly what you can expect from your Telegram Bot and how to create it.

To make it short, a Bot is a type of Telegram account that doesn't need to be associated to a phone number. It's an application account associated to your personnal account.

Once you have created your Bot, you get your API key. This key looks like 123456789:AABBCCDD_abcdefghijklmnopqrstuvwxyz.

As Telegram APIs are using plain httpsURL with POST data, this API key is needed to identify the Bot when you send messages, photos and documents straight from any web client.

All parameters are explained in Telegram API page.

Your Bot will be able to send messages either to :

  • your personnal account
  • any channel it belongs to

But to send any message, your Bot will need to use either your user ID or a Channel ID. It can not address an account simply using its name.

Here is the way to get these IDs.

1.2. Get your User ID

To get your user ID, you just need to :

  • send a message to your Bot from your Telegram client
  • call the following URL from any web browser
 Answer  {"ok":true,"result":[{"update_id":563273027,"message":{"message_id":505, "from":"id":11223344, "first_name":"YourFirstName", "last_name":"YourLastName", "username":"YourUserName"},
"chat":{"id":11223344, "first_name":"YourFirstName", "last_name":"YourLastName", "username":"YourUserName", "type":"private"}, "date":1483150094, "text":"Hello bot !"}}]}


You can see here that your user ID is 11223344.

This is the client ID that Telegram Bot should use to send me a message.

1.3. Get Channel ID

If your server must notify multiple users, it should notify a channel.

First, from your Telegram client, create a channel and keep it public as you need to obtain the channel ID. Give a name @YourNewChannelName to your channel.

Next, from your Bot thread, go to the Bot parameters page. You should see that your Bot is in both Members and Administrators list.

The Bot is now ready to publish messages.

To get your channel ID, you just need to send a message to @YourNewChannelName from any web browser using your Bot API key :


{"ok":true, "result":{"message_id":2, "chat":{"id":-1234567890123, "title":"Your Channel", "username":"YourNewChannelName", "type":"channel"}, "date":1483383169, "text":"FirstMessage"}}


You can see in the resulting JSON string that your new channel ID is -1234567890123.

You can now edit your Channel and convert its type to Private.

Your Bot can still send a message to the channel using the Channel ID :


{"ok":true, "result":{"message_id":2, "chat":{"id":-1234567890123, "title":"Your Channel", "username":"YourNewChannelName", "type":"channel"}, "date":1483383169, "text":"SecondMessage"}}


2. Telegram Notification Script

It's now time to install and configure Telegram notification script on the server.

The script will be in charge of sending Telegram notification and can be used by any script, service, daemon, … on the server.

2.1. Functionalities

Main functionality of Telegram notification script is to … send a Telegram notification.

It allows to :

  • display plain text message or a file content (log, …)
  • display a title
  • display an emoji as leading icon  (codes may be found in this emoji table)
  • add a photo or a document
  • select formatting style as Markdown (default) or HTML
  • disable message notification on the client side
  • select Bot to use to send the message (thru API key)
  • set message recipient ID

# telegram-notify
Tool to send a message to a Telegram User or Channel.
Message is sent from a Telegram Bot and can contain icon, text, image and/or document.
Main parameters are :
  --text <text>       Text of the message or file holding the text
  --photo <file>      Image to display
  --document <file>   Document to transfer
Options are :
  --title <title>     Title of the message (if text message)
  --html              Use HTML mode for text content (markdown by default)
  --silent            Send message in silent mode (no user notification on the client)
  --user <user-id>    Recipient User or Channel ID (replaces user-id= in /etc/telegram-notify.conf)
  --key <api-key>     API Key of your Telegram bot (replaces api-key= in /etc/telegram-notify.conf)
Optionnal icons are :
  --success           Add a success icon
  --error             Add an error icon
  --question          Add a question mark icon
  --icon <code>       Add an icon by UTF code (ex 1F355)

Here are some examples of notifications and the expected result :

# telegram-notify --success --text "Action *sucessful* with markdown *bold* example"
# telegram-notify --error --title "Error" --text "Error message with a title"
# telegram-notify --question --title "File content display" --text "/tmp/log.txt"
# telegram-notify --icon 1F355 --text "Message with custom icon 1F355 and embedded image" --photo "/tmp/icon.png"
# telegram-notify --text "Result is available in the embedded document" --document "/tmp/result.log"

telegram test message

2.2. Script

Main notification script is placed under /usr/local/sbin/telegram-notify.

# ---------------------------------------------------
#  Send notification to a telegram account thru a bot account
#  Configuration is stored in /etc/telegram-notify.conf
#  Depends on curl 
#  Revision history :
#    10/01/2016, V1.0 - Creation by N. Bernaerts
#    22/01/2016, V1.1 - Handle emoticons
#    06/08/2016, V1.2 - Add API key and User ID parameters
#                       Remove dependency to PERL
#    08/08/2016, V1.3 - Add --document, --html and --silent options
#    10/11/2016, V1.4 - Add --icon option
#    11/01/2018, V1.5 - Add possibility of piped text, idea from Yasir Atabani
#    19/05/2018, V1.6 - Add socks5 proxy option, idea from RangerRU
#    28/06/2018, V1.7 - Add --warning and --config options, idea from Markus Hof
#    08/08/2019, V1.8 - Add --file option (file holding text to display)
#    23/09/2019, V1.9 - Add --quiet option, thanks to Alberto Panu
#    06/02/2020, V2.0 - Add --disable_preview option, thanks to Alex P.
# ---------------------------------------------------

# initialise variables

# Configuration file

# -------------------------------------------------------
#   Check tools availability
# -------------------------------------------------------

command -v curl >/dev/null 2>&1 || { echo "[Error] Please install curl"; exit 1; }

# -------------------------------------------------------
#   Loop to load arguments
# -------------------------------------------------------

# if no argument, display help
if [ $# -eq 0 ] 
  echo "Tool to send a message to a Telegram User or Channel."
  echo "Message is sent from a Telegram Bot and can contain icon, text, image and/or document."
  echo "Main parameters are :"
  echo "  --text <text>       Text of the message (use - for piped text)"
  echo "  --file <file>       File holding the text of the message"
  echo "  --photo <file>      Image to display"
  echo "  --document <file>   Document to transfer"
  echo "Options are :"
  echo "  --title <title>     Title of the message (if text message)"
  echo "  --html              Use HTML mode for text content (markdown by default)"
  echo "  --disable_preview   Don't create previews for links, image and/or document"
  echo "  --silent            Send message in silent mode (no user notification on the client)"
  echo "  --quiet             Don't print message to stdout"
  echo "  --config <file>     use alternate config file, instead of default ${FILE_CONF}"
  echo "  --user <user-id>    Recipient User or Channel ID (replaces user-id= in ${FILE_CONF})"
  echo "  --key <api-key>     API Key of your Telegram bot (replaces api-key= in ${FILE_CONF})"
  echo "Optional icons are :"
  echo "  --success           Add a success icon"
  echo "  --warning           Add a warning icon"
  echo "  --error             Add an error icon"
  echo "  --question          Add a question mark icon"
  echo "  --icon <code>       Add an icon by UTF code (ex 1F355)"
  echo "Here is an example of piped text :"
  echo "  echo 'text to be displayed' | telegram-notify --success --text -"

# loop to retrieve arguments
while test $# -gt 0
  case "$1" in
    "--text") shift; DISPLAY_TEXT="$1"; shift; ;;
    "--file") shift; TEXTFILE="$1"; shift; ;;
    "--photo") shift; PICTURE="$1"; shift; ;;
    "--document") shift; DOCUMENT="$1"; shift; ;;
    "--title") shift; DISPLAY_TITLE="$1"; shift; ;;
    "--html") DISPLAY_MODE="html"; shift; ;;
    "--disable_preview") DISABLE_PREVIEW="true"; shift; ;;
    "--silent") DISPLAY_SILENT="true"; shift; ;;
    "--quiet") QUIET="true"; shift; ;;
    "--config") shift; FILE_CONF="$1"; shift; ;;
    "--user") shift; USER_ID="$1"; shift; ;;
    "--key") shift; API_KEY="$1"; shift; ;;
    "--success") DISPLAY_ICON=$(echo -e "\U2705"); shift; ;;
    "--warning") DISPLAY_ICON=$(echo -e "\U26A0"); shift; ;;
    "--error") DISPLAY_ICON=$(echo -e "\U1F6A8"); shift; ;;
    "--question") DISPLAY_ICON=$(echo -e "\U2753"); shift; ;;
    "--icon") shift; DISPLAY_ICON=$(echo -e "\U$1"); shift; ;;
    *) shift; ;;

# -------------------------------------------------------
#   Read configuration
# -------------------------------------------------------

# if configuration file is present
if [ -f "${FILE_CONF}" ]
    # display used config file unless --quiet parameter is used
    [ "${QUIET}" = "false" ] && echo "[Info] Using configuration file ${FILE_CONF}"

    # if needed, load from configuration file
    [ "${API_KEY}" = "" ] && API_KEY=$(cat "${FILE_CONF}" | grep "api-key=" | cut -d'=' -f2)
    [ "${USER_ID}" = "" ] && USER_ID=$(cat "${FILE_CONF}" | grep "user-id=" | cut -d'=' -f2)

    # load socks proxy from configuration file
    SOCKS_PROXY=$(cat "${FILE_CONF}" | grep "socks-proxy=" | cut -d'=' -f2)
    # display warning unless --quiet parameter is used
    [ "${QUIET}" = "false" ] && echo "[Warning] Configuration file missing ${FILE_CONF}"

# check API key and User ID
[ "${API_KEY}" = "" ] && { echo "[Error] Please provide API key or set it in ${FILE_CONF}"; exit 1; }
[ "${USER_ID}" = "" ] && { echo "[Error] Please provide User ID or set it in ${FILE_CONF}"; exit 1; }

# -------------------------------------------------------
#   Check for file existence
# -------------------------------------------------------

# if text file, check for text file
[ "${TEXTFILE}" != "" -a ! -f "${TEXTFILE}" ] && { echo "[error] Text file ${TEXTFILE} doesn't exist"; exit 1; }

# if picture, check for image file
[ "${PICTURE}" != "" -a ! -f "${PICTURE}" ] && { echo "[error] Image file ${PICTURE} doesn't exist"; exit 1; }

# if document, check for document file
[ "${DOCUMENT}" != "" -a ! -f "${DOCUMENT}" ] && { echo "[error] Document file ${DOCUMENT} doesn't exist"; exit 1; }

# -------------------------------------------------------
#   String preparation : space and line break
# -------------------------------------------------------

# if text is a file, get its content
[ -f "${TEXTFILE}" ] && DISPLAY_TEXT=$(cat "${TEXTFILE}")

# if text is to be read from pipe, get it
[ ! -t 0 -a "${DISPLAY_TEXT}" = "-" ] && DISPLAY_TEXT=$(cat)

# convert \n to LF
DISPLAY_TEXT=$(echo "${DISPLAY_TEXT}" | sed 's:\\n:\n:g')

# if icon defined, include ahead of notification

# if title defined, add it with line break
if [ "${DISPLAY_TITLE}" != "" ]
    # convert title according to Markdown or HTML
    [ "${DISPLAY_MODE}" = "html" ] && NOTIFY_TEXT="${NOTIFY_TEXT}<b>${DISPLAY_TITLE}</b>%0A%0A" \
                       || NOTIFY_TEXT="${NOTIFY_TEXT}*${DISPLAY_TITLE}*%0A%0A"

# if text defined, replace \n by HTML line break

# -------------------------------------------------------
#   Notification
# -------------------------------------------------------

# default option
ARR_OPTIONS=( "--silent" "--insecure" )

# if needed, socks5 option
[ "${SOCKS_PROXY}" != "" ] && ARR_OPTIONS=( "${ARR_OPTIONS[@]}" "--socks5-hostname" "${SOCKS_PROXY}" )

# if photo defined, display it with icon and caption
if [ "${PICTURE}" != "" ]
  # display image
  CURL_RESULT=$(curl "${ARR_OPTIONS[@]}" --form chat_id=${USER_ID} --form disable_notification=${DISPLAY_SILENT} --form disable_web_page_preview=${DISABLE_PREVIEW} --form photo="@${PICTURE}" --form caption="${NOTIFY_TEXT}" "${API_KEY}/sendPhoto")

# if document defined, send it with icon and caption
elif [ "${DOCUMENT}" != "" ]
  # transfer document
  CURL_RESULT=$(curl "${ARR_OPTIONS[@]}" --form chat_id=${USER_ID} --form disable_notification=${DISPLAY_SILENT} --form disable_web_page_preview=${DISABLE_PREVIEW} --form document="@${DOCUMENT}" --form caption="${NOTIFY_TEXT}" "${API_KEY}/sendDocument")

# else, if text is defined, display it with icon and title
elif [ "${NOTIFY_TEXT}" != "" ]
  # display text message
  CURL_RESULT=$(curl "${ARR_OPTIONS[@]}" --data chat_id="${USER_ID}" --data "disable_notification=${DISPLAY_SILENT}" --data "disable_web_page_preview=${DISABLE_PREVIEW}" --data "parse_mode=${DISPLAY_MODE}" --data "text=${NOTIFY_TEXT}" "${API_KEY}/sendMessage")

#  else, nothing, error
  # display error message unless --quiet parameter is used
  [ "${QUIET}" = "false" ] && echo "[Error] Nothing to notify"
  exit 1

# check curl request result
echo ${CURL_RESULT} | grep '"ok":true' > /dev/null || { echo ${CURL_RESULT}; exit 1; }

# end
exit 0

2.3. Configuration

Telegram notification script is using 2 default parameters that should be configured in /etc/telegram-notify.conf :

  • api-key : Your Bot API key
  • user-id : Default User ID or Channel ID to send messages to

# -------------------------------#
#   /etc/telegram-notify.conf    #
# -------------------------------#



When calling the notification script these default parameters may be surcharged with --user and --key parameters.

2.4. Installation

Before installing notification script, you have to make sure that your locale is set to UTF-8 on your server to properly encode icons.

# locale

If not, you should set locale to UTF-8 according to your langage :

# update-locale LANG=en_US.UTF-8 LANGUAGE=en.UTF-8
# reboot

Installation of Telegram notification script is quite simple as all files are available from my Debian GitHub repository :

# wget
# ./

Once you've configured /etc/telegram-notify.conf, you are ready to send your first Telegram notification from command line.


Hope it helps.

Signature Technoblog

This article is published "as is", without any warranty that it will work for your specific need.
If you think this article needs some complement, or simply if you think it saved you lots of time & trouble,
just let me know at This email address is being protected from spambots. You need JavaScript enabled to view it.. Cheers !

icon linux icon debian icon apache icon mysql icon php icon piwik icon googleplus