Puppet: System Administration Automated

Support

Managing Debian packages using debconf preseed

Problem

I want to install postfix on all my servers as a standalone mta that relays all mail to a central mta.
Normally you would just do something like the following:

package { "postfix": ensure => present }
service { "postfix": ensure => true, enable => true }
file { "/etc/postfix/main.cf":
  backup => false,
  content => template("daemons/mta/postfix/main.cf.erb"),
  notify => Service["postfix"],
  require => Package["postfix"],
}

So we are installing the package and a default main.cf is installed as part of that package installation, then we clobber that file with an erb template.
Why bother clobbering a config file that is automatically generated out of debconf anyway?

Solution

We can use a preseed file which is a list of responses that debconf can use to configure a package.
Firstly the easiest way to get your response file is by manually installing a package on a target system.

apt-get install postfix

During this process we get asked what type of mta we want to install, so for my purpose i selected Satellite and entered in my relay server.
Once that is done you will need to install debconf-utils which provides the command debconf-get-selections After you have installed this package run the following:

debconf-get-selections | grep "postfix\/" > /tmp/postfix.preseed

If we look at the contents of that file:

postfix	postfix/master_upgrade_warning	boolean	
postfix	postfix/db_upgrade_warning	boolean	true
postfix	postfix/mailname	string	/etc/mailname
postfix	postfix/tlsmgr_upgrade_warning	boolean	
postfix	postfix/recipient_delim	string	+
postfix	postfix/dynamicmaps_upgrade_warning	boolean	
postfix	postfix/main_mailer_type	select	Satellite system
postfix	postfix/transport_map_warning	note	
postfix	postfix/relayhost	string	someserver.domain.tld
postfix	postfix/procmail	boolean	false
postfix	postfix/bad_recipient_delimiter	note	
postfix	postfix/chattr	boolean	false
postfix	postfix/root_address	string	
postfix	postfix/rfc1035_violation	boolean	false
postfix	postfix/mydomain_warning	boolean	
postfix	postfix/mynetworks	string	127.0.0.0/8
postfix	postfix/destinations	string	puppet, localhost.localdomain, localhost
postfix	postfix/nqmgr_upgrade_warning	boolean	
postfix	postfix/not_configured	note	
postfix	postfix/mailbox_limit	string	0
postfix	postfix/protocols	select	all

NOTE: one line i changed in that file was "postfix postfix/mailname string XXXXX" from the server i generated this on to /etc/mailname as it sets the current hostname to that value.

Now that we have a preseed file we can then put that on our fileserver. Depending on your setup place this wherever you feel necessary.

define preseed_package ( $ensure ) {
  file { "/var/local/preseed/$name.preseed":
    source => "puppet://$server/rfile/daemons/$name/$name.preseed",
    mode => 600,
    backup => false,
  }
  package { "$name":
    ensure => $ensure,
    responsefile => "/var/local/preseed/$name.preseed",
    require => File["/var/local/preseed/$name.preseed"],
  }

Then we can just call this postfix package as the following:

class mta {
  preseed_package {"postfix": ensure => present }
}

Now when you run the client you will see something like the following:

info: Package[postfix](provider=apt): Preseeding /var/local/preseed/postfix.preseed to debconf-set-selections
notice: //Node[gbl-admin-01]/soe/daemon-mta-relay/Package[postfix]/ensure: ensure changed 'purged' to 'present'

Discussion