Uptime Kuma installeren met Docker voor monitoring
Monitor websites en poorten met Uptime Kuma in Docker. Leer hoe u deze tool op een externe VPS draait voor betrouwbare meldingen via e-mail of Telegram bij serveruitval.
Wat u bouwt
Eén kleine container die uw andere servers en websites van buitenaf monitort en u direct via e-mail, Telegram, Discord of een webhook waarschuwt zodra een service niet meer reageert. Uptime Kuma is één Node-proces dat gebruikmaakt van een SQLite-bestand. Het draait soepel met 256-512 MB RAM en biedt een live dashboard, historische grafieken en een publieke statuspagina. De installatie bestaat uit een Compose-bestand van tien regels; het belangrijkste aspect is waar u het uitvoert en of uw waarschuwingen ooit zijn getest. Een monitor waarvan u niet heeft bewezen dat deze u kan bereiken, is namelijk slechter dan helemaal geen monitor: het geeft u een vals gevoel van veiligheid terwijl er in werkelijkheid niets wordt gecontroleerd.
Draai de monitor op een locatie die niet door de uitval wordt getroffen
Deze beslissing bepaalt het succes van het hele systeem en krijgt daarom de hoogste prioriteit. Draai Uptime Kuma niet op dezelfde machine als de services die het bewaakt. Als de monitor op de server staat die hij controleert, zorgt de gebeurtenis waar u juist waarschuwingen voor wilt ontvangen — het uitvallen van de server of een tekort aan geheugen — er ook voor dat de monitor stopt. U ontvangt dan helemaal geen melding; stilte van een dode monitor is niet te onderscheiden van "alles werkt naar behoren". Er is een subtieler risico terwijl de server nog wel draait: een monitor die naar localhost wijst, deelt de CPU met de werklast. Een piek in de belasting zorgt er dan voor dat de controle zelf een time-out krijgt en de status op down zet. Dit is een vals alarm, terwijl echte gebruikers de service nog wel kunnen bereiken.
Draai Uptime Kuma daarom op een andere VPS dan de server die wordt bewaakt, bij voorkeur bij een andere provider of in een andere regio. Benader uw services op dezelfde manier als uw gebruikers: via het publieke internet en op hostnaam. Een goedkope instantie volstaat; één kleine monitoring-VPS kan al uw servers in de gaten houden. Deze scheiding is vooral cruciaal voor zware applicaties die u host. Een tool zoals een PhotoPrism- of Immich-fotobibliotheek kan de CPU urenlang volledig belasten tijdens het indexeren van een nieuwe import. Een monitor die die hardware deelt, zou dan onterecht een melding sturen dat de service offline is, terwijl deze enkel druk bezig is. Om een uitval van Kuma zelf op te merken, kunt u een push-heartbeat toevoegen via een cron-job op een andere locatie.
Vereisten en dimensionering
- Een verse Ubuntu 24.04 VPS met Docker Engine en de Compose v2-plugin, geïnstalleerd vanuit de eigen apt-repository van Docker, niet het
docker.iodistro-pakket, dat achterloopt. - 256 MB RAM is voldoende voor een handvol monitors; 512 MB tot 1 GB is comfortabel voor tientallen monitors plus de reverse proxy, en het CPU-gebruik is vrijwel nihil tussen de controles door.
- Een domein en een DNS
A-record (bijvoorbeeldstatus.example.comdat naar de VPS wijst), alleen als u TLS en een openbare statuspagina wilt. Een privé-instantie kan DNS overslaan en een VPN of SSH-tunnel gebruiken. - Uitgaand netwerkverkeer naar de bestemming van uw meldingen: SMTP naar uw e-mailprovider, of HTTPS naar Telegram en Discord.
Het Compose-bestand
Plaats dit in /srv/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:
- kuma-data:/app/data
volumes:
kuma-data:Start de container en bekijk de eerste opstartfase:
sudo mkdir -p /srv/uptime-kuma
# save the file above as /srv/uptime-kuma/compose.yaml, then:
cd /srv/uptime-kuma && sudo docker compose up -d
sudo docker compose logs -f uptime-kumaEen correcte start logt Listening on 3001 en wordt daarna stil. Drie zaken in dat bestand zijn bewust zo gekozen.
127.0.0.1:3001:3001, niet 3001:3001. Docker publiceert poorten met DNAT-regels die worden geëvalueerd voordat ufw het pakket ooit ziet. Een kale 3001:3001 plaatst uw dashboard dus op het openbare internet, ongeacht uw firewall. Door te binden aan de loopback blijft het privé en is alleen de reverse proxy blootgesteld; een privé-instantie kan de proxy overslaan en 3001 bereiken via een zelfgehoste WireGuard VPN.
Een named volume op /app/data. Alles wat Uptime Kuma onthoudt – de SQLite-database, uw monitors, notificatie-instellingen en logo's voor statuspagina's – staat daar. Verliest u dit, dan begint u met een leeg beheerscherm; dit is het enige dat u moet back-uppen.
De image is vastgezet op een major-tag, :2. Dit is de huidige stabiele lijn; controleer Docker Hub voor de nieuwste major-versie voordat u deze kopieert. Volg nooit een bewegende tag zoals latest, aangezien het project dit afraadt. Een overstap naar een nieuwe major-versie van deze image is een eenrichtings-databasemigratie die u bewust wilt triggeren, en niet per ongeluk wilt uitvoeren bij een routine-update.
Eén waarschuwing: /app/data moet op een bestandssysteem staan met POSIX-filelocks. Een lokaal Docker-volume is prima; op NFS raakt de SQLite-database corrupt en krijgt u SQLITE_BUSY en database disk image is malformed. Gebruik daarom nooit een netwerkshare.
Eerste run: maak het beheerdersaccount aan
Navigeer naar de instantie via uw proxy op https://status.example.com, of via een SSH-tunnel: voer ssh -L 3001:127.0.0.1:3001 user@your-vps uit en open http://localhost:3001. De eerste pagina is een configuratieformulier voor de gebruikersnaam en het wachtwoord van de beheerder; er is geen standaard login. Kies een sterk wachtwoord: dit dashboard heeft inzicht in de interne adressen en tokens van alles wat u monitort. Later vergeten? Reset het vanaf de host, niet via de browser:
sudo docker compose exec uptime-kuma npm run reset-passwordVoeg eerst uw notificatiekanalen toe en test deze
Configureer waarschuwingen voordat u monitors toevoegt, zodat u bij het aanmaken van elke monitor direct een kanaal kunt koppelen. Ga naar Settings dan Notifications dan Setup Notification en gebruik de Test-knop van elk kanaal om te bevestigen dat het bericht aankomt. Een ongeteste notificatie is namelijk de op één na meest voorkomende reden waarom een configuratie ongemerkt faalt.
Email (SMTP). Vul de host, poort, encryptie, gebruikersnaam, wachtwoord, een From-adres en een To-adres in. De twee werkende combinaties zijn 465 met "Secure" ingesteld op TLS/SSL, of 587 met STARTTLS. Voor Gmail en de meeste providers met tweefactorauthenticatie moet u een app password genereren; een normaal accountwachtwoord resulteert in Error: Invalid login: 535-5.7.8 Username and Password not accepted.
Telegram. Stuur een bericht naar @BotFather, verstuur /newbot en kopieer de bot-token. Voor uw chat-ID stuurt u het nieuwe bot-account eenmalig een bericht, opent u https://api.telegram.org/bot<token>/getUpdates en leest u chat.id uit de JSON. Een bot waarnaar u nog nooit een bericht heeft gestuurd, heeft een lege getUpdates en geen bestemming om naar te versturen.
Discord. Open in het kanaal Edit Channel dan Integrations dan Webhooks dan New Webhook, kopieer de URL en plak deze als een Discord-notificatie.
Generieke webhook. Voor alle overige gevallen, zoals een Slack incoming webhook, een aangepast eindpunt of een home-automation hook: het type Webhook verstuurt een JSON-payload via POST naar een URL die u opgeeft. De meegeleverde Apprise-integratie ondersteunt het merendeel van de negentig andere diensten op de lijst. Als u liever niet heeft dat een derde partij tussen een storing en uw telefoon staat, kies dan het ingebouwde type ntfy en verwijs dit naar een ntfy-server die u zelf beheert. Hiermee pusht u berichten naar uw toestel via een kanaal dat u volledig in eigen beheer heeft.
Monitors toevoegen, één type per keer
Klik op Add New Monitor, kies een type en stel de Friendly Name, het Check Interval (60 seconden is een redelijke waarde), het aantal Retries (opeenvolgende fouten voordat de status op "down" gaat; 2 of 3 voorkomt dat één verloren pakket direct een melding veroorzaakt) en de te activeren notificaties in. De types die u zult gebruiken:
- HTTP(s). Een volledige URL. "Up" betekent een geaccepteerde statuscode (standaard 200-299; verruim dit onder Accepted Status Codes als
301of401normaal is voor uw situatie). Dit is uw standaardmethode voor websites en API's. - HTTP(s) - Keyword. Hetzelfde verzoek, maar "up" vereist hierbij ook dat een specifieke tekstreeks aanwezig is in de body (of afwezig is bij gebruik van Invert). Dit detecteert situaties waarin de site
200 OKteruggeeft terwijl de pagina "Error establishing a database connection" toont, wat een standaard HTTP-check als gezond zou markeren. Dit is ook de juiste check voor een browser-frontend die communiceert met een aparte backend, zoals een Halcyon video-store skin over Jellyfin, waarbij de paginashell vrolijk200teruggeeft terwijl de mediaserver erachter onbereikbaar is. - TCP Port. Een eenvoudige TCP-verbinding naar een host en poort, voor zaken die geen HTTP zijn: SSH op 22, Postgres op 5432, een SMTP-server op 25 of een gameserver.
- Ping. ICMP echo: goedkope methode voor bereikbaarheid en latentie. Veel netwerken en cloud-firewalls blokkeren echter ICMP, waardoor een rode ping-monitor kan betekenen dat de "host down" is of dat de "provider ping blokkeert"; verifieer dit met een TCP-monitor.
- DNS. Lost een record op (A, AAAA, MX, TXT, enzovoort) via een door u opgegeven resolver en kan de uitkomst valideren, waardoor een storing bij de registrar of DNS vroegtijdig wordt opgemerkt.
- Push. De inside-out monitor, die hierna wordt behandeld.
Een cron job monitoren met een push-monitor (heartbeat)
Elke voorgaande monitor benadert uw service van buitenaf. Een push-monitor werkt andersom: Uptime Kuma wacht af en uw taak meldt zelf: "Ik ben uitgevoerd." Dit is de enige betrouwbare manier om een back-up of cron job te controleren: een HTTP-check ziet alleen of een URL reageert, maar alleen de taak zelf weet of deze succesvol is voltooid.
Maak een monitor aan van het type Push. Uptime Kuma genereert een unieke URL zoals:
https://status.example.com/api/push/j8Xa2Kd9Qe?status=up&msg=OK&ping=Stel het Heartbeat Interval in op de frequentie waarmee de taak wordt uitgevoerd, plus een kleine marge. Voeg vervolgens één regel toe aan het einde van het script, zodat deze alleen bij succes wordt aangeroepen:
#!/usr/bin/env bash
set -euo pipefail
# ... your backup or job runs here; set -e aborts on any failure ...
curl -fsS --retry 3 "https://status.example.com/api/push/j8Xa2Kd9Qe?status=up&msg=backup+ok&ping="Als de taak faalt, breekt set -e af vóór de curl; als de server offline is, wordt het script nooit uitgevoerd. In beide gevallen stopt de heartbeat. Zodra het venster van het interval plus het aantal retries is verstreken, zet Uptime Kuma de monitor op down en ontvangt u een melding. Behandel dit push-token als een geheim: iedereen die hierover beschikt, kan een succesvolle statusmelding vervalsen.
Een openbare statuspagina bouwen
Een statuspagina is het publieke overzicht voor uw klanten: welke services actief zijn en hun recente geschiedenis, zonder uw dashboard bloot te stellen. Ga naar Status Pages dan New Status Page, geef de pagina een naam en een slug (het publieke pad, zoals /status/main), sleep de gewenste monitors naar groepen zoals "Websites" en "APIs", voeg een logo en een korte beschrijving toe en kies Save. U kunt de pagina ook koppelen aan een eigen domein, zodat status.example.com deze direct serveert.
Twee waarschuwingen: voeg alleen monitors toe die u openbaar wilt maken, aangezien een statuspagina onthult dat een service bestaat en of deze actief is; daarnaast blijft het dashboard achter uw inloggegevens, terwijl de statuspagina bewust openbaar is en geen authenticatie vereist.
Plaats het achter een reverse proxy met TLS en let op de websockets
Plaats voor een publieke instantie een reverse proxy voor de container die aan localhost is gebonden, ten behoeve van TLS en een hostnaam. Het detail waar iedereen over struikelt: de UI van Uptime Kuma is een live Socket.IO-applicatie, dus de proxy moet de WebSocket-verbinding upgraden. Als dit ontbreekt, laadt de pagina wel, maar komt er geen verbinding tot stand; het dashboard blijft hangen op "Connecting...", live heartbeats worden niet bijgewerkt en de browserconsole toont WebSocket connection to 'wss://.../socket.io/...' failed.
Installeer nginx en certbot en schrijf vervolgens de vhost die doorstuurt naar de localhost-poort. Gebruik voorlopig poort 80 en laat certbot daarna TLS toevoegen; de challenge, de vernieuwingstimer en de bijbehorende foutmodi worden behandeld in het uitgeven van Let's Encrypt-certificaten met certbot en nginx.
sudo apt install -y nginx certbot python3-certbot-nginxSla dit op als /etc/nginx/sites-available/status.example.com; de twee WebSocket-regels zijn hierbij van belang:
server {
listen 80;
server_name status.example.com;
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;
proxy_read_timeout 3600s;
}
}Schakel de site in, test de configuratie en laat certbot vervolgens het blok herschrijven om op 443 te luisteren, het certificaat toe te voegen en een HTTP-naar-HTTPS-redirect in te stellen:
sudo ln -s /etc/nginx/sites-available/status.example.com /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d status.example.comHet paar Upgrade en Connection "upgrade" is essentieel, en proxy_read_timeout 3600s voorkomt dat nginx de langdurige socketverbinding verbreekt; certbot kopieert beide naar het 443-blok dat het genereert. Als u al meerdere containers achter één proxy draait, doet het routeren via Traefik met automatische TLS hetzelfde met container-labels en worden WebSocket-upgrades standaard doorgestuurd.
Pas geen basic-auth toe op de gehele vhost, omdat dit ook de publieke statuspagina en het /api/push-eindpunt blokkeert. Gebruik de ingebouwde login van Uptime Kuma, voeg fail2ban toe om te monitoren op herhaalde mislukte inlogpogingen als de service vanaf internet bereikbaar is, en als het dashboard niet publiek hoeft te zijn, laat de proxy dan achterwege en benader het via een VPN.
Monitoring van certificaatverloop, op de juiste manier
Een HTTP(s)-monitor kan u ook waarschuwen voordat een TLS-certificaat verloopt: vink Certificate Expiry Notification aan en Uptime Kuma verstuurt een melding een ingesteld aantal dagen van tevoren. Twee fouten zorgen voor een onjuiste uitlezing. Monitor op hostnaam, niet op IP, anders ontvangt een verzoek zonder SNI het standaardcertificaat van de server en ziet u Hostname/IP does not match certificate's altnames. Vink bovendien Ignore TLS/SSL Error niet aan bij een monitor waarvan u verloopwaarschuwingen wilt ontvangen: die optie is bedoeld voor interne hosts met self-signed certificaten (unable to verify the first certificate, DEPTH_ZERO_SELF_SIGNED_CERT), maar zorgt er ook voor dat Uptime Kuma het certificaat in zijn geheel niet meer controleert, inclusief de verloopdatum.
Backups: het is één map
Omdat alles zich in /app/data bevindt, is een backup een kopie van dat volume die wordt gemaakt terwijl de container is gestopt. Hierdoor is het SQLite-bestand consistent:
cd /srv/uptime-kuma
sudo docker compose stop
sudo docker run --rm \
-v uptime-kuma_kuma-data:/data \
-v /var/backups/kuma:/backup \
alpine tar czf /backup/kuma-$(date -u +%Y%m%dT%H%M%SZ).tgz -C /data .
sudo docker compose startControleer eerst de werkelijke naam van het volume met docker volume ls | grep kuma, aangezien Compose er een prefix aan toevoegt op basis van de projectmap. Kopieer het tar-bestand vervolgens buiten de server; een backup op dezelfde VPS is slechts een kopie, geen echte backup. Een restore werkt in omgekeerde volgorde: stop de stack, pak het archief uit in een leeg /app/data volume en start de stack opnieuw.
Upgrades
Upgrades zijn een image pull:
cd /srv/uptime-kuma
sudo docker compose pull
sudo docker compose up -dDe nieuwe container voert bij de eerste start eventuele databasemigraties uit; monitor docker compose logs -f. Maak de bovenstaande back-up voordat u de pull uitvoert en blijf binnen een major tag: overstappen van :1 naar :2 is een eenrichtingsmigratie. Maak daarom eerst een back-up en controleer de release notes.
Foutmodi en de bijbehorende meldingen
Onterechte "down"-melding bij een monitor gericht op localhost. De monitor kleurt rood met timeout of 48000ms exceeded of connect ETIMEDOUT, terwijl de service wel reageert vanaf uw laptop. Als de monitor gericht is op de host waarop Uptime Kuma draait, heeft een CPU- of geheugenpiek de controleactie vertraagd, niet de doel-service. Verplaats de monitor naar een aparte VPS en gebruik de publieke hostnaam als doel.
connect ECONNREFUSED 127.0.0.1:443 (of een willekeurige poort). Er luisterde niets op die poort: de service is offline, of u monitort localhost vanuit de container, waarbij 127.0.0.1 de container zelf is en niet uw server. Monitor de publieke hostnaam, niet de loopback-interface.
Invalid login: 535-5.7.8 Username and Password not accepted bij een e-mailtest. De SMTP-inloggegevens zijn onjuist, of de provider vereist een app-specifiek wachtwoord in plaats van uw accountwachtwoord. Genereer een app-wachtwoord en gebruik dat.
connect ETIMEDOUT of queryA ETIMEDOUT <host> bij een e-mailtest. De poort is onjuist of de provider blokkeert uitgaand SMTP-verkeer. Controleer of 465 of 587 overeenkomt met de Secure/STARTTLS-instelling en test vanaf de host met nc -vz smtp.example.com 587. Veel providers blokkeren uitgaand 25 en sommige blokkeren submission-poorten totdat u hierom verzoekt.
self signed certificate of unable to verify the first certificate bij een e-mailtest. Uw SMTP-server presenteert een certificaat dat Node niet vertrouwt; repareer het certificaat van de mailserver in plaats van de foutmelding te negeren.
Dashboard blijft hangen op "Connecting...", console toont WebSocket connection ... failed. De reverse proxy voert geen WebSocket-upgrade uit. Voeg de headers Upgrade en Connection "upgrade" toe in nginx, of gebruik een proxy die deze standaard doorstuurt, zoals Traefik of Caddy. De HTML wordt geladen omdat dit een standaard HTTP GET-verzoek is; alleen de live socket vereist de upgrade.
Certificaatverloop-monitor waarschuwt niet of geeft onjuiste waarschuwingen. Of Ignore TLS/SSL Error is aangevinkt, waardoor certificaatcontrole is uitgeschakeld, of de monitor richt zich op een IP-adres en leest het verkeerde certificaat door ontbrekende SNI, wat resulteert in Hostname/IP does not match certificate's altnames. Vink de optie uit en monitor op basis van de hostnaam.
SQLITE_BUSY of database disk image is malformed in de logs. Het /app/data-volume bevindt zich op een bestandssysteem zonder correcte file-locking, meestal NFS; verplaats het naar een lokaal Docker-volume en herstel vanuit een back-up.
FAQ
Waar moet ik mijn uptime-monitor draaien?
Op een andere server dan de servers die worden gecontroleerd, bij voorkeur bij een andere provider of in een andere regio. U bereikt ze via de hostnaam over het openbare internet, precies zoals uw gebruikers dat doen. Als de monitor op dezelfde machine draait als de doelen, zorgt een storing die de server platlegt er ook voor dat de monitor stopt. Bovendien kan een overbelaste host ervoor zorgen dat de monitor ten onrechte "down" rapporteert voor services die in feite goed functioneren. Een kleine, aparte VPS voorkomt beide problemen.
Hoe ontvang ik meldingen via Telegram of e-mail?
Voeg het kanaal toe onder Settings en vervolgens Notifications, en koppel dit daarna aan elke monitor. Voor Telegram maakt u een bot aan met @BotFather en leest u chat.id uit https://api.telegram.org/bot<token>/getUpdates. Voor e-mail gebruikt u 465 voor SSL of 587 voor STARTTLS met een app-wachtwoord als uw provider tweefactorauthenticatie vereist. Druk op Test en controleer of het bericht aankomt voordat u op de meldingen vertrouwt.
Kan Uptime Kuma een cron job of back-upscript monitoren?
Ja, dat is de Push-monitor: Uptime Kuma geeft u een URL die u aan het einde van het script curl, zodat deze alleen wordt aangeroepen bij een succesvolle afronding. Als de taak faalt of de server offline is, komt de heartbeat niet aan en wordt u gewaarschuwd zodra het interval is verstreken. Dit is de enige betrouwbare manier om te weten of een geplande taak daadwerkelijk is uitgevoerd, aangezien een externe controle niet in het proces zelf kan kijken.
Uptime Kuma versus Zabbix, wat moet ik gebruiken?
Uptime Kuma beantwoordt binnen tien minuten de vraag "is het online, vanaf de buitenkant, en heeft het mij gewaarschuwd" met nauwelijks verbruik van systeembronnen, inclusief een statuspagina. Het verzamelt geen diepgaande statistieken zoals trends voor CPU, geheugen en schijfgebruik of drempelwaarden voor een heel serverpark. Voor dat doel is een volledige Zabbix-monitoringserver de zwaardere, agent-gebaseerde tool; veel mensen gebruiken beide. Twijfelt u nog over wat u in het algemeen moet draaien? Ons overzicht van wat u in 2026 zelf kunt hosten plaatst monitoring in de juiste context.