Self-host guide

How to Self-Host Uptime Kuma on a VPS

Run Uptime Kuma 2 on Ubuntu 24.04 with the project's Docker Compose file, Caddy HTTPS with WebSocket support, data backups and safe updates.

Uptime Kuma is a self-hosted monitoring tool. It checks websites, TCP ports, ping, DNS records and Docker containers on an interval, and alerts you through Telegram, Discord, Slack, email and over 90 other services. This guide installs version 2 by hand on Ubuntu 24.04 with the project's own Docker Compose file, and puts Caddy in front for HTTPS.

Prefer one click? Deploy Uptime Kuma from the VeloxaHost marketplace and skip the manual steps; this guide is for when you want to run every command yourself.

What you need

  • A VeloxaHost server with the Ubuntu 24.04 LTS image. You get root, over SSH or in the browser terminal on the server's page.
  • For HTTPS on a domain: a subdomain such as status.example.com and a dedicated IPv4 address. Caddy gets its certificate over ports 80 and 443, which the shared IPv4 address does not offer; it only gives you a block of forwarded ports. A dedicated IPv4 is a paid add-on (the console shows the current price): choose it as "Network access" on the create page, or take one from the IP addresses page and attach it. If none is free in the region, the request is refused.
  • Local disk for the data folder. The project warns that network file systems such as NFS are not supported, because SQLite needs working file locks.

The project lists no CPU or memory minimum. The default 2 image includes an embedded MariaDB and Chromium; the 2-slim image drops both and is about 300 to 400 MB smaller.

Think about where it runs. A monitor on the same server it watches goes down with that server and cannot alert you. Run Uptime Kuma on its own small server and point it at your other servers and sites.

A Veloxa Nano (1 vCPU, 1 GB RAM, 25 GB disk) at $4 a month, billed at $0.01 an hour and capped at the monthly price, is enough for a typical set of monitors.

Install Uptime Kuma

  1. Install Docker Engine and the Compose plugin from Docker's apt repository, as in Docker's Ubuntu guide. sudo also works as root.

    # Add Docker's official GPG key:
    sudo apt update
    sudo apt install ca-certificates curl
    sudo install -m 0755 -d /etc/apt/keyrings
    sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
    sudo chmod a+r /etc/apt/keyrings/docker.asc
    
    # Add the repository to Apt sources:
    sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
    Types: deb
    URIs: https://download.docker.com/linux/ubuntu
    Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
    Components: stable
    Architectures: $(dpkg --print-architecture)
    Signed-By: /etc/apt/keyrings/docker.asc
    EOF
    
    sudo apt update
    sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
    sudo docker run hello-world
    
  2. Download the project's compose file, as the README does.

    mkdir uptime-kuma
    cd uptime-kuma
    curl -o compose.yaml https://raw.githubusercontent.com/louislam/uptime-kuma/master/compose.yaml
    
  3. Caddy will run on the same server, so publish port 3001 on localhost only. Edit compose.yaml to look like this:

    services:
      uptime-kuma:
        image: louislam/uptime-kuma:2
        restart: unless-stopped
        volumes:
          - ./data:/app/data
        ports:
          # <Host Port>:<Container Port>
          - "127.0.0.1:3001:3001"
    

    Everything Uptime Kuma stores goes into ./data, mounted at /app/data.

  4. Start it and follow the logs until the server reports it is listening.

    sudo docker compose up -d
    sudo docker compose logs -f
    
  5. Make the server answer on its dedicated IPv4. Add the address to the interface (check the name with ip addr) and to the network configuration so it survives a reboot. Then create a DNS A record for status.example.com pointing at it.

    ip addr add 198.51.100.5/32 dev eth0
    
  6. Install Caddy from its apt repository, as in Caddy's install docs. The package runs Caddy as the caddy systemd service.

    sudo apt install --yes debian-keyring debian-archive-keyring apt-transport-https curl
    curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
    curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
    sudo chmod o+r /usr/share/keyrings/caddy-stable-archive-keyring.gpg
    sudo chmod o+r /etc/apt/sources.list.d/caddy-stable.list
    sudo apt update
    sudo apt install caddy
    
  7. Replace /etc/caddy/Caddyfile with this, then reload Caddy.

    status.example.com {
        reverse_proxy 127.0.0.1:3001
    }
    
    sudo systemctl reload caddy
    

    Uptime Kuma runs over WebSocket, so a proxy must pass the Upgrade and Connection headers. Caddy's reverse_proxy handles WebSocket on its own and renews the certificate. Subdirectories are not supported, so use a subdomain.

Without a dedicated IPv4. For private use, skip steps 5 to 7 and open an SSH tunnel through the first port of your block, which forwards to SSH. Then browse to http://localhost:3001.

ssh -p 20000 -L 3001:127.0.0.1:3001 root@203.0.113.10

You can also publish the port as "3001:3001" and forward a port of your block to it, for example http://203.0.113.10:20001. That is plain HTTP unless you add a certificate from a DNS challenge.

