Uptime Kuma is a self-hosted monitoring tool that provides a clean web dashboard for tracking uptime across HTTP endpoints, TCP ports, DNS records, Docker containers, and more. On RHEL 9, you can run it directly with Node.js and PM2 for process management, or deploy it instantly via Docker. This tutorial walks through both approaches, firewall configuration, and setting up monitors and notification channels so your team receives alerts the moment a service goes down.

Prerequisites

  • RHEL 9 server with a non-root sudo user
  • Node.js 20 or Docker installed (instructions for both covered below)
  • Firewall managed by firewalld
  • Optional: a domain name or reverse proxy (Nginx/Caddy) for HTTPS access

Step 1 — Install Node.js 20 and Uptime Kuma

RHEL 9 ships Node.js 18 by default. Enable the Node.js 20 module stream to get a supported LTS release, then install Uptime Kuma globally via npm.

sudo dnf module reset nodejs -y
sudo dnf module enable nodejs:20 -y
sudo dnf module install -y nodejs:20
node -v          # confirm v20.x
npm -v           # confirm npm is available

sudo npm install -g uptime-kuma

The global install places the uptime-kuma executable in /usr/local/bin/. Uptime Kuma stores its SQLite database and configuration in ~/.config/uptime-kuma by default, or in the current working directory if started from a specific path.

Step 2 — Run Uptime Kuma with PM2

PM2 is a production process manager for Node.js that handles restarts on crashes and survives server reboots.

sudo npm install -g pm2

# Start Uptime Kuma as a named PM2 process
pm2 start uptime-kuma --name uptime-kuma

# Generate and enable the systemd startup hook
pm2 startup
# Run the command printed by pm2 startup (it will look like:
#   sudo env PATH=... pm2 startup systemd -u root --hp /root)
# Then save the PM2 process list:
pm2 save

pm2 status          # confirm uptime-kuma is "online"
pm2 logs uptime-kuma --lines 20   # inspect startup output

Uptime Kuma listens on port 3001 by default. You can override this with the --port flag: pm2 start uptime-kuma --name uptime-kuma -- --port 3001.

Step 3 — Docker Alternative

If Docker is already installed on the server, you can skip the Node.js setup entirely and run the official image instead.

# Pull and run the Uptime Kuma container
docker run -d 
  --name uptime-kuma 
  --restart unless-stopped 
  -p 3001:3001 
  -v uptime-kuma-data:/app/data 
  louislam/uptime-kuma:latest

docker ps        # confirm container is running
docker logs uptime-kuma --tail 20

The named volume uptime-kuma-data persists your monitors, alerts, and status pages across container restarts and upgrades.

Step 4 — Open the Firewall Port

sudo firewall-cmd --permanent --add-port=3001/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-ports    # should include 3001/tcp

If you plan to put Nginx or Caddy in front of Uptime Kuma as a reverse proxy, open port 80/443 instead and keep 3001 restricted to localhost (--zone=internal or a firewalld rich rule).

Step 5 — Configure Monitors in the Web UI

Navigate to http://<server-ip>:3001 and complete the first-run account setup. Then add monitors:

  • HTTP(s): paste the URL, set check interval (default 60 s), choose expected status code (200), and optionally validate keyword presence in the response body.
  • Ping: enter a hostname or IP; Uptime Kuma will ICMP-ping it and record response time.
  • TCP Port: specify host and port to confirm a socket is listening (useful for databases, SMTP).
  • DNS: query a record type (A, MX, TXT) and verify the resolved value matches an expected result.
  • Docker Container: connect to the local Docker socket and monitor container health status.

Step 6 — Set Up Notification Channels and Status Pages

In Settings → Notifications, add one or more alert channels. Common integrations:

  • Telegram: create a bot via @BotFather, obtain a token and chat ID, paste both into Uptime Kuma.
  • Slack: create an incoming webhook in your Slack workspace and paste the URL.
  • Email (SMTP): provide your SMTP host, port, credentials, and recipient addresses.

To publish a public status page, go to Status Pages → New Status Page, give it a slug (e.g., status), add the monitors you want displayed, and save. The page is accessible at http://<server-ip>:3001/status/<slug> with no login required.

Conclusion

You now have Uptime Kuma running on RHEL 9, managed by PM2 (or Docker), with firewall access open on port 3001. Monitors are checking your HTTP endpoints, TCP services, and DNS records at regular intervals, and your notification channels will alert you immediately when anything goes down. The public status page gives customers or stakeholders a live view of service health without exposing the admin interface.

Next steps: How to Use Prometheus Blackbox Exporter for Endpoint Monitoring on RHEL 9, How to Configure SNMP Monitoring on RHEL 9, and How to Build Grafana Dashboards for Linux Server Metrics on RHEL 9.