Kea DHCP and Stork on Ubuntu 24.04 on Azure User Guide
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 to127.0.0.1:8080) - A per-VM Stork
adminpassword, 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
/healthzendpoint 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:*

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.

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

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

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

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.

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.

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.

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
storkPostgreSQL database; snapshot the OS disk or usepg_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 bothisc-kea-dhcp4-serverandisc-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.