Security Azure

Fleet on Ubuntu 24.04 on Azure User Guide

| Product: Fleet on Ubuntu 24.04 LTS on Azure

Overview

Fleet is an open source device management and endpoint security platform built on osquery. It enrolls laptops, servers and cloud hosts as agents, then lets you run live queries across the whole fleet, apply policies to check security posture, collect software inventory, and surface vulnerabilities from one web interface. A REST API and the fleetctl command line client expose the same data to automation, so security, IT and infrastructure teams share one accurate source of truth for what is running on every machine.

The cloudimg image installs the official Fleet 4.89.1 server as a single node on one VM: the Fleet Go binary backed by on-box MySQL 8 and Redis, fronted by nginx which terminates TLS. It ships the free (MIT-licensed) tier with no premium licence key. Every secret, the first administrator account, and the TLS certificate are generated uniquely on the first boot of each VM, and Fleet's one-time setup page is consumed automatically before the port is ever public, so nobody can claim the instance before you retrieve the per-VM password. Backed by 24/7 cloudimg support.

What is included:

  • Fleet 4.89.1 (the official upstream binary, verified by SHA-256), free tier, no premium licence key
  • On-box MySQL 8.0 and Redis 7, both bound to loopback with per-VM passwords
  • nginx terminating TLS on :443 (per-VM self-signed certificate) and reverse-proxying to Fleet on 127.0.0.1:8080, with :80 redirecting to :443
  • A single administrator account created uniquely on first boot and recorded in a root-only credentials file - no default login ships in the image
  • Fleet's one-time setup page consumed on first boot, so nobody can register the first admin before you do
  • A 2 GiB swapfile and the OS fully patched at build time

Before you start

You will need an Azure subscription, the Azure CLI (or the Azure Portal), and an SSH key pair. Fleet's web UI and the osquery agent enrollment both use HTTPS on port 443, and you connect over SSH on port 22, so allow both in the VM's network security group.

The recommended size is Standard_B2s (2 vCPU, 4 GiB) for evaluation and small fleets; move up to a Standard_B2ms or D2s_v5 for larger deployments.

Deploy the VM

From the Azure Portal

  1. Open the Fleet on Ubuntu 24.04 LTS offer on the Azure Marketplace and select Get it now, then Create.
  2. Choose your subscription, resource group and region, set the VM size to Standard_B2s, and provide your SSH public key for the azureuser account.
  3. On the Networking tab, allow inbound SSH (22) and HTTPS (443).
  4. Review and create. When deployment finishes, note the VM's public IP address.

From the Azure CLI

az vm create \
  --resource-group my-fleet-rg \
  --name fleet \
  --image cloudimg:fleet:fleet-ubuntu-24-04:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard
# The web UI and agent enrollment share 443:
az vm open-port --resource-group my-fleet-rg --name fleet --port 443 --priority 1001

Replace the --image URN with the exact plan reference shown on the offer's Marketplace page if it differs.

Retrieve the per-VM administrator password

The image ships no known credential. On first boot each VM generates its own administrator password (plus MySQL, Redis and server keys) and writes them to a root-only file. SSH in and read it:

sudo cat /root/fleet-credentials.txt

You will see the per-VM login URL, the admin email and password, and the internal database and cache passwords:

fleet.url=https://<your-vm-ip>/
fleet.admin.login=https://<your-vm-ip>/login
fleet.admin.email=admin@fleet.local
fleet.admin.pass=****************************
fleet.org=cloudimg Fleet
fleet.db.name=fleet
fleet.db.user=fleet

The per-VM Fleet credentials file with the admin, database and Redis passwords masked, alongside the swapfile and the preserved MIT LICENSE

Confirm the stack is healthy

Fleet, MySQL, Redis and nginx should all be active. MySQL, Redis and the Fleet server listen only on loopback; nginx is the single public listener on :443:

systemctl is-active mysql redis-server fleet nginx
active
active
active
active

Check the listeners and confirm the web endpoint answers over HTTPS:

sudo ss -tlnp | grep -E ':(443|8080|3306|6379)'
curl -sk -o /dev/null -w 'fleet web: HTTP %{http_code}\n' https://127.0.0.1/

nginx is bound to 0.0.0.0:443, while Fleet (8080), MySQL (3306) and Redis (6379) are bound to 127.0.0.1 only, and the web endpoint returns HTTP 200:

Fleet, MySQL, Redis and nginx active, the loopback listeners for Fleet, MySQL and Redis, nginx on 443, and the Fleet version

Sign in to Fleet

Browse to https://<your-vm-ip>/ and sign in with the admin email and password from the credentials file. Because the VM ships a per-VM self-signed certificate, your browser shows a one-time certificate warning on first visit - click through it, or install your own domain certificate as described in the hardening section below.

The Fleet sign-in page served by the VM

After signing in you land on the dashboard, which summarises how many hosts are enrolled, their operating systems, and which are online. It is empty until you enroll your first host.

