51 07/04/2026 9 min

Prerequisiti e obiettivo

Qui l’obiettivo è installare Consul Server su Ubuntu 22.04 in modo pulito, con configurazione minima ma già pronta per un uso reale in rete interna. Consul può fare da service discovery, health check, key/value store e base per una piccola control plane. In questa guida ci concentriamo sul ruolo server, quindi sul nodo che partecipa al cluster e mantiene lo stato.

Assumo un server Ubuntu 22.04 aggiornato, accesso root o sudo, rete privata tra nodi Consul e una scelta chiara su uno di questi scenari: laboratorio singolo nodo o cluster con più server. Se vuoi produzione, la scelta corretta è almeno 3 server per quorum; un solo server è utile solo per test o ambienti non critici.

Prima di toccare il sistema, verifica questi punti:

  • hostname e IP statico già definiti
  • porta TCP/UDP 8301 disponibile tra i nodi
  • porta TCP 8300, 8301, 8302, 8500 e 8600 pianificate secondo l’uso
  • disco e RAM sufficienti per il servizio e i log

Pacchetto, utente e struttura file

Il modo più lineare su Ubuntu 22.04 è installare il binario ufficiale HashiCorp, creare un utente dedicato e mantenere la configurazione in /etc/consul.d/. La directory dati tipica è /opt/consul o /var/lib/consul, ma l’importante è che sia persistente e con permessi corretti.

Installa prima i requisiti base:

sudo apt update
sudo apt install -y curl unzip gpg ca-certificates lsb-release

Scarica Consul dal repository ufficiale. Per evitare di prendere versioni a caso, conviene usare una release specifica. Sostituisci 1.19.2 con la versione che hai deciso di standardizzare nel tuo ambiente.

CONSUL_VERSION="1.19.2"
cd /tmp
curl -O https://releases.hashicorp.com/consul/${CONSUL_VERSION}/consul_${CONSUL_VERSION}_linux_amd64.zip
unzip consul_${CONSUL_VERSION}_linux_amd64.zip
sudo install -m 0755 consul /usr/local/bin/consul
consul version

Il comando consul version deve restituire la release installata e confermare che il binario è nel path. Se non vuoi gestire manualmente i download, puoi usare il repository HashiCorp, ma il controllo della versione resta comunque consigliato.

Crea l’utente di servizio e le directory di lavoro:

sudo useradd --system --home /etc/consul.d --shell /usr/sbin/nologin consul
sudo mkdir -p /etc/consul.d /opt/consul
sudo chown -R consul:consul /etc/consul.d /opt/consul
sudo chmod 750 /etc/consul.d /opt/consul

Se hai già policy di hardening, puoi restringere ulteriormente i permessi, ma non farlo prima di aver fatto partire il servizio almeno una volta e verificato i log.

Configurazione minima di Consul Server

La configurazione di base vive in un file JSON o HCL sotto /etc/consul.d/. Su ambienti nuovi è più leggibile HCL. La parte essenziale per un server è: datacenter, data_dir, bind_addr, client_addr, bootstrap_expect e retry_join.

Per un singolo server di laboratorio usa una configurazione semplice. Per un cluster reale, imposta bootstrap_expect uguale al numero di server previsto nel quorum iniziale, ad esempio 3.

sudo tee /etc/consul.d/consul.hcl > /dev/null <<'EOF'
datacenter = "dc1"
data_dir = "/opt/consul"
node_name = "consul-1"
server = true
bootstrap_expect = 1
bind_addr = "0.0.0.0"
client_addr = "127.0.0.1"
ui_config {
  enabled = true
}
log_level = "INFO"
EOF

Qui client_addr = "127.0.0.1" limita l’accesso all’API e alla UI al localhost. È una scelta prudente per partire. Se vuoi accedere da un’altra macchina, cambia in modo esplicito e chiudi il firewall in modo coerente. Non esporre l’API senza una ragione precisa.

Se stai preparando un cluster, aggiungi il join automatico ai peer già noti. Esempio:

