Streaming & Messaging Azure

Apicurio Registry on Ubuntu 24.04 on Azure User Guide

| Product: Apicurio Registry on Ubuntu 24.04 LTS on Azure

Overview

Apicurio Registry is a popular open source runtime registry and datastore for API definitions and event schemas. It stores and serves Avro, Protobuf, JSON Schema, OpenAPI, AsyncAPI, GraphQL and WSDL artifacts through a REST API, a Confluent compatible Schema Registry API and a React web interface, so producers and consumers across your event streaming and API estate can share a single source of truth for their data contracts. The cloudimg image runs the official Quarkus backend under a JDK 21 runtime with local PostgreSQL storage under systemd, then locks it down for a marketplace appliance. Apicurio has no built in authentication in this configuration, so the backend is bound to loopback (127.0.0.1:8080 for the UI and REST API, 127.0.0.1:9000 for the Quarkus management interface) and never exposed directly. An nginx reverse proxy on port 80 serves the official pre built web UI and proxies the REST API, adding a per VM HTTP Basic Auth gate (user admin, unique password generated on first boot) in front of the whole surface, plus an unauthenticated /healthz endpoint for load balancer probes. A set of example schemas is registered on first boot so the browsing UI is populated out of the box. Backed by 24/7 cloudimg support.

What is included:

  • Apicurio Registry 3.2.6 running the official Quarkus backend under a JDK 21 runtime as the apicurio systemd service
  • Local PostgreSQL storage for durable persistence of every group, artifact and version
  • The official pre built React web UI and the REST API on :80, fronted by nginx with the backend bound to loopback only
  • Per VM HTTP Basic Auth (user admin) protecting the UI and API, with a unique password generated on first boot
  • The core Apicurio REST API at /apis/registry/v3 and the Confluent compatible Schema Registry API at /apis/ccompat/v7
  • Three example schemas registered on first boot so the UI is populated immediately
  • An unauthenticated /healthz endpoint for Azure Load Balancer health probes
  • apicurio.service, nginx.service and postgresql.service as systemd units, enabled and active
  • The bcrypt Basic Auth hash stored on disk only, the PostgreSQL password rotated and the database recreated fresh on first boot, so no usable credential ships in the image
  • 24/7 cloudimg support

Prerequisites

An active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a comfortable starting point; raise the size for heavy schema traffic. NSG inbound: allow 22/tcp from your management network, 80/tcp for the web UI and API, and 443/tcp if you add TLS. Apicurio serves plain HTTP on port 80; for production, terminate TLS in front of it with your own domain and restrict access to trusted IP ranges (see Maintenance).

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Apicurio Registry by cloudimg, and select Create. On Basics pick your subscription, resource group, region and size; under Administrator account choose SSH public key and paste your key; under Inbound port rules allow SSH (22) and HTTP (80). Then Review + create then Create.

Step 2 - Deploy from the Azure CLI

az vm create \
  --resource-group <your-rg> \
  --name apicurio \
  --image <marketplace-image-urn> \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard

Open port 80 for the web UI and API:

az vm open-port --resource-group <your-rg> --name apicurio --port 80

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the services are running

systemctl is-active apicurio.service nginx.service postgresql.service

All three report active. The Apicurio backend serves its UI and REST API on the loopback address 127.0.0.1:8080 and its management interface on 127.0.0.1:9000; nginx fronts it on port 80 and adds the per VM HTTP Basic Auth gate. The backend is never bound to a public interface, so nginx is the only way in.

The apicurio, nginx and postgresql services reporting active, the backend listening on loopback 127.0.0.1:8080 and 127.0.0.1:9000, nginx listening on port 80, and the registry reporting version 3.2.6

Step 5 - Retrieve your web UI password

nginx protects the whole Apicurio surface with HTTP Basic Auth. The username is admin and a unique password is generated on the first boot of your VM and written to a root only file:

sudo cat /root/apicurio-credentials.txt

This file contains APICURIO_USERNAME, APICURIO_PASSWORD and the APICURIO_URL to open in a browser, along with the local PostgreSQL credentials. The web UI password is stored on disk only as a bcrypt hash in /etc/nginx/.apicurio.htpasswd, so no plaintext password ships in the image. Store the password somewhere safe.

The registry reporting version 3.2.6 from the system info endpoint and the per VM credentials file with the generated admin username, masked password and URL

Step 6 - Confirm the health and readiness endpoints

nginx serves an unauthenticated health endpoint for load balancers and probes, and the Quarkus management interface reports readiness on loopback:

curl -s http://localhost/healthz
curl -s http://127.0.0.1:9000/health/ready

/healthz returns ok and the readiness endpoint reports "status":"UP". The /healthz endpoint never requires authentication, so it is safe for an Azure Load Balancer health probe.

Step 7 - Confirm authentication

Because a password is set on first boot, an unauthenticated request to the UI or API returns HTTP 401, so nobody reaches the registry without the password. The following reads the per VM password from the credentials file and proves the round trip - unauthenticated is rejected, a wrong password is rejected, and the correct password authenticates:

PW=$(sudo grep '^APICURIO_PASSWORD=' /root/apicurio-credentials.txt | cut -d= -f2-)
echo "unauth  : $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1/)"
echo "wrongpw : $(curl -s -o /dev/null -w '%{http_code}' -u admin:wrong-pw http://127.0.0.1/)"
echo "authed  : $(curl -s -o /dev/null -w '%{http_code}' -u admin:$PW http://127.0.0.1/)"

