It is the 29th of March 2020

How to setup a Debian Wheezy Mail and DNS server using SaltStack - Deployment

In the last chapter I finalized the SaltStack configuration for my server. The current directory structure is as follows. Please Note Just use your preferred configuration for the missing files or adapt the state files correspondingly if you want to use a more tidy folder structure for example.

  • /path/to/
    • ./pillar/top.sls
    • ./pillar/common/init.sls
    • ./pillar/dns/init.sls
    • ./pillar/ssh/init.sls
    • ./pillar/mail/init.sls
    • ./salt/common
      • ./init.sls
      • ./bash.bashrc
      • ./bash_aliases
      • ./iptables.rules
      • ./vagrant_iptables.rules
    • ./salt/dns
      • ./init.sls
      • ./named_conf.tmpl
      • ./reverse_zone.tmpl
      • ./zone.tmpl
      • ./default/bind9
      • ./chroot/bind/etc/bind/named.conf
      • ./chroot/bind/etc/bind/named.conf.options
    • ./salt/mail
      • ./init.sls
      • ./.forward
      • ./mailname
      • ./spamassassin
      • ./dovecot/conf.d/10-mail.conf
      • ./exim4
        • ./update-exim4.conf.conf
        • ./virtual/
        • ./conf.d
          • ./acl/40_exim4-config_check_data-deny-virus.patch
          • ./main/01_exim4-config_listmacrosdefs
          • ./main/03_exim4-config_tlsoptions
          • ./router/350_exim4-config_vdom_aliases
    • ./salt/ssh
      • ./init.sls
      • ./sshd_config
      • ./ssh_config
      • ./vagrant_sshd_config
      • ./motd
      • ./
    • ./salt/top.sls
    • ./Vagrantfile (optional)
    • ./vagrantconfig.yaml (optional)


At this point I would have made sure that everything works as expected using my vagrant box. Since the steps to deploy on the live system and the vagrant box are almost identical I will write it only once for the live system. The only real difference is that you can mount or symlink your salt project directly to /srv on the vagrant box so you have no need to communicate via git. All you have to do is change whatever state file you want on your host OS in your favorite editor and run salt highstate as shown below. Since this tutorial deals with a single server I will setup salt master and minion.

Preparing the target

Update the system, install salt, deploy your configuration repository and bring the master/minion to highstate

# apt-get update && sudo apt-get upgrade
# wget --no-check-certificate -O - | sudo sh    
# apt-get install -y curl && curl -L | sudo sh -s -- -M -N

Make sure you point the salt host to localhost, i.e. the salt master. Simply add the corresponding host.

/etc/hosts:      salt

Start salt now:

# service salt-master restart
# service salt-minion restart

If you experience problems because salt is already running just kill it first, because installation starts salt without using the init.d service.

Time to check if communication is up:

# salt-key -L
Accepted Keys:
Unaccepted Keys:
Rejected Keys:

You should see an unaccepted key for your host, which means the minion is communicating with the master but has not been approved. So:

# salt-key -A

Accept the key.

Finally deploy your configuration git repository. You might want to use some build mechanism to automate things here or hook in wild remote fetches in your git config. To keep it simple and since it completely satisfies my needs I do it by hand.
First I clone and copy my project repository from my local computer to the server and add it as the remote origin.

Local machine

$ pwd
$ git clone --bare . /tmp/
$ rsync -avz --progress /tmp/ root@<ssh_host>:/path/to/repos
$ rm -rf /tmp/
$ git add remote origin <ssh_host>:/path/to/repos/
$ git push --set-upstream origin master

Remote server

# apt-get install git
# git clone /path/to/repos/ /srv

By now your /srv directory should be that of your project directory containing the directory structure outlined at the beginning of this post. Your entire /srv directory is now under version control so you might want to use a different approach.

And that's it

Running the configuration

Having prepared everything it is time to bring the minion to highstate, but lets test first:

# salt '*' state.highstate test=True

If everything looks good ommit the test clause and run

# salt '*' state.highstate

If all went well you should see no error and your minion should now be in the defined state. Check your configuration, especially ssh, and then do a reboot to ensure everything works as expected after reboot, which is a main reason for all this effort.

# netstat -tulpen
# ps -ef
# reboot

What's next?

From now on you can simply modify your version controlled Salt configuration for whatever reason you have and push it to the master. Write state files for OpenVPN & Co...


$ vim ./salt/mail/init.sls
... change some configuration
$ git commit -a -m "changed mail config"
$ git push


# cd /srv
# git pull
# salt '*' state.highstate

The End

I hope you found something useful in this tutorial! To me it was a pleasant enough experience to work with this kind of setup.

Featured Apps