It is the 25th of February 2020

How to setup a Debian Wheezy mail and DNS server using SaltStack.

In this tutorial I will show you how to setup a Debian Wheezy (7.0) server using SaltStack.
The final configuration will include:

  • Some basic configuration like users, ssh, bash aliases, admin & security software
  • Exim4 mail transfer agent
  • Dovecot IMAP
  • Bind9 DNS Server

I have collected information for my setup from several sites and will try to credit them all. If you feel missed out simply drop a note.


I was looking for a consistent and easy way to manage my server without having to repeat countless of menial tasks every time I move it to another host. So I dug a little into configuration management and provisioning. I first tried puppet which was allright but I found to like Salt better. It just feels more lightweight and allowed me to write down some messy state files that will allow me to keep my server in a defined and version controlled state without much hassle.
I am pretty new to Salt so the presented state files won't win you any beauty contest. But setting up a single server to me really is a menial task. I don't want to make a science out of it considering to run 100s of minions, I just needed a provisioning tool that would help me to achieve exactly what I wanted without having to learn too much about the tool itself and in time I started to enjoy it though.
I like Salt for several reasons. It is python, which is good. I uses yaml which is good. It uses jinja which is good. So if you are somewhat used to these technologies salt is super simple to start with and allowed me to solve everything I needed in a way that occured very natural me. It is also kinda appealing to be a master of minions, speaking of computers only of course.

Starting at the top

First I create a new folder for my project called *master" and write down my super simple top.sls file for my single server in the default salt states folder.

$ mkdir -p master.<yourdomain.tld>/salt
$ cd !$
$ cat > top.sls << EOF
> base:
>   '*':
>     - common
>     - ssh
>     - mail
>     - dns

Development environment (optional)

Since I didn't want to try out my setup on a live system I decided to go with vagrant and setup a simple development environment. This is completely optional of course.

I fire up the box using the following Vagrantfile, downloading a prepackaged Debian Wheezy box, in my project directory, so:

Based on mozilla/playdoh Vagrantfile

$ cd ..
$ cat Vagrantfile
require "yaml"

# Load up our vagrant config files -- vagrantconfig.yaml first
_config = YAML.load(,
                    "vagrantconfig.yaml"), File::RDONLY).read)

# Local-specific/not-git-managed config -- vagrantconfig_local.yaml
                   "vagrantconfig_local.yaml"), File::RDONLY).read))
rescue Errno::ENOENT # No vagrantconfig_local.yaml found -- that's OK; just
                     # use the defaults.

CONF = _config
MOUNT_POINT = '/home/vagrant/project' do |config| = "wheezy64"
    config.vm.box_url = ""

    config.vm.forward_port 8000, 8000

    # Increase vagrant's patience during hang-y CentOS bootup
    # see:
    config.ssh.max_tries = 150
    config.ssh.timeout   = 600

    # nfs needs to be explicitly enabled to run.
    if CONF['nfs'] == false or RUBY_PLATFORM =~ /mswin(32|64)/
        config.vm.share_folder("vagrant-root", MOUNT_POINT, "./srv")
        config.vm.share_folder("vagrant-root", MOUNT_POINT, "./srv", :nfs => true)

    # Add to /etc/hosts: :hostonly, ""

#    config.vm.provision :puppet do |puppet|
#        puppet.manifests_path = "puppet/manifests"
#        puppet.manifest_file  = "vagrant.pp"
#    end
$ cat vagrantconfig.yaml
nfs: false

Now is a good time to initialize the git repository:

$ git init
$ git add .
$ git commit -a -m "initial Vagrantfile and top state"

Finally it is time to start the dev machine.

$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...

In the next chapter I will write the common state file as referenced in top.sls

Featured Apps