Set up multi-location monitoring with distributed Uptime Kuma instances

Intermediate 45 min Apr 14, 2026 223 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Deploy multiple Uptime Kuma instances across different geographic locations to monitor your services from various vantage points. This setup provides comprehensive monitoring coverage, reduces false positives, and enables regional performance analysis with centralized alerting.

Prerequisites

  • Multiple servers in different geographic locations
  • Basic knowledge of NGINX reverse proxy
  • Understanding of systemd service management

What this solves

A single monitoring instance can miss regional outages or give false positives due to local network issues. Multi-location monitoring with distributed Uptime Kuma instances provides comprehensive coverage by checking your services from multiple geographic locations. This approach helps identify regional connectivity problems, reduces monitoring blind spots, and provides better insights into global service performance.

Step-by-step installation

Update system packages

Start by updating your package manager on all monitoring nodes to ensure you get the latest versions.

sudo apt update && sudo apt upgrade -y
sudo dnf update -y

Install Node.js and npm

Uptime Kuma requires Node.js version 14 or higher. Install the latest LTS version along with npm package manager.

curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt install -y nodejs
curl -fsSL https://rpm.nodesource.com/setup_lts.x | sudo bash -
sudo dnf install -y nodejs npm

Create dedicated user for Uptime Kuma

Create a system user to run Uptime Kuma services securely without root privileges.

sudo adduser --system --group --home /opt/uptime-kuma uptime-kuma
sudo mkdir -p /opt/uptime-kuma
sudo chown uptime-kuma:uptime-kuma /opt/uptime-kuma

Install Uptime Kuma on primary instance

Install the primary Uptime Kuma instance which will serve as your main monitoring dashboard and central coordination point.

sudo -u uptime-kuma bash
cd /opt/uptime-kuma
npm install pm2 -g
git clone https://github.com/louislam/uptime-kuma.git .
npm run setup

Configure primary instance systemd service

Create a systemd service file to manage the primary Uptime Kuma instance with automatic startup and proper logging.

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

[Service]
Type=simple
User=uptime-kuma
Group=uptime-kuma
WorkingDirectory=/opt/uptime-kuma
ExecStart=/usr/bin/node server/server.js
Restart=on-failure
RestartSec=5
Environment=NODE_ENV=production
Environment=PORT=3001
Environment=HOST=0.0.0.0
SyslogIdentifier=uptime-kuma-primary

[Install]
WantedBy=multi-user.target

Install Uptime Kuma on monitoring nodes

Repeat the installation process on each monitoring node. Use different ports and working directories for each node.

sudo -u uptime-kuma bash
cd /opt/uptime-kuma
mkdir -p node-{us-east,eu-west,asia-pacific}
cd node-us-east
git clone https://github.com/louislam/uptime-kuma.git .
npm run setup

Configure monitoring node systemd services

Create separate systemd services for each monitoring node with unique ports and identifiers.

[Unit]
Description=Uptime Kuma US East Node
After=network.target

[Service]
Type=simple
User=uptime-kuma
Group=uptime-kuma
WorkingDirectory=/opt/uptime-kuma/node-us-east
ExecStart=/usr/bin/node server/server.js
Restart=on-failure
RestartSec=5
Environment=NODE_ENV=production
Environment=PORT=3002
Environment=HOST=0.0.0.0
SyslogIdentifier=uptime-kuma-us-east

[Install]
WantedBy=multi-user.target

Configure EU West monitoring node

Create the European monitoring node service with its dedicated port and configuration.

[Unit]
Description=Uptime Kuma EU West Node
After=network.target

[Service]
Type=simple
User=uptime-kuma
Group=uptime-kuma
WorkingDirectory=/opt/uptime-kuma/node-eu-west
ExecStart=/usr/bin/node server/server.js
Restart=on-failure
RestartSec=5
Environment=NODE_ENV=production
Environment=PORT=3003
Environment=HOST=0.0.0.0
SyslogIdentifier=uptime-kuma-eu-west

[Install]
WantedBy=multi-user.target

Setup reverse proxy for centralized access

Configure NGINX to provide centralized access to all monitoring nodes through a single domain with path-based routing.

sudo apt install -y nginx
sudo dnf install -y nginx

Configure NGINX reverse proxy

Set up NGINX configuration to route requests to different Uptime Kuma instances based on the URL path. For enhanced security, consider implementing ModSecurity web application firewall protection.

upstream uptime-kuma-primary {
    server 127.0.0.1:3001;
}

upstream uptime-kuma-us-east {
    server 127.0.0.1:3002;
}

upstream uptime-kuma-eu-west {
    server 127.0.0.1:3003;
}

