Repository navigation
Feature Guide Geo Blocking
Block or allow traffic to your proxy hosts based on the visitor's geographic location, network, or IP address.
- Overview
- Prerequisites
- GeoIP Database Setup
- Configuring Geo Blocking
- Rule Types
- Allow vs. Block Rules
- Examples
- Troubleshooting
Geo blocking is powered by the caddy-blocker-plugin and MaxMind GeoLite2 databases. Rules are evaluated by Caddy on every request before it reaches your upstream service.
Supported rule types:
- Country (ISO 3166-1 alpha-2 code, e.g.
DE,US,FI) - Continent (
AF,AN,AS,EU,NA,OC,SA) - ASN — Autonomous System Number (e.g.
24940for Hetzner) - CIDR range (e.g.
203.0.113.0/24) - Exact IP address (e.g.
203.0.113.10)
Geo blocking is configured per proxy host, so you can have different rules for different services.
- MaxMind GeoLite2 Country and/or ASN databases
- The
geoipupdateDocker profile enabled (see setup below)
Country and continent rules require the Country DB. ASN rules require the ASN DB. CIDR and IP rules work without any database.
Register for free at maxmind.com. No payment required for GeoLite2.
In your MaxMind account portal:
- Go to My License Key
- Click Generate new license key
- Name it (e.g.
caddy-proxy-manager) - Note your Account ID and the generated License Key
Add to your .env file:
GEOIPUPDATE_ACCOUNT_ID=123456
GEOIPUPDATE_LICENSE_KEY=your_license_key_heredocker compose --profile geoipupdate up -dThis starts the geoipupdate container which downloads and periodically refreshes the databases (every 72 hours by default). Databases are stored in the geoip-data Docker volume, which is mounted read-only into both the web and caddy containers.
In the Caddy Proxy Manager web UI, the geo blocking section of each proxy host will show which databases are available. You can also check the Settings page.
- Open Proxy Hosts and edit (or create) a proxy host
- Scroll to the Geo Blocking section
- Toggle Enable Geo Blocking on
- Add rules using the rule builder
- Click Save
Changes take effect immediately — Caddy configuration is updated in real time.
The rule builder includes a LAN Only (RFC1918) preset button. Clicking it automatically populates the rules with allow entries for all private address ranges:
10.0.0.0/8172.16.0.0/12192.168.0.0/16
This is useful when you want to restrict access to internal services to LAN clients only. Combined with appropriate block rules for public ranges, it provides a quick way to lock down an internal-only service.
Block or allow based on the visitor's country.
Uses the MaxMind GeoLite2 Country database. Requires Country DB.
Format: ISO 3166-1 alpha-2 code (two uppercase letters)
| Country | Code |
|---|---|
| Germany | DE |
| United States | US |
| Finland | FI |
| United Kingdom | GB |
| France | FR |
Example: Block all requests from Germany → Rule: Block, Country, DE
Block or allow based on the visitor's continent. Useful for broad geographic restrictions.
Requires Country DB.
| Continent | Code |
|---|---|
| Africa | AF |
| Antarctica | AN |
| Asia | AS |
| Europe | EU |
| North America | NA |
| Oceania | OC |
| South America | SA |
Example: Block all traffic from Europe → Rule: Block, Continent, EU
Block or allow based on the visitor's Autonomous System Number. Useful for blocking specific hosting providers, VPN services, or ISPs.
Requires ASN DB.
Format: Numeric ASN without the AS prefix
| Provider | ASN |
|---|---|
| Hetzner | 24940 |
| Cloudflare | 13335 |
| DigitalOcean | 14061 |
| OVH | 16276 |
Example: Block Hetzner servers → Rule: Block, ASN, 24940
Block or allow an IP range in CIDR notation. Does not require any GeoIP database.
Format: x.x.x.x/prefix for IPv4, x:x::x/prefix for IPv6
Examples:
-
203.0.113.0/24— a /24 subnet (256 addresses) -
10.0.0.0/8— private network -
2001:db8::/32— IPv6 range
Example: Block a specific subnet → Rule: Block, CIDR, 203.0.113.0/24
Block or allow a single exact IP address. Does not require any GeoIP database.
Format: x.x.x.x (IPv4) or full IPv6 address
Example: Allow a specific server IP → Rule: Allow, IP, 203.0.113.10
Allow rules take precedence over block rules.
This means you can create broad block rules and then punch specific exceptions through them.
For each incoming request, Caddy evaluates all rules:
- If any Allow rule matches → request is passed through
- If any Block rule matches (and no Allow rule matched) → request gets 403 Forbidden
- If no rules match → request is passed through
Block a country:
Block → Country → DE
Blocks all traffic from Germany.
Block a continent:
Block → Continent → EU
Blocks all traffic from Europe.
Block a continent, allow a specific country:
Block → Continent → EU
Allow → Country → FI
Blocks Europe but allows Finland through.
Block a hosting provider, allow your own server:
Block → ASN → 24940
Allow → IP → 1.2.3.4
Blocks Hetzner traffic except for your specific server IP.
Allow only one country (block everywhere else):
There is no "block all" rule type. To allow only one country, you need to block all other continents:
Block → Continent → AF
Block → Continent → AN
Block → Continent → AS
Block → Continent → EU
Block → Continent → NA
Block → Continent → OC
Block → Continent → SA
Allow → Country → US
This blocks all continents and then allows only the US through.
Goal: Block all traffic from Germany
Rules:
Block → Country → DE
Goal: Block all Hetzner servers (common source of bots/scanners)
Rules:
Block → ASN → 24940
Goal: Block all of Europe, but allow your home IP through
Rules:
Block → Continent → EU
Allow → IP → YOUR_HOME_IP
Goal: Block a specific IP range (e.g. a known malicious subnet)
Rules:
Block → CIDR → 203.0.113.0/24
Goal: Only allow traffic from Finland, block everything else
Rules:
Block → Continent → AF
Block → Continent → AN
Block → Continent → AS
Block → Continent → EU
Block → Continent → NA
Block → Continent → OC
Block → Continent → SA
Allow → Country → FI
The GeoLite2 databases are not mounted or haven't been downloaded yet.
Fix:
- Ensure
GEOIPUPDATE_ACCOUNT_IDandGEOIPUPDATE_LICENSE_KEYare set in.env - Start with the geoipupdate profile:
docker compose --profile geoipupdate up -d - Wait for the databases to download (check logs:
docker compose logs geoipupdate) - Verify the
geoip-datavolume is mounted:docker compose exec web ls /usr/share/GeoIP/
Configuration is applied when you save. If changes don't take effect:
- Check Caddy logs:
docker compose logs caddy - Verify the proxy host was saved successfully (check the audit log)
- Restart Caddy:
docker compose restart caddy
Check rule order and types:
- Allow rules override block rules — ensure your allow rule type matches what you expect
- Country and continent rules require the Country database — verify it's present
- ASN rules require the ASN database — verify it's present
- CIDR and IP rules don't require databases — verify the format is correct
- Country/continent/ASN lookups depend on database accuracy — MaxMind GeoLite2 is not 100% accurate
- Feature Guide Proxy Hosts - Setting up proxy hosts
- Installation Guide - Docker setup
- caddy-blocker-plugin - The underlying Caddy plugin
Need help? Open an issue with your configuration details.