Hasura is powerful — and dangerously open by default.
To run it safely in production, especially in regulated or hostile environments,
a Zero Trust Architecture is not optional — it’s essential.
This post presents a layered, hardened deployment model for Hasura under zero trust principles.
1. Design Philosophy
"Never trust the network. Never trust the client. Always verify, at every layer."
We enforce:
- No public surface without authentication
- Strict identity propagation via JWT
- Micro-segmentation for roles and routes
- Immutable permissions
- Audit everything
2. High-Level Architecture
[Client] → [API Gateway] → [Auth Proxy] → [Hasura] → [PostgreSQL]
↘︎ [OPA / Authz]
↘︎ [JWT Signer]
- All traffic goes through gateway
- Auth proxy (e.g. Firebase Auth / custom) issues JWTs
- OPA or equivalent enforces external authorization
- Hasura trusts only verified JWTs via
x-hasura-*
claims
3. JWT Configuration in Hasura
Set the following environment vars:
HASURA_GRAPHQL_JWT_SECRET='{
"type": "HS256",
"key": "",
"claims_namespace_path": "$.hasura"
}'
HASURA_GRAPHQL_AUTH_HOOK=https://opa.example.com/authorize
HASURA_GRAPHQL_ADMIN_SECRET=disable_this_in_zero_trust
🔥 Best Practice:
- DO NOT use admin secret in production
- DO NOT expose
/v1/graphql
directly to the internet - DO NOT allow unauthenticated roles unless locked-down
4. Permissions via Roles
Define strict roles with field and row-level filters.
Example: user
role for table invoices
select:
filter:
owner_id: { _eq: X-Hasura-User-Id }
columns:
- id
- amount
- status
Use Hasura Console or metadata YAML to version-control permission rules.
5. API Gateway Layer
Use Envoy / Traefik / Kong / AWS API Gateway to:
- Enforce HTTPS only
- Strip any client-supplied
x-hasura-*
headers - Inject clean, signed JWTs
- Rate-limit per role/IP/token
- Block unknown routes (
/_console
,/v2/query
,/v1alpha1
)
6. Open Policy Agent (OPA) Integration
Add a sidecar or external OPA for dynamic policy checks:
- Time-based access control
- IP allowlists per tenant
- Data-driven deny rules
OPA can inject headers like x-hasura-allowed: true
,
which Hasura can read via custom auth hook logic.
7. Monitoring and Auditing
Use:
- Hasura Events / Webhooks to log high-value actions
- PostgreSQL log_statement for backend visibility
- GraphQL depth/complexity limits to avoid DoS
Example:
HASURA_GRAPHQL_ENABLE_TELEMETRY=false
HASURA_GRAPHQL_ENABLE_CONSOLE=false
HASURA_GRAPHQL_ENABLED_LOG_TYPES=startup,http-log,webhook-log
Push all logs to ELK / Loki / CloudWatch for long-term review.
Final Hardening Tips
- 🛡 Remove public role entirely
- 🔒 Disable console and metadata APIs
- 🧠 Review permissions via CI on every schema change
- 📶 Lock network ingress via security group / VPC firewall
- 🎯 Adopt a deny-by-default policy — then allow per role
Final Thoughts
Hasura is GraphQL at hyperspeed — but that velocity cuts both ways.
If you're not running Zero Trust, you're trusting too much.
In upcoming articles:
- Build a JWT issuing system for Hasura with short-lived tokens
- Policy versioning for field-level access
- Shadow mode attack detection via telemetry signals
Trust no one. Authorize everything. Harden by design.