Deployment guide

Fleet

Overview

Fleet is an open-source device management and endpoint security platform built on osquery. It enrolls laptops, servers and cloud hosts as agents. From one web interface you can then run live queries across the whole fleet, apply policies to check security posture, collect software inventory and surface vulnerabilities.

A REST API and the fleetctl command-line client expose the same data to automation. Security, IT and infrastructure teams share one accurate source of truth for what is running on every machine.

The SecureAnyCloud image installs the official Fleet 4.89.1 server as a single node on one VM. It runs 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 license key. Every secret, the first administrator account and the TLS certificate are generated uniquely on the first boot of each VM. 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.

What you get:

  • Fleet 4.89.1 (the official upstream binary, verified by SHA-256), free tier, no premium license 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, with no default login 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
  • 24/7 SecureAnyCloud support

Before you start

You 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. Allow both ports in the VM's network security group.

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

Deploy the VM

From the Azure Portal

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

From the Azure CLI

az vm image terms accept --urn sac1647283583153:fleet:default:latest
az vm create \
  --resource-group my-fleet-rg \
  --name fleet \
  --image sac1647283583153:fleet:default: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

If the plan reference on the offer's Marketplace page differs, replace the --image URN with that reference.

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. Connect over SSH and read the file:

sudo cat /root/fleet-credentials.txt

The file lists the per-VM login URL, the admin email and password, and the 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=sac Fleet fleet.db.name=fleet fleet.db.user=fleet

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/

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

Sign in to Fleet

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

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

Enroll your first host

Fleet manages hosts through a lightweight agent (fleetd, which bundles osquery). From the dashboard, select Hosts then Add hosts and choose the platform. Fleet shows 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. Agents enroll over the same 443 endpoint, so 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 that covers 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.

You can run 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 hosts that fail. The image ships example Linux policies: SSH root login disabled, host firewall enabled and disk encryption present. You can edit or extend them under Policies > Add policy. Failing hosts appear on the dashboard so you can act on posture drift.

Security model

This image follows SecureAnyCloud's no-known-credential rule. On a stock Fleet install, the one-time setup page lets whoever reaches it first create the admin account and seize the server. On this image, the page 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 response (the page is already consumed), and the blank-password login returns HTTP 401.

Production hardening

Beyond evaluation, take these steps:

  • 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). 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 your 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 is patched at build time and ships with unattended-upgrades enabled. Leave it on.

Support

This image is maintained by SecureAnyCloud with 24/7 support. Fleet is free, open-source software, and its core is licensed under the MIT license. The copy shipped here is unmodified, and the LICENSE is preserved at /usr/share/doc/fleet/LICENSE.

SecureAnyCloud is not affiliated with or endorsed by Fleet Device Management Inc. The Fleet name is used only to identify the software.

Deploy on Azure

Launch Fleet 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