Networking Azure

Kea DHCP and Stork on Ubuntu 24.04 on Azure User Guide

| Product: Kea DHCP and Stork on Ubuntu 24.04 LTS on Azure

Overview

This image runs ISC Kea 3.0.3 (the current LTS release), the modern, high throughput open source DHCPv4 and DHCPv6 server, together with ISC Stork 2.4.1, its web dashboard and monitoring UI, on Ubuntu 24.04 LTS. Kea serves DHCP with a clean JSON configuration and a full management API; Stork gives operators an at a glance view of Kea's daemons, subnets, address pools, host reservations and lease utilisation from a single screen. Both are maintained by Internet Systems Consortium and are licensed under the Mozilla Public License 2.0.

Everything runs on one VM. nginx on port 80 is the only public service; it reverse proxies to the Stork server on 127.0.0.1:8080. The Stork server stores its data in a local PostgreSQL 16 database on 127.0.0.1:5432. The Stork agent on 127.0.0.1:8081 monitors the local Kea, which exposes its control channel on 127.0.0.1:8000 protected with a per-VM credential. Kea 3.0 talks to Stork through its own HTTP control socket, so the deprecated Kea Control Agent is not used.

What is included:

  • ISC Kea 3.0.3 (kea-dhcp4) with a sample DHCPv4 subnet, run by systemd
  • ISC Stork 2.4.1 server and agent, with the local Kea already registered and authorised
  • The Stork web dashboard on :80 (nginx reverse proxy to 127.0.0.1:8080)
  • A per-VM Stork admin password, generated on first boot and recorded in a root-only file
  • A per-VM PostgreSQL password and a per-VM Kea control API credential, both generated on first boot
  • PostgreSQL 16, bound to loopback, holding the Stork dashboard's data
  • The Kea control channel bound to loopback only, protected with basic authentication
  • An unauthenticated /healthz endpoint for Azure Load Balancer health probes
  • 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; size up for larger deployments. NSG inbound: allow 22/tcp from your management network and 80/tcp for the dashboard. Stork serves plain HTTP on port 80; for production, terminate TLS in front of it with your own domain (see Maintenance).

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Kea DHCP 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 kea-stork \
  --image <marketplace-image-urn> \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_ed25519.pub \
  --vnet-name <your-vnet> --subnet <your-subnet> \
  --public-ip-sku Standard

az vm open-port --resource-group <your-rg> --name kea-stork --port 80 --priority 1010

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the services are running

The dashboard is served by nginx on port 80, which reverse-proxies to the Stork server on 127.0.0.1:8080. The Stork agent, the Kea control channel and PostgreSQL are all bound to loopback - only nginx listens on a public address. Confirm every service is active and check the bindings:

systemctl is-active postgresql isc-kea-dhcp4-server isc-stork-server isc-stork-agent nginx
sudo ss -tlnp | grep -E ':80 |:8080 |:8081 |:8000 |:5432 '

Expected output:

active
active
active
active
active
LISTEN 0      511          0.0.0.0:80        0.0.0.0:*
LISTEN 0      4096       127.0.0.1:8000      0.0.0.0:*
LISTEN 0      4096       127.0.0.1:8081      0.0.0.0:*
LISTEN 0      4096       127.0.0.1:8080      0.0.0.0:*
LISTEN 0      200        127.0.0.1:5432      0.0.0.0:*

postgresql, Kea, the Stork server and agent, and nginx all active, with the Kea control channel, Stork server, Stork agent and PostgreSQL on loopback and only nginx on public port 80

Step 5 - Retrieve your Stork admin password

On the first boot of every VM, kea-dhcp-stork-firstboot.service generates a unique Stork administrator password, a PostgreSQL password and a Kea control API credential, seeds the Stork database, rotates the default admin login to the unique password before the port is ever reachable, and registers the local Kea with Stork. It writes the Stork username, password and dashboard URL, plus the Kea control credential, into a root-only file. Read it with:

sudo cat /root/kea-dhcp-stork-credentials.txt

There is no default or shared credential in the image. Stork's built-in admin/admin login is rotated to a password unique to this VM on first boot, so the well-known default never works. Store the password somewhere safe.

The per-VM Kea and Stork credentials file, with the Stork admin password and the Kea control API credential masked

Step 6 - Confirm the versions and health endpoint

nginx serves an unauthenticated /healthz endpoint for load balancer probes. Confirm the Kea and Stork versions and that the dashboard responds:

kea-dhcp4 -V | head -1
stork-tool --version
curl -s http://127.0.0.1/api/version
curl -sI http://127.0.0.1/healthz | head -1

Expected output:

3.0.3 (3.0.3 (isc20260313155935 deb))
2.4.1
{"date":"2026-05-08 13:24","version":"2.4.1"}
HTTP/1.1 200 OK

Kea 3.0.3 and Stork 2.4.1 versions, the Stork API version endpoint, and the healthz endpoint returning 200

Step 7 - Query the Kea control API

