This episode covers IP-based access control: the remote_ip matcher with CIDR, whitelists and blacklists, the trusted_proxies directive for detecting the real IP, GeoIP filtering with plugins, and rate limiting for basic DDoS protection.

Not every visitor deserves entry. An admin panel should only be reachable from the office. Internal endpoints should only accept requests from specific services. Episode 19 covers IP-based access control in Caddy.
You'll learn the remote_ip matcher with CIDR notation for whitelists and blacklists, the trusted_proxies directive so Caddy knows the real client IP behind a proxy, GeoIP filtering with plugins for country-based control, and rate limiting to protect against attacks.
Layered access control makes a system far more resilient — and all of these tools are available in Caddy.
The remote_ip matcher matches the client's IP address:
example.com {
@kantor {
remote_ip 192.168.1.0/24
}
handle @kantor {
root * /var/www/admin
file_server
}
respond "Access denied" 403
}Only clients from the 192.168.1.0/24 subnet can access /admin. Everyone else gets a 403. remote_ip accepts one or many addresses and CIDR ranges.
The whitelist pattern — only the listed IPs are allowed:
example.com {
@boleh {
remote_ip 10.0.0.5 10.0.0.6 203.0.113.7
}
handle @boleh {
reverse_proxy localhost:8080
}
respond "Not allowed" 403
}The blacklist pattern — everyone except the blocked list:
example.com {
@dilarang {
remote_ip 198.51.100.0/24
}
respond @dilarang "Blocked" 403
root * /var/www
file_server
}A whitelist is stricter (deny by default); a blacklist is more open (allow by default). For sensitive resources, a whitelist is the safer choice.
When Caddy sits behind another proxy (a CDN, a cloud load balancer), the IP it sees isn't the real client IP. The X-Forwarded-For header contains the real IP, but that header can be spoofed. trusted_proxies tells Caddy which proxies are trustworthy:
{
servers {
trusted_proxies static 10.0.0.0/8 172.16.0.0/12
}
}
example.com {
@internal {
remote_ip 192.168.1.0/24
}
handle @internal {
respond "Internal"
}
}trusted_proxies static 10.0.0.0/8 marks every IP in that range as a trusted proxy. Only headers from trusted proxies are treated as the real IP.
With correct trusted_proxies, the remote_ip matcher works with the real client IP, not the proxy IP. Without it, every client appears to come from the CDN IP — making an office whitelist useless.
Country-based control requires a plugin (episode 29). With the GeoIP module installed, block or allow based on country:
example.com {
@terlarang {
ip_country CN RU
}
respond @terlarang "Not available" 403
root * /var/www
file_server
}ip_country CN RU (via the caddy-security or GeoIP module) blocks traffic from specific countries. Useful for:
Note: GeoIP based on IP addresses can be evaded with VPNs and isn't 100 percent accurate — treat it as one layer of defense, not the only one.
Rate limiting limits the number of requests from a single IP within a time window. The caddy-rate-limit module (a plugin, episode 29) is used like this:
{
order rate_limit before basicauth
}
example.com {
rate_limit {
zone api {
key {remote_host}
events 60
window 1m
}
}
}rate_limit limits 60 requests per minute per IP on the matching paths. Basic DDoS protection uses this pattern together with matchers:
example.com {
@login {
path /api/login
}
rate_limit @login {
zone login {
key {remote_host}
events 10
window 1m
}
}
reverse_proxy localhost:8080
}The login endpoint is limited to 10 requests per minute per IP — hindering brute force. rate_limit @login applies the limit only to the login path.
Episode 19 built IP-based access control: the remote_ip matcher with CIDR for whitelists and blacklists, the trusted_proxies directive so real IPs are detected behind a proxy, GeoIP filtering for regional control, and rate limiting to protect sensitive endpoints.
Key takeaways:
remote_ip accepts IP addresses and CIDR ranges.trusted_proxies must be set when a proxy sits in front of Caddy.In the next episode, episode 20, we'll cover security headers & CORS — the header directive for adding and removing headers, all the important security headers like CSP and HSTS, complete CORS configuration with OPTIONS preflight, and best practices for hiding server information.