Come installare Uptime Kuma con Docker
Configura Uptime Kuma in Docker per monitorare siti, porte e DNS. Scopri come impostare avvisi su Telegram e creare una status page su un VPS isolato.
Cosa stai costruendo
Un singolo container leggero che monitora i tuoi server e siti web dall'esterno. Ti avvisa tramite email, Telegram, Discord o webhook nel momento in cui un servizio smette di rispondere. Uptime Kuma è un processo Node supportato da un file SQLite. Funziona con 256-512 MB di RAM e fornisce una dashboard in tempo reale, grafici storici e una pagina di stato pubblica. L'installazione richiede un file Compose di dieci righe. Gli aspetti fondamentali sono dove lo esegui e se hai testato il funzionamento degli avvisi, poiché un monitoraggio non verificato è inutile: dà una falsa percezione di sicurezza mentre non ricevi alcuna notifica.
Esegui il monitoraggio su un sistema isolato dal downtime
Questa decisione è fondamentale per il successo dell'intero sistema. Non eseguire Uptime Kuma sullo stesso server che deve monitorare. Se il monitor risiede sul server monitorato, l'evento critico (il crash del server o l'esaurimento della memoria) disabiliterà anche il monitor. In questo caso non riceverai alcun avviso: l'assenza di segnali da un monitor spento è indistinguibile da uno stato di "funzionamento regolare". Esiste un rischio più sottile quando il server è attivo: un monitor puntato su localhost condivide la CPU con il carico di lavoro. Un picco di carico può causare il timeout del controllo, portando lo stato del target a down. Questo genera un falso allarme, mentre gli utenti reali continuano a ricevere il servizio correttamente.
Esegui quindi Uptime Kuma su un VPS diverso da quello monitorato. L'ideale è utilizzare un provider o una regione differenti, che raggiungano i servizi tramite internet pubblica e hostname, esattamente come fanno gli utenti. Una istanza economica è sufficiente; un singolo VPS dedicato al monitoraggio può controllare tutti i tuoi server. Per rilevare un eventuale crash di Kuma stesso, configura un push heartbeat tramite cron su un altro sistema.
Prerequisiti e dimensionamento
- Un VPS Ubuntu 24.04 pulito con Docker Engine e il plugin Compose v2. Installare i pacchetti dal repository apt ufficiale di Docker, non dal pacchetto della distro
docker.io, poiché è meno aggiornato. - 256 MB di RAM sono sufficienti per pochi monitor. 512 MB o 1 GB sono consigliati per gestire decine di monitor più il reverse proxy; la CPU rimane quasi inattiva tra un controllo e l'altro.
- Un dominio e un record DNS
A(ad esempiostatus.example.comche punta al VPS), solo se si desidera il supporto TLS e una pagina di stato pubblica. Un'istanza privata può evitare il DNS e utilizzare una VPN o un tunnel SSH. - Connessione di rete in uscita verso i destinatari degli avvisi: SMTP verso il provider email, o HTTPS verso Telegram e Discord.
Il file Compose
Inserire questo contenuto 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:Avviare il servizio e monitorare il primo avvio:
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-kumaUn avvio corretto registra Listening on 3001 e termina l'attività. Tre elementi in questo file sono intenzionali.
127.0.0.1:3001:3001, non 3001:3001. Docker pubblica le porte tramite regole DNAT che vengono valutate prima che ufw riceva il pacchetto. Pertanto, un semplice 3001:3001 espone la dashboard su internet, indipendentemente dal firewall. Il binding su loopback mantiene l'istanza privata, esponendo solo il reverse proxy; un'istanza privata può saltare il proxy e raggiungere 3001 tramite una VPN WireGuard self-hosted invece.
Un volume nominato in /app/data. Tutti i dati salvati da Uptime Kuma — il database SQLite, i monitor, le impostazioni di notifica e i loghi della status-page — risiedono lì. Se il volume viene perso, l'interfaccia admin sarà vuota; è l'unico elemento da eseguire il backup.
L'immagine è fissata a un tag major, :2. Questa è la versione stabile attuale; verificare su Docker Hub l'ultima versione major prima di copiare il comando. Non utilizzare tag mobili come latest, poiché il progetto li considera obsoleti. Un salto di versione major su questa immagine comporta una migrazione del database unidirezionale; deve essere eseguita intenzionalmente e non per errore durante un pull di routine.
Una nota importante: /app/data deve risiedere su un filesystem con supporto ai file lock POSIX. Un volume Docker locale è idoneo; su NFS il database SQLite si corrompe causando SQLITE_BUSY e database disk image is malformed, quindi non utilizzare mai una condivisione di rete.
Primo avvio: creare l'account admin
Accedi all'istanza tramite il proxy all'indirizzo https://status.example.com, oppure tramite un tunnel SSH: esegui ssh -L 3001:127.0.0.1:3001 user@your-vps e apri http://localhost:3001. La prima pagina è un modulo di configurazione per il nome utente e la password dell'amministratore; non sono presenti credenziali predefinite. Scegli una password sicura: questa dashboard visualizza gli indirizzi interni e i token di tutti gli elementi monitorati. Se la dimentichi, procedi al reset dall'host e non dal browser:
sudo docker compose exec uptime-kuma npm run reset-passwordAggiungi prima i canali di notifica e testali
Configura gli avvisi prima di aggiungere i monitor. In questo modo potrai associare un canale durante la creazione di ogni monitor. Vai su Settings then Notifications then Setup Notification e usa il pulsante Test di ogni canale per confermare la ricezione del messaggio. Una notifica non testata è la seconda causa più comune di fallimento silenzioso della configurazione.
Email (SMTP). Inserisci host, port, encryption, username, password, un indirizzo From e un indirizzo To. Le due combinazioni funzionanti sono 465 con "Secure" impostato su TLS/SSL, oppure 587 con STARTTLS. Per Gmail e la maggior parte dei provider con autenticazione a due fattori è necessario generare una app password; una password standard dell'account restituisce Error: Invalid login: 535-5.7.8 Username and Password not accepted.
Telegram. Invia un messaggio a @BotFather, invia /newbot e copia il bot token. Per il tuo chat ID, invia un messaggio al nuovo bot e apri https://api.telegram.org/bot<token>/getUpdates per leggere chat.id dal JSON. Un bot a cui non è stato inviato alcun messaggio iniziale ha un getUpdates vuoto e non ha una destinazione di invio.
Discord. Nel canale, seleziona Edit Channel then Integrations then Webhooks then New Webhook, copia l'URL e incollalo come notifica Discord.
Generic webhook. Per qualsiasi altro servizio, come un incoming webhook di Slack, un endpoint personalizzato o un hook per la domotica, il tipo Webhook invia un payload JSON tramite POST a un URL fornito. L'integrazione Appise inclusa copre la maggior parte degli altri novanta servizi presenti nell'elenco.
Aggiungi monitor, un tipo alla volta
Clicca su Add New Monitor, seleziona un tipo e imposta il Friendly Name, il Check Interval (60 secondi è un valore consigliato), i Retries (numero di fallimenti consecutivi prima di segnalare lo stato "down"; imposta 2 o 3 per evitare falsi allarmi dovuti a singoli pacchetti persi) e le notifiche da attivare. I tipi disponibili sono:
- HTTP(s). Un URL completo. Lo stato "up" indica un codice di stato accettato (di default 200-299; estendi l'intervallo sotto Accepted Status Codes se
301o401sono normali per il tuo sistema). È lo strumento principale per siti web e API. - HTTP(s) - Keyword. La stessa richiesta di prima, ma lo stato "up" richiede anche la presenza di una stringa nel corpo della risposta (se l'opzione Invert non è selezionata). Questo metodo rileva se il sito restituisce
200 OKmostrando il messaggio "Error establishing a database connection", un caso in cui un controllo HTTP standard risulterebbe invece positivo. - TCP Port. Una connessione TCP diretta verso un host e una porta, per servizi non HTTP: SSH sulla porta 22, Postgres sulla 5432, un server SMTP sulla 25 o un server di gioco.
- Ping. Echo ICMP: per verificare con basso overhead la raggiungibilità e la latenza. Molte reti e firewall cloud scartano i pacchetti ICMP; pertanto, un monitor ping in stato "down" può indicare l'host offline oppure il blocco dei pacchetti da parte del provider; verifica la situazione con un monitor TCP.
- DNS. Risolve un record (A, AAAA, MX, TXT, ecc.) tramite un resolver specificato e può verificare la risposta, permettendo di rilevare tempestivamente guasti al registrar o al servizio DNS.
- Push. Il monitoraggio "inside-out", descritto nel prossimo paragrafo.
Monitoraggio di un cron job con un monitor push (heartbeat)
Ogni monitor sopra descritto interroga il servizio dall'esterno. Un monitor push funziona in modo opposto: Uptime Kuma attende, e il job invia una chiamata per confermare l'esecuzione. È l'unico metodo affidabile per monitorare un backup o un cron: un controllo HTTP verifica che un URL risponda, ma solo il job sa se l'operazione è stata completata correttamente.
Crea un monitor di tipo Push. Uptime Kuma genera un URL univoco come:
https://status.example.com/api/push/j8Xa2Kd9Qe?status=up&msg=OK&ping=Imposta il Heartbeat Interval con la frequenza di esecuzione del job, aggiungendo un breve margine di tolleranza. Successivamente, aggiungi una riga alla fine dello script, in modo che venga eseguita solo in caso di successo:
#!/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="Se il job fallisce, set -e interrompe l'esecuzione prima del comando curl; se il server è spento, il comando non viene eseguito. In entrambi i casi il heartbeat si interrompe e, una volta superato l'intervallo previsto più i tentativi di riprova, Uptime Kuma imposta lo stato del monitor su down e invia l'alert. Tratta il push token come un segreto: chiunque ne sia in possesso può simulare un segnale di attività regolare.
Crea una pagina di stato pubblica
Una pagina di stato è la visualizzazione rivolta ai clienti: mostra quali servizi sono attivi e la loro cronologia recente, senza esporre la dashboard. Vai su Status Pages quindi su New Status Page, assegna un nome e uno slug (il percorso pubblico, come /status/main), trascina i monitor desiderati in gruppi come "Websites" e "APIs", aggiungi un logo e una breve descrizione, quindi clicca su Save. È possibile anche collegare la pagina a un dominio dedicato in modo che status.example.com la serva direttamente.
Due avvertenze: aggiungi solo i monitor che intendi rendere pubblici, poiché una pagina di stato rivela l'esistenza di un servizio e il suo stato di attività; la dashboard rimane protetta dal login, mentre la pagina di stato è intenzionalmente pubblica e non richiede autenticazione.
Configuralo dietro un reverse proxy con TLS e gestisci i websockets
Per un'istanza pubblica, posiziona un reverse proxy davanti al container collegato al loopback per abilitare TLS e un hostname. Il dettaglio che causa errori: l'interfaccia di Uptime Kuma è un'app Socket.IO live, quindi il proxy deve gestire l'upgrade della connessione WebSocket. Se non lo configuri, la pagina viene caricata ma non si connette; la dashboard rimane su "Connecting...", i heartbeat non si aggiornano e la console del browser mostra WebSocket connection to 'wss://.../socket.io/...' failed.
Installa nginx e certbot, quindi scrivi il vhost che effettua il proxy verso la porta loopback. Utilizza la porta 80 per ora e lascia che certbot aggiunga TLS successivamente; la gestione di sfide, timer di rinnovo e relativi errori è trattata in issuing Let's Encrypt certificates with certbot and nginx.
sudo apt install -y nginx certbot python3-certbot-nginxSalva questo file come /etc/nginx/sites-available/status.example.com; le due righe WebSocket sono le uniche fondamentali:
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;
}
}Abilita il sito, testa la configurazione, quindi lascia che certbot riscriva il blocco per ascoltare sulla porta 443, inserisca il certificato e aggiunga un redirect HTTP-to-HTTPS:
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.comLa coppia Upgrade e Connection "upgrade" è fondamentale, e proxy_read_timeout 3600s impedisce a nginx di chiudere il socket a lunga durata; certbot copia entrambi nel blocco 443 generato. Se esegui già diversi container dietro un unico proxy, routing them through Traefik with automatic TLS esegue la stessa operazione tramite label dei container e inoltra gli upgrade WebSocket di default.
Non applicare la basic-auth all'intero vhost, poiché bloccheresti la pagina di stato pubblica e l'endpoint /api/push. Mantieni il login integrato di Uptime Kuma, aggiungi fail2ban watching for repeated failed logins se l'istanza è esposta su internet; se la dashboard non deve essere pubblica, rimuovi il proxy e raggiungila tramite VPN.
Monitoraggio della scadenza dei certificati, fatto correttamente
Un monitor HTTP(s) può avvisarti prima che un certificato TLS scada: seleziona Certificate Expiry Notification e Uptime Kuma invierà un avviso con un numero prestabilito di giorni di anticipo. Due errori causano letture errate. Monitora tramite hostname, non IP; in caso contrario, una richiesta senza SNI riceverà il certificato predefinito del server e vedrai Hostname/IP does not match certificate's altnames. Inoltre, non selezionare Ignore TLS/SSL Error su un monitor da cui desideri ricevere avvisi di scadenza: quell'opzione serve per host interni con certificati self-signed (unable to verify the first certificate, DEPTH_ZERO_SELF_SIGNED_CERT), ma impedisce a Uptime Kuma di controllare il certificato, inclusa la scadenza.
Backups: è una singola directory
Poiché tutti i dati risiedono in /app/data, il backup consiste in una copia di quel volume eseguita con il container arrestato. Questo garantisce la coerenza del file SQLite:
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 startVerificare prima il nome reale del volume con docker volume ls | grep kuma, poiché Compose aggiunge il prefisso della directory di progetto. Successivamente, copiare il file tarball fuori dal server, poiché un backup salvato sullo stesso VPS è una semplice copia e non un backup. Il ripristino avviene con l'operazione inversa: arrestare lo stack, estrarre i dati in un volume /app/data vuoto e avviare lo stack.
Upgrades
Gli upgrade consistono nel pull di un'immagine:
cd /srv/uptime-kuma
sudo docker compose pull
sudo docker compose up -dIl nuovo container esegue ogni database migration al primo avvio; monitorare docker compose logs -f. Eseguire il backup indicato sopra prima di effettuare il pull e rimanere all'interno dello stesso major tag: il passaggio da :1 a :2 è una migrazione unidirezionale, quindi eseguire il backup e consultare le release notes.
Modalità di errore e relativi messaggi
Falso stato "down" su un monitor puntato su localhost. Il monitor diventa rosso con timeout of 48000ms exceeded o connect ETIMEDOUT, ma il servizio risponde correttamente dal laptop. Se il monitor punta allo stesso host su cui è in esecuzione Uptime Kuma, il controllo fallisce a causa di un picco di CPU o memoria, non per il target. Sposta il monitor su un VPS separato e punta all'hostname pubblico.
connect ECONNREFUSED 127.0.0.1:443 (o qualsiasi altra porta). Nessun servizio è in ascolto su quella porta: il servizio è offline oppure hai monitorato localhost dall'interno del container, dove 127.0.0.1 è il container e non il server. Monitora l'hostname pubblico, non l'indirizzo loopback.
Invalid login: 535-5.7.8 Username and Password not accepted durante un test email. Le credenziali SMTP sono errate, oppure il provider richiede una password specifica per le app e ha ricevuto la password dell'account. Genera una password per le app e utilizza quella.
connect ETIMEDOUT o queryA ETIMEDOUT <host> durante un test email. Porta errata o il provider blocca il traffico SMTP in uscita. Verifica che 465 o 587 corrisponda all'impostazione Secure/STARTTLS e testa la connessione dall'host con nc -vz smtp.example.com 587. Molti provider bloccano l'uscita 25 e alcuni bloccano le porte di submission fino a richiesta esplicita.
self signed certificate o unable to verify the first certificate durante un test email. Il server SMTP presenta un certificato non riconosciuto da Node; correggi il certificato del server mail invece di ignorare l'errore.
Dashboard bloccata su "Connecting...", la console mostra WebSocket connection ... failed. Il reverse proxy non effettua l'upgrade del WebSocket. Aggiungi gli header Upgrade e Connection "upgrade" su nginx, oppure usa un proxy che li inoltri di default come Traefik o Caddy. L'HTML viene caricato perché è una normale richiesta HTTP GET; solo il socket live richiede l'upgrade.
Il monitor dell'espira certificati non avvisa mai, o avvisa erroneamente. L'opzione Ignore TLS/SSL Error è selezionata, disabilitando il controllo dei certificati, oppure il monitor punta a un IP e legge il certificato errato a causa della mancanza di SNI, mostrando Hostname/IP does not match certificate's altnames. Deseleziona l'opzione e monitora tramite hostname.
SQLITE_BUSY o database disk image is malformed nei log. Il volume /app/data si trova su un filesystem senza supporto al file locking, solitamente NFS; spostalo su un volume Docker locale e ripristina i dati da un backup.
FAQ
Dove dovrei eseguire il mio monitor di uptime?
Su un server diverso da quelli monitorati, idealmente un altro provider o una regione differente, raggiungendoli tramite hostname via internet pubblica esattamente come i tuoi utenti. Se il monitor condivide lo stesso server dei target, il guasto che blocca il server bloccherà anche il monitor; inoltre, un host sovraccarico potrebbe segnalare falsi "down" su servizi che sono invece funzionanti. Un piccolo VPS separato evita entrambi i problemi.
Come posso ricevere avvisi su Telegram o via email?
Aggiungi il canale sotto Settings then Notifications, quindi associarlo a ogni monitor. Per Telegram, crea un bot con @BotFather e leggi chat.id da https://api.telegram.org/bot<token>/getUpdates; per l'email, usa 465 per SSL o 587 per STARTTLS con una app password se il provider utilizza l'autenticazione a due fattori. Premi Test e conferma che il messaggio arrivi prima di fare affidamento sul sistema.
Uptime Kuma può monitorare un cron job o uno script di backup?
Sì, questo è il monitor Push: Uptime Kuma fornisce un URL e tu lo curl alla fine dello script, in modo che l'avviso scatti solo in caso di successo. Se il job fallisce o il server è offline, il heartbeat non arriva e riceverai un avviso dopo il superamento dell'intervallo stabilito. È l'unico modo affidabile per sapere se un job pianificato è stato effettivamente eseguito, poiché un controllo esterno non può analizzarne l'interno.
Uptime Kuma vs Zabbix, quale dovrei eseguire?
Uptime Kuma risponde alla domanda "è online, visto dall'esterno, e mi ha avvisato?" in dieci minuti con un consumo di risorse quasi nullo, oltre a fornire una status page. Non raccoglie metriche profonde come trend di CPU, memoria e disco o soglie per l'intera infrastruttura; per questo, un server di monitoraggio Zabbix completo è lo strumento più pesante basato su agenti, e molte persone li utilizzano entrambi. Stai ancora decidendo cosa installare? la nostra selezione su cosa self-hostare nel 2026 contestualizza il monitoraggio.