# How to install Uptime Kuma 2 with Docker Compose and HTTPS

> Install Uptime Kuma 2 with Docker Compose behind Caddy, secure the admin account with 2FA, set up monitors, alerts and status pages, then back up and update.

Difficulty: Beginner\
Tested on: Ubuntu 24.04 LTS, Ubuntu 26.04 LTS, Debian 12, Debian 13

Uptime Kuma is a self-hosted monitoring tool with a clean web interface. It checks websites, APIs, TCP ports, DNS records, ping targets and more at a fixed interval, sends alerts through dozens of notification services when something goes down, and can publish public status pages for your users. Version 2 is the current major release.

This guide installs Uptime Kuma 2 with the project's **official Docker Compose file**, publishes the web interface only on `127.0.0.1`, and serves it over HTTPS with Caddy, which passes the WebSocket connection the interface depends on. You then choose a database, create the admin account with two-factor authentication, add your first monitors, notifications and a status page, and learn how to back up, update and troubleshoot the installation.

> **Note**
>
> A monitor cannot report its own outage. Run Uptime Kuma on a different server, ideally in a different location, from the services it watches.

## Prerequisites

- A server running **Ubuntu 24.04 LTS**, **Ubuntu 26.04 LTS**, **Debian 12** or **Debian 13**. The steps work on a HyperDC Linux VPS, VDS or dedicated server with root access.
- A non-root user with `sudo` rights: see [Secure a new Linux server](/guides/secure-a-new-linux-server) and [Set up SSH keys](/guides/ssh-keys).
- Docker Engine with the Compose plugin: [Install Docker on Ubuntu](/guides/install-docker-ubuntu) or [Install Docker on Debian](/guides/install-docker-debian).
- A domain name such as `status.example.com` with an A (and optionally AAAA) record pointing at the server, and Caddy installed as in [Caddy as a reverse proxy](/guides/caddy-reverse-proxy).
- A local disk for the data folder. The project states that network file systems such as NFS are not supported.

| Resource | Minimum (official) | Suggested starting point |
|---|---|---|
| CPU | Not published | 1 vCPU |
| RAM | Not published | 1 GB |
| Disk | Not published | 10 GB, more if you keep long history |

The project does not publish minimum requirements for the Docker image. The right-hand column is a conservative starting point for a few dozen monitors, not a benchmark. The full image includes an embedded MariaDB and Chromium; the `2-slim` tag leaves both out and is a few hundred megabytes smaller.

## Step 1 — Get the official Compose file

Create the app folder and download the Compose file that the project's README recommends:

```bash
sudo mkdir -p /opt/uptime-kuma
sudo chown $USER:$USER /opt/uptime-kuma
cd /opt/uptime-kuma
curl -fsSL -o compose.yaml https://raw.githubusercontent.com/louislam/uptime-kuma/master/compose.yaml
cat compose.yaml
```

The file runs the `louislam/uptime-kuma:2` image, keeps all data in `./data` (mounted at `/app/data`), and publishes port 3001 on every address of the server. Docker-published ports bypass ufw, so change the port line to listen on loopback only. Open the file with `nano compose.yaml` and make it look like this:

```yaml
services:
  uptime-kuma:
    image: louislam/uptime-kuma:2
    restart: unless-stopped
    volumes:
      - ./data:/app/data
    ports:
      - "127.0.0.1:3001:3001"
```

About the image tag: `2` follows the newest 2.x release and is the tag the project recommends. Exact tags such as `2.5.5` pin a version, `2-slim` is the smaller variant, and `latest` is deprecated and still points to version 1.

## Step 2 — Start Uptime Kuma

```bash
docker compose up -d
docker compose ps
docker compose logs --tail 30
curl -I http://127.0.0.1:3001
```

`docker compose ps` shows the container as running, the logs show no errors, and `curl` answers with an HTTP status line (a redirect to the setup page is normal at this point). The interface is not yet reachable from the internet, which is intended.

## Step 3 — Serve Uptime Kuma over HTTPS with Caddy

Add a site block to `/etc/caddy/Caddyfile`. Caddy's `reverse_proxy` upgrades WebSocket connections automatically, so no extra headers are needed:

