Как включить GeoIP в Nginx: переменные для логов и заголовков
Запрос «как включить GeoIP в Nginx и получить переменные для логов и заголовков» чаще всего всплывает у тех, кто ведёт аудит трафика на VPS: нужно видеть страну/город в access.log или прокинуть страну в приложение (например, Bitrix за Apache). В конце будет рабочая конфигурация для BitrixVM (nginx+httpd), проверка, и список типичных проблем.
В чём проблема
Симптом обычно один из этих:
1) В конфиг добавили geoip_country / geoip_city, а Nginx на перезагрузке падает:
nginx: [emerg] unknown directive "geoip\_country" in /etc/nginx/nginx.conf:XX
- Или модуль подключили, но переменные пустые — в логах вместо страны -:
1.2.3.4 - - [16/Feb/2026:12:10:11 +0000] "GET / HTTP/2.0" 200 123 "-" "-" country=- city=-
Причины ровно две:
- Модуль не загружен (динамические модули подключаются через load_module, иначе директивы неизвестны). Официальный модуль называется ngx_http_geoip_module и создаёт переменные на основе баз MaxMind. (nginx.org)
- Нет базы или она не в том формате. Важно: legacy GeoLite (.dat) давно сняты с раздачи, MaxMind официально прекратил GeoLite Legacy. Поэтому старые команды с GeoIP.dat.gz по прямым ссылкам сегодня чаще мёртвые, чем живые. (MaxMind)
Ещё по современности (2025–2026): если вам нужна актуальная бесплатная геобаза, это GeoLite2 (MMDB) и по сути это уже модуль GeoIP2 (в NGINX Plus он официальный). (docs.nginx.com)
Но в BitrixVM обычно стоит open source Nginx — там штатный модуль ngx_http_geoip_module работает с legacy-форматом. Поэтому ниже — два практичных пути: (A) включить legacy GeoIP модуль с .dat, если база у вас есть (коммерческая/внутренняя), (B) если у вас NGINX Plus — включить GeoIP2 как правильный вариант на будущее.
Рабочее решение
Ниже шаги ориентированы на BitrixVM 9+ (CentOS Stream 9+, nginx + httpd). Все команды выполняются из-под root , sudo не используем.
1) Убедиться, что Nginx установлен из официального репозитория
Официальные пакеты Nginx ставятся из репозитория nginx.org. Инструкция по подключению репозитория — на сайте NGINX. (nginx.org)
Проверка:
nginx -v
rpm -qa | grep -E '^nginx'
Если Nginx не из nginx.org — дальше тоже можно жить, но пакеты модулей и путь к .so могут отличаться.
2) Установить динамический модуль GeoIP (legacy)
Пакет модуля на RHEL/CentOS-семействе обычно называется nginx-module-geoip (динамический модуль). Сам принцип — модуль ставится отдельно, затем подключается через load_module. (nginx.org)
Команды:
dnf makecache
dnf install -y nginx-module-geoip
Проверим, что файл модуля появился:
ls -la /usr/lib64/nginx/modules | grep geoip || true
Ожидаемо увидеть что-то вроде:
ngx\_http\_geoip\_module.so
3) Подготовить каталог под базы GeoIP
Создадим каталог, куда будем класть базы (как минимум country, опционально city):
mkdir -p /etc/nginx/geoip
chmod 0755 /etc/nginx/geoip
Важное примечание про базы (без розовых очков)
- Официальный модуль ngx_http_geoip_module ожидает предкомпилированные базы MaxMind legacy формата. (nginx.org)
- Бесплатные GeoLite Legacy базы официально прекращены (их больше не обновляют и не раздают). (MaxMind)
Что делать на практике:
- Если у вас уже есть GeoIP.dat / GeoLiteCity.dat (из старых проектов, из внутреннего артефакт-хранилища, из коммерческой подписки) — кладём их в /etc/nginx/geoip/.
- Если нет — не тратьте время на “магические” левые ссылки: проще и правильнее перейти на GeoIP2 (см. путь B ниже) или использовать GeoIP только для грубой аналитики через внешний сервис.
Для варианта A предполагаем, что файлы у вас есть:
пример: вы загрузили базы сами и положили в каталог
ls -la /etc/nginx/geoip
Ожидаемые имена (можно свои, главное путь правильно указать в конфиге):
- /etc/nginx/geoip/GeoIP.dat
- /etc/nginx/geoip/GeoLiteCity.dat
4) Подключить модуль и базы в конфиге Nginx (BitrixVM)
Где править в BitrixVM
В BitrixVM конфигурация обычно разнесена, но базовый путь стандартный:
- главный файл: /etc/nginx/nginx.conf
- дополнительные: /etc/nginx/conf.d/*.conf (и/или bitrix-специфичные include)
Нам важно соблюсти правило Nginx: load_module допускается только в основном контексте (верх файла, до events {} / http {}). (nginx.org)
Сделаем аккуратно: создадим отдельный файл и подключим его в nginx.conf, если у вас уже есть include для модулей. Если include нет — вставьте строку load_module прямо в начало nginx.conf.
Вариант 1 (предпочтительно): отдельный файл
Создаём /etc/nginx/conf.d/00-geoip-load.conf (если у вас conf.d инклюдится в main-контексте — это редкость). В большинстве схем conf.d подключается внутри http {}, поэтому этот вариант может не сработать.
Вариант 2 (надёжно): правим /etc/nginx/nginx.conf
Открываем /etc/nginx/nginx.conf и добавляем в самое начало:
load\_module "/usr/lib64/nginx/modules/ngx\_http\_geoip\_module.so";
Дальше — внутри http {} добавляем пути к базам:
http {
geoip\_country /etc/nginx/geoip/GeoIP.dat;
geoip\_city /etc/nginx/geoip/GeoLiteCity.dat;
...
}
Это включает переменные $geoip_country_code, $geoip_country_name и пачку city-переменных. Список переменных и назначение описаны в документации модуля. (nginx.org)
5) Добавить GeoIP в access.log и прокинуть заголовки к Apache/приложению
5.1. Логирование (быстро увидеть пользу)
В http {} определим формат лога, где будут страна/город:
log\_format main\_geoip '$remote\_addr - $remote\_user [$time\_local] '
'"$request" $status $body\_bytes\_sent '
'"$http\_referer" "$http\_user\_agent" '
'country=$geoip\_country\_code country\_name="$geoip\_country\_name" '
'city="$geoip\_city" lat=$geoip\_latitude lon=$geoip\_longitude';
И используем его для access.log:
access\_log /var/log/nginx/access.log main\_geoip;
Если у вас уже задан свой log_format в BitrixVM — не ломайте чужое. Добавьте новый main_geoip и подключите его точечно на нужном server {} через access_log ... main_geoip;.
5.2. Заголовки в апстрим (nginx -> httpd -> Bitrix)
Если Nginx проксирует в Apache (типично для BitrixVM), вы можете прокинуть страну/город в бекенд заголовками. В вашем server {} или location ~ .php$ (где стоит proxy_pass или upstream на httpd) добавьте:
proxy\_set\_header X-GeoIP-Country $geoip\_country\_code;
proxy\_set\_header X-GeoIP-Country-Name $geoip\_country\_name;
proxy\_set\_header X-GeoIP-City $geoip\_city;
Так приложение сможет читать это из $_SERVER['HTTP_X_GEOIP_COUNTRY'] и т.д.
6) Если перед Nginx есть прокси/балансировщик: geoip_proxy
Если Nginx стоит не “на краю”, а за прокси (Cloudflare, ELB, внешний балансировщик), GeoIP будет смотреть на IP прокси, а не клиента. Для этого модуль поддерживает geoip_proxy и geoip_proxy_recursive и учитывает X-Forwarded-For. (nginx.org)
Пример в http {}:
geoip\_proxy 10.0.16.0/26;
geoip\_proxy\_recursive on;
Диапазон подставьте свой (подсеть балансировщика/прокси).
Проверка результата
- Проверяем синтаксис конфига:
nginx -t
Ожидаемо:
syntax is ok
test is successful
- Перезагружаем:
systemctl reload nginx
- Дёргаем сайт и смотрим лог:
curl -I https://your-domain.tld/ | head
tail -n 5 /var/log/nginx/access.log
В конце строки лога должны появиться country=XX и другие поля. Если видите country=- — значит модуль жив, но база не отрабатывает (см. типичные ошибки ниже).
Типичные ошибки
❌ 1) unknown directive "geoip_country"
Причина: модуль не загружен через load_module или установлен не тот пакет.
Как исправить:
- убедитесь, что модуль установлен: dnf install -y nginx-module-geoip
- проверьте наличие файла: ls /usr/lib64/nginx/modules/ngx_http_geoip_module.so
- проверьте, что load_module стоит в самом верху /etc/nginx/nginx.conf (до http {}), иначе Nginx его просто не увидит. (nginx.org)
❌ 2) Nginx стартует, но GeoIP-переменные пустые
Причина: база отсутствует/не читается/не legacy формата. Legacy GeoLite официально прекращены — это частая ловушка у инструкций “из 2016”. (MaxMind)
Как исправить:
- проверьте файлы: ls -la /etc/nginx/geoip
- проверьте права (Nginx должен читать): chmod 0644 /etc/nginx/geoip/*.dat
- если базы нет — планируйте переход на GeoLite2 + GeoIP2 модуль (см. ниже, путь B). (docs.nginx.com)
❌ 3) Хотите “закрыть страны” и тянет написать if
Причина: в Nginx if — не как в языках программирования. Есть известная рекомендация избегать сложных if-конструкций, и использовать map. При этом даже NGINX-экосистема признаёт, что безопасные случаи есть (обычно return/rewrite). (nginx.org)
Как исправить (без фанатизма):
- для маршрутизации/флагов используйте map (переменная вычисляется один раз и дальше используется в логике)
- если всё-таки нужен if, ограничьте его до “проверка → return”, без set, без вложенных rewrite-цепочек (иначе потом сложно отлаживать). (nginx.org)
Где применять
- Prod на VPS (BitrixVM 9+, CentOS 9+): добавить страну/город в логи, передавать в приложение, включать доп. метрики в мониторинг.
- Docker : удобно, если Nginx на периметре контейнеров и вам нужно логировать географию запросов (но с базами там отдельная история).
- CI/CD : можно проверять nginx -t и деплоить конфиги автоматически, чтобы GeoIP не ронял nginx на бою.
- Связка nginx + httpd : прокидывайте X-GeoIP-* заголовки в Apache и дальше в Bitrix, чтобы не городить логику в PHP.
Сниппеты по статье: Nginx GeoIP: load_module и базы .dat · log_format и заголовки X-GeoIP · geoip_proxy за прокси/балансировщиком · Проверка модуля и баз (bash)
Внутренние ссылки по теме (чтобы собрать цепочку на сайте):
Путь B (коротко, но честно): GeoIP2 вместо legacy в 2025–2026
Если ваша цель — актуальная бесплатная геобаза, то правильная база — GeoLite2 (MMDB), а правильный модуль — GeoIP2. В документации NGINX Plus GeoIP2 модуль описан как официальный динамический модуль. (docs.nginx.com)
Legacy GeoIP/GeoLite в виде .dat в 2025–2026 — это в основном “наследие”, которое живёт только если у вас уже есть источник баз.

Top comments (0)