1,199 26/03/2026 07/04/2026 4 min

Il problema: il deploy funziona, ma il server non è più quello atteso

In molti flussi DevOps la CI costruisce un artifact, lo pubblica e poi un job di deploy lo installa sul server. Il guaio arriva dopo qualche giorno: qualcuno modifica a mano un file di configurazione, una variabile d’ambiente cambia, oppure il pacchetto distribuito non coincide più con quello installato.

Questo è environment drift: il sistema in produzione si allontana dallo stato previsto. Se non lo controlli, i rollback diventano lenti e approssimativi.

Scenario pratico: un timer che verifica ogni notte

Qui uso un caso concreto: una piccola app web distribuita come tar.gz firmato dalla CI. Un systemd timer esegue ogni notte uno script che:

  • scarica il manifest dell’ultimo artifact valido;
  • confronta checksum e versione installata;
  • verifica due file critici di configurazione;
  • se trova drift, salva lo stato corrente come backup;
  • riapplica l’artifact atteso oppure prepara un rollback.

Perché non usare solo il deploy pipeline?

Perché il problema spesso nasce dopo il deploy: una modifica manuale, un riavvio incompleto, un file sovrascritto da un hotfix. Il controllo periodico serve proprio a intercettare queste deviazioni senza attendere un incidente.

Struttura minima del controllo

Lo script può essere semplice. L’idea è confrontare tre cose:

  1. artifact atteso: checksum o digest pubblicato dalla CI;
  2. versione installata: file version.txt o release tag;
  3. stato locale: configurazioni e servizio in esecuzione.

Esempio di logica:

se checksum != checksum atteso oppure config diff > 0, allora avvisa, salva backup e ripristina la release corretta.

Esempio di script di verifica

Lo script seguente è intenzionalmente essenziale: controlla un artifact e un file di configurazione, poi decide se intervenire.

#!/usr/bin/env bash
set -euo pipefail

APP_DIR=/opt/myapp
STATE=/var/lib/myapp
MANIFEST_URL=https://ci.example.com/artifacts/myapp/latest.txt
EXPECTED_SHA=$(curl -fsSL "$MANIFEST_URL" | awk '{print $1}')
CURRENT_SHA=$(sha256sum "$APP_DIR/release.tar.gz" | awk '{print $1}')

if [ "$EXPECTED_SHA" != "$CURRENT_SHA" ]; then
  echo "DRIFT: artifact diverso"
  cp -a "$APP_DIR/config.yml" "$STATE/config.yml.$(date +%F-%H%M%S).bak"
  curl -fsSL https://ci.example.com/artifacts/myapp/release.tar.gz -o "$APP_DIR/release.tar.gz"
  systemctl restart myapp.service
  exit 2
fi

grep -q '^mode: prod$' "$APP_DIR/config.yml" || {
  echo "DRIFT: config alterata"
  cp -a "$STATE/config.yml.last-good" "$APP_DIR/config.yml"
  systemctl restart myapp.service
  exit 3
}

echo "OK"

In pratica, questo script non sostituisce la CI: la completa con un controllo di coerenza lato server.

Timer systemd: meglio di un cron generico

Puoi farlo anche con cron, ma systemd timer aiuta in due punti:

  • ha log integrati con journalctl;
  • può partire con ritardo casuale per evitare carichi simultanei;
  • può dipendere dallo stato del sistema e del network.

Un timer notturno tipico potrebbe eseguire il controllo alle 02:15, con una finestra di jitter per non sovraccaricare la CI o il server artefatti.

Rollback: quando farlo davvero

Il rollback non deve scattare a ogni differenza minima. Conviene limitarlo a casi chiari:

  • artifact con checksum errato;
  • versione installata non corrispondente alla release approvata;
  • file di configurazione critico alterato;
  • servizio non avviabile dopo il deploy.

Se invece cambia solo un file non essenziale, meglio segnalare e conservare il backup per una revisione manuale.

Un dettaglio utile: salva sempre il “last known good”

La parte più preziosa del flusso è il backup dello stato buono. Non basta archiviare l’artifact: serve anche conservare la configurazione associata a quella release. Così, se il server deriva, puoi tornare indietro in modo coerente e non solo reinstallare binari.

Checklist rapida

  • artifact con checksum pubblicato dalla CI;
  • manifest firmato o almeno immutabile;
  • verifica notturna con timer;
  • backup del file di config prima di ogni ripristino;
  • log centralizzati per capire quando nasce il drift.

Conclusione

Un controllo periodico con systemd timer è una difesa semplice contro drift, deploy incompleti e rollback fatti male. Non è un sistema di monitoraggio completo, ma è perfetto per automatizzare il compito ripetitivo più trascurato: verificare che ciò che gira in produzione sia ancora ciò che la CI ha approvato.

Se vuoi ridurre i falsi positivi, parti da un solo artifact e una sola config critica, poi estendi il controllo agli altri componenti.