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
source
s /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