```caddyfile
status.example.com {
    reverse_proxy 127.0.0.1:3001
}
```

Reload Caddy and allow only SSH and web traffic through the firewall:

```bash
sudo systemctl reload caddy
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
curl -I https://status.example.com
```

The last command returns a response over a valid certificate. If you use Nginx instead ([Nginx with Certbot](/guides/nginx-reverse-proxy-certbot)), add the `Upgrade` and `Connection` headers for WebSockets as shown in the project's reverse proxy wiki page; [Traefik](/guides/traefik-reverse-proxy) handles WebSockets on its own.

## Step 4 — Choose a database and create the admin account

Open `https://status.example.com` straight away; until you finish setup, anyone who finds the address could claim the admin account.

1. The first screen asks which database to use. **SQLite** is described as a simple database file recommended for small-scale deployments, and it is the right choice for most single-server setups. **Embedded MariaDB** runs a MariaDB server inside the same container (full image only). **MariaDB/MySQL** connects to an external database server.
2. Create the admin account with a unique user name and a long password from your password manager.

You land on the empty dashboard. Then harden the account:

- Open **Settings**, then **Security**, and use **Set Up 2FA** under **Two Factor Authentication**. Scan the QR code with an authenticator app and confirm with a code.
- Open **Settings**, then **Reverse Proxy**, and under **HTTP Headers** set **Trust Proxy** to **Yes**. Uptime Kuma then logs the real visitor IP addresses sent by Caddy instead of `127.0.0.1`. Only do this when the app is reachable solely through your proxy, as it is here.

## Step 5 — Add monitors, notifications and a status page

**Notifications first.** Open **Settings**, then **Notifications**, and click **Setup Notification**. Pick a service (email via SMTP, Telegram, Discord, Slack, Microsoft Teams, ntfy, a webhook and many more), fill in its details and use **Test** before saving. Tick **Default enabled** to attach it to new monitors automatically. For email alerts, enter your relay's host name (for example `smtp.example.com`), port `587` with STARTTLS security, your SMTP user and password, and the sender and recipient addresses.

> **Note**
>
> Outbound port 25 is closed by default on HyperDC VPS. For services bought for a term of 3 months or longer, it is opened on request: [open a support ticket](/guides/support-tickets). Until then, send mail through an SMTP relay on port 587.

**Then monitors.** Click **Add New Monitor** and choose a type:

- **HTTP(s)** checks that a URL answers with a success status; **HTTP(s) - Keyword** also looks for a word in the response.
- **TCP Port**, **Ping** and **DNS** check services that do not speak HTTP.
- **Push** waits for your own job (for example a backup script) to call a URL, and alerts when the call does not arrive in time.

Set the **Heartbeat Interval** (60 seconds is a sensible default), a few **Retries** to avoid alerts for one-off blips, and save. HTTPS monitors also warn you before certificates expire when you enable the certificate expiry notification.

> **Warning**
>
> The **Docker Container** monitor type needs the Docker socket mounted into the Uptime Kuma container. Access to that socket is equivalent to root access on the host, so only add it if you really need it.

**Finally a status page.** Open **Status Pages**, click **New Status Page**, enter a name and a slug, and add the monitors you want to show. The page is public at `https://status.example.com/status/your-slug`. It shows only the monitors you select, and you can schedule **Maintenance** windows so planned work does not appear as an outage.

## Back up and restore

Everything lives in the `data` folder: the SQLite database (or the embedded MariaDB files), uploaded logos and settings. Version 2 removed the old JSON backup feature, and the project's migration guide names backing up the data directory as the only supported method. Stop the container so the database files are consistent, archive the folder and the Compose file, and start it again:

```bash
sudo mkdir -p /opt/backups
cd /opt/uptime-kuma
docker compose stop
sudo tar -czf /opt/backups/uptime-kuma-$(date +%F).tar.gz -C /opt/uptime-kuma compose.yaml data
docker compose start
```

Monitoring pauses for the few seconds the backup takes. Schedule it with cron at a quiet time and copy the archives off the server.

To restore, stop the stack, move the current data aside, unpack the archive and start again:

