Se non sai ancora bene cosa siano Prometheus e Grafana, leggi il nostro articolo su Prometheus vs Grafana. Se conosci già la differenza, ecco come eseguirli insieme.
Questo articolo è la parte pratica. Distribuisce Prometheus, Grafana e Node Exporter su un solo VPS con Docker Compose, mette HTTPS davanti a Grafana con Caddy, importa la dashboard Node Exporter Full (ID 1860) e mostra come raccogliere metriche da un secondo VPS tramite WireGuard.
Il test originale di aprile 2026 girava su Ubuntu 24.04 LTS con Docker Engine 27.x e Docker Compose v2.30. Le versioni fissate nella configurazione qui sotto sono state nel frattempo aggiornate alle release attualmente supportate. In quel test originale con cinque host, l'hub usava circa 300 MB di RAM a riposo e tra 530 e 650 MB durante la raccolta continua.
TL;DR
- Il VPS hub esegue Prometheus, Grafana e Node Exporter in un unico stack Compose, con Caddy installato sull'host come reverse proxy.
- Prometheus e Grafana restano in ascolto solo su 127.0.0.1. L'accesso pubblico passa da Caddy con HTTPS automatico.
- Aggiungi altri server installando Node Exporter su ciascuno e aggiungendo voci a
prometheus.yml. - WireGuard è il percorso di rete consigliato tra hub e nodi. La rete privata funziona bene quando i tuoi server condividono già una rete privata.
- Un VPS da 2 GB è bastato per il test con cinque host qui sotto, ma consideralo un riferimento di partenza e non una regola fissa legata al numero di host.
Cosa costruirai
Ecco a grandi linee come sarà la configurazione una volta finito.
+-------------------+
| Your laptop |
+---------+---------+
| HTTPS
v
+--------------------------+----------------------------+
| MONITORING HUB VPS (2 GB RAM starting point) |
| Caddy (reverse proxy, auto HTTPS) |
| Grafana (port 3000, only via Caddy) |
| Prometheus (port 9090, internal only) |
| Node Exporter (port 9100, scraped on localhost) |
+----+---------------------------------+----------------+
| |
| scrape over WireGuard | scrape over WG
v v
+----+--------+ +-----+-------+
| App VPS 1 | | App VPS 2 |
| Node Expo. | | Node Expo. |
+-------------+ +-------------+
Un solo VPS hub ospita l'intero stack di monitoraggio. Ogni altro VPS che vuoi tenere d'occhio esegue soltanto Node Exporter. Prometheus sull'hub raccoglie le metriche da ciascuno, Grafana le visualizza e Caddy si occupa dell'HTTPS.
Quello che ti serve
Per questa configurazione precisa servono un VPS Ubuntu da usare come hub, un dominio e l'accesso sudo.
- Un VPS con almeno 2 GB di RAM che esegue Ubuntu 24.04 LTS.
- Un nome di dominio con un record A che punta all'IP pubblico del VPS (per esempio grafana.example.com). Serve per l'HTTPS.
- Accesso root o sudo via SSH.
In tutta questa guida, sostituisci grafana.example.com con il sottodominio che hai effettivamente puntato al tuo VPS di monitoraggio. Usa lo stesso dominio nella variabile d'ambiente di Grafana, nel controllo DNS e nel Caddyfile.
Se vuoi monitorare un solo server e non ti serve ancora l'HTTPS, puoi eseguire lo stack Compose sul VPS che già hai, saltando la sezione sul reverse proxy. Il resto della guida resta valido.
Avvia un VPS Ubuntu all'istante con accesso root e storage NVMe.
Distribuisci VPS UbuntuPasso 1: preparazione del server
Collegati via SSH al VPS hub con un utente abilitato a sudo. Per prima cosa aggiorna il sistema.
sudo apt update && sudo apt upgrade -y
Installa Docker Engine e il plugin Compose dal repository ufficiale di Docker.
# Install prerequisites
sudo apt install -y ca-certificates curl gnupg lsb-release
# Add Docker's official GPG key
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
# Add the Docker repository
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Verifica che entrambi siano installati.
docker --version
docker compose version
Entrambi i comandi devono restituire una versione senza errori. Le versioni esatte di Docker Engine e Compose dipenderanno da ciò che il repository ufficiale distribuisce al momento dell'installazione.
sudo usermod -aG docker $USER
Prima di proseguire, esci e rientra nella sessione così la nuova appartenenza al gruppo diventa effettiva. Il gruppo docker concede di fatto privilegi di livello root, quindi aggiungi solo amministratori fidati.
Configura UFW per consentire SSH, HTTP e HTTPS sull'hub di monitoraggio. La porta 80 gestisce il reindirizzamento da HTTP a HTTPS e la validazione ACME. Grafana resta comunque dietro Caddy.
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status
Non aprire le porte 3000, 9090 o 9100 verso internet. Non è un caso che i servizi di monitoraggio restino in ascolto su 127.0.0.1.
Passo 2: lo stack Compose
Crea una cartella per lo stack e la configurazione di Prometheus.
mkdir -p ~/monitoring/prometheus
cd ~/monitoring
Scrivi il file Compose.
# ~/monitoring/docker-compose.yml
services:
prometheus:
image: prom/prometheus:v3.13.2
container_name: prometheus
restart: unless-stopped
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--storage.tsdb.retention.time=15d'
- '--web.enable-lifecycle'
- '--web.listen-address=127.0.0.1:9090'
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus_data:/prometheus
network_mode: host
node-exporter:
image: prom/node-exporter:v1.12.1
container_name: node-exporter
restart: unless-stopped
pid: host
network_mode: host
command:
- '--path.rootfs=/host'
- '--web.listen-address=127.0.0.1:9100'
- '--collector.filesystem.mount-points-exclude=^/(dev|proc|sys|var/lib/docker/.+|var/lib/kubelet/.+)($$|/)'
volumes:
- '/:/host:ro,rslave'
grafana:
image: grafana/grafana:13.1.3
container_name: grafana
restart: unless-stopped
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD}
- GF_USERS_ALLOW_SIGN_UP=false
- GF_SERVER_ROOT_URL=https://grafana.example.com
- GF_SERVER_HTTP_ADDR=127.0.0.1
volumes:
- grafana_data:/var/lib/grafana
network_mode: host
depends_on:
- prometheus
volumes:
prometheus_data:
grafana_data:
Ora scrivi la configurazione di Prometheus.
# ~/monitoring/prometheus/prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
external_labels:
monitor: 'monitoring-hub'
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['127.0.0.1:9090']
- job_name: 'node'
static_configs:
- targets: ['127.0.0.1:9100']
labels:
host: 'monitoring-hub'
Crea un file .env con la password di amministratore di Grafana. Usa una password robusta e non fare il commit di questo file su git.
cat > ~/monitoring/.env <<'EOF'
GRAFANA_ADMIN_PASSWORD='replace-with-a-strong-password'
EOF
chmod 600 ~/monitoring/.env
Alcuni dei flag qui sopra meritano una frase di spiegazione.
--web.listen-address=127.0.0.1:9090fa sì che Prometheus resti in ascolto solo sull'interfaccia di loopback dell'host. In questo modo la porta 9090 resta fuori dalla rete pubblica, pur rimanendo raggiungibile da Grafana e dall'amministrazione locale.--web.enable-lifecycleabilitaPOST /-/reload, così puoi applicare le modifiche alla configurazione di Prometheus senza riavviare il container.pid: host,network_mode: host, il bind mount della root dell'host e--path.rootfs=/hostdanno al Node Exporter containerizzato il contesto dell'host di cui ha bisogno, invece di limitarsi al proprio ambiente di container.GF_USERS_ALLOW_SIGN_UP=falseimpedisce ai visitatori di creare da soli un account Grafana. Questo non rende Grafana privato: la pagina di login resta pubblicamente raggiungibile tramite Caddy.
Consiglio: Se preferisci evitare l'installazione manuale, Cloudzy offre deployment con un clic di Grafana e i piani Prometheus . Il deployment di Prometheus può installare anche Node Exporter.
Passo 3: primo avvio e verifica
Avvia lo stack.
cd ~/monitoring
docker compose up -d
Aspetta qualche secondo, poi verifica che tutti e tre i container siano in esecuzione.
docker compose ps
Tutti e tre i servizi devono risultare in stato running.
Apri un tunnel SSH dal tuo portatile per controllare la pagina dei target di Prometheus.
ssh -L 9090:localhost:9090 your-user@your-vps-ip
Poi apri http://localhost:9090/targets nel browser. Dovresti vedere due target, entrambi in stato UP:
prometheus UP http://127.0.0.1:9090/metrics
node UP http://127.0.0.1:9100/metrics
Se uno dei due è DOWN, passa alla sezione Problemi comuni. Non proseguire finché entrambi non sono UP.
Chiudi il tunnel quando hai finito di controllare i target. Dall'esterno del VPS, Prometheus resterà raggiungibile solo tramite questo tunnel SSH. Il passo successivo espone Grafana via HTTPS.
Passo 4: reverse proxy con HTTPS usando Caddy
Caddy è un singolo binario e gestisce l'HTTPS in automatico. Per un reverse proxy con un solo sito, la configurazione è più breve del blocco Nginx equivalente.
Installa Caddy dal repository ufficiale.
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | \
sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | \
sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo chmod o+r /usr/share/keyrings/caddy-stable-archive-keyring.gpg
sudo chmod o+r /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install -y caddy
Prima del passo successivo, verifica che il record DNS A di grafana.example.com punti all'IP pubblico del VPS. Senza questo, la validazione ACME fallisce.
dig +short grafana.example.com
# Should print the VPS public IP
Modifica il Caddyfile.
# /etc/caddy/Caddyfile
grafana.example.com {
reverse_proxy 127.0.0.1:3000
encode gzip
}
Ricarica Caddy.
sudo systemctl reload caddy
Caddy ottiene e rinnova automaticamente certificati TLS pubblicamente attendibili tramite ACME, non appena il dominio punta al tuo server e le porte 80 e 443 sono raggiungibili. Apri https://grafana.example.com nel browser: dovresti vedere la pagina di login di Grafana su una connessione HTTPS valida. Accedi con admin e la password del tuo file .env.
Passo 5: aggiungere Prometheus come sorgente dati e importare la dashboard 1860
Nell'interfaccia di Grafana, vai su Connessioni > Sorgenti dati > Aggiungi sorgente dati e scegli Prometheus.
Imposta l'URL su:
http://127.0.0.1:9090
In questa configurazione Grafana e Prometheus condividono la rete dell'host, mentre Prometheus resta in ascolto solo su loopback. Fai clic su Save & test e verifica che Grafana riesca a interrogare l'API di Prometheus. Dovresti vedere "Successfully queried the Prometheus API".
Ora importa la dashboard. Node Exporter Full (ID 1860, di rfmoz) è una dashboard della community molto usata per le metriche di Node Exporter. Copre CPU, memoria, I/O del disco, rete, descrittori di file e temperature hardware quando l'host le espone. Include anche variabili per job e instance, quindi funziona in modalità hub-and-spoke senza alcuna modifica.
Vai a Dashboard > Nuovo > Importa dashboard, inserisci l'ID dashboard 1860, seleziona la tua sorgente dati Prometheus e importala.
La dashboard dovrebbe popolarsi non appena il tuo target Node Exporter è UP. La dashboard 1860 usa inoltre, per alcuni pannelli, le metriche dei collector opzionali systemd e processes, quindi un singolo pannello vuoto non significa necessariamente che il target sia guasto.
Passo 6: aggiungere un secondo VPS (hub-and-spoke)
Prima di avviare Node Exporter, assicurati che l'IP privato a cui vuoi associarlo esista già sul secondo VPS. Se usi WireGuard, completa prima la sua configurazione.
Sul secondo VPS installa Docker seguendo la parte di installazione di Docker del passo 1, ma non aprire le porte 80 o 443 solo per il monitoraggio. Poi esegui il solo Node Exporter.
mkdir -p ~/node-exporter
cd ~/node-exporter
cat > docker-compose.yml <<'EOF'
services:
node-exporter:
image: prom/node-exporter:v1.12.1
container_name: node-exporter
restart: unless-stopped
pid: host
command:
- '--path.rootfs=/host'
- '--web.listen-address=10.10.0.2:9100' # bind to the private monitoring IP, never 0.0.0.0
volumes:
- '/:/host:ro,rslave'
network_mode: host
EOF
docker compose up -d
Sostituisci 10.10.0.2 con l'IP privato di monitoraggio di questo server. Se usi WireGuard, usa il suo IP WireGuard; se usi la rete privata di Cloudzy, usa l'IP dell'interfaccia privata del VPS. Se su questo VPS UFW è già attivo, consenti l'accesso a Node Exporter solo all'hub di monitoraggio. Per esempio, se l'IP privato dell'hub è 10.10.0.1:
sudo ufw allow proto tcp from 10.10.0.1 to any port 9100
sudo ufw status
Sostituisci 10.10.0.1 con l'IP privato reale dell'hub. Se UFW è disattivato, l'opzione esplicita --web.listen-address tiene comunque Node Exporter fuori dall'interfaccia pubblica, ma anche altre macchine che raggiungono quella rete privata possono arrivare alla porta 9100.
Due buone opzioni per il percorso di rete tra hub e nodi:
- Rete WireGuard. Ogni VPS entra in una rete WireGuard e Prometheus raccoglie le metriche dagli IP privati. È l'opzione più sicura una volta configurato WireGuard. Offriamo WireGuard come deployment con un clic e abbiamo anche un tutorial di configurazione già pubblicato a riguardo.
- Rete privata Cloudzy. Le istanze VPS di Cloudzy nella stessa regione dispongono di un'interfaccia privata per il traffico est-ovest, quindi puoi raccogliere le metriche da quell'indirizzo invece di costruire un tunnel WireGuard separato.
Una volta che Node Exporter è in esecuzione sul secondo VPS ed è raggiungibile sul suo IP privato, sostituisci il job node esistente in prometheus.yml sull'hub con il blocco qui sotto.
# Update the existing 'node' job in ~/monitoring/prometheus/prometheus.yml
- job_name: 'node'
static_configs:
- targets: ['127.0.0.1:9100']
labels:
host: 'monitoring-hub'
- targets: ['10.10.0.2:9100']
labels:
host: 'app-vps-1'
tier: 'production'
Ricarica Prometheus senza riavviare il container.
curl -X POST http://localhost:9090/-/reload
Riapri il tunnel SSH del passo 3, poi vai su http://localhost:9090/targets. Il nuovo target dovrebbe comparire come UP. Apri la dashboard Node Exporter Full, cambia la variabile instance in alto scegliendo il nuovo server e dovresti vederne i grafici.
Consumo di risorse e quando fare l'upgrade
Questi numeri vengono dal test originale di aprile 2026 su un VPS Ubuntu da 2 GB con cinque host monitorati. Consideralo un riferimento per questo carico di lavoro e non una garanzia di dimensionamento per le release più recenti.
| Componente | RAM a riposo | RAM in attività (1 host) | RAM con 5 host | Disco (retention 15 g, 5 host) |
|---|---|---|---|---|
| Prometheus | ~100 MB | ~150 MB | ~250-350 MB | ~500 MB a 1,5 GB |
| Grafana | ~150 MB | ~180 MB | ~200 MB | ~50 MB |
| Node Exporter | ~15 MB | ~20 MB | non applicabile | trascurabile |
| Caddy | ~30 MB | ~40 MB | ~40 MB | non applicabile |
| Totale hub | ~300 MB | ~390 MB | ~530-650 MB | ~1,5 GB di working set |
Fai l'upgrade quando l'hub inizia a restare a corto di memoria o di spazio su disco. Il solo numero di host è un pessimo criterio di dimensionamento, perché cardinalità delle serie, collector attivi, intervallo di raccolta e retention modificano tutti il consumo. Per l'archiviazione centralizzata a lungo termine, Prometheus supporta integrazioni di remote storage. VictoriaMetrics è una delle opzioni compatibili con Prometheus.
Problemi comuni
I sette problemi che si presentano più spesso, con le relative soluzioni.
- Prometheus raggiungibile da internet. Una semplice mappatura di porta 9090:9090 espone Prometheus a tutto il mondo. Soluzione: mantieni
--web.listen-address=127.0.0.1:9090nel comando di Prometheus come mostrato sopra. In questo modo Prometheus resta in ascolto solo sull'interfaccia di loopback dell'host. - La sorgente dati di Grafana non riesce a raggiungere Prometheus. Questo stack usa la rete dell'host, quindi Grafana può raggiungere Prometheus su http://127.0.0.1:9090. Verifica che Prometheus sia in esecuzione e resti in ascolto su loopback.
- La dashboard di Node Exporter mostra "No data". Tre cause abituali. (a) Prometheus non sta raccogliendo dal target. Controlla
/targets. (b) L'etichetta job nella variabile della dashboard non corrisponde aljob_namenella configurazione di scrape. (c) Un firewall blocca la porta 9100 tra hub e target. - La password di amministratore di Grafana è ancora
admin/adminin produzione. ImpostaGF_SECURITY_ADMIN_PASSWORDda un file .env prima del primo avvio. Se te ne sei dimenticato, cambiala al primo accesso e disattiva la registrazione. - Caddy restituisce "ACME challenge failed". Il record DNS A non si è ancora propagato, oppure la porta 80 è bloccata. Esegui
ufw allow 80,443/tcp, attendi il DNS, eseguisudo systemctl reload caddy. Usadig +shortper confermare la propagazione. - Il disco di Prometheus si riempie. Etichette ad alta cardinalità o intervalli di raccolta brevi con molti host possono riempire il volume in fretta. Tieni d'occhio
prometheus_tsdb_head_seriese la dimensione del volume. Mitigazioni: disattiva i collector di Node Exporter che non usi, allungascrape_intervala 30s oppure riduci la retention. - Errori di permessi sui bind mount. Se monti una directory dell'host invece di un volume con nome, l'UID del container (65534 per Prometheus, 472 per Grafana) deve avere accesso in scrittura. I volumi con nome, come nel file Compose qui sopra, evitano il problema.
Quando questo stack è eccessivo
Se tutto ciò che vuoi è un avviso quando un URL smette di rispondere, questo stack è eccessivo. Uptime Kuma è una scelta molto più leggera se ti bastano controlli di uptime di base.
Domande frequenti
Qual è la differenza tra Prometheus e Grafana?
Prometheus è un database di serie temporali: raccoglie metriche dai target configurati con l'intervallo che imposti, le salva su disco e risponde a query PromQL. Grafana è un livello di visualizzazione che si collega a Prometheus (e a molte altre sorgenti dati) e disegna dashboard. Quasi sempre servono entrambi: Prometheus per raccogliere e archiviare, Grafana per mostrare.
Quanta RAM serve a una configurazione Prometheus + Grafana?
Un hub di monitoraggio che esegue Prometheus, Grafana, Node Exporter e un reverse proxy su un solo VPS usa circa 300 MB di RAM a riposo e tra 530 e 650 MB quando raccoglie attivamente da cinque host ogni 15 secondi.
Posso monitorare più server con una sola istanza di Grafana?
Sì. Lo schema standard è hub-and-spoke. Una sola istanza di Prometheus su un VPS hub raccoglie dal Node Exporter in esecuzione su ogni altro server che vuoi monitorare. Grafana sull'hub interroga solo quell'unico Prometheus. La dashboard Node Exporter Full (ID 1860) supporta una variabile instance, così passi da un server all'altro da un'unica dashboard.
Qual è la migliore dashboard Grafana per Node Exporter?
Per questa configurazione, Node Exporter Full (dashboard con ID 1860, di rfmoz) è un'ottima scelta di default. Copre le principali metriche host di Node Exporter e supporta le variabili job e instance per il monitoraggio di più server. Alcuni pannelli dipendono da collector opzionali di Node Exporter, quindi un singolo pannello vuoto non significa necessariamente che il target di raccolta sia guasto.
Come espongo Grafana via HTTPS?
Esegui Grafana associato a 127.0.0.1:3000 e mettici davanti un reverse proxy che gestisca l'HTTPS. Caddy è l'opzione più semplice: un Caddyfile di quattro righe con reverse_proxy 127.0.0.1:3000 e un blocco di dominio fa tutto, inclusa la gestione automatica dei certificati TLS.
Prometheus + Grafana sono gratuiti per uso commerciale?
Prometheus è rilasciato con licenza Apache 2.0. Grafana OSS è sotto AGPLv3. L'uso interno e commerciale di Grafana OSS non modificato è consentito, ma modificarlo o distribuirlo, oppure offrire una versione modificata via rete, può far scattare obblighi di condivisione del sorgente ai sensi dell'AGPL. Grafana Enterprise e Grafana Cloud hanno condizioni commerciali distinte.
Quando conviene passare da Prometheus a VictoriaMetrics?
Valuta VictoriaMetrics quando una retention più lunga, un'elevata cardinalità delle serie o più istanze di Prometheus rendono difficile gestire il TSDB locale di Prometheus entro il budget di memoria e disco del tuo server. VictoriaMetrics può ricevere i dati di Prometheus ed esporre un'API di query compatibile, quindi può fare da archiviazione a lungo termine o da backend delle metriche per Grafana. Provalo con il tuo carico di lavoro invece di migrare a una soglia fissa di RAM.
