Streaming & Messaging Azure

AKHQ for Apache Kafka on Ubuntu 24.04 on Azure User Guide

| Product: AKHQ for Apache Kafka on Ubuntu 24.04 LTS on Azure

Overview

AKHQ is a fast, open source web GUI for managing and observing Apache Kafka. From a single browser console you can inspect nodes and their configuration, browse topics and partitions, read and search live messages, monitor consumer groups and their lag, and work with schemas, connectors and ACLs. Because AKHQ is a management console rather than a broker, it needs a Kafka cluster to talk to, so this cloudimg image bundles one: a single node Apache Kafka 4.3 broker running in KRaft mode (no ZooKeeper) alongside AKHQ, giving you a complete, self contained Kafka workbench that is useful the moment the instance boots.

The image ships AKHQ 0.27.1 as a Micronaut service behind an nginx reverse proxy on port 80, on a hardened, fully patched Ubuntu 24.04 LTS base. The bundled Kafka broker listens only on the loopback interface, so it is never exposed to the network; the only client that talks to it is AKHQ on the same host. AKHQ is secured with authentication enabled, and a unique administrator password and token signing secret are generated on the first boot of every VM. A set of demo topics with sample messages and a consumer group are seeded at first boot so the console shows real data straight away. Backed by 24/7 cloudimg support.

What is included:

  • AKHQ 0.27.1 served by nginx on port 80, running as a Micronaut service on a bundled Eclipse Temurin 25 JRE
  • A bundled single node Apache Kafka 4.3.1 broker in KRaft mode (no ZooKeeper), already formatted and running
  • AKHQ security enabled by default, with a per VM administrator password and a per VM token signing secret generated on first boot and recorded in a root only file
  • No shipped default login: authentication is switched on and no known or blank credential authenticates
  • The Kafka broker bound to 127.0.0.1 only (ports 9092 and 9093), never exposed to the network
  • Demo topics (demo-orders, demo-payments, demo-users) with sample messages and a demo-consumer consumer group, seeded on first boot
  • kafka.service, akhq.service and nginx.service as enabled systemd units
  • An unauthenticated /health endpoint on the loopback management port for liveness checks
  • 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 sensible starting point and is what the image is tuned for; size up for larger clusters or heavier browsing. NSG inbound: allow 22/tcp from your management network and 80/tcp for the console. AKHQ serves plain HTTP on port 80; for production, terminate TLS in front of it with your own domain. The bundled Kafka broker is never exposed: it listens on 127.0.0.1 only, so ports 9092 and 9093 stay off the network.

Step 1 - Deploy the image

Option A: Azure portal

  1. In the Azure portal, open Create a resource and search for AKHQ for Apache Kafka on Ubuntu 24.04 LTS by cloudimg.
  2. Select the plan and click Create.
  3. On the Basics tab, choose your subscription, resource group and region, name the VM, and select Standard_B2s.
  4. Set Authentication type to SSH public key, with azureuser as the username, and provide your public key.
  5. On the Networking tab, allow inbound 22/tcp (from your IP) and 80/tcp.
  6. Review and create. When deployment completes, note the VM's public IP address.

Option B: Azure CLI

az vm create \
  --resource-group my-akhq-rg \
  --name akhq \
  --image cloudimg:akhq-ubuntu-24-04:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard
az vm open-port --resource-group my-akhq-rg --name akhq --port 80 --priority 900

Step 2 - Confirm the services are running

SSH in as azureuser and confirm the three systemd units are active. kafka.service is the bundled broker, akhq.service is the web console, and nginx.service is the reverse proxy on port 80.

systemctl is-active kafka akhq nginx

Expected output:

active
active
active

AKHQ exposes a management health endpoint on the loopback port 28081, which you can use for liveness checks:

curl -s http://127.0.0.1:28081/health
{"name":"akhq","status":"UP", ... }

The bundled broker, the console and the management endpoint all bind to the loopback interface; nginx on port 80 is the sole external surface. You can confirm the listening sockets:

