Uptime Kuma is a self-hosted monitoring tool that checks websites, ports, DNS records and other services at a fixed interval, notifies you when one goes down, and publishes public status pages. It has a web interface for everything, so there are no configuration files to maintain. In this tutorial you will run Uptime Kuma with Docker Compose on Ubuntu 24.04, put it behind Nginx with a Let's Encrypt certificate, create your first monitors and notifications, publish a status page, and set up backups.
Prerequisites
To follow this tutorial you need:
- A server running Ubuntu 24.04 LTS with at least 1 GB of RAM, for example a CubePath VPS. Run it on a different server or provider from the services you monitor, otherwise an outage can take down the monitor too.
- A non-root user with
sudoprivileges and UFW enabled with SSH allowed. - Docker Engine and the Docker Compose plugin installed from Docker's official repository.
- A domain name,
your_domainin this guide (for examplestatus.example.com), with an A record pointing to the server's IP.
Step 1 - Creating the Docker Compose project
Keep everything related to Uptime Kuma, including its data, in one directory so it is easy to back up:
sudo mkdir -p /opt/uptime-kuma
cd /opt/uptime-kuma
Create the Compose file:
sudo nano /opt/uptime-kuma/compose.yaml
services:
uptime-kuma:
image: louislam/uptime-kuma:2
container_name: uptime-kuma
restart: unless-stopped
ports:
- "127.0.0.1:3001:3001"
volumes:
- ./data:/app/data
Two details matter here:
- The port is published on
127.0.0.1only. Docker writes its own iptables rules, and a port published on all interfaces is reachable from the internet even when UFW has no rule for it. Nginx on the same host will be the only public entry point. ./dataholds the database, uploaded logos and settings. Everything you need to back up or migrate Uptime Kuma lives in that directory.
The 2 tag follows the latest 2.x release. If you are upgrading an existing 1.x installation, back up its data directory first, because the first 2.x start migrates the database and can take a while on large installations.
Step 2 - Starting Uptime Kuma
Pull the image and start the container in the background:
sudo docker compose up -d
Check that the container is running and healthy. The image includes a health check, which reports starting for the first seconds:
sudo docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
uptime-kuma louislam/uptime-kuma:2 "/usr/bin/dumb-init …" uptime-kuma 30 seconds ago Up 29 seconds (healthy) 127.0.0.1:3001->3001/tcp
Confirm it answers locally:
curl -sI http://127.0.0.1:3001 | head -n 1
HTTP/1.1 302 Found
If the container keeps restarting, read its log with sudo docker compose logs -f uptime-kuma.
Step 3 - Configuring Nginx as a reverse proxy
Uptime Kuma updates its dashboard over a WebSocket connection (Socket.IO), so the proxy must forward the Upgrade and Connection headers. Install Nginx:
sudo apt update
sudo apt install -y nginx
Create a server block for your domain:
sudo nano /etc/nginx/sites-available/uptime-kuma
server {
listen 80;
listen [::]:80;
server_name your_domain;
location / {
proxy_pass http://127.0.0.1:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Enable the site, test the syntax and reload Nginx:
sudo ln -s /etc/nginx/sites-available/uptime-kuma /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Step 4 - Enabling HTTPS with Let's Encrypt
Open HTTP and HTTPS in the firewall. Port 80 is needed for the certificate challenge and for the redirect to HTTPS:
sudo ufw allow 'Nginx Full'
Install Certbot with its Nginx plugin and request a certificate. Certbot adds the TLS configuration to the server block and sets up the HTTP to HTTPS redirect:
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your_domain
The package installs a systemd timer that renews the certificate automatically. Check that renewal works:
sudo certbot renew --dry-run
Step 5 - Completing the initial setup
Open https://your_domain in your browser. The setup wizard asks which database to use. SQLite is the right choice for most single-server installations with up to a few hundred monitors; it is stored in ./data with everything else.
Next, create the administrator account with a strong password. There is only one account, so treat these credentials like any other admin password.
After logging in, open Settings and review two options:
- General > Primary Base URL: set it to
https://your_domain. Uptime Kuma uses it in notification links. - Reverse Proxy > Trusted Proxies: set Trust Proxy to Yes, so Uptime Kuma reads the client IP from the
X-Forwarded-Forheader sent by Nginx instead of logging127.0.0.1for every login.
Enabling two-factor authentication under Settings > Security is also recommended, since the dashboard is public on the internet.
Step 6 - Adding monitors
Click Add New Monitor. Each monitor has a type, a target, a check interval and a retry count. A monitor only switches to DOWN after the configured number of consecutive failures, which avoids alerts for a single lost packet. These are the monitors most setups need:
| Monitor type | Target example | What it verifies |
|---|---|---|
| HTTP(s) | https://example.com | The URL returns a 2xx status code within the timeout. |
| HTTP(s) - Keyword | https://example.com/health, keyword ok | The response body contains (or does not contain) a string. |
| TCP Port | db.example.com, port 5432 | A TCP connection can be established. |
| Ping | 203.0.113.10 | The host answers ICMP echo requests. |
| DNS | example.com, record type A | The name resolves, optionally through a specific resolver. |
For your first monitor, create an HTTP(s) monitor for your main website:
- Friendly Name:
Website. - URL:
https://your_website. - Heartbeat Interval:
60seconds, and Retries:2. - Under Advanced, enable Certificate Expiry Notification. Uptime Kuma then warns you before the TLS certificate expires, by default at 7, 14 and 21 days.
- Click Save.
The monitor appears in the left column. Within a minute it shows a green heartbeat bar and the response time graph starts filling.
Step 7 - Setting up notifications
Monitors are only useful if someone is told when they fail. Go to Settings > Notifications > Setup Notification and choose a notification type. Uptime Kuma supports many services; the most common are:
- Email (SMTP): enter your SMTP server, port
587with STARTTLS (or465with TLS), username, password, and the sender and recipient addresses. Outbound port 25 is blocked on many cloud servers, so use your mail provider's submission port. - Slack, Discord or Microsoft Teams: paste an incoming webhook URL created in the chat application.
- Telegram: enter a bot token from
@BotFatherand your chat ID. - Webhook: Uptime Kuma sends a POST request with a JSON body to any URL, for integrations with your own tools.
Click Test before saving; a test message should arrive within seconds. Enable Default enabled so the notification is attached to every new monitor, and Apply on all existing monitors to attach it to the ones you already created.
To verify the full alert path, edit the Website monitor, change the URL to a path that does not exist on a site that returns 404, and save. After the retries, the monitor turns red and you receive a DOWN notification. Restore the URL and you receive an UP notification.
Step 8 - Publishing a status page
A status page shows your users the current state and recent uptime of selected monitors without giving them access to the dashboard.
- Go to Status Pages > New Status Page.
- Enter a name, for example
Example Status, and a slug such asexample. The page will be available athttps://your_domain/status/example. - In the editor, add a group (for example
WebsiteorAPI) and add monitors to it. Only the monitors you add are shown. - Optionally add a description, a logo and a footer text, then click Save.
Open the page in a private browser window to see it as your users will. To show planned work on the page, schedule a window under Maintenance: affected monitors are shown as under maintenance and do not send DOWN notifications during that time.
Step 9 - Backing up and updating
All state lives in /opt/uptime-kuma/data. The safest backup is a copy taken while the container is stopped, because the database may be mid-write while running. Stopping for a few seconds only delays the next checks:
cd /opt/uptime-kuma
sudo docker compose stop
sudo tar -czf "/root/uptime-kuma-$(date +%F).tar.gz" -C /opt/uptime-kuma data
sudo docker compose start
Copy the archive off the server, for example with scp or to object storage. To restore on a new server, extract it into /opt/uptime-kuma, create the same compose.yaml and run sudo docker compose up -d.
To update to the latest 2.x release, take a backup first, then pull the new image and recreate the container:
cd /opt/uptime-kuma
sudo docker compose pull
sudo docker compose up -d
sudo docker image prune -f
Troubleshooting
The dashboard loads but stays on "Cannot connect to the socket server". The WebSocket upgrade is not reaching the container. Check that the proxy_http_version, Upgrade and Connection lines are in the Nginx location block, and that no other proxy in front of Nginx strips them.
502 Bad Gateway from Nginx. The container is not running or not listening on 127.0.0.1:3001. Check sudo docker compose ps and sudo docker compose logs uptime-kuma.
You lost the admin password. Reset it from inside the container, then follow the prompts:
sudo docker exec -it uptime-kuma npm run reset-password
Ping monitors always fail. The target may block ICMP, or an upstream firewall filters it. Use a TCP Port or HTTP monitor instead, which also better reflects whether the service works.
Many monitors show DOWN at the same time. Before assuming a mass outage, check the monitoring server itself: DNS resolution (resolvectl query example.com), outbound connectivity (curl -sI https://example.com), and the container log (sudo docker compose logs --tail 50 uptime-kuma).
Conclusion
You now have Uptime Kuma running in Docker on Ubuntu 24.04, reachable over HTTPS through Nginx, with HTTP and certificate monitoring, alert notifications and a public status page, and a simple backup and update procedure.
As next steps, add monitors for every public endpoint and critical internal port, use Push monitors to get alerted when a cron job or backup stops reporting in, and schedule the backup commands above with a systemd timer so copies are taken automatically.
