Production Setup
On this page
Security Checklist
Before going live, complete every item:
Credentials & Secrets
- Change all default passwords — PostgreSQL, Redis, admin account
- Enable Redis AUTH with a strong password
- Replace in-memory RSA keys with Vault-backed key storage
- Use Kubernetes Secrets or Vault for all credentials — never hardcode
Network
- TLS/HTTPS everywhere — terminate SSL at load balancer or gateway
- Microservices are not publicly accessible — only through gateway
- Set
allowedOriginsto your actual domain (removelocalhost) - Enable Kafka SSL and SASL for internal messaging
Application
- Set
spring.jpa.show-sql: false - Set
spring.jpa.hibernate.ddl-auto: validate(nevercreate-drop) - Restrict
/actuator/**to internal networks only - Enable
mfaRequired: trueon sensitive realms - Adjust token lifespans — shorter access tokens (5 min), shorter refresh (7 days)
Never expose actuator publicly
/actuator/env, /actuator/beans, and /actuator/heapdump expose sensitive runtime data. Restrict them to internal networks.
Recommended Settings
application.yml (all services, production)yaml
spring:
jpa:
show-sql: false
hibernate:
ddl-auto: validate
flyway:
enabled: true
server:
tomcat:
max-connections: 10000
accept-count: 100
forward-headers-strategy: framework # trust X-Forwarded-* from proxy
management:
endpoints:
web:
exposure:
include: health,metrics,prometheus
base-path: /actuator
endpoint:
health:
show-details: never # hide sensitive details from public
server:
port: 9090 # expose actuator on separate internal port
opengate:
token:
access-token-ttl: 300 # 5 minutes
refresh-token-ttl: 604800 # 7 daysDatabase
Use a managed PostgreSQL instance (AWS RDS, Google Cloud SQL, Azure Database for PostgreSQL):
┌───────────────────────────────────────────────────────────┐
│ Production Database Setup │
│ │
│ ┌─────────────────┐ ┌─────────────────────┐ │
│ │ Primary DB │──────────│ Read Replica │ │
│ │ (writes only) │ repl │ (reads only) │ │
│ └────────┬────────┘ └─────────────────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ PgBouncer │ ← Connection pooling │
│ │ (pool: 100) │ │
│ └────────┬────────┘ │
│ │ │
│ Microservices (max 10 connections each) │
└───────────────────────────────────────────────────────────┘
- Enable automatic backups with at least 7-day retention
- Enable point-in-time recovery (PITR)
- Use PgBouncer for connection pooling
- Set up read replicas for user-service and realm-service
Reverse Proxy
/etc/nginx/sites-available/opengatenginx
server {
listen 80;
server_name iam.yourdomain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name iam.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/iam.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/iam.yourdomain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_cache shared:SSL:10m;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Monitoring Endpoints
Each service exposes Spring Actuator endpoints:
| Endpoint | Description |
|---|---|
GET /actuator/health | Service health + dependency status |
GET /actuator/metrics | JVM, HTTP, DB metrics |
GET /actuator/prometheus | Prometheus-format metrics |
GET /actuator/info | Build info, version |
Restrict actuator in production
Only expose health, metrics, and prometheus. Never expose env, beans, heapdump, or threaddump publicly.