1 14/05/2026 11 min

Su AlmaLinux 9 e Rocky Linux 9 GeoIP non è più “una cosa da mettere su e dimenticare”. La parte che conta davvero è scegliere il formato giusto del database, installarlo in modo ripetibile e verificare dove il web server o PHP lo consumano davvero. Se fai solo il pacchetto e basta, spesso ti ritrovi con una libreria presente ma nessuna geolocalizzazione utile nelle risposte HTTP o nell’applicazione.

La distinzione pratica è questa: GeoIP legacy identifica il formato vecchio basato su .dat e moduli datati, mentre oggi la via corretta è GeoLite2 o un database MaxMind equivalente in formato .mmdb. Su RHEL-like 9 conviene ragionare così: installi il supporto al database, scarichi o sincronizzi il file, poi lo agganci a Nginx, Apache, PHP-FPM o all’applicazione che ne ha bisogno.

Scelta del componente: libreria, database o integrazione web

Prima di toccare il sistema conviene decidere cosa vuoi ottenere. Se ti serve solo sapere il paese o la città dell’IP nei log o in una web app, il database MaxMind è sufficiente. Se vuoi arricchire le richieste HTTP a livello di server, allora ti serve anche il modulo del web server. Se invece la geolocalizzazione serve all’applicazione, la soluzione più pulita è usare il database direttamente dal codice o da una libreria del linguaggio usato.

In pratica hai tre scenari frequenti:

  • Geolocalizzazione nei log: Nginx o Apache leggono l’IP e lo associano al paese.
  • Geolocalizzazione nelle variabili applicative: PHP, Python o Go interrogano il database .mmdb.
  • Regole di routing o blocco: il web server usa il paese per riscritture, redirect o limitazioni, con molta più cautela perché l’errore operativo ha impatto immediato sugli utenti.

Se non hai un requisito preciso, la scelta meno fragile è mantenere il database separato dal server web e farlo consumare solo dove serve. Così riduci il blast radius: un aggiornamento del database non richiede necessariamente il reload del web server.

Pacchetti disponibili su AlmaLinux 9 e Rocky Linux 9

Nei repository standard trovi spesso il supporto alla libreria MaxMind e, in alcuni casi, pacchetti per l’integrazione con Nginx o Apache tramite repository aggiuntivi come EPEL o Remi, a seconda dello stack installato. Il dettaglio cambia nel tempo, quindi il controllo corretto è sempre sul sistema reale, non sulla memoria.

Verifica cosa è disponibile prima di installare:

dnf search geoip maxmind mmdb

Se vuoi una vista più precisa dei pacchetti installabili:

dnf list available '*geoip*' '*maxmind*' '*mmdb*'

Su molte installazioni recenti ti interessano soprattutto:

  • libmaxminddb per leggere database .mmdb.
  • libmaxminddb-utils per testare il database da CLI.
  • Eventuali moduli per Nginx o Apache, se vuoi variabili già pronte nel web server.
  • Il pacchetto PHP o l’estensione del linguaggio, se la logica vive nell’applicazione.

Se il pacchetto non c’è, non forzare soluzioni vecchie solo per “farlo funzionare”. L’errore classico è installare un modulo legacy che compila o si carica male su EL9 e poi passare ore a inseguire warning inutili. Meglio usare il percorso moderno con .mmdb.

Installazione base del supporto MaxMind

Per il supporto di base installa la libreria e gli strumenti di test. Questo non attiva ancora la geolocalizzazione nel web server, ma ti dà la parte più importante: leggere e validare il database.

sudo dnf install -y libmaxminddb libmaxminddb-utils

Dopo l’installazione, controlla che la libreria sia presente e che gli strumenti rispondano:

rpm -q libmaxminddb libmaxminddb-utils
mmdblookup --help | head

Se mmdblookup c’è, hai già un modo pratico per fare troubleshooting senza coinvolgere subito Nginx o Apache. Questo è utile anche quando il database viene aggiornato da un job esterno e vuoi capire se il file è leggibile, se il formato è corretto e se i record contengono i campi attesi.

Scaricare e posizionare il database GeoLite2

Il database va ottenuto da MaxMind o da una fonte autorizzata equivalente. Non ha senso inventarsi un download casuale: il file deve essere affidabile, aggiornato e con licenza gestita correttamente. Il formato tipico è .mmdb, ad esempio GeoLite2-Country.mmdb o GeoLite2-City.mmdb.

Una collocazione ragionevole è sotto /usr/share/GeoIP/ oppure /var/lib/GeoIP/, con permessi di sola lettura per il servizio che lo usa. Esempio:

