Deploying Apicurio Registry using the Operator

Deploy and configure Apicurio Registry instances by using the Apicurio Registry Operator on Kubernetes.

Prerequisites

Apicurio Registry Operator deployment overview

The Apicurio Registry Operator installs the ApicurioRegistry3 custom resource definition (CRD). You use the ApicurioRegistry3 CR to deploy and manage Apicurio Registry instances on Kubernetes. The custom resource enables you to declaratively configure all aspects of your Apicurio Registry deployment, including storage, authentication, networking, and component-specific settings.

Additional ApicurioRegistry3 custom resource examples are available in the Apicurio Registry upstream repository.

The ApicurioRegistry3 custom resource is organized into two main components:

  • spec.app - Configures the Apicurio Registry backend (REST API) component

  • spec.ui - Configures the Apicurio Registry web console component

Each component can be independently configured with its own settings for replicas, ingress, environment variables, and pod specifications.

Storage options

Apicurio Registry supports the following storage options:

  • Embedded H2 database (default) - When you do not specify a storage type, Apicurio Registry uses SQL storage with an embedded H2 database. Suitable for development and testing only. Apicurio Registry stores all data in memory and loses it when the pod restarts.

  • PostgreSQL - Stores data in a PostgreSQL database. Suitable for production deployments.

  • MySQL - Stores data in a MySQL database. Suitable for production deployments.

  • KafkaSQL - Stores data in Apache Kafka topics, with an embedded H2 database as a local SQL store that Apicurio Registry rebuilds from the Kafka journal on each startup. Suitable for production deployments when you configure persistent Kafka storage.

  • KubernetesOps - Read-only storage that loads registry data from Kubernetes ConfigMaps. Suitable for Kubernetes-native and GitOps workflows. This is an experimental feature.

The default embedded H2 configuration is not suitable for production environments. Configure a storage type (postgresql, mysql, kafkasql, or kubernetesops) for production use.

Deploying Apicurio Registry with default configuration (embedded H2 database)

You can deploy a basic Apicurio Registry instance by using the default storage configuration (SQL with an embedded H2 database). You do not need to specify a storage type in the CR. When omitted, Apicurio Registry defaults to an embedded H2 database. This configuration is suitable for development and testing environments only.

Prerequisites
Procedure
  1. In the Kubernetes web console, log in using an account with cluster administrator privileges.

  2. Change to the namespace in which the Apicurio Registry Operator is installed. For example, from the Project drop-down, select my-project.

  3. Click Installed Operators > Apicurio Registry > ApicurioRegistry3 > Create ApicurioRegistry3.

  4. Paste in the following custom resource definition:

    apiVersion: registry.apicur.io/v1
    kind: ApicurioRegistry3
    metadata:
      name: example-registry
    spec:
      app:
        ingress:
          host: registry.example.com
      ui:
        ingress:
          host: registry-ui.example.com
    Replace the host values with appropriate hostnames for your environment. Currently, Apicurio Registry Operator only creates simple HTTP Ingresses. To enable TLS, you must create your own Ingress or Route resources with TLS configuration.
  5. Click Create and wait for the Apicurio Registry deployment to be created.

  6. Click Networking > Ingresses (or Routes) to access the route for the Apicurio Registry web console.

Verification
  • Access the Apicurio Registry web console using the configured hostname and verify that the UI loads successfully.

Deploying Apicurio Registry with PostgreSQL storage

Deploy Apicurio Registry with PostgreSQL database storage. This configuration is suitable for production environments.

Prerequisites
  • You must have cluster administrator access to an Kubernetes cluster.

  • You must have already installed the Apicurio Registry Operator. See Installing Apicurio Registry on OpenShift.

  • You must have a PostgreSQL database available with a database created for Apicurio Registry.

  • You must have created a Kubernetes Secret containing the PostgreSQL database password.