It prints unauth : 401, wrongpw : 401 and authed : 200. The whole surface is only reachable with the per VM password because the backend is bound to loopback and nginx is the only way in.

The health endpoint returning ok, the readiness endpoint reporting status UP, and the HTTP Basic Auth round trip returning 401 unauthenticated, 401 for a wrong password, and 200 with the per VM password

Step 8 - List and fetch schemas with the core REST API

The core Apicurio REST API is at /apis/registry/v3. The image registers three example schemas in the default group on first boot. List them and fetch one back:

PW=$(sudo grep '^APICURIO_PASSWORD=' /root/apicurio-credentials.txt | cut -d= -f2-)
curl -s -u "admin:$PW" http://127.0.0.1/apis/registry/v3/groups/default/artifacts
curl -s -u "admin:$PW" \
  "http://127.0.0.1/apis/registry/v3/groups/default/artifacts/user-signup/versions/branch=latest/content"

The first call lists user-signup (JSON Schema), payment-received (Avro) and order-placed (JSON Schema). The second returns the JSON Schema content of the latest version of user-signup. The same REST API is what your applications, CI pipelines and the apicurio-registry client libraries use to publish and resolve schemas.

The REST API listing the three example artifacts in the default group with their types, and the user-signup JSON Schema content fetched back

Step 9 - Register a schema with the Confluent compatible API

Apicurio also exposes a Confluent compatible Schema Registry API at /apis/ccompat/v7, so tools and clients that speak the Confluent Schema Registry protocol work unchanged - just point them at the registry URL with the Basic Auth credentials. Register an Avro schema under a subject and read it back:

PW=$(sudo grep '^APICURIO_PASSWORD=' /root/apicurio-credentials.txt | cut -d= -f2-)
curl -s -u "admin:$PW" -X POST \
  http://127.0.0.1/apis/ccompat/v7/subjects/orders-value/versions \
  -H 'Content-Type: application/vnd.schemaregistry.v1+json' \
  -d '{"schemaType":"AVRO","schema":"{\"type\":\"record\",\"name\":\"Order\",\"fields\":[{\"name\":\"id\",\"type\":\"string\"}]}"}'
curl -s -u "admin:$PW" http://127.0.0.1/apis/ccompat/v7/subjects

The POST returns the assigned schema id and the subject appears in the subject list. This is the same endpoint a Kafka producer or consumer configured with schema.registry.url would use.

Step 10 - Sign in and browse the artifacts

Open http://<vm-public-ip>/ in a browser. The browser prompts for the HTTP Basic Auth credentials: enter admin and the password from Step 5. The Apicurio Registry Explore view opens. Click into the default group to see the three example schemas registered on first boot, each with its type and description.

The Apicurio Registry Explore view showing the default group with its three example artifacts - order placed, payment received and user signup - listed with their types and descriptions

Step 11 - Open an artifact and review its versions

Click an artifact, for example user-signup, to open its detail view. The Overview tab shows the artifact metadata - name, description, type and timestamps - alongside the list of versions. Each artifact can hold many versions, and you can create, compare and manage them from here.

The user-signup artifact detail view showing the artifact metadata on the left - name, description, type JSON and timestamps - and the versions in artifact panel listing version 1.0.0 on the right

Step 12 - View the schema content

Open a version and select the Content tab to view the schema itself in a syntax highlighted editor, with a Download button and a JSON or YAML toggle. This is the exact content your producers and consumers resolve at runtime.

The content view of user-signup version 1.0.0 showing the JSON Schema in a syntax highlighted editor with a Download button and a JSON or YAML toggle

Step 13 - Configure global content rules

The Global rules page lets you enforce governance across the registry. Enable the Validity rule to ensure content is valid when an artifact or version is created, the Compatibility rule to enforce a compatibility level such as Backward for safe schema evolution, and the Integrity rule to enforce reference integrity. Rules can also be set per artifact from an artifact's Rules tab.

The Global rules page showing the Validity, Compatibility and Integrity rules, each with a description and an Enable button

Maintenance

Service management. The registry runs as apicurio.service; PostgreSQL as postgresql.service; the reverse proxy as nginx.service. Restart the registry with sudo systemctl restart apicurio and view logs with sudo journalctl -u apicurio -f.

Add TLS and a domain. For production, put your own domain in front and terminate TLS. Point DNS at the VM, then either add a certbot managed certificate to nginx or place the VM behind an Azure Application Gateway or Front Door that terminates HTTPS. Keep the backend bound to loopback and nginx as the only public listener.

Rotate the web UI password. Generate a new bcrypt entry for user admin and reload nginx:

NEWPW=$(openssl rand -base64 24 | tr -dc 'A-Za-z0-9' | head -c 24)
printf '%s\n' "$NEWPW" | sudo htpasswd -iB /etc/nginx/.apicurio.htpasswd admin
sudo systemctl reload nginx
echo "new password: $NEWPW"

Back up your schemas. All groups, artifacts and versions live in the local PostgreSQL database apicurio. Take a logical backup with sudo -u postgres pg_dump apicurio > apicurio-backup.sql and restore it into a fresh database when needed.

Scale the JVM. The heap is sized to half of the VM memory (clamped between 512 MB and 1024 MB) on first boot. For a larger VM, override APICURIO_JAVA_OPTS in /etc/apicurio/apicurio.env and restart the service.

Support

This image is backed by 24/7 cloudimg support. Apicurio is a trademark of Red Hat, Inc. All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.