How to Install Uptime Kuma on Proxmox LXC — Full Guide 2026
homelab

How to Install Uptime Kuma on Proxmox LXC — Full Guide 2026

Ricardo Gil
September 7, 2026
15 min read
#proxmox #lxc #uptime-kuma #homelab #monitoring

What Is Uptime Kuma and Why I Run It in My Homelab

When I started building out my self-hosted stack on my Beelink EQ12 running Proxmox VE, I had a problem I didn't realize I had: I only knew something was down when I tried to use it. My Jellyfin instance would silently die after a Proxmox host restart and I wouldn't notice for hours. Vaultwarden would occasionally go unresponsive after a memory spike and I'd only find out when I reached for a password and got a timeout. I needed a monitoring layer that would tell me immediately when any of my services went offline — and Uptime Kuma turned out to be exactly the right tool for the job.

Uptime Kuma is a self-hosted, open-source uptime monitoring tool built with Node.js and Vue.js. Think of it as a self-hosted Uptime Robot: it periodically checks your services via HTTP, HTTPS, TCP port, ping, DNS, and other methods, and immediately alerts you through a notification channel of your choice when something goes down. It also tracks response times over time and lets you publish a public-facing status page showing the health of your services. The web UI is clean, fast, and genuinely pleasant to use — which matters when you're checking it daily.

I've been running Uptime Kuma in a dedicated Proxmox LXC container for about nine months now. In that time it has saved me on multiple occasions — catching a Forgejo container that failed to start after a storage migration, alerting me to a Traefik misconfiguration that left my reverse proxy unreachable, and even catching a network switch issue before I would have noticed anything was wrong. This guide covers the exact setup I use: LXC creation, Node.js install, systemd service configuration, Telegram notifications, and optional Traefik integration for HTTPS access.

Hardware Setup and Resource Requirements

Before getting into the steps, here's the hardware context. I run my entire homelab on a Beelink EQ12 Mini PC (~$189) with Proxmox VE installed bare metal. It's a compact, nearly silent machine drawing about 10–15W under typical homelab load, and it handles my full LXC container stack without breaking a sweat. I've upgraded it with Crucial 32GB DDR4 RAM (~$59) and a WD Black 2TB NVMe SSD (~$129), which gives me more than enough headroom to run 20+ containers simultaneously.

Uptime Kuma is one of the lightest services in my entire stack. The dedicated LXC container I give it runs on 1 CPU core and 512MB of RAM — it consistently uses around 120–150MB of memory in practice and barely registers on the CPU utilization graph. Even if you're running on a more modest setup, Uptime Kuma will fit comfortably alongside your other services. The SQLite database it uses for storing historical uptime data stays small too: after nine months of monitoring 23 services at 60-second intervals, my database file is only around 45MB.

For networking, I use a TP-Link 2.5G USB Ethernet Adapter (~$29) on my secondary development machine for fast local transfers, but the Beelink EQ12 has a built-in 2.5G NIC which handles all traffic for the Proxmox host. Uptime Kuma's network footprint is minimal since it's just sending small HTTP HEAD requests or TCP connection attempts every 60 seconds — bandwidth is not a concern at all.

Prerequisites

To follow this guide, you'll need a running Proxmox VE 8.x installation with at least one LXC template downloaded. I use Debian 12 Bookworm for most of my containers because it's stable, well-supported, and the base image is small. You'll also need basic comfort with the Proxmox shell — we'll run a handful of commands but nothing complex.

Optional but recommended: have Traefik set up as your reverse proxy before starting. My Traefik on Proxmox LXC guide walks through that setup in full. If you don't have Traefik yet, you can still follow this entire guide and access Uptime Kuma via its direct IP and port — you can add the reverse proxy layer later. Also, if you're new to LXC containers in general, my complete Proxmox LXC self-hosting guide is worth reading first to get familiar with the workflow.

Here's the full prerequisites list:

  • Proxmox VE 8.0 or later running on bare metal or a VM
  • Debian 12 Bookworm LXC template downloaded in Proxmox
  • Access to the Proxmox web UI or SSH access to the Proxmox host
  • A static IP reservation for your new container (recommended) or DHCP
  • Optional: Traefik running for HTTPS reverse proxy access
  • Optional: A Telegram account for instant push notifications

Step 1 — Create the Proxmox LXC Container

