The kill-switch: GEOBOUNDS_ENABLED
The entire feature is gated by one setting:
Leaving it
False is safe: project owners can configure geobound policy, but nothing is enforced until you flip the switch. Set it True only after you have configured a trusted signal provider (below) — otherwise every fail-closed project will deny all reads, because the viewer’s region is always unknown.
Configuring a signal provider: GEOBOUNDS_SIGNAL_PROVIDER
Region and VPN/proxy evidence come from a pluggable signal provider you configure:
Point this at a provider backed by your IP-intelligence source (a GeoIP database, a commercial VPN/proxy feed, etc.). The provider’s job is to turn the trusted client IP into a country code and a VPN/proxy flag; the geobounds evaluator owns the allow/deny decision.
Trusted client IP: GEOBOUNDS_TRUSTED_PROXY_HOPS
Geobounds derive the client IP from the X-Forwarded-For header so it reflects the real viewer behind your edge, not your load balancer:
Set this to the number of reverse proxies / load balancers between the public internet and the application, so a client cannot spoof its country by injecting
X-Forwarded-For entries. Getting this wrong is a security issue: too low and clients can forge their apparent country; too high and you trust an attacker-controlled hop.
No bypass — recovery is a policy edit
Geobounds enforce all-access, no-bypass, fail-closed semantics:- The fence applies to anonymous / public-link readers, directly-granted users, organization members, and system administrators alike.
- There is no request-time override — no header, query parameter, or admin “unlock” reads a fenced project from outside the fence.
- A locked-out owner or admin can only be recovered by an out-of-band policy edit: an operator with database or Django-admin access sets
geobound_enabled = Falseon the affected Project row.
Government lists are deny-kind country sets
GeoBoundCountrySet rows are versioned, source-attributed reference lists, each with a kind:
- allow — permits only the listed countries (geographic groupings).
- deny — blocks the listed countries no matter what else permits them.
POST /api/geobound-country-sets/.
The geobounds evaluator does no live network calls during access evaluation, and the platform does not automatically interpret the legal meaning of a government list. You own keeping deny-kind sets current and correct.
Verification
When you enable geobounds, confirm:- With
GEOBOUNDS_ENABLED=False, fenced projects are reachable as normal (no-op). - With it
Trueand a provider configured, a viewer outside the fence is denied on every read surface, and a viewer inside is allowed. - A system admin outside the fence is also denied (no bypass).
- The only way back in for a locked-out project is editing
geobound_enabledon the Project row.
api/tests/test_geobounds_acl.py exercises the IP-based allow/deny, fail-closed, basis modes, VPN blocking, allow/deny sets, and the no-bypass guarantee against a stub signal provider.
Next steps
Geographic access fences
The end-user view of geobounds.
Organization administration
Other things operators and org admins manage.