Docker & DevOps

Self-host Uptime Kuma for uptime and alert monitoring

Install Uptime Kuma on a Linux VPS with Docker, add HTTP and TCP monitors, and route alerts to email or Telegram.

BeginnerLinux server7 min read

To self-host Uptime Kuma you run one Docker container, open port 3001, and add a monitor for each site or service you care about. This guide takes you from a fresh Linux VPS to working HTTP checks, TCP port checks and alerts that reach you by email or Telegram.

Uptime Kuma is a small self-hosted monitoring tool: it pings your endpoints on a schedule, records response times, and notifies you when something stops answering. Because you host it yourself, your check history and alert credentials stay on your own server.

Before you start

You need:

  • A Linux VPS running Ubuntu 22.04/24.04, Debian 12, or AlmaLinux/Rocky 8–9, with root or sudo access.
  • Docker Engine and the Docker Compose plugin. If they are not installed yet, follow the official Docker install docs for your distribution, then confirm:
Bash
docker --version
docker compose version
  • A domain name if you plan to publish a public status page. You can finish the install without one.
  • Outbound access from the VPS to whatever you monitor. Note that many providers block outbound SMTP port 25 — use port 587 or 465 for mail alerts.

Log in over SSH and keep the server's IP handy. The examples below use 203.0.113.10.

Self-host Uptime Kuma with Docker Compose

Create the project directory

Keep the stack in its own folder so upgrades and backups stay simple.

Bash
sudo mkdir -p /opt/uptime-kuma
cd /opt/uptime-kuma

Write the Compose file

Create /opt/uptime-kuma/compose.yaml:

YAML
services:
  uptime-kuma:
    image: louislam/uptime-kuma:1
    container_name: uptime-kuma
    restart: unless-stopped
    ports:
      - "3001:3001"
    volumes:
      - uptime-kuma-data:/app/data

volumes:
  uptime-kuma-data:

The named volume is what holds your monitors, users and history. Never start the container without it, or you lose everything on the next recreate.

Tip: Pin the image to a major tag such as :1 and upgrade on purpose. Check the project's release notes before a big jump so you know about database migrations.

Start the container

Bash
docker compose up -d
docker compose logs -f

Wait for a line about the server listening on port 3001, then press Ctrl+C to leave the logs. Confirm the container is healthy:

Bash
docker compose ps

Open the firewall

Bash
sudo ufw allow 3001/tcp
sudo ufw reload

Warning: Port 3001 gives full access to the admin setup on first visit. If your provider has a cloud firewall or security group, restrict 3001 to your own IP, and put the app behind HTTPS as shown below before you rely on it. Do not leave it open to the whole internet longer than necessary.

Create your admin account and first monitor

Open http://203.0.113.10:3001 in a browser. Uptime Kuma asks you to create the first user — choose a long password and store it in your password manager. That account is the administrator; every monitor and notification lives under it.

Once you are logged in, click Add New Monitor and fill in:

  1. Monitor Type — HTTP(s) for websites, TCP Port for services like SSH or a database.
  2. Friendly Name — something you will recognise in an alert, for example example.com homepage.
  3. URL or Hostname and Port.
  4. Heartbeat Interval — how often to check. Start with 60 seconds; shorter intervals create more traffic and more noise.
  5. Retries — how many failed checks in a row before it is marked down. 2 or 3 avoids alerts from a single blip.

Save, and the monitor starts immediately. The dashboard shows a heartbeat bar per check, plus response time.

Add HTTP and TCP monitors

A practical starter set for one VPS:

  • HTTP(s) on https://example.com with keyword checking enabled, so you catch a page that returns 200 but shows an error message.
  • TCP Port on 203.0.113.10:22 to know SSH is reachable.
  • TCP Port on 203.0.113.10:3389 if you also run a Windows VPS with Remote Desktop.
  • HTTP(s) on each self-hosted app's health endpoint, for example https://cloud.example.com/status.php for Nextcloud.

To check for a keyword, expand the monitor, tick Keyword, and enter a word that only appears on a healthy page, such as your company name. Set the condition to "exists".

For anything behind HTTPS with a certificate you manage yourself, leave certificate expiry checking on — Uptime Kuma warns you before a renewal is missed.

You can also group monitors with Tags and build a public Status Page under the status page menu. Only publish a status page if you are happy for the world to see which services exist.

Set up alerts to email or Telegram

Monitors are only half the job. Add a notification so you hear about an outage.

Email (SMTP)

Go to Settings → Notifications → Setup Notification, choose Email (SMTP), and enter:

  • Host and port from your mail provider — usually 587 with STARTTLS or 465 with TLS. Avoid port 25; many providers block it outbound.
  • Username and password for the sending account.
  • From and To addresses.

Use the Test button. If it fails, the error message from the mail server is usually specific enough to fix the setting.

Telegram

  1. Message @BotFather in Telegram, create a bot, and copy the token.
  2. Send your new bot any message, then open https://api.telegram.org/bot<TOKEN>/getUpdates in a browser and copy the chat.id value.
  3. In Uptime Kuma, choose Telegram, paste the bot token and chat ID, and test.

Tip: Add the notification to Default notifications so new monitors inherit it, then override per monitor where you want a different channel.

Put Uptime Kuma behind HTTPS

Running the dashboard on plain HTTP means your admin password crosses the network in clear text. Two common options:

  • Terminate TLS with Nginx Proxy Manager and proxy uptime.example.com to http://127.0.0.1:3001. This gives you a Let's Encrypt certificate and a single place to manage certificates for your other apps.
  • Use Traefik with Docker labels if your stack already runs it.

Whichever you choose, once HTTPS works, remove the public port mapping so 3001 is only reachable from the proxy, then reopen the dashboard on the domain.

Check it works

  1. From your own machine, open http://203.0.113.10:3001 (or your HTTPS domain) and confirm the dashboard loads.
  2. Confirm the container restarts cleanly and keeps data:
Bash
cd /opt/uptime-kuma
docker compose restart
docker compose ps
  1. In the UI, your monitors should still be listed with their history intact — proof the volume is mounted correctly.
  2. Force a failure to test alerting: add a TCP monitor for 203.0.113.10:65000, which should be closed. Within a couple of intervals it goes down and your email or Telegram alert should arrive.
  3. Delete that test monitor.

Troubleshooting

  • The container restarts in a loop. Check docker compose logs uptime-kuma. The usual causes are a missing ./data volume, or an existing file where the volume should mount. Recreate with docker compose down && docker compose up -d after fixing the volume block.
  • The browser cannot reach the dashboard. Test from the server itself with curl -I http://127.0.0.1:3001. If that works, the problem is the firewall or your provider's security group, not the container.
  • Monitors report "down" for a site you know is up. Run curl -I https://example.com and dig example.com from the VPS. DNS resolution or an IPv6 preference is often the culprit; disable IPv6 per monitor if the target has no AAAA record.
  • No alerts arrive. For email, confirm the port is not blocked (587/465, not 25) and read the SMTP error in the test result. For Telegram, re-check the bot token and chat ID — the bot cannot message you until you have sent it a message first.
  • All history disappeared after an upgrade. The container was recreated without the data volume. Restore from a backup of the uptime-kuma-data volume; going forward, snapshot it before upgrades.

Next steps

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.