server {
    listen 80;
    server_name monitoring.example.com;
    
    location / {
        proxy_pass http://uptime-kuma-primary;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
    
    location /us-east/ {
        rewrite ^/us-east(.*)$ $1 break;
        proxy_pass http://uptime-kuma-us-east;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
    
    location /eu-west/ {
        rewrite ^/eu-west(.*)$ $1 break;
        proxy_pass http://uptime-kuma-eu-west;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Enable NGINX configuration

Activate the NGINX configuration and restart the service to apply changes.

sudo ln -s /etc/nginx/sites-available/uptime-kuma-multi /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx

Start all Uptime Kuma services

Enable and start all Uptime Kuma instances to begin monitoring operations.

sudo systemctl daemon-reload
sudo systemctl enable --now uptime-kuma-primary
sudo systemctl enable --now uptime-kuma-us-east
sudo systemctl enable --now uptime-kuma-eu-west

Configure firewall rules

Open necessary ports for NGINX while keeping individual Uptime Kuma ports restricted to localhost.

sudo ufw allow 'Nginx Full'
sudo ufw enable
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

Setup inter-node communication script

Create a synchronization script to share monitoring configurations between nodes and enable centralized management.

#!/bin/bash

Configuration

PRIMARY_URL="http://localhost:3001" NODES=("http://localhost:3002" "http://localhost:3003") API_KEY="your-api-key-here"

Export monitors from primary

export_monitors() { curl -s "${PRIMARY_URL}/api/monitors" \ -H "Authorization: Bearer ${API_KEY}" > /tmp/monitors.json }

Import monitors to nodes

import_to_nodes() { for node in "${NODES[@]}"; do echo "Syncing to ${node}" curl -X POST "${node}/api/monitors/import" \ -H "Authorization: Bearer ${API_KEY}" \ -H "Content-Type: application/json" \ -d @/tmp/monitors.json done } export_monitors import_to_nodes echo "Monitor synchronization completed"

Make sync script executable and schedule

Set proper permissions for the synchronization script and schedule it to run automatically.

sudo chmod +x /opt/uptime-kuma/sync-monitors.sh
sudo chown uptime-kuma:uptime-kuma /opt/uptime-kuma/sync-monitors.sh

Add to crontab for uptime-kuma user

sudo -u uptime-kuma crontab -e

Add this line to run synchronization every 10 minutes:

/10    * /opt/uptime-kuma/sync-monitors.sh >/dev/null 2>&1

Configure centralized alerting webhook

Set up a webhook endpoint to aggregate alerts from all monitoring nodes and prevent duplicate notifications.

const express = require('express');
const app = express();
const port = 3100;

app.use(express.json());

// Store recent alerts to prevent duplicates
const recentAlerts = new Map();
const DUPLICATE_WINDOW = 300000; // 5 minutes

app.post('/webhook/:location', (req, res) => {
    const location = req.params.location;
    const alert = req.body;
    const alertKey = ${alert.monitorName}-${alert.status};
    const now = Date.now();
    
    // Check for recent duplicate
    if (recentAlerts.has(alertKey)) {
        const lastAlert = recentAlerts.get(alertKey);
        if (now - lastAlert.timestamp < DUPLICATE_WINDOW) {
            console.log(Duplicate alert suppressed for ${alertKey});
            return res.status(200).send('Duplicate suppressed');
        }
    }
    
    // Store alert
    recentAlerts.set(alertKey, { timestamp: now, location });
    
    // Forward to your notification system
    console.log(Alert from ${location}: ${alert.monitorName} is ${alert.status});
    
    // Here you would integrate with Slack, Discord, email, etc.
    
    res.status(200).send('Alert processed');
});

app.listen(port, () => {
    console.log(Alert aggregator listening on port ${port});
});

Configure monitoring checks

Set up initial admin accounts

Access each Uptime Kuma instance through your browser and set up admin accounts. Use strong, unique passwords for each instance.

# Primary instance
echo "Access primary: http://monitoring.example.com"

US East node

echo "Access US East: http://monitoring.example.com/us-east"

EU West node

echo "Access EU West: http://monitoring.example.com/eu-west"

Create monitoring checks on each node

Configure identical monitoring checks on each node to monitor the same services from different locations. This provides comprehensive coverage and helps identify regional issues.

Note: Configure the same monitors on all nodes to compare results across locations. Different response times or status from different locations can indicate regional connectivity issues.

Configure notification channels

Set up notification channels that include location information to distinguish alerts from different monitoring nodes. For more advanced monitoring integration, consider implementing Prometheus federation for metrics aggregation.

Verify your setup

Check that all services are running and accessible through the reverse proxy.

# Check service status
sudo systemctl status uptime-kuma-primary
sudo systemctl status uptime-kuma-us-east
sudo systemctl status uptime-kuma-eu-west
sudo systemctl status nginx

Check listening ports

ss -tlnp | grep -E ':(3001|3002|3003|80)'

Test connectivity

curl -I http://localhost:3001 curl -I http://localhost:3002 curl -I http://localhost:3003

Check logs for errors

sudo journalctl -u uptime-kuma-primary -n 20 sudo journalctl -u uptime-kuma-us-east -n 20 sudo journalctl -u uptime-kuma-eu-west -n 20

Common issues

SymptomCauseFix
Service fails to startPort already in useCheck with ss -tlnp | grep :PORT and change port in systemd service
Cannot access through NGINXProxy configuration errorCheck NGINX error logs: sudo tail -f /var/log/nginx/error.log
WebSocket connection failedMissing Upgrade headersEnsure proxy_set_header Upgrade and Connection are configured in NGINX
High memory usageToo many concurrent monitorsReduce check frequency or distribute monitors across more nodes
Database permission errorsIncorrect ownershipsudo chown -R uptime-kuma:uptime-kuma /opt/uptime-kuma
Alerts not aggregatingWebhook endpoint misconfiguredCheck alert-aggregator logs: node /opt/uptime-kuma/alert-aggregator.js
Never use chmod 777. It gives every user on the system full access to your files. Instead, fix ownership with chown and use minimal permissions like 755 for directories and 644 for files.

Next steps

Automated install script

Run this to automate the entire setup

Need help?

Don't want to manage this yourself?

We handle managed devops services for businesses that depend on uptime. From initial setup to ongoing operations.