Procedure
  1. Create a Secret containing the database password:

    apiVersion: v1
    kind: Secret
    metadata:
      name: postgresql-credentials
    type: Opaque
    stringData:
      password: your-database-password
  2. In the Kubernetes web console, click Installed Operators > Apicurio Registry > ApicurioRegistry3 > Create ApicurioRegistry3.

  3. Paste in the following custom resource definition, adjusting the values for your environment:

    apiVersion: registry.apicur.io/v1
    kind: ApicurioRegistry3
    metadata:
      name: example-registry-postgresql
    spec:
      app:
        storage:
          type: postgresql
          sql:
            dataSource:
              url: jdbc:postgresql://postgresql.my-project.svc:5432/registry
              username: registry_user
              password:
                name: postgresql-credentials
                key: password
        ingress:
          host: registry.example.com
      ui:
        ingress:
          host: registry-ui.example.com
    Update the url to match your PostgreSQL service name, namespace, port, and database name. Update the username to match your database user.
  4. Click Create and wait for the Apicurio Registry deployment to be created.

Verification
  • Access the Apicurio Registry web console and create a test artifact to verify that data is being persisted to the database.

  • Restart the Apicurio Registry pod and verify that the artifact still exists, confirming that data is persisted.

Deploying Apicurio Registry with MySQL storage

Deploy Apicurio Registry with MySQL database storage. This configuration is suitable for production environments.

Prerequisites
  • You must have cluster administrator access to an Kubernetes cluster.

  • You must have already installed the Apicurio Registry Operator. See Installing Apicurio Registry on OpenShift.

  • You must have a MySQL database available with a database created for Apicurio Registry.

  • You must have created a Kubernetes Secret containing the MySQL database password.

Procedure
  1. Create a Secret containing the database password:

    apiVersion: v1
    kind: Secret
    metadata:
      name: mysql-credentials
    type: Opaque
    stringData:
      password: your-database-password
  2. In the Kubernetes web console, click Installed Operators > Apicurio Registry > ApicurioRegistry3 > Create ApicurioRegistry3.

  3. Paste in the following custom resource definition, adjusting the values for your environment:

    apiVersion: registry.apicur.io/v1
    kind: ApicurioRegistry3
    metadata:
      name: example-registry-mysql
    spec:
      app:
        storage:
          type: mysql
          sql:
            dataSource:
              url: jdbc:mysql://mysql.my-project.svc:3306/registry
              username: registry_user
              password:
                name: mysql-credentials
                key: password
        ingress:
          host: registry.example.com
      ui:
        ingress:
          host: registry-ui.example.com
    Update the url to match your MySQL service name, namespace, port, and database name. Update the username to match your database user.
  4. Click Create and wait for the Apicurio Registry deployment to be created.

Verification
  • Access the Apicurio Registry web console and create a test artifact to verify that data is being persisted to the database.

  • Restart the Apicurio Registry pod and verify that the artifact still exists, confirming that data is persisted.

Deploying Apicurio Registry with KafkaSQL storage

You can deploy Apicurio Registry with KafkaSQL storage. KafkaSQL uses Apache Kafka as the primary data store, with an embedded H2 database as a local SQL store that Apicurio Registry rebuilds from the Kafka journal on each startup. This configuration is suitable for production environments when you configure persistent Kafka storage.

Prerequisites
Procedure
  1. Obtain the Kafka bootstrap servers address from your Kafka cluster. For example, with Strimzi: my-cluster-kafka-bootstrap.my-project.svc:9092

  2. In the Kubernetes web console, click Installed Operators > Apicurio Registry > ApicurioRegistry3 > Create ApicurioRegistry3.

  3. Paste in the following custom resource definition, adjusting the bootstrapServers value:

    apiVersion: registry.apicur.io/v1
    kind: ApicurioRegistry3
    metadata:
      name: example-registry-kafkasql
    spec:
      app:
        storage:
          type: kafkasql
          kafkasql:
            bootstrapServers: my-cluster-kafka-bootstrap.my-project.svc:9092
        ingress:
          host: registry.example.com
      ui:
        ingress:
          host: registry-ui.example.com
  4. Click Create and wait for the Apicurio Registry deployment to be created.

  5. If using Strimzi, configure the Kafka topic that Apicurio Registry uses (named kafkasql-journal by default) with delete cleanup policy and infinite retention:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaTopic
    metadata:
      name: kafkasql-journal
      labels:
        strimzi.io/cluster: my-cluster
    spec:
      partitions: 3
      replicas: 3
      config:
        cleanup.policy: delete
        retention.ms: -1
        retention.bytes: -1
    You must configure the Kafka topic used by Apicurio Registry with cleanup.policy: delete and infinite retention (retention.ms: -1 and retention.bytes: -1), otherwise data loss might occur.