ss -tln | grep -E ':80 |:8080 |:9092 |:9093 |:28081 '

The kafka, akhq and nginx systemd services all active, with nginx listening on port 80 while the AKHQ app on 8080, the management port on 28081 and the Kafka broker on 9092 and 9093 are bound to loopback only, and the AKHQ management health endpoint reporting status UP

Step 3 - Retrieve the per VM administrator password

AKHQ ships with authentication switched on. There is no default or shared password: on the first boot of every VM a one shot service generates a random administrator password and a unique token signing secret for that instance and writes them to a root only file. Read it with sudo:

sudo cat /root/akhq-credentials.txt

The file records the console URL, the administrator username (admin) and the generated password:

# AKHQ for Apache Kafka - Per-VM Credentials
AKHQ_UI_URL=http://YOUR_VM_IP/
AKHQ_ADMIN_USER=admin
AKHQ_ADMIN_PASSWORD=<AKHQ_ADMIN_PASSWORD>

The file is 0600 root:root, so only the root user can read it. Keep this password safe: it is the single administrator credential for the console.

The per VM AKHQ credentials file, owned root only with mode 600, showing the console URL, the admin username and the generated password masked, alongside the login round trip where an unauthenticated request is blocked, a valid admin login is served, and a wrong password is rejected

Step 4 - Sign in to the console

Open http://YOUR_VM_IP/ in your browser. AKHQ redirects to its login page because authentication is enabled. Enter the username admin and the password from /root/akhq-credentials.txt, then click Login. Any attempt to reach the console or its API without signing in is refused, so the console is never served anonymously.

Step 5 - Explore the nodes

After signing in, open Nodes to see the bundled cluster. This is a single node KRaft deployment: one broker that is also the active controller, so there is no separate ZooKeeper to run. The view shows the node id, its host and port, whether it is the controller, and the share of partitions it hosts.

The AKHQ Nodes view for the cloudimg cluster, showing a single KRaft node on 127.0.0.1:9092 that is the active controller and hosts 100 percent of the partitions

Step 6 - Browse topics

Open Topics to list the topics on the broker. The image seeds three demo topics on first boot so the console has real data to explore: demo-orders (3 partitions), demo-payments and demo-users. Each row shows the record count, size, partition count, replication factor and any consumer groups reading the topic. From here you can create, configure, empty or delete topics, and click into any topic for its details.

The AKHQ Topics list for the cloudimg cluster, showing the seeded demo-orders, demo-payments and demo-users topics with their record counts, sizes, partition counts and replication factors, and the demo-consumer group with its lag against demo-orders

Step 7 - Read live messages

Click a topic and open its Data tab to read what is on the topic. Here demo-orders shows its seeded order events: each message has a key (for example order-001), a timestamp, a partition, an offset and a JSON value preview. You can change the sort order, filter by partition, choose a deserializer, and search, which is how you inspect what producers are actually writing.

The AKHQ Data tab for the demo-orders topic, showing the seeded order events with their keys, timestamps, partitions, offsets and JSON value previews, and the sort, partition, search and live tail controls

Step 8 - Monitor consumer groups

Open Consumer Groups to see consumer groups and their lag. The seeded demo-consumer group has read part of demo-orders and committed its offsets, and a few more messages were produced afterwards, so it shows a small non zero lag. Consumer lag, the gap between the latest offset and the last committed offset, is the key signal that a consumer is keeping up with its topics.

The AKHQ Consumer Groups view for the cloudimg cluster, showing the demo-consumer group with its state, coordinator, member count and a small non zero consumer lag against the demo-orders topic

Step 9 - Work with the bundled Kafka broker from the command line

The bundled broker is a full Apache Kafka install under /opt/kafka, so the standard Kafka command line tools are available on the VM. The broker listens on 127.0.0.1:9092. List the topics:

/opt/kafka/bin/kafka-topics.sh --bootstrap-server 127.0.0.1:9092 --list
__consumer_offsets
demo-orders
demo-payments
demo-users