Log into your Proxmox web UI and click "Create CT" in the top-right corner of the node view. Here are the exact settings I use for my Uptime Kuma container — these are conservative enough to work on any mini PC or server, including a basic Beelink setup:

  • CT ID: 104 (use the next available ID in your setup)
  • Hostname: uptime-kuma
  • Password: A strong root password — write it down
  • Template: Debian 12 Bookworm (debian-12-standard)
  • Disk: 8GB on local-lvm (plenty; the SQLite DB stays small)
  • CPU cores: 1
  • Memory: 512MB RAM, 512MB swap
  • Network: eth0 on vmbr0, static IP (e.g. 192.168.1.104/24)
  • Gateway: Your router IP (e.g. 192.168.1.1)
  • DNS: Leave as default or point to your local Pi-hole or AdGuard Home

Leave "Unprivileged container" checked unless you plan to use ping monitors — I'll explain that caveat in the troubleshooting section. Leave "Nesting" unchecked. Click Finish to create the container, then Start it from the Proxmox UI. Open the console and log in as root.

First thing I always do on a fresh Debian LXC is update the system:

bash
apt update && apt upgrade -y
apt install -y curl wget gnupg2 ca-certificates git net-tools iputils-ping

That iputils-ping package is critical for Uptime Kuma — without it, ping-type monitors will silently fail. I include it in every container I build now out of habit.

Step 2 — Install Node.js 20 LTS

Uptime Kuma requires Node.js. The version bundled with Debian's package repositories is outdated — I always use the NodeSource repository to get a current LTS release. Here's the exact sequence I run:

bash
# Add the NodeSource repository for Node.js 20 LTS
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -

# Install Node.js (npm is bundled)
apt install -y nodejs

# Confirm the versions
node --version   # Should show v20.x.x
npm --version    # Should show 10.x.x

If you see Node.js v20 and npm v10, you're in good shape. The NodeSource install is clean and doesn't conflict with anything else on the system. I've used this same approach on all my Node.js-based LXC containers — n8n, Uptime Kuma, and others — without any issues over the past year.

Step 3 — Install Uptime Kuma

With Node.js in place, installing Uptime Kuma itself is a single npm command. I install it into /opt/uptime-kuma to keep things organized:

bash
mkdir -p /opt/uptime-kuma
cd /opt/uptime-kuma
npm install uptime-kuma

This downloads Uptime Kuma and all its dependencies. Depending on your internet connection it typically takes 2–4 minutes. Once it finishes, do a quick sanity check to confirm the server starts correctly:

bash
node node_modules/uptime-kuma/server/server.js

You should see log output indicating the server started on port 3001. If you see any errors about missing modules, run npm install again inside the node_modules/uptime-kuma directory. Hit Ctrl+C to stop it once you've confirmed it starts — we'll manage it as a systemd service next.

Alternatively, if you want the absolute latest version or want to contribute to the project, you can clone from GitHub:

bash
git clone https://github.com/louislam/uptime-kuma.git /opt/uptime-kuma
cd /opt/uptime-kuma
npm run setup

I personally use the npm install approach for production homelab services because updates are explicit and intentional — I don't want a git pull accidentally introducing breaking changes.

Step 4 — Configure Uptime Kuma as a Systemd Service

Running the server manually in a terminal session is fine for testing, but for a real homelab setup you want Uptime Kuma to start automatically on boot and restart if it crashes. Systemd handles both perfectly. Here's the exact service unit file I use:

bash
cat > /etc/systemd/system/uptime-kuma.service << 'EOF'
[Unit]
Description=Uptime Kuma Self-Hosted Monitor
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/opt/uptime-kuma/node_modules/uptime-kuma
ExecStart=/usr/bin/node server/server.js
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal
SyslogIdentifier=uptime-kuma
Environment=NODE_ENV=production

[Install]
WantedBy=multi-user.target
EOF

Enable and start the service:

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

The status output should show Active: active (running). If it shows failed, check the logs with journalctl -u uptime-kuma -n 50 — the error messages are usually clear about what went wrong. In my experience the most common issue is the WorkingDirectory path being slightly off, so double-check that the path matches where npm installed the package on your system.

Once the service is running, also make sure your LXC container itself is set to autostart in Proxmox. In the web UI, go to the container → Options → Start at boot → Yes. I've been bitten by this omission before: the container works perfectly until a Proxmox host reboot, and then nothing comes back up because the containers aren't configured to autostart.

Step 5 — First Login and Adding Monitors

