← All guidesGitHub
Site Operations

Monitor a Website with Uptime Kuma

Run Uptime Kuma on a separate server, check a website over HTTPS, and prove that an alert and recovery reach you before an outage does.

Jump to stepsGitHub: TylorMayfield/uptime-kuma-droplet-monitor

Decide what this monitor can prove

Run Uptime Kuma on a different server from the site it checks. An application-server failure should not stop the monitor. Two Droplets at one provider still do not cover a provider-wide outage.

Create and restrict the monitor server

Create a fresh Ubuntu 24.04 LTS Droplet. A region near the site reduces latency; a different region checks another network path. Choose the path you want to monitor.

  1. In DigitalOcean, create a Droplet with an SSH key. Name it for its role, such as uptime-kuma-monitor, rather than after the site it checks.
  2. Create a Cloud Firewall and attach it only to this Droplet. Allow TCP 80 and 443 from the internet for HTTPS certificate issuance and dashboard access. Allow TCP 22 only from your current administrator address or VPN range.
  3. Create an A or AAAA record for the dashboard name that points to the monitor Droplet. Wait for it to resolve before starting Caddy, because Caddy uses the name to obtain a public certificate.
  4. Do not open Uptime Kuma's own port 3001 in the firewall. The companion Compose file keeps it on the internal Docker network and lets Caddy be the only public listener.
  1. From your computer: connect with your SSH keyLocal terminal
    ssh root@YOUR_DROPLET_IP
On Ubuntu 24.04: install Docker and ComposeConnected Droplet
apt-get update
apt-get install -y docker.io docker-compose-v2 git nano python3
systemctl enable --now docker
docker compose version
cd /root

Start Uptime Kuma behind HTTPS

Run the following commands in the root SSH terminal opened above. In Nano, save with Ctrl+O and Enter, then exit with Ctrl+X before continuing.

The companion repository keeps the configuration short on purpose. Uptime Kuma stores its state under ./data, while Caddy owns ports 80 and 443 and proxies to the Uptime Kuma container. The setup uses Uptime Kuma's maintained major-version image tag. Review the project's update notes before changing it.

Uptime Kuma documents that its data must live on a local directory or volume, not NFS. Keep the data on the monitor Droplet's local disk and include it in your server backup plan. The monitor should be boring enough that you can rebuild it, but its notification settings and monitor history are still useful data.

If the dashboard check fails, first confirm DNS resolves to this Droplet and that the Cloud Firewall is attached. Then inspect the relevant service status. Do not open port 3001 as a shortcut: this configuration intentionally keeps it private behind Caddy, so exposing it would change the security boundary rather than prove the installation.

Before continuing: This starts public HTTPS services on the monitor Droplet. Confirm the DNS record and firewall rules before running it.

  1. Clone the companion projectOn the monitoring server
    git clone https://github.com/TylorMayfield/uptime-kuma-droplet-monitor.git
  2. Open the directory
    cd uptime-kuma-droplet-monitor
  3. Create the environment file
    cp .env.example .env
  4. Set the DNS nameFile editor
    nano .env
  5. Allow the scripts to runOn the monitoring server
    chmod 700 scripts/preflight.sh scripts/check-dashboard.sh
  6. Run the preflight
    ./scripts/preflight.sh
  7. Start the services
    docker compose up -d
  8. Check the dashboard
    ./scripts/check-dashboard.sh

Create one monitor and one notification before adding more

Open https://KUMA_DOMAIN and create the first administrator account. Treat it as a private operations dashboard. Do not make it a public status page by accident. A public status page is a separate choice for people who need to check your service, and it can expose service names and outage history.

In the dashboard, add a notification method you can test. Then add an HTTP(s) monitor for a harmless health URL, set its expected status code, and attach the notification. Start with one monitor. Add more monitors after the down and recovery test succeeds.

  1. Send Uptime Kuma's notification test and confirm it reaches the intended person or channel.
  2. Create an HTTP(s) monitor for a health URL that returns a predictable success response without changing application state.
  3. Set a timeout and retry behavior that match the service. Do not choose a tiny timeout just to make the dashboard look busy.
  4. Give the monitor a name that says what failed, such as Website HTTPS health check, rather than a vague name such as Production.

Prove an alert and recovery without taking down production

Create a temporary HTTP monitor in Uptime Kuma for http://host.docker.internal:8099, expecting status 200, with your notification enabled. For this test add extra_hosts: ["host.docker.internal:host-gateway"] to the Uptime Kuma service in your Compose file and recreate it. The small server below listens on the host; keep 8099 closed to the internet in the Cloud Firewall. It initially returns 503.

Save the Python below as /root/kuma-test-target.py. In a second SSH terminal, run python3 /root/kuma-test-target.py and keep it open. Wait for the down notification. In the first terminal, create /tmp/kuma-test-healthy with touch /tmp/kuma-test-healthy. Wait for recovery, then delete the temporary monitor, stop Python with Ctrl+C, and remove the marker file. Do not change the production site.

Disposable HTTP target: kuma-test-target.pyFile contents
from http.server import BaseHTTPRequestHandler, HTTPServer
from pathlib import Path

marker = Path("/tmp/kuma-test-healthy")
marker.unlink(missing_ok=True)

class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        status = 200 if marker.exists() else 503
        self.send_response(status)
        self.end_headers()
        self.wfile.write(str(status).encode())

HTTPServer(("0.0.0.0", 8099), Handler).serve_forever()

Before continuing: This restarts the monitoring dashboard. Run it only after a working deployment exists.

Check that the dashboard is reachable after a restartOn the monitoring server
cd /root/uptime-kuma-droplet-monitor
docker compose up -d
./scripts/check-dashboard.sh

Keep the signal useful

Review monitors after the first false alert. If a transient failure is common and harmless, change the retry or timeout after you understand it. Do not silence a monitor because it caught an inconvenient problem. Route alerts to people who can act on them, and remove destinations when responsibilities change.

Update Uptime Kuma deliberately. Back up its local data, read the upstream update notes, pull the image, recreate the services, and recheck one dashboard login, one monitor, and one notification.

Check your result

Expected result
The dashboard is available over HTTPS, the down notification arrives after the controlled failure, and the recovery notification arrives when the target succeeds again.
Stop if
Stop if the monitor runs on the application server, port 3001 is public, the dashboard has no administrator account, DNS does not resolve to the monitor, or the notification test does not arrive.
Next step
Record the alert and recovery times, then add the production health check only after its URL and expected response are known.