Create an Uptime Kuma and Grafana Homelab Monitor with Prometheus Metrics
Deploy Uptime Kuma v2 for endpoint checks and status pages, scrape its supported /metrics endpoint with Prometheus, and visualize response-time/status metrics in Grafana without...
Expected Outcome
A homelab monitoring stack in which Uptime Kuma owns checks and notifications, Prometheus collects supported metrics, and Grafana queries Prometheus for dashboards.
Assumptions
A Linux host with Docker Engine and Docker Compose v2.
At least one low-impact HTTP or TCP service you can monitor.
A reviewed Grafana and Prometheus image tag for the Lab.
A secure place to store the Uptime Kuma metrics API key.
Bill of Materials
Uptime Kuma v2 container image.
Prometheus container image.
Grafana container image.
One intentionally testable endpoint whose temporary outage will not affect users.
Build Steps
- Verify Compose v2 and create the stack directory
Use the current Docker Compose plugin rather than the retired standalone docker-compose executable.
Changes system state: review before running
docker --version docker compose version mkdir -p ~/homelab-monitor/{prometheus,.secrets} && cd ~/homelab-monitor - Start Uptime Kuma v2 first
Run Uptime Kuma with local persistent storage. Uptime Kuma's documentation warns that NFS-backed /app/data is unsupported, so use a local Docker volume or local filesystem path.
Changes system state: review before running
cat > compose.yaml <<'EOF' services: uptime-kuma: image: louislam/uptime-kuma:2 restart: unless-stopped ports: - "3001:3001" volumes: - uptime-kuma-data:/app/data volumes: uptime-kuma-data: EOF docker compose config --quiet docker compose up -d uptime-kuma docker compose ps - Create the first monitor and notification path
Open Uptime Kuma, create the administrator account, and add one low-impact HTTP or TCP monitor. Configure a notification method you can safely test. Uptime Kuma can send notifications and publish status pages, but it is not a general multi-stage incident-escalation engine; document any true escalation policy outside the tool if your workflow requires one.
- Create an API key for Prometheus metrics
Uptime Kuma supports a Prometheus-format /metrics endpoint. Create an API key in Uptime Kuma settings, then store the key in a root-readable/local secret file. Uptime Kuma documents API-key authentication as the password side of HTTP Basic Auth with an unused username.
Changes system state: review before running
printf '%s' '<UPTIME_KUMA_API_KEY>' > .secrets/kuma-metrics-key chmod 600 .secrets/kuma-metrics-key
- Configure Prometheus to scrape Uptime Kuma
Use the supported /metrics endpoint rather than querying Uptime Kuma's SQLite database. The documented metrics include monitor status and response time with labels such as monitor name/type/URL.
Read-only command: verify target and scope
cat > prometheus/prometheus.yml <<'EOF' global: scrape_interval: 30s scrape_configs: - job_name: uptime-kuma metrics_path: /metrics static_configs: - targets: ['uptime-kuma:3001'] basic_auth: username: '' password_file: /run/secrets/kuma_metrics_key EOF - Add Prometheus and Grafana to Compose
Replace the image placeholders with reviewed tags. Prometheus reads the Uptime Kuma key through a Compose secret, while Grafana reads only Prometheus—not Uptime Kuma's internal data store.
Read-only command: verify target and scope
cat >> compose.yaml <<'EOF' prometheus: image: prom/prometheus:<reviewed-tag> restart: unless-stopped command: ['--config.file=/etc/prometheus/prometheus.yml'] volumes: - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro secrets: - kuma_metrics_key ports: - "127.0.0.1:9090:9090" grafana: image: grafana/grafana:<reviewed-tag> restart: unless-stopped volumes: - grafana-data:/var/lib/grafana ports: - "3000:3000" depends_on: - prometheus volumes: grafana-data: secrets: kuma_metrics_key: file: ./.secrets/kuma-metrics-key EOF docker compose config --quiet - Start the metrics path and verify scraping
Bring up Prometheus and Grafana, then verify Prometheus sees the Uptime Kuma target as healthy before building a Grafana dashboard.
Changes system state: review before running
docker compose up -d docker compose ps curl -fsS 'http://127.0.0.1:9090/api/v1/query?query=up%7Bjob%3D%22uptime-kuma%22%7D'
- Add Prometheus as the Grafana data source and build two panels
In Grafana, add Prometheus at http://prometheus:9090. Create a status panel from monitor_status and a response-time panel from monitor_response_time, grouped by monitor_name. This makes the integration explicit and supportable.
- Create and validate a Uptime Kuma status page
Publish a status page only for monitors whose names and availability you are comfortable exposing to the intended audience. A public status page can disclose internal service names or topology, so keep it internal unless external publication is intentional.
- Run a controlled outage test
Temporarily stop or block only the disposable test endpoint. Confirm Uptime Kuma changes state and sends the configured notification, Prometheus reflects monitor_status, and Grafana displays the change. Restore the endpoint and confirm recovery is observed.
Validation
Uptime Kuma v2 is running with local persistent storage and at least one real monitor.
Prometheus successfully authenticates to Uptime Kuma's supported `/metrics` endpoint.
Grafana uses Prometheus as its data source rather than Uptime Kuma's internal database.
The dashboard displays `monitor_status` and `monitor_response_time` for the test monitor.
A controlled endpoint outage produces an Uptime Kuma state change/notification and a corresponding Prometheus/Grafana metric change.
Any status page exposes only information intentionally approved for its audience.
Troubleshooting
If Prometheus returns 401 from `/metrics`, verify the API key and Uptime Kuma's current metrics-authentication settings. Do not disable authentication merely to make scraping easy.
If Grafana has no data, query Prometheus directly for `up{job="uptime-kuma"}`, `monitor_status`, and `monitor_response_time` before changing Grafana panels.
If Uptime Kuma fails after moving its data to network storage, return `/app/data` to supported local storage; the project explicitly warns that NFS is unsupported.
Cleanup or Rollback
Restore the controlled test endpoint before ending the Lab.
Delete or revoke the Uptime Kuma API key if you remove Prometheus integration.
Stop the stack with `docker compose down`; preserve Uptime Kuma/Grafana volumes unless you have intentionally decided to destroy monitor history and dashboards.
Next Improvements
Add a second monitor type such as TCP or keyword checking to compare metrics behavior.
Put Uptime Kuma and Grafana behind an internal HTTPS reverse proxy before wider use.
Define actual escalation/on-call policy outside Uptime Kuma if the environment needs staged incident response.
