Copy linkThemeUnmute sounds
Blog

Uptime Kuma Setup Guide

A comprehensive, streamlined guide to deploying Uptime Kuma behind an Apache Reverse Proxy on a RHEL/Rocky Linux system with ModSecurity enabled.

By Joshua Sarmiento//4 min read/Monitoring

Prerequisites

  • OS: Rocky Linux / RHEL 8 or 9
  • Node.js: 20.4 or newer — this guide installs the Node.js 22 module, since Node.js 20 reached end-of-life in April 2026
  • Access: Root or sudo privileges
  • Network: Static IP address or domain name (e.g., 192.168.1.100 or monitor.yourdomain.com)

Note

Upstream ships Uptime Kuma as louislam/uptime-kuma:2, and the 2.x line requires Node.js ≥ 20.4. Everything below is the supported non-Docker path, which runs the same code as the container image. If you are upgrading an existing 1.x install rather than starting fresh, back up data/ first — 2.x migrates the database on first boot and the upgrade is not reversible.


1. Install & Run Uptime Kuma

We will clone Uptime Kuma and run it as a service using Node.js and PM2 (or natively via systemd).

Install Node.js & Clone Repository

# Update system packages
sudo dnf update -y

# Enable and install the current Node.js LTS module & Git
sudo dnf module enable nodejs:22 -y
sudo dnf install nodejs git -y

# Confirm the runtime Uptime Kuma requires (>= 20.4)
node -v

# Clone Uptime Kuma to /opt
cd /opt
sudo git clone https://github.com/louislam/uptime-kuma.git
cd uptime-kuma

# Install dependencies and set up Uptime Kuma
sudo npm run setup

Note

Uptime Kuma keeps its data in data/ as an SQLite database, which needs POSIX file locks. Keep that directory on a local filesystem — an NFS mount or a networked share is a common cause of silent database corruption. On 2.3.2 and later the single-connection default (UPTIME_KUMA_SQLITE_SINGLE_CONNECTION) exists for exactly this reason.

# Install PM2 globally, with log rotation so logs can't fill the disk
sudo npm install pm2 -g
sudo pm2 install pm2-logrotate

# Start Uptime Kuma service
sudo pm2 start server/server.js --name uptime-kuma

# Persist the process list and enable PM2 on boot
sudo pm2 save
sudo pm2 startup
# (Run the command printed by the line above, then reload with `pm2 save`)

Option B: Run using Systemd Service

Create the service file at /etc/systemd/system/uptime-kuma.service:

[Unit]
Description=Uptime Kuma - Self-hosted monitoring tool
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/opt/uptime-kuma
ExecStart=/usr/bin/node /opt/uptime-kuma/server/server.js
Restart=on-failure
Environment=NODE_ENV=production PORT=3001 HOST=127.0.0.1

[Install]
WantedBy=multi-user.target

Enable and start the systemd service:

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

Tip

HOST=127.0.0.1 keeps Uptime Kuma reachable only through Apache, so port 3001 is never exposed directly. The equivalent for PM2 and for local runs is UPTIME_KUMA_HOST=127.0.0.1 in a .env file in the project root, or the --host=127.0.0.1 server argument.


2. Configure System Security

SELinux and Firewalld block internal reverse proxy traffic and external web access by default.

Configure SELinux

Allow Apache (httpd) to connect to backend network services (Uptime Kuma running on port 3001):

sudo setsebool -P httpd_can_network_connect 1

Configure Firewall

Open HTTP (80) and HTTPS (443) ports:

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

3. Install & Configure Apache Reverse Proxy

Install Apache and configure it to proxy traffic to Uptime Kuma, including WebSocket upgrades and ModSecurity rule bypasses.

Install Apache

sudo dnf install httpd -y
sudo systemctl enable httpd --now

# Uptime Kuma is WebSocket-based, so confirm the tunnel module is present
sudo httpd -M | grep -E 'proxy_http|proxy_wstunnel'

Configure Reverse Proxy VirtualHost

Create a new configuration file /etc/httpd/conf.d/uptime-kuma.conf:

<VirtualHost _default_:80>
    ServerName your_domain_or_ip

    ProxyPreserveHost On
    ProxyRequests Off

    <Proxy *>
        Require all granted
    </Proxy>

    # 1. Handle Socket.io long-polling & bypass strict ModSecurity rules
    <Location /socket.io>
        <IfModule mod_security2.c>
            SecRuleEngine Off
            SecRuleRemoveById 920350
            SecRuleRemoveById 920420
        </IfModule>

        Require all granted
        ProxyPass http://127.0.0.1:3001/socket.io
        ProxyPassReverse http://127.0.0.1:3001/socket.io
    </Location>

    # 2. Upgrade HTTP polling connections to persistent WebSocket channel
    RewriteEngine On
    RewriteCond %{HTTP:Upgrade} =websocket [NC]
    RewriteCond %{HTTP:Connection} upgrade [NC]
    RewriteRule ^/socket.io/(.*) ws://127.0.0.1:3001/socket.io/$1 [P,L]

    # 3. Proxy routing for regular frontend assets
    ProxyPass / http://127.0.0.1:3001/
    ProxyPassReverse / http://127.0.0.1:3001/

    # Log configuration
    ErrorLog /var/log/httpd/uptime-kuma-error.log
    CustomLog /var/log/httpd/uptime-kuma-access.log combined
</VirtualHost>

Warning

Unlike most web apps, Uptime Kuma cannot work through a proxy that drops WebSocket upgrades — the dashboard loads but every monitor stays disconnected. Both the Upgrade/Connection conditions above and a loaded mod_proxy_wstunnel are required.


4. Initialize Services & Browser Setup

Validate Apache Configuration

sudo httpd -t
# Output should show: Syntax OK

Start Apache Service

sudo systemctl restart httpd

Clear Browser Storage (Fix 403 Forbidden Loop)

If you previously accessed the IP and encountered a 403 Forbidden error, the browser may cache old socket session tokens:

  1. Open your browser to http://<YOUR_SERVER_IP>
  2. Press F12 to open Developer Tools.
  3. Go to the Application (Chrome/Edge/Brave) or Storage (Firefox) tab.
  4. Select Clear Site Data (or clear Cookies, Local Storage, and Session Storage for the server's IP).
  5. Perform a hard refresh: Ctrl + F5 (Windows/Linux) or Cmd + Shift + R (Mac).

Create your administrator credentials on the Uptime Kuma dashboard setup screen.


Need Help with Your Infrastructure?

If you're looking to implement a similar monitoring setup, configure secure reverse proxies, or need a robust DevOps solution, feel free to reach out!

Contact Me:

Tools in this guide

Each tool links to where it sits in my full stack.