Verification
  • Access the Apicurio Registry web console and create a test artifact to verify that data is being persisted to Kafka.

  • Restart the Apicurio Registry pod and verify that the artifact still exists after the cache is rebuilt from Kafka.

KafkaSQL TLS configuration

When your Kafka cluster requires TLS encryption, you can configure Apicurio Registry to connect securely.

apiVersion: registry.apicur.io/v1
kind: ApicurioRegistry3
metadata:
  name: example-registry-kafkasql-tls
spec:
  app:
    storage:
      type: kafkasql
      kafkasql:
        bootstrapServers: my-cluster-kafka-bootstrap.my-project.svc:9093
        tls:
          truststoreSecretRef:
            name: kafka-cluster-ca-cert
            key: ca.p12
          truststorePasswordSecretRef:
            name: kafka-cluster-ca-cert
            key: ca.password
    ingress:
      host: registry.example.com
The Secret containing the Kafka cluster CA certificate must be in PKCS12 format.

KafkaSQL SASL authentication configuration

When your Kafka cluster requires SASL authentication (such as SCRAM-SHA-512), the recommended approach is to use the Strimzi Kafka Access Operator (available starting with Apicurio Registry version 3.2.0), which automatically provides all connection details in a single Kubernetes Secret.

apiVersion: registry.apicur.io/v1
kind: ApicurioRegistry3
metadata:
  name: example-registry-kafkasql-sasl
spec:
  app:
    storage:
      type: kafkasql
      kafkasql:
        kafkaAccessSecretName: my-kafka-access
    ingress:
      host: registry.example.com

For OAuth (OAUTHBEARER) authentication, use the auth section instead:

apiVersion: registry.apicur.io/v1
kind: ApicurioRegistry3
metadata:
  name: example-registry-kafkasql-oauth
spec:
  app:
    storage:
      type: kafkasql
      kafkasql:
        bootstrapServers: my-cluster-kafka-bootstrap.my-project.svc:9093
        tls:
          truststoreSecretRef:
            name: kafka-cluster-ca-cert
          truststorePasswordSecretRef:
            name: kafka-cluster-ca-cert
        auth:
          enabled: true
          mechanism: OAUTHBEARER
          clientIdRef:
            name: kafka-oauth-credentials
            key: clientId
          clientSecretRef:
            name: kafka-oauth-credentials
            key: clientSecret
          tokenEndpoint: https://identity-server.example.com/token
          loginHandlerClass: io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler
    ingress:
      host: registry.example.com

Deploying Apicurio Registry with KubernetesOps storage

Deploy Apicurio Registry with KubernetesOps storage. KubernetesOps is a read-only storage variant that loads registry data from Kubernetes ConfigMaps, enabling Kubernetes-native and GitOps workflows for managing schemas and APIs.

KubernetesOps storage is an experimental feature. You must enable the experimental features gate to use it.
Prerequisites
  • You must have cluster administrator access to an Kubernetes cluster.

  • You must have already installed the Apicurio Registry Operator. See Installing Apicurio Registry on OpenShift.

  • You must have access to create ConfigMaps in your cluster. The Apicurio Registry Operator creates the required RBAC resources automatically.

