No description
  • TypeScript 73.7%
  • Svelte 26.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-09-23 15:42:56 +02:00
backend feat: heartbeat pings to Healthchecks, with an optional checks view 2026-09-21 19:05:45 +02:00
frontend fix(frontend): ignore a second ping or refresh while one is in flight 2026-09-23 15:21:45 +02:00
shared feat: heartbeat pings to Healthchecks, with an optional checks view 2026-09-21 19:05:45 +02:00
.gitignore feat: heartbeat pings to Healthchecks, with an optional checks view 2026-09-21 19:05:45 +02:00
CLAUDE.md feat: heartbeat pings to Healthchecks, with an optional checks view 2026-09-21 19:05:45 +02:00
opsdeck.module.json feat: heartbeat pings to Healthchecks, with an optional checks view 2026-09-21 19:05:45 +02:00
README.md feat: heartbeat pings to Healthchecks, with an optional checks view 2026-09-21 19:05:45 +02:00
tsconfig.check.json feat: heartbeat pings to Healthchecks, with an optional checks view 2026-09-21 19:05:45 +02:00

OpsDeck module: Healthchecks

Reports this OpsDeck server as alive to Healthchecks (hosted or self-hosted) by pinging a check on a schedule. If the server, its container or its host stops, the pings stop and Healthchecks alerts whoever it is configured to alert.

Optionally — with a read-only API key — it also shows that project's checks inside OpsDeck: status, last and next ping, tags and schedule. Without a key the module only sends pings and shows its own heartbeat.

Configuration

Everything is set through the environment of the OpsDeck container and read once at start. The module's own configuration page (the info icon on the web, the "Configuration" page on mobile) lists the same variables with what is in effect.

Heartbeat

Variable Default What it does
OPSDECK_MOD_HEALTHCHECKS_PING_URL — Ping URL of the check that watches this server, e.g. https://hc-ping.com/<uuid>. Without it nothing is sent.
OPSDECK_MOD_HEALTHCHECKS_PING_INTERVAL_SEC 300 Seconds between pings. Keep it well below the check's period plus grace. Minimum 15.
OPSDECK_MOD_HEALTHCHECKS_ALERTS on Notify in OpsDeck when pings stop getting through, and when they work again.

Checks view (optional)

Variable Default What it does
OPSDECK_MOD_HEALTHCHECKS_API_KEY — A read-only API key turns the view on. Create one under Project Settings → API Access.
OPSDECK_MOD_HEALTHCHECKS_URL https://healthchecks.io Base URL of the instance the key belongs to (a path prefix is kept).
OPSDECK_MOD_HEALTHCHECKS_CHECKS_INTERVAL_SEC 60 Seconds between polls of the checks list. Minimum 15; the API allows 100 requests a minute per key.
OPSDECK_MOD_HEALTHCHECKS_TAGS — Only list checks carrying all of these tags, comma- or space-separated.
services:
  opsdeck:
    environment:
      OPSDECK_MOD_HEALTHCHECKS_PING_URL: https://hc-ping.com/<uuid>
      OPSDECK_MOD_HEALTHCHECKS_PING_INTERVAL_SEC: "300"
      OPSDECK_MOD_HEALTHCHECKS_ALERTS: "on"
      # optional, turns the checks view on:
      OPSDECK_MOD_HEALTHCHECKS_API_KEY: ${HEALTHCHECKS_API_KEY}

Set the check's period in Healthchecks a good deal higher than PING_INTERVAL_SEC (300 s pings against a 15 min period and 5 min grace is a sane pair), so a single dropped request does not page anyone.

Invalid values are reported on the configuration page and replaced by their default; they never disable the module. An unset PING_URL is reported the same way, and the module simply sends nothing.

What a ping looks like

A POST to the ping URL carrying one line of text (OpsDeck is up — uptime 3h 20m), which Healthchecks keeps as that ping's log. Any 2xx answer counts as delivered. Two failures in a row raise an OpsDeck notification, which clears itself when a ping gets through again.

Install

OPSDECK_EXTERNAL_MODULES=https://git.imhof.cloud/OpsDeck/module_healthchecks.git#<sha>

Pin the commit: a module runs with the server's privileges.

What's in here

opsdeck.module.json   manifest
shared/               wire shapes + time helpers used by BOTH halves (no imports)
backend/ping.ts       the heartbeat request and what may be shown of a ping URL
backend/config.ts     the settings, their validation, and the description the
                      configuration page is generated from
backend/api.ts        the one Management API call, and the fold to the wire shape
backend/mod.ts        schedules, alerts, routes, portable UI schema
frontend/             custom web pages + dashboard card (mobile renders the schema)

API (mounted at /api/mod/healthchecks)

Route Answers
GET /summary heartbeat state, checks-view state, configuration problems
POST /ping admin: send a heartbeat now
GET /checks the checks as last fetched (empty without an API key)
GET /check/:id one check; 404 when unknown
GET /settings the settings rows (secrets are masked)
POST /refresh admin: poll the checks list now

Pages re-fetch on the module's ping and checks topics, which are published only when something changed.

Develop

git clone <core> && cd core
cp -r ../module_healthchecks packages/modules/healthchecks
deno task build                       # or build:modules after frontend edits
OPSDECK_AUTH=disabled OPSDECK_MODULES=healthchecks \
  OPSDECK_MOD_HEALTHCHECKS_PING_URL=https://hc-ping.com/… deno task start
# http://localhost:8080/m/healthchecks

deno test packages/modules/healthchecks/   # or `deno test backend/ shared/` in a bare clone
deno check packages/modules/healthchecks/backend/mod.ts
deno run -A npm:svelte-check@^4 --workspace packages/modules/healthchecks \
  --tsconfig ./tsconfig.check.json --threshold error

Remove the copy afterwards; this repository is the source of truth.