Describe a topic to see its partitions and configuration:

/opt/kafka/bin/kafka-topics.sh --bootstrap-server 127.0.0.1:9092 --describe --topic demo-orders

Inspect the demo consumer group's committed offsets and lag from the CLI, the same data the Consumer Groups view shows:

/opt/kafka/bin/kafka-consumer-groups.sh --bootstrap-server 127.0.0.1:9092 --describe --group demo-consumer

The Kafka command line tools on the VM listing the seeded topics on the loopback broker, describing the demo-orders topic and its three partitions, and showing the demo-consumer group's committed offsets and per partition lag

You can produce and consume your own messages too. Create a topic, produce a couple of records, then read them back:

/opt/kafka/bin/kafka-topics.sh --bootstrap-server 127.0.0.1:9092 --create --if-not-exists --topic my-events --partitions 1 --replication-factor 1
printf 'hello\nworld\n' | /opt/kafka/bin/kafka-console-producer.sh --bootstrap-server 127.0.0.1:9092 --topic my-events
/opt/kafka/bin/kafka-console-consumer.sh --bootstrap-server 127.0.0.1:9092 --topic my-events --from-beginning --max-messages 2 2>/dev/null

Refresh the Topics view in the browser and your new my-events topic appears alongside the demo topics.

Step 10 - Security model

This image is secure by default. AKHQ ships with authentication disabled, so cloudimg switches it on and rotates a per VM administrator password and a per VM token signing secret at first boot; the shipped image carries only placeholders, never a usable credential. You can prove the login wall directly: an unauthenticated API request is refused, a request with the correct password is served, and a request made with the wrong password is not served.

PW=$(sudo grep '^AKHQ_ADMIN_PASSWORD=' /root/akhq-credentials.txt | cut -d= -f2-)
echo "no auth   -> $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1/api/cloudimg/topic)"
echo "admin     -> $(curl -s -o /dev/null -w '%{http_code}' -u "admin:$PW" http://127.0.0.1/api/cloudimg/topic)"
echo "wrong pw  -> $(curl -s -o /dev/null -w '%{http_code}' -u admin:wrong-password http://127.0.0.1/api/cloudimg/topic)"
no auth   -> 401
admin     -> 200
wrong pw  -> 401

The 401 responses are the login wall rejecting requests that do not carry the correct credential; the 200 is the authenticated request being served. The bundled Kafka broker is bound to loopback only, so it is never reachable from the network, and the NSG needs to open only ports 22 and 80.

Step 11 - Base image and versions

The base is a hardened, fully patched Ubuntu 24.04 LTS with unattended security upgrades enabled, so the image keeps receiving security updates on your VMs. You can confirm the bundled software versions:

echo "kernel: $(uname -r)"
echo "kafka:  $(ls -d /opt/kafka_*/ | sed 's#.*/opt/##;s#/##')"
/opt/akhq/jre/bin/java -version 2>&1 | head -1

Apache Kafka runs on the system OpenJDK 17, and AKHQ runs on a bundled Eclipse Temurin 25 JRE (AKHQ 0.27.1 targets Java 25). A first boot service formats the KRaft storage and sets the per VM administrator password and token signing secret before the broker and console start, so ordering is deterministic on every boot.

The VM showing zero held packages and zero pending security upgrades including phased updates on the current kernel, and the bundled Apache Kafka 4.3.1 and AKHQ 0.27.1 with AKHQ on Temurin 25 and Kafka on OpenJDK 17

Managing the services

Restart the console, the broker or the proxy with systemd:

sudo systemctl restart akhq
sudo systemctl restart kafka
sudo systemctl restart nginx

The Kafka broker keeps its log and metadata directories under /var/lib/kafka/data, and AKHQ reads its configuration from /opt/akhq/application.yml. The Kafka broker connection AKHQ uses is 127.0.0.1:9092.

Support

Every cloudimg image is backed by 24/7 support. If you have any questions about this deployment, contact the cloudimg team at support@cloudimg.co.uk.