Vai al contenuto principale
50% di sconto tutti i piani, tempo limitato. A partire da $2.48/mo
14 min left
Strumenti per sviluppatori e DevOps

Come configurare uno stack di monitoraggio Grafana + Prometheus sul tuo VPS (guida Docker Compose)

C Di Chike 14 min di lettura
Prometheus and Grafana monitoring stack illustration: a central dashboard panel showing Prometheus and Grafana logos over metric graphs, with three server nodes feeding metrics into it

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

Diagram of monitoring traffic boundaries: ports 80 and 443 are public, Grafana on 3000, Prometheus on 9090 and Node Exporter on 9100 stay on loopback, and a remote Node Exporter on 10.10.0.2:9100 is reachable only over the private network

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.

Distribuisci VPS Ubuntu

Avvia un VPS Ubuntu all'istante con accesso root e storage NVMe.

Distribuisci VPS Ubuntu

Passo 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:9090 fa 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-lifecycle abilita POST /-/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=/host danno 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=false impedisce 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:

  1. 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.
  2. 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

Observed five-host baseline from the April 2026 test: Prometheus 250 to 350 MB, Grafana 200 MB, Caddy 40 MB, hub Node Exporter 15 to 20 MB, total hub 530 to 650 MB RAM on a 2 GB VPS with a 1.5 GB fifteen-day working set

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.

ComponenteRAM a riposoRAM in attività (1 host)RAM con 5 hostDisco (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 MBnon applicabiletrascurabile
Caddy~30 MB~40 MB~40 MBnon 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.

  1. 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:9090 nel comando di Prometheus come mostrato sopra. In questo modo Prometheus resta in ascolto solo sull'interfaccia di loopback dell'host.
  2. 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.
  3. 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 al job_name nella configurazione di scrape. (c) Un firewall blocca la porta 9100 tra hub e target.
  4. La password di amministratore di Grafana è ancora admin/admin in produzione. Imposta GF_SECURITY_ADMIN_PASSWORD da un file .env prima del primo avvio. Se te ne sei dimenticato, cambiala al primo accesso e disattiva la registrazione.
  5. 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, esegui sudo systemctl reload caddy. Usa dig +short per confermare la propagazione.
  6. 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_series e la dimensione del volume. Mitigazioni: disattiva i collector di Node Exporter che non usi, allunga scrape_interval a 30s oppure riduci la retention.
  7. 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.

Condividi

Altro dal blog

Continua a leggere.

Pronto a distribuire? Da 2,48 $/mese.

Cloud indipendente, dal 2008. AMD EPYC, NVMe, 40 Gbps. Rimborso entro 14 giorni.