How to Enable Apicurio Registry
This guide shows you how to switch Apicurio Registry v3 on in the Axual Streaming chart, apply a working base configuration, and confirm the registry is reachable over TLS before you register a schema against it.
Type |
How-to guide |
Goal |
Get Apicurio Registry v3 running as part of an Axual Streaming installation. |
Audience |
Platform Operator who can edit the Axual Streaming values and apply them. |
When to use |
Use this guide when installing the streaming layer, or when adding Apicurio Registry to an installation that has none. |
Apicurio Registry is a runtime server that stores schemas as artifacts, so producers can reference a schema by id instead of carrying it in every record.
Prerequisites
Confirm the following before you begin.
Access and permissions required
You need the following access and permissions:
-
Permission to edit the Axual Streaming values and apply them.
Tools and versions required
You need the following tools:
-
helm>= 3.12, or access to the pipeline that applies the values. -
openssl, for the verification step.
Resources that must exist before starting
The following must already exist:
-
A running Apache Kafka cluster, because Apicurio stores its artifacts on a Kafka topic.
-
A DNS name and a server certificate for the registry, plus a client certificate whose identity matches that server certificate.
| Apicurio must use a client certificate whose identity matches the DNS name in its server certificate. When they differ, Apicurio cannot obtain the Access Control List (ACL) entries it needs, and the failure appears as an authorisation error rather than a certificate error. |
Enable the chart dependency
Axual Streaming charts 3.0.0 and later deploy Apicurio Registry v3 by default. Set global.apicurio-registry-v3.enabled to true in your values so the file states that the registry runs.
global:
apicurio-registry-v3:
enabled: true
Apply the base configuration
The example below is a working starting point: it stores artifacts on a Kafka topic and authenticates through Keycloak. Adjust the hostnames, Secret names and Keycloak details to your installation.
Click to open apicurio-values.yaml
global:
apicurio-registry-v3:
enabled: true
apicurio-registry-v3:
logLevel: INFO
# In Apicurio v3 the web UI runs as its own container.
# `registryApiUrl` is REQUIRED: it is the public HTTPS URL the browser uses to reach the API.
# Do NOT use localhost - this URL is resolved by the user's browser, not by the container.
ui:
config:
registryApiUrl: "https://apicurio.<domain>/apis/registry/v3"
# Application configuration, injected as an application.properties file.
# Apicurio v3 uses the `apicurio.*` property prefix.
config:
apicurio.auth.anonymous-read-access.enabled: "true"
apicurio.auth.role-based-authorization: "true"
apicurio.auth.owner-only-authorization: "true"
apicurio.auth.admin-override.enabled: "true"
# The configuration related to authentication and authorization of users to the registry.
# Note: security.authentication.enabled must be enabled for any other authentication feature to work.
security:
authentication:
enabled: true
basicAuthEnabled: true
# Attributes required for Apicurio to access the Keycloak instance
keycloak:
authUrl: "https://apicurio-keycloak.<domain>/auth"
realm: "<realm>" # Typically it is set to apicurio
webClientId: "apicurio-web"
webRedirectUrl: "https://apicurio.<domain>"
# Kafka storage. Apicurio v3 uses three topics (journal, snapshots, events). All three are
# created by the init container below, together with the ACLs for the Apicurio principal.
kafka:
# -- Kafka bootstrap servers
bootstrapServers: "cluster01-kafka-bootstrap:9093"
# -- KafkaSQL journal topic (typically _{tenant}-{instance}-journal)
journalTopic: "_<tenant-short-name>-<instance-short-name>-journal"
# -- KafkaSQL snapshots topic (typically _{tenant}-{instance}-snapshots)
snapshotsTopic: "_<tenant-short-name>-<instance-short-name>-snapshots"
# -- Registry events topic (typically _{tenant}-{instance}-events)
eventsTopic: "_<tenant-short-name>-<instance-short-name>-events"
# -- Override group prefix to give access to (typically {tenant}.{instance}.apicurio)
# groupPatternOverride: ""
tls:
# -- Existing server Keypair secret name
serverKeypairSecretName: "server-cert-secret" # Server cert generated from Cert-Manager. Ensure a Kafka superUser matches the DNS of this certificate
# -- Existing client Keypair secret name
clientKeypairSecretName: "client-cert-secret" # Client cert generated from Cert-Manager with the right DNS
# -- Existing truststore secret name
truststoreCaSecretName: "my-external-ca" # The CA secret used by Cert-Manager to create the previous two certificates
kafkaInitContainer:
# -- The principal common name used to produce and consume from the schema topics (should match the one on APICURIO_KAFKASQL_SSL_KEYSTORE_LOCATION)
# If Kafka is configured to validate ACLs over the full principal chain, please provide the principal chain as this example: [0] CN=Root CA, [1] CN=Intermediate CA, [3] CN=schema-registry
# Otherwise, just provide the common name prefixed with `CN:`
apicurioPrincipal: "CN=Apicurio Client"
# -- Replication factor of the journal, snapshots and events topics
replicationFactor: "3"
# -- min.isr of the journal, snapshots and events topics
minIsr: "2"
tls:
# -- Existing Keypair secret name
keypairSecretName: "server-cert-secret"
# -- Existing Keypair key name
keypairSecretKeyName: "tls.key"
# -- Existing Keypair certificate name
keypairSecretCertName: "tls.crt"
# -- Existing Truststore secret name
truststoreCaSecretName: "my-external-ca"
# -- Existing Truststore certificate name
truststoreCaSecretCertName: "ca.crt"
# Apicurio v3 splits the ingress in two: `backend` serves the API (/apis) and `ui` serves the web UI (/).
# They can share the same hostname.
ingress:
backend:
# -- Enable creation of the backend Ingress resource (serves /apis).
enabled: true
# -- The name of the IngressClass cluster resource.
# NOTE: "nginx" refers to the community ingress-nginx controller, deprecated March 2026.
# Axual has migrated to a supported enterprise-grade ingress controller.
# Update className and annotations to match the ingress controller in your cluster.
className: "nginx"
annotations:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
# -- The fully qualified domain name of a network host.
host: "apicurio.<domain>"
tls:
- hosts:
- "apicurio.<domain>"
# This field is required to set the correct certificates on the ingress. Generated from Cert-Manager as well
secretName: "apicurio-ingress-cert-secret"
ui:
# -- Enable creation of the UI Ingress resource (serves /).
enabled: true
className: "nginx"
annotations:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
host: "apicurio.<domain>"
tls:
- hosts:
- "apicurio.<domain>"
secretName: "apicurio-ingress-cert-secret"
apicurioKeycloakMysql:
enabled: true
image:
repository: bitnamilegacy/mysql
nameOverride: "apicurio-kc-mysql"
auth:
rootPassword: "rootpassword"
database: "apicurio-kc-db"
username: "keycloak"
password: "Passw0rd1!"
primary:
resources:
requests:
cpu: 250m
memory: 200Mi
limits:
memory: 500Mi
apicurioKeycloak:
enabled: true
# -- Required when running Apicurio Keycloak on the same k8s cluster as Governance Keycloak
nameOverride: "apicurio-keycloak"
realm: "apicurio"
# -- Keycloak proxy configuration (required since Keycloak 25.0.1 when running behind an ingress)
proxy:
mode: xforwarded
http:
enabled: true
autoscaling:
enabled: false
database:
vendor: "mysql"
hostname: "streaming-apicurio-kc-mysql"
database: "apicurio-kc-db"
port: "3306"
username: "keycloak"
password: "Passw0rd1!"
# -- By default, we are importing the Apicurio realm used to Authenticate Admin access
args: [ 'start', '--import-realm' ]
extraVolumes: |
- name: keycloak-init-realm
configMap:
name: streaming-apicurio-registry-keycloak-realm
extraVolumeMounts: |
- name: keycloak-init-realm
mountPath: "/opt/keycloak/data/import"
readOnly: true
extraEnv: |
- name: KEYCLOAK_ADMIN
value: "admin"
- name: KEYCLOAK_ADMIN_PASSWORD
value: "admin123"
- name: JAVA_OPTS_APPEND
value: -Djgroups.dns.query={{ template "keycloak.serviceDnsName" . }}
- name: KC_HTTP_ENABLED
value: "true"
- name: KC_HOSTNAME_STRICT
value: "false"
ingress:
enabled: true
# NOTE: "nginx" refers to the community ingress-nginx controller, deprecated March 2026.
# Axual has migrated to a supported enterprise-grade ingress controller.
# Update className and annotations to match the ingress controller in your cluster.
className: "nginx"
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
rules:
- # -- The fully qualified domain name of a network host.
host: "apicurio-keycloak.<domain>"
paths:
- # -- Matched against the path of an incoming request.
path: "/auth"
# -- Determines the interpretation of the Path matching.
# Can be one of the following values: `Exact`, `Prefix`, `ImplementationSpecific`.
pathType: "ImplementationSpecific"
tls:
- hosts:
- "apicurio-keycloak.<domain>"
# This field is required in order to set the correct certificates to ingress. Generated from Cert-Manager as well
secretName: "keycloak-ingress-cert-secret"
resources:
requests:
cpu: 450m
memory: 200Mi
limits:
memory: 700Mi
Every key in that file is described in Apicurio Chart Values Reference. For anything the Axual chart does not wrap, see the Apicurio documentation.
Confirm the registry is reachable
Check the certificate chain the registry serves before trying to register anything, because a missing certificate authority here looks like a client problem later.
Replace every <VALUE> placeholder with your own value before running a command.
|
openssl s_client -showcerts -verify 5 -connect apicurio.<DOMAIN>:443 -servername apicurio.<DOMAIN> < /dev/null
Then attach the registry to an instance with the Apicurio Keycloak configuration steps, register a schema, and produce and consume a record with it from a Java application. That is the end-to-end check.
What to configure next
The base configuration authenticates with Keycloak and allows anonymous reads, which a production installation has to change. Continue with How to Configure Apicurio Authentication.