The Puppet Labs Issue Tracker has Moved: https://tickets.puppetlabs.com

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, $source = false ) {
  $real_source = $source ? {
    false => "puppet:////daemons/$name/$name.preseed",
    default => $source,
  }
  file { "/var/local/preseed/$name.preseed":
    source => $real_source,
    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

Note: Its possible that debconf-get-selections will not return the correct order in which debconf asks questions to the user. So, you should pay particular attention to the order of questions asked, and then preseed the answers accordingly.