Developer Tools Azure

Hoverfly on Ubuntu 24.04 on Azure User Guide

| Product: Hoverfly API Simulation Proxy on Ubuntu 24.04 LTS on Azure

Overview

This guide covers the deployment and configuration of Hoverfly on Ubuntu 24.04 on Azure using cloudimg Azure Marketplace images. Hoverfly is a lightweight, open source API simulation and service virtualization tool developed by SpectoLabs. It sits as a proxy in front of the HTTP and HTTPS services your application depends on, and can capture real traffic, replay it as fast deterministic virtual services, spy on requests, or modify responses on the fly. This lets teams develop and test against realistic simulations of third party or internal APIs that are slow, rate limited, costly or not yet built, and reproduce specific responses, latencies and failure modes on demand.

The image installs the pinned official Hoverfly 1.12.10 release, verified by checksum, and runs it under systemd as the unprivileged hoverfly user. Both the hoverfly server and the hoverctl command line tool are installed to /usr/local/bin.

Ready on first boot. The image ships a working demo simulation so Hoverfly is virtualising traffic the moment the VM boots. A single request/response pair virtualises GET http://demo.cloudimg.local/api/health, so sending that request through the proxy returns a canned JSON response, a real service virtualization round trip you can see immediately. You replace the demo with your own captured or authored simulations when you are ready (see Step 7).

Security by design — authentication enabled. Hoverfly's admin API is unauthenticated out of the box. This image enables authentication and generates a unique admin password and a JWT signing secret on each VM's first boot, written to a root only file. Nothing is baked into the image. The admin API requires a JWT (obtained from your admin credentials), and because authentication is enabled the proxy also requires credentials, so it is never an open relay.

Security by design — bound to loopback. Both the admin API (127.0.0.1:8888) and the proxy (127.0.0.1:8500) are bound to loopback only. The admin API is fronted by an nginx reverse proxy on port 80 so it is reachable off the box only through Hoverfly's own token authentication. The proxy is kept private by default; you expose it deliberately to trusted clients when you need to (see Step 8). The only inbound ports on the image are SSH 22 and the nginx admin port 80.

What is included:

  • Hoverfly 1.12.10 (pinned, checksum verified), plus hoverctl, run under systemd as the unprivileged hoverfly user (hoverfly.service)

  • A working demo simulation so the proxy virtualises traffic on first boot

  • Authentication enabled with a unique admin password and JWT secret generated per VM, nothing baked into the image

  • The admin API and proxy bound to loopback, with nginx fronting the admin API on port 80 behind Hoverfly's own token authentication

  • The proxy is never an open relay — it requires credentials and is not exposed by default

  • Unattended security upgrades left enabled so the OS keeps receiving patches

Prerequisites

  • Active Azure subscription, SSH public key, VNet and subnet in the target region

  • Subscription to the Hoverfly listing on Azure Marketplace

  • Network Security Group rules allowing TCP 22 for administration and TCP 80 for the admin API

Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM) for development and test use. Simulations serving heavy traffic should use Standard_D2s_v5 or larger.

Step 1: Deploy from the Azure Portal

Search Hoverfly in Marketplace, select the cloudimg publisher, and click Create. Configure the Network Security Group to allow TCP 22 for administration and TCP 80 for the admin API. The Hoverfly proxy is not exposed by default; if you later choose to expose it to trusted clients, open only that port and only from the networks that should reach it (see Step 8).

Step 2: Deploy from the Azure CLI

RG="devtools-prod"; LOCATION="eastus"; VM_NAME="hoverfly1"
GALLERY_IMAGE_ID="/subscriptions/<sub-id>/resourceGroups/azure-cloudimg/providers/Microsoft.Compute/galleries/cloudimgGallery/images/hoverfly-ubuntu-24-04/versions/<version>"
SSH_KEY="$(cat ~/.ssh/id_rsa.pub)"
az group create --name "$RG" --location "$LOCATION"
az vm create \
  --resource-group "$RG" --name "$VM_NAME" \
  --image "$GALLERY_IMAGE_ID" \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values "$SSH_KEY" \
  --public-ip-sku Standard
# Open SSH and the admin API port on the VM's NSG:
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 22 --priority 1001
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 80 --priority 1002

Step 3: First boot

On first boot the image generates a unique admin username and password and a JWT signing secret, enables authentication, starts Hoverfly, proves the authentication round trip and the demo simulation, starts nginx, and writes /root/hoverfly-credentials.txt. This completes within a minute. SSH in as azureuser and read your credentials:

sudo cat /root/hoverfly-credentials.txt

The file records the admin username, the per VM admin password, and the off box admin URL. Store the password somewhere safe; it is unique to this VM and is the only credential that can obtain an admin token or use the proxy.

