DEV Community

Cover image for Bash + Telegram: Server Monitoring and Instant Notifications
Юрий
Юрий

Posted on

1 1 1 1 1

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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 &
Enter fullscreen mode Exit fullscreen mode

Fig. 5 The nohup command

Now let's check if our script is running:

ps aux |  telegram_notification*
Enter fullscreen mode Exit fullscreen mode

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!

Sentry image

Make it make sense

Only get the information you need to fix your code that’s broken with Sentry.

Start debugging →

Top comments (1)

Collapse
 
_2974322d72d5f53d8c2c profile image
Юрий

How to Configure fail2ban to Monitor SSH Activity:

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
Enter fullscreen mode Exit fullscreen mode

Edit this file by adding the following section:

[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log  # For Debian/Ubuntu
maxretry = 5
bantime = 6000
Enter fullscreen mode Exit fullscreen mode

Restart fail2ban:

sudo systemctl restart fail2ban
Enter fullscreen mode Exit fullscreen mode

Relaunch the script in the background:

sudo nohup script_name.sh &
Enter fullscreen mode Exit fullscreen mode

Congratulations! You’ve successfully configured fail2ban.

ACI image

ACI.dev: Fully Open-source AI Agent Tool-Use Infra (Composio Alternative)

100% open-source tool-use platform (backend, dev portal, integration library, SDK/MCP) that connects your AI agents to 600+ tools with multi-tenant auth, granular permissions, and access through direct function calling or a unified MCP server.

Check out our GitHub!