Dragonfly 2.5.3 on AWS User Guide
Overview
This guide covers launching and using the Dragonfly 2.5.3 on Ubuntu 24.04 AMI from cloudimg on Amazon EC2. It is one version of the cloudimg file sharing and sync listing on AWS Marketplace; you pick it as the software version when you subscribe and launch.
Dragonfly is an open source peer to peer (P2P) distribution system for files, container images, OCI artifacts and AI models, a graduated project of the Cloud Native Computing Foundation. Instead of every machine downloading the same large file from its origin, Dragonfly splits it into pieces and lets machines fetch the pieces from each other, coordinated by a scheduler. This image runs a complete single node Dragonfly:
- the manager (version 2.5.3) with its web console and REST API, which holds the clusters, the schedulers, the jobs and the users;
- the scheduler, which plans which peer fetches which piece from where;
- a dfdaemon seed peer (client 1.5.10), which downloads from origins ("back to source"), keeps the pieces in its cache and serves them; and the dfget command line tool that pulls a file through it;
- MariaDB and Redis, the manager's database and cache.
You can pull files through the P2P cache with dfget, use the local dfdaemon proxy as a registry mirror for a container runtime on the instance, and run preheat jobs from the console to load files or images into the cache before they are needed.
The cloudimg image locks Dragonfly down:
- Closed by default. Every Dragonfly listener (the manager's REST API, console and gRPC port, the scheduler and every dfdaemon port), MariaDB and Redis listen on 127.0.0.1 only. The only network ports are SSH (22) and nginx (80 and 443). This is a single node appliance: no peer on another host can talk to it until you open it on purpose (see "Join peers on other hosts").
- HTTPS from the first boot. nginx serves the console on port 443 with a certificate generated on your instance's first boot. Port 80 redirects to HTTPS, and requests for a host name the instance does not serve are dropped.
- Two sign ins, both unique to your instance. nginx asks for a per instance Basic authentication credential before anything of the console or its API is shown, then the console asks for its own
rootaccount. Dragonfly normally createsrootwith the published passworddragonfly; on this image first boot createsrootdirectly with a random password, so the published default never exists. Self registration (which would give anyone a read only account) is refused. - Secrets unique to your instance. The image ships with no database, no configuration, no signing key and no certificate. First boot creates the MariaDB database and its account, the Redis password, the key that signs console sessions and the TLS key, all on your instance.
- Hardened web front. nginx removes the manager's permissive cross origin (CORS) headers, marks its session cookie
SecureandSameSite=Strict, refuses cross origin requests that change something, refuses cross site requests to the OAuth sign in pages, sets the client address itself (a forgedX-Forwarded-Forheader is ignored), keeps query strings out of its access log and rate limits the sign in. - Unprivileged and fenced in. The manager, scheduler and dfdaemon run as an unprivileged
dragonflyaccount with no Linux capabilities. Every service, including MariaDB, Redis and nginx, is blocked at the kernel level from reaching the EC2 instance metadata service, so a URL given to Dragonfly (adfgetdownload, a proxy request or a preheat job) can never fetch the instance's role credentials. - Built from source with current security fixes. cloudimg compiles the Dragonfly 2.5.3 manager and scheduler from the project's own release tag with the current Go toolchain and patched Go libraries (the upstream release binaries are built with an older Go release that has since received many security fixes). The web console is the project's own build, unchanged. The build is reproducible and its record is on the image.
- Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.
What is on the image: Dragonfly manager and scheduler 2.5.3 and dfdaemon and dfget 1.5.10 (/opt/dragonfly/bin, Apache-2.0), MariaDB 10.11 and Redis 7.0 from the Ubuntu archive, nginx, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent. The licences, the source locations, the exact Go module list and the build record are in /usr/share/doc/cloudimg/dragonfly/.
Default user: ubuntu · Architecture: x86_64 · Recommended instance type: m5.large
Prerequisites
- An AWS account subscribed to the listing, an EC2 key pair and a VPC subnet with a route to the internet.
- A security group that allows TCP 22 (SSH), TCP 443 (the console) and TCP 80 (redirects to HTTPS) from your own networks only.
Step 1: Launch the instance
In the AWS Marketplace listing choose Continue to Subscribe, then Continue to Configuration, pick Dragonfly 2.5.3 on Ubuntu 24.04 as the software version and your Region, then Launch through EC2. Choose m5.large, your key pair, a security group as above, and a subnet. The AMI brings an 8 GiB root volume and the dfdaemon piece cache lives on it (/var/lib/dragonfly/storage), so raise the root volume under Configure storage to fit the files you plan to cache.
With the AWS CLI (replace the values in angle brackets; this sets the root volume to 100 GiB):
aws ec2 run-instances --region <region> --image-id <ami-id-from-the-listing> \
--instance-type m5.large --key-name <your-key-pair> \
--security-group-ids <your-security-group> --subnet-id <your-subnet> \
--metadata-options HttpTokens=required,HttpEndpoint=enabled \
--block-device-mappings 'DeviceName=/dev/sda1,Ebs={VolumeSize=100,VolumeType=gp3}' \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=dragonfly}]'
Step 2: Connect to your instance
| Version | SSH user |
|---|---|
| Dragonfly 2.5.3 on Ubuntu 24.04 | ubuntu |
ssh -i <your-key.pem> ubuntu@<public-ip>
Step 3: Check the services
First boot creates the database, the secrets, the configuration and the console account, then starts Dragonfly and publishes the console. It takes about half a minute:
systemctl is-active dragonfly-firstboot mariadb redis-server dragonfly-manager dragonfly-scheduler dragonfly-dfdaemon nginx
active
active
active
active
active
active
active
Only SSH (22) and nginx (80, 443) listen on the network. Everything else listens on 127.0.0.1: MariaDB (3306), Redis (6379), the manager (8080 console and REST API, 65003 gRPC), the scheduler (8002) and the dfdaemon (4000 to 4005, and UDP 4006); the two port 53 entries are Ubuntu's local DNS resolver:
sudo ss -lntu | awk 'NR>1 {print $1, $5}' | sort -u
tcp 0.0.0.0:22
tcp 0.0.0.0:443
tcp 0.0.0.0:80
tcp 127.0.0.1:3306
tcp 127.0.0.1:4000
tcp 127.0.0.1:4001
tcp 127.0.0.1:4002
tcp 127.0.0.1:4003
tcp 127.0.0.1:4004
tcp 127.0.0.1:4005
tcp 127.0.0.1:6379
tcp 127.0.0.1:65003
tcp 127.0.0.1:8002
tcp 127.0.0.1:8080
tcp 127.0.0.53%lo:53
tcp 127.0.0.54:53
tcp [::]:22
tcp [::]:443
tcp [::]:80
udp 127.0.0.1:4006
...
The manager's health endpoint needs no sign in, and the programs report their versions:
curl -sk https://127.0.0.1/healthy; echo
/opt/dragonfly/bin/manager version | grep GitVersion
dfget --version
"OK"
GitVersion: v2.5.3
dfget 1.5.10 (024c6e9c7, 2026-10-26)
If nginx serves nothing, first boot has not finished (or failed, in which case nothing is published and Dragonfly does not start). Check systemctl status dragonfly-firstboot and journalctl -u dragonfly-firstboot.
Step 4: Get your URL and passwords
sudo cat /root/dragonfly-credentials.txt
The file is readable by root only and holds the address, the Basic authentication credential, the console sign in and the passwords the Dragonfly services use for MariaDB and Redis:
# Dragonfly on Ubuntu 24.04 (cloudimg AWS Marketplace image) - this instance's sign-in.
...
DRAGONFLY_CONSOLE_URL=https://ec2-203-0-113-10.compute-1.amazonaws.com/
CONSOLE_BASIC_AUTH_USER=admin
CONSOLE_BASIC_AUTH_PASSWORD=<CONSOLE_BASIC_AUTH_PASSWORD>
MANAGER_ADMIN_USER=root
MANAGER_ADMIN_PASSWORD=<MANAGER_ADMIN_PASSWORD>
MANAGER_DB_USER=dragonfly
MANAGER_DB_PASSWORD=...
REDIS_PASSWORD=...
You can confirm everything from the instance itself. The helper goes through nginx: it checks that the console refuses a missing or wrong Basic credential, that self registration, root/dragonfly and a wrong password are refused, that your root password signs in, and then pulls a 6 MiB test file through the dfdaemon seed peer and compares its checksum. It prints DRAGONFLY_ROUNDTRIP_OK:
sudo /usr/local/sbin/dragonfly-verify.sh | tail -1
DRAGONFLY_ROUNDTRIP_OK
The certificate is self signed until you install your own (Step 8). Before you accept it in the browser, you can compare its SHA-256 fingerprint with the one the browser shows:
sudo openssl x509 -in /etc/ssl/dragonfly/dragonfly.crt -noout -fingerprint -sha256
sha256 Fingerprint=3F:A1:...:7C
Step 5: Sign in to the console
Open the DRAGONFLY_CONSOLE_URL address in your browser and accept the certificate once (after comparing the fingerprint). The browser asks for a user name and password: enter admin and the CONSOLE_BASIC_AUTH_PASSWORD. The console's sign in page then opens; enter root and the MANAGER_ADMIN_PASSWORD.