Procedure
  1. In the Kubernetes web console, click Installed Operators > Apicurio Registry > ApicurioRegistry3 > Create ApicurioRegistry3.

  2. Paste in the following custom resource definition, adjusting the values for your environment:

    apiVersion: registry.apicur.io/v1
    kind: ApicurioRegistry3
    metadata:
      name: example-registry-kubernetesops
    spec:
      app:
        storage:
          type: kubernetesops
          kubernetesops:
            registryId: my-registry
            namespace: apicurio
        ingress:
          host: registry.example.com
      ui:
        ingress:
          host: registry-ui.example.com
    Replace registryId with a unique identifier for your registry instance, and namespace with the namespace containing your ConfigMaps. The operator automatically enables the experimental features gate required by KubernetesOps storage.
  3. Optional: Verify that the Apicurio Registry Operator created the RBAC resources that grant the registry read access to ConfigMaps. The Apicurio Registry Operator automatically creates a ServiceAccount, a Role, and a RoleBinding, each named <cr-name>-kubeops, and sets the service account on the registry deployment. For deployments without the Apicurio Registry Operator, see RBAC requirements.

  4. Create ConfigMaps containing your registry data. See ConfigMap data format for the required format.

  5. Click Create and wait for the Apicurio Registry deployment to be created.

Verification
  • Access the Apicurio Registry web console and verify that artifacts from your ConfigMaps are visible.

  • Note that KubernetesOps storage is read-only. You cannot create, update, or delete artifacts through the REST API or web console.

Configuring authentication and authorization

Configure Apicurio Registry with OIDC authentication and role-based authorization by using an identity provider such as Keycloak.

Prerequisites
Procedure
  1. Configure two clients in your identity provider:

    • Backend API client (for example, registry-client-api) - Used by the Apicurio Registry backend (REST API) component.

    • UI client (for example, registry-client-ui) - Used by the Apicurio Registry web console component.

  2. Update your ApicurioRegistry3 custom resource to enable authentication:

    apiVersion: registry.apicur.io/v1
    kind: ApicurioRegistry3
    metadata:
      name: example-registry
    spec:
      app:
        auth:
          enabled: true
          appClientId: registry-client-api
          uiClientId: registry-client-ui
          authServerUrl: https://keycloak.example.com/realms/registry
          redirectUri: https://registry-ui.example.com
          logoutUrl: https://registry-ui.example.com
        ingress:
          host: registry.example.com
      ui:
        ingress:
          host: registry-ui.example.com
  3. To enable role-based authorization, add the authz configuration:

    spec:
      app:
        auth:
          enabled: true
          appClientId: registry-client-api
          uiClientId: registry-client-ui
          authServerUrl: https://keycloak.example.com/realms/registry
          redirectUri: https://registry-ui.example.com
          logoutUrl: https://registry-ui.example.com
          authz:
            enabled: true
            ownerOnlyEnabled: true
            roles:
              source: token
              admin: sr-admin
              developer: sr-developer
              readOnly: sr-readonly
        ingress:
          host: registry.example.com
  4. To enable admin override functionality:

    spec:
      app:
        auth:
          authz:
            enabled: true
            ownerOnlyEnabled: true
            adminOverride:
              enabled: true
              from: token
              type: role
              role: sr-admin
  5. To allow anonymous read-only access:

    spec:
      app:
        auth:
          enabled: true
          anonymousReadsEnabled: true
          appClientId: registry-client-api
          # ... other auth settings
Verification
  • Access the Apicurio Registry web console and verify that you are redirected to the identity provider login page.

  • Log in with different users having different roles and verify that authorization is enforced correctly.

Basic authentication for client credentials

To enable HTTP basic authentication for client credentials flow (useful for service accounts), add the basicAuth configuration to your ApicurioRegistry3 custom resource.

spec:
  app:
    auth:
      enabled: true
      appClientId: registry-client-api
      authServerUrl: https://keycloak.example.com/realms/registry
      basicAuth:
        enabled: true
        cacheExpiration: 25m

TLS configuration for OIDC connections

When your identity provider uses custom certificates, configure TLS verification in your ApicurioRegistry3 custom resource.

