Сервис уведомлений - ntfy.sh

Пока только заметки

Запуск сервиса

docker-compose.yaml

version: '3.3'

services:
  ntfy:
    image: binwiederhier/ntfy
    container_name: ntfy
    command:
      - serve
    environment:
      - TZ=Europe/Moscow    # optional: set desired timezone
    user: 1002:1002 # optional: replace with your own user/group or uid/gid
    network_mode: "host"
    volumes:
      - /srv/data/ntfy:/var/cache/ntfy
      - /srv/docker/ntfy/etc:/etc/ntfy
    environment:
      NTFY_LISTEN_HTTP: "127.0.0.1:9010"
      NTFY_BASE_URL: "https://ntfy.myhost.ru"
      NTFY_BEHIND_PROXY: "true"
      NTFY_AUTH_FILE: "/var/cache/ntfy/auth.db"
      NTFY_AUTH_DEFAULT_ACCESS: "deny-all"
      NTFY_ENABLE_LOGIN: "true"
      NTFY_REQUIRE_LOGIN: "true"
      NTFY_ATTACHMENT_CACHE_DIR: "/var/cache/ntfy/attachments"
      NTFY_CACHE_FILE: "/var/cache/ntfy/cache.db"
    restart: unless-stopped

Nginx

server {
  server_name ntfy.myhost.ru;

  location / {
    proxy_pass http://127.0.0.1:9010;
    proxy_http_version 1.1;

    proxy_buffering off;
    proxy_request_buffering off;
    proxy_redirect off;

    proxy_set_header Host $http_host;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    proxy_connect_timeout 3m;
    proxy_send_timeout 3m;
    proxy_read_timeout 3m;

    client_max_body_size 0; # Stream request body to backend
  }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/ntfy.myhost.ru/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/ntfy.myhost.ru/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

server {
    listen 80;
    server_name ntfy.myhost.ru;

    location /.well-known/acme-challenge/ {
        root /srv/www/ntfy/well-known;
    }
    location / {
        return 301 https://$host$request_uri;
    }
}

Новый пользователь - docker exec -it ntfy ntfy user a user
Права (можно использовать *) - docker exec -it ntfy ntfy access user myChannel wo
Получения токена (для отправки) - docker exec -it ntfy ntfy token a user

Скрипт отправки системных уведомлений

#!/bin/bash

CHANNEL=Channel
HOST=https://ntfy.myhost.ru
TOKEN=wewedfshdjfg7e8rfiqgewhfd

print_help() {
    cat <<'EOF'
Usage:
  send_notify.sh [-c CHANNEL] [-p PRIORITY] [SUBJECT...]
  echo "message body" | send_notify.sh [options] [SUBJECT...]

Options:
  -c CHANNEL     Ntfy channel/topic (default: myChannel)
  -p PRIORITY    Ntfy priority (1-5 or min/low/default/high/max)
  -h, --help     Show this help
  --             Stop parsing options; rest goes to SUBJECT

Examples:
  echo "Disk is full" | send_notify.sh -p high disk alert
  echo "Host down" | send_notify.sh -c alerts -p 5 production host
EOF
}

SUBJECT="Host: `hostname`"
PRIORITY=""

while [[ $# -gt 0 ]]; do
    case "$1" in
        -c)
            if [[ -z "$2" ]]; then
                echo "Channel is required" >&2
                exit 1
            fi
            CHANNEL="$2"
            shift 2
            ;;
        -p)
            if [[ -z "$2" ]]; then
                echo "Priority is required" >&2
                print_help >&2
                exit 1
            fi
            PRIORITY="$2"
            shift 2
            ;;
        -h|--help)
            print_help
            exit 0
            ;;
        --)
            shift
            break
            ;;
        -*)
            echo "Unknown option: $1" >&2
            print_help >&2
            exit 1
            ;;
        *)
            break
            ;;
    esac
done

