Apicurio Registry
Overview
Apicurio Registry is an 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. Producers and consumers across your event streaming and API estate can share a single source of truth for their data contracts.
The SecureAnyCloud image runs the official Quarkus backend under a JDK 21 runtime, with local PostgreSQL storage, under systemd. Apicurio has no built-in authentication in this configuration, so the backend is bound to loopback and never exposed directly. It listens on 127.0.0.1:8080 for the UI and REST API and on 127.0.0.1:9000 for the Quarkus management interface.
An nginx reverse proxy on port 80 serves the official prebuilt web UI and proxies the REST API. It adds a per-VM HTTP Basic Auth gate (user admin, with a unique password generated on first boot) in front of the whole surface. It also serves 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.
What you get:
- Apicurio Registry 3.2.6 running the official Quarkus backend under a JDK 21 runtime as the
apicuriosystemd service. - Local PostgreSQL storage for durable persistence of every group, artifact and version.
- The official prebuilt 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) that protects the UI and API, with a unique password generated on first boot. - The core Apicurio REST API at
/apis/registry/v3and 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
/healthzendpoint for Azure Load Balancer health probes. apicurio.service,nginx.serviceandpostgresql.serviceas systemd units, enabled and active.- The bcrypt Basic Auth hash is stored on disk only. The PostgreSQL password is rotated and the database is recreated fresh on first boot, so no usable credential ships in the image.
- 24/7 SecureAnyCloud support.
Prerequisites
- An active Azure subscription.
- An SSH key pair.
- A VNet and a 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 rules that allow
22/tcpfrom your management network,80/tcpfor the web UI and API, and443/tcpif 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 and choose Create a resource. Search the Marketplace for Apicurio Registry by SecureAnyCloud and select Create.
On the Basics tab, 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 choose Review + create, and then Create.
Step 2 - Deploy from the Azure CLI
Accept the Marketplace terms and create the virtual machine. Replace the value in angle brackets with your resource group name.
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:apicurio-registry-ubuntu-24-04:default:latest
az vm create \
--resource-group <your-rg> \
--name apicurio \
--image sac1647283583153:apicurio-registry-ubuntu-24-04:default:latest \
--size Standard_B2s \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku StandardOpen port 80 for the web UI and API:
az vm open-port --resource-group <your-rg> --name apicurio --port 80Step 3 - Connect to your VM
Connect to the VM over SSH:
ssh azureuser@<vm-public-ip>Step 4 - Confirm the services are running
Check that the three services are active:
systemctl is-active apicurio.service nginx.service postgresql.serviceAll 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.
Step 5 - Retrieve your web UI password
nginx protects the whole Apicurio surface with HTTP Basic Auth. The username is admin. A unique password is generated on the first boot of your VM and written to a root-only file. Read the file:
sudo cat /root/apicurio-credentials.txtThis 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 in a safe place.
Step 6 - Confirm the health and readiness endpoints
nginx serves an unauthenticated health endpoint for load balancers and probes. The Quarkus management interface reports readiness on loopback. Query both endpoints:
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 to use 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. Nobody reaches the registry without the password.
The following commands read the per-VM password from the credentials file and prove the round trip. An unauthenticated request 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/)"The output is unauth : 401, wrongpw : 401 and authed : 200. The whole surface is reachable only with the per-VM password, because the backend is bound to loopback and nginx is the only way in.
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 the schemas 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 call returns the JSON Schema content of the latest version of user-signup.
Your applications, CI pipelines and the apicurio-registry client libraries use the same REST API to publish and resolve schemas.
Step 9 - Register a schema with the Confluent compatible API
Apicurio also exposes a Confluent-compatible Schema Registry API at /apis/ccompat/v7. Tools and clients that speak the Confluent Schema Registry protocol work unchanged. 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/subjectsThe POST returns the assigned schema id, and the subject appears in the subject list. A Kafka producer or consumer configured with schema.registry.url uses the same endpoint.
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. Open the default group to see the three example schemas registered on first boot, each with its type and description.
Step 11 - Open an artifact and review its versions
Select an artifact, for example user-signup, to open its detail view. The Overview tab shows the artifact metadata (name, description, type and timestamps) next to the list of versions. Each artifact can hold many versions. You can create, compare and manage them from here.
Step 12 - View the schema content
Open a version and select the Content tab to view the schema in a syntax-highlighted editor. The editor has a Download button and a JSON or YAML toggle. This is the exact content that your producers and consumers resolve at runtime.
Step 13 - Configure global content rules
The Global rules page lets you enforce governance across the registry. Enable the Validity rule to ensure that content is valid when an artifact or version is created. Enable the Compatibility rule to enforce a compatibility level such as Backward for safe schema evolution. Enable the Integrity rule to enforce reference integrity.
You can also set rules per artifact from the artifact's Rules tab.
Maintenance
Service management. The registry runs as apicurio.service, PostgreSQL as postgresql.service and the reverse proxy as nginx.service. Restart the registry with sudo systemctl restart apicurio. View the 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 keep 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. Restore it into a fresh database when needed.
Scale the JVM. On first boot, the heap is sized to half of the VM memory, clamped between 512 MB and 1024 MB. 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 SecureAnyCloud 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.
Deploy on Azure
Launch Apicurio Registry on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com
Overview
Apicurio Registry is an 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/XSD artifacts through a REST API, a Confluent-compatible Schema Registry API and a web UI. Producers and consumers across your event streaming and API estate can share a single source of truth for their contracts. This image runs Apicurio Registry with its storage and web server already set up.
The registry backend is the official Apicurio Registry 3.2.6 Quarkus application. It runs under a headless OpenJDK 21 runtime as a dedicated unprivileged apicurio system account. A systemd service starts it on boot and restarts it on failure.
Durable storage is a local PostgreSQL database. Its data directory lives on a dedicated, independently resizable EBS data volume mounted at /var/lib/postgresql. nginx serves the official prebuilt React web UI statically.
This image is secure by default. Apicurio Registry has no built-in authentication in this configuration, so exposing it directly would let anyone read, write or delete your schemas. Instead, the registry backend binds to the loopback interface only. nginx on port 80 is the sole public listener, and it fronts the whole surface behind an HTTP Basic Auth gate as the admin user.
The password is generated on the first boot of every deployed instance, so two instances launched from the same AMI never share a password. It is written to /root/apicurio-credentials.txt with mode 0600, so only the root user can read it. An unauthenticated /healthz endpoint is provided for load balancer probes. A set of example schemas is registered on first boot, so the UI is populated immediately.
Prerequisites
Before you deploy this image, you need:
- An Amazon Web Services account where you can launch EC2 instances.
- IAM permissions to launch instances, create security groups and subscribe to AWS Marketplace products.
- An EC2 key pair in the target Region for SSH access to the instance.
- A VPC and subnet in the target Region, with a security group that allows inbound port 22 from your management network, port 80 for the web UI and API, and optionally port 443 if you add TLS.
- The AWS CLI (version 2) installed locally if you plan to deploy from the command line.
Launching the instance
You can launch this product from the AWS Marketplace console or from the AWS CLI. In the Marketplace console, subscribe to the product and choose Launch through EC2. Then select your instance type, VPC, subnet, key pair and security group.
A general-purpose m5.large instance is a sensible starting point. The registry runs comfortably on any instance with enough memory for the JVM and PostgreSQL. Scale up for larger artifact catalogues and higher request rates.
When you configure the security group, allow inbound TCP port 22 from your management network. Allow TCP port 80 from the networks that reach the web UI and API. The registry backend itself is never exposed directly, and nginx on port 80 is the only public listener.
Connecting to your instance
Connect over SSH as the default login user for your operating system variant. The private key is the EC2 key pair that you selected at launch.
OS variant SSH login user
Ubuntu 24.04 ubuntu
Run the following command and replace the values in angle brackets:
ssh -i /path/to/your-key.pem ubuntu@<public-ip>Retrieving the web UI and API password
The HTTP Basic Auth password is unique to each instance and is stored in a root-only file. Retrieve it over SSH:
sudo grep '^APICURIO_PASSWORD=' /root/apicurio-credentials.txtThe full credentials file also records the registry URL, the username (admin) and the PostgreSQL database credentials:
sudo cat /root/apicurio-credentials.txtVerifying the service
systemd manages the registry, PostgreSQL and nginx. Confirm that they are active:
systemctl is-active apicurio nginx postgresqlThe unauthenticated health endpoint returns ok. Point a load balancer or uptime probe at this endpoint:
curl -fsS http://127.0.0.1/healthzUsing the web UI
Open http://<public-ip>/ in a browser. Your browser prompts for credentials. Sign in as admin with the password from the credentials file.
The dashboard shows artifact and version counts, recent artifacts and quick actions. Use Explore to browse groups and artifacts. Use Search to find artifacts across the registry.
Select an artifact to see its metadata, its versions and its content. The example user-signup artifact registered on first boot is a JSON Schema that you can inspect and download. The content view renders the stored schema with syntax highlighting and a JSON/YAML toggle.
Using the core REST API
The Apicurio core REST API v3 is served on the same port 80 behind the same Basic Auth gate. List the artifacts in the default group:
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 | jq '.artifacts[].artifactId'Register a new JSON Schema artifact and read its content back to confirm it persisted:
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/registry/v3/groups/default/artifacts?ifExists=FIND_OR_CREATE_VERSION' \
-H 'Content-Type: application/json' \
-d '{"artifactId":"product-updated","artifactType":"JSON","name":"Product Updated Event","firstVersion":{"version":"1.0.0","content":{"content":"{\"type\":\"object\",\"title\":\"ProductUpdated\",\"properties\":{\"sku\":{\"type\":\"string\"}}}","contentType":"application/json"}}}' \
-o /dev/null -w 'register HTTP %{http_code}\n'
curl -s -u "admin:$PW" \
'http://127.0.0.1/apis/registry/v3/groups/default/artifacts/product-updated/versions/branch=latest/content'From your own workstation, use the instance's public address instead of loopback:
curl -s -u 'admin:<APICURIO_PASSWORD>' http://<public-ip>/apis/registry/v3/groups/default/artifactsUsing the Confluent compatible Schema Registry API
Apicurio Registry implements the API defined by the Confluent Schema Registry. Kafka producers and consumers that use the Confluent serializers work unchanged. Point them at http://<public-ip>/apis/ccompat/v7. List the registered subjects:
PW=$(sudo grep '^APICURIO_PASSWORD=' /root/apicurio-credentials.txt | cut -d= -f2-)
curl -s -u "admin:$PW" http://127.0.0.1/apis/ccompat/v7/subjectsRegister an Avro schema under a subject and read it back by its assigned id:
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\":\"orderId\",\"type\":\"string\"}]}"}' echo
curl -s -u "admin:$PW" http://127.0.0.1/apis/ccompat/v7/subjects/orders-value/versionsThe PostgreSQL data volume
The registry's durable state lives in a local PostgreSQL database whose data directory is on a dedicated EBS volume mounted at /var/lib/postgresql, separate from the operating system disk. This lets you resize or snapshot the schema store independently. Confirm the mount, and confirm that the PostgreSQL data directory sits on it:
findmnt -no SOURCE,TARGET,FSTYPE /var/lib/postgresql
sudo -u postgres psql -tAc 'SHOW data_directory'To resize the store, grow the EBS volume in the AWS console. Then extend the filesystem on the instance with resize2fs.
Backup and maintenance
Because all registry state is in PostgreSQL, a logical dump captures every group, artifact and version. Take a backup with pg_dump:
sudo -u postgres pg_dump apicurio | gzip > /var/tmp/apicurio-backup.sql.gzStore the resulting file off the instance, for example in Amazon S3. You can also take EBS snapshots of the /var/lib/postgresql volume for point-in-time backups.
The operating system is fully patched at build time and continues to receive unattended security updates.
Security notes
- The registry backend listens only on
127.0.0.1. nginx on port 80 is the only public listener, and every UI and API path except/healthzrequires authentication. - The Basic Auth password and the PostgreSQL password are both generated per instance on first boot. No shared or default credential ships in the AMI.
- Restrict the security group so that only trusted networks reach port 80. For production, add TLS termination (port 443) in front of the registry.
- The dedicated data volume can use AWS EBS encryption. Enable it when you launch the instance, or use encrypted snapshots.
Support
This AMI is published by SecureAnyCloud with 24/7 technical support included. Contact sales@secureanycloud.com for deployment help, sizing guidance, PostgreSQL and backup questions, API and authentication configuration, or any issue, including requesting refunds.
Deploy on AWS
Launch Apicurio Registry on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com