spec:
  app:
    auth:
      enabled: true
      appClientId: registry-client-api
      authServerUrl: https://keycloak.example.com/realms/registry
      tls:
        tlsVerificationType: all
        truststoreSecretRef:
          name: keycloak-ca-cert
          key: ca.p12
        truststorePasswordSecretRef:
          name: keycloak-ca-cert
          key: ca.password
Set tlsVerificationType to none to disable TLS verification (not recommended for production).

Ingress hostname and class configuration

You can specify the Ingress hostname and IngressClass for each component.

apiVersion: registry.apicur.io/v1
kind: ApicurioRegistry3
metadata:
  name: example-registry
spec:
  app:
    ingress:
      host: registry-api.example.com
      ingressClassName: nginx
      annotations:
        nginx.org/proxy-connect-timeout: "30s"
  ui:
    ingress:
      host: registry-ui.example.com
      ingressClassName: nginx
      annotations:
        nginx.org/proxy-connect-timeout: "30s"

Operator-managed Ingress configuration

To manage Ingress resources manually, disable the operator-managed Ingress.

spec:
  app:
    ingress:
      enabled: false
  ui:
    ingress:
      enabled: false
When Ingress is disabled, you must create your own Ingress or Route resources to expose the Apicurio Registry services.

NetworkPolicy configuration

The operator creates NetworkPolicy resources by default. To manage NetworkPolicy manually, disable the operator-managed NetworkPolicy.

spec:
  app:
    networkPolicy:
      enabled: false
  ui:
    networkPolicy:
      enabled: false

Resource deletion configuration

By default, artifacts and groups in Apicurio Registry are immutable and cannot be deleted. To enable deletion, set the resourceDeleteEnabled feature flag.

apiVersion: registry.apicur.io/v1
kind: ApicurioRegistry3
metadata:
  name: example-registry
spec:
  app:
    features:
      resourceDeleteEnabled: true

Artifact version mutability configuration

By default, artifact versions are immutable once created. To allow draft versions to be mutable, set the versionMutabilityEnabled feature flag.

spec:
  app:
    features:
      versionMutabilityEnabled: true
Enabling version mutability also unlocks Studio functionality in the Apicurio Registry UI.

UI component configuration

If you only need the REST API and do not want to deploy the UI, disable the UI component.

apiVersion: registry.apicur.io/v1
kind: ApicurioRegistry3
metadata:
  name: example-registry
spec:
  app:
    ingress:
      host: registry.example.com
  ui:
    enabled: false

UI environment variable configuration

You can configure the UI with environment variables in the ApicurioRegistry3 custom resource.

spec:
  ui:
    env:
      - name: REGISTRY_API_URL
        value: https://registry.example.com/apis/registry/v3
    ingress:
      host: registry-ui.example.com

Replica configuration

You can configure the number of replicas for each component.

apiVersion: registry.apicur.io/v1
kind: ApicurioRegistry3
metadata:
  name: example-registry
spec:
  app:
    replicas: 3
    ingress:
      host: registry.example.com
  ui:
    replicas: 2
    ingress:
      host: registry-ui.example.com

Autoscaling configuration

You can configure the Apicurio Registry Operator to manage a horizontal pod autoscaler (HPA) for the app and UI components. When autoscaling is enabled, the Apicurio Registry Operator creates an HPA that targets the component’s Deployment, and the static replicas field is ignored.

apiVersion: registry.apicur.io/v1
kind: ApicurioRegistry3
metadata:
  name: example-registry
spec:
  app:
    autoscaling:
      enabled: true
      minReplicas: 2
      maxReplicas: 5
      targetCPUUtilizationPercentage: 70
Table 1. Autoscaling fields
Field Description Type Default

enabled

Whether the Apicurio Registry Operator manages a HorizontalPodAutoscaler for the component.

Boolean

false

minReplicas

Minimum number of replicas.

Integer

1

maxReplicas

Maximum number of replicas. Set this field when you enable autoscaling; when omitted, it falls back to the minReplicas value.

Integer

