Uptime Monitoring

Monitoring Private Endpoints and APIs

By: August Flanagan|Last Updated: Oct 09, 2026

Uptime checks request your URL from Cronitor's public regions. That works until the host is only reachable on a private network.

Cronitor does not run those checks from inside your network, and there is no private-location probe to install. Pick the path that matches how reachable the endpoint already is.

  • The host is on the internet, and a firewall can allow a fixed set of source addresses. Create a normal check. Turn on Use Static IPs for Checks in account settings and allow the addresses at cronitor.io/ips.txt. Static addresses are published for US West, US East, EU West, and EU Central. The free plan cannot enable this. Leave the check's regions empty to use the account default, which follows that pool when static IPs are on.
  • The host must stay unreachable from the internet. Do not open a port or a tunnel for the probe. Run the request on a machine that can already see the URL, and report the result to Cronitor as a job. That is the rest of this guide.
  • The machine that should send the report cannot reach cronitor.link. Put a narrow outbound proxy on a peer that can. See Monitoring Private Servers.

A private MCP server is the same case as any other private URL. See Monitor an MCP Server.

A job inside the private network pings Nginx, Django, and Kubernetes, then reports out to Cronitor.

Get Started in Cronitor, with Jobs, Checks, Heartbeats, Sites, and Status Pages.

You need:

  1. A script that requests the private URL and exits non-zero when the request fails.
  2. A cron entry for each URL, wrapped so Cronitor hears about the exit status.
  3. A Cronitor account. The free plan includes up to 5 monitors.

Run the cron job on a server that is already inside the private network.

Bash script for checking uptime

Save this as /opt/check_url.sh. curl --fail exits non-zero unless the response status is 2xx, and set -e stops the script on that failure.

#!/usr/bin/env bash

if [ -z "$1" ]; then
  echo "Usage: check_url.sh <URL>" >&2
  exit 1
fi

set -e
curl --fail --silent --show-error "$1"
echo "OK"
chmod +x /opt/check_url.sh
/opt/check_url.sh https://cronitor.io

A successful run prints OK.

Install CronitorCLI

The install script picks the binary for the machine. It does not take an API key.

curl -fsSL 'https://cronitor.io/install-linux?sudo=1' | sh

Copy the SDK Integration key from API settings. Put it in the environment, not on the command line:

export CRONITOR_API_KEY
sudo --preserve-env=CRONITOR_API_KEY cronitor configure

configure prints API Key: Set. It does not print the key. It writes /etc/cronitor/cronitor.json. A new file is owner-only (mode 0600), so only root can read the key.

Register the cron job

Install the lines with sudo crontab -e. That is root's crontab, and root can read the config file. A normal user's crontab runs cronitor exec as that user, who cannot read /etc/cronitor/cronitor.json. Give that user credentials of their own: set CRONITOR_API_KEY in their crontab, or set CRONITOR_CONFIG to a file they own and run cronitor configure as them.

Without a readable key, exec does not create a monitor. It sends an unauthenticated ping only when the monitor id is a 3 to 12 character code. Accounts created after January 11, 2021 have anonymous events off until you enable them, so that ping is rejected. The keys below are not codes, so the ping is not sent at all.

Run the script on a schedule. Every minute is a reasonable start for an uptime check. CronitorCLI's exec starts the command, waits for it, and sends run, complete, or fail with the exit status. --no-stdout has to come before the monitor key. It skips uploading the script's output. The command string is still sent, so keep tokens out of the URL.

* * * * * cronitor exec --no-stdout check-internal-api /opt/check_url.sh https://example.com/internal-api
* * * * * cronitor exec --no-stdout check-other-internal-api /opt/check_url.sh https://example.com/other-internal-api

check-internal-api is the monitor key. When the ping is authenticated, a new monitor is created on the first ping. That does not copy the cron expression onto the monitor. Open the job and set the same schedule, or a missed minute cannot alert. Grace periods and failure tolerance are in the cron job docs.

cronitor sync imports crontab lines and writes their schedules onto the monitors. Review what it will change before you run it. discover is an alias of the same command. See Using Cronitor CLI.

After a real run, the job appears on the Jobs list. The detail page shows the schedule, execution time, and the latest run or failure.

Job detail for prune-events, with execution time, events, and the latest complete run. The telemetry URL is covered.

Attach a notification list under Alert Settings, or on the alerts settings page, before you rely on the monitor. Slack, email, SMS, and the other integrations all hang off that list. When the script exits non-zero, Cronitor opens an issue and notifies the list. The run's duration is on the job. With --no-stdout, the script's output is left out.

What this does not do

The script above only checks for a 2xx response. It does not record response time as a check chart, and it does not run from Cronitor's regions. If you later publish the service, replace the job with a check so Cronitor makes the request itself.

Questions: support@cronitor.io.

Previous
How to Fix & Monitor DNS Errors