Ansible project for provisioning and configuring SensorFleet hosts: fleet management (fleetmgmt) servers and sensor (sensors) hosts. It is a standalone repository (not a submodule of anything else).
Licensed under the MIT License — see LICENSE.md (Copyright (c) 2026 SensorFleet Oy).
-
Ansible 2.10.8 or newer as the supported minimum. This is a floor, not a target — see
AGENTS.mdfor the full version-constraint rationale (avoid relying on anything introduced after 2.10.8). -
The full
ansiblecommunity package on the control node (not bareansible-core). Roles use modules from bundled collections such asansible.posix, and there is deliberately norequirements.yml— the assumption is that the full package already provides what's needed. -
Python 3 on target hosts (
interpreter_python = /usr/bin/python3, set inansible.cfg). -
A local
.venv(gitignored) is the supported way to get a pinned Ansible +ansible-lint. Activate it before running any command below:source .venv/bin/activate
ansible.cfg # roles_path, interpreter_python
playbooks/ # top-level playbooks (flat directory)
roles/ # sensorfleet_<component> roles
inventories/
example/ # checked-in example inventory (starting-point template)
devel/ # local/gitignored real dev inventory (never committed)
docs/
VARIABLES.md # reference for every role's configurable variables
tools/migrate/ # standalone inventory-variable migration tool (own README)
AGENTS.md / CLAUDE.md # conventions and guidance for AI coding agents
LICENSE.md # MIT license
Every inventory has exactly two groups:
fleetmgmt— normally a single host, the fleet management server.sensors— one or more sensor hosts managed by that fleet management server.
inventories/example/ is the checked-in starting-point template — copy the whole directory as the basis for a new environment (it is not meant to be run against directly):
inventories/example/
hosts.yml # fleetmanagement + sensor001/sensor002, OpenVPN addressing
group_vars/all.yml # repositories, extra packages, commented-out optional settings
group_vars/fleetmgmt.yml # FM firewall rule example, initial admin account options
group_vars/sensors.yml # commented-out bridge/instrument examples
host_vars/sensor001.yml # commented-out per-sensor instruments, configs and homenets
all:
vars:
ansible_user: root
sensorfleet_openvpn_server_connect_ip: 192.168.0.10 # address sensors dial to reach the FM's OpenVPN server
children:
fleetmgmt:
hosts:
fleetmanagement:
ansible_host: 192.168.0.10
sensorfleet_openvpn_internal_ip: 169.254.255.255 # FM's (server) address inside the OpenVPN tunnel
sensors:
hosts:
sensor001:
ansible_host: 192.168.1.101
sensorfleet_openvpn_internal_ip: 169.254.1.1 # sensor's (client) address, unique per sensor
sensor002:
ansible_host: 192.168.2.102
sensorfleet_openvpn_internal_ip: 169.254.1.2Every host needs sensorfleet_openvpn_internal_ip, its own address inside the OpenVPN tunnel. The FM always uses 169.254.255.255, the server end of the tunnel, and each sensor gets a unique address from 169.254.0.0/16. See docs/VARIABLES.md.
Repository credentials (sensorfleet_repos_repository_login/_password) are left commented out with replace_me placeholders. They must be set before running against a real fleet (always on fleetmgmt), preferably via ansible-vault rather than in plain text. Generated admin credentials are written under <inventory>/credentials/, which is gitignored.
inventories/devel/ is the local, gitignored inventory used for real development/test targets (hosts, group_vars, cached PKI material, generated credentials). It is never committed — see .gitignore. Role-specific configuration on top of the defaults documented in docs/VARIABLES.md is set the same way: inventory hosts.yml vars, or group_vars/host_vars files alongside it.
Migrating an inventory that already uses the legacy SensorFleet variable naming scheme? Use the standalone tool in tools/migrate/ instead of hand-writing a new one.
Validate an inventory before running anything against it:
ansible-inventory -i inventories/devel/hosts.yml --listThe main, recurring provisioning play. Targets fleetmgmt:sensors and runs every role in sequence.
ansible-playbook -i inventories/devel/hosts.yml playbooks/sensorfleet.ymlsensorfleet_globals and sensorfleet_sanity_checks always run (tagged always); every other role is tagged with its own short name (mounts, internal_certificates, openvpn, system_cacerts, repos, services_ntp, kernel, sysctl, system, logging, ssh, nginx, fleetgram, firewall, config, usermgmt, license, instruments), so a subset can be applied with --tags/--skip-tags, e.g.:
ansible-playbook -i inventories/devel/hosts.yml playbooks/sensorfleet.yml --tags firewall,sshRun once, before the first sensorfleet.yml run, on a fresh Ubuntu install: upgrades/purges packages, sets up base mounts and certificates/VPN, and installs the role-specific package. It's guarded to skip hosts that are already bootstrapped, unless explicitly forced.
When creating a new sensor network using the prepare ubuntu playbooks it is required to create and fully provision the Fleet Management VM first. Proper ordering is:
- Create Fleet Management VM with Ubuntu 22.04 installed on it (FM-VM)
- Run sensorfleet_prepare_ubuntu playbook on the FM-VM
- Run sensorfleet playbook on the FM-VM
- Create sensor(s) VM(s) if desired with Ubuntu 22.04 on them (S-VMs)
- Run sensorfleet_prepare_ubuntu playbook on the S-VMs
- Run sensorfleet playbook on S-VMs (or without any limit)
ansible-playbook -i inventories/devel/hosts.yml playbooks/prepare_ubuntu.ymlTransition path for a host previously managed by the legacy Ansible project. Two phases: migrate legacy files forward (default), then remove them once the new setup is verified working (sensorfleet_ansible_migrate_cleanup is tagged [cleanup, never], so it only runs when explicitly requested). See tools/migrate/README.md's "Migration notes" section for the full runbook (order of operations, verification steps, reboot).
ansible-playbook -i inventories/devel/hosts.yml playbooks/migrate_legacy_ansible.yml
ansible-playbook -i inventories/devel/hosts.yml playbooks/sensorfleet.yml
ansible-playbook -i inventories/devel/hosts.yml playbooks/migrate_legacy_ansible.yml --tags cleanupTrivial helper: a single ansible.builtin.reboot task against fleetmgmt:sensors.
ansible-playbook -i inventories/devel/hosts.yml playbooks/reboot.ymlProvisioning roles, in the order sensorfleet.yml runs them. See docs/VARIABLES.md for every variable each role accepts.
| Role | Purpose | Variables |
|---|---|---|
sensorfleet_globals |
Shared defaults consumed by other roles (retry counts/delays, grsec kernel flag, FM repo service flag); defines no tasks of its own. | → |
sensorfleet_sanity_checks |
Asserts system hostname matches the inventory hostname, checks clock skew against the controller, and waits out any apt lock before proceeding. | → |
sensorfleet_mounts |
Sets up /mnt/transient-data (tmpfs) and /mnt/persistent-data. |
— (no configurable variables) |
sensorfleet_internal_certificates |
Manages internal TLS material and CSRs under /etc/sensorfleet/tls/internal and /etc/sensorfleet/csr. |
→ |
sensorfleet_openvpn |
Configures OpenVPN client/server material under /etc/sensorfleet/openvpn and /etc/openvpn. |
→ |
sensorfleet_system_cacerts |
Manages ca-certificates debconf settings and custom CA certificates. |
→ |
sensorfleet_repos |
Installs the SensorFleet apt GPG key; configures FM-relayed or direct apt repository access. | → |
sensorfleet_services_ntp |
Configures time sync: chrony on fleetmgmt, systemd-timesyncd on sensors. |
→ |
sensorfleet_kernel |
Installs linux-fleet/linux-fleet-grsec kernel packages and disables selected kernel modules. |
→ |
sensorfleet_sysctl |
Applies merged sysctl defaults, optional grsec overrides, and user overrides. | → |
sensorfleet_system |
General system hardening: package installation, root password, auth-import lockdown, journald/shell/sudo/lxd configuration. | → |
sensorfleet_logging |
Configures remote loghost forwarding over TCP/UDP/TLS via syslog-ng. | → |
sensorfleet_ssh |
Installs sshd_config (validated with sshd -t) and the SSH login banner. |
→ |
sensorfleet_nginx |
Installs the nginx vhost SSL certificate/key for the sensor UI. | → |
sensorfleet_fleetgram |
Manages the fleetgram index config and initial sensor config sync via the fleet config CLI. |
→ |
sensorfleet_firewall |
Manages ferm firewall rules under /etc/ferm/ferm.d. |
→ |
sensorfleet_config |
Reads, merges/replaces, and writes back fleet config via the fleet CLI. |
→ |
sensorfleet_usermgmt |
Creates the initial admin account on fleetmgmt hosts via the fleet CLI. |
→ |
sensorfleet_license |
Installs a base64-decoded license file to /etc/sensorfleet/license.json. |
→ |
sensorfleet_instruments |
Manages instrument configuration (e.g. netflow) via fleet config. |
→ |
Bootstrap and migration roles, used only by prepare_ubuntu.yml and migrate_legacy_ansible.yml:
| Role | Purpose | Variables |
|---|---|---|
sensorfleet_prepare_ubuntu |
One-time bootstrap of a fresh Ubuntu install: upgrades packages, installs the required base package set, purges unneeded ones, reboots if needed. Skips already-bootstrapped hosts unless forced. | → |
sensorfleet_prepare_role |
Installs the role-specific package (sensorfleet-fm on fleetmgmt, sensorfleet-sensor on sensors). |
— (no configurable variables) |
sensorfleet_ansible_migrate |
Copies/adapts files left over from the legacy Ansible setup (e.g. ta.key) forward to their new locations. |
— (no configurable variables) |
sensorfleet_ansible_migrate_cleanup |
Removes the legacy files once the migration is verified. Only runs with --tags cleanup. |
— (no configurable variables) |
Full contributor/agent-facing conventions live in AGENTS.md — read it before making changes. In short:
-
Every role is named
sensorfleet_<component>, and every role variable is prefixed with its role's name (sensorfleet_<component>_*). -
Roles that behave differently on
fleetmgmtvs.sensorshosts dispatch to separatefm.yml/sensor.ymltask files, gated onwhen: "'fleetmgmt' in group_names". -
ansible-lint --profile productionis the acceptance bar for every change to a role or playbook:ansible-lint --profile production roles/<role>
MIT — Copyright (c) 2026 SensorFleet Oy. See LICENSE.md.