---
title: "Self-host Uptime Kuma"
description: "Run Uptime Kuma on exe.dev. Watch your sites, get outage alerts, and share a status page, with a private dashboard and nightly backups."
url: https://exe-staging.dev/deploy/uptime-kuma
category: "Monitoring"
updated: 2026-10-14
---

# Self-host Uptime Kuma

A little lookout for your websites. Green bars encouraged.

- **Software:** Uptime Kuma (https://uptime.kuma.pet)
- **Source:** https://github.com/louislam/uptime-kuma
- **License:** MIT
- **Time:** 10 minutes
- **Example VM name:** `my-uptime-kuma` (yours will differ; on the VM, `hostname` prints it)
- **Machine-readable:** https://exe-staging.dev/deploy/uptime-kuma/manifest.json

## What you get

- Uptime Kuma 2, ready for your first monitor.
- A private dashboard and a separate status-page preview.
- Nightly backups, with monitoring set to restart after a reboot.

Running on the VM:

- **Uptime Kuma 2**: Docker Compose, with SQLite, port 8000, data in `~/uptime-kuma/data`
- **Status page proxy**: nginx; status pages only, no dashboard, port 8080
- **Nightly backup**: A systemd timer; keeps two weeks of copies, data in `~/uptime-kuma/backups`

How it is reached:

- https://my-uptime-kuma.exe.xyz:8000/ (private): Your dashboard, whether or not you publish a status page
- https://my-uptime-kuma.exe.xyz:8080/ (private): Status page preview
- https://my-uptime-kuma.exe.xyz/ (public): Your status page, only after you choose to publish it

## Deploy with Shelley

Open https://exe-staging.dev/new?prompt=Set%20up%20Uptime%20Kuma%20on%20this%20VM%20by%20following%20the%20exe.dev%20recipe%20at%20https%3A%2F%2Fexe-staging.dev%2Fdeploy%2Fuptime-kuma.md%20from%20top%20to%20bottom.%0A%0AThe%20recipe%27s%20example%20VM%20name%20is%20my-uptime-kuma.%20This%20VM%27s%20name%20is%20the%20output%20of%20%60hostname%60%3A%20use%20it%20wherever%20the%20recipe%20writes%20my-uptime-kuma.%20Skip%20the%20step%20that%20creates%20the%20VM%3B%20you%20are%20on%20it.%0A%0AYou%20are%20done%20when%20all%20of%20these%20are%20true.%20Check%20each%20one%20yourself%3A%0A-%20Uptime%20Kuma%202%2C%20ready%20for%20your%20first%20monitor.%0A-%20A%20private%20dashboard%20and%20a%20separate%20status-page%20preview.%0A-%20Nightly%20backups%2C%20with%20monitoring%20set%20to%20restart%20after%20a%20reboot.%0A%0ARead%20the%20whole%20recipe%2C%20including%20closed%20details%2C%20and%20follow%20%22Install%20by%0Ahand%22%20first.%20The%20opening%20walkthrough%20is%20for%20the%20owner%20afterwards.%0ADo%20not%20create%20the%20Kuma%20account%2C%20add%20monitors%2C%20or%20send%20email.%20Leave%20public%0Asharing%20off.%20Do%20not%20run%20the%20later%20Restore%20or%20Update%20instructions.%0AWork%20as%20exedev%20in%20~%2Fuptime-kuma.%20Verify%20docker.service%20is%20enabled%2C%20both%0Acontainers%20restart%20unless-stopped%2C%20the%20dashboard%20responds%20on%20localhost%3A8000%2C%0Aand%20%2Fdashboard%2C%20%2Fsocket.io%2F%2C%20and%20%2Fmetrics%20return%20404%20on%20localhost%3A8080.%0ACheck%20that%20the%20backup%20timer%20is%20enabled%20and%20its%20first%20archive%20passes%20gzip%20-t.%0AThe%20status%20page%20will%20not%20exist%20until%20the%20owner%20creates%20it.%0AFinish%20with%20the%20private%20dashboard%20URL%20on%20port%208000%20and%20invite%20the%20owner%0Ato%20create%20their%20account%20and%20add%20their%20first%20monitor.%0A%0AFinish%20with%20the%20URLs%20I%20should%20open.%0A to create a VM whose agent, Shelley, follows this recipe. From a terminal:

```sh
curl -fsSL https://exe-staging.dev/deploy/uptime-kuma/prompt.txt | ssh exe.dev new --prompt=/dev/stdin
```

Or follow the steps below by hand.

Is your site up? Uptime Kuma keeps asking so you don't have to. Give it a
URL, pick an alert, and let your VM do the worrying.

## Get your first green bar

Open the dashboard URL Shelley gives you, like
`https://my-uptime-kuma.exe.xyz:8000/`. Sign in to exe.dev, then create your
Uptime Kuma admin account. Save that password somewhere safe.

1. Click **Add New Monitor** and leave the type as **HTTP(s)**.
2. Give it a name, paste your public site's URL, and **Save**.
3. Wait about a minute. Green and **Up**? You're watching.

## Get a heads-up

Open **Settings → Notifications → Set Up Notification**. Pick a service
you actually read—Telegram, Discord, Slack, or email.

Turn on **Default enabled** and **Apply on all existing monitors**, then
press **Test**. Check that the message arrives and **Save**. Green bars
are nice; knowing when they turn red is the point.

<details id="email-alerts" class="dp-details">
<summary>Email me, without an SMTP server</summary>

Choose **Webhook** to use exe.dev's [email gateway](/docs/send-email):

- **Post URL**: `http://169.254.169.254/gateway/email/send`
- **HTTP Method**: `POST`
- **Request Body**: **Custom Body**

Paste this body, replacing `you@example.com` with your **exe.dev email
address**:

```json
{"to":"you@example.com","subject":"Uptime Kuma alert","body":{{ msg | json }}}
```

Enable **Additional Headers** and paste:

```json
{"Content-Type":"application/json"}
```

Then use **Test** and **Save** as above. No SMTP password to dig up.

</details>

## Share a status page (optional)

In **Status Pages**, choose **New Status Page**. Give it a name, use
`status` as the slug, then click **Next**. Add a group, select only the
monitors you want visitors to see, and **Save**.

Preview it at `https://my-uptime-kuma.exe.xyz:8080/`. Publishing makes all
your status pages public, so review their monitor lists first. Ready?
On your computer, using your VM's name:

```bash
ssh exe.dev share port my-uptime-kuma 8080
ssh exe.dev share set-public my-uptime-kuma
```

`https://my-uptime-kuma.exe.xyz/` now shows your status page. **The dashboard
stays private on port 8000.** To unpublish, run
`ssh exe.dev share set-private my-uptime-kuma` on your computer.

## Keep your history

Your monitors and history live in `~/uptime-kuma/data`. Nightly backups go
to `~/uptime-kuma/backups`. Keep a copy **off the VM**—a backup on a lost VM
won't help much. On your computer:

```bash
scp -r my-uptime-kuma.exe.xyz:uptime-kuma/backups .
```

Backups include notification credentials, so keep them private. For
updates or hiccups, ask Shelley—or open the instructions below.

## The nuts and bolts

Happy clicking Deploy? You can stop here. These are Shelley's setup steps
and your maintenance reference.

<details id="create-the-vm" data-manual-setup class="dp-details">
<summary>Install by hand</summary>

### Create a VM

On your computer (pick another name if `my-uptime-kuma` is taken):

```bash
ssh exe.dev new --name=my-uptime-kuma
ssh my-uptime-kuma.exe.xyz
```

All remaining installation commands run **on the VM**, as `exedev`.

### Start Uptime Kuma

Enable Docker at boot so monitoring comes back after a reboot:

```bash
sudo systemctl enable --now docker.service
mkdir -p ~/uptime-kuma && cd ~/uptime-kuma
cat > compose.yaml <<'EOF'
name: uptime-kuma
services:
  uptime-kuma:
    image: louislam/uptime-kuma:2
    restart: unless-stopped
    environment:
      UPTIME_KUMA_DB_TYPE: sqlite
    ports: ["8000:3001"]
    volumes: ["./data:/app/data"]
  status-proxy:
    image: nginx:stable-alpine
    restart: unless-stopped
    ports: ["8080:8080"]
    volumes: ["./status-proxy.conf:/etc/nginx/conf.d/default.conf:ro"]
    depends_on: [uptime-kuma]
EOF

cat > status-proxy.conf <<'EOF'
server {
    listen 8080;
    absolute_redirect off;
    resolver 127.0.0.11 valid=30s;
    set $kuma http://uptime-kuma:3001;

    location = / { return 302 /status/status; }

    location ~ ^/(status/|api/status-page/|api/badge/|assets/|upload/) {
        limit_except GET HEAD { deny all; }
        proxy_pass $kuma;
        proxy_set_header Host $host;
    }
    location ~ ^/[^/]+\.(svg|png|ico|json|txt|js)$ {
        limit_except GET HEAD { deny all; }
        proxy_pass $kuma;
    }
    location / { return 404; }
}
EOF

docker compose up -d --wait --wait-timeout 180
docker compose ps
printf 'Dashboard: https://%s.exe.xyz:8000/\n' "$(hostname)"
```

Both services should be **Up**, with Kuma **healthy**. The
[HTTPS proxy](/docs/proxy) handles HTTPS and exe.dev login. The nginx
proxy lets you publish status pages later without exposing the dashboard.

### Set up nightly backups

This copies SQLite safely while Kuma keeps watching, checks the copy, and
keeps two weeks of backups:

```bash
cat > backup.sh <<'EOF'
#!/bin/sh
set -eu
umask 077
cd "$(dirname "$0")"
mkdir -p -m 700 backups
out="backups/uptime-kuma-$(date +%Y%m%d-%H%M%S).tar.gz"
docker compose exec -T uptime-kuma sh -eu -c '
  work=$(mktemp -d)
  trap "rm -rf \"$work\"" EXIT
  sqlite3 /app/data/kuma.db ".backup $work/kuma.db"
  test "$(sqlite3 "$work/kuma.db" "PRAGMA integrity_check;")" = ok
  cp -a /app/data/db-config.json /app/data/upload /app/data/docker-tls "$work/"
  tar -C "$work" -czf - .
' > "$out.tmp"
mv "$out.tmp" "$out"
find backups -name 'uptime-kuma-*.tar.gz' -mtime +14 -delete
EOF
chmod +x backup.sh

sudo tee /etc/systemd/system/uptime-kuma-backup.service >/dev/null <<'EOF'
[Unit]
Description=Back up Uptime Kuma
After=docker.service

[Service]
Type=oneshot
User=exedev
ExecStart=/home/exedev/uptime-kuma/backup.sh
EOF
sudo tee /etc/systemd/system/uptime-kuma-backup.timer >/dev/null <<'EOF'
[Unit]
Description=Back up Uptime Kuma nightly

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now uptime-kuma-backup.timer
sudo systemctl start uptime-kuma-backup.service
systemctl list-timers uptime-kuma-backup.timer
gzip -t backups/*.tar.gz
```

The timer should list its next run; `gzip` exits silently on success.
You're ready for the dashboard. Create your account and try the walkthrough
above.

</details>

<details id="back-up-and-restore" class="dp-details">
<summary>Back up and restore</summary>

To take an extra backup, on the VM:

```bash
cd ~/uptime-kuma
./backup.sh
```

### Restore

Pick an archive in `backups/` and substitute its filename below. On a new
VM, run **Install by hand** first and copy your archive into that folder.
These commands run **on the VM**; they set the current data aside rather
than delete it:

```bash
cd ~/uptime-kuma
backup=backups/uptime-kuma-YYYYMMDD-HHMMSS.tar.gz
tar -tzf "$backup" >/dev/null &&
sudo systemctl stop uptime-kuma-backup.timer uptime-kuma-backup.service &&
docker compose stop uptime-kuma &&
sudo mv data "data.before-restore-$(date +%s)" &&
mkdir data &&
sudo tar -C data -xzf "$backup" &&
docker compose up -d --wait &&
sudo systemctl start uptime-kuma-backup.timer
```

Open the dashboard and check your monitors. Your account and notification
settings return to how they were when the backup was taken.

</details>

<details id="update" class="dp-details">
<summary>Update</summary>

On the VM, back up first, then pull and restart:

```bash
cd ~/uptime-kuma
./backup.sh && docker compose pull && docker compose up -d --wait
```

Reopen the dashboard and check your monitors. The `2` image tag keeps you
on Uptime Kuma 2; read the
[release notes](https://github.com/louislam/uptime-kuma/releases) before
changing major versions.

</details>

<details id="troubleshooting" class="dp-details">
<summary>Something's not happy?</summary>

Start with the logs. On the VM:

```bash
cd ~/uptime-kuma
docker compose ps
docker compose logs --tail=50
```

- **Down after a reboot?** Run `sudo systemctl enable --now docker.service`.
- **No email?** Check your spam folder, the webhook's email address and
  headers, and the logs for `Cannot send notification`.
- **Forgot your Kuma password?** Run
  `docker compose exec uptime-kuma npm run reset-password`.
- **Status page missing?** Its slug must be `status`, or you'll need to
  change `/status/status` in `status-proxy.conf` and run
  `docker compose restart status-proxy`.

</details>

## Frequently asked questions

### Is Uptime Kuma free?

Yes—it's open source and MIT-licensed. You pay for your VM; see [exe.dev plans](https://exe.dev/pricing).

### Can I monitor a private exe.dev app?

Yes, through a [VM-to-VM integration](/docs/integrations-vm-to-vm). Monitor the integration's URL, not the app's private exe.xyz address; otherwise you may just be checking the exe.dev login page.

### Can my status page use my own domain?

Yes. Publish it first, then follow the [custom domain guide](/docs/cnames), or ask Shelley to help.

### Who watches the watcher?

Kuma can't alert you while its own VM is offline. Run it separately from the apps it watches; use an outside monitoring service if you need to keep an eye on Kuma itself.


## Related

- [Self-host n8n](https://exe-staging.dev/deploy/n8n.md): Connect your apps. Let the boring bits run themselves.
- [VS Code in your browser, with code-server](https://exe-staging.dev/deploy/code-server.md): Your editor in a tab. Your projects right where you left them.
- [Run Claude Code on a remote server](https://exe-staging.dev/deploy/claude-code.md): A computer for Claude. A breather for your laptop.
- [Host OpenClaw](https://exe-staging.dev/deploy/openclaw.md): An AI sidekick with its own computer. Your laptop can take a nap.
