Deployment
Deployment Model
CIVITAS/CORE V2 is deployed exclusively on Kubernetes using Helmfile to orchestrate multiple Helm charts. There is no Docker Compose or VM-based deployment model.
Supported Environments
| Environment | Support Level | Notes |
|---|---|---|
| Kubernetes (x86_64) | Fully supported | Production and development |
| Kubernetes (ARM64) | Not officially supported | Planned for the future |
| Docker Compose | Not available | Use the local k3d deployment for development |
| Virtual Machines | Not available | Kubernetes is required |
Namespace Strategy
Currently, CIVITAS/CORE V2 deploys all components into a single namespace named after global.instanceSlug (e.g. dev). Multi-namespace deployments are planned but not yet supported.
Deployment Profiles
The global.profile setting controls environment-specific behavior:
| Aspect | development | production |
|---|---|---|
| Resource requests/limits | Lower | Higher |
| Replicas | Single | Multiple (HA, where applicable) |
Secrets
If you haven't already, make sure to create the required secrets in your cluster before deploying CIVITAS/CORE V2. You can find the list of required secrets in the prerequisites documentation.
First Deployment
To deploy a certain environment (e.g., testing), navigate to your deployment directory and run:
helmfile -f deployment/helmfile.yaml sync -e testing
This will:
- Install CRDs for CloudNativePG and Strimzi operators
- Generate secrets for all components
- Deploy PostgreSQL, Etcd, and Kafka infrastructure
- Deploy application components (Keycloak, Portal, APISIX, etc.)
The component deployment order is defined by the components list in global.yaml and respects inter-component dependencies.
Subsequent Deployments
If CRDs are already installed, it is also possible to run apply, which will only apply changes instead of doing a full sync. This is faster for subsequent deployments after the initial deployment.
helmfile -f deployment/helmfile.yaml apply -e testing
Deploying a Single Component
To deploy or update a specific component without redeploying everything:
helmfile -f deployment/helmfile.yaml apply -e testing --selector component=keycloak
Replace keycloak with the component name. This is useful for iterating on individual components.
Dry-Run / Preview
To see what would be deployed without making changes:
# Render all templates (dry-run)
helmfile -f deployment/helmfile.yaml template -e testing
# Validate templates without deploying
helmfile -f deployment/helmfile.yaml lint -e testing
Tips and Tricks
Some helpful flags:
-ior--interactive: Shows a diff of what will be changed and prompts for confirmation before applying changes (only forapplycommand).--selector component=<component-name>: Deploys only the specified component. Component name must be camelCase.
You can set your kubeconfig with export KUBECONFIG=<path>. It uses always the current context set with kubectl config set-context.
Runnable Example
A minimal production deployment from scratch:
# 1. Clone the deployment repository
git clone https://gitlab.com/civitas-connect/civitas-core/civitas-core-v2/civitas-core-deployment.git
cd civitas-core-deployment
# 2. Create your deployment directory
cp -r defaults/deployment deployment
# 3. Create a production environment
mkdir -p deployment/environments/production
# 4. Configure the environment
cat > deployment/environments/production/global.yaml.gotmpl << 'EOF'
global:
domain: civitas.example.com
instanceSlug: prod
profile: production
initialUserEmail: replace-with-your-email@example.com
ingress:
clusterIssuer: 'letsencrypt-prod'
ingressClass: 'nginx'
EOF
For `initialUserEmail` a platform admin will be created later. This user is your initial user to log into the portal and to create other desired users.
# 5. Register the environment in helmfile.yaml
# (edit deployment/helmfile.yaml to add 'production' to environments and helmfiles sections)
# 6. Create required secrets
kubectl create namespace prod
kubectl create secret generic keycloak-smtp \
--from-literal=host='smtp.example.com' \
--from-literal=port='587' \
--from-literal=from='noreply@example.com' \
--from-literal=user='noreply@example.com' \
--from-literal=password='YOUR_SMTP_PASSWORD' \
-n prod
# 7. Deploy
helmfile -f deployment/helmfile.yaml sync -e production