Kea 3.0 exposes an HTTP control channel directly on kea-dhcp4. On this image it is bound to 127.0.0.1:8000, is never public, and is protected with a per-VM basic-authentication credential (the Stork agent uses the same credential to monitor Kea). Send it the core config-get command with the credential from Step 5 to see the sample DHCPv4 subnet the image ships, and confirm that an unauthenticated request is rejected:

KU=$(sudo grep '^KEA_CTRL_USER=' /root/kea-dhcp-stork-credentials.txt | cut -d= -f2-)
KP=$(sudo grep '^KEA_CTRL_PASSWORD=' /root/kea-dhcp-stork-credentials.txt | cut -d= -f2-)
curl -s -u "$KU:$KP" -H 'Content-Type: application/json' -X POST \
  -d '{"command":"config-get"}' http://127.0.0.1:8000/ \
  | python3 -c 'import sys,json; print("demo subnet:", json.load(sys.stdin)[0]["arguments"]["Dhcp4"]["subnet4"][0]["subnet"])'
curl -s -o /dev/null -w 'unauthenticated request: HTTP %{http_code}\n' -H 'Content-Type: application/json' \
  -X POST -d '{"command":"list-commands"}' http://127.0.0.1:8000/

Expected output:

demo subnet: 192.0.2.0/24
unauthenticated request: HTTP 401

The authenticated Kea control API returning the demo DHCPv4 subnet configuration, and an unauthenticated request being rejected with 401

Step 8 - Sign in to the Stork dashboard

Browse to http://<vm-public-ip>/. Enter admin and the password from Step 5.

The Stork sign-in page for the Kea DHCP and BIND 9 dashboard

You are signed in as the per-VM administrator. Because the first-boot rotation replaces the default password before the dashboard is reachable, the well-known admin/admin login is already rejected.

Step 9 - Tour the DHCP dashboard

After signing in you land on the DHCP Dashboard, which summarises every Kea server Stork monitors: DHCPv4 and DHCPv6 subnets, shared networks, address pool utilisation and per-daemon service status. On this image the local Kea appears immediately with its DHCPv4 daemon healthy and the sample subnet loaded.

The Stork DHCP dashboard showing the monitored Kea server, its DHCPv4 daemon and the sample subnet

Step 10 - Inspect the registered Kea server

Open Services -> Machines and select the local machine to see its system information and monitored daemons. The local Kea was registered and authorised automatically on first boot, so its DHCPv4 daemon shows here with its version and health, ready to inspect - no manual agent approval required.

The Stork machine detail page showing system information and the monitored Kea DHCPv4 3.0.3 daemon

Step 11 - Review subnets, pools and reservations

Open DHCP -> Subnets to see every subnet Kea serves, with total and assigned address counts, pool utilisation and the owning daemon. The sample subnet 192.0.2.0/24 ships with an address pool (192.0.2.100 - 192.0.2.200) and a host reservation so the dashboard has real content to explore. The DHCP -> Host Reservations and DHCP -> Leases pages show reservations and live leases the same way.

The Stork subnets page showing the 192.0.2.0/24 sample subnet with its address pool and owning DHCPv4 daemon

Step 12 - Configure Kea to serve your own network

The image ships a sample subnet purely so the dashboard has content; interfaces-config lists no interface, so the image never hands out addresses on your network until you configure it. Edit the Kea DHCPv4 configuration to serve your own subnets:

sudo nano /etc/kea/kea-dhcp4.conf

Set "interfaces-config": { "interfaces": [ "eth0" ] } to the interface Kea should serve, replace the sample subnet4 entry with your own subnets, pools and options, then validate and apply:

sudo kea-dhcp4 -t /etc/kea/kea-dhcp4.conf
sudo systemctl restart isc-kea-dhcp4-server

Stork picks up the new configuration automatically on its next poll and shows your subnets on the dashboard. See the Kea Administrator Reference Manual for the full configuration syntax.

Maintenance

  • Back up your data: the Stork dashboard's data lives in the local stork PostgreSQL database; snapshot the OS disk or use pg_dump stork. Kea's own configuration is the file /etc/kea/kea-dhcp4.conf - keep it in version control.
  • Kea control credential: the Stork agent reads the per-VM Kea control credential from /etc/kea/kea-dhcp4.conf; if you rotate it, restart both isc-kea-dhcp4-server and isc-stork-agent.
  • Security updates: unattended security upgrades are enabled, so the OS keeps itself patched. Reboot when a new kernel is installed. Update Kea and Stork with sudo apt update && sudo apt upgrade.
  • TLS: for production, front the dashboard with your own domain and a TLS-terminating reverse proxy or Azure Application Gateway.
  • Add operators: manage additional Stork users and groups from Configuration -> Users after signing in.

Support

cloudimg provides 24/7/365 expert technical support for this image. Contact support@cloudimg.co.uk. ISC Kea and Stork are licensed under the Mozilla Public License 2.0. This image is provided by cloudimg; additional charges apply for build, maintenance and 24/7 support.