```bash
cd /opt/uptime-kuma
docker compose down
sudo mv data data.old
sudo tar -xzf /opt/backups/uptime-kuma-2026-10-09.tar.gz -C /opt/uptime-kuma
docker compose up -d
```

Delete `data.old` once you have checked that the restored dashboard shows your monitors.

## Update Uptime Kuma

Read the [release notes](https://github.com/louislam/uptime-kuma/releases) first and take a backup as shown above. Then pull the new image and recreate the container, as the project's update guide describes:

```bash
cd /opt/uptime-kuma
docker compose pull
docker compose up -d --force-recreate
docker compose logs -f
```

Some updates migrate the database on first start. The migration from version 1 to version 2 rewrites the heartbeat table and can take minutes or, on slow hardware with a lot of history, hours. Watch the logs (`Ctrl+C` stops following them) and do not stop the container during a migration; if it is interrupted, restore the backup and try again.

## Troubleshooting

### A monitor shows DOWN but the site works in your browser

The check runs from inside the container, so Docker networking, DNS or a firewall on the target can produce a different result. The project's troubleshooting page suggests testing from inside the container:

```bash
docker compose exec uptime-kuma bash
apt update && apt --yes install curl
curl -I https://www.example.com
```

Type `exit` to leave the container shell. Also remember that `localhost` and `127.0.0.1` inside a monitor point at the container itself, not at the host; monitor the public HTTPS address instead.

### You forgot the admin password

Reset it from the command line as the project documents. Open a shell in the container, run the reset script and enter a new password when asked:

```bash
docker compose exec uptime-kuma bash
npm run reset-password
```

### The page loads but stays on a spinner or keeps reconnecting

The browser could not open the WebSocket connection. Caddy handles this automatically; with Nginx, add `proxy_http_version 1.1` and the `Upgrade` and `Connection` headers. Also check that a CDN or firewall in front of the site allows WebSockets.

### SQLite errors such as database is locked or a corrupted database

Usually the data folder sits on a network file system, which the project does not support. Move `data` to a local disk, restore the most recent backup if the database is damaged, and keep one Uptime Kuma container per data folder.

### IPv6 monitors always fail

Docker networks have no IPv6 by default, so the container cannot reach IPv6-only targets. The project's troubleshooting page shows how to add a Compose network with `enable_ipv6: true`, or you can monitor the target's IPv4 address.

## Next steps

- Learn the file format behind this setup in [Docker Compose basics](/guides/docker-compose-basics).
- Put other apps behind HTTPS the same way with [Caddy](/guides/caddy-reverse-proxy).
- Harden the server itself with [Secure a new Linux server](/guides/secure-a-new-linux-server).
- Browse more tools you can run yourself on the [self-hosted apps](/self-hosted-apps) page.
- Read the [Uptime Kuma wiki](https://github.com/louislam/uptime-kuma/wiki) for all monitor types and settings.

## Frequently asked questions

### Should I use the latest tag for Uptime Kuma?

No. The project's Docker tag list marks latest as deprecated and says it still points to version 1. Use the 2 tag, which follows the newest 2.x release, or pin an exact 2.x.y tag.

### Can Uptime Kuma monitor the server it runs on?

It can check services on the same server, but it cannot tell you when that whole server or its network is down, because it goes down too. Run Uptime Kuma on a different server or location from the services you care about most.

### SQLite or MariaDB for Uptime Kuma 2?

The setup screen describes SQLite as a simple database file recommended for small-scale deployments. The full Docker image also offers an embedded MariaDB, and you can connect an external MariaDB or MySQL server. Moving an existing SQLite database to MariaDB later is not supported by the maintainers.

### Can I store the data folder on NFS?

No. The project states that network file systems such as NFS are not supported, because SQLite needs reliable POSIX file locks. Keep /app/data on a local disk or local Docker volume.

### Is there a built-in backup button in version 2?

No. The JSON backup and restore feature was removed in version 2. The migration guide says backing up the data directory is the only supported backup method.

---

Source: <https://hyperdc.com/guides/tutorials/install-uptime-kuma>\
Updated: 2026-10-09
