Configurar GeoIP2 en Nginx detrás de Nginx Proxy Manager (NPM)

Introducción
En este artículo quiero mostrar cómo configurar GeoIP2 en Nginx cuando el servidor web se encuentra detrás de un proxy inverso administrado mediante Nginx Proxy Manager (NPM).
El objetivo es identificar la IP real de los visitantes, conocer su país y ciudad, y posteriormente utilizar esta información para generar estadísticas o alertas de seguridad.
Arquitectura
La arquitectura utilizada es la siguiente:
Cliente → Nginx Proxy Manager (NPM) → Nginx Backend
NPM recibe las conexiones HTTPS desde Internet y las reenvía hacia un servidor Nginx interno.
Configurando la IP real del visitante
Como el servidor se encuentra detrás de Nginx Proxy Manager, inicialmente Nginx registraba la IP privada del proxy en lugar de la IP pública del visitante.
Para solucionarlo agregué al archivo /etc/nginx/sites-available/misitio dentro del bloque server {}:
set_real_ip_from 192.0.2.255;
real_ip_header X-Forwarded-For;
real_ip_recursive on;Donde 192.0.2.255 corresponde a la IP interna de mi servidor Nginx Proxy Manager.
Posteriormente validé la configuración:
nginx -tY recargué el servicio:
systemctl reload nginxVerificando la IP real del visitante
Una vez aplicada la configuración, verifiqué el contenido del log:
tail -f /var/log/nginx/access.logComencé a observar registros similares a:
198.51.100.0 - - [16/Jun/2026:11:19:11 -0300] "GET /favicon.ico HTTP/1.1" 200
203.0.113.0 - - [16/Jun/2026:11:20:01 -0300] "GET /api/live/matches HTTP/1.1" 304
Como aparecen direcciones IP públicas reales y no la IP privada de NPM, confirmé que el proxy estaba reenviando correctamente la información del cliente.
Instalación del módulo GeoIP2
Instalé el módulo GeoIP2 para Nginx:
apt update
apt install libnginx-mod-http-geoip2
Luego verifiqué que el módulo estuviera cargado:
nginx -T | grep load_module
Resultado:
load_module modules/ngx_http_geoip2_module.so;
Descarga de las bases GeoLite2
Registré una cuenta gratuita en MaxMind y descargué:
GeoLite2-Country.mmdb
GeoLite2-City.mmdb
Creé el directorio:
mkdir -p /etc/nginx/geoip
Y copié los archivos:
cp GeoLite2-Country.mmdb /etc/nginx/geoip/
cp GeoLite2-City.mmdb /etc/nginx/geoip/
Configuración de GeoIP2 en Nginx
Dentro del bloque http {} del archivo /etc/nginx/nginx.conf agregué:
geoip2 /etc/nginx/geoip/GeoLite2-Country.mmdb {
auto_reload 5m;
$geoip2_country_code country iso_code;
$geoip2_country_name country names en;
}
geoip2 /etc/nginx/geoip/GeoLite2-City.mmdb {
auto_reload 5m;
$geoip2_city_name city names en;
}
Endpoint de prueba
Para validar la configuración agregué al archivo /etc/nginx/sites-available/misitio dentro del bloque server {}:
location /geoiptest {
default_type text/plain;
return 200 "$remote_addr | $geoip2_country_code | $geoip2_country_name | $geoip2_city_name\n";
}
Luego validé la configuración:
nginx -t
systemctl reload nginx
Al acceder a:
https://misitio.com/geoiptest
obtuve:
192.0.2.0 | UY | Uruguay | Montevideo
Lo que confirmó que GeoIP2 estaba funcionando correctamente.
Incorporando GeoIP al access.log
La configuración del formato de log debe realizarse dentro del bloque http {} del archivo:
/etc/nginx/nginx.confAgregué el siguiente formato personalizado:
log_format geoip '$remote_addr [$time_local] '
'$geoip2_country_code '
'$geoip2_country_name '
'$geoip2_city_name '
'"$request" $status';Luego configuré el archivo de log para utilizar dicho formato.
Esto puede hacerse de forma global dentro del bloque http {} en /etc/nginx/nginx.conf:
access_log /var/log/nginx/access.log geoip;o de forma específica para un sitio dentro del bloque server {} ubicado normalmente en:
/etc/nginx/sites-available/misitioo
/etc/nginx/sites-enabled/misitioEjemplo:
server {
access_log /var/log/nginx/access.log geoip;
...
}Después de aplicar los cambios validé la configuración:
nginx -tY recargué Nginx:
systemctl reload nginxLos registros comenzaron a verse así:
198.52.100.255 [16/Jun/2026:13:15:00 -0300] UY Uruguay Montevideo "GET / HTTP/1.1" 200A partir de este momento cada acceso queda registrado junto con el país y la ciudad del visitante obtenidos mediante GeoIP2.
Además, si tienes varios virtual hosts detrás de NPM, probablemente te convenga definir el log_format geoip en /etc/nginx/nginx.conf (una sola vez) y luego activar access_log ... geoip; únicamente en los sitios donde quieras registrar geolocalización. Esto te da más flexibilidad para el futuro.
Conclusión
La combinación de Nginx Proxy Manager, Nginx y GeoIP2 permite obtener información geográfica de los visitantes con muy poco consumo de recursos. Esta información puede utilizarse tanto para análisis de tráfico como para mejorar la seguridad del servidor mediante sistemas de monitoreo y alertas.
¡Salud y buen blogging!
— Valerka (Montevideo, Uruguay)
¿Te gustó el post? ¿Dudas, comentarios o querés compartir tu experiencia?
Escribime a: valerkasystem@protonmail.com — ¡Siempre leo los mails y trato de responder cuando puedo!