🛠️ Tutorials · ⏱ 9 min read

Monitor Your Homelab in 2026: Uptime Kuma + Grafana + Alerts (Complete Guide)

2026 tutorial for monitoring a homelab using Uptime Kuma, Prometheus, and Grafana via Docker. Covers availability probes, system metrics with node_exporter, dashboards, and Telegram alerts. Includes ready-to-use docker-compose configs and commands.

S By Selfhostr Team · independent tests
Monitor Your Homelab in 2026: Uptime Kuma + Grafana + Alerts (Complete Guide)
ⓘ This article may contain affiliate links (no extra cost to you, it supports our tests). See the disclosure.
⏱️
30-45 min
Est. Setup Time
💾
30 days
Data Retention
📉
Very Low
Resource Usage

👍 What we like

  • Complete self-hosted stack using only Docker containers
  • Combines availability monitoring with deep system metrics
  • Instant Telegram alerts for proactive issue notification
  • Visual dashboards via Grafana for easy data interpretation

👎 What to watch

  • Requires manual configuration of Prometheus scrape targets
  • Initial setup exposes ports directly before reverse proxy config
  • Admin password must be manually changed in compose file
  • Telegram integration requires external account setup
📑 Contents

A running homelab is good. A homelab where you know, to the second, that a service has crashed, the disk is filling up, or RAM is spiking, is a homelab you control. Too many self-hosters discover a service is dead… only when they try to use it. Monitoring is not a luxury reserved for enterprises: with two or three containers, you get complete visibility and alerts that warn you before your users do.

In this guide, we build a complete, 100% self-hosted monitoring stack via Docker: Uptime Kuma for availability monitoring (are services responding?), Prometheus + node_exporter for system metrics (CPU, RAM, disk, network), and Grafana for beautiful dashboards. We finish with Telegram alerts to notify you instantly. By the end, you’ll know at a glance if everything is fine, and you’ll be notified if it isn’t.

Prerequisites

  • A Linux server or homelab with Docker and Docker Compose installed. See the Docker installation in our Caddy reverse proxy + Docker guide.

  • Ideally, a VPS or dedicated machine for monitoring (a small node is sufficient: the stack consumes very little). For hardware/VPS selection, see best VPS for self-hosting.

  • A reverse proxy (Caddy) if you want to expose the interfaces over HTTPS, which is recommended.

  • A Telegram account and app, to receive alerts.

  • 30 to 45 minutes.

If you are unsure about the tools, our comparison Uptime Kuma vs Grafana vs Netdata explains why these building blocks are complementary rather than competitive.

Stack Architecture

Before diving in, let’s understand what each component does:

  • Uptime Kuma: Availability probes (HTTP, TCP, ping, DNS…). Answers the question “is my service responding?”. Simple interface, built-in alerts.

  • node_exporter: A lightweight agent that exposes system metrics from a machine (CPU, RAM, disk, network) in Prometheus format.

  • Prometheus: A time-series database that periodically collects (“scrapes”) metrics from node_exporter.

  • Grafana: Visualization. Connects to Prometheus to display dashboards and trigger alerts based on thresholds.

We deploy everything in a single docker-compose.yml for simplicity.

Step 1: Prepare the directory structure and docker-compose

Create a working directory:


mkdir -p ~/monitoring && cd ~/monitoring

mkdir -p prometheus

Create the composition file:


nano docker-compose.yml

services:

  uptime-kuma:

    image: louislam/uptime-kuma:1

    container_name: uptime-kuma

    restart: unless-stopped

    volumes:

      - uptime-kuma-data:/app/data

    ports:

      - "3001:3001"



  node-exporter:

    image: prom/node-exporter:latest

    container_name: node-exporter

    restart: unless-stopped

    command:

      - '--path.rootfs=/host'

    pid: host

    volumes:

      - '/:/host:ro,rslave'

    ports:

      - "9100:9100"



  prometheus:

    image: prom/prometheus:latest

    container_name: prometheus

    restart: unless-stopped

    volumes:

      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro

      - prometheus-data:/prometheus

    command:

      - '--config.file=/etc/prometheus/prometheus.yml'

      - '--storage.tsdb.retention.time=30d'

    ports:

      - "9090:9090"



  grafana:

    image: grafana/grafana-oss:latest

    container_name: grafana

    restart: unless-stopped

    environment:

      - GF_SECURITY_ADMIN_PASSWORD=ChangeThisPassword

    volumes:

      - grafana-data:/var/lib/grafana

    ports:

      - "3000:3000"

    depends_on:

      - prometheus



volumes:

  uptime-kuma-data:

  prometheus-data:

  grafana-data:

Security: Change GF_SECURITY_ADMIN_PASSWORD to a strong password. The ports are exposed here in plain text for setup; in production, place these services behind an HTTPS reverse proxy and do not publish the ports directly to the Internet (remove the ports: sections once you have routed them through Caddy on a shared Docker network).

Step 2: Configure Prometheus

Prometheus needs to know what to collect. Create its config file:


nano ~/monitoring/prometheus/prometheus.yml

global:

  scrape_interval: 15s

  evaluation_interval: 15s



scrape_configs:

  - job_name: 'prometheus'

    static_configs:

      - targets: ['localhost:9090']



  - job_name: 'node'

    static_configs:

      - targets: ['node-exporter:9100']

Since all containers are on the same Docker network (the default project network for compose), Prometheus reaches node-exporter by its service name. Start the stack:


docker compose up -d

Verify that everything starts:


docker compose ps

All four containers should be running.

Step 3: Verify metric collection

Verify that node_exporter is exposing its metrics:


curl -s http://localhost:9100/metrics | head -5

You will get metric lines in Prometheus format. Then, open Prometheus in your browser at http://SERVER_IP:9090, go to Status > Targets: the node target should be in state UP. If it is DOWN, check the service name and port in prometheus.yml.

Step 4: Configure Uptime Kuma

Open http://SERVER_IP:3001. On first launch, create the admin account (username + strong password).