if [[ -n "$*" ]]; then
    SUBJECT="${SUBJECT}, $*"
fi

TEXT="$(cat)"
if [[ -z "${TEXT}" ]]; then
    exit
fi

PRIORITY_HEADER=()
if [[ -n "${PRIORITY}" ]]; then
    PRIORITY_HEADER=(-H "Priority: ${PRIORITY}")
fi

/usr/bin/curl --silent --output /dev/null \
    -H "Authorization: Bearer ${TOKEN}" \
    -H "Title: ${SUBJECT}" \
    "${PRIORITY_HEADER[@]}" \
    -d "${TEXT}" \
    "${HOST}/${CHANNEL}"

Icinga2

ntfy-host-notification.sh

#!/usr/bin/env bash
PROG="`basename $0`"
HOSTNAME="`hostname`"
unset DEBUG

Usage() {
cat << EOF
The following are required:
  -4 HOSTADDRESS (\$address$)
  -l HOSTALIAS (\$host.name$)
  -n HOSTDISPLAYNAME (\$host.display_name$)
  -o HOSTOUTPUT (\$host.output$)
  -d LONGDATETIME (\$icinga.long_date_time$)
  -s HOSTSTATE (\$host.state$)
  -t NOTIFICATIONTYPE (\$notification.type$)
  -C NTFYCHANNEL (\$ntfy_channel$)
  -H NTFYHOST (\$ntfy_host$)
  -T NTFYTOKEN (\$ntfy_token$)

And these are optional:
  -b NOTIFICATIONAUTHORNAME (\$notification.author$)
  -c NOTIFICATIONCOMMENT (\$notification.comment$)
  -P NTFYPRIORITY (1-5 or min/low/default/high/max)
EOF

exit 1;
}

while getopts 4:b:c:d:h:l:n:o:s:t:C:H:T:P: opt
do
  case "$opt" in
    4) HOSTADDRESS=$OPTARG ;;
    b) NOTIFICATIONAUTHORNAME=$OPTARG ;;
    c) NOTIFICATIONCOMMENT=$OPTARG ;;
    d) LONGDATETIME=$OPTARG ;;
    h) Usage ;;
    l) HOSTALIAS=$OPTARG ;;
    n) HOSTDISPLAYNAME=$OPTARG ;;
    o) HOSTOUTPUT=$OPTARG ;;
    s) HOSTSTATE=$OPTARG ;;
    t) NOTIFICATIONTYPE=$OPTARG ;;
    C) NTFYCHANNEL=$OPTARG ;;
    H) NTFYHOST=$OPTARG ;;
    T) NTFYTOKEN=$OPTARG ;;
    P) NTFYPRIORITY=$OPTARG ;;

   \?) echo "ERROR: Invalid option -$OPTARG" >&2
       Usage ;;
    :) echo "Missing option argument for -$OPTARG" >&2
       Usage ;;
    *) echo "Unimplemented option: -$OPTARG" >&2
       Usage ;;
  esac
done

SUBJECT="[$NOTIFICATIONTYPE] Host $HOSTDISPLAYNAME is $HOSTSTATE!"

## Build the message itself
NOTIFICATION_MESSAGE=$(cat << EOF
When:    $LONGDATETIME
Host:    $HOSTALIAS ($HOSTADDRESS)
Info:    $HOSTOUTPUT
EOF
)

## Are there any comments? Put them into the message!
if [ -n "$NOTIFICATIONCOMMENT" ] ; then
  NOTIFICATION_MESSAGE="$NOTIFICATION_MESSAGE
Comment by $NOTIFICATIONAUTHORNAME:
  $NOTIFICATIONCOMMENT"
fi

PRIORITY_HEADER=()
if [ -n "$NTFYPRIORITY" ] ; then
  PRIORITY_HEADER=(-H "Priority: ${NTFYPRIORITY}")
fi