Step 4: Confirm the service is running

hoverfly.service and nginx.service are active, hoverfly -version reports the pinned release, and the admin API answers /api/health on loopback.

systemctl is-active hoverfly.service nginx.service
hoverfly -version
curl -s http://127.0.0.1:8888/api/health

Expected output:

active
active
v1.12.10
{"message":"Hoverfly is healthy"}

hoverfly.service and nginx.service both report active, hoverfly -version shows the pinned v1.12.10 release, and a curl to the loopback admin API health endpoint returns the message Hoverfly is healthy

Step 5: Authenticate to the admin API

Authentication is enabled, so the admin API rejects unauthenticated requests with 401. To use it, obtain a JSON Web Token from your per VM admin credentials by posting to /api/token-auth, then send that token as a Bearer header. The block below reads the credentials from the first boot file and performs the full round trip against the loopback admin API:

sudo bash -c '
U=$(grep "^HOVERFLY_ADMIN_USERNAME=" /root/hoverfly-credentials.txt | cut -d= -f2-)
PW=$(grep "^HOVERFLY_ADMIN_PASSWORD=" /root/hoverfly-credentials.txt | cut -d= -f2-)
echo -n "unauthenticated GET /api/v2/hoverfly -> HTTP "
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8888/api/v2/hoverfly
TOKEN=$(curl -s -H "Content-Type: application/json" -X POST \
  -d "{\"Username\":\"$U\",\"Password\":\"$PW\"}" \
  http://127.0.0.1:8888/api/token-auth | jq -r .token)
echo "obtained a JWT (first 40 chars): ${TOKEN:0:40}..."
echo "authenticated GET /api/v2/hoverfly/mode:"
curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1:8888/api/v2/hoverfly/mode
echo
'

Expected output (the mode is simulate, the default for serving virtual services):

unauthenticated GET /api/v2/hoverfly -> HTTP 401
obtained a JWT (first 40 chars): eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJ...
authenticated GET /api/v2/hoverfly/mode:
{"mode":"simulate","arguments":{"matchingStrategy":"strongest"}}

The admin API is also reachable off the box at http://<public-ip>/ (nginx forwards port 80 to the loopback admin API), protected by the same token authentication. Replace http://127.0.0.1:8888 with http://<public-ip> in the commands above to manage Hoverfly remotely.

the admin API rejects an unauthenticated call with HTTP 401, then a POST to slash api slash token-auth with the per VM admin credentials returns a JSON Web Token, and an authenticated GET of the hoverfly mode endpoint using the Bearer token returns mode simulate with the strongest matching strategy

Step 6: Send a request through the proxy

The shipped demo simulation virtualises GET http://demo.cloudimg.local/api/health. Because authentication is enabled, the proxy also requires credentials, so an unauthenticated request is rejected with 407. Supply your admin credentials as HTTP Basic proxy credentials and the proxy returns the simulated response:

sudo bash -c '
U=$(grep "^HOVERFLY_ADMIN_USERNAME=" /root/hoverfly-credentials.txt | cut -d= -f2-)
PW=$(grep "^HOVERFLY_ADMIN_PASSWORD=" /root/hoverfly-credentials.txt | cut -d= -f2-)
echo -n "unauthenticated proxy request -> HTTP "
curl -s -o /dev/null -w "%{http_code}\n" -x http://127.0.0.1:8500 http://demo.cloudimg.local/api/health
echo "authenticated proxy request (the demo simulation):"
curl -s --proxy-user "$U:$PW" -x http://127.0.0.1:8500 http://demo.cloudimg.local/api/health
echo
'

Expected output:

unauthenticated proxy request -> HTTP 407
authenticated proxy request (the demo simulation):
{"status":"ok","service":"cloudimg-hoverfly-demo","virtualized":true}

This is a complete service virtualization round trip: the request never reaches a real demo.cloudimg.local server, Hoverfly answers it from the shipped simulation. Point any HTTP client's proxy at Hoverfly and requests it has a simulation for are answered instantly and deterministically.

an unauthenticated request through the Hoverfly proxy on port 8500 is rejected with HTTP 407 proxy authentication required, then the same request with the per VM admin credentials as basic proxy authentication returns the demo simulation JSON body showing status ok, service cloudimg-hoverfly-demo and virtualized true

Step 7: Capture and author your own simulations

You replace the demo with your own simulations using hoverctl, the Hoverfly command line tool. The typical workflow is to run Hoverfly in capture mode, send your application's real traffic through it to record the responses, then switch back to simulate mode to replay them. Simulations are portable JSON files you can capture once and commit to source control.

The shipped simulation lives at /etc/hoverfly/demo-simulation.json. You can inspect the current simulation through the admin API:

sudo bash -c '
U=$(grep "^HOVERFLY_ADMIN_USERNAME=" /root/hoverfly-credentials.txt | cut -d= -f2-)
PW=$(grep "^HOVERFLY_ADMIN_PASSWORD=" /root/hoverfly-credentials.txt | cut -d= -f2-)
TOKEN=$(curl -s -H "Content-Type: application/json" -X POST \
  -d "{\"Username\":\"$U\",\"Password\":\"$PW\"}" \
  http://127.0.0.1:8888/api/token-auth | jq -r .token)
curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1:8888/api/v2/simulation | jq ".data.pairs[0].request.path"
'

Expected output:

[
  {
    "matcher": "exact",
    "value": "/api/health"
  }
]

To capture new simulations with hoverctl, point it at a target and switch modes. For example, to record traffic to a real API and export it to a file:

hoverctl mode capture
# ... send your application's traffic through the proxy on port 8500 ...
hoverctl mode simulate
hoverctl export my-service.json

You can then load a saved simulation on any Hoverfly instance:

hoverctl import my-service.json

See the Hoverfly documentation for the full capture, matching and templating reference.

Step 8: Expose the proxy to trusted clients

The proxy is bound to loopback and is not exposed by the Network Security Group. For an application on another host to use Hoverfly for service virtualization, expose the proxy deliberately. The safest option is an SSH tunnel from the client, which needs no open port:

ssh -L 8500:127.0.0.1:8500 azureuser@<public-ip>
# then on the client, use the proxy at 127.0.0.1:8500 with your admin credentials

If you need the proxy reachable directly, rebind Hoverfly to a routable interface by adding -listen-on-host 0.0.0.0 to the service command in /etc/systemd/system/hoverfly.service, then add a Network Security Group rule for TCP 8500 scoped to the specific client CIDR, never to the whole internet. Authentication remains enforced, so clients still need the admin credentials, but scoping the rule is essential defence in depth.

Step 9: Manage the service

Hoverfly is managed with systemd. Common operations:

systemctl status hoverfly.service --no-pager

To restart the service (for example after editing the simulation or the service command):

sudo systemctl restart hoverfly.service

The runtime environment, including the per VM admin credentials and JWT secret, lives in /etc/default/hoverfly (root only). The BoltDB store that holds users and tokens lives at /var/lib/hoverfly/hoverfly.db.

Step 10: Security recommendations

Both the admin API and the proxy are bound to loopback, and only SSH 22 and the nginx admin port 80 are exposed. You can confirm the listening sockets at any time:

ss -tln | grep -E ':(22|80|8888|8500)\b'

the ss listening socket table shows the Hoverfly admin API on 127.0.0.1 port 8888 and the proxy on 127.0.0.1 port 8500 both bound to loopback only, while only nginx on port 80 and SSH on port 22 are bound to all interfaces, confirming the admin API and proxy are not directly reachable off the box

  • Keep the admin API and proxy on loopback. Both are bound to 127.0.0.1 and reached off the box only through nginx (admin) or an SSH tunnel (proxy). Do not rebind to 0.0.0.0 without scoping a Network Security Group rule to specific client networks.

  • Terminate TLS in front of nginx. Port 80 is plain HTTP. For production, add a TLS certificate to the nginx server block so admin credentials and tokens are encrypted in transit.

  • Rotate the admin password if it is ever exposed. The password is generated per VM and stored in /root/hoverfly-credentials.txt and /etc/default/hoverfly. To rotate it, update HoverflyAdminPass in /etc/default/hoverfly, remove /var/lib/hoverfly/hoverfly.db, and restart the service.

  • Scope any proxy exposure tightly. If you expose the proxy on port 8500, restrict the Network Security Group rule to the exact client CIDR. An open forward proxy is an abuse relay.

  • Keep the OS and Hoverfly patched. Unattended security upgrades remain enabled for the OS. Track new Hoverfly releases and update the binaries when you upgrade.

Step 11: Support and Licensing

Hoverfly is developed by SpectoLabs and distributed under the Apache License 2.0, free and open source with no per CPU or per deployment fee. This cloudimg image bundles the unmodified official Hoverfly release. cloudimg provides the packaging, the working demo simulation, the enabled authentication with per VM credentials, the loopback only bindings, the nginx fronted admin API, the no open relay proxy posture, and 24/7 support with a guaranteed 24 hour response SLA.

cloudimg is not affiliated with or endorsed by SpectoLabs. Hoverfly is a mark of its respective owner and is used here only to identify the software.

Deploy on Azure

Find Hoverfly on Ubuntu 24.04 LTS on the Azure Marketplace, published by cloudimg. Deploy from the Portal or the Azure CLI as shown above.

Need Help?

Email support@cloudimg.co.uk for deployment help, configuration questions, or licensing enquiries.