Aletyx Decision Control Tower Setup Guide¶
This guide covers deploying Aletyx Decision Control Tower in your Kubernetes cluster.
Prerequisites
Before deploying Aletyx Decision Control Tower, ensure you have:
- Kubernetes cluster with Decision Control environments deployed
- Keycloak configured with the
aletyxrealm - Governance API running
- DNS entries for Aletyx Decision Control Tower hostname
Architecture¶
Aletyx Decision Control Tower deployment includes:
graph TB
subgraph "Aletyx Decision Control Tower Stack"
LP[Landing Page<br/>nginx]
GOV[Governance API<br/>Node.js]
DB[(Governance DB<br/>PostgreSQL)]
end
subgraph "Existing Infrastructure"
KC[Keycloak]
DC[Decision Control<br/>Environments]
end
LP --> GOV
LP --> KC
LP --> DC
GOV --> DB
GOV --> KC
GOV --> DC
style LP fill:#90EE90
style GOV fill:#FFB6C1
Step 1: Deploy Governance Database¶
Create PostgreSQL for governance data:
# governance-database.yaml
apiVersion: v1
kind: Secret
metadata:
name: postgres-governance-secret
namespace: prod
type: Opaque
stringData:
POSTGRES_USER: governance_user
POSTGRES_PASSWORD: CHANGE_ME_SECURE_PASSWORD
POSTGRES_DB: governance_db
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres-governance
namespace: prod
spec:
replicas: 1
selector:
matchLabels:
app: postgres-governance
template:
metadata:
labels:
app: postgres-governance
spec:
containers:
- name: postgres
image: postgres:15-alpine
ports:
- containerPort: 5432
env:
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: postgres-governance-secret
key: POSTGRES_USER
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-governance-secret
key: POSTGRES_PASSWORD
- name: POSTGRES_DB
valueFrom:
secretKeyRef:
name: postgres-governance-secret
key: POSTGRES_DB
volumeMounts:
- name: postgres-storage
mountPath: /var/lib/postgresql/data
volumes:
- name: postgres-storage
persistentVolumeClaim:
claimName: postgres-governance-pvc
---
apiVersion: v1
kind: Service
metadata:
name: postgres-governance
namespace: prod
spec:
selector:
app: postgres-governance
ports:
- port: 5432
targetPort: 5432
Apply:
Step 2: Deploy Governance API¶
Create the Governance API backend:
# governance-api.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: governance-api
namespace: prod
spec:
replicas: 1
selector:
matchLabels:
app: governance-api
template:
metadata:
labels:
app: governance-api
spec:
containers:
- name: governance-api
image: registry-keystone.aletyx.services/governance-api:1.1.7
ports:
- containerPort: 3001
env:
- name: PORT
value: "3001"
- name: DB_HOST
value: postgres-governance
- name: DB_PORT
value: "5432"
- name: DB_NAME
value: governance_db
- name: DB_USER
valueFrom:
secretKeyRef:
name: postgres-governance-secret
key: POSTGRES_USER
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-governance-secret
key: POSTGRES_PASSWORD
- name: KEYCLOAK_URL
value: https://keycloak.your-domain.com
- name: KEYCLOAK_REALM
value: aletyx
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: 1000m
memory: 1Gi
---
apiVersion: v1
kind: Service
metadata:
name: governance-api
namespace: prod
spec:
selector:
app: governance-api
ports:
- port: 3001
targetPort: 3001
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: governance-api-ingress
namespace: prod
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-origin: "https://control-tower.your-domain.com"
spec:
ingressClassName: nginx
tls:
- hosts:
- governance-api.your-domain.com
secretName: governance-api-tls
rules:
- host: governance-api.your-domain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: governance-api
port:
number: 3001
Apply:
Step 3: Create Environment Configuration¶
Create the environment configuration ConfigMap:
# Create config.json
cat <<EOF > config.json
{
"environments": {
"dev": {
"name": "Development",
"baseUrl": "https://decision-control-dev.your-domain.com",
"enabled": true,
"features": {
"submitForReview": true,
"governance": true
},
"apis": {
"units": "/api/runtime/units",
"versions": "/api/runtime/units/{unitId}/versions",
"models": "/api/runtime/units/{unitId}/versions/{versionId}/models",
"health": "/actuator/health"
}
},
"test": {
"name": "Testing",
"baseUrl": "https://decision-control-test.your-domain.com",
"enabled": true,
"features": {
"submitForReview": true,
"governance": true
}
},
"prod": {
"name": "Production",
"baseUrl": "https://decision-control-prod.your-domain.com",
"enabled": true,
"features": {
"submitForReview": false,
"governance": true
}
}
},
"governance": {
"apiUrl": "https://governance-api.your-domain.com",
"workflow": {
"submitForReview": ["BUSINESS_ANALYST"],
"riskApproval": ["RISK_MANAGER"],
"complianceApproval": ["COMPLIANCE"],
"promoteToProduction": ["OPERATOR"]
}
},
"keycloak": {
"url": "https://keycloak.your-domain.com",
"realm": "aletyx",
"clientId": "decision-control-ui"
}
}
EOF
# Create ConfigMap
kubectl create configmap environment-config \
--from-file=config.json \
--namespace=prod
Step 4: Deploy Landing Page¶
Deploy the Aletyx Decision Control Tower landing page:
# control-tower.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: control-tower
namespace: prod
spec:
replicas: 1
selector:
matchLabels:
app: control-tower
template:
metadata:
labels:
app: control-tower
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
volumeMounts:
- name: landing-page
mountPath: /usr/share/nginx/html
- name: environment-config
mountPath: /usr/share/nginx/html/environments
volumes:
- name: landing-page
configMap:
name: control-tower-landing
- name: environment-config
configMap:
name: environment-config
---
apiVersion: v1
kind: Service
metadata:
name: control-tower
namespace: prod
spec:
selector:
app: control-tower
ports:
- port: 80
targetPort: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: control-tower-ingress
namespace: prod
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- control-tower.your-domain.com
secretName: control-tower-tls
rules:
- host: control-tower.your-domain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: control-tower
port:
number: 80
Apply:
Step 5: Configure Keycloak¶
Ensure Keycloak has the required roles:
Required Realm Roles¶
Create these roles in the aletyx realm:
decision-control-dev-users- Business Analystsdecision-control-risk-manager- Risk Managersdecision-control-compliance- Compliance Officersdecision-control-prod-users- Operations Managersdecision-control-admin- Administrators
Client Configuration¶
Update the decision-control-ui client:
- Valid redirect URIs: Add
https://control-tower.your-domain.com/* - Web origins: Add
https://control-tower.your-domain.com
Step 6: Verify Deployment¶
Check all components are running:
# Check pods
kubectl get pods -n prod | grep -E "control-tower|governance"
# Expected output:
# control-tower-xxx 1/1 Running 0
# governance-api-xxx 1/1 Running 0
# postgres-governance-xxx 1/1 Running 0
Test endpoints:
# Landing page
curl -I https://control-tower.your-domain.com
# Governance API
curl https://governance-api.your-domain.com/health
Step 7: First Login¶
- Navigate to
https://control-tower.your-domain.com - You'll be redirected to Keycloak for authentication
- Log in with a user that has one of the Decision Control roles
- You should see the Aletyx Decision Control Tower dashboard
Updating Configuration¶
To update environment configuration:
# Delete existing ConfigMap
kubectl delete configmap environment-config -n prod
# Create updated ConfigMap
kubectl create configmap environment-config \
--from-file=config.json \
--namespace=prod
# Restart Aletyx Decision Control Tower to pick up changes
kubectl rollout restart deployment/control-tower -n prod
Troubleshooting¶
Cannot Log In¶
- Verify Keycloak is accessible
- Check client redirect URIs include Aletyx Decision Control Tower URL
- Verify user has a Decision Control role
Environments Not Loading¶
- Check environment URLs are accessible
- Verify CORS is configured on Governance API
- Check browser console for errors
Tasks Not Appearing¶
- Verify Governance API is running
- Check database connectivity
- Ensure user has correct role
Next Steps¶
- Dashboard and Navigation: Learn the interface
- Environment Management: Configure environments
- Task Management: Work with tasks
- Governance Workflow: Configure workflows