curl -H "Authorization: Bearer ${NTFYTOKEN}" -H "Title: ${SUBJECT}" "${PRIORITY_HEADER[@]}" -d "${NOTIFICATION_MESSAGE}" {$NTFYHOST}/${NTFYCHANNEL}

set +x

ntfy-service-notification.sh`

#!/usr/bin/env bash

PROG="`basename $0`"
HOSTNAME="`hostname`"
unset DEBUG

Usage() {
cat << EOF
The following are required:
  -4 HOSTADDRESS (\$address$)
  -d LONGDATETIME (\$icinga.long_date_time$)
  -e SERVICENAME (\$service.name$)
  -l HOSTALIAS (\$host.name$)
  -n HOSTDISPLAYNAME (\$host.display_name$)
  -o SERVICEOUTPUT (\$service.output$)
  -s SERVICESTATE (\$service.state$)
  -t NOTIFICATIONTYPE (\$notification.type$)
  -u SERVICEDISPLAYNAME (\$service.display_name$)
  -C NTFYCHANNEL (\$ntfy_channel$)
  -H NTFYHOST (\$ntfy_host$)
  -T NTFYTOKEN (\$ntfy_token$)

And these are optional:
  -b NOTIFICATIONAUTHORNAME (\$notification.author$)
  -c NOTIFICATIONCOMMENT (\$notification.comment$)
  -P NTFYPRIORITY (1-5 or min/low/default/high/max)

EOF
exit 1;
}

while getopts 4:b:c:d:e:l:n:o:s:t:u:C:H:T:P: opt
do
  case "$opt" in
    4) HOSTADDRESS=$OPTARG ;;
    b) NOTIFICATIONAUTHORNAME=$OPTARG ;;
    c) NOTIFICATIONCOMMENT=$OPTARG ;;
    d) LONGDATETIME=$OPTARG ;;
    e) SERVICENAME=$OPTARG ;;
    h) Usage ;;
    l) HOSTALIAS=$OPTARG ;;
    n) HOSTDISPLAYNAME=$OPTARG ;;
    o) SERVICEOUTPUT=$OPTARG ;;
    s) SERVICESTATE=$OPTARG ;;
    t) NOTIFICATIONTYPE=$OPTARG ;;
    u) SERVICEDISPLAYNAME=$OPTARG ;;
    C) NTFYCHANNEL=$OPTARG ;;
    H) NTFYHOST=$OPTARG ;;
    T) NTFYTOKEN=$OPTARG ;;
    P) NTFYPRIORITY=$OPTARG ;;
   \?) echo "ERROR: Invalid option -$OPTARG" >&2
       Usage ;;
    :) echo "Missing option argument for -$OPTARG" >&2
       Usage ;;
    *) echo "Unimplemented option: -$OPTARG" >&2
       Usage ;;
  esac
done

## Build the message's subject
SUBJECT="[$NOTIFICATIONTYPE] $SERVICEDISPLAYNAME on $HOSTDISPLAYNAME is $SERVICESTATE!"

## Build the message itself
NOTIFICATION_MESSAGE=$(cat << EOF
When: $LONGDATETIME
Host: $HOSTALIAS ($HOSTADDRESS)
Info: $SERVICEOUTPUT
EOF
)

## Are there any comments? Put them into the message!
if [ -n "$NOTIFICATIONCOMMENT" ] ; then
  NOTIFICATION_MESSAGE="$NOTIFICATION_MESSAGE
Comment by $NOTIFICATIONAUTHORNAME:
  $NOTIFICATIONCOMMENT"
fi

PRIORITY_HEADER=()
if [ -n "$NTFYPRIORITY" ] ; then
  PRIORITY_HEADER=(-H "Priority: ${NTFYPRIORITY}")
fi

/usr/bin/curl -H "Authorization: Bearer ${NTFYTOKEN}" -H "Title: ${SUBJECT}" "${PRIORITY_HEADER[@]}" -d "${NOTIFICATION_MESSAGE}" {$NTFYHOST}/${NTFYCHANNEL}

set +x

commands.conf

object NotificationCommand "ntfy-host-notifaction" {
    import "plugin-notification-command"
    command = [
        "/data/etc/icinga2/scripts/ntfy-host-notification.sh"
    ]
    timeout = 2m
    arguments += {
        "-4" = {
            required = true
            value = "$address$"
        }
        "-b" = {
            required = true
            value = "$notification.author$"
        }
        "-c" = "$notification.comment$"
        "-d" = {
            required = true
            value = "$icinga.long_date_time$"
        }
        "-l" = "$host.name$"
        "-n" = "$host.display_name$"
        "-o" = {
            required = true
            value = "$host.output$"
        }
        "-C" = {
            required = true
            value = "$ntfy_channel$"
        }
        "-T" = {
            required = true
            value = "$ntfy_token$"
        }
        "-H" = {
            required = true
            value = "$ntfy_host$"
        }
        "-s" = "$host.state$"
        "-t" = "$notification.type$"
        "-P" = "$ntfy_priority$"
    }
}

object NotificationCommand "ntfy-service-notification" {
    import "plugin-notification-command"
    command = [
        "/data/etc/icinga2/scripts/ntfy-service-notification.sh"
    ]
    timeout = 2m
    arguments += {
        "-4" = {
            required = true
            value = "$address$"
        }
        "-b" = {
            required = true
            value = "$notification.author$"
        }
        "-c" = "$notification.comment$"
        "-d" = {
            required = true
            value = "$icinga.long_date_time$"
        }
        "-e" = {
            required = true
            value = "$service.name$"
        }
        "-l" = "$host.name$"
        "-n" = "$host.display_name$"
        "-o" = {
            required = true
            value = "$service.output$"
        }
        "-s" = "$service.state$"
        "-t" = "$notification.type$"
        "-u" = {
            required = true
            value = "$service.display_name$"
        }
        "-C" = {
            required = true
            value = "$ntfy_channel$"
        }
        "-T" = {
            required = true
            value = "$ntfy_token$"
        }
        "-H" = {
            required = true
            value = "$ntfy_host$"
        }
        "-P" = "$ntfy_priority$"
    }
}

templates.conf

template Notification "ntfy-host-notification" {
  command = "ntfy-host-notifaction"
  states = [ Up, Down ]
  types = [ Problem, Acknowledgement, Recovery, Custom,
            FlappingStart, FlappingEnd ]
  vars += {
    notification_logtosyslog = false
    ntfy_token = "weklrhjsdfasdf7qw8eudfasf"
    ntfy_host = "https://ntfy.myhost.ru"
    ntfy_channel = "Channel"
    ntfy_priority = "5"
  }
  interval = 5h
  period = "24x7 local"
}

template Notification "ntfy-service-notification" {
  command = "ntfy-service-notification"
  states = [ OK, Warning, Critical, Unknown ]
  types = [ Problem, Acknowledgement, Recovery, Custom,
            FlappingStart, FlappingEnd ]
  vars += {
    ntfy_token = "shkfwfr8w9erydfidsahfkjq4r"
    ntfy_host = "https://ntfy.myhost.ru"
    ntfy_channel = "Channel"
    ntfy_priority = service.vars.ntfy_priority ? service.vars.ntfy_priority : ""
  }
  interval = 5h
  period = "24x7 local"
}

notifications.conf

apply Notification "ntfy-icingaadmin" to Host {
  import "ntfy-host-notification"
  users = [ "icingaadmin" ]

  assign where host.vars.notification.ntfy && host.vars.nohostalert != true
}

apply Notification "ntfy-icingaadmin" to Service {
  import "ntfy-service-notification"
  users = [ "icingaadmin" ]

  assign where service.vars.notification.ntfy
}

[ Править ]

@kiranananda