minReplicas

targetCPUUtilizationPercentage

Target average CPU utilization percentage across all pods.

Integer

80

targetMemoryUtilizationPercentage

Target average memory utilization percentage across all pods. When not set, memory-based scaling is not configured.

Integer

Not set

The autoscaling configuration is available on both spec.app.autoscaling and spec.ui.autoscaling. If you set both replicas and autoscaling on a component, the Apicurio Registry Operator reports a validation error condition and ignores the replicas field. The Apicurio Registry Operator also manages a PodDisruptionBudget when autoscaling is enabled with maxReplicas greater than 1.

PodDisruptionBudget configuration

The operator creates PodDisruptionBudget resources by default. To manage PodDisruptionBudget manually, disable the operator-managed PodDisruptionBudget.

spec:
  app:
    podDisruptionBudget:
      enabled: false
  ui:
    podDisruptionBudget:
      enabled: false

Environment variable configuration

You can add custom environment variables to Apicurio Registry components.

spec:
  app:
    env:
      - name: QUARKUS_LOG_LEVEL
        value: DEBUG
      - name: CUSTOM_CONFIG
        valueFrom:
          configMapKeyRef:
            name: my-config
            key: custom.value
Order of evaluation: The environment variables defined in the env field override any environment variables set by the operator. This enables you to customize configuration and provide workarounds while still benefiting from operator-managed settings. Do not use the custom PodTemplateSpec method to set environment variables.

PodTemplateSpec advanced customization

For advanced pod configuration, you can provide a custom PodTemplateSpec.

spec:
  app:
    podTemplateSpec:
      metadata:
        labels:
          custom-label: custom-value
        annotations:
          custom-annotation: custom-value
      spec:
        containers:
          - name: apicurio-registry-app
            resources:
              requests:
                memory: "512Mi"
                cpu: "500m"
              limits:
                memory: "1Gi"
                cpu: "1000m"
        affinity:
          podAntiAffinity:
            preferredDuringSchedulingIgnoredDuringExecution:
              - weight: 100
                podAffinityTerm:
                  labelSelector:
                    matchExpressions:
                      - key: app
                        operator: In
                        values:
                          - apicurio-registry
                  topologyKey: kubernetes.io/hostname

To customize the component container (for example, to set resource requests/limits), you must specify the container name as follows:

  • apicurio-registry-app for the Apicurio Registry backend (REST API) component.

  • apicurio-registry-ui for the Apicurio Registry web console component.

You can also add additional containers to the pod if needed.

Order of evaluation: The operator first extends the provided PodTemplateSpec with default values and then applies additional configuration based on other fields in the ApicurioRegistry3 CR. Therefore, other configuration fields might override settings in the PodTemplateSpec.

OpenShift Console plugin configuration

On OpenShift, the Apicurio Registry Operator can deploy a console plugin that adds an Apicurio section to the OpenShift Console administrator perspective, with pages for listing and inspecting ApicurioRegistry3 instances.

To deploy the console plugin, both of the following conditions must be met:

  • The top-level spec.consolePlugin.enabled field is set to true in the custom resource. The field defaults to false.

  • The console plugin image is configured on the Apicurio Registry Operator, by using the REGISTRY_CONSOLE_PLUGIN_IMAGE environment variable on the operator deployment.

spec:
  consolePlugin:
    enabled: true

The Apicurio Registry Operator then creates a console plugin Deployment and Service secured with OpenShift service serving certificates, and registers a cluster-scoped ConsolePlugin resource named <cr-name>-console-plugin. The plugin backend forwards the logged-in user’s OpenShift bearer token to the registry API. On clusters that are not OpenShift, the console plugin is not deployed.

Application TLS configuration

To configure TLS certificates for the Apicurio Registry application, provide keystore references in the ApicurioRegistry3 custom resource.

spec:
  app:
    tls:
      keystoreSecretRef:
        name: registry-tls
        key: keystore.p12
      keystorePasswordSecretRef:
        name: registry-tls
        key: keystore.password