load_module /usr/lib/nginx/modules/ngx_http_geoip2_module.so; user nginx; worker_processes auto; error_log /var/log/nginx/error.log notice; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; # ── Logging ─────────────────────────────────────────────────────────────── log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" country=$geoip2_country iso=$geoip2_subdivision'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; keepalive_timeout 65; # ── GeoIP2 database ─────────────────────────────────────────────────────── # The GeoLite2-City database gives us country + subdivision (state/province) geoip2 /usr/share/GeoIP/GeoLite2-City.mmdb { # ISO 3166-1 alpha-2 country code (e.g. "US") $geoip2_country country iso_code; # ISO 3166-2 subdivision code — country prefix stripped below # Full value looks like "US-CA"; we expose just the subdivision part $geoip2_subdivision subdivisions 0 iso_code; } # Compound key used in per-repo map blocks: "CC-SUBDIV" e.g. "US-CA" # When the DB has no subdivision the variable is empty; the key becomes "CC-" # which will not match any rule unless you explicitly add it. map "$geoip2_country-$geoip2_subdivision" $geoip2_region_key { default ""; include /etc/nginx/geoblock/repo_maps.conf; } # ── Per-repo block decision variables ───────────────────────────────────── # Loaded from the rendered snippet produced by geoblock_watcher. # Each repo gets a variable like $geoblock_ # with value "" (allow) or ":" (block). include /etc/nginx/geoblock/repo_vars.conf; # ── Virtual hosts ───────────────────────────────────────────────────────── include /etc/nginx/conf.d/*.conf; }