You don't need a monitoring platform
Datadog starts at $15/host/month. Uptime Robot's free tier gives you 50 monitors with 5‑minute checks — and they read your data. If you have one website, one API, or one side project, all you need is curl, cron, and a way to get a push on your phone when something breaks.
Nerve is free during beta. The alert payload is encrypted before it leaves your server. The monitoring token can only send — it cannot read your alert history or execute commands.
Step 1: Install the CLI
go install github.com/nerve-ink/nerve-cli/cmd/nerve@latest
No Go on your server? Paste this block — it installs Go first:
command -v go >/dev/null || {
GO_VERSION="$(curl -fsSL 'https://go.dev/VERSION?m=text' | head -n 1)"
case "$(uname -m)" in
x86_64|amd64) GO_ARCH="amd64" ;;
aarch64|arm64) GO_ARCH="arm64" ;;
esac
curl -fsSLO "https://go.dev/dl/${GO_VERSION}.linux-${GO_ARCH}.tar.gz"
sudo tar -C /usr/local -xzf "${GO_VERSION}.linux-${GO_ARCH}.tar.gz"
export PATH="/usr/local/go/bin:$PATH"
}
go install github.com/nerve-ink/nerve-cli/cmd/nerve@latest
export PATH="$PATH:$(go env GOPATH)/bin"
Step 2: Create the monitoring script
#!/bin/bash
# /usr/local/bin/check-website.sh
set -euo pipefail
export NERVE_DSN="nerve://TOKEN:[email protected]"
URL="https://yoursite.com"
TIMEOUT=10
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time "$TIMEOUT" "$URL" || echo "000")
if [ "$HTTP_CODE" = "000" ]; then
echo "DOWN: $URL is unreachable (timeout ${TIMEOUT}s)" | nerve send --severity critical
elif [ "$HTTP_CODE" -ge 500 ]; then
echo "ERROR: $URL returned HTTP $HTTP_CODE" | nerve send --severity critical
elif [ "$HTTP_CODE" -ge 400 ]; then
echo "WARNING: $URL returned HTTP $HTTP_CODE" | nerve send --severity alert
fi
chmod +x /usr/local/bin/check-website.sh
Step 3: Add to cron
# Check every 2 minutes
*/2 * * * * /usr/local/bin/check-website.sh
That's it. Your phone will buzz when the site goes down.
Check multiple URLs
#!/bin/bash
export NERVE_DSN="nerve://TOKEN:[email protected]"
TIMEOUT=10
URLS=(
"https://yoursite.com"
"https://api.yoursite.com/health"
"https://dashboard.yoursite.com"
)
for URL in "${URLS[@]}"; do
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time "$TIMEOUT" "$URL" || echo "000")
if [ "$HTTP_CODE" = "000" ] || [ "$HTTP_CODE" -ge 500 ]; then
echo "DOWN: $URL (HTTP $HTTP_CODE)" | nerve send --severity critical
fi
done
Check response body (smoke test)
Sometimes a page returns 200 OK but the content is wrong — a blank page, an error message, or a maintenance screen.
BODY=$(curl -s --max-time 10 "https://yoursite.com")
if ! echo "$BODY" | grep -q "Welcome"; then
echo "CONTENT CHECK FAILED: yoursite.com missing expected text" | nerve send --severity alert
fi
Check response time
TIME=$(curl -s -o /dev/null -w "%{time_total}" --max-time 15 "https://yoursite.com" || echo "99")
SLOW=$(echo "$TIME > 3.0" | bc -l 2>/dev/null || echo "0")
if [ "$SLOW" = "1" ]; then
echo "SLOW: yoursite.com took ${TIME}s" | nerve send --severity alert
fi
Why not Uptime Robot or Datadog?
Next: add disk, SSL, and backup checks
Once you have basic uptime monitoring, the same pattern works for everything: