Running Uptime Kuma in a Proxmox LXC for Simple Home Lab Monitoring

As Realm Labs grew, I already had Prometheus and Grafana giving me detailed metrics about the infrastructure.

CPU load.

Memory.

Storage.

Network interfaces.

Service performance.

That was useful, but it answered a very specific question:

How is the system performing?

What I also wanted was something simpler.

Is it actually up?

That’s where Uptime Kuma fitted in.

Rather than adding it to another Docker stack, I decided to run it in a lightweight Proxmox LXC so it had its own small place in the lab and could monitor everything else independently.

Why Uptime Kuma?

Prometheus and Grafana are excellent for metrics.

But sometimes I don’t need a graph.

I just want to know whether:

Home Assistant is reachable
Portainer is responding
Synology is online
Node-RED is up
MQTT is listening
A website is available
A server responds to ping

Uptime Kuma is perfect for that.

Its job is essentially:

Check service
    |
    v
Is it alive?
    |
    +--> Yes
    |
    +--> No

Simple.

And sometimes simple is exactly what you want.

The Existing Monitoring Setup

By this point, Realm Labs already had a more detailed monitoring stack.

Conceptually:

Devices
   |
   v
Prometheus
   |
   v
Grafana

That gave me dashboards and historical metrics.

Uptime Kuma added another layer:

Devices / Services
        |
        +--> Prometheus / Grafana
        |       Detailed metrics
        |
        +--> Uptime Kuma
                Availability

The two systems solve different problems.

Why I Didn’t Just Run It in Docker

I could easily have deployed Uptime Kuma in Docker.

In fact, that’s probably the most common way to run it.

But I liked the idea of keeping the monitoring system slightly separated from the services it was monitoring.

If the Docker host itself had a problem, I still wanted the monitoring service to remain available if possible.

So I used Proxmox.

Why an LXC Was a Good Fit

Uptime Kuma doesn’t need much.

A full virtual machine would have been overkill.

A small LXC container provides:

  • Its own IP address
  • Very little resource usage
  • Simple backups
  • Easy startup and shutdown
  • Isolation from other applications
  • Fast deployment

The architecture became:

Proxmox
   |
   v
Uptime Kuma LXC
   |
   +--> Home Assistant
   +--> Synology
   +--> Portainer
   +--> Node-RED
   +--> MQTT
   +--> Websites

That was exactly what I wanted.

Creating the LXC

Inside Proxmox, I created a new Debian-based LXC.

The exact resource allocation doesn’t need to be huge.

Something along the lines of:

CPU: 1-2 cores
RAM: 512 MB - 1 GB
Disk: 8 GB

is more than enough for a small home lab.

I also gave it a fixed IP address so I always knew where the monitoring dashboard lived.

For example:

192.168.68.x

The exact address doesn’t matter as much as keeping it consistent.

Update the Container

After creating the LXC:

apt update
apt upgrade -y

Then install the basic tools needed.

For example:

apt install curl git -y

Installing Node.js

Uptime Kuma runs on Node.js.

The important part is using a supported Node.js release rather than whatever ancient version happens to be in the default repository.

After installing Node.js, confirm:

node -v

and:

npm -v

If both return sensible versions, you’re ready to install Kuma.

Installing Uptime Kuma

I created a suitable application directory and cloned the project.

For example:

cd /opt
git clone https://github.com/louislam/uptime-kuma.git
cd uptime-kuma

Then install the dependencies:

npm run setup

Once complete, Uptime Kuma can be started with:

node server/server.js

By default, the interface is normally available on port:

3001

So from another machine:

http://<uptime-kuma-ip>:3001

should open the setup page.

Making It Start Automatically

Running it manually is fine for testing.

But I wanted the service to survive reboots.

A systemd service is a clean way to do that.

For example:

[Unit]
Description=Uptime Kuma
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/opt/uptime-kuma
ExecStart=/usr/bin/node /opt/uptime-kuma/server/server.js
Restart=always

[Install]
WantedBy=multi-user.target

Save that as:

/etc/systemd/system/uptime-kuma.service

Then:

systemctl daemon-reload
systemctl enable uptime-kuma
systemctl start uptime-kuma

Check:

systemctl status uptime-kuma

At that point the monitoring system starts automatically with the LXC.

Adding the First Monitor

Once logged into the dashboard, the next step was adding actual services.

The simplest monitor is a ping check.

For example:

Synology
192.168.68.20

Uptime Kuma periodically checks whether the host responds.

That gives a very simple:

UP

or:

DOWN

status.

Monitoring Web Services

For services with a web interface, HTTP checks are more useful.

For example:

Home Assistant
http://192.168.68.x:8123

or:

Portainer
https://192.168.68.x:9443

or:

Node-RED
http://192.168.68.x:1880

This doesn’t just prove the host is alive.

It proves the actual service is responding.

That’s a much better test.

Why Ping Alone Isn’t Enough

A server can answer ping while an application is completely broken.

For example:

Server responds to ICMP
        |
        v
Machine is online

But:

Home Assistant service crashed

So for important services, I prefer checking the service itself.

That gives:

Host availability
+
Application availability

rather than assuming one means the other.

Monitoring My Public Realm Labs Site

Uptime Kuma is also useful for checking public services.

For example:

https://realmlabs.uk

That means I can detect whether:

  • The website is reachable
  • Cloudflare routing is working
  • WordPress is responding
  • HTTPS is functioning

This is particularly useful because the monitoring request travels through the same public route as a normal visitor.

Monitoring Cloudflare-Tunnelled Services

Some Realm Labs services are published through Cloudflare Tunnel.

That creates two possible checks.

Internal check

http://192.168.68.x:port

External check

https://service.realmlabs.uk

This gives useful diagnostic information.

If the internal check works but the public check fails:

Application healthy
Cloudflare/public path broken

If both fail:

Application itself may be down

That distinction is extremely useful.

Monitoring MQTT

MQTT doesn’t provide a normal HTTP page.

Uptime Kuma can still monitor TCP ports.

For Mosquitto:

Port: 1883

That checks whether something is listening.

It doesn’t prove the entire MQTT workflow is healthy, but it does tell me whether the broker is reachable.

The same approach works for other services.

TCP Monitoring

Useful examples include:

SSH
Port 22
MQTT
Port 1883
HTTPS
Port 443
RDP
Port 3389

This makes Uptime Kuma useful beyond websites.

Monitoring Proxmox

For Proxmox itself, I can monitor the management interface.

For example:

https://192.168.68.x:8006

That tells me whether the Proxmox UI is alive.

I can then separately monitor important guests.

The hierarchy becomes:

Proxmox Host
    |
    +-- Pi-hole
    +-- Uptime Kuma
    +-- Other VMs / LXCs

If several guests go offline at the same time, the host becomes an obvious suspect.

Monitoring Synology

The Synology is a particularly important system because so many Realm Labs services depend on it.

I can monitor:

Ping

and perhaps:

DSM HTTPS

and selected services.

That makes it easier to distinguish:

NAS offline

from:

One NAS service down

Grouping Monitors

Once you have more than a handful of checks, organisation matters.

I found it useful to group systems by function.

For example:

Core Infrastructure

with:

  • Router
  • Synology
  • Proxmox
  • DNS

Then:

Home Automation

with:

  • Home Assistant
  • Node-RED
  • MQTT

Then:

Public Services

with:

  • realmlabs.uk
  • Portainer hostname
  • Leaderboard
  • Other published services

This makes the dashboard much easier to read.

Status Pages

One of Uptime Kuma’s nicest features is the ability to create a status page.

That can show selected monitors in a clean read-only view.

For a home lab, that might seem excessive.

But it’s actually useful as a quick dashboard.

Something like:

Realm Labs Status

Core Network      Operational
Home Assistant    Operational
MQTT              Operational
Website           Operational
Synology          Operational

It gives you an immediate health overview.

Notifications

Monitoring isn’t very useful if you have to constantly stare at the dashboard.

Uptime Kuma supports notifications through multiple services.

The exact integration depends on what you use, but the important idea is:

Monitor detects failure
        |
        v
Notification sent

That means I can find out about a failed service before I happen to notice it manually.

Avoid Alert Fatigue

One thing I learned quickly is not to monitor everything too aggressively.

If every tiny transient timeout creates an alert, you stop paying attention.

For example, rather than checking every few seconds, it can be better to use sensible intervals and retries.

The goal is:

Tell me when something is actually broken.

Not:

Tell me every time a Wi-Fi device misses one packet.

Use Retries

Retries are especially useful for services that may occasionally respond slowly.

Instead of:

One failed check
=
DOWN

use something closer to:

Several consecutive failures
=
DOWN

That makes the monitoring much more useful.

Heartbeat Monitors

Uptime Kuma can also work the other way around.

Instead of Kuma polling a service, a script can periodically contact Kuma.

This is useful for jobs such as:

  • Backups
  • Cron jobs
  • Scheduled scripts
  • Maintenance tasks

For example:

Backup runs
    |
    v
Calls heartbeat URL

If Kuma stops receiving the heartbeat, the job may have failed.

This is very different from simply checking whether a server is online.

Monitoring Backups

This gave me another idea for Realm Labs.

Rather than only asking:

Is Synology online?

I can also ask:

Did the backup job actually run?

That is a much more meaningful form of monitoring.

A server being healthy doesn’t mean its backups are healthy.

Grafana vs Uptime Kuma

I don’t see Uptime Kuma as replacing Grafana.

They answer different questions.

Grafana:

What is happening?
How much CPU?
How much memory?
How much bandwidth?
What happened over time?

Uptime Kuma:

Is it up?
How long has it been up?
When did it fail?
Did it recover?

Together, they’re much stronger.

Example Monitoring Stack

The Realm Labs monitoring architecture can therefore look like:

                    Realm Labs Systems
                            |
             +--------------+--------------+
             |                             |
             v                             v
       Prometheus                      Uptime Kuma
             |                             |
             v                             v
          Grafana                    Availability
             |
             v
      Detailed Metrics

One gives depth.

The other gives clarity.

Why Running Kuma Separately Helps

Putting Uptime Kuma in its own LXC gives it a degree of independence.

For example, if Docker on the Synology breaks:

Synology Docker
      X

Uptime Kuma can still tell me that the services disappeared.

If Uptime Kuma itself were hosted inside the same failing Docker environment, I’d lose the monitor at the same time as the monitored service.

That doesn’t make the LXC immune to everything.

But it avoids one obvious shared failure point.

Backing Up the LXC

One of the advantages of Proxmox is that the whole LXC can be backed up.

So rather than manually rebuilding Uptime Kuma if something goes wrong, I can use Proxmox’s normal backup process.

That gives me:

Uptime Kuma
+
Configuration
+
Monitor history
+
Settings

in one manageable guest.

Don’t Monitor by Hostname Until DNS Is Proven

This is a small troubleshooting lesson.

If Uptime Kuma checks:

homeassistant.order.realm

and DNS fails, Kuma will report the service down.

But the application may actually be fine.

For critical infrastructure, it can be useful to monitor both:

IP-based reachability

and:

DNS-based service URL

That helps identify whether:

Service failed

or:

DNS failed

The First Dashboard

Once the initial monitors were configured, I finally had a simple overview of Realm Labs.

Instead of checking individual apps:

Open Home Assistant
Open Synology
Open Portainer
Open Proxmox
Open website

I could open one page.

And immediately see:

Everything green

or:

Something needs attention

That’s surprisingly satisfying.

A Sensible Starting List

If you’re setting up Uptime Kuma in a home lab, I would start small.

Monitor:

  1. Router
  2. DNS server
  3. NAS
  4. Hypervisor
  5. Home Assistant
  6. MQTT
  7. Important Docker host
  8. Public website

Once those are reliable, add more.

There is no prize for having hundreds of monitors.

The dashboard should remain useful.

Useful Monitor Types

The monitor type depends on the service.

Ping

Good for:

Router
Switch
NAS
Server

HTTP/HTTPS

Good for:

Home Assistant
Portainer
Websites
Proxmox
Node-RED

TCP Port

Good for:

MQTT
SSH
RDP
Databases

Heartbeat

Good for:

Backups
Cron jobs
Scheduled scripts

The best check is the one that most closely represents what you actually care about.

The Realm Labs Takeaway

Grafana tells me whether a system is busy.

Uptime Kuma tells me whether it’s alive.

That’s why I ended up keeping both.

The final model became:

Prometheus + Grafana
        |
        v
Performance and history

Uptime Kuma
        |
        v
Availability and alerts

Running Kuma in a small Proxmox LXC also keeps the monitoring platform separate from many of the services it watches.

It’s lightweight.

It’s easy to understand.

And when I open the dashboard and see a wall of green status indicators, I know the important parts of Realm Labs are at least responding.

Sometimes that’s all the monitoring you need.