Open your browser and navigate to http://YOUR_CONTAINER_IP:3001. The first visit will prompt you to create an admin account. Set a strong password — this interface controls your entire monitoring setup, and if you later expose it through a reverse proxy, a weak password is a real risk.

Once logged in, click "Add New Monitor" to start tracking your first service. The monitor type options are comprehensive: HTTP(s), TCP Port, Ping, DNS, Docker Container, and more. Here's how I configure monitors for the most common homelab services:

For an HTTP service (Jellyfin, Vaultwarden, Immich, etc.):

  • Monitor Type: HTTP(s)
  • Friendly Name: Jellyfin
  • URL: http://192.168.1.100:8096 (internal IP and port)
  • Heartbeat Interval: 60 seconds
  • Retries before unhealthy: 3
  • HTTP Method: GET or HEAD (HEAD is lighter on your server)

For a TCP-only service (database, mail server, etc.):

  • Monitor Type: TCP Port
  • Host: 192.168.1.105
  • Port: 5432
  • Heartbeat Interval: 60 seconds

I set retries to 3 on all my monitors after getting false-positive alerts early on. A single failed check doesn't necessarily mean the service is down — it could be a momentary network blip or a slow response during a backup. Three consecutive failures are a much more reliable signal that something genuinely needs attention. After nine months of running with this setting, my false-positive rate dropped to near zero.

Step 6 — Set Up Telegram Notifications

Uptime Kuma supports over 90 notification channels including Telegram, Discord, Slack, email, PagerDuty, ntfy, and many more. I use Telegram because I already have it on my phone and a Telegram bot is free and takes about three minutes to set up. Here's the exact process:

First, create a bot via Telegram's BotFather. Open Telegram, search for @BotFather, start a chat, and send the command /newbot. Follow the prompts — give it a name and a username. BotFather will respond with your bot token, which looks like 7234567890:ABCdefGhIJKlmNoPQRsTUVwxyZ. Save that token.

Next, you need your Telegram chat ID. Send any message to your new bot (just type "hello"), then fetch the updates via this URL in your browser (replace with your actual token):

bash
https://api.telegram.org/bot{YOUR_BOT_TOKEN}/getUpdates

Look for the chat.id field in the JSON response — it's a numeric value like 123456789. That's your chat ID. Now in Uptime Kuma, go to Settings → Notifications → Add Notification. Select Telegram, enter your bot token and chat ID, and click Test Notification. You should get an instant message from your bot on your phone. I also set up a second notification channel pointing to a Telegram group I share with my family, so they know when the Jellyfin server goes down before they message me wondering why it's not working.

Step 7 — Expose Uptime Kuma with Traefik for HTTPS

Accessing Uptime Kuma over plain HTTP on an internal IP is fine for local-only use, but if you want secure HTTPS access — especially useful if you access your homelab remotely over Headscale or Tailscale — adding it to Traefik takes about two minutes. In your Traefik dynamic configuration directory, create a new router and service definition:

yaml
# /etc/traefik/dynamic/uptime-kuma.yml
http:
  routers:
    uptime-kuma:
      rule: "Host(`status.yourdomain.com`)"
      service: uptime-kuma
      entryPoints:
        - websecure
      tls:
        certResolver: letsencrypt

  services:
    uptime-kuma:
      loadBalancer:
        servers:
          - url: "http://192.168.1.104:3001"

Replace 192.168.1.104 with your container's IP and status.yourdomain.com with whatever subdomain you want to use. Traefik picks up the new configuration file without a restart and begins handling HTTPS for that subdomain automatically, including Let's Encrypt certificate provisioning. I have my Uptime Kuma accessible at an internal subdomain only reachable over my Headscale VPN, so it's never exposed to the public internet — but I can check it from my phone from anywhere in the world.

If you want the status page publicly accessible (so others can check if your services are up), you can expose that subdomain publicly while keeping the admin UI private. Uptime Kuma lets you set a different URL for the status page vs. the admin interface — a useful separation if you run services for others.

Step 8 — Build Your Status Page

One of the most satisfying features in Uptime Kuma is the public status page generator. Settings → Status Pages → New Status Page gives you a clean customizable page showing the uptime history, current status, and response time graphs for whichever monitors you choose to include.

I maintain a private status page for my own reference that shows all 23 of my monitored services at a glance — uptime percentages for the last 24 hours, 7 days, and 30 days, plus a live response time graph. When I do maintenance on a service, I can flip it to "under maintenance" mode in Uptime Kuma rather than letting it show as "down," which avoids unnecessary alerts. This is the kind of small quality-of-life feature that makes Uptime Kuma feel genuinely production-ready rather than a toy monitoring tool.