First login

Open https://status.example.com. Version 2 first asks which database to use: SQLite, a single file recommended for small deployments; Embedded MariaDB, already set up inside the full image; or an external MariaDB/MySQL server. SQLite is a sound choice for one small server. Next, create your admin account.

Then set up the basics:

  • In Settings, General, set Primary Base URL to your HTTPS address. The Auto Get button fills it in.
  • Add a notification. For email, VeloxaHost blocks outbound TCP port 25, so use your provider's SMTP on port 587 or 465.
  • Add monitors for your other servers and sites.

Secure it

In the console, go to Firewalls, New Firewall, Add Rule. Allow TCP 80 and 443 from 0.0.0.0/0 and TCP 22 only from YOUR.IP/32, then attach the firewall on the server's page. Until one is attached, all traffic is allowed. Ports published by Docker bypass ufw, so rely on the VeloxaHost firewall; the compose file above keeps 3001 on localhost.

In Uptime Kuma:

  • Settings, Security: turn on Two Factor Authentication. Leave Disable Auth alone; it is only for setups with third-party authentication in front.
  • Settings, Reverse Proxy: set Trust Proxy to Yes, since Uptime Kuma is only reachable through Caddy. Logs then show real client IPs.

Back it up

The project says backing up the data directory is the only supported backup method; version 2 removed the old JSON export. The folder holds the database, whether SQLite or embedded MariaDB. Stop the container first so the copy is consistent.

cd uptime-kuma
sudo docker compose stop
sudo tar czf ../uptime-kuma-data.tar.gz data
sudo docker compose up -d

On VeloxaHost, snapshots are instant and free (5 on Starter, 30 on Pay as you go): server page, Snapshots, name, Create. Restoring overwrites the current state. Automatic snapshots run every hour, 6 hours, 12 hours, daily or weekly, kept for 1, 3, 7, 14 or 30 days. The Backups page creates, downloads and restores server backups (as a new server), on a schedule of every 6 hours, 12 hours, daily or weekly, keeping 1 to 10. Download one now and then for an off-site copy.

Update it

Take a snapshot, then pull the new image and recreate the container, as the project's update page describes:

cd uptime-kuma
sudo docker compose pull
sudo docker compose up -d --force-recreate

The 2 tag tracks the latest 2.x release, 2.5.6 when this was checked. To update on your own schedule, pin a release tag such as louislam/uptime-kuma:2.5.6. Do not use latest: it is deprecated and still points to version 1. New Docker images can appear a little after a release.

Coming from version 1? It is a major update with breaking changes. Stop the stack, back up data, switch the tag to 2 and start it. The migration can take hours on a large database; do not interrupt it.

Troubleshooting

The page loads but never connects. Your proxy is not passing WebSocket upgrades. Caddy does this by default; for nginx or Apache, add the Upgrade and Connection headers shown in the project's reverse proxy wiki.

A monitor says DOWN but the service works. Test from inside the container with sudo docker compose exec uptime-kuma bash, then install curl with apt update && apt --yes install curl and try the target. Note that IPv6 is not available in US East yet, so IPv6-only targets cannot be checked from this server.

You forgot the admin password. Run sudo docker compose exec uptime-kuma npm run reset-password and follow the prompt.

Email alerts never arrive. Port 25 is blocked outbound. Switch the SMTP notification to port 587 or 465.

FAQ

What license is Uptime Kuma under?

Uptime Kuma is released under the MIT license. There is no paid edition; all features are in the self-hosted project.

Should Uptime Kuma run on the server it monitors?

It is a weak setup. If that server goes down, so does your monitor, and no alert goes out. Run it on a separate small server and use it to watch your other servers, sites and services.

Should I pick SQLite or MariaDB?

The setup screen recommends SQLite for small-scale deployments. Embedded MariaDB comes with the full image and needs no setup. Either way the data lives in the data folder. Moving SQLite data to MariaDB later is not officially supported.

Which Docker image tag should I use?

Use louislam/uptime-kuma:2, which the project recommends and which tracks the latest 2.x release. Pin a specific release such as 2.5.6 if you want to choose when updates happen, or use 2-slim if you need neither embedded MariaDB nor the Browser Engine monitor.

Which VeloxaHost size fits Uptime Kuma?

A Veloxa Nano (1 vCPU, 1 GB RAM, 25 GB disk) at $4 a month, billed at $0.01 an hour and capped at the monthly price, covers a typical set of monitors. For hundreds of monitors on short intervals, or Browser Engine monitors that use the bundled Chromium, a Veloxa 1 (1 vCPU, 2 GB RAM, 50 GB disk) at $8 a month, billed at $0.02 an hour and capped at the monthly price, gives more headroom.

Commands and settings checked on 2026-10-18 against the official documentation: github.com, docs.docker.com, caddyserver.com. Software changes; if a step no longer matches, the vendor's docs win.

Ready to deploy?

Start a free trial, or compare plans to match your team's scale.