Run Uptime Kuma Without Fooling Yourself
A self-hosted Uptime Kuma instance is both a monitoring tool and a privileged observer of the network around it. The operational question is therefore not only how to start the dashboard, but what data, credentials, targets, browsers, daemons, and public routes the instance can reach. Understanding those trust boundaries lets the reader prepare a deployment, test its real dependencies, and treat release or documentation conflicts as verification tasks rather than silently accepted defaults.
The signal pipeline is only as dependable as the environment that runs it. A monitor can be perfectly configured and still fail because its server cannot reach a resolver, its browser is unavailable, its Docker daemon is inaccessible, its database is locked, or its notification provider rejects a message. A green public page can also be misleading if the wrong monitors are public, the data is cached, or the check comes from a location that does not represent the people who rely on the service.
The application owns durable data, but not every live state
The standard Docker Compose arrangement maps the host's data directory to /app/data and exposes port 3001. That directory is more than a place for a few settings. Uptime Kuma creates a database location along with upload, screenshot, and Docker-TLS directories. The data directory is where the operator's monitoring history and configuration become persistent, so it belongs in the backup and access-control plan. The supplied Compose example uses a local directory, and the project warns that network file systems such as NFS are not supported for this purpose.
The application can use SQLite, MariaDB, or an embedded MariaDB mode. With SQLite, the code enables write-ahead logging, foreign keys, a busy timeout, automatic vacuum behavior, and a normal synchronous setting. These are concrete choices about how the database handles concurrency, integrity, and durability; they are not a promise that every storage environment will behave identically. A storage volume can be mounted correctly while still being slow, full, unavailable after a host failure, or inaccessible to the container user.
Startup makes the ownership boundary visible. Uptime Kuma initializes the data directory, connects to the database, applies migrations, initializes authentication and status-page mappings, and only then starts listening and restores active monitors. Background cleanup begins after the server and monitors are ready. During shutdown, the process stops the server services and monitor timers, waits briefly, closes the database, stops background jobs, and then exits. The order is designed to reduce an avoidable race between migration, monitoring, and cleanup, but it does not replace backups or a recovery test.
The durable active flag and the live monitor timer are different things. Pausing a monitor changes the stored flag and stops its in-process timer. Resuming it writes the flag, loads the monitor, and starts a new timer. After a restart, active records are loaded and timers are rebuilt. The database can therefore preserve the intention to monitor while the process is down, but it cannot perform checks while no monitoring process is running. A successful recovery plan has to verify both: that configuration and history survived, and that active monitoring actually resumed.
The live dashboard has a similar boundary. It connects to the server through Socket.IO and receives monitor lists, heartbeats, statistics, and status updates. If the connection is lost, the browser can reconnect and ask for current data again. The browser's view is not the owner of the timers or the database. This distinction matters during a network interruption: a disconnected operator interface is not automatically evidence that the target is down, and a connected interface is not proof that every monitor has a fresh result.
Authentication protects the control surface, not the target itself.