For anyone who runs services for family members — a Jellyfin server for movie night, a shared Immich instance for photo backup — a public status page is a great way to proactively communicate service status without having to respond to "is the server down?" messages every time you do maintenance.

Troubleshooting Common Issues

Here are the issues I ran into during initial setup and over the following months of operation, plus how I resolved each one:

Ping monitors not working in an unprivileged container. This is a known limitation: unprivileged LXC containers don't have the Linux capability needed to send raw ICMP packets. You have two options: switch the container to privileged mode (simpler, what I ultimately did), or add the cap_net_raw capability explicitly to the container config in /etc/pve/lxc/104.conf by adding lxc.cap.drop: with the cap_net_raw entry removed. I opted for privileged since this container only runs Uptime Kuma and the risk profile is low.

Uptime Kuma not restarting after Proxmox host reboot. Two separate things need to be configured: the LXC container must be set to autostart (Options → Start at boot in Proxmox UI), and inside the container, the systemd service must be enabled (systemctl enable uptime-kuma). Missing either one means manual intervention after every host restart. I double-check both settings any time I create a new container.

Gradual memory increase over several weeks. Node.js applications sometimes develop memory drift over long uptimes. I added a weekly restart via cron to keep memory usage stable without disrupting monitoring for long. The monitoring gap during a restart is about 10 seconds, which is acceptable in a homelab context:

bash
# Run: crontab -e
# Restart every Sunday at 3:00 AM local time
0 3 * * 0 /bin/systemctl restart uptime-kuma

Excessive false-positive alerts for a service behind Cloudflare. Some of my external services go through Cloudflare, which can occasionally return non-200 status codes for bot-like HTTP HEAD requests. I switched those monitors to use GET instead of HEAD, and set the "Accepted Status Codes" field to include 200–299 plus any Cloudflare-specific codes my service legitimately returns. That eliminated the noise.

My Full Monitor List After Nine Months

To give you a sense of what a mature Uptime Kuma setup looks like, here's what I currently monitor in my homelab. This list grew organically as I added services over time — each new self-hosted app gets a monitor added on the same day I deploy it, which has become a natural part of my deployment checklist:

  • Jellyfin — HTTP, port 8096 (media server)
  • Vaultwarden — HTTP via Traefik HTTPS (password manager)
  • Immich — HTTP, port 2283 (photo backup)
  • Navidrome — HTTP, port 4533 (music server)
  • Forgejo — HTTP via Traefik HTTPS (git server)
  • MinIO Console — HTTP, port 9001 (S3 object storage)
  • N8N — HTTP, port 5678 (workflow automation)
  • Traefik Dashboard — HTTP, port 8080 (reverse proxy health)
  • Proxmox Host — Ping (hardware availability)
  • Headscale — TCP port 8080 (VPN coordination)
  • PostgreSQL — TCP port 5432 (shared database)
  • Paperless-ngx — HTTP, port 8000 (document management)
  • Komodo — HTTP, port 9120 (container manager)
  • External site (gilricardo.com) — HTTP(s) (public presence)

That last entry — monitoring my own public website from inside my homelab — is a useful trick. It gives me a different vantage point than external monitors: if my site shows as down from inside but up from an external check service, that's a DNS or routing issue. If it's down from both, the site is genuinely unreachable. The dual-perspective monitoring has helped me diagnose two separate issues in the past year that would have been much harder to troubleshoot with only one monitoring point.

One more recommendation: set up an external monitor to watch your Uptime Kuma instance itself. Use the free tier of Uptime Robot, Freshping, or any other external service to ping your Uptime Kuma URL. If Uptime Kuma goes down, it obviously can't alert you to its own failure — an external watchdog closes that gap. I set this up on day one and it caught a crash caused by a full disk (I forgot to set a disk size limit on a different LXC container that was consuming space) within about two minutes.

Need help setting up your homelab?

I help individuals and small teams design and deploy Proxmox-based self-hosted infrastructure — from hardware selection to running services in production. Let's talk →

Ricardo Gil is a full-stack developer (.NET/Angular) with 6+ years of experience. He runs a personal homelab on a Beelink mini PC with Proxmox VE, self-hosting everything from Jellyfin to local LLMs with Ollama. More about Ricardo →
📬Weekly Newsletter

Get the best home lab & AI content

No spam. One email per week. Unsubscribe anytime.

Share this article