sudo mkdir -p /var/lib/GeoIP
sudo install -o root -g root -m 0644 GeoLite2-Country.mmdb /var/lib/GeoIP/GeoLite2-Country.mmdb
ls -l /var/lib/GeoIP/GeoLite2-Country.mmdb

Se il database arriva da un archivio compresso, estrailo prima e verifica hash o dimensione. Il controllo minimo è che il file esista, abbia dimensione plausibile e sia leggibile dal servizio che lo userà.

Test rapido del contenuto con la CLI:

mmdblookup --file /var/lib/GeoIP/GeoLite2-Country.mmdb --ip 8.8.8.8 country names en

Se il comando restituisce un nome di paese, il file è valido e il formato è corretto. Se invece ottieni errori su file corrotto o non supportato, il problema è nel download, nella decompressione o nella versione del database.

Integrazione con Nginx

Con Nginx l’integrazione tipica passa dal modulo ngx_http_geoip2_module, che espone variabili ricavate dal database MaxMind. Su EL9 il modulo può arrivare da repository terzi o da build specifiche, quindi prima verifica la presenza del pacchetto o del modulo già compilato.

Controlla la configurazione caricata:

nginx -V 2>&1 | tr ' ' '
' | grep -i geoip

Se il modulo è disponibile, una configurazione minima può essere simile a questa:

geoip2 /var/lib/GeoIP/GeoLite2-Country.mmdb {
    auto_reload 5m;
    $geoip2_data_country_code country iso_code;
    $geoip2_data_country_name country names en;
}

log_format main_geo '$remote_addr - $geoip2_data_country_code - $request';

Il punto importante è auto_reload: se il database viene sostituito periodicamente, Nginx può ricaricarlo senza restart completo. La frequenza va scelta con criterio: troppo bassa e perdi aggiornamenti, troppo alta e sprechi risorse inutilmente.

Dopo avere modificato la config, valida sempre prima del reload:

sudo nginx -t
sudo systemctl reload nginx

Se il test fallisce, non fare reload “sperando”. Correggi l’errore indicato nel file di configurazione e ripeti il controllo. In produzione il reload di una config rotta è il modo più rapido per trasformare un problema locale in un disservizio visibile.

Integrazione con Apache

Su Apache il percorso cambia in base a come vuoi usare GeoIP. Con moduli dedicati puoi valorizzare variabili di ambiente o arricchire i log, ma spesso la soluzione più pulita è usare il supporto applicativo o un modulo esterno ben mantenuto. L’obiettivo è evitare configurazioni fragili e poco documentate.

Verifica i moduli caricati:

httpd -M | grep -i geo

Se hai un modulo compatibile con MaxMind, la logica è simile: punti al database .mmdb, definisci quali campi vuoi estrarre e poi li consumi nelle direttive di logging o nelle regole applicative. Se il modulo non è disponibile nei repository stabili, non forzare build manuali su un server di produzione senza piano di rollback.

Per il logging, il risultato tipico da ottenere è questo: ogni riga di access log deve includere IP, codice paese e magari ASN o città, se davvero serve. Esempio concettuale:

%h %l %u %t "%r" %>s %b country=%{GEOIP_COUNTRY_CODE}e

Se i campi restano vuoti, il problema non è sempre il database. Può essere il modulo non caricato, la variabile sbagliata o un ordine errato delle direttive. In questi casi i log di Apache e il controllo dei moduli sono più utili di un riavvio alla cieca.

Uso in PHP e nelle applicazioni

Quando la geolocalizzazione serve all’applicazione, PHP è spesso il punto più sensato. Invece di far dipendere il web server da logiche di business, puoi interrogare il database da codice e decidere lì come comportarti. Questo rende più semplice testare, fare cache e cambiare provider in futuro.

Con Composer e una libreria per MaxMind, il flusso tipico è: installi la dipendenza, punti al file .mmdb, leggi l’IP del client e trasformi il risultato in una struttura usabile. Esempio concettuale:

$reader = new GeoIp2\Database
eader('/var/lib/GeoIP/GeoLite2-Country.mmdb');
$record = $reader->country($_SERVER['REMOTE_ADDR']);
echo $record->country->isoCode;

Qui il punto critico è sempre l’IP reale del client. Se hai proxy, CDN o load balancer davanti, non devi leggere ciecamente REMOTE_ADDR. Prima devi definire la catena fidata, altrimenti geolocalizzi l’ultimo hop e non l’utente.

Con PHP-FPM controlla anche i permessi del file database. Se il processo gira come nginx, apache o un utente dedicato, il file deve essere leggibile da quel contesto. Un test utile è verificare l’accesso con lo stesso utente del servizio, non come root.

