Bash + Telegram: Server Monitoring and Instant Notifications

This article is written for people with basic Linux knowledge. It explains how to write a bash script for sending instant server activity notifications to Telegram. I'll try to explain the topic in accessible language and provide practical examples so you can easily apply this knowledge. Telegram has deeply penetrated our lives. It's no longer just a messenger but a vast ecosystem with various channels, apps, stores, and games. We store notes, make purchases, and communicate with friends and colleagues there. So why not use it as a work tool for monitoring server activity? How it all began. I have a VPS where I test and deploy my pet projects. To protect my server, I installed the standard fail2ban program, and I was unpleasantly surprised when checking the logs to see 500 daily SSH connection attempts. You might say: add keys, disable SSH access, and the problem is solved. However, that's not always convenient, and this article wouldn't exist if I had done that. So to monitor such activity, I decided to write a small script that would send notifications with statistics about failed and successful login attempts. What we'll need: Install fail2ban Install curl Create a Telegram bot, get its token and chat_id (the chat identifier where messages will be sent) First, let's install fail2ban sudo apt update sudo apt install fail2ban Fig. 1 Installing fail2ban Note that after installation, Fail2ban isn't configured by default for active protection. However, it includes some preset configurations and filters you can use. For more details, refer to the official website. Create an empty file in the directory touch ~/usr/local/bin/telegram_notification.sh Fig. 2 Command to create an empty file Let's start writing the script #!/bin/bash # Replace with your token and chat_id TOKEN="7904202989:AAHuqZwKD-Piyv62DeeJYlId5d7rxjtWRBk" CHAT_ID="5524715173" # Function to send Telegram messages send_telegram_message() {    local message="$1"    curl -s -X POST "https://api.telegram.org/bot$TOKEN/sendMessage" \        -d "chat_id=$CHAT_ID" \        -d "text=$message" \        -d "parse_mode=HTML" } # Variable to track time since last failed attempt/ban notification last_failed_time=0 # Time period (1 day) after which to send notifications about failed attempts track_time_range=86400 # Function to check and send notifications about failed attempts and bans check_failed_attempts() {    current_time=$(date +%s)    # Check if more than a day has passed since last notification    if (( current_time - last_failed_time >= track_time_range )); then        # Get info about failed attempts and bans in the last 24 hours        failed_attempts=$(grep "Failed password" /var/log/auth.log | wc -l)        bans=$(grep "Ban" /var/log/fail2ban.log | wc -l)        # Compose the message        message=" Statistics for last 24 hours:\n"        message+=" Failed login attempts: $failed_attempts\n"        message+=" Banned IPs: $bans"        # Send the message        send_telegram_message "$message"        last_failed_time=$current_time    fi } # Monitoring authentication and Fail2Ban logs tail -F /var/log/auth.log /var/log/fail2ban.log | while read line; do    # Check for successful logins    if echo "$line" | grep "Accepted password" &> /dev/null; then        send_telegram_message "✅ Successful login: $line"    fi    # Check for failed attempts    if echo "$line" | grep "Failed password" &> /dev/null; then        check_failed_attempts    fi    # Check for banned IPs    if echo "$line" | grep "Ban" &> /dev/null; then        check_failed_attempts    fi done Fig. 3 Script responsible for sending statistics with notifications This script is quite understandable. Let's focus on a few key points, particularly: tail -F /var/log/auth.log /var/log/fail2ban.log | while read line; Fig. 4 The tail command displaying the last lines of a text file The tail -F command tracks all changes in log files and pipes (|) them into a while loop where changes are written to the 'line' variable. The loop then checks conditions and compiles statistics on failed login attempts, while immediately sending notifications to Telegram about successful attempts. Now we just need to run the script. For simplicity, we'll use nohup. This command lets you run processes while ignoring the HUP (hangup) signal. This is useful when you want a process to keep running even after logging out or closing the terminal. However, a better alternative would be using systemd or supervisor, but that's beyond this article's scope. To run the command with nohup, simply add nohup before the command: nohup telegram_notification.sh & Fig. 5 The nohup command Now let's check if our script is running: ps aux | telegram_notification* Fig. 6 Displaying information about the running process The terminal should show the running process and its PID. Congratulations, you'll now receive notif

Apr 15, 2025 - 14:24
 0
Bash + Telegram: Server Monitoring and Instant Notifications

This article is written for people with basic Linux knowledge. It explains how to write a bash script for sending instant server activity notifications to Telegram. I'll try to explain the topic in accessible language and provide practical examples so you can easily apply this knowledge.

Telegram has deeply penetrated our lives. It's no longer just a messenger but a vast ecosystem with various channels, apps, stores, and games. We store notes, make purchases, and communicate with friends and colleagues there. So why not use it as a work tool for monitoring server activity?

