To run Uptime Kuma on a VPS, start the official louislam/uptime-kuma:2 Docker container with its data in a volume and port 3001 bound to 127.0.0.1, create the admin account through an SSH tunnel, then put Caddy in front for HTTPS. Uptime Kuma is a free, MIT-licensed, self-hosted monitor that checks HTTP(S), TCP, ping, DNS and keyword targets and alerts you through Telegram, Discord, email or any of its 90-plus notification services; version 2.5.5, released September 16, 2026, was current on October 3, 2026.
Where the server runs matters as much as the install. A monitor on the same machine or in the same data center as your apps fails with them and sends nothing. This guide puts Uptime Kuma on the smallest plan in a different city from your apps, adds outside-in checks through its built-in Globalping monitor type, and backs it up the way version 2 requires: the data folder, because the old JSON export is gone.
Key takeaways
- Run Uptime Kuma in a different city from the servers it watches: a monitor on the same server or in the same facility fails with them and sends nothing.
- Bind port 3001 to 127.0.0.1 and create the admin account through an SSH tunnel, because until an admin exists, whoever reaches the setup screen first can claim the instance.
- Uptime Kuma 2 removed the JSON export, so the data directory is the only supported backup: stop the container, archive the volume and copy it off the server.
- Since version 2.1.0 the Globalping monitor type adds checks from probes in other countries, within a free budget of 250 tests per hour, or 500 with a free token.
- The project publishes no RAM minimum; on a 1 GB plan, choose SQLite and skip embedded MariaDB and the Browser Engine monitor.
Uptime Kuma on a VPS: the short version
- Deploy an Ubuntu 24.04 LTS VPS with 1 GB of RAM in a different city from the servers you want to watch. Secure SSH and allow only ports 22, 80 and 443.
- Install Docker Engine.
- Start Uptime Kuma with the README’s Docker command, published on localhost only:
-p 127.0.0.1:3001:3001. - Open an SSH tunnel to port 3001, choose SQLite as the database and create the admin account.
- Point a subdomain at the server and add a three-line Caddy site block with
reverse_proxy 127.0.0.1:3001. - Turn on two-factor authentication, set Trust Proxy and the Primary Base URL.
- Add monitors and notifications, then a status page if other people need one.
- Back up the
uptime-kumavolume every night and copy it off the server.
Plan the server: location first, then size
Why monitor from a different location?
Uptime Kuma runs every check from one place: the server it is installed on. If that server shares a failure with the things it watches, the alert never leaves. This table shows what each placement can and cannot see.
| Where Uptime Kuma runs | What it catches | What it misses |
|---|---|---|
| On the same server as your apps | Crashed apps, expired certificates, a full disk that breaks one service | Anything that takes the server or its network down: the monitor goes down too, silently |
| On another server in the same data center | A crashed or overloaded server | Facility-wide power, network or routing problems that hit both servers at once |
| On a server in another city | Server and data-center outages, routing problems between the two cities | Problems only users in other regions see, and failure of the monitor itself |
| Another city, plus Globalping checks | Reachability from probes in the countries you choose | Failure of the monitor itself |
| Two instances in two cities, watching each other | All of the above, including a dead monitor | Both cities failing at the same time |
HourlyVPS takes orders in Istanbul today; New York is coming soon, and the locations page shows the current status of each city. If your apps run with another provider or in another region, an Istanbul server is already a separate city and network. If they run in Istanbul, put the monitor somewhere else: a small server at another provider now, or our second city once it opens. Distance shows up in response-time graphs. Our guide on how to choose a VPS location puts the physical floor for a round trip from Istanbul at about 18 ms to Frankfurt and 79 ms to New York, so judge latency by its trend, not by the absolute number.
A monitor that is down sends no alerts, so something should watch it too. A low-cost fix is a second small Uptime Kuma in another city, with an HTTP(s) monitor on each instance pointing at the other one’s HTTPS address. A hosted free plan pointed at your Uptime Kuma URL does the same job (compared in the cost section).
How much RAM does Uptime Kuma need?
Uptime Kuma’s README and wiki publish no RAM or CPU minimum. They do document what makes it heavier. The Docker Tags page says the full 2 image bundles an embedded MariaDB server and Chromium for the “Browser Engine” monitor type, while 2-slim leaves both out and is about 300 to 400 MB smaller. On Docker Hub on October 3, 2026, the compressed amd64 download was 602 MB for 2 and 182 MB for 2-slim.
| Your setup | Plan | Reasoning |
|---|---|---|
| Personal or small-team monitoring: HTTP, keyword, TCP, ping, DNS and push monitors on SQLite | Quartz Q1 (1 vCPU, 1 GB, 25 GB NVMe) | Ubuntu Server documents 1 GB as the minimum RAM for its cloud images. SQLite is a file inside the Uptime Kuma process, so no second server competes for memory. |
| Embedded MariaDB, Browser Engine monitors, or other containers on the same server | Quartz Q2 (1 vCPU, 2 GB, 50 GB NVMe) | Embedded MariaDB runs a second database server inside the container, and the Browser Engine type drives a headless Chromium. |
| Hundreds of monitors at short intervals, or a long history | Quartz Q4 (2 vCPU, 4 GB, 80 GB NVMe) | Every check writes a heartbeat; version 2.5.5 keeps 365 days of history by default, so more monitors and shorter intervals mean more database work. |
After a day of real checks, read actual usage with sudo docker stats --no-stream uptime-kuma and move up a plan if memory stays near the limit or the container restarts on its own. On a 1 GB plan, a swap file gives a short memory spike somewhere to go before the out-of-memory killer acts; see how to add swap on Ubuntu 24.04.
Traffic is small but not zero. An HTTP(s) monitor with the default GET method downloads the whole response every time: a 60-second check of a page that transfers 100 KB runs 43,200 times in 30 days and pulls about 4.3 GB. For plain up/down checks of heavy pages, switch the monitor’s method to HEAD if the target answers it correctly. Istanbul plans include the monthly traffic allowance listed for each plan, prorated for a server that exists for part of a billing period.
Quartz Q1
KVM · 1 Gbps port · Istanbul · initial credit $5
- vCPU
- 1 shared
- RAM
- 1 GB
- NVMe
- 25 GB
- Traffic
- Istanbul: 2 TB/month
- Per hour$0.01/hour
- Per day (24 h)$0.24/day
- Monthly cap$5.00/month
Install Uptime Kuma with Docker
Start from a hardened server: a sudo user, SSH keys, root and password logins off, and UFW allowing only SSH, HTTP and HTTPS. Our guides on connecting to a VPS over SSH and the VPS security checklist cover that in about 15 minutes. Then follow how to install Docker on a VPS, which uses Docker’s official apt repository. Run every command below as your sudo user.
Step 1: Start the container on localhost only
The README’s Docker command publishes port 3001 on every address of the server. Ports that Docker publishes bypass UFW, so a firewall rule would not hide it. The README offers a localhost-only variant; use it from the start:
sudo docker run -d --restart=always -p 127.0.0.1:3001:3001 -v uptime-kuma:/app/data --name uptime-kuma louislam/uptime-kuma:2
-v uptime-kuma:/app/datakeeps everything in a named Docker volume: the SQLite databasekuma.db,db-config.jsonwith your database choice and, if you pick it, the embedded MariaDB files under/app/data/mariadb. The README warns that NFS is not supported; keep this on local disk.:2tracks the latest 2.x release. The oldlatesttag is deprecated and still points at version 1. Pin a release such as2.5.5if you want to choose when upgrades happen.--restart=alwaysstarts Uptime Kuma again after a reboot or a crash.
Check that it is running. The image has a built-in health check that runs every 60 seconds and gives the app a 180-second start period, so the status shows (health: starting) first and then (healthy):
sudo docker ps --filter name=uptime-kuma
sudo docker logs --tail 20 uptime-kuma
Prefer Docker Compose? The project’s compose.yaml stores data in a ./data folder next to the file and publishes 3001:3001. Change that line to "127.0.0.1:3001:3001" before docker compose up -d. On a 1 GB server that will only use SQLite, the louislam/uptime-kuma:2-slim image runs the same app without embedded MariaDB and Chromium.
Step 2: Create the admin account through an SSH tunnel
Until an admin account exists, anyone who can reach Uptime Kuma sees the setup screen and can create that account. The server refuses a second setup only once a user exists. So finish setup privately, before the dashboard gets a public address. From your own computer, open a tunnel:
ssh -L 3001:127.0.0.1:3001 you@SERVER_IP
Keep that session open and browse to http://localhost:3001 on your computer. Our guide to local SSH port forwarding explains the syntax. Then:
- Choose the database. Uptime Kuma 2 asks on first start: SQLite (“a simple database file, recommended for small-scale deployments”), Embedded MariaDB (full image only) or an external MariaDB/MySQL. On a 1 GB server, pick SQLite. Treat the choice as final: the migration guide says moving an existing SQLite database to MariaDB cannot be done directly and is not officially supported.
- Create the admin username and password. Uptime Kuma rejects passwords its strength check rates “Too weak”; a password manager makes a long one painless.
- Open Settings > Security and set up two-factor authentication with an authenticator app.
Add HTTPS with Caddy and lock down the dashboard
Uptime Kuma’s reverse proxy page recommends serving it over HTTPS behind a proxy. Two details shape the setup: Uptime Kuma does not support a subdirectory such as example.com/uptime, so give it a subdomain, and its dashboard runs over WebSocket. Caddy needs no extra configuration for that: its reverse_proxy directive performs the upgrade and tunnels WebSocket connections by itself, where Nginx and Apache need extra Upgrade and Connection headers.
Create an A record (and an AAAA record if you use IPv6) such as status.example.com pointing at the server. Install Caddy from its official repository and open ports 80 and 443 as described in our Caddy reverse proxy guide. Then add this site block, the one from Uptime Kuma’s wiki, to /etc/caddy/Caddyfile:
status.example.com {
reverse_proxy 127.0.0.1:3001
}
Reload Caddy and open the hostname in a browser. Caddy gets the certificate on the first request:
sudo systemctl reload caddy
Now finish the settings that depend on the proxy:
- Settings > Reverse Proxy > HTTP Headers: set Trust Proxy to Yes. Caddy sends
X-Forwarded-ForandX-Forwarded-Hostby default, and with this on Uptime Kuma logs the real client address. It is safe here because port 3001 is reachable only through Caddy. - Settings > General > Primary Base URL: enter
https://status.example.comor press Auto Get. The Push URLs the dashboard shows, and the links that several notification types (Slack, Microsoft Teams, Pushover, PagerDuty and others) put in alerts, are built from it. - Leave authentication on. The Disable Auth option exists for setups where something such as Cloudflare Access or Authelia authenticates users in front of Uptime Kuma. Without that, it opens your dashboard to anyone.
Behind Cloudflare’s proxy? The wiki says WebSockets must be enabled in the Cloudflare dashboard. Use the Full (strict) SSL mode; our Caddy guide explains Caddy behind Cloudflare. Uptime Kuma can also run a Cloudflare Tunnel itself from Settings > Reverse Proxy, which needs no open ports; this guide sticks to Caddy.
Which Uptime Kuma monitor type should you use?
Uptime Kuma 2.5.5 offers more than 30 monitor types, from plain HTTP to databases, MQTT, SNMP and game servers. Three are hidden when Uptime Kuma runs in Docker, because they need the host itself: system services, SIP Options Ping and Tailscale Ping. These types cover most servers:
| Monitor type | What counts as UP | Use it for | Watch out for |
|---|---|---|---|
| HTTP(s) | An accepted status code, 200–299 by default, after up to 10 redirects | Websites, APIs, health endpoints | A GET downloads the full response on every check |
| HTTP(s) – Keyword | The same, plus a word that must appear in the response (or, with Invert Keyword, must not) | Pages that can return 200 while broken, such as a database error page | The search is case-sensitive |
| TCP Port | A TCP connection to host:port opens | SSH, databases, mail and game ports | An open port says nothing about the app behind it |
| Ping | ICMP echo replies arrive | Basic reachability and network latency | Some networks and firewalls drop ICMP |
| DNS | A query for the record type succeeds (A, AAAA, CAA, CNAME, MX, NS, PTR, SOA, SRV or TXT) through the resolver you set, 1.1.1.1 by default | Catching a changed, hijacked or missing record | Add a condition, such as the A record equals your server’s IP, or any answer counts as UP |
| HTTP(s) – Json Query | A JSONata expression on the response, compared with an expected value (==, !=, contains, or a numeric < <= > >=) | Health endpoints that report status in JSON | The expression must return a single value, not an object or array |
| Push | Your server or job calls the monitor’s URL within the interval | Cron jobs, backups, servers that cannot be reached from outside | No call within the interval means DOWN |
| Docker Container | The container is running | Containers on the same host | Needs /var/ mounted, which gives Uptime Kuma full control of Docker; the wiki advises against exposing Kuma to the internet then |
Point monitors only at systems you run or have permission to check. Our acceptable use policy forbids scanning networks you do not own; a TCP monitor on your own database port is fine.
Settings that prevent false alarms and missed ones
- Heartbeat Interval: 60 seconds by default. The editor accepts lower values but warns that intervals below 20 seconds may result in poor performance.
- Retries: version 2 creates new monitors with 0 retries, so one failed check sends an alert. One or two retries at the default 60-second retry interval filter one-off network blips, at the cost of a slower alert.
- Request Timeout: 48 seconds by default for most types (10 for Ping), and never more than 80% of the interval.
- Certificate Expiry Notification: off by default on each HTTPS monitor, so tick it. The warning days live in Settings > Notifications and default to 7, 14 and 21 days before expiry. Domain Name Expiry Notification is on by default.
- Resend Notification if Down X times consecutively: 0 (off) by default; set it if a single alert is easy to miss.
- Upside Down Mode: flips the result. A TCP monitor on your app server’s database port with Upside Down on alerts you if that port ever becomes reachable from the internet.
- Maintenance: schedule a window from the menu to pause notifications for chosen monitors and show a message on status pages during planned work.
Check from other countries with the Globalping monitor
Since version 2.1.0 (February 2026), Uptime Kuma has a Globalping monitor type. Instead of checking from your server, it asks a probe in Globalping‘s free, community-hosted network to run a ping, HTTP(s) or DNS measurement and records the result. The location field accepts a continent, country, region, city, ASN, ISP or cloud region, one location per monitor. The default is “world”, which picks any probe; the editor’s help text suggests narrowing to a small region, plus the datacenter filter, for steadier latency.
The limit is a test budget: 250 tests per hour without an account, counted per IP address, or 500 with a free API token saved in Uptime Kuma’s settings. Globalping’s credits page counts one test per probe result, and Uptime Kuma asks for one probe per check, so every check, including retries, costs one test. That decides how many Globalping monitors one instance can run:
| Interval | Tests per monitor per hour | Monitors without a token (250/hour) | Monitors with a free token (500/hour) |
|---|---|---|---|
| 60 s | 60 | 4 | 8 |
| 120 s | 30 | 8 | 16 |
| 300 s | 12 | 20 | 41 |
| 600 s | 6 | 41 | 83 |
Use Globalping for a few outside-in checks of your most important URLs, from the regions your users are in, and normal monitors from your server for everything else. Probes are volunteer-hosted, so a single failure can be the probe’s own network; give Globalping monitors at least one retry.
Watch cron jobs and backups with Push monitors
A Push monitor turns the check around: Uptime Kuma waits for a request and marks the monitor DOWN if none arrives within the heartbeat interval. The editor shows a URL in this form:
https://status.example.com/api/push/PUSH_TOKEN?status=up&msg=OK&ping=
Call it from the job itself, and only when the job succeeds. This crontab line on the server that runs a nightly backup reports success at about 02:30; set the Push monitor’s interval a little longer than the schedule, such as 90000 seconds (25 hours):
30 2 * * * /usr/local/bin/nightly-backup.sh && curl -fsS -m 10 -o /dev/null "https://status.example.com/api/push/PUSH_TOKEN?status=up&msg=OK&ping="
A failed backup, a full disk or a dead server all end the same way: no call, so you get an alert. The same works for a job that a systemd timer starts, such as the nightly PostgreSQL dump in our PostgreSQL guide: add the curl call as the last line of the job’s script. With set -e at the top, the script stops at the first error and never reaches it.
Set up Telegram, Discord and email notifications
Add channels under Settings > Notifications > Set Up Notification, or from any monitor’s edit page. Uptime Kuma ships more than 90 notification types. Every form has a Test button; use it before you rely on an alert. Tick Default enabled to attach a channel to new monitors, and Apply on all existing monitors to add it to the ones you already have.
| Channel | What Uptime Kuma asks for | Where to get it | Notes |
|---|---|---|---|
| Telegram | Bot Token and Chat ID | Create a bot with @BotFather, send it a message, then press Auto Get next to Chat ID; it reads the Bot API’s getUpdates | If you reuse a bot that already runs on a webhook, Auto Get finds nothing: the Bot API serves no getUpdates while a webhook is set. A separate alert bot avoids that. Our Telegram bot guide covers both modes. |
| Discord | Discord Webhook URL | Server Settings > Integrations > View Webhooks > New Webhook (needs the Manage Webhooks permission) | Discord’s webhook docs say webhooks need no bot user or authentication, so anyone with the URL can post: keep it secret. Want a real bot instead? See how to host a Discord bot on a VPS. |
| Email (SMTP) | Hostname, port, security, username, password, From and To | Your mail provider’s SMTP settings | Outbound port 25 is blocked on new HourlyVPS servers (AUP). Use port 587 with “None / STARTTLS” or 465 with “TLS”. Since version 2, subject and body templates use LiquidJS, with case-sensitive variables. |
Before the first real outage, pause a test monitor’s target or point a monitor at a URL that returns 404, and check that the DOWN and UP messages arrive where you expect, on the phone you actually carry.
Create a public status page
A status page shows chosen monitors to your users without giving them a login. Create one under Status Pages > New Status Page with a name and a slug; it appears at https://status.example.com/status/your-slug. The slug default is reserved. Add monitors in groups, a description and a footer, and save. Worth knowing, from the status page wiki and the source code:
- It is not live like the dashboard: the server caches status page data for 5 minutes and heartbeat data for 1 minute, and the page reloads itself every 300 seconds by default (the Refresh Interval setting).
- Each status page has an RSS feed at
/status/your-slug/rss, and badges are available for monitors on public status pages. - You can post an incident message at the top of a page. There is no email sign-up for visitors in 2.5.5, so people follow a page by opening it or through its RSS feed.
- Put the status page on a server outside the infrastructure it reports on, for the same reason as the monitor itself.
To serve a page on its own domain, such as status.yourbrand.com, create the DNS record, add a second site block to the Caddyfile and reload Caddy. Then enter the domain under Domain Names in the status page’s sidebar. Caddy passes the host name through, and Uptime Kuma uses it to pick the page:
status.yourbrand.com {
reverse_proxy 127.0.0.1:3001
}
Back up, restore and update Uptime Kuma
Uptime Kuma 2 removed the old JSON Backup/Restore feature. The migration guide is explicit: backing up the data directory is currently the only supported backup method. For the install above, that directory is the uptime-kuma volume. Stop the container for a few seconds so the database files are consistent, archive the volume with the --volumes-from pattern from Docker’s volume backup docs, and start it again.
A nightly backup of the data volume
Save this as /usr/local/sbin/kuma-backup.sh with sudo nano. The trap line starts Uptime Kuma again even if the archive step fails:
#!/bin/sh
# Uptime Kuma backup: stop, archive the data volume, start again
set -eu
BACKUP_DIR=/var/backups/uptime-kuma
STAMP=$(date +%F-%H%M)
mkdir -p "$BACKUP_DIR"
docker stop uptime-kuma
trap 'docker start uptime-kuma' EXIT
docker run --rm --volumes-from uptime-kuma -v "$BACKUP_DIR:/backup" ubuntu \
tar czf "/backup/kuma-data-$STAMP.tgz" -C /app data
chmod 600 "$BACKUP_DIR"/kuma-data-*.tgz
find "$BACKUP_DIR" -name 'kuma-data-*.tgz' -mtime +14 -delete
Make it executable, run it once and check the archive:
sudo chmod 700 /usr/local/sbin/kuma-backup.sh
sudo /usr/local/sbin/kuma-backup.sh
sudo ls -lh /var/backups/uptime-kuma
Schedule it in root’s crontab with sudo crontab -e. This line runs it at 03:15 server time:
15 3 * * * /usr/local/sbin/kuma-backup.sh >> /var/log/kuma-backup.log 2>&1
Checks pause for the few seconds the container is stopped. If a second instance watches this one, give that monitor one retry so the nightly stop does not page you.
Copy the backup off the server
An archive on the same disk does not survive a deleted or broken server. Copy it to another machine every night; the rsync and checksum steps in our delete-VPS checklist work for these archives too, and our restic backup guide sends them to S3-compatible storage, encrypted. Treat the archive as a secret: it holds password hashes, 2FA secrets, bot tokens, webhook URLs and SMTP passwords.
Restore on a fresh server
Install Docker on the new server, copy the newest archive to your home folder, and unpack it into a new volume before the first start:
cd ~
sudo docker volume create uptime-kuma
sudo docker run --rm -v uptime-kuma:/app/data -v "$PWD:/backup" ubuntu tar xzf /backup/kuma-data-2026-10-03-0315.tgz -C /app
sudo docker run -d --restart=always -p 127.0.0.1:3001:3001 -v uptime-kuma:/app/data --name uptime-kuma louislam/uptime-kuma:2
The restored instance starts checking and alerting at once, so stop the old one first or expect duplicate alerts. Then move the DNS record to the new IP address. Rehearse this once on a Quartz Q1 billed by the hour: a two-hour drill uses $0.02 of server time, and deleting the server afterwards stops billing. Ordering it needs an initial credit, which prepays that server’s hours. A stopped server is still billed, because its vCPU, memory, disk and IP addresses stay reserved for you; only deleting the server stops billing.
Update Uptime Kuma
The official update steps for a docker run install are: pull the new image, remove the container and run the same command again. The volume keeps your data. Back up first:
sudo /usr/local/sbin/kuma-backup.sh
sudo docker pull louislam/uptime-kuma:2
sudo docker stop uptime-kuma
sudo docker rm uptime-kuma
sudo docker run -d --restart=always -p 127.0.0.1:3001:3001 -v uptime-kuma:/app/data --name uptime-kuma louislam/uptime-kuma:2
With Compose, run docker compose pull and then docker compose up -d --force-recreate in the project folder.
Upgrading from 1.x? Read the migration guide first: stop Uptime Kuma, back up the data directory, switch the tag to :2 and watch the logs while it aggregates the heartbeat table into the new format. The author’s 20 monitors with 90 days of data took about 7 minutes, and slower hardware with more monitors can take hours; an interrupted migration means restoring the backup and starting again, and rootless images are not recommended for this step. Rehearse it by restoring last night’s backup on an hourly server and upgrading there first.
| Advice in older tutorials | Status in Uptime Kuma 2.x | Use instead |
|---|---|---|
louislam/ or :1 | latest is deprecated and still points at v1 | :2, :2-slim or a pinned 2. tag |
| Settings > Backup > Export JSON | Removed | Back up the data directory or volume |
| Alpine-based images | Dropped | The Debian-based 2 or 2-slim images |
| New monitors retry once | New monitors start with 0 retries | Set retries on each monitor yourself |
| Custom placeholders in email templates | LiquidJS templates; variables are case-sensitive | name, msg, status, heartbeatJSON, monitorJSON, hostnameOrUrl |
| DNS Cache setting on HTTP monitors | Removed | The nscd cache bundled in the Docker image |
| Node.js 14, 16 or 18 for non-Docker installs | Unsupported | Node.js 20.4 or newer |
Troubleshooting Uptime Kuma on a VPS
| Symptom | Likely cause | Fix |
|---|---|---|
| The dashboard loads but never connects, or keeps reconnecting | WebSocket is not passed through: Nginx or Apache without the Upgrade and Connection headers, or WebSockets turned off in Cloudflare | Caddy needs no extra lines. Check Caddy’s logs with sudo journalctl -u caddy, and enable WebSockets in Cloudflare if the record is proxied. |
http: does not open | Expected: the port is bound to 127.0.0.1 | Use the HTTPS hostname, or the SSH tunnel. Do not publish 3001 to work around it. |
| A monitor says DOWN, but the site works in your browser | The target blocks your server’s IP, a firewall drops the check, or the request times out | Test from inside the container, as the troubleshooting wiki suggests: sudo docker exec -it uptime-kuma bash, then curl -I or ping the target. |
| A site behind Cloudflare answers Uptime Kuma with 403 | Cloudflare’s Browser Integrity Check blocks it | Allow your Uptime Kuma server’s IP in Cloudflare IP Access rules, or use a WAF skip rule with a secret header, per the Cloudflare side note. |
| IPv6-only targets are always DOWN | Docker containers get no IPv6 connectivity by default | Attach Uptime Kuma to an IPv6-enabled Docker network (docker network create --ipv6 …), following Docker’s IPv6 docs. |
response timeout: incomplete response within a interval | The target answers slower than the Request Timeout, which can be at most 80% of the interval | Raise the timeout (and the interval, if the cap stops you), or find out why the target is slow. |
| Forgot the admin password, or lost the 2FA device | No other admin login | sudo docker exec -it uptime-kuma npm run reset-password, or npm run remove-2fa the same way. |
| The disk keeps filling | History is kept for 365 days by default | Lower the retention under Settings > Monitor History. |
SQLITE_ or a corrupted database | Data on NFS, which the README says is not supported, or UPTIME_, which the environment variables page warns can cause this error | Keep /app/ on a local volume or directory, remove that variable, and restore from backup if the database is damaged. |
What does self-hosted monitoring cost?
The software is free; the server is the cost. HourlyVPS bills by the hour, and charges for a server stop at the plan’s monthly price in each billing period (one month from your order date). So the same server covers both jobs: a trial or a restore drill costs only its hours, and an always-on monitor never costs more than a monthly VPS, with no contract. This is what the smallest plan costs over those lifetimes; our hourly vs monthly guide explains the cap.
| Duration | Hours on the meter | Cost $0.01 | Note |
|---|---|---|---|
| 2 hours | 2 | $0.02 | |
| 1 day | 24 | $0.24 | |
| 7 days | 168 | $1.68 | |
| 30 days | 720 | $5.00 | Capped at the monthly price |
A pair of instances watching each other doubles the server bill: each Q1 costs at most $5.00 per billing period. There is no prepaid monthly plan: leave a server on and its charges stop at the monthly price in each billing period (after 500 hours, about 20.8 days), with no contract and no annual term. Compare every plan on the pricing page.
How does that compare with a hosted service? UptimeRobot is a common reference point:
| Option | Price | Monitors | Shortest interval | Where checks run from |
|---|---|---|---|---|
| Uptime Kuma on Quartz Q1 | Up to $5.00/month (the monthly cap) | No limit in the software; the server’s size sets it | 20 s before the editor warns about performance | Your server’s city, plus Globalping probes |
| UptimeRobot Free | $0, described as for hobby and non-profit projects | 50 | 5 minutes | UptimeRobot’s network |
| UptimeRobot Solo | From $9/month billed annually ($108/year) | 10 (50 on a higher tier) | 60 seconds | UptimeRobot’s network, multi-location |
| UptimeRobot Team | $35/month billed annually ($420/year) | 100 | 30 seconds | UptimeRobot’s network, multi-location |
UptimeRobot’s pricing page also lists SSL monitoring as a paid-plan feature, while Uptime Kuma’s certificate-expiry alerts come with the free software. A hosted service is the better fit if you do not want to run another server, if you want checks confirmed from several regions before an alert, or if you need team seats and phone-friendly escalation out of the box. Self-hosting Uptime Kuma fits when you want many monitors at short intervals, checks of private targets such as databases and internal ports, status pages on your own domain at no extra cost, and the monitoring data on a server you control. The two also combine well: a free hosted check is a cheap way to watch your Uptime Kuma instance itself.
Deploy this setup
Run Uptime Kuma 24/7 in a different city from your servers
Quartz Q1 · 1 shared vCPU · 1 GB RAM · 25 GB NVMe · Istanbul
- Per hour$0.01/hour
- Per day (24 h)$0.24/day
- Monthly cap$5.00/monthFor this job
Starts with a $5 initial credit, which goes into the server’s balance and pays for its hours.
Billed by the hour, never more than $5.00 per billing period. Delete the server and billing stops.



