GeoIP2 no Nginx: geolocalização por IP no Ubuntu, Rocky Linux e Oracle Linux
Identificar aproximadamente a localização de um visitante pelo endereço IP pode ser útil para selecionar idioma, personalizar conteúdo, gerar estatísticas, aplicar regras regionais ou encaminhar dados para uma aplicação.
Uma solução comum é consultar uma API externa. Isso, porém, adiciona latência, dependência de terceiros, limites de requisições e possíveis custos. Com o módulo GeoIP2, o próprio Nginx pode consultar localmente as bases da MaxMind e disponibilizar os resultados como variáveis.
Neste guia, configuraremos:
- país e código ISO;
- estado ou região;
- cidade;
- código postal;
- latitude e longitude;
- encaminhamento dos dados para aplicações PHP, Node.js e Next.js;
- instalação no Ubuntu, Rocky Linux e Oracle Linux;
- atualização automática das bases GeoLite2;
- tratamento correto do IP quando há Cloudflare ou outro proxy reverso.
A localização obtida por IP é aproximada. Ela não equivale ao GPS do dispositivo e não deve ser usada como prova da localização exata de uma pessoa.
Como a solução funciona
O fluxo será este:
- O visitante se conecta ao Nginx.
- O Nginx obtém o IP remoto da conexão.
- O módulo
ngx_http_geoip2_moduleconsulta uma base.mmdbda MaxMind. - Os resultados são armazenados em variáveis do Nginx.
- Essas variáveis podem ser usadas em logs, regras, cabeçalhos HTTP, FastCGI ou
proxy_pass.
A consulta acontece localmente e não exige uma chamada externa para cada acesso.
GeoIP antigo e GeoIP2 não são a mesma coisa
Não confunda estes módulos:
ngx_http_geoip_module: módulo antigo, baseado nas bases GeoIP legadas;ngx_http_geoip2_module: módulo atual, compatível com arquivos MaxMind DB no formato.mmdb.
Este artigo utiliza exclusivamente o GeoIP2.
1. Verifique se o módulo GeoIP2 já está disponível
Execute:
nginx -V 2>&1 | grep -i geoipTambém procure módulos dinâmicos já instalados:
find /usr/lib64/nginx /usr/lib/nginx /etc/nginx/modules \
-type f -iname '*geoip2*.so' 2>/dev/nullSe aparecer algo semelhante a:
ngx_http_geoip2_module.soo módulo já está instalado. Verifique se ele é carregado no início do /etc/nginx/nginx.conf:
load_module modules/ngx_http_geoip2_module.so;Dependendo do pacote e da distribuição, o caminho também pode ser absoluto:
load_module /usr/lib64/nginx/modules/ngx_http_geoip2_module.so;Teste a configuração:
sudo nginx -tO comando
nginx -Vnem sempre lista módulos carregados dinamicamente. Por isso, também é importante procurar o arquivo.soe verificar as diretivasload_module.
2. Instale a biblioteca MaxMind DB
O módulo do Nginx depende da biblioteca libmaxminddb.
Ubuntu e Debian
sudo apt update
sudo apt install -y libmaxminddb0 libmaxminddb-dev mmdb-bin geoipupdateO comando de teste será:
mmdblookup --versionRocky Linux 8, 9 ou 10
Instale o EPEL e as ferramentas necessárias:
sudo dnf install -y epel-release
sudo dnf install -y libmaxminddb libmaxminddb-devel geoipupdate git gcc make wget tarSe algum pacote não for encontrado, confira os repositórios ativos:
sudo dnf repolist
sudo dnf search maxmindNo Rocky Linux 9, também pode ser necessário habilitar o CRB:
sudo dnf config-manager --set-enabled crbNo Rocky Linux 8, o repositório equivalente normalmente é chamado PowerTools:
sudo dnf config-manager --set-enabled powertoolsDepois, repita a instalação:
sudo dnf install -y libmaxminddb libmaxminddb-devel geoipupdateOracle Linux 8, 9 ou 10
Habilite o repositório de desenvolvimento compatível com a sua versão.
No Oracle Linux 9:
sudo dnf config-manager --enable ol9_codeready_builderNo Oracle Linux 8:
sudo dnf config-manager --enable ol8_codeready_builderInstale o EPEL fornecido para Oracle Linux quando disponível:
sudo dnf install -y oracle-epel-release-el9No Oracle Linux 8, use:
sudo dnf install -y oracle-epel-release-el8Em seguida:
sudo dnf install -y libmaxminddb libmaxminddb-devel geoipupdate git gcc make wget tarNo Oracle Linux 10, os nomes dos repositórios podem variar conforme a imagem e os repositórios habilitados. Consulte as opções disponíveis:
sudo dnf repolist all | grep -Ei 'code|developer|epel'
sudo dnf search libmaxminddbCaso libmaxminddb-devel não esteja disponível, habilite o repositório de desenvolvimento correspondente mostrado pelo comando anterior.
3. Instale o módulo GeoIP2 do Nginx
A instalação depende da origem do seu Nginx. Um módulo dinâmico precisa ser binariamente compatível com a versão e com os parâmetros usados para compilar o Nginx instalado.
Opção A: usar um pacote da distribuição
Primeiro, pesquise se sua distribuição oferece um pacote pronto:
sudo dnf search nginx | grep -i geoipou, no Ubuntu:
apt search nginx | grep -i geoipSe existir um pacote explicitamente chamado GeoIP2, prefira-o. Não instale o módulo chamado apenas geoip pensando que ele é equivalente: normalmente esse é o módulo legado.
Após instalar, localize o arquivo:
find /usr/lib64/nginx /usr/lib/nginx /etc/nginx/modules \
-type f -iname '*geoip2*.so' 2>/dev/nullOpção B: compilar um módulo dinâmico compatível
Esta é a opção mais universal para Rocky Linux e Oracle Linux quando não há um RPM pronto.
3.1 Descubra a versão e os argumentos do Nginx
nginx -v
nginx -V 2>&1Guarde a versão exibida. Exemplo:
nginx version: nginx/1.28.0O código-fonte usado na compilação precisa corresponder à versão instalada.
Defina a versão em uma variável:
NGINX_VERSION="$(nginx -v 2>&1 | sed -E 's#nginx version: nginx/##')"
echo "$NGINX_VERSION"3.2 Instale as dependências de compilação
No Rocky Linux e Oracle Linux:
sudo dnf groupinstall -y "Development Tools"
sudo dnf install -y \
git wget tar gcc make \
pcre2-devel zlib-devel openssl-devel \
libmaxminddb-develEm algumas versões, o pacote de compatibilidade do zlib pode ser necessário:
sudo dnf install -y zlib-ng-compat-devel3.3 Baixe os códigos-fonte
cd /usr/local/src
sudo wget "https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz"
sudo tar -xzf "nginx-${NGINX_VERSION}.tar.gz"
sudo git clone --depth 1 \
https://github.com/leev/ngx_http_geoip2_module.git3.4 Compile somente o módulo
Entre no diretório do Nginx:
cd "/usr/local/src/nginx-${NGINX_VERSION}"Copie os argumentos exibidos por nginx -V, mantendo os parâmetros originais e acrescentando:
--with-compat --add-dynamic-module=/usr/local/src/ngx_http_geoip2_moduleExemplo simplificado:
sudo ./configure \
--with-compat \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--add-dynamic-module=/usr/local/src/ngx_http_geoip2_module
sudo make modulesO resultado será criado em:
objs/ngx_http_geoip2_module.soPara evitar o erro
module is not binary compatible, utilize a mesma versão do Nginx e preserve os argumentos relevantes mostrados pornginx -V. Não substitua cegamente os parâmetros da sua instalação pelo exemplo simplificado acima.
3.5 Instale o módulo
Descubra o diretório de módulos configurado no Nginx:
nginx -V 2>&1 | grep -oE -- '--modules-path=[^ ]+'Em sistemas RPM, ele costuma ser:
/usr/lib64/nginx/modulesCrie o diretório e copie o módulo:
sudo mkdir -p /usr/lib64/nginx/modules
sudo cp objs/ngx_http_geoip2_module.so /usr/lib64/nginx/modules/
sudo chmod 755 /usr/lib64/nginx/modules/ngx_http_geoip2_module.soNo início de /etc/nginx/nginx.conf, antes do bloco events, adicione:
load_module /usr/lib64/nginx/modules/ngx_http_geoip2_module.so;Teste:
sudo nginx -tAtenção às atualizações do Nginx
Quando o Nginx é atualizado para outra versão, um módulo compilado manualmente pode deixar de ser compatível. Depois de uma atualização:
sudo nginx -tSe aparecer module is not binary compatible, recompile o módulo usando exatamente a nova versão do Nginx.
4. Crie uma conta gratuita na MaxMind
As bases GeoLite2 são gratuitas, mas exigem uma conta MaxMind e uma chave de licença.
No painel da MaxMind:
- crie ou acesse sua conta;
- gere uma nova license key;
- anote o
AccountIDe a chave; - não publique a chave no Git, em imagens Docker ou em artigos.
Usaremos as bases:
GeoLite2-Country;GeoLite2-City.
A base City já contém informações de país, mas manter Country separada pode ser útil em instalações que desejam uma base menor para determinadas consultas.
5. Configure o geoipupdate
Edite o arquivo de configuração:
sudo nano /etc/GeoIP.confUse este modelo:
AccountID SEU_ACCOUNT_ID
LicenseKey SUA_LICENSE_KEY
EditionIDs GeoLite2-Country GeoLite2-City
DatabaseDirectory /var/lib/GeoIPProteja o arquivo:
sudo chmod 600 /etc/GeoIP.conf
sudo chown root:root /etc/GeoIP.confCrie o diretório das bases:
sudo mkdir -p /var/lib/GeoIPBaixe ou atualize as bases:
sudo geoipupdateConfira os arquivos:
ls -lh /var/lib/GeoIP/A saída deverá conter arquivos como:
GeoLite2-City.mmdb
GeoLite2-Country.mmdb6. Teste a base pela linha de comando
Escolha um IP público para o teste:
mmdblookup \
--file /var/lib/GeoIP/GeoLite2-City.mmdb \
--ip 8.8.8.8Para consultar apenas o código do país:
mmdblookup \
--file /var/lib/GeoIP/GeoLite2-City.mmdb \
--ip 8.8.8.8 \
country iso_codePara consultar o nome da cidade em português, quando disponível:
mmdblookup \
--file /var/lib/GeoIP/GeoLite2-City.mmdb \
--ip 8.8.8.8 \
city names pt-BRNem todos os registros possuem cidade, CEP ou coordenadas. Por isso, sempre defina valores padrão na configuração do Nginx.
7. Permissões e SELinux no Rocky Linux e Oracle Linux
O processo do Nginx precisa conseguir ler os arquivos .mmdb.
Aplique permissões seguras:
sudo chown -R root:root /var/lib/GeoIP
sudo find /var/lib/GeoIP -type d -exec chmod 755 {} \;
sudo find /var/lib/GeoIP -type f -name '*.mmdb' -exec chmod 644 {} \;Verifique o SELinux:
getenforceSe estiver em Enforcing, atribua um contexto legível pelo Nginx:
sudo semanage fcontext -a -t httpd_sys_content_t "/var/lib/GeoIP(/.*)?"
sudo restorecon -Rv /var/lib/GeoIPSe semanage não existir:
sudo dnf install -y policycoreutils-python-utilsConfira o contexto:
ls -lZ /var/lib/GeoIP/Não desative o SELinux para resolver um problema de permissão. Corrija o contexto do arquivo.
8. Configure as variáveis GeoIP2 no Nginx
Crie um arquivo dedicado:
sudo nano /etc/nginx/conf.d/geoip2.confAdicione:
geoip2 /var/lib/GeoIP/GeoLite2-City.mmdb auto_reload=5m {
$geoip2_country_code default=-- source=$remote_addr country iso_code;
$geoip2_country_name default=Unknown source=$remote_addr country names pt-BR;
$geoip2_region_code default=-- source=$remote_addr subdivisions 0 iso_code;
$geoip2_region_name default=Unknown source=$remote_addr subdivisions 0 names pt-BR;
$geoip2_city_name default=Unknown source=$remote_addr city names pt-BR;
$geoip2_postal_code default=-- source=$remote_addr postal code;
$geoip2_latitude default=0 source=$remote_addr location latitude;
$geoip2_longitude default=0 source=$remote_addr location longitude;
$geoip2_time_zone default=Unknown source=$remote_addr location time_zone;
$geoip2_accuracy_radius default=0 source=$remote_addr location accuracy_radius;
}O parâmetro:
auto_reload=5mfaz o módulo verificar periodicamente se a base foi substituída, evitando a necessidade de reiniciar o Nginx após cada atualização.
Fallback para nomes em inglês
Nem todas as localidades têm tradução pt-BR. Para garantir um nome, você pode criar duas variáveis e usar map:
geoip2 /var/lib/GeoIP/GeoLite2-City.mmdb auto_reload=5m {
$geoip2_city_pt source=$remote_addr city names pt-BR;
$geoip2_city_en source=$remote_addr city names en;
}
map $geoip2_city_pt $geoip2_city_name {
"" $geoip2_city_en;
default $geoip2_city_pt;
}As diretivas
geoip2emappertencem ao contextohttp. Em instalações comuns, arquivos de/etc/nginx/conf.d/*.confsão incluídos dentro desse bloco. Não coloque essas diretivas dentro deserveroulocation.
Teste:
sudo nginx -t
sudo systemctl reload nginx9. Exponha os dados em uma rota de teste
Dentro de um bloco server, crie temporariamente:
location = /geoip-debug {
default_type application/json;
return 200 '{
"ip": "$remote_addr",
"countryCode": "$geoip2_country_code",
"country": "$geoip2_country_name",
"regionCode": "$geoip2_region_code",
"region": "$geoip2_region_name",
"city": "$geoip2_city_name",
"postalCode": "$geoip2_postal_code",
"latitude": "$geoip2_latitude",
"longitude": "$geoip2_longitude",
"timeZone": "$geoip2_time_zone",
"accuracyRadiusKm": "$geoip2_accuracy_radius"
}';
}Teste:
curl https://seu-dominio.com/geoip-debugRemova essa rota depois dos testes. Expor dados de depuração publicamente sem necessidade não é recomendável.
10. Envie os dados para uma aplicação com proxy_pass
Para Node.js, Next.js, Bun, NestJS ou qualquer aplicação atrás de proxy reverso:
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-GeoIP-Country-Code $geoip2_country_code;
proxy_set_header X-GeoIP-Country-Name $geoip2_country_name;
proxy_set_header X-GeoIP-Region-Code $geoip2_region_code;
proxy_set_header X-GeoIP-Region-Name $geoip2_region_name;
proxy_set_header X-GeoIP-City $geoip2_city_name;
proxy_set_header X-GeoIP-Postal-Code $geoip2_postal_code;
proxy_set_header X-GeoIP-Latitude $geoip2_latitude;
proxy_set_header X-GeoIP-Longitude $geoip2_longitude;
proxy_set_header X-GeoIP-Time-Zone $geoip2_time_zone;
proxy_set_header X-GeoIP-Accuracy-Radius $geoip2_accuracy_radius;
}Lendo os cabeçalhos no Next.js
Em um Server Component, Route Handler ou Server Action:
import { headers } from "next/headers";
type GeoLocation = {
countryCode: string | null;
countryName: string | null;
regionCode: string | null;
regionName: string | null;
city: string | null;
postalCode: string | null;
latitude: number | null;
longitude: number | null;
timeZone: string | null;
accuracyRadiusKm: number | null;
};
function parseNumber(value: string | null): number | null {
if (value === null || value.trim() === "") {
return null;
}
const parsed = Number(value);
return Number.isFinite(parsed) ? parsed : null;
}
export async function getGeoLocation(): Promise<GeoLocation> {
const requestHeaders = await headers();
return {
countryCode: requestHeaders.get("x-geoip-country-code"),
countryName: requestHeaders.get("x-geoip-country-name"),
regionCode: requestHeaders.get("x-geoip-region-code"),
regionName: requestHeaders.get("x-geoip-region-name"),
city: requestHeaders.get("x-geoip-city"),
postalCode: requestHeaders.get("x-geoip-postal-code"),
latitude: parseNumber(requestHeaders.get("x-geoip-latitude")),
longitude: parseNumber(requestHeaders.get("x-geoip-longitude")),
timeZone: requestHeaders.get("x-geoip-time-zone"),
accuracyRadiusKm: parseNumber(
requestHeaders.get("x-geoip-accuracy-radius"),
),
};
}Esses cabeçalhos só devem ser considerados confiáveis quando a aplicação não está exposta diretamente à internet e recebe tráfego exclusivamente pelo Nginx.
11. Envie os dados para PHP com FastCGI
Em uma configuração PHP-FPM:
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php-fpm/www.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param GEOIP_COUNTRY_CODE $geoip2_country_code;
fastcgi_param GEOIP_COUNTRY_NAME $geoip2_country_name;
fastcgi_param GEOIP_REGION_NAME $geoip2_region_name;
fastcgi_param GEOIP_CITY $geoip2_city_name;
fastcgi_param GEOIP_LATITUDE $geoip2_latitude;
fastcgi_param GEOIP_LONGITUDE $geoip2_longitude;
}No PHP:
<?php
$countryCode = $_SERVER['GEOIP_COUNTRY_CODE'] ?? null;
$countryName = $_SERVER['GEOIP_COUNTRY_NAME'] ?? null;
$city = $_SERVER['GEOIP_CITY'] ?? null;12. Use os dados no access log
Crie um formato de log personalizado no contexto http:
log_format geoip_combined
'$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'country=$geoip2_country_code '
'region="$geoip2_region_name" '
'city="$geoip2_city_name"';No servidor virtual:
access_log /var/log/nginx/access_geoip.log geoip_combined;Depois:
sudo nginx -t
sudo systemctl reload nginxEvite registrar latitude, longitude e outras informações desnecessárias se isso não tiver uma finalidade legítima. Logs também estão sujeitos a requisitos de privacidade e retenção.
13. Cloudflare, balanceadores e proxies: restaure o IP real primeiro
Quando o Nginx está atrás da Cloudflare, de um load balancer ou de outro proxy, $remote_addr pode representar o endereço do proxy. Nesse caso, o GeoIP retornará a localização do datacenter, não a do visitante.
Com Cloudflare, configure o módulo Real IP do Nginx e confie somente nas redes oficiais da Cloudflare.
Exemplo estrutural:
# Inclua aqui todas as faixas IPv4 e IPv6 oficiais e atuais da Cloudflare.
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
# ...demais redes oficiais...
real_ip_header CF-Connecting-IP;
real_ip_recursive on;Depois que o Real IP estiver corretamente configurado, $remote_addr passa a representar o visitante e pode ser usado como source nas diretivas GeoIP2.
Não configure algo como:
set_real_ip_from 0.0.0.0/0;Isso permitiria que qualquer cliente falsificasse o IP por meio de cabeçalhos HTTP.
Se o seu provedor já informa o IP em outro cabeçalho, adapte real_ip_header e restrinja set_real_ip_from aos IPs ou redes do proxy confiável.
14. Atualização automática das bases
As bases GeoLite2 precisam ser mantidas atualizadas. O geoipupdate pode ser executado periodicamente por systemd.
Crie o serviço:
sudo nano /etc/systemd/system/geoipupdate.service[Unit]
Description=Atualiza as bases GeoLite2 da MaxMind
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/bin/geoipupdateConfirme o caminho do programa:
command -v geoipupdateSe for diferente, ajuste o ExecStart.
Crie o timer:
sudo nano /etc/systemd/system/geoipupdate.timer[Unit]
Description=Atualização semanal das bases GeoLite2
[Timer]
OnCalendar=Sun *-*-* 04:15:00
Persistent=true
RandomizedDelaySec=30m
[Install]
WantedBy=timers.targetAtive:
sudo systemctl daemon-reload
sudo systemctl enable --now geoipupdate.timerConfira:
systemctl list-timers geoipupdate.timer
sudo systemctl start geoipupdate.service
sudo journalctl -u geoipupdate.service --no-pagerComo configuramos auto_reload=5m, o Nginx reconhecerá os novos arquivos automaticamente.
15. Diagnóstico de problemas comuns
unknown directive "geoip2"
O módulo não foi carregado.
Verifique:
sudo nginx -T 2>&1 | grep -i load_module
find /usr/lib64/nginx /usr/lib/nginx -iname '*geoip2*.so' 2>/dev/nullConfirme que a diretiva load_module aparece antes do bloco events.
module is not binary compatible
O módulo foi compilado para outra versão ou com parâmetros incompatíveis.
Solução: recompile usando a mesma versão e os argumentos do Nginx exibidos por:
nginx -V 2>&1MMDB_open ... Permission denied
Verifique permissões e SELinux:
namei -l /var/lib/GeoIP/GeoLite2-City.mmdb
ls -lZ /var/lib/GeoIP/
sudo ausearch -m AVC -ts recentReaplique o contexto:
sudo restorecon -Rv /var/lib/GeoIPCidade aparece como Unknown
Isso pode ser normal. Nem todo IP possui resolução de cidade, e redes móveis, VPNs, CGNAT e provedores regionais podem reduzir a precisão.
Teste diretamente:
mmdblookup \
--file /var/lib/GeoIP/GeoLite2-City.mmdb \
--ip IP_PUBLICO_DO_VISITANTE \
city names enO resultado mostra a localização da Cloudflare
O Nginx ainda está usando o IP do proxy. Configure real_ip_header, set_real_ip_from e real_ip_recursive antes da consulta GeoIP2.
Funciona no terminal, mas não no Nginx
O usuário do Nginx ou o domínio SELinux pode não ter acesso ao arquivo. Descubra o usuário:
ps -eo user,group,comm | grep nginxDepois confira todas as permissões do caminho:
namei -l /var/lib/GeoIP/GeoLite2-City.mmdb16. Segurança e privacidade
Algumas recomendações importantes:
- não trate GeoIP como localização exata;
- não tome decisões críticas apenas com base no país ou cidade detectados;
- não confie em cabeçalhos GeoIP enviados diretamente pelo cliente;
- mantenha a aplicação acessível apenas pelo proxy reverso;
- não exponha sua chave MaxMind;
- não registre dados além do necessário;
- informe o uso de geolocalização aproximada em sua política de privacidade quando aplicável;
- permita fallback manual de idioma ou região;
- considere que VPN, Tor, redes móveis e CGNAT alteram ou reduzem a precisão.
Configuração final resumida
O arquivo /etc/nginx/conf.d/geoip2.conf pode ficar assim:
geoip2 /var/lib/GeoIP/GeoLite2-City.mmdb auto_reload=5m {
$geoip2_country_code default=-- source=$remote_addr country iso_code;
$geoip2_country_name default=Unknown source=$remote_addr country names pt-BR;
$geoip2_region_code default=-- source=$remote_addr subdivisions 0 iso_code;
$geoip2_region_name default=Unknown source=$remote_addr subdivisions 0 names pt-BR;
$geoip2_city_name default=Unknown source=$remote_addr city names pt-BR;
$geoip2_postal_code default=-- source=$remote_addr postal code;
$geoip2_latitude default=0 source=$remote_addr location latitude;
$geoip2_longitude default=0 source=$remote_addr location longitude;
$geoip2_time_zone default=Unknown source=$remote_addr location time_zone;
$geoip2_accuracy_radius default=0 source=$remote_addr location accuracy_radius;
}E o proxy para uma aplicação Next.js:
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-GeoIP-Country-Code $geoip2_country_code;
proxy_set_header X-GeoIP-Country-Name $geoip2_country_name;
proxy_set_header X-GeoIP-Region-Code $geoip2_region_code;
proxy_set_header X-GeoIP-Region-Name $geoip2_region_name;
proxy_set_header X-GeoIP-City $geoip2_city_name;
proxy_set_header X-GeoIP-Postal-Code $geoip2_postal_code;
proxy_set_header X-GeoIP-Latitude $geoip2_latitude;
proxy_set_header X-GeoIP-Longitude $geoip2_longitude;
proxy_set_header X-GeoIP-Time-Zone $geoip2_time_zone;
proxy_set_header X-GeoIP-Accuracy-Radius $geoip2_accuracy_radius;
}Finalize sempre com:
sudo nginx -t
sudo systemctl reload nginxConclusão
O GeoIP2 permite que o Nginx identifique informações aproximadas de localização sem consultar uma API externa em cada requisição. A solução é rápida, local e especialmente útil em arquiteturas nas quais o Nginx já funciona como proxy reverso para PHP, Node.js ou Next.js.
Os pontos mais importantes são utilizar o módulo GeoIP2 — e não o módulo GeoIP legado —, manter as bases atualizadas, preservar a compatibilidade binária do módulo e restaurar corretamente o IP do visitante quando houver Cloudflare ou outro proxy à frente do Nginx.
Referências
- Artigo que inspirou este guia: https://dev.to/gbhorwood/nginx-doing-ip-geolocation-right-in-nginx-442h
- Módulo GeoIP2 para Nginx: https://github.com/leev/ngx_http_geoip2_module
- GeoLite2 e documentação da MaxMind: https://dev.maxmind.com/geoip/geolite2-free-geolocation-data/
- Atualização das bases MaxMind: https://dev.maxmind.com/geoip/updating-databases/
- Nginx no Rocky Linux: https://docs.rockylinux.org/guides/web/nginx-mainline/
- Nginx no Oracle Linux: https://docs.oracle.com/en/learn/ol-nginx/