Test operativo: dal database al risultato HTTP

La verifica finale non è “il pacchetto è installato”, ma “la risposta del sistema cambia in modo atteso”. Se hai integrato GeoIP nel server web, prova una richiesta e osserva l’header, il log o la variabile resa disponibile all’applicazione.

Se hai configurato Nginx per loggare il paese, una richiesta di test potrebbe essere:

curl -I https://example.com

Poi controlli il log accessi nel path configurato, ad esempio /var/log/nginx/access.log, e cerchi il campo paese. Se il dato non compare, non partire dal database: verifica prima la direttiva di logging e il reload del servizio.

Se vuoi testare direttamente il file database, questa è la prova più pulita:

mmdblookup --file /var/lib/GeoIP/GeoLite2-Country.mmdb --ip 1.1.1.1 country iso_code

Il risultato atteso è un codice paese coerente con l’IP interrogato. Se il database risponde bene da CLI ma non nel web server, il problema è quasi sempre nella configurazione del modulo o nei permessi del processo.

Aggiornamento periodico e manutenzione

GeoIP è utile solo se il database resta aggiornato. Gli IP cambiano assegnazione e un database vecchio degrada lentamente la qualità del dato, senza creare errori evidenti. Per questo l’aggiornamento va automatizzato.

Una soluzione semplice è un job giornaliero o settimanale che scarica il nuovo file, lo verifica e poi sostituisce quello in uso con un rename atomico. Il flusso corretto è: download in percorso temporaneo, controllo integrità, copia finale con permessi corretti, eventuale reload del servizio se richiesto dal modulo.

sudo cp GeoLite2-Country.mmdb.new /var/lib/GeoIP/GeoLite2-Country.mmdb
sudo chown root:root /var/lib/GeoIP/GeoLite2-Country.mmdb
sudo chmod 0644 /var/lib/GeoIP/GeoLite2-Country.mmdb

Se usi Nginx con auto reload del database, spesso non serve altro. Se invece il server web carica il file solo all’avvio, pianifica un reload controllato. In entrambi i casi conserva una copia precedente per rollback rapido.

Rollback pratico: rinomina il file nuovo se introduce errori, ripristina il precedente e verifica di nuovo con mmdblookup e con il servizio web. Questa è la parte che evita i problemi più banali: aggiornamento riuscito a metà e geolocalizzazione rotta senza che nessuno se ne accorga subito.

Errori tipici e come leggerli senza perdere tempo

Gli errori più comuni non sono misteriosi. Il file non esiste, il modulo non è caricato, il database è nel formato sbagliato, i permessi non consentono la lettura oppure l’IP analizzato non è quello che pensi. Ogni caso ha una verifica rapida.

  • File mancante: ls -l /var/lib/GeoIP/GeoLite2-Country.mmdb
  • Formato errato: mmdblookup --file ... fallisce subito
  • Modulo non caricato: nginx -V o httpd -M
  • Permessi: test con utente del servizio e controllo di SELinux se presente
  • IP sbagliato: verifica proxy, CDN e header fidati prima di leggere il dato

Su sistemi con SELinux in enforcing, non dimenticare che un file leggibile da Unix può comunque essere bloccato dal contesto di sicurezza. Se il servizio vede il database come “permission denied” anche con chmod corretto, controlla i log di audit e i context del file. La verifica minima è:

ls -Z /var/lib/GeoIP/GeoLite2-Country.mmdb
ausearch -m avc -ts recent

Se il contesto SELinux è incoerente, il fix non è disabilitare SELinux. Il fix è assegnare il contesto corretto o spostare il file in un path già previsto dalla policy del servizio.

Quando conviene non usare GeoIP nel web server

Non sempre conviene mettere GeoIP dentro Nginx o Apache. Se la logica serve solo a livello applicativo, il web server aggiunge complessità senza vantaggio reale. Se invece ti serve solo per report o analisi offline, spesso è meglio elaborare i log a valle, in modo da non dipendere dal database in tempo reale.

La regola pratica è semplice: se la geolocalizzazione influenza routing, redirect o access control, mantienila il più possibile vicino al punto decisionale ma con test e rollback chiari. Se serve solo come arricchimento informativo, centralizzala nell’app o nella pipeline di log.

Su AlmaLinux 9 e Rocky Linux 9 la strada migliore resta quasi sempre questa: libreria MaxMind aggiornata, database .mmdb in un path stabile, integrazione nel punto più adatto al caso d’uso e controlli periodici con mmdblookup e log applicativi. Così GeoIP diventa uno strumento utile, non l’ennesimo componente opaco da rincorrere quando qualcosa smette di tornare.