The Fleet dashboard showing enrolled hosts by operating system and the hosts-online timeline

Enroll your first host

Fleet manages hosts through a lightweight agent (fleetd, which bundles osquery). From the dashboard select Hosts then Add hosts, choose the platform, and Fleet shows you an install command that embeds this server's URL and an enrollment secret. For Linux and macOS the flow is:

# On the machine you want to enroll (NOT the Fleet server), install fleetd
# using the command Fleet generates for you under Hosts > Add hosts:
fleetctl package --type=deb --fleet-url=https://<your-vm-ip> --enroll-secret=<secret>
sudo dpkg -i fleet-osquery_*.deb

Within a minute the host appears under Hosts with its hardware, operating system, software inventory and policy results. Because agents enroll over the same 443 endpoint, no extra port is required.

The enrollment secret is generated per-VM and shown in the UI under Hosts > Add hosts; you can also retrieve it with fleetctl get enroll-secret.

Run queries across your fleet

osquery exposes the operating system as a SQL database. Saved queries live under Reports - the image ships a starter set covering system information, OS version, installed software, logged-in users and listening ports. Open any query to run it live against selected hosts and see results stream back in seconds.

The Reports page listing the saved osquery queries shipped with the image

You can drive the same queries from the API. Read your per-VM admin credential from the credentials file, log in to obtain a token, then call the REST API:

CREDS=/root/fleet-credentials.txt
EMAIL=$(sudo awk -F= '/^fleet.admin.email=/{print $2}' "$CREDS")
PASS=$(sudo awk -F= '/^fleet.admin.pass=/{print $2}' "$CREDS")
TOKEN=$(curl -sk -X POST https://127.0.0.1/api/v1/fleet/login \
  -H 'Content-Type: application/json' \
  -d "{\"email\":\"$EMAIL\",\"password\":\"$PASS\"}" \
  | python3 -c 'import sys,json;print(json.load(sys.stdin)["token"])')
curl -sk -H "Authorization: Bearer $TOKEN" https://127.0.0.1/api/v1/fleet/hosts \
  | python3 -c 'import sys,json;print("hosts enrolled:",len(json.load(sys.stdin)["hosts"]))'
hosts enrolled: 0

Check compliance with policies

Policies are yes/no osquery checks that run on every host and flag the ones that fail. The image ships example Linux policies - SSH root login disabled, host firewall enabled, and disk encryption present - which you can edit or extend under Policies > Add policy. Failing hosts are surfaced on the dashboard so you can act on posture drift.

The Policies page listing the example compliance checks shipped with the image

Security model

This image follows cloudimg's no-known-credential rule. The one-time setup page - which, on a stock Fleet install, lets whoever reaches it first create the admin account and seize the server - is consumed automatically on first boot, on the loopback interface, before nginx exposes :443. A fresh admin POST is refused, no blank or guessable default credential authenticates, and the loopback-bound database rejects a wrong password:

curl -sk -o /dev/null -w 'second setup POST: HTTP %{http_code}\n' \
  -X POST https://127.0.0.1/api/v1/setup -H 'Content-Type: application/json' \
  -d '{"admin":{"admin":true,"email":"x@x.io","password":"Aa1#aaaaaaaa","name":"x"},"org_info":{"org_name":"x"}}'
curl -sk -o /dev/null -w 'blank password login: HTTP %{http_code}\n' \
  -X POST https://127.0.0.1/api/v1/fleet/login -H 'Content-Type: application/json' \
  -d '{"email":"admin@fleet.local","password":""}'

The setup POST returns a non-200 (the page is already consumed) and the blank-password login returns HTTP 401:

Proof that the setup page is consumed, no default or blank credential logs in, the wrong database password is refused, and the free tier ships with no premium licence key

Production hardening

For anything beyond evaluation:

  • Use your own domain and a real certificate. Point a DNS record at the VM, then replace /etc/nginx/ssl/fleet.crt and /etc/nginx/ssl/fleet.key with a certificate for your domain (for example via Certbot), and set the Fleet server URL to https://fleet.example.com under Settings > Organization settings. Agents enroll against this URL, so set it before deploying agents at scale.
  • Rotate the admin password after first sign-in, and add named user accounts under Settings > Users rather than sharing the bootstrap admin.
  • Back up MySQL. All Fleet state lives in the on-box fleet database; schedule a mysqldump (or snapshot the disk) on your own cadence.
  • Configure SMTP under Settings > Organization settings so Fleet can send invitations and password resets.
  • Keep the OS patched. The image ships fully patched with unattended-upgrades enabled; leave it on.

Support

This image is maintained by cloudimg with 24/7 support. Fleet is free and open source software licensed under the MIT licence for its core; the copy shipped here is unmodified and the LICENSE is preserved at /usr/share/doc/fleet/LICENSE. cloudimg is not affiliated with or endorsed by Fleet Device Management Inc; the Fleet name is used only to identify the software.