Using Uptime Kuma push monitors

Uptime Kuma has a “push” monitor type which supports sending in status updates for something like a cron job to make sure it continues to execute. I use this for tasks like running backups or cleanup chores.

Aside: To avoid tying monitoring to my normal infrastructure, I’ve been successfully running Uptime Kuma on I also recommend Cronitor for a similar commercial offering but its pricing doesn’t align well with my personal projects.

Normally to update Uptime Kuma you might append && curl … to invoke the monitor URL at the end of a script. I think this is a little too limiting, so I’ve written a small script that wraps an underlying command with a monitor update:

if [ $# -lt 1 ]; then
    echo "Usage: $0 <push_token> [command...]" >&2
    exit 1

push_token=$1; shift
start_time=$(date -u +%s%3N)

if [ $# -gt 0 ]; then
    "$@" || exit

end_time=$(date -u +%s%3N)
duration=$(($end_time - $start_time))

result=$(curl --fail --no-progress-meter --retry 3 "$push_token?ping=$duration" 2>&1)
if [ $? -ne 0 ]; then
    echo "Failed: $result" >&2

This script is invoked with the token and an optional underlying command to execute and report to Uptime Kuma when the command is successful along with its execution time as the ping property. For example:

kuma 3EpwDA93fC docker system prune -a -f

I’ve automated this using the ansible-uptime-kuma Ansible collection to automatically create “push” monitors for recurring jobs and “http” monitors for web-facing services. This ends up looking something like the following for a push monitor:

- name: Store the monitor name
    monitor_name: "{{ inventory_hostname }}-borgmatic"
- name: Create Uptime Kuma push monitor
    api_url: ""
    api_token: "{{ uptime_kuma_api_token }}"
    type: push
    name: "{{ monitor_name }}"
    interval: 3600
- name: Get Uptime Kuma push monitor info
    api_url: ""
    api_token: "{{ uptime_kuma_api_token }}"
    name: "{{ monitor_name }}"
  register: monitor_info
- name: Set Uptime Kuma push token
    push_token: "{{ monitor_info.monitors[0].pushToken }}"
- name: Create borg cronjob
    name: "Borg backups"
    job: "/usr/local/bin/kuma {{ push_token }} /usr/local/bin/borgmatic create"
    minute: 33

This creates a monitor for my borgmatic cron and executes it hourly. When it fails to check in, Uptime Kuma sends me notifications, and when it succeeds it keeps track of how long it takes to execute. Perfect!