How it all began. I have a VPS where I test and deploy my pet projects. To protect my server, I installed the standard fail2ban program, and I was unpleasantly surprised when checking the logs to see 500 daily SSH connection attempts. You might say: add keys, disable SSH access, and the problem is solved. However, that's not always convenient, and this article wouldn't exist if I had done that.
So to monitor such activity, I decided to write a small script that would send notifications with statistics about failed and successful login attempts.

What we'll need:

  1. Install fail2ban
  2. Install curl
  3. Create a Telegram bot, get its token and chat_id (the chat identifier where messages will be sent)
  • First, let's install fail2ban
sudo apt update
sudo apt install fail2ban

Fig. 1 Installing fail2ban

Note that after installation, Fail2ban isn't configured by default for active protection. However, it includes some preset configurations and filters you can use. For more details, refer to the official website.

  • Create an empty file in the directory
touch ~/usr/local/bin/telegram_notification.sh

Fig. 2 Command to create an empty file

  • Let's start writing the script
#!/bin/bash 

# Replace with your token and chat_id 
TOKEN="7904202989:AAHuqZwKD-Piyv62DeeJYlId5d7rxjtWRBk" 
CHAT_ID="5524715173" 

# Function to send Telegram messages 
send_telegram_message() { 
   local message="$1" 
   curl -s -X POST "https://api.telegram.org/bot$TOKEN/sendMessage" \ 
       -d "chat_id=$CHAT_ID" \ 
       -d "text=$message" \ 
       -d "parse_mode=HTML" 
} 

# Variable to track time since last failed attempt/ban notification 
last_failed_time=0 
# Time period (1 day) after which to send notifications about failed attempts
track_time_range=86400

# Function to check and send notifications about failed attempts and bans 
check_failed_attempts() { 
   current_time=$(date +%s) 
   # Check if more than a day has passed since last notification 
   if (( current_time - last_failed_time >= track_time_range )); then 
       # Get info about failed attempts and bans in the last 24 hours 
       failed_attempts=$(grep "Failed password" /var/log/auth.log | wc -l) 
       bans=$(grep "Ban" /var/log/fail2ban.log | wc -l) 

       # Compose the message 
       message=" Statistics for last 24 hours:\n" 
       message+=" Failed login attempts: $failed_attempts\n" 
       message+=" Banned IPs: $bans" 

       # Send the message 
       send_telegram_message "$message" 
       last_failed_time=$current_time 
   fi 
} 

# Monitoring authentication and Fail2Ban logs 
tail -F /var/log/auth.log /var/log/fail2ban.log | while read line; do 
   # Check for successful logins 
   if echo "$line" | grep "Accepted password" &> /dev/null; then 
       send_telegram_message "✅ Successful login: $line" 
   fi 

   # Check for failed attempts 
   if echo "$line" | grep "Failed password" &> /dev/null; then 
       check_failed_attempts 
   fi 

   # Check for banned IPs 
   if echo "$line" | grep "Ban" &> /dev/null; then 
       check_failed_attempts 
   fi 
done

Fig. 3 Script responsible for sending statistics with notifications

This script is quite understandable. Let's focus on a few key points, particularly:

tail -F /var/log/auth.log /var/log/fail2ban.log | while read line;

Fig. 4 The tail command displaying the last lines of a text file

The tail -F command tracks all changes in log files and pipes (|) them into a while loop where changes are written to the 'line' variable. The loop then checks conditions and compiles statistics on failed login attempts, while immediately sending notifications to Telegram about successful attempts.

Now we just need to run the script. For simplicity, we'll use nohup. This command lets you run processes while ignoring the HUP (hangup) signal. This is useful when you want a process to keep running even after logging out or closing the terminal. However, a better alternative would be using systemd or supervisor, but that's beyond this article's scope.

To run the command with nohup, simply add nohup before the command:

nohup telegram_notification.sh &

Fig. 5 The nohup command

Now let's check if our script is running:

ps aux |  telegram_notification*

Fig. 6 Displaying information about the running process

The terminal should show the running process and its PID. Congratulations, you'll now receive notifications about successful and failed SSH login attempts on your server.

Conclusion:

In conclusion, I should note there are other notification methods. For example, you could use jail and action in fail2ban itself with ready-made templates (mail, Telegram, Slack, etc.). However, I prefer using scripts - this provides independence from tools and allows implementing any logic: from monitoring SSH connections to controlling system services, network traffic, and changes in critical files.

If you liked this article, you know what to do - subscribe, like, and repost. It's the best support for the author. This was Yury Dubovitsky from Your Code Isn't Ready Yet, Sir.
Our code is ready now. See you next time!