IP Geo blocking
Qool restricts access to the Netherlands using NGINX GeoIP2.
1. Install the NGINX GeoIP2 module
sudo apt update
sudo apt install libnginx-mod-http-geoip2
Ubuntu should automatically create:
/etc/nginx/modules-enabled/50-mod-http-geoip2.conf
With the contents:
load_module modules/ngx_http_geoip2_module.so;
2. Download the country database
DB-IP publishes its free country database monthly in MMDB format. Select the current release from the official DB-IP download page. The free database requires attribution under CC BY 4.0.
For the November 2026 release:
cd /tmp
curl -fL \
https://download.db-ip.com/free/dbip-country-lite-2026-11.mmdb.gz \
-o dbip-country-lite.mmdb.gz
gzip -dc dbip-country-lite.mmdb.gz \
> dbip-country-lite.mmdb
sudo install -d -o root -g root -m 0755 /usr/share/GeoIP
sudo install -o root -g root -m 0644 \
dbip-country-lite.mmdb \
/usr/share/GeoIP/dbip-country-lite.mmdb
DB-IP documents that Lite databases are updated monthly, so the YYYY-MM value must periodically be updated. DB-IP documentation
3. Define the country policy
Create /etc/nginx/conf.d/nl-country-map.conf:
geoip2 /usr/share/GeoIP/dbip-country-lite.mmdb {
auto_reload 1h;
$visitor_country_code default=ZZ country iso_code;
}
map $remote_addr $trusted_ip {
default 0;
# Replace this with your own trusted public IP.
203.0.113.10 1;
}
map "$visitor_country_code:$trusted_ip" $country_allowed {
default 0;
# Allow clients classified as Dutch.
~^NL: 1;
# Allow explicitly trusted source addresses.
~:1$ 1;
}
4. Create the enforcement snippet
Create /etc/nginx/snippets/some-countries-only.conf:
# Reusable Netherlands-only access policy.
# Requires $nl_country_allowed in the HTTP context.
if ($country_allowed = 0) {
return 403;
}
Using if with a simple return is appropriate here.
5. Enable it for a website
Inside the applicable server block:
server {
listen 443 ssl;
server_name example.com;
include snippets/some-countries-only.conf;
# Remaining website configuration...
}
6. Test before reloading
sudo nginx -t
Only when that succeeds:
sudo systemctl reload nginx
Test from:
- A Dutch connection, which should receive the normal website.
- A non-Dutch VPN endpoint, which should receive HTTP
403. - Your trusted IP, which should work regardless of its GeoIP classification.
You can inspect NGINX’s effective configuration with:
sudo nginx -T
Important considerations
- If NGINX is behind Cloudflare, another reverse proxy, or a load balancer, $remote_addr may be the proxy address. Configure NGINX’s real-IP module correctly before applying this restriction. Do not blindly trust client-supplied forwarding headers.
- A server-level restriction can also block Let’s Encrypt HTTP-01 validation. If Certbot uses HTTP-01, provide a separate unrestricted ACME challenge virtual host/location or use DNS-01 validation.
- GeoIP is not an absolute security boundary. VPNs, proxies, database inaccuracies, and stale records can bypass or incorrectly trigger it.
- The qool server currently has no detected automatic database updater. A monthly replacement of the MMDB file should therefore be scheduled if you want current classifications.
- SSH access is unaffected; this configuration only restricts websites served through the applicable NGINX virtual host.
--