Then add your first probes (“monitors”):

  1. Click Add New Monitor.

  2. HTTP(s) Type for a website or web service: enter the URL (e.g., https://cloud.example.com), a descriptive name, and the check interval (60s is a good default).

  3. TCP Port Type for a service without a web interface (e.g., a database): specify the host and port.

  4. Ping Type to check if a machine responds on the network.

Uptime Kuma immediately displays an availability history, uptime percentage, and response time. Create a public status page via Status Pages if you want to share the status of your services.

Tip: For a scheduled task (like a restic backup) to report that it executed successfully, create a Push type monitor in Uptime Kuma. Your script calls the provided URL at the end; if the call does not arrive within the allotted time, Uptime Kuma alerts you. Useful for detecting silently failed backups.

Step 5: Configure Grafana

Open http://SERVER_IP:3000 and log in with admin and the password defined in the compose file.

Add Prometheus as a data source

  1. Menu Connections > Data sources > Add data source.

  2. Choose Prometheus.

  3. In Prometheus server URL, enter http://prometheus:9090 (container name resolution on the Docker network).

  4. Click Save & test: you should see “Successfully queried the Prometheus API”.

Import a ready-made dashboard

No need to build everything from scratch: the community offers excellent dashboards. For node_exporter, import the famous Node Exporter Full dashboard (ID 1860):

  1. Menu Dashboards > New > Import.

  2. Enter ID 1860 in the field, click Load.

  3. Select your Prometheus data source, then Import.

You instantly get a complete dashboard: CPU usage, memory, disk space, I/O, network traffic, system load. It is the control panel for your server.

Step 6: Set up Telegram alerts

The point of monitoring is to be notified. We configure Telegram in both tools.

Create a Telegram bot

  1. In Telegram, search for @BotFather, start it, and send /newbot.

  2. Choose a name and username for the bot. BotFather gives you a token (something like 123456789:AAH...).

  3. Start a conversation with your new bot (send it any message).

  4. Retrieve your chat ID: open in a browser https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates and locate the chat.id field in the JSON response.

Alerts in Uptime Kuma

  1. In Uptime Kuma: Settings > Notifications > Setup Notification.

  2. Type Telegram, paste the Bot Token and Chat ID.

  3. Click Test to receive a verification message, then Save.

  4. Edit your monitors and check this notification: you will be alerted on every UP → DOWN transition and upon recovery.

System alerts via Grafana

To be notified when disk usage exceeds 85% or RAM exceeds 90%, create an alert rule in Grafana:

  1. Alerting > Contact points > Add contact point, type Telegram, enter token and chat ID, test.

  2. Alerting > Alert rules > New alert rule. Define a PromQL query, for example for root disk usage:


100 - ((node_filesystem_avail_bytes{mountpoint="/"} * 100) / node_filesystem_size_bytes{mountpoint="/"})
  1. Set the condition “IS ABOVE 85” over a 5-minute window, associate the Telegram contact point, and save.

You will now receive a message as soon as a critical threshold is crossed, before it becomes an incident.

Stack Verification

Run through the checklist:


# All four services are running

docker compose ps



# Prometheus has the node target UP (returns "up")

curl -s 'http://localhost:9090/api/v1/query?query=up{job="node"}' | grep -o '"value":\[[^]]*\]'



# node_exporter responds

curl -sI http://localhost:9100/metrics | head -1

Perform a real test: intentionally stop a service monitored by Uptime Kuma (docker stop <service>), wait for the check interval, and confirm that you receive the Telegram alert, followed by the recovery message after restart.

Best Practices and Security

  • Do not expose ports in plain text. Place Grafana, Prometheus, and Uptime Kuma behind your Caddy reverse proxy over HTTPS. Prometheus, in particular, has no native authentication: it should never be publicly accessible.

  • Back up the volumes. Uptime Kuma configurations, Grafana dashboards, and Prometheus history live in Docker volumes. Include them in your backup strategy (see encrypted backups with restic).

  • Monitor remote machines. Install node_exporter on each machine in your homelab and add them as targets in prometheus.yml. Secure inter-machine scraping via WireGuard VPN rather than in plain text.

  • Define reasonable retention. --storage.tsdb.retention.time=30d prevents Prometheus from filling the disk. Increase if you need long-term history, while monitoring disk space.

  • Useful alerts, not noisy ones. Too many alerts kill alerting. Reserve notifications for actionable events (service down, full disk, expiring certificate) and group the rest into dashboards.

FAQ

Don’t Uptime Kuma and Grafana do the same thing?

No, they are complementary. Uptime Kuma answers “is it responding?” (availability, from the outside) with near-instant setup. Grafana + Prometheus answer “how is it doing internally?” (detailed system metrics, trends, capacity). Using them together provides a complete view. Our comparison Uptime Kuma vs Grafana vs Netdata details the strengths of each.

What load does this stack put on the server?

Modest. node_exporter is negligible, Uptime Kuma takes ~100 MB of RAM, and Prometheus and Grafana consume based on the number of targets and retention, but a few hundred MB are sufficient for a typical homelab. The main disk usage is for Prometheus history, controlled by the retention period. A small VPS or mini-PC is more than enough.

Why not Netdata, which installs in one command?

Netdata is excellent for ultra-detailed real-time diagnostics on a single machine, with trivial installation. But for centralizing multiple machines, retaining long-term history, and customizing dashboards and alerts, the Prometheus + Grafana combination remains more flexible and standard. There is nothing stopping you from running Netdata locally alongside Grafana centrally.

How do I monitor my Docker containers themselves?

Add cAdvisor to the stack: it exposes per-container metrics (CPU, RAM, network, I/O) that Prometheus collects just like node_exporter. Then import a Grafana dashboard dedicated to Docker containers (several are available in the gallery). You can then distinguish which container is consuming what.

Do alerts work if the monitoring server itself goes down?

No, and this is a classic limitation: a system cannot alert on its own failure. The solution is external supervision. Use a third-party service (or a second instance of Uptime Kuma on another machine/VPS) to monitor the availability of your monitoring server. Thus, if the entire stack goes down, you are still notified.

Your homelab is now under surveillance: availability, system metrics, and instant alerts. You will know before anyone else when something is wrong. To follow new monitoring tools, vulnerabilities, and VPS deals, join our Telegram watch bot.

Tags: homelabmonitoringUptime KumaGrafanaPrometheusDockernode_exporterautomation

Related

🛠️ Tutorials

Hosting n8n on a VPS in 2026: Complete Self-Hosted Guide (Docker, HTTPS, Backups)

2026 technical guide to self-hosting n8n on a VPS using Docker Compose, HTTPS, and security best practices. Compare cloud vs on-premise costs to automate workflows without subscriptions.

Read
🛠️ Tutorials

Deploy n8n with Docker and HTTPS in 2026: Complete Tutorial (Postgres, Reverse Proxy, Persistence)

Step-by-step 2026 guide to self-host n8n, the no-code automation platform, using Docker Compose. Features PostgreSQL, workflow persistence, automatic HTTPS via Caddy and Let's Encrypt, credential encryption, backups, and hardening. Ready-to-use configs.

Read
⚖️ Comparisons

Uptime Kuma vs Grafana vs Netdata 2026: Best Self-Hosted Monitoring

Technical 2026 comparison of Uptime Kuma, Grafana, and Netdata. Analyze resource usage, use cases, and architecture to choose the optimal self-hosted monitoring stack for your homelab or professional server.

Read