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

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 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!