Skip to content

Get alerted when a cron job stops running

A watchdog expects a ping on a schedule. As long as your job pings it, all is well; if a ping is ever missed, the watchdog alerts you through your existing notifications (the Console feed, Telegram, or your phone). It is the classic dead-man’s-switch for cron jobs, backups, and any task that is supposed to run on time. (Since v0.3.0.)

  1. In the Console, open Watchdogs and click New watchdog.
  2. Pick a template: Custom for a blank schedule, or a preset like Nightly backup (24 h period, 1 h grace), Frequent cron job (5 m + 1 m), or Weekly job (7 d + 6 h). Templates only prefill the form - everything stays editable. (Since v0.3.1.)
  3. Give it a name (letters, digits, - and _, up to 64 characters).
  4. Set the period - how often you will ping it (at least 30 seconds).
  5. Set the grace - extra slack before an alert fires.

An alert fires if no ping arrives for period + grace. For a job that runs every 5 minutes, a 5-minute period with a minute or two of grace is typical.

After creating, the dialog shows the watchdog’s ping URL and a Copy instructions for an AI agent button: paste the copied prompt into an AI coding agent (such as Claude Code) on the machine that runs the job, and it wires the pings into your cron entry or script for you. (Since v0.3.1.)

An AI agent can also do the whole thing for you, creating the watchdog and wiring the pings into the job on the machine that runs it, once you connect it to DedNets: see Let an AI agent run DedNets. (Since v0.4.1.)

Copy the ping URL from the watchdog’s row (or open its Details page, whose Ping command section has a ready-made curl line and crontab snippet). Any HTTP GET or POST to the URL counts as a ping:

Terminal window
curl -fsS https://console.dednets.com/api/v0/wd/wd<your-address>

A 200 ok response means the ping was recorded. Put the ping at the end of your job so a failed run stops pinging and the watchdog notices:

*/5 * * * * /usr/local/bin/nightly-backup && curl -fsS https://console.dednets.com/api/v0/wd/wd<your-address>

Possession of the URL is the credential, so keep it secret. There is no way to rotate a leaked URL in place: delete the watchdog and create a new one.

For jobs that can fail loudly, the next section shows how to alert immediately on failure and track how long each run takes.

A plain ping says “the job ran”. Two extra pings let a watchdog say more:

  • Ping the /start URL when the job begins, and the plain URL when it succeeds. Between the two, the watchdog knows a run is in progress and shows a live “running for” timer.
  • If the job fails, ping the /fail URL to alert immediately instead of waiting for the timeout.

The Ping command section on the watchdog’s Details page gives you a paste-ready crontab line that does all three. It uses an explicit if/then/else so the failure ping fires only when the job itself fails:

*/5 * * * * curl -fsS https://console.dednets.com/api/v0/wd/wd<your-address>/start; if /usr/local/bin/nightly-backup; then curl -fsS https://console.dednets.com/api/v0/wd/wd<your-address>; else curl -fsS https://console.dednets.com/api/v0/wd/wd<your-address>/fail; fi

Do not use the shorter job && ok-ping || fail-ping form: it fires the failure ping when the success ping itself fails (say, a brief network blip), a false alarm. The if/then/else reports failure only when the job exits non-zero.

A few things worth knowing:

  • Response codes match the plain ping. /start and /fail return the same 200 ok / 404 / 429. A /fail returns 200 even on an already-down watchdog; it simply does nothing extra.
  • If the job crashes after /start but before the success or /fail ping, the run stays open and the watchdog alerts as stalled once period + grace elapses from the start. So always send a matching success or /fail when you use /start.
  • /start also arms a brand-new watchdog (its first /start makes it active), and /start or /fail on a paused watchdog does nothing.
Status Meaning
new created but never pinged; stays silent until the first ping arrives
up pinged on time and healthy
late the period has lapsed but the grace window has not; no alert yet
running a run is in progress (you pinged /start); the row shows a live “running for” timer and, once the run finishes, its “last run” duration
down no ping for period + grace; an alert has fired
paused you paused it; the checker will not alert

A brand-new watchdog stays new and silent until its first ping - send one ping to arm it. Once healthy, it goes late when the period lapses and down after the grace window, which is when the alert fires. While a run is open the row shows a running badge with a live elapsed timer, and after the run closes it shows the last run duration.

Alerts land in your watchdogs notification topic and follow your normal routing: live in the Console, and on Telegram or your phone if you have linked them (see Send notifications from your systems). There are three alarm alerts, all high priority:

  • a down alert - no ping arrived in time;
  • a failed alert - your job reported a failure via /fail;
  • a stalled alert - a started run never finished in time.

