Introducing AI agent: Get information about your infrastructure faster. Learn more >

Change in behavior: Storage promise

Posted by Nick Anderson
August 13, 2026

CFEngine 3.29.0 changes how storage promises treat a filesystem that is already mounted. A promise for an unmounted filesystem now mounts only that filesystem instead of all unmounted filesystems, edit_fstab actively maintains the file system table entry to keep it aligned with the promise even when the filesystem is already mounted, and an unmount promise acts only on the explicitly promised filesystem. Additionally there are is new functionality to remount a filesystem automatically to correct its state.

Only the promised filesystem is mounted

Previously, a promise for a filesystem that was not mounted did not mount that filesystem directly, rather it was seeing that a mount was needed which would cause mount -a to run at the end of the agent run (mounting any unmounted entries). A single promise could therefore bring up unrelated filesystems as a side effect.

Now only the promised filesystem is mounted (CFE-1863). If you want every entry in the file system table mounted, use mountfilesystems in body agent control.

The file system table entry is maintained for mounted filesystems

edit_fstab used to write the entry as part of the initial mount. If the filesystem was already mounted there was nothing to do, so a missing or drifted entry was not altered as long as the mount point had something mounted.

With 3.29.0 the fstab entry is managed independently, regardless of whether the filesystem is mounted (CFE-1539). A missing entry is restored, and an entry whose options have drifted is rewritten.

When mount_options is not specified the entry is written with the platform default options – defaults on Linux, bg,hard,intr on AIX, HP-UX and Solaris, -i,-b on the BSDs and macOS.

unmount acts only on the filesystem it names

Promising that a filesystem is not mounted keys off of mount_source and mount_server instead of the promised mountpoint (CFE-2350).

bundle agent example_unmount
{
      storage:
      "/mnt/-export-home"
        mount => decomissioned;
}
body mount decommissioned
{
  mount_type   => "nfs";
  unmount => "true";
  mount_source => "/export/home";
  mount_server => "decommissioned_host.example.org";
  edit_fstab   => "true";
}

If a filesystem other than the promised one is mounted at the promiser, it is neither unmounted nor removed from the file system table. When the promised filesystem is mounted there it is unmounted and its entry removed; when nothing is mounted there the entry is removed anyway.

New: reconciling the options of a running mount

By default mount_options still affect only the initial mount and, with edit_fstab, the file system table entry. A filesystem that is already mounted with different options is left as it is.

When remount is enabled the promised options are compared against the running mount and reconciled when they differ.

body mount readonly_data
{
  mount_type    => "nfs";
  mount_source  => "/export/data";
  mount_server  => "fileserver.example.com";
  mount_options => { "ro", "nosuid" };
  edit_fstab    => "true";

  remount => "true";
}

remount also decides what happens when the mount point holds a filesystem different from the promised one. Without it the promise would be reported as not kept. With remount enabled cf-agent will attempt correction.

Mount reconciliation

remount_methods is an ordered list of mechanisms attempted sequentially, waiting for remount_timeout (60 second default) between each.

  • remount – remount in place (mount -o remount,...). Applies generic mount flags such as ro / rw and the atime options, but cannot change NFS-negotiated options such as vers, proto or sec.
  • unmount_mount – unmount and mount again. Applies any option change and can correct a wrong mount source or server, but is disruptive and fails if the filesystem is busy.

The default is { "remount" }.

body mount reconcile_hard
{
  remount => "true";

  # try an in-place remount first, then unmount + mount for options a
  # remount cannot change, or a wrong source or server
  remount_methods => { "remount", "unmount_mount" };
}

How promised fstab options are compared

Only the fstab options promised are enforced. Kernel-added options like vers=, rsize=, wsize=, timeo=, addr= and anything else the promise does not mention are not enforced.

CFEngine expands defaults to rw, suid, dev, exec and async, then checks each of those against the running mount.

Let us know how it goes!

If you have questions or want to share your experience with the new behavior, reach out on GitHub discussions, the mailing list, or Matrix. To report a bug or request a feature, open an issue on the issue tracker. If you have a support contract, feel free to open a ticket (sooner is better than later) in our support system.