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. Create a watchdog
Section titled “1. Create a watchdog”- In the Console, open Watchdogs and click New watchdog.
- 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.)
- Give it a name (letters, digits,
-and_, up to 64 characters). - Set the period - how often you will ping it (at least 30 seconds).
- 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.)
2. Ping from cron
Section titled “2. Ping from cron”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:
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.
3. Report failures and track run time
Section titled “3. Report failures and track run time”A plain ping says “the job ran”. Two extra pings let a watchdog say more:
- Ping the
/startURL 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
/failURL 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; fiDo 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.
/startand/failreturn the same200 ok/404/429. A/failreturns200even on an already-downwatchdog; it simply does nothing extra. - If the job crashes after
/startbut before the success or/failping, the run stays open and the watchdog alerts as stalled onceperiod + graceelapses from the start. So always send a matching success or/failwhen you use/start. /startalso arms a brand-new watchdog (its first/startmakes it active), and/startor/failon a paused watchdog does nothing.
4. Statuses
Section titled “4. Statuses”| 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.
5. Where alerts go
Section titled “5. Where alerts go”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.
Group related watchdogs
Section titled “Group related watchdogs”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.)
See uptime history
Section titled “See uptime history”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.
Pause, edit, delete
Section titled “Pause, edit, delete”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
404and no more alerts fire.
Troubleshooting
Section titled “Troubleshooting”- 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/startalso arms a new watchdog even before its first success ping. - My job pinged
/failbut no alert fired (or it still shows up). A/failon a watchdog that is alreadydownorpauseddoes nothing, and it returns200regardless. 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 - thecurlfailed, or the job exited before pinging - so the run stayed open pastperiod + grace. Make sure the closing ping runs even when earlier steps fail, and prefer the wrappedif/then/elseform above. - The “last run” duration never appears. A duration is recorded only when a
run was open, meaning you sent
/startfirst. 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.