Hosts and inventory

An inventory is just a list of hosts with connection details. For anything beyond a couple of machines, split it into its own file:

# inventory.yml
groups:
  web:
    hosts:
      - name: web01
        address: 203.0.113.42
      - name: web02
        address: 203.0.113.43
    vars:
      user: deploy
      ssh_key: ~/.ssh/id_ed25519_deploy

  db:
    hosts:
      - name: db01
        address: 203.0.113.50
    vars:
      user: postgres

Reference it from a playbook with --inventory:

conflux apply site.yml --inventory inventory.yml --limit web

Modules

A module is a single declarative unit — “this package should be present”, “this file should have this content”, “this service should be running”. Conflux ships with a small built-in set:

ModulePurpose
packageInstall/remove packages via the host’s native package manager
fileManage file content, ownership, permissions
serviceStart/stop/enable systemd units
userCreate or modify system users
cronManage crontab entries
execRun an arbitrary command, with a change-detection guard

Every module reports one of three states after running: unchanged, changed, or failed. Nothing is applied twice if it’s already in the desired state.

State tracking

Conflux does not keep a central database. Instead, each host keeps a small local manifest at /var/lib/conflux/state.json recording the last-applied checksum of each module. This is what lets conflux plan tell you what would change without a round trip to a server anywhere.

conflux state show web01
web01 — last applied 2026-09-12 14:03 UTC
  package.nginx        checksum a1b2c3d  (unchanged since 2026-08-01)
  file./etc/nginx/nginx.conf   checksum 9f8e7d6  (changed 2026-09-12)
  service.nginx         checksum 4c4c4c4  (unchanged since 2026-08-01)

Idempotency guarantee

A module is only allowed to report changed if its post-condition differs from its pre-condition. This is enforced by the module framework itself, not left to convention — see Writing Custom Modules if you’re extending Conflux.