How do I make Ansible actually compile a config file having changed my debconf settings for an application?

That's how debconf works, you wouldn't expect packages to reconfigure automatically if you just edited the file either.

What you want is a notify handler that does the dpkg reconfigure once at the end of the play.

- debconf: name: 'btsync' question: 'btsync/folder_defaults-use_dht' value: 'true' vtype: 'boolean' notify: reconfigure btsync

and in your handlers file:

- name: reconfigure btsync command: sudo dpkg-reconfigure -f noninteractive btsync

Now, if debconf actually changed anything (and only if - idempotent), btsync will get reconfigured once when all your tasks have run.


TL;DR; Use Ansible debconf but then mv /var/lib/dpkg/info/<package>.config file aside whilst reconfiguring using dpkg-reconfigure

The rest of this is for others searching for insight into debconf and Ansible's debconf module.

I spent some time digging into this and have submitted some docs to the Ansible debconf module which I've edited a bit for this answer.

Reconfiguring packages in Debian using debconf is not straightforward!

The Ansible debconf module does not reconfigure packages, it just updates the debconf database. An additional playbook step is needed (typically via notify if debconf makes a change) to reconfigure the package and apply the changes.

Now debconf is primarily used for pre-seeding configuration prior to installation.

So, whilst dpkg-reconfigure does use debconf data, it is not always authoritative and you may need to check how your package is handled.

dpkg-reconfigure is a 3-phase process. It invokes the control scripts from the /var/lib/dpkg/info directory with the following arguments:

  <package>.prerm  reconfigure <version>
  <package>.config reconfigure <version>
  <package>.postinst control <version>

The main issue is that the <package>.config reconfigure step for many packages will first reset the debconf database (overriding changes made by the Ansible module) by checking the on-disk configuration. If this is the case for your package then dpkg-reconfigure will effectively ignore changes made by this debconf module.

However although dpkg-reconfigure finally invokes:

/var/lib/dpkg/info/<package>.postinst configure <version>

to actually configure the package; using this turns out not to be that simple. The script is expected to be run from a "debconf frontend" and uses IPC to respond to the _db_cmd statements in the script.

To see this in more detail

export DPKG_MAINTSCRIPT_PACKAGE=<package>
export DPKG_MAINTSCRIPT_NAME=<script path>
export DEBIAN_HAS_FRONTEND=1

and run the script. I was trying to setup unattended-upgrades so I ran:

sh -x /var/lib/dpkg/info/unattended-upgrades.postinst configure 1.11.2

This then halts waiting for a response from the frontend.

Running

/usr/share/debconf/frontend /var/lib/dpkg/info/unattended-upgrades.postinst configure 1.11.2

works... but has the exact same problem as dpkg-reconfigure - it resets the debconf database :(

This is because running

 /var/lib/dpkg/info/unattended-upgrades.postinst configure 1.11.2

sources /usr/share/debconf/confmodule which exec()s /usr/share/debconf/frontend which forces the <package>.config configure phase to take place.

This is done based on the existence (ie using shell [-e]) of the .config file and cannot be avoided.

The solution is to mv /var/lib/dpkg/info/<package>.config out of the way whilst dpkg-reconfigure (or other related debconf code) runs.

Note the Debian programmers manual says that the config script's sole purpose is to populate debconf and must not affect other files; so doing this in a playbook is (to my understanding) compliant with debian policy: http://www.fifi.org/doc/debconf-doc/tutorial.html#AEN113

HTH