sudo tee -a /etc/consul.d/consul.hcl > /dev/null <<'EOF'
retry_join = ["10.0.0.11", "10.0.0.12", "10.0.0.13"]
EOF

In un ambiente serio è meglio usare DNS stabile o un meccanismo di discovery coerente con la tua rete. Se i nodi cambiano IP spesso, il cluster si complica inutilmente.

Unità systemd e avvio del servizio

Consul deve partire come servizio gestito da systemd. Crea una unità semplice ma corretta, con l’utente dedicato e un avvio basato sulla directory di configurazione.

sudo tee /etc/systemd/system/consul.service > /dev/null <<'EOF'
[Unit]
Description=Consul Service Discovery Agent
Documentation=https://developer.hashicorp.com/consul
Wants=network-online.target
After=network-online.target

[Service]
User=consul
Group=consul
ExecStart=/usr/local/bin/consul agent -config-dir=/etc/consul.d
ExecReload=/bin/kill --signal HUP $MAINPID
LimitNOFILE=65536
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

Carica la nuova unità e avvia il servizio:

sudo systemctl daemon-reload
sudo systemctl enable --now consul
sudo systemctl status consul --no-pager

Il servizio deve risultare active (running). Se fallisce, il primo posto da guardare è il journal:

sudo journalctl -u consul -n 100 --no-pager

Gli errori più comuni sono permessi errati su /opt/consul, configurazione HCL non valida o porta già occupata. Non andare avanti senza risolvere il primo errore visibile nel log.

Verifiche di base e accesso alla UI

Una volta avviato il demone, verifica che stia ascoltando sulle porte previste. Per un server con UI e API locali, la porta più utile è 8500.

sudo ss -lntup | grep consul

Se l’output non mostra le porte, il processo non è partito correttamente o sta usando un bind diverso da quello atteso. Puoi verificare anche lo stato del cluster locale con l’API HTTP:

curl -s http://127.0.0.1:8500/v1/status/leader
curl -s http://127.0.0.1:8500/v1/status/peers

Su un singolo server, /v1/status/leader deve restituire un indirizzo del leader locale. Su un cluster, /v1/status/peers deve mostrare i server attesi. Se la risposta è vuota o l’endpoint non risponde, il problema è sul servizio o sul bind dell’interfaccia.

Se hai abilitato la UI, apri:

http://IP_DEL_SERVER:8500/ui

Se hai lasciato client_addr su localhost, la UI sarà raggiungibile solo localmente. In quel caso puoi fare port forwarding SSH:

ssh -L 8500:127.0.0.1:8500 user@server

e poi aprire http://127.0.0.1:8500/ui dal tuo browser.

Firewall e porte da aprire

Consul usa porte diverse per gossip, RPC e HTTP. In un cluster server-to-server devi consentire almeno traffico tra i nodi sulle porte giuste. La regola esatta dipende dal tuo firewall, ma il minimo da considerare è:

  • 8300/tcp per RPC tra server
  • 8301/tcp e 8301/udp per gossip LAN
  • 8302/tcp e 8302/udp se usi WAN gossip
  • 8500/tcp per API e UI
  • 8600/tcp e 8600/udp per DNS

Con UFW, ad esempio, puoi applicare regole restrittive solo verso la tua subnet interna:

sudo ufw allow from 10.0.0.0/24 to any port 8300 proto tcp
sudo ufw allow from 10.0.0.0/24 to any port 8301 proto tcp
sudo ufw allow from 10.0.0.0/24 to any port 8301 proto udp
sudo ufw allow from 10.0.0.0/24 to any port 8500 proto tcp
sudo ufw allow from 10.0.0.0/24 to any port 8600 proto tcp
sudo ufw allow from 10.0.0.0/24 to any port 8600 proto udp
sudo ufw status verbose

Se il cluster non converge, la prima verifica è sempre la connettività tra nodi, non il file di configurazione. Un tcpdump o un semplice nc spesso chiariscono subito se il problema è rete o servizio.

Configurazione per un cluster di tre server

