Deployment guide

Dragonfly

Overview

This guide covers the deployment and use of Dragonfly on Ubuntu 24.04 on Azure using SecureAnyCloud Azure Marketplace images.

Dragonfly is an open source, cloud-native peer-to-peer (P2P) file and container image distribution system, and a graduated project of the Cloud Native Computing Foundation. It turns the machines that pull artifacts into a swarm that shares pieces with each other. A large image, model file or dataset is fetched from the origin once and then spread between peers.

This cuts origin bandwidth, speeds up mass rollouts, and stops registries and object stores from being overwhelmed when thousands of hosts pull the same content at once.

This image is a complete single-node cluster. Dragonfly normally scales out across many hosts. This appliance runs the smallest useful shape of the same software on one VM, managed by systemd:

  • manager: the control plane and web console. It holds cluster configuration and users, and serves the REST and gRPC APIs. A bundled MariaDB database and a Redis cache back it.
  • scheduler: builds the P2P scheduling graph and decides which peer fetches which piece from whom.
  • dfdaemon (seed peer): the peer agent, running in seed peer mode. It fetches from the origin, seeds the swarm, and exposes an HTTP proxy and a dfget command line for pulling content through the P2P network.

Security by design. Dragonfly's manager ships a default console login of root / dragonfly. An appliance that shipped that login unchanged would be wide open, so this image does the opposite:

  • The published default login is never present on your VM. At first boot, the manager console comes up on the loopback interface only. Its root password is rotated to a value unique to your VM, and only then is the console rebound to the network. There is no window in which the published default is reachable from off the box, and the image itself contains no console password.
  • Nothing is baked into the image. The image contains no console password, no database password, no Redis password and no API signing key. First boot generates all of them uniquely on your VM and writes them to a root-only file.
  • The database and cache are private. MariaDB and Redis listen on the loopback interface only and are never exposed to the network.
  • Proven before it ships. Every image is verified before it is published. The check pulls a real file end to end through the seed peer and scheduler, then confirms that the checksum of the delivered bytes matches the source.

What you get:

  • Dragonfly server 2.5.1 (the manager and scheduler Go binaries) from the pinned upstream release, under systemd as dragonfly-manager.service and dragonfly-scheduler.service
  • Dragonfly client 1.4.9 (the Rust dfdaemon and dfget binaries) from the pinned upstream release, with dfdaemon running in seed peer mode as dragonfly-dfdaemon.service
  • MariaDB and Redis from the Ubuntu archive, preconfigured as the manager's backing store and tuned to run comfortably on a small VM
  • A first-boot service that rotates every secret and registers the cluster before anything accepts connections

Prerequisites

  • An Azure subscription and the Azure CLI (az) installed and logged in (az login), or access to the Azure Portal.
  • An SSH key pair for Linux VM access.
  • A network security group that allows inbound TCP 22 (SSH) and 8080 (the manager web console) from your address, and, if you want other machines to pull through this node's proxy, 4001. Restrict the manager console to trusted addresses (see Security recommendations).

Deploy the virtual machine

Create a resource group and launch the image. Replace the image reference with the SecureAnyCloud Dragonfly offer from the Azure Marketplace.

az group create --name my-resource-group --location eastus
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:dragonfly-oss:default:latest
az vm create \
  --resource-group my-resource-group \
  --name dragonfly \
  --image sac1647283583153:dragonfly-oss:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard
# Open the console port to your address (and, optionally, the proxy port 4001):
az vm open-port --resource-group my-resource-group --name dragonfly --port 8080 --priority 1001

Note the public IP address that az vm create prints. This guide refers to it as <vm-ip>.

Confirm the services are healthy

SSH in:

ssh azureuser@<vm-ip>

Then check that all five services are active. The manager, scheduler and dfdaemon are exposed on the network. MariaDB and Redis are bound to the loopback interface only.

sudo systemctl is-active dragonfly-manager dragonfly-scheduler dragonfly-dfdaemon mariadb redis-server

All five report active, and the listening sockets show the manager on 8080 and 65003, the scheduler on 8002, the dfdaemon proxy and health ports on 4001 and 4003, and MariaDB and Redis on loopback only.

The manager exposes an unauthenticated liveness probe. The probe returns HTTP 200 and nothing sensitive, so an Azure Load Balancer or Application Gateway health probe can use it directly.

curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8080/healthy

Retrieve your per-VM credentials

First boot writes the unique administrator password and every backing secret to a root-only file. Read the file over your SSH session:

sudo cat /root/dragonfly-oss-credentials.txt

The file lists the manager console URL, the root administrator password unique to this VM, the proxy URL, and the database and Redis passwords. The values in the example output are masked. Yours are real and unique to your VM.

The health check answers 200, the per-VM root password authenticates against the console API, and the published default root / dragonfly is rejected with HTTP 401:

Sign in to the Manager console