The sign in page offers Create an account: self registration is switched off on this image (nginx refuses it), because a self registered account can read every cluster, job and audit record. Add people from the console (User) or connect an OAuth provider instead.
Change the console password now: open the account menu at the bottom left, choose Profile, and set a password of your own (8 to 16 characters, with at least one lower case letter and one digit). nginx allows two sign in attempts a second per address (with a short burst), so a script hammering the sign in is slowed down with HTTP 429.
The console opens on the cluster list. The single cluster cluster-1 holds this instance's scheduler and its seed peer:


Step 6: Pull files through the P2P cache
dfget asks the local dfdaemon to download a URL. The dfdaemon fetches the file from its origin in pieces (or from its cache, or from other peers when you run a cluster) and writes it to the output path. Downloading the Dragonfly licence file and checking its published checksum:
F=/tmp/dragonfly-LICENSE-$$
sudo dfget https://raw.githubusercontent.com/dragonflyoss/dragonfly/v2.5.3/LICENSE -O "$F" >/dev/null
sudo sha256sum "$F" | cut -c1-64
c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4
Things to know about dfget on this image:
- The dfdaemon writes the output file, as the
dragonflyaccount (mode 0640, groupdragonfly), so the output directory must be writable bydragonfly(for example/tmp, or a directory you create and give todragonfly). - Only root and members of the
dragonflygroup can usedfget(the dfdaemon's socket directory is closed to everyone else). Add a user withsudo usermod -aG dragonfly <user>. - The origin must support HTTP range requests (most web servers, S3 and CDNs do).
dfget --helplists the object storage schemes (s3://,gs://and others) and options such as--digest sha256:<hash>, which makesdfgetverify the file's checksum.
Step 7: Preheat and the registry mirror
Preheat loads files or container images into the cache before anyone asks for them. In the console open Job, then Preheat, and choose Add preheat: enter a file URL (or an image reference and its registry credentials), pick the cluster and create the job. The list shows each run:

The console marks a preheat run as finished even when its download failed; open the run to see which peers succeeded. For automation, create a personal access token under Developer and call the open API (https://<your-host>/oapi/v1/jobs) with Authorization: Bearer <token>; the open API does not use the Basic credential.

The dfdaemon also runs an HTTP proxy on 127.0.0.1:4001 that a container runtime on this instance can use as a registry mirror (Docker Hub by default); image layers then travel through the P2P cache. Point containerd or Docker on the instance at http://127.0.0.1:4001 as described in the Dragonfly documentation. The proxy listens on localhost only, so it is not an open proxy.
Step 8: Use your own host name and certificate
Point a DNS record at the instance (an Elastic IP keeps the address across stop and start), then tell the instance its name. This mints a new self signed certificate for that name, updates the nginx host rule, the origin and cross site guards and the address in the credentials file, and keeps the name across reboots:
sudo dragonfly-set-hostname dragonfly.example.com
To use a certificate from a public authority instead, replace /etc/ssl/dragonfly/dragonfly.crt (full chain) and /etc/ssl/dragonfly/dragonfly.key (mode 0600, owned by root) with your own and run sudo systemctl reload nginx. Running dragonfly-set-hostname again later would replace them with a new self signed pair.
To change the Basic authentication password, write a new hash (openssl asks for the new password twice) and reload nginx:
sudo sh -c 'printf "admin:%s\n" "$(openssl passwd -6)" > /etc/nginx/dragonfly.htpasswd'
sudo chown root:www-data /etc/nginx/dragonfly.htpasswd && sudo chmod 0640 /etc/nginx/dragonfly.htpasswd
sudo systemctl reload nginx
Step 9: Join peers on other hosts
This image is a closed single node. To let dfdaemons on other machines use it as their manager, scheduler and seed peer, you would have to make the manager's gRPC port (65003), the scheduler (8002) and the dfdaemon's upload and piece ports (4000, 4005, 4006/udp) listen on the instance's private address (listenIP/advertiseIP in /etc/dragonfly/manager.yaml and scheduler.yaml, the ip fields in dfdaemon.yaml) and open them in the security group. Those Dragonfly gRPC services have no authentication of their own: open them only to the private address ranges of your own peers, never to the internet, and consider Dragonfly's mutual TLS options. The Dragonfly documentation describes multi node deployments.
Step 10: Check persistence and updates
Every service is enabled, so Dragonfly returns after a reboot or a stop and start. If the public address changes, the next boot re-issues the certificate and the address for the new name (unless you set your own name in Step 8). Unattended security upgrades keep the operating system, MariaDB, Redis and nginx patched:
systemctl is-enabled mariadb redis-server dragonfly-manager dragonfly-scheduler dragonfly-dfdaemon dragonfly-set-host nginx unattended-upgrades
enabled
enabled
enabled
enabled
enabled
enabled
enabled
enabled
The manager and scheduler are built by cloudimg from the 2.5.3 source; /usr/share/doc/cloudimg/dragonfly/BUILD-PROVENANCE.txt records how. cloudimg publishes a new version of this image for new Dragonfly releases. To move to a newer release yourself, back up first (Step 11), replace the programs in /opt/dragonfly/bin with the new releases from the Dragonfly releases page and the client releases page, and restart the three dragonfly-* services. Read the release notes first: a new manager may migrate its database.
Step 11: Back up
The manager's state (clusters, jobs, users, tokens) is in the MariaDB database manager; the configuration is in /etc/dragonfly; the dfdaemon cache in /var/lib/dragonfly/storage can always be rebuilt from the origins. An EBS snapshot of the root volume (or AWS Backup on the instance) captures everything. For a database dump:
sudo mariadb-dump --single-transaction manager | gzip > dragonfly-manager.sql.gz
Security notes
- No shared secret ships in the image. No password, database, configuration, signing key or TLS key exists until your instance's first boot generates them, and the published
root/dragonflyconsole login is never created. - Fail closed. If first boot cannot complete, nothing is published: nginx has nothing to serve and the Dragonfly services, MariaDB and Redis do not start.
- Dragonfly is confined. Every Dragonfly, MariaDB and Redis port listens on 127.0.0.1. The Dragonfly services run as the unprivileged
dragonflyaccount, hold no Linux capabilities, write no core dumps, cannot change their programs or configuration and cannot read the TLS key, the credentials file or the database files. Every service is blocked from the EC2 instance metadata service. - Every published Dragonfly advisory is fixed in 2.5.3, and each class was re-tested on this image: the manager's REST API answers nothing without the Basic credential and the console sign in, the gRPC services cannot be reached from another host, and neither
dfget, the proxy nor a preheat job can reach the metadata service. - Origin certificates. By upstream design the dfdaemon does not verify the TLS certificate of the origin it downloads from (and its proxy answers HTTPS requests with a certificate it creates itself). Verify what you download with
dfget --digest, or rely on container image digests, which container runtimes check. - Go libraries. The Go vulnerability scanner lists two advisories for the Docker daemon library (GO-2026-4883, GO-2026-4887: an authorisation plugin bypass and a plugin privilege check in the Docker daemon). No fixed version exists; Dragonfly only uses that library's registry client helpers, never the daemon code concerned.
- Client libraries. The Rust dfdaemon carries some library advisories with no compatible fix yet: the XML parser
quick-xml(denial of service from a hostile XML document, which the dfdaemon only parses from object storage servers you choose and for profiling output), and moderaterustls, certificate store, DNS and time parsing issues. None of the dfdaemon's ports is reachable from outside the instance. - Restrict 22/tcp to your management network, and 80/443 to the networks that use the console.
Architecture summary
| Component | Detail |
|---|---|
| Manager | Dragonfly manager 2.5.3 (Apache-2.0, cloudimg source build), dragonfly-manager.service, console and REST 127.0.0.1:8080, gRPC 127.0.0.1:65003, account dragonfly |
| Scheduler | Dragonfly scheduler 2.5.3, dragonfly-scheduler.service, gRPC 127.0.0.1:8002 |
| Seed peer | dfdaemon 1.5.10, dragonfly-dfdaemon.service, 127.0.0.1:4000 to 4005 and UDP 4006, socket /run/dragonfly/dfdaemon.sock, cache /var/lib/dragonfly/storage |
| Database and cache | MariaDB 10.11 (127.0.0.1:3306, database manager), Redis 7.0 (127.0.0.1:6379, password) |
| Web server | nginx on 443 (HTTPS, per instance certificate in /etc/ssl/dragonfly, Basic authentication), 80 redirects to HTTPS |
| Configuration | /etc/dragonfly/{manager,scheduler,dfdaemon}.yaml (generated at first boot, root owned, readable by dragonfly) |
| Logs | /var/log/dragonfly/{manager,scheduler,dfdaemon} |
| Credentials | /root/dragonfly-credentials.txt, mode 0600, root only |
| First boot | dragonfly-firstboot.service; host name and certificate dragonfly-set-host.service (every boot) |
| Tools | dfget, dragonfly-set-hostname, dragonfly-verify.sh |
| Ports | 22 SSH, 80 redirect, 443 console and API |
| Base image | Ubuntu 24.04 LTS, fully patched, unattended security upgrades enabled, IMDSv2 required |
Support
cloudimg images come with 24/7 support. Email support@cloudimg.co.uk with your AWS account ID and the instance ID. For Dragonfly itself, see the Dragonfly documentation and the Dragonfly project on GitHub.
Dragonfly is a Cloud Native Computing Foundation project. cloudimg is not affiliated with or endorsed by the Dragonfly project or the CNCF.