Recovery is the all-clear: a ping on a down watchdog recovers it and sends the all-clear automatically.

Give a watchdog a group - any label such as homelab, backups, or a customer name - and the Console lists every watchdog sharing that label together, in one collapsible section. The section header shows how many watchdogs it holds and a single badge for the worst status inside, so one glance at a collapsed group tells you whether anything in your homelab is down. Groups are listed alphabetically, and watchdogs without one come last, under Ungrouped. Click a header to fold a group away.

The Group field sits right under the name in the create and edit dialogs and suggests the groups you already use, so the names stay consistent. It is optional: leave it empty and nothing changes - if none of your watchdogs have a group, the list looks exactly as it always did. Clearing the field on an existing watchdog moves it back to Ungrouped. Group names take the same characters as watchdog names (letters, digits, - and _, up to 64 characters). (Since v0.4.1.)

Each row in the watchdogs list shows its last-24-hours uptime at a glance: the percentage plus a mini strip of hourly cells, the same readout the services table uses. For the full picture, every watchdog row has a Details link that opens its history page. There you get an uptime percentage and a row of status cells for three ranges - the last 24 hours (hourly cells), 30 days (daily), and 12 weeks (weekly). Each cell is colored by its uptime: green for a clean run, dimmer shades as downtime grows, and a hatched grey cell for time with no data. Hover a cell for its exact window and percentage. Below the strip, the Outages list shows each down period with its cause (timeout, failure, or stall), when it started, how long it lasted, and whether it is resolved or still ongoing; Load more pages back through older outages.

A few things worth knowing:

  • Uptime counts from a watchdog’s first ping or /start, not from the moment you created it. A brand-new watchdog shows all-grey (no data) until that first signal, so it never shows a misleading 100%.
  • Paused time and time before creation count as no data (grey), never as downtime.
  • History goes back about 90 days by default (the operator can change this with CONSOLE_WATCHDOG_HISTORY_DAYS). Older resolved outages age out of the list. Deleting a watchdog erases its history for good.

The list rows keep just Details and Edit; pausing, deleting, and the ping-command snippets live on the watchdog’s Details page.

  • Pause stops alerts without deleting the watchdog; resume picks back up.
  • Editing the name, period, or grace keeps the same ping URL.
  • Deleting revokes the URL: old pings return 404 and no more alerts fire.
  • No alert ever fired. The watchdog never received a first ping (it is still new, and the checker only watches monitors that were healthy), or it is paused. Send one ping to arm it. A /start also arms a new watchdog even before its first success ping.
  • My job pinged /fail but no alert fired (or it still shows up). A /fail on a watchdog that is already down or paused does nothing, and it returns 200 regardless. The failure alert fires only once per outage, on the flip from healthy to down.
  • A stalled alert fired but the job actually finished. The success (or /fail) ping at the end of the run did not reach us - the curl failed, or the job exited before pinging - so the run stayed open past period + grace. Make sure the closing ping runs even when earlier steps fail, and prefer the wrapped if/then/else form above.
  • The “last run” duration never appears. A duration is recorded only when a run was open, meaning you sent /start first. Plain pings alone never open a run, so there is nothing to time.
  • Alert in the Console but not on my phone or Telegram. You have not linked Telegram or subscribed a push app, or the topic’s minimum priority is set above the alert’s priority. See the notifications guide.
  • Ping returns 404. Wrong or deleted watchdog URL; copy it again from the row.
  • Ping returns 429. Too many requests too fast - pings share your account’s notification rate limit. One ping per run is enough, and the minimum period is 30 seconds.
  • The alert is a little late. The checker runs about every 30 seconds, so an alert can arrive up to ~30 seconds after period + grace.
  • The chart has grey cells. Grey means no data, not downtime: time before you created the watchdog, before its first ping (while it was new), or while it was paused reads as no data. A brand-new watchdog is all grey until its first ping or /start.
  • Uptime starts partway through the window / a new watchdog shows no green. Uptime is measured from the first affirmative signal (the first success ping or /start), not from creation, so a just-created or long-idle watchdog has no green until it first reports in.
  • An old outage disappeared from the list. History is pruned after the retention window (about 90 days by default), so resolved outages older than that drop off. The watchdog’s current status is always correct regardless.
  • A deleted watchdog’s history is gone. Deleting a watchdog removes its history with it; recreating one with the same name starts fresh.