Deployment guide

Kea DHCP Stork

Overview

ISC Kea is a modern, high-throughput open source DHCPv4 and DHCPv6 server with a clean JSON configuration and a full management API. ISC Stork is its web dashboard and monitoring UI. It gives operators an at-a-glance view of the daemons, subnets, address pools, host reservations and lease utilization of Kea from a single screen. Both are maintained by Internet Systems Consortium and licensed under the Mozilla Public License 2.0.

This SecureAnyCloud image runs ISC Kea 3.0.3 (the current LTS release) together with ISC Stork 2.4.1 on Ubuntu 24.04 LTS.

Everything runs on one VM. nginx on port 80 is the only public service, and 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 you get:

  • 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 authorized
  • 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 data of the Stork dashboard
  • The Kea control channel bound to loopback only and protected with basic authentication
  • An unauthenticated /healthz endpoint for Azure Load Balancer health probes
  • 24/7 SecureAnyCloud support

Prerequisites

You need an active Azure subscription, an SSH key pair, and a VNet with a subnet in the target region.

Standard_B2s (2 vCPU / 4 GiB RAM) is a sensible starting size. Choose a larger size for bigger deployments.

Configure the network security group (NSG) to allow inbound 22/tcp from your management network and 80/tcp for the dashboard. Stork serves plain HTTP on port 80, so 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 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).

Select Review + create, then Create.

Step 2 - Deploy from the Azure CLI

# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:kea-dhcp-stork:default:latest
az vm create \
  --resource-group <your-rg> \
  --name kea-stork \
  --image sac1647283583153:kea-dhcp-stork:default:latest \
  --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

Connect to the VM over SSH as azureuser:

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the services are running

nginx serves the dashboard on port 80 and 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, so only nginx listens on a public address. Confirm that 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 admin password, a PostgreSQL password and a Kea control API credential. It seeds the Stork database, rotates the default admin login to the unique password before the port is reachable, and registers the local Kea with Stork. It writes the Stork username, password and dashboard URL, plus the Kea control credential, to a root-only file. Read the file with:

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

The image contains no default or shared credential. First boot rotates the built-in Stork admin/admin login to a password unique to this VM, 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 check 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, the channel 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 the core config-get command with the credential from Step 5 to see the sample DHCPv4 subnet that ships with the image. Then 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 now signed in as the per-VM admin user. The first-boot rotation replaces the default password before the dashboard is reachable, so the well-known admin/admin login is already rejected.

Step 9 - Tour the DHCP dashboard

After you sign in, you land on the DHCP Dashboard. It summarizes every Kea server that Stork monitors, including DHCPv4 and DHCPv6 subnets, shared networks, address pool utilization 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. First boot registers and authorizes the local Kea automatically, so its DHCPv4 daemon appears here with its version and health. No manual agent approval is required.

Step 11 - Review subnets, pools and reservations

Open DHCP -> Subnets to see every subnet that Kea serves, with total and assigned address counts, pool utilization 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 content to explore. The DHCP -> Host Reservations and DHCP -> Leases pages show reservations and live leases in the same way.

Step 12 - Configure Kea to serve your own network

The sample subnet exists only so that the dashboard has content. interfaces-config lists no interface, so the image does not hand 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 that Kea should serve. Replace the sample subnet4 entry with your own subnets, pools and options. Then validate and apply the configuration:

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

Stork picks up the new configuration on its next poll and shows your subnets on the dashboard. For the full configuration syntax, see the Kea Administrator Reference Manual.

Maintenance

  • Back up your data. The data of the Stork dashboard lives in the local stork PostgreSQL database. Snapshot the OS disk or use pg_dump stork. The Kea configuration is the file /etc/kea/kea-dhcp4.conf, so keep it in version control.
  • Rotate the Kea control credential with care. 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.
  • Apply 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.
  • Add TLS. For production, front the dashboard with your own domain and a TLS-terminating reverse proxy or Azure Application Gateway.
  • Add operators. After you sign in, manage additional Stork users and groups from Configuration -> Users.

Support

SecureAnyCloud provides 24/7/365 expert technical support for this image. Contact sales@secureanycloud.com.

ISC Kea and Stork are licensed under the Mozilla Public License 2.0. SecureAnyCloud provides this image, and additional charges apply for build, maintenance and 24/7 support.

Deploy on Azure

Launch Kea DHCP and Stork 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

Deploy on Azure