FerrisKey Operator
The operator manages FerrisKey instances declaratively, through a custom resource. You describe the cluster you want in a FerrisKeyCluster manifest, and the operator reconciles towards it.
The FerrisKeyCluster resource
The CRD is ferriskeyclusters.ferriskey.rs, API version ferriskey.rs/v1alpha1, namespaced, with the short name fkcl. kubectl get fkcl prints the version, the replica count, readiness, and the current phase.
apiVersion: ferriskey.rs/v1alpha1
kind: FerrisKeyCluster
metadata:
name: my-ferriskey
namespace: ferriskey
spec:
name: my-ferriskey
replicas: 3
version: "0.7.0"
api:
apiUrl: "https://api.iam.yourorg.com"
webappUrl: "https://iam.yourorg.com"
allowedOrigins:
- "https://iam.yourorg.com"
database:
secretRef:
name: ferriskey-db-credentials
namespace: ferriskey
databaseName: ferriskey
sslMode: require
Spec reference
Every field below is required unless the description says otherwise.
Root
| Field | Type | Description |
|---|---|---|
name | string | Cluster name |
replicas | integer | Number of API replicas |
version | string | FerrisKey version to deploy |
api | object | API configuration |
database | object | Database configuration |
spec.api
| Field | Type | Description |
|---|---|---|
apiUrl | string | Public URL of the API |
webappUrl | string | Public URL of the console |
allowedOrigins | string[] | Optional. Browser origins allowed on every route |
As with the standalone deployment, per-client web origins only cover realm-scoped routes. /config, the health probes, and the API documentation carry no realm, so a console served from a different origin than the API has to keep its origin in allowedOrigins.
spec.database
| Field | Type | Description |
|---|---|---|
secretRef.name | string | Secret holding the database credentials |
secretRef.namespace | string | Optional. Defaults to the resource’s namespace |
databaseName | string | Optional. Overrides the database name from the Secret |
sslMode | string | Optional. disable, prefer, require, verify-ca, or verify-full |
Database Secret format
The referenced Secret must carry host, port, user, and password. database is optional and can be supplied through databaseName instead.
Status
The operator reports cluster status through the status subresource:
status:
ready: true
phase: Running
databaseStatus:
connected: true
host: "postgres.database.svc.cluster.local"
database: "ferriskey"
lastCheck: "2026-03-17T10:30:00Z"
conditions:
- conditionType: Ready
status: "True"
lastTransitionTime: "2026-03-17T10:25:00Z"
- conditionType: DatabaseConnected
status: "True"
lastTransitionTime: "2026-03-17T10:24:00Z"
| Field | Description |
|---|---|
ready | Overall cluster readiness |
phase | Current phase (Pending, Running, Failed) |
message | Human-readable status message |
databaseStatus | Database connectivity information |
conditions | Standard Kubernetes conditions |
Deploying
Install the operator
The operator ships as its own Helm chart, which installs the CRD, the operator Deployment, and the RBAC it needs:
helm install ferriskey-operator oci://ghcr.io/ferriskey/charts/ferriskey-operator \
--namespace ferriskey-system \
--create-namespace Create a database secret
kubectl create secret generic ferriskey-db-credentials \
--namespace ferriskey \
--from-literal=host=postgres.database.svc.cluster.local \
--from-literal=port=5432 \
--from-literal=user=ferriskey \
--from-literal=password=your-db-password Apply the FerrisKeyCluster manifest
kubectl apply -f ferriskey-cluster.yaml Check status
kubectl get fkcl -n ferriskey CRD and RBAC ownership
By default the chart installs the CRD and annotates it with helm.sh/resource-policy: keep, so helm uninstall leaves it, and your clusters, alone. It also creates a ClusterRole and ClusterRoleBinding letting the operator manage FerrisKeyCluster resources across namespaces.
If either is managed elsewhere, for example through GitOps or a dedicated CRD chart, turn the chart’s copy off:
crds:
install: false
rbac:
create: false
Keep the CRD on uninstall
Leave crds.keep at true in production. Deleting the CRD deletes every FerrisKeyCluster in the cluster along with it.