Open the manager web console in your browser at http://<vm-ip>:8080/. Sign in with the account root and the MANAGER_ADMIN_PASSWORD from your credentials file.

After you sign in, the Cluster overview shows your live control plane: one cluster (the default), one active scheduler, and the cluster-1 default cluster card. This is the managed P2P fabric that the appliance registered at first boot.

Open cluster-1 to see its detail. It is the default cluster, scheduler cluster ID 1, with its scopes and load limits. The Schedulers and Peers tabs list the fabric members.

Distribute a file through the P2P swarm

The point of Dragonfly is to move bytes peer to peer. dfget hands a download to the local dfdaemon. The dfdaemon asks the scheduler and pulls the content through the seed peer, fetching from the origin in pieces and caching them in the swarm.

The self-test below serves a 6 MiB file from a local origin that speaks HTTP range requests, pulls it with dfget, and confirms that the delivered bytes match the source checksum. It runs entirely on the VM and needs no internet access:

OD=$(mktemp -d); head -c 6291456 /dev/urandom > "$OD/model.bin"
SRC=$(sha256sum "$OD/model.bin" | awk '{print $1}')
cat > "$OD/range.py" <<'PY' import http.server,os,sys,re F=sys.argv[2]; SZ=os.path.getsize(F) class H(http.server.BaseHTTPRequestHandler): def log_message(self,*a): pass def do_GET(self): d=open(F,'rb').read(); r=self.headers.get('Range') if r: m=re.match(r'bytes=(\d+)-(\d*)',r); s=int(m.group(1)); e=int(m.group(2)) if m.group(2) else SZ-1 self.send_response(206); self.send_header('Content-Range',f'bytes {s}-{e}/{SZ}') self.send_header('Content-Length',str(e-s+1)); self.end_headers(); self.wfile.write(d[s:e+1]) else: self.send_response(200); self.send_header('Content-Length',str(SZ)); self.send_header('Accept-Ranges','bytes'); self.end_headers(); self.wfile.write(d) http.server.ThreadingHTTPServer(('127.0.0.1',18085),H).serve_forever() PY python3 "$OD/range.py" 18085 "$OD/model.bin" >/dev/null 2>&1 & SRV=$! sleep 2 dfget http://127.0.0.1:18085/model.bin -O "$OD/pulled.bin" kill "$SRV" 2>/dev/null echo "source sha256: $SRC" echo "dfget sha256: $(sha256sum "$OD/pulled.bin" | awk '{print $1}')" rm -rf "$OD"

The two checksums match, which shows the file was pulled through the Dragonfly seed peer and scheduler, not fetched directly.

In production, point Dragonfly at your real origins. Route HTTP downloads through the dfdaemon proxy on port 4001 (curl -x http://<vm-ip>:4001 <url>). For container images, configure your registry mirror or containerd to use the proxy so that image layers are distributed P2P.

Preheat content across the swarm

Under Job, then Preheat, the console can preheat content. Preheating pre-distributes an image or file across the swarm before your hosts need it, so a mass rollout is served from peers instead of hammering the origin.

On a fresh appliance the list is empty until you create your first preheat job.

Network ports

The appliance listens on these ports:

  • 22: SSH, exposed to the network
  • 8080: manager REST API and web console, exposed to the network (restrict to trusted addresses)
  • 65003: manager gRPC, exposed to the network
  • 8002: scheduler gRPC, exposed to the network
  • 4001: dfdaemon HTTP/HTTPS proxy, exposed to the network
  • 4003: dfdaemon health, exposed to the network
  • 3306: MariaDB, loopback only
  • 6379: Redis, loopback only

Managing the services

sudo systemctl status dragonfly-manager
sudo systemctl restart dragonfly-scheduler
sudo journalctl -u dragonfly-dfdaemon -f

The manager, scheduler and dfdaemon are enabled and restart on failure, and the whole stack survives a reboot. Configuration files live under /etc/dragonfly/ (manager.yaml, scheduler.yaml, dfdaemon.yaml).

Security recommendations

  • Restrict the manager console (port 8080). Limit it to trusted addresses with your network security group. Dragonfly's manager job API has a known advisory (CVE-2026-24124) in which preheat job endpoints are callable without authentication. Never open the console port to the whole internet.
  • Keep the per-VM administrator password safe. It is unique to your VM and lives in /root/dragonfly-oss-credentials.txt (mode 0600). If needed, rotate it in the console under your profile.
  • The database and cache stay private. MariaDB and Redis are bound to loopback. Do not expose them.
  • Keep the OS patched. Unattended security updates are enabled by default.

Support

SecureAnyCloud maintains these images with security updates and documentation. For deployment help or questions, contact support through the SecureAnyCloud listing.

Dragonfly itself is an open source CNCF project. Upstream documentation is at https://d7y.io and https://github.com/dragonflyoss.

Deploy on Azure

Launch Dragonfly Peer to Peer File and Image Distribution on Ubuntu 24.04 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