ZITADEL is a modern IAM platform with extensive API exposure; securing organization/project boundaries and implementing proper hardening measures are critical for maintaining a secure identity management system.
ZITADEL implements a multi-tenant architecture by design. Organizations and projects are isolated at the database level:
Configure MFA policies for enhanced security:
# MFA configuration in config.yaml
login_policy:
force_mfa: true # Force MFA for all users
force_mfa_local: false # Don't force MFA for local users
second_factors:
- OTP # Time-based one-time passwords
- U2F # Hardware security keys
multi_factors:
- OTP
- U2F
Implement strong password requirements:
# Password complexity configuration
password_complexity:
min_length: 14
has_lowercase: true
has_uppercase: true
has_number: true
has_symbol: true
Configure account lockout policies to prevent brute-force attacks:
# Lockout configuration
lockout:
max_attempts: 5
find_automatically: true
threshold: 5 # Attempts within lockout window
duration: 15m # Lockout duration
Restrict network access to ZITADEL services:
# For systems using ufw
sudo ufw allow from trusted_network to any port 8080 # HTTP API
sudo ufw allow from trusted_network to any port 8081 # gRPC API
sudo ufw deny 8080 # Block all other access to HTTP API
sudo ufw deny 8081 # Block all other access to gRPC API
# For systems using firewalld
sudo firewall-cmd --permanent --zone=trusted --add-port=8080/tcp
sudo firewall-cmd --permanent --zone=trusted --add-port=8081/tcp
sudo firewall-cmd --reload
Enforce HTTPS and proper TLS configuration:
# TLS configuration in config.yaml
http:
addr: 0.0.0.0:8080
tls:
mode: custom
cert_file: /path/to/fullchain.pem
key_file: /path/to/privkey.pem
min_version: "TLS1.2"
cipher_suites:
- "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"
- "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"
- "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305"
- "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305"
Properly configure Cross-Origin Resource Sharing:
# CORS configuration
external:
cors:
allowed_origins:
- https://your-domain.com
- https://console.your-domain.com
- https://admin.your-domain.com
allowed_headers:
- Authorization
- Content-Type
- X-Requested-With
allowed_methods:
- GET
- POST
- PUT
- DELETE
- OPTIONS
max_age: 86400 # 24 hours
Secure the PostgreSQL database backend:
-- Create database with restricted permissions
CREATE DATABASE zitadel WITH OWNER zitadel ENCODING 'UTF8';
-- Create user with minimal required permissions
CREATE USER zitadel WITH PASSWORD 'strong_password';
GRANT CONNECT ON DATABASE zitadel TO zitadel;
GRANT USAGE ON SCHEMA public TO zitadel;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO zitadel;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO zitadel;
Use encrypted connections to the database:
# Database SSL configuration
database:
postgres:
host: localhost
port: 5432
database: zitadel
user: zitadel
password: your_secure_password
ssl:
mode: require # Require SSL connection
root_cert_file: /path/to/ca.crt # Path to CA certificate
cert_file: /path/to/client.crt # Client certificate (optional)
key_file: /path/to/client.key # Client key (optional)
The master key is critical for encrypting sensitive data:
Manage API tokens securely:
When deploying with Docker, implement security best practices:
# Secure docker-compose.yml configuration
services:
zitadel:
image: ghcr.io/zitadel/zitadel:4.10.1
security_opt:
- no-new-privileges:true
read_only: true
tmpfs:
- /tmp
- /run
user: "1000:1000" # Non-root user
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE # Only necessary capabilities
sysctls:
- net.core.somaxconn=1024
ulimits:
nproc: 65535
nofile:
soft: 20000
hard: 40000
For Kubernetes deployments:
apiVersion: apps/v1
kind: Deployment
metadata:
name: zitadel
spec:
template:
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
seccompProfile:
type: RuntimeDefault
containers:
- name: zitadel
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
Configure secure logging:
# Logging configuration
logging:
level: info # Change to 'debug' only temporarily
format: json
stacktrace: false # Prevent sensitive data in stack traces
sampling:
enabled: true
initial: 100
thereafter: 100
ZITADEL maintains audit logs:
Implement security monitoring:
# Example log monitoring with fail2ban
# /etc/fail2ban/filter.d/zitadel.conf
[Definition]
failregex = ^.*authentication failed for user .* from <HOST>.*$
ignoreregex =
# /etc/fail2ban/jail.d/zitadel.conf
[zitadel]
enabled = true
port = 8080,8081
filter = zitadel
logpath = /var/log/zitadel/*.log
maxretry = 5
bantime = 3600
findtime = 600
ZITADEL includes features for GDPR compliance:
Implement SOC 2 controls:
If credentials are compromised:
Stay informed about security updates: