Learn how to install Uptime Kuma, a self-hosted monitoring tool, with SSL certificates, email notifications, and comprehensive website monitoring capabilities. Set up automated alerts and maintain reliable uptime tracking for your web services.
Prerequisites
- Root or sudo access
- Domain name with DNS configured
- SMTP email account for notifications
What this solves
Uptime Kuma is a self-hosted monitoring solution that tracks website availability, response times, and service health. This tutorial helps you install Uptime Kuma with SSL encryption, configure email alerts for downtime notifications, and set up comprehensive monitoring for your websites and services.
Step-by-step installation
Update system packages
Start by updating your package manager to ensure you get the latest versions of all dependencies.
sudo apt update && sudo apt upgrade -y
Install Node.js and npm
Uptime Kuma requires Node.js 16 or higher. Install the Node.js runtime and package manager from your distribution's repositories.
sudo apt install -y nodejs npm curl git
Verify the Node.js installation meets the minimum version requirement:
node --version
npm --version
Create dedicated user for Uptime Kuma
Create a system user to run Uptime Kuma securely. This follows security best practices by avoiding running services as root.
sudo useradd --system --home /opt/uptime-kuma --create-home --shell /bin/bash uptimekuma
sudo usermod -aG uptimekuma uptimekuma
Install Uptime Kuma
Switch to the uptime-kuma user and install Uptime Kuma using npm. This installs the application in the user's home directory.
sudo -u uptimekuma bash
cd /opt/uptime-kuma
npm create uptime-kuma@latest
The installation will create a new directory with the Uptime Kuma application. Navigate to it and install dependencies:
cd uptime-kuma
npm ci --production
exit
Create systemd service
Create a systemd service file to manage Uptime Kuma as a system service. This enables automatic startup and proper process management.
[Unit]
Description=Uptime Kuma
After=network.target
Wants=network.target
[Service]
Type=simple
User=uptimekuma
Group=uptimekuma
WorkingDirectory=/opt/uptime-kuma/uptime-kuma
ExecStart=/usr/bin/node server/server.js
Restart=always
RestartSec=5
Environment=NODE_ENV=production
Environment=UPTIME_KUMA_PORT=3001
Environment=UPTIME_KUMA_HOST=127.0.0.1
Security settings
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/uptime-kuma
[Install]
WantedBy=multi-user.target
Set proper file permissions
Set the correct ownership and permissions for the Uptime Kuma directory. The uptimekuma user needs full access to manage the application files and database.
sudo chown -R uptimekuma:uptimekuma /opt/uptime-kuma
sudo chmod -R 755 /opt/uptime-kuma
sudo chmod 644 /etc/systemd/system/uptime-kuma.service
Enable and start Uptime Kuma service
Reload systemd configuration and start the Uptime Kuma service. Enable it to start automatically on boot.
sudo systemctl daemon-reload
sudo systemctl enable --now uptime-kuma
sudo systemctl status uptime-kuma
Install and configure Nginx reverse proxy
Install Nginx to act as a reverse proxy and handle SSL certificates. This provides better security and performance compared to exposing Node.js directly.
sudo apt install -y nginx certbot python3-certbot-nginx
Configure Nginx virtual host
Create an Nginx configuration file for your Uptime Kuma domain. Replace example.com with your actual domain name.
server {
listen 80;
server_name uptime.example.com;
access_log /var/log/nginx/uptime-kuma-access.log;
error_log /var/log/nginx/uptime-kuma-error.log;
location / {
proxy_pass http://127.0.0.1:3001;
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;
proxy_cache_bypass $http_upgrade;
# WebSocket support
proxy_set_header Sec-WebSocket-Extensions $http_sec_websocket_extensions;
proxy_set_header Sec-WebSocket-Key $http_sec_websocket_key;
proxy_set_header Sec-WebSocket-Version $http_sec_websocket_version;
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# Security headers
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
}
Enable the site and test the Nginx configuration:
sudo ln -s /etc/nginx/sites-available/uptime-kuma /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Obtain SSL certificate
Use Certbot to obtain a free SSL certificate from Let's Encrypt. This automatically configures Nginx with SSL settings and redirects HTTP to HTTPS.
sudo certbot --nginx -d uptime.example.com
Follow the prompts to enter your email address and agree to the terms of service. Certbot will automatically configure SSL and set up automatic renewal.
Configure firewall rules
Open the necessary ports in your firewall to allow web traffic. This allows users to access your Uptime Kuma installation securely.
sudo ufw allow 'Nginx Full'
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status
Configure Uptime Kuma
Access web interface and initial setup
Open your web browser and navigate to your Uptime Kuma domain. You'll be presented with the initial setup wizard to create your administrator account.
https://uptime.example.com
Create an administrator account with a strong password. This will be your main account for managing all monitoring configurations.
Configure email notifications
Navigate to Settings > Notifications in the Uptime Kuma interface. Click "Add New notification" and select "Email (SMTP)" as the notification type.
Enter your SMTP configuration details:
- SMTP Host: Your mail server hostname (e.g., smtp.gmail.com)
- SMTP Port: 587 for TLS or 465 for SSL
- Security: Choose TLS or SSL based on your provider
- Username: Your email username
- Password: Your email password or app-specific password
- From Email: The sender email address
- To Email: Where to send alerts
Test the notification to ensure email delivery works correctly before proceeding to monitor setup.
Add website monitors
Click "Add New Monitor" to create your first website monitor. Configure the following settings:
- Monitor Type: HTTP(s) for websites
- Friendly Name: Descriptive name for your monitor
- URL: The website URL to monitor
- Heartbeat Interval: How often to check (recommended: 60 seconds)
- Max Retries: Number of retry attempts (recommended: 3)
- Max Redirects: Maximum allowed redirects (recommended: 10)
- Accepted Status Codes: HTTP codes considered successful (default: 200-299)
Assign the email notification you configured earlier to this monitor. Enable "Advanced" settings to configure custom headers, authentication, or SSL certificate monitoring.
Configure SSL certificate monitoring
For SSL certificate monitoring, enable the "Ignore TLS/SSL error" option initially, then configure specific SSL monitoring:
- Set "Certificate Expiry" notification to warn before certificates expire
- Configure certificate expiry threshold (recommended: 7 days)
- Enable certificate domain verification
This ensures you receive alerts before SSL certificates expire, preventing service disruptions.
Configure backup automation
Create backup script
Create a backup script to regularly save your Uptime Kuma configuration and database. This protects against data loss and enables easy migration.
#!/bin/bash
Uptime Kuma backup script
BACKUP_DIR="/opt/uptime-kuma/backups"
DATE=$(date +"%Y%m%d_%H%M%S")
BACKUP_FILE="uptime-kuma-backup_${DATE}.tar.gz"
Create backup directory
mkdir -p "$BACKUP_DIR"
Stop Uptime Kuma service
sudo systemctl stop uptime-kuma
Create backup
tar -czf "${BACKUP_DIR}/${BACKUP_FILE}" -C /opt/uptime-kuma uptime-kuma/data
Start Uptime Kuma service
sudo systemctl start uptime-kuma
Remove backups older than 30 days
find "$BACKUP_DIR" -name "uptime-kuma-backup_*.tar.gz" -mtime +30 -delete
echo "Backup completed: ${BACKUP_DIR}/${BACKUP_FILE}"
Make the backup script executable and set proper ownership:
sudo chown uptimekuma:uptimekuma /opt/uptime-kuma/backup.sh
sudo chmod 755 /opt/uptime-kuma/backup.sh
Schedule automated backups
Create a systemd timer to run backups automatically. This provides more reliable scheduling than traditional cron jobs.
[Unit]
Description=Uptime Kuma Backup
Requires=uptime-kuma.service
[Service]
Type=oneshot
User=uptimekuma
Group=uptimekuma
ExecStart=/opt/uptime-kuma/backup.sh
[Unit]
Description=Run Uptime Kuma backup daily
Requires=uptime-kuma-backup.service
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
Enable and start the backup timer:
sudo systemctl daemon-reload
sudo systemctl enable --now uptime-kuma-backup.timer
sudo systemctl list-timers | grep uptime-kuma
Verify your setup
Confirm that all components are working correctly with these verification commands:
# Check Uptime Kuma service status
sudo systemctl status uptime-kuma
Verify Nginx configuration
sudo nginx -t
sudo systemctl status nginx
Check SSL certificate
sudo certbot certificates
Test local connectivity
curl -I http://127.0.0.1:3001
Verify backup timer
sudo systemctl status uptime-kuma-backup.timer
Check application logs
sudo journalctl -u uptime-kuma -n 20
Test external connectivity
curl -I https://uptime.example.com
Access your Uptime Kuma web interface and verify that monitors are running and email notifications are working by triggering a test notification.
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| Service won't start | Node.js version too old | Install Node.js 16+ or use NodeSource repository |
| 502 Bad Gateway error | Uptime Kuma not running | sudo systemctl restart uptime-kuma |
| WebSocket connection failed | Nginx proxy configuration | Verify proxy_set_header Upgrade and Connection settings |
| Email notifications not working | SMTP configuration or firewall | Test SMTP settings and check port 587/465 access |
| SSL certificate renewal fails | Nginx configuration conflicts | Run sudo certbot renew --dry-run to test renewal |
| Permission denied errors | Incorrect file ownership | sudo chown -R uptimekuma:uptimekuma /opt/uptime-kuma |
| High memory usage | Too many monitors or short intervals | Increase heartbeat intervals or upgrade server resources |
| Database corruption | Unexpected shutdowns | Restore from backup and enable proper shutdown procedures |
Next steps
- Set up Grafana with Prometheus for comprehensive system monitoring
- Configure automated system backups with rsync and systemd timers
- Install Nagios Core for advanced network monitoring
- Configure advanced Uptime Kuma monitoring with API integrations
- Set up multi-location monitoring with distributed Uptime Kuma instances
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Default values
DOMAIN=""
EMAIL=""
PORT="3001"
# Usage function
usage() {
echo "Usage: $0 -d <domain> -e <email> [-p <port>]"
echo " -d: Domain name for Uptime Kuma (e.g., uptime.example.com)"
echo " -e: Email for SSL certificate"
echo " -p: Port for Uptime Kuma (default: 3001)"
exit 1
}
# Parse arguments
while getopts "d:e:p:h" opt; do
case $opt in
d) DOMAIN="$OPTARG" ;;
e) EMAIL="$OPTARG" ;;
p) PORT="$OPTARG" ;;
h) usage ;;
*) usage ;;
esac
done
if [[ -z "$DOMAIN" || -z "$EMAIL" ]]; then
usage
fi
# Cleanup function
cleanup() {
echo -e "${RED}[ERROR] Installation failed. Cleaning up...${NC}"
systemctl stop uptime-kuma 2>/dev/null || true
systemctl disable uptime-kuma 2>/dev/null || true
rm -f /etc/systemd/system/uptime-kuma.service
userdel -r uptimekuma 2>/dev/null || true
exit 1
}
trap cleanup ERR
# Check if running as root
if [[ $EUID -ne 0 ]]; then
echo -e "${RED}This script must be run as root${NC}"
exit 1
fi
# Detect distribution
if [[ ! -f /etc/os-release ]]; then
echo -e "${RED}Cannot detect Linux distribution${NC}"
exit 1
fi
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_UPDATE="apt update && apt upgrade -y"
PKG_INSTALL="apt install -y"
NGINX_CONF_DIR="/etc/nginx/sites-available"
NGINX_ENABLED_DIR="/etc/nginx/sites-enabled"
FIREWALL_CMD="ufw"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_UPDATE="dnf update -y"
PKG_INSTALL="dnf install -y"
NGINX_CONF_DIR="/etc/nginx/conf.d"
NGINX_ENABLED_DIR=""
FIREWALL_CMD="firewall-cmd"
;;
amzn)
PKG_MGR="yum"
PKG_UPDATE="yum update -y"
PKG_INSTALL="yum install -y"
NGINX_CONF_DIR="/etc/nginx/conf.d"
NGINX_ENABLED_DIR=""
FIREWALL_CMD="firewall-cmd"
;;
*)
echo -e "${RED}Unsupported distribution: $ID${NC}"
exit 1
;;
esac
echo -e "${BLUE}Installing Uptime Kuma on $PRETTY_NAME${NC}"
# Step 1: Update system
echo -e "${YELLOW}[1/10] Updating system packages...${NC}"
$PKG_UPDATE
# Step 2: Install dependencies
echo -e "${YELLOW}[2/10] Installing Node.js, npm, and dependencies...${NC}"
if [[ "$ID" == "ubuntu" || "$ID" == "debian" ]]; then
$PKG_INSTALL nodejs npm curl git nginx certbot python3-certbot-nginx
else
$PKG_INSTALL nodejs npm curl git nginx certbot python3-certbot-nginx
if ! systemctl is-enabled firewalld >/dev/null 2>&1; then
systemctl enable --now firewalld
fi
fi
# Verify Node.js version
NODE_VERSION=$(node --version | sed 's/v//' | cut -d. -f1)
if [[ $NODE_VERSION -lt 16 ]]; then
echo -e "${RED}Node.js version 16 or higher is required. Current version: $(node --version)${NC}"
exit 1
fi
echo -e "${GREEN}Node.js version: $(node --version)${NC}"
# Step 3: Create system user
echo -e "${YELLOW}[3/10] Creating dedicated user for Uptime Kuma...${NC}"
if ! id uptimekuma >/dev/null 2>&1; then
useradd --system --home /opt/uptime-kuma --create-home --shell /bin/bash uptimekuma
fi
# Step 4: Install Uptime Kuma
echo -e "${YELLOW}[4/10] Installing Uptime Kuma...${NC}"
sudo -u uptimekuma bash << 'EOF'
cd /opt/uptime-kuma
if [[ ! -d "uptime-kuma" ]]; then
npm create uptime-kuma@latest
cd uptime-kuma
npm ci --production
fi
EOF
# Step 5: Create systemd service
echo -e "${YELLOW}[5/10] Creating systemd service...${NC}"
cat > /etc/systemd/system/uptime-kuma.service << EOF
[Unit]
Description=Uptime Kuma
After=network.target
Wants=network.target
[Service]
Type=simple
User=uptimekuma
Group=uptimekuma
WorkingDirectory=/opt/uptime-kuma/uptime-kuma
ExecStart=/usr/bin/node server/server.js
Restart=always
RestartSec=5
Environment=NODE_ENV=production
Environment=UPTIME_KUMA_PORT=$PORT
Environment=UPTIME_KUMA_HOST=127.0.0.1
# Security settings
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/uptime-kuma
[Install]
WantedBy=multi-user.target
EOF
# Step 6: Set permissions
echo -e "${YELLOW}[6/10] Setting proper file permissions...${NC}"
chown -R uptimekuma:uptimekuma /opt/uptime-kuma
find /opt/uptime-kuma -type d -exec chmod 755 {} \;
find /opt/uptime-kuma -type f -exec chmod 644 {} \;
chmod 644 /etc/systemd/system/uptime-kuma.service
# Step 7: Enable and start service
echo -e "${YELLOW}[7/10] Starting Uptime Kuma service...${NC}"
systemctl daemon-reload
systemctl enable --now uptime-kuma
# Wait for service to start
sleep 5
# Step 8: Configure Nginx
echo -e "${YELLOW}[8/10] Configuring Nginx reverse proxy...${NC}"
if [[ "$ID" == "ubuntu" || "$ID" == "debian" ]]; then
NGINX_CONF="$NGINX_CONF_DIR/$DOMAIN"
else
NGINX_CONF="$NGINX_CONF_DIR/$DOMAIN.conf"
fi
cat > "$NGINX_CONF" << EOF
server {
listen 80;
server_name $DOMAIN;
access_log /var/log/nginx/uptime-kuma-access.log;
error_log /var/log/nginx/uptime-kuma-error.log;
location / {
proxy_pass http://127.0.0.1:$PORT;
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;
proxy_cache_bypass \$http_upgrade;
}
}
EOF
if [[ -n "$NGINX_ENABLED_DIR" ]]; then
ln -sf "$NGINX_CONF" "$NGINX_ENABLED_DIR/"
fi
systemctl enable --now nginx
nginx -t
systemctl reload nginx
# Step 9: Configure firewall
echo -e "${YELLOW}[9/10] Configuring firewall...${NC}"
if [[ "$FIREWALL_CMD" == "ufw" ]]; then
ufw --force enable
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
else
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --permanent --add-service=ssh
firewall-cmd --reload
fi
# Step 10: Setup SSL certificate
echo -e "${YELLOW}[10/10] Setting up SSL certificate...${NC}"
certbot --nginx -d "$DOMAIN" --email "$EMAIL" --agree-tos --non-interactive --redirect
# Verification
echo -e "${YELLOW}Verifying installation...${NC}"
if systemctl is-active --quiet uptime-kuma; then
echo -e "${GREEN}✓ Uptime Kuma service is running${NC}"
else
echo -e "${RED}✗ Uptime Kuma service is not running${NC}"
systemctl status uptime-kuma
fi
if systemctl is-active --quiet nginx; then
echo -e "${GREEN}✓ Nginx service is running${NC}"
else
echo -e "${RED}✗ Nginx service is not running${NC}"
systemctl status nginx
fi
if curl -s -o /dev/null -w "%{http_code}" "http://127.0.0.1:$PORT" | grep -q "200\|302"; then
echo -e "${GREEN}✓ Uptime Kuma is responding on port $PORT${NC}"
else
echo -e "${RED}✗ Uptime Kuma is not responding on port $PORT${NC}"
fi
echo
echo -e "${GREEN}=== Installation Complete ===${NC}"
echo -e "Uptime Kuma is now installed and configured with SSL"
echo -e "Domain: ${BLUE}https://$DOMAIN${NC}"
echo -e "Local access: ${BLUE}http://127.0.0.1:$PORT${NC}"
echo
echo -e "${YELLOW}Next steps:${NC}"
echo "1. Visit https://$DOMAIN to complete the initial setup"
echo "2. Create your admin account"
echo "3. Configure email notifications in settings"
echo "4. Add your first monitors"
echo
echo -e "${YELLOW}Useful commands:${NC}"
echo "- Check status: systemctl status uptime-kuma"
echo "- View logs: journalctl -u uptime-kuma -f"
echo "- Restart service: systemctl restart uptime-kuma"
Review the script before running. Execute with: bash install.sh