# How Do I Run Uptime Kuma in a Cloud Sandbox?

> Run docker run -d --restart unless-stopped -p 3001:3001 -v uptime-kuma:/app/data louislam/uptime-kuma:1 in a small Sandboxer sandbox, then sbx host <id> 3001 for a private HTTPS URL. It suits trying Uptime Kuma or watching apps in the same sandbox. No checks run while the sandbox is stopped, and Kuma doesn't flag that gap.

Source: https://sandboxer.com/guides/run-uptime-kuma-in-a-sandbox. Updated 2026-10-27.

**Short answer:** Run docker run -d --restart unless-stopped -p 3001:3001 -v uptime-kuma:/app/data louislam/uptime-kuma:1 in a small Sandboxer sandbox, then sbx host <id> 3001 for a private HTTPS URL. It suits trying Uptime Kuma or watching apps in the same sandbox. No checks run while the sandbox is stopped, and Kuma doesn't flag that gap.

## Is a sandbox the right place for an uptime monitor?

Be clear about the fit first. A monitor has to run all the time. A sandbox stops after its auto-stop deadline (one hour by default) and pauses itself when idle. Uptime Kuma's own checks don't count as activity, so they don't keep it awake. We measured that below.

| You want to | Fit |
| - | - |
| Try Uptime Kuma, build monitors and status pages, then copy the setup elsewhere | Good |
| Watch apps that run in the same sandbox while you work on them | Good |
| Watch an agent's dev servers during a long task | Good, with idle pausing off and auto-stop extended |
| Production alerting for sites your customers use | Poor. Run it on an always-on server, or use a hosted monitor. A monitor that stops is silent exactly when you need it |

## At a glance

Everything below ran on one `small` sandbox (2 vCPU, 4 GB) in `eu-central` on October 27, 2026. Single runs, so treat timings as rough.

| Check | What we saw |
| - | - |
| Image | `louislam/uptime-kuma:1`, version 1.23.17, 448 MB |
| Memory used in the whole VM, just after Kuma started | 594 MB of 3.9 GB |
| Hosted URL without the token | `401`, for pages and for `/socket.io/` |
| Dashboard WebSocket through the hosted URL, with the cookie | Logged in over `websocket` in 0.92 s, from a laptop |
| App stopped, check every 20 s | First `DOWN` 7 s later, back `UP` 17 s after the app restarted |
| `sbx stop --wait`, 2 minutes, `sbx resume` | `memoryRestored: true`, same PIDs, 128 s with no heartbeats and no `DOWN` |
| Idle pause with Kuma checking every 20 s | Paused 96 s after the last API call with idle set to 1 minute |
| Reboot | Kuma back with its monitors; an app started with `systemd-run` was not |

## 1. Start Uptime Kuma

Docker is preinstalled and running in every sandbox. The command follows [Uptime Kuma's Docker install](https://github.com/louislam/uptime-kuma#-how-to-install), with `--restart unless-stopped` so it comes back after a reboot, and one addition: `--add-host` lets Kuma reach servers running on the sandbox itself as `host.docker.internal`.

```bash
sbx new --name kuma --type small
id=sb_s0rmhm89da    # the id that sbx new printed

sbx exec $id --timeout 300 "docker run -d --name uptime-kuma --restart unless-stopped \
  -p 3001:3001 --add-host=host.docker.internal:host-gateway \
  -v uptime-kuma:/app/data louislam/uptime-kuma:1"
sbx exec $id "docker ps --format '{{.Names}} {{.Status}}'"
```

```text
uptime-kuma Up 2 seconds (health: starting)
```

The named volume `uptime-kuma` holds Kuma's SQLite database: monitors, heartbeats, users and status pages. We used the `1` tag because the scripting client below was built for 1.x.

For something to watch, we started a small web server on the sandbox, port 8000:

```bash
sbx exec $id "mkdir -p ~/site && echo demo ok > ~/site/index.html && \
  sudo systemd-run -q --unit demo --uid=user --working-directory=/home/user/site python3 -m http.server 8000"
```

`systemd-run` is quick, but the unit it makes doesn't survive a reboot. See section 6.

## 2. Open the dashboard on a private URL

```bash
sbx host $id 3001 --title "Uptime Kuma"
```

```text
https://<subdomain>-3001.box.sandboxer.com?_token=<token>   # subdomain and token redacted
```

What the proxy returned, from a laptop:

| Request | Status |
| - | - |
| `/` or `/api/entry-page`, no token | `401` from the proxy. Kuma never sees it |
| The full URL with `?_token=` | `302` to `/`, sets the `__sbx_auth` cookie |
| `/` with the cookie | `302` to `/dashboard` |
| `/socket.io/?EIO=4&transport=polling` with the cookie | `200` |
| Same, no cookie | `401` |

The dashboard runs over Socket.IO, so it needs WebSockets. They work through the hosted URL: a client sending the cookie connected with the `websocket` transport and logged in. Open the token URL in a browser, and Kuma asks you to create its admin account on first visit. That login is the second lock behind the token.

If you want a public status page, `sbx host $id 3001 --public` drops the token. Kuma's login then guards the dashboard on its own, so set the admin account up before you do that.

## 3. Add monitors from a script

Kuma has no REST API for monitors. The dashboard talks Socket.IO. To script setup we used the community [uptime-kuma-api](https://github.com/lucasheld/uptime-kuma-api) Python client (1.2.1) inside the sandbox. The admin password is generated in the sandbox and never printed.

```bash
sbx scp kuma.py $id:/home/user/
sbx exec $id --timeout 300 "umask 077; openssl rand -hex 16 > ~/.kuma-admin; \
  python3 -m venv ~/kv && ~/kv/bin/pip -q install uptime-kuma-api && ~/kv/bin/python kuma.py setup"
```

```python
# kuma.py (setup part)
import os
from uptime_kuma_api import UptimeKumaApi, MonitorType

pw = open(os.path.expanduser("~/.kuma-admin")).read().strip()
api = UptimeKumaApi("http://localhost:3001", timeout=30)
if api.need_setup():
    api.setup("admin", pw)
api.login("admin", pw)
a = api.add_monitor(type=MonitorType.HTTP, name="demo app",
                    url="http://host.docker.internal:8000/", interval=20, retryInterval=20, maxretries=0)
b = api.add_monitor(type=MonitorType.HTTP, name="example.com", url="https://example.com/", interval=60)
print("monitors", a["monitorID"], b["monitorID"])
print("version", api.info().get("version"))
api.disconnect()
```

```text
monitors 1 2
version 1.23.17
```

`maxretries=0` marks the monitor down on the first failed check. Kuma's default retries before declaring an outage, which is calmer but slower. Read heartbeats back with `api.get_monitor_beats(monitor_id, 1)` (the last hour).

## 4. Watch an app go down and come back

We stopped the demo app at 10:29:27 UTC and started it again at 10:30:17:

```text
== 1 demo app
10:29:14.697 UP    6 ms  200 - OK
10:29:34.708 DOWN        connect ECONNREFUSED 172.17.0.1:8000
10:29:54.714 DOWN        connect ECONNREFUSED 172.17.0.1:8000
10:30:14.721 DOWN        connect ECONNREFUSED 172.17.0.1:8000
10:30:34.726 UP    8 ms  200 - OK
```

`host.docker.internal` resolved to the Docker bridge, `172.17.0.1`, so a server on the sandbox must listen on `0.0.0.0`, not only `127.0.0.1`. Checks against the sandbox's own apps took 3 to 11 ms. Checks of `https://example.com` from `eu-central` took about 70 ms.

## 5. What happens to checks while the sandbox is stopped

We stopped the sandbox at 10:31:39, left it stopped for two minutes and resumed at 10:33:42:

```bash
sbx stop $id --wait
sbx resume $id --json | jq -c '{state, memoryRestored, resumeReason}'
```

```text
{"state":"ready","memoryRestored":true,"resumeReason":null}
```

Kuma's process kept its PID, and the hosted URL went from `404` while stopped to `200` right after resume, with no new `sbx host`. The heartbeats show what a stop means for a monitor:

```text
10:31:14.749 UP    4 ms   200 - OK
10:31:34.755 UP    8 ms   200 - OK
10:33:42.800 UP  346 ms   200 - OK
10:34:03.689 UP    3 ms   200 - OK
```

A 128-second hole, with no `DOWN` and no "monitor was offline" note. Kuma didn't run while frozen, so it saw nothing to report. The uptime percentage counts only the beats that exist, so it stays at 100%. If anything you watched broke during that window, Kuma never knew, and no notification went out. The first check after resume was slow (346 ms), then normal again.

### Idle pausing

The sandbox in this test came with `idleStopMinutes` 30 (it depends on your plan). We set it to 1 minute with `sbx idle $id 1` and stopped making API calls. With Kuma checking every 20 seconds and the load average at 0.17, the sandbox paused 96 seconds later with `"reason":"idle"`. Kuma's checks are local traffic, so they don't count as activity.

To keep a sandbox monitoring for a working session:

```bash
sbx idle $id 0            # never pause when idle
sbx extend $id --hours 12 # push out the auto-stop deadline
```

Auto-stop is a hard deadline even with idle pausing off. During the free trial, deadlines over eight hours and `--no-auto-stop` are refused. See [long-running tasks](/docs/long-running).

## 6. After a reboot

A resume boots from disk instead of restoring memory when it lands on a different CPU type. We tested that path with `sudo systemctl reboot`:

```text
uptime-kuma Up 2 minutes (healthy)
inactive                                  # systemctl is-active demo
10:37:03.780 UP    4 ms   200 - OK
10:37:29.285 DOWN        connect ECONNREFUSED 172.17.0.1:8000
```

The Docker daemon starts at boot and `--restart unless-stopped` brought Kuma back, with both monitors and their history in the volume. The demo app, started with `systemd-run`, did not come back, and Kuma reported it down. Here the monitor did its job. For apps that should survive a cold boot, write a real unit file with `WantedBy=multi-user.target` and `systemctl enable` it, as the [long-running docs](/docs/long-running) show.

## FAQ

### Can Uptime Kuma in a sandbox alert me when my production site is down?

It can send alerts while the sandbox runs, but it can't promise to be running. It stops at the auto-stop deadline, and nothing tells you when it's paused or stopped. Use it to try Kuma or watch the sandbox's own apps, and run production monitoring on an always-on host.

### Which size do I need?

`small` (2 vCPU, 4 GB) was plenty. The whole VM used 594 MB just after Kuma started. Moving to a smaller size isn't supported yet, so start small and size up only if you add heavy apps next to it.

### Does a request to the dashboard wake a paused sandbox?

Yes, if it carries the token or cookie. A request to a hosted URL wakes a sandbox that paused for being idle. Kuma then resumes checking, but beats from the paused time are missing, not marked down.

### How do I move my monitors to a permanent server?

Kuma keeps everything in `/app/data`, which here is the `uptime-kuma` volume. Stop the container, pack that directory into a file, download it, and mount it on your server with the same image tag. We didn't run the migration. See [move files in and out of a sandbox](/guides/move-files-in-and-out-of-a-sandbox) for the download.

### Can Kuma monitor other sandboxes?

Over their hosted URLs, yes; we only tested monitors of the sandbox's own apps and of a public site. A private URL answers `401` without its token, so a check either carries the token (which then sits in Kuma's database) or targets a port hosted with `--public`. Note that each check of a paused sandbox's URL wakes it. For metrics rather than up/down, see [Grafana and Prometheus in a sandbox](/guides/run-grafana-and-prometheus-in-a-sandbox).

## Related

- [Does a cloud sandbox pause itself when idle?](/guides/idle-auto-pause-and-wake-on-use)
- [Give a sandbox port an HTTPS URL](/guides/give-a-sandbox-port-an-https-url)
- [Run Grafana and Prometheus in a sandbox](/guides/run-grafana-and-prometheus-in-a-sandbox)
- [Long-running tasks](/docs/long-running)
