> ## Content Index
> Fetch the complete content index at: https://blog.rnazar.nl/llms.txt
> Use this file to discover other available public pages before exploring further.

# Creating a Telegram Bot and Setting Up Advanced System Notifications
- URL: https://blog.rnazar.nl/creating-a-telegram-bot-and-setting-up-advanced-system-notifications/
- Published: 2026-09-04T07:43:26.000Z
- Updated: 2026-09-04T08:08:49.000Z
- Description: Running a headless home lab server means staying proactive is key. Follow this guide to set up real-time Telegram notifications for system updates, successful logins, and failed login security monitoring.
- Author: Riju Nazar
- Tags: Technology, Homelab, linux, Self hosting

> **Series:** Home Lab on an Intel NUC  
> **Related:** [Introduction to my homelab series](https://blog.rnazar.nl/series-home-lab-on-an-intel-nuc/)

When running a headless server in your home lab, staying informed about what happens under the hood is critical. While checking system logs manually works, getting proactive alerts straight to your phone is far better.

In this guide, we will set up a robust Telegram notification pipeline that handles:

1. **System updates and reboots** triggered automatically via a cron job, featuring detailed repository breakdowns, automatic message chunking for long lists, and pending reboot detection (inspired by [apt-updates-telegram](https://github.com/JuanJesusAlejoSillero/apt-updates-telegram?ref=blog.rnazar.nl) by Juan Jesús Alejo Sillero and his [accompanying blog post](https://blog.juanje.net/en/posts/apt-updates-telegram/?ref=blog.rnazar.nl)).
2. **Successful logins** hooked directly into PAM (`/etc/pam.d/`) across SSH, Cockpit, and local terminal sessions.
3. **Failed login attempts** parsed securely from audit logs in real-time.

## Step 1: Create Your Telegram Bot & Get Your Chat ID

Before writing any scripts, you need a Telegram bot token and your unique chat ID.

1. Open Telegram, search for `@BotFather`, and start a chat.
2. Send the command `/newbot` and follow the prompts to name your bot.
3. Copy the **HTTP API Token** provided by BotFather.
4. Send any message (e.g., `Hello`) to your new bot in a separate chat window.
5. Retrieve your chat ID by running this command on your machine or workstation:

```
curl "https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates"

```

Look for the `"chat":{"id":XXXXXXXXX,...}` field in the response JSON to find your chat ID number.

## Step 2: The Core Helper Script (`send-telegram.sh`)

To keep our automation clean, we will create a central utility script at `/usr/local/bin/send-telegram.sh` that takes any message string and pushes it to your Telegram bot. Using `/usr/local/bin` is a cleaner, more standard UNIX convention for custom administrator scripts than placing them in `/opt`.

*(Note: You can also find this helper script available in* [*this public GitHub Gist*](https://gist.github.com/rijunazar/7f59b2fee54326376b939510e03cd959?ref=blog.rnazar.nl)*).*

Create the script file:

```
nano /usr/local/bin/send-telegram.sh

```

Paste the following script structure (using your real token and chat ID):

```bash
#!/bin/bash
# ----------------------------------------------------------
# Core helper script to send messages via Telegram Bot API
# ----------------------------------------------------------

TOKEN="your-telegram-bot-token"
CHAT_ID="your-chat-id"

MESSAGE="$1"

if [ -z "$MESSAGE" ]; then
  echo "Usage: $0 \"Your message here\""
  exit 1
fi

curl -s -X POST "https://api.telegram.org/bot${TOKEN}/sendMessage" \
  -d chat_id="${CHAT_ID}" \
  -d text="${MESSAGE}" \
  -d parse_mode="Markdown" > /dev/null

```

Make the script executable:

```
chmod +x /usr/local/bin/send-telegram.sh

```

Test it out:

```
/usr/local/bin/send-telegram.sh "Hello from my Intel NUC lab!"

```

## Step 3: Package Updates & Reboot Notifications (`apt-update-telegrams.sh`)

Keeping track of system packages across multiple repositories can become tedious. We can automate this check to query available updates, parse them by repository source, inspect whether a system reboot is pending via `/var/run/reboot-required`, and cleanly format the output into readable messages. Furthermore, because Telegram limits message lengths, the script includes a built-in chunking function that automatically splits long lists into blocks of 20 lines so nothing gets truncated.

> **Dependency:** This script depends on the core helper script we created above at `/usr/local/bin/send-telegram.sh` to push formatted messages out to Telegram.

### Credits & Inspiration

This package update notification logic is adapted from the excellent [apt-updates-telegram](https://github.com/JuanJesusAlejoSillero/apt-updates-telegram?ref=blog.rnazar.nl) repository by Juan Jesús Alejo Sillero, and builds upon the concepts detailed in his [Apt Updates Telegram Blog Post](https://blog.juanje.net/en/posts/apt-updates-telegram/?ref=blog.rnazar.nl).

### Setting Up the Script

You can grab the complete, ready-to-use update script from [this public GitHub Gist](https://gist.github.com/rijunazar/6aa7bd851e2b41f09452ce53dcab56e0?ref=blog.rnazar.nl) and place it at `/usr/local/bin/apt-update-telegrams.sh`.

Create the file:

```
nano /usr/local/bin/apt-update-telegrams.sh

```

Paste the script contents from the Gist (making sure to point the `SEND_TELEGRAM` variable to `/usr/local/bin/send-telegram.sh`), and save it.

Make it executable:

```
chmod +x /usr/local/bin/apt-update-telegrams.sh

```

### Automating with Cron (Do we need sudo?)

Since checking package lists and running updates requires root privileges, you **do not** need a separate `sudo` command inside the crontab if you edit the **root user's crontab directly**.

Open the root user's crontab by running:

```
sudo crontab -e

```

Add the following line to run this check daily at 8:00 AM as root:

```
0 8 * * * /usr/local/bin/apt-update-telegrams.sh > /var/log/apt-telegram.log 2>&1

```

*(Note: Because you are editing root's personal crontab via `sudo crontab -e`, everything in it executes automatically with root permissions. You do not prepend `sudo` inside crontab entries).*

## Step 4: Successful Login Alerts via PAM (`login-success-notify.sh`)

Whenever someone successfully logs in via SSH, Cockpit, or a local terminal session, we can trigger an instant alert.

Create `/usr/local/bin/login-success-notify.sh`:

```bash
#!/bin/bash

# Path to your main Telegram notification script
TELEGRAM_SCRIPT="/usr/local/bin/send-telegram.sh"

# Only send notifications for session opening
if [ "$PAM_TYPE" = "open_session" ]; then
    USER="$PAM_USER"
    RHOST="${PAM_RHOST:-N/A}" # Remote host (IP or hostname), N/A if local
    SERVICE="$PAM_SERVICE"    # e.g., sshd, login, cockpit
    TTY="$PAM_TTY"            # Terminal device, e.g., pts/0, tty1

    # Get hostname of the server
    HOSTNAME=$(hostname)

    MESSAGE="🔐 *Login Alert on $HOSTNAME* 🚪%0A"
    MESSAGE+="User: *${USER}*%0A"
    MESSAGE+="Service: *${SERVICE}*%0A"
    MESSAGE+="Source IP: *${RHOST}*%0A"
    MESSAGE+="TTY: *${TTY}*%0A"
    MESSAGE+="Time: *$(date '+%Y-%m-%d %H:%M:%S %Z')*"

    # Send the Telegram message
    "$TELEGRAM_SCRIPT" "$MESSAGE"
fi

exit 0

```

Make the script executable:

```
chmod +x /usr/local/bin/login-success-notify.sh

```

### Hooking into PAM Across Services

To ensure you are notified regardless of whether you sign in via SSH, the web-based Cockpit dashboard, or a physical terminal, hook the script into the relevant PAM configuration files.

#### 1\. SSH Logins (`/etc/pam.d/sshd`)

Open `/etc/pam.d/sshd` and append the following line at the very bottom:

```
session optional pam_exec.so seteuid /usr/local/bin/login-success-notify.sh

```

#### 2\. Local Terminal & Console Logins (`/etc/pam.d/login`)

Open `/etc/pam.d/login` and add the same session rule:

```
session optional pam_exec.so seteuid /usr/local/bin/login-success-notify.sh

```

#### 3\. Cockpit Dashboard Logins (`/etc/pam.d/cockpit`) 

Open `/etc/pam.d/cockpit` and add the session rule there as well:

```
session optional pam_exec.so seteuid /usr/local/bin/login-success-notify.sh

```

## Step 5: Failed Login Monitoring via Audit Logs (`login-failure-notify.sh`)

Tracking failed login attempts protects you against brute-force attacks. We can tail `/var/log/audit/audit.log` to catch invalid login events in real-time.

You can grab the complete failed login monitor script from [this public GitHub Gist](https://gist.github.com/rijunazar/913177809c705b3cdec38cb6cc3389df?ref=blog.rnazar.nl) and place it at `/usr/local/bin/login-failure-notify.sh`.

### How the Failed Login Script Works

The failure monitoring script operates continuously in the background by piping the audit log stream (`tail -F`) into a parsing loop:

1. **Event Filtering:** It continuously scans lines for audit record types (`USER_AUTH`, `USER_LOGIN`, `LOGIN`, `SYSCALL`) combined with a failure flag (`res=fail`).
2. **Field Extraction:** Using standard Linux text-processing tools (`grep`, `awk`, and Perl-compatible regex matching via `grep -oP`), it extracts key contextual details such as the target user ID/name (`uid` or `auid`), the source IP address (`addr=`), and the triggering service daemon (`comm=` or `exe=`).
3. **Service Mapping:** Raw service identifiers (like `sshd-session` or `login`) are cleanly translated into friendly lab labels (e.g., `SSH`, `TTY`, `Cockpit`, or `Sudo`).
4. **Instant Dispatch:** Once a failure is verified, it builds an alert payload containing the timestamp, source IP, user, and the raw audit log snippet encased in a code block, then forwards it through `/usr/local/bin/send-telegram.sh`.

Make the script executable:

```
chmod +x /usr/local/bin/login-failure-notify.sh

```

### Running the Failure Monitor as a Background Service

To ensure the failure script runs continuously and restarts if the system reboots, create a systemd service file at `/etc/systemd/system/telegram-fail-monitor.service`:

```bash
[Unit]
Description=Telegram Failed Login Monitor
After=network.target auditd.service

[Service]
Type=simple
ExecStart=/usr/local/bin/login-failure-notify.sh
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

```

Enable and start the service:

```
systemctl daemon-reload
systemctl enable --now telegram-fail-monitor.service

```

![Failed login notification](https://blog.rnazar.nl/content/images/2026/09/image-2.png)

##   
Summary

You now have a complete, self-hosted notification engine running on your home lab server:

- **Centralized messaging** via `/usr/local/bin/send-telegram.sh`
- **Daily automated checks** for package updates and pending reboots via root's crontab (adapted from [apt-updates-telegram](https://github.com/JuanJesusAlejoSillero/apt-updates-telegram?ref=blog.rnazar.nl))
- **Instant security awareness** with successful login tracking through PAM hooks across SSH, Cockpit, and terminal sessions, alongside failed login monitoring via auditd logs.