In produzione, il modo corretto di partire è con tre server. La configurazione di ciascun nodo è quasi identica, cambia node_name, bind_addr e l’elenco dei peer da contattare. Se usi indirizzi IP statici, il modello è semplice e robusto.

Esempio per il nodo 1:

datacenter = "dc1"
data_dir = "/opt/consul"
node_name = "consul-1"
server = true
bootstrap_expect = 3
bind_addr = "10.0.0.11"
client_addr = "127.0.0.1"
retry_join = ["10.0.0.12", "10.0.0.13"]
ui_config { enabled = true }

Per il nodo 2 e 3 cambia node_name e bind_addr. Se vuoi evitare un singolo punto di errore iniziale, puoi usare retry_join su tutti e tre i nodi con gli IP dei server rimanenti. Il cluster raggiunge il quorum quando almeno due server si vedono correttamente.

Verifica lo stato del cluster con:

consul members

e, se vuoi una lettura più precisa, con l’API:

curl -s http://127.0.0.1:8500/v1/agent/members | code

Se l’ultimo comando non è disponibile perché hai sbagliato il path o il formato, usa invece:

curl -s http://127.0.0.1:8500/v1/agent/members | python3 -m json.tool

Il risultato atteso è una lista con i nodi del cluster e lo stato alive. Se vedi failed o nessun peer, il problema è quasi sempre firewall, bind address o configurazione retry_join.

Hardening di base e manutenzione

Se il server non deve esporre l’API fuori dalla macchina, lascia client_addr su localhost e accedi tramite SSH tunnel o reverse proxy controllato. È la scelta più prudente. Se invece devi esporre l’interfaccia su rete interna, limita l’accesso con firewall e, se possibile, con un layer di autenticazione davanti.

Per la manutenzione, tieni sotto controllo tre cose: versione del binario, stato del cluster e crescita della directory dati. I controlli minimi periodici possono essere questi:

consul version
consul members
sudo du -sh /opt/consul
sudo journalctl -u consul --since "24 hours ago" | tail -n 100

Se usi Consul per service discovery in ambienti dinamici, pianifica anche la rotazione delle versioni. Aggiornare un server alla volta riduce il rischio, ma va fatto solo dopo aver verificato compatibilità tra release e schema di cluster. Non saltare release importanti senza leggere le note del vendor.

Problemi tipici e correzioni rapide

Se il servizio non parte, controlla in quest’ordine:

  1. sudo journalctl -u consul -n 100 --no-pager per il messaggio d’errore reale
  2. sudo consul validate /etc/consul.d per la validità della configurazione
  3. sudo ss -lntup | grep 8500 per capire se la porta è occupata
  4. ls -ld /opt/consul /etc/consul.d per i permessi

Se la validazione fallisce, correggi prima il file HCL e poi riavvia:

sudo consul validate /etc/consul.d
sudo systemctl restart consul

Se il cluster non si forma, controlla che ogni server abbia lo stesso datacenter, che bootstrap_expect sia coerente e che i nodi riescano a parlarsi sulle porte di gossip e RPC. Un errore banale, come un IP scritto male in retry_join, può bloccare tutta la formazione del cluster.

Regola pratica: prima fai partire il server in locale, poi apri la rete, poi aggiungi gli altri nodi. Saltare i passaggi rende il debug molto più lento.

Verifica finale dell’installazione

A questo punto l’installazione è corretta se questi controlli passano tutti:

  • systemctl is-active consul restituisce active
  • consul version mostra la release attesa
  • curl -s http://127.0.0.1:8500/v1/status/leader restituisce un leader valido
  • consul members mostra il nodo in stato alive
  • journalctl -u consul -n 50 non mostra errori ricorrenti

Se tutto è verde, hai un Consul Server installato correttamente su Ubuntu 22.04, pronto per essere esteso a cluster o integrato con i tuoi servizi. Da qui in avanti il lavoro vero è sulla topologia, sulla sicurezza della rete e sulla disciplina operativa dei nodi.

Assunzione: la guida usa una configurazione iniziale semplificata; in produzione vanno aggiunti TLS, ACL e criteri di accesso coerenti con il tuo ambiente.