Skip to content

Notifications for the system administrator

The server should tell you itself when something goes wrong. You don’t need to log into the machine every five minutes and check df -h, journalctl or the backup status — let the server just call when a threshold is reached.

All recipes on these pages work on a plain Linux without additional monitoring agents. bash, curl and cron/systemd are enough. For Windows servers similar scenarios are implemented via PowerShell + Task Scheduler — see the Windows: PowerShell + Task Scheduler sections in each recipe.

СценарийКогда придёт уведомление
Disk space running outFree space less than N %
systemd service downAny important service has gone to failed
Suspicious SSH loginsSuccessful or failed SSH login
Fail2ban triggersIP ban or unban
Backup completionBackup completed successfully or failed
SSL certificate expiryExpires in < N days
High load / OOMCPU/RAM load above threshold
Failed cron jobsCron-job exited with an error

Basic principle: silence is not “everything is fine”, silence is “I don’t know”. Individual “success” notifications (green) are also needed to make sure the system is alive and the check itself works. For example, a daily backup should send “OK” — if it’s missing, something in the check itself is broken.

Everywhere in this section the same send wrapper is used. Save it once to /usr/local/bin/notifly-send:

#!/usr/bin/env bash
# Usage:
# notifly-send "Title" "Message text" [priority]
set -eu
: "${NOTIFLY_URL:?NOTIFLY_URL not set}"
: "${NOTIFLY_TOKEN:?NOTIFLY_TOKEN not set}"
TITLE="${1:?title required}"
MESSAGE="${2:?message required}"
PRIORITY="${3:-5}"
curl -s --max-time 10 \
"$NOTIFLY_URL/message?token=$NOTIFLY_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg t "$TITLE" --arg m "$MESSAGE" --argjson p "$PRIORITY" \
'{title:$t, message:$m, priority:$p}')" >/dev/null

Make the file executable and put the tokens in /etc/notifly.env:

Окно терминала
sudo chmod +x /usr/local/bin/notifly-send
sudo tee /etc/notifly.env >/dev/null <<'EOF'
NOTIFLY_URL=https://your-notifly.example.com
NOTIFLY_TOKEN=AGdjfk_L.dKe8q
EOF
sudo chmod 600 /etc/notifly.env

Then in all scripts it’s enough to source the variables:

Окно терминала
set -a; source /etc/notifly.env; set +a
notifly-send "Тест" "Привет с $(hostname)"

For Windows servers use the PowerShell function Send-Notifly. Save it to the profile C:\Program Files\WindowsPowerShell\Modules\Notifly\Notifly.psm1 (or just dot-source via . C:\scripts\Notifly.ps1 at the start of each script):

C:\scripts\Notifly.ps1
$NotiflyConfigPath = "C:\ProgramData\Notifly\notifly.json"
function Send-Notifly {
param(
[Parameter(Mandatory)] [string] $Title,
[string] $Message = "",
[int] $Priority = 5
)
$cfg = Get-Content $NotiflyConfigPath -Raw | ConvertFrom-Json
$body = @{ title = $Title; message = $Message; priority = $Priority } | ConvertTo-Json -Compress
try {
Invoke-RestMethod -Method Post `
-Uri "$($cfg.url)/message?token=$($cfg.token)" `
-ContentType "application/json; charset=utf-8" `
-Body ([System.Text.Encoding]::UTF8.GetBytes($body)) `
-TimeoutSec 10 | Out-Null
} catch {
Write-EventLog -LogName Application -Source "Notifly" -EntryType Warning `
-EventId 1000 -Message "Send-Notifly failed: $_" -ErrorAction SilentlyContinue
}
}

Create the config (once, as administrator):

Окно терминала
New-Item -ItemType Directory -Path "C:\ProgramData\Notifly" -Force | Out-Null
@{
url = "https://your-notifly.example.com"
token = "AGdjfk_L.dKe8q"
} | ConvertTo-Json | Set-Content "C:\ProgramData\Notifly\notifly.json"
# Restrict reading to administrators and SYSTEM
icacls "C:\ProgramData\Notifly\notifly.json" /inheritance:r /grant:r "SYSTEM:R" "Administrators:R"

Test:

Окно терминала
. C:\scripts\Notifly.ps1
Send-Notifly -Title "Тест" -Message "Привет с $env:COMPUTERNAME" -Priority 5

All Windows examples in this section dot-source Notifly.ps1 and call Send-Notifly.