8

I'm using Ansible to try to configure all of the workstations involved with a particular project to be able to use BitTorrent sync with a standard configuration (this is actually just an example of the kind of thing I want to do).

When I execute the playbook I can confirm that the debconf settings on the remote PCs have been updated, however the config file for the application has not been updated.

Is there a way to get ansible to finish the job off - having supplied a bunch of config data I just want to recompile the actual config file and then restart the service.

I'm using the latest Ansible (from PyPi) on Ubuntu 14.10 64bit hosts.

- hosts: btsync
  sudo: True
  tasks:
    - apt_repository: repo='ppa:tuxpoldo/btsync' update_cache=yes state=present
    - apt: name=btsync state=present
    - apt: name=debconf-utils state=present
    - apt: name=btsync-gui state=present
    - file: name='create a directory for BT Sync' path=/home/sal/bittorrent_sync state=directory owner=sal group=users mode=0755
    - debconf: name='btsync' question='btsync/runas' value='sal' vtype='string'
    - debconf: name='btsync' question='btsync/directory_root' value='/home/sal/bittorrent_sync' vtype='string'
    - debconf: name='btsync' question='btsync/webgui-bindaddr' value='0.0.0.0' vtype='string'
    - debconf: name='btsync' question='btsync/folder_defaults-use_lan_broadcast' value='true' vtype='boolean'
    - debconf: name='btsync' question='btsync/log_size' value='1' vtype='string'
    - debconf: name='btsync' question='btsync/folder_defaults-use_dht' value='true' vtype='boolean'
    - service: name='btsync' state=restarted

I can force the config file to be reconfigured from the debconf like this:

sudo dpkg-reconfigure -f noninteractive btsync

I suppose I could force Ansible to remotely execute that statement, but surely there's a better, more ansibleish way to do this?

dawud
  • 14,918
  • 3
  • 41
  • 61
Salim Fadhley
  • 183
  • 1
  • 4

2 Answers2

8

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.

4wk_
  • 292
  • 2
  • 14
xddsg
  • 3,202
  • 2
  • 26
  • 33
3

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

lbt
  • 161
  • 5
  • Thank you for answering such an ancient question! – Salim Fadhley Apr 08 '21 at 12:56
  • No problem @SalimFadhley - the question is old but still valid (I was looking for the information myself!) I ended up doing more digging and now I think I have a complete answer – lbt May 16 '21 at 09:22