The Handbook

    Theme
    • Guides
        • Check a system before installing FreeBSD
        • Orient a Linux administrator on FreeBSD
        • Supported FreeBSD releases
        • Choose a FreeBSD documentation and support channel
        • Move files safely without GNU mv -t
        • Update, upgrade, or update packages?
        • Upgrade 14.4 or 15.0 to FreeBSD 15.1
        • Choose packages, ports, or poudriere
        • Choose the quarterly or latest package branch
        • Choose a FreeBSD download or package mirror
        • Make a system setting persistent
        • Configure locale, keyboard, and time zone
        • Configure a serial console for recovery
        • Choose a custom kernel, module, or loader setting
        • Run a Linux binary with the compatibility layer
        • Check desktop and laptop hardware before installation
        • Choose and check a graphics driver
        • Choose Xorg or Wayland
        • Build a maintainable desktop baseline
        • Install and check a desktop browser
        • Check laptop Wi-Fi, power, and suspend
        • Check multimedia readiness
        • Choose and configure a printing stack
        • Run Windows applications with Wine
        • Snapshot and replicate a ZFS dataset
        • Choose a filesystem and storage layout
        • Operate ZFS without losing the recovery path
        • Restore files from a ZFS snapshot
        • Read ZFS pool health and run a scrub
        • Replace a failed device in a ZFS mirror
        • Replicate a ZFS dataset over SSH
        • Change PF safely on a remote host
        • Configure a narrow WireGuard tunnel
        • Plan a FreeBSD home server
        • Choose a mail server or an outgoing relay
        • Publish a network service safely
        • Choose a jail network model
        • Choose native jails or a jail manager
        • Choose a jail or a bhyve virtual machine
        • Establish a FreeBSD security baseline
        • Choose a MAC policy
        • Audit security-relevant activity
        • Start a DTrace performance investigation
    • Integrations
        • Create a first jail with Bastille
        • Compare jail managers and OCI tooling
        • Publish a Bastille service through PF
        • Mount a ZFS dataset in a Bastille jail
        • Update and upgrade Bastille jails
        • Back up and restore a Bastille jail
        • Prepare bhyve and vm-bhyve
        • Choose NFS or Samba for file sharing
        • Choose ZFS backup automation
        • Operate a signed poudriere repository
        • Manage FreeBSD configuration with Ansible or Salt
        • Run Motion with webcamd on FreeBSD
        • Design a reverse proxy, certificates, and monitoring
    • FAQ
      • Troubleshooting
          • Recover an interrupted freebsd-update run
          • Resolve a package repository or ABI mismatch
          • Diagnose the FreeBSD boot path
          • Recover with a ZFS boot environment
          • Diagnose DNS, routing, and firewall paths
          • Diagnose network mbuf exhaustion
          • Bind a service to a low port without running it as root
          • Diagnose audio output or input
          • Diagnose webcamd, cuse, and a webcam
          • Fix USB device permissions without opening every device
      • About this handbook
      • Synopsis
      • Choose the control model
      • Bootstrap deliberately
      • Assign one owner to every resource
      • Keep package operations bounded
      • Validate files before activation
      • Stage every rollout
      • Audit drift without erasing evidence
      • Primary references

      Manage FreeBSD configuration with Ansible or Salt

      Last reviewed
      13 August 2026
      Applies to
      15.1-RELEASE, 15.0-RELEASE, 14.4-RELEASE

      Synopsis #

      Ansible and Salt can manage FreeBSD packages, files, rc.conf variables, and services. Neither tool makes an unsafe package upgrade, invalid configuration, or fleet-wide restart safe. Reliability comes from explicit file ownership, FreeBSD-aware modules, preflight validation, small rollout batches, and a tested recovery path.

      Begin with the system’s manually reviewed source of truth. Persistent system settings distinguishes loader, sysctl, rc.conf, and service configuration; those boundaries should remain visible in automation.

      Choose the control model #

      RequirementAnsibleSalt
      Agentless SSH-oriented executionPrimary modelSalt SSH is available, but not the default minion model
      Resident agent and event-driven stateNot the normal architectureSalt minion and master model
      Small fleet with occasional convergent runsStrong fitPossible, with more infrastructure
      Frequent state enforcement and event integrationPossible through external schedulingStronger native fit
      FreeBSD package providercommunity.general.pkgngpkg virtual provider backed by pkgng on modern FreeBSD
      FreeBSD rc.conf integrationcommunity.general.sysrcsysrc execution module or explicitly managed files

      Tool selection should follow the desired operating model, not a generic module-count comparison. The controller, state repository, secrets store, and execution credentials are production infrastructure and need their own backup and recovery plan.

      Bootstrap deliberately #

      Most Ansible POSIX modules require a Python interpreter on the managed host. FreeBSD base does not provide a general-purpose Python runtime. A bootstrap path may use Ansible’s raw action for the minimal reviewed package installation, after which normal modules can manage the runtime. Interpreter discovery and package naming must be tested on every supported host group.

      Salt normally installs a minion and its runtime on each managed host. Salt SSH changes that topology but also changes available behavior and performance. Choose one documented enrollment path, authenticate the control endpoint, and treat master or roster credentials as secrets.

      Do not allow an enrollment script to perform a general package upgrade. Bootstrap should establish only the management prerequisites and then stop for an ordinary reviewed convergence.

      Assign one owner to every resource #

      Maintain a resource register for at least these classes:

      ResourceSafe ownership rule
      Installed packageOne repository policy and one automation declaration
      /etc/rc.conf variableA FreeBSD-aware rc.conf operation or one dedicated managed fragment
      /etc filePreserve base-system semantics, owner, mode, and validation command
      /usr/local/etc fileCoordinate with the package’s sample, upgrade notes, and rc.d service
      SecretRetrieve from the designated secret store; never commit plaintext
      Service restartTrigger only after a validated material change
      Loader or network changeUse a maintenance window and explicit recovery path

      Avoid managing the same file through a whole-file template, a line editor, and a local administrator. Convergence is undefined when several owners rewrite one resource.

      For rc.conf values, prefer community.general.sysrc in Ansible rather than treating /etc/rc.conf as an arbitrary text file. Salt exposes a FreeBSD sysrc module, but a deployment should verify its available functions against the installed Salt release before encoding state around it.

      Keep package operations bounded #

      Ansible’s community.general.pkgng and Salt’s pkgng provider use FreeBSD pkg. They inherit the client’s configured repositories and the consequences of changing them.

      Package state should name required packages and a deliberate version policy. A fleet-wide equivalent of an unreviewed pkg upgrade can remove or replace dependencies on every host. Review package-branch policy with choose quarterly or latest , and qualify private packages with operate a signed poudriere repository .

      Before a broad change, capture the proposed package transaction on a representative host. Keep application configuration and package upgrades separate when either change can require a migration.

      Validate files before activation #

      Use whole-file management for configuration that automation fully owns. Set owner, group, and mode explicitly. Ansible copy and template support a validation command that checks a temporary candidate before replacing the destination. Salt file.managed has its own validation and test facilities; use the interface documented for the installed Salt release.

      A safe service change follows this sequence:

      1. render the candidate without restarting the service;
      2. run the service’s native syntax checker against that candidate;
      3. replace the file only after validation succeeds;
      4. reload rather than restart when the service documents that behavior;
      5. test a real health condition, not only process existence;
      6. stop the rollout on the first failed host.

      A handler or requisite should run only when the managed resource changed. Unconditional service restarts turn harmless convergence into an availability event.

      Stage every rollout #

      Ansible check mode and diff mode, and Salt test mode, predict changes where modules support them. They are review aids, not proof: external commands, package transactions, and service behavior can differ during a real run.

      Use a rollout ladder:

      1. syntax and policy checks in the state repository;
      2. an expendable host matching production;
      3. one canary with console or out-of-band recovery;
      4. a small serial batch;
      5. the remaining fleet only after health and observation time.

      Keep network, firewall, SSH, storage, and boot-loader changes out of an unrestricted all-host run. The safe PF change procedure is an example of a change that needs a rollback timer and independent management path.

      For ZFS-root systems, a boot environment can improve recovery from package and configuration changes, but it does not protect external datasets or correct a broken network path. See boot environment recovery .

      Audit drift without erasing evidence #

      Schedule read-only convergence or drift reports separately from automatic remediation when a resource is operationally sensitive. An unexpected manual change can be evidence of an incident or an emergency repair. Capture the diff and owner before overwriting it.

      Record tool version, collection or extension versions, state revision, target set, start and completion time, changed resources, and health result for every production run. Pin controller dependencies so a routine run does not silently adopt new module semantics.

      Primary references #

      • Ansible: FreeBSD platform guide
      • Ansible community.general.pkgng
      • Ansible community.general.sysrc
      • Ansible copy module
      • Salt pkgng provider
      • Salt sysrc module
      • Salt file.managed state
      • sysrc(8)

      Independent documentation. Not affiliated with or endorsed by the FreeBSD Project or the FreeBSD Foundation.

      Report a bug
      • Synopsis
      • Choose the control model
      • Bootstrap deliberately
      • Assign one owner to every resource
      • Keep package operations bounded
      • Validate files before activation
      • Stage every rollout
      • Audit drift without erasing evidence
      • Primary references