Installing a mailserver on Debian 8/9 – Part 11: Sources, config files, colouring and comments

How to install a complete mailserver on Debian 8/9, featuring Postfix, Dovecot, MySQL, Spamassassin, ClamAV, Roundcube and Fail2ban.

~ the howto that actually works ~

Part 1: Introduction
Part 2: Preparations: Apache, Let’s Encrypt, MySQL and phpMyAdmin
Part 3: MTA: Postfix
Part 4: IMAP server: Dovecot
Part 5: Web interface: Roundcube
Part 6: Spam filtering: SpamAsasssin
Part 7: Antivirus: ClamAV and ClamSMTP
Part 8: Quota and other Roundcube settings
Part 9: Using mail with a remote IMAP client (i.e. Thunderbird)
Part 10: Counter brute-force attacks with Fail2ban
Part 11: Sources, config files, colouring and comments

On this page

Config files
Colouring Picture

All done!
All done!

I hope you’ve enjoyed my howto on installing a mailserver on Debian. If this article has been of use to you feel free to click the ads to generate a few cents of revenue or even consider a small donation using the PayPal button in the upper right corner of this page.

Please post comments or questions the comment section on this page. Note that I can’t answer every individual question and more technical questions should generally be asked in the mailing lists of the software in question.


If you’ve made it this far I salute you. To reward you for your perseverance you may print out the colouring picture below for an hour of colouring fun \o/ If you scan it and mail to dekapitein [at] this site’s domain I will post it here :)


Official documentation:
Let’s Encrypt

Inspiring sources:
EasyEngine: Sieve Mail Filtering Setup
Debian Mail Server with Postfix and Dovecot
Server world: Install Dovecot
BinaryTides: Setup a mail server with Postfix and Dovecot on Ubuntu / Debian
DigitalOcean: How To Configure a Mail Server Using Postfix, Dovecot, MySQL, and SpamAssassin
RoseHosting: How to set-up server-side email filtering with Dovecot Sieve and Roundcube on a CentOS 6 VPS Generate SSL Certificates With LetsEncrypt on Debian Linux

Config files

This file contains all settings of the files we’ve worked with in this howto. You may use it for reference in case you get stuck. It is not intended for production.

Config files

Colouring Picture

Picture courtesy of Click for a larger version!


  1. Wannabe SysAdmin

    great guide and thanks for sharing!

    The only problem I encountered was with the configuration of ‘Automatically delete spam after 30 days’.

    My logs give me ‘dovecot: auth: Error: Trying to iterate users, but userdbs don’t support it’.
    In my ‘/etc/dovecot/dovecot-sql.conf.ext’ I added ‘iterate_query = SELECT email AS user FROM addresses’ but the problem persists.

    The only thing I did different from your tutorial was the settings of ‘/etc/dovecot/conf.d/auth-sql.conf.ext’.
    I have:
    userdb {
    driver = static
    args = uid=vmail gid=vmail home=/var/vmail/%d/%n

    and I also commented out the following because it gives me an error about ‘my_db_name.users don’t exit’
    #userdb {
    # driver = sql
    # args = /etc/dovecot/dovecot-sql.conf.ext

    Of course I tried all kinds of configuration in ‘/etc/dovecot/conf.d/auth-sql.conf.ext’ but nothing seems to work.

    Any help would be grealty appreciated!
    Thanks in advance!

    = = = = = = = = =

    Some suggestions/fixes to improve your tutorial:
    – CREATE DATABASE postfix; => CREATE DATABASE postfix CHARACTER SET utf8 COLLATE utf8_general_ci;
    – BBCode typo [em]may[/em] => [i]may[/i] in /installing-a-mailserver-on-debian-8-part-2-preparations-apache-lets-encrypt-mysql-and-phpmyadmin/
    – Alias /roundcube /var/log/roundcube => Alias /roundcube /var/lib/roundcube => Alias /webmail /var/lib/roundcube (the last one is personal choice)
    – After creating the spamfilter.sieve file the user should => sievec /etc/dovecot/sieve/spamfilter.sieve (otherwise they might end up with a ‘sieve not compiled’ kind of error)

    • Kapitein Vorkbaard

      Because you are using static lookups instead of dynamics your iterate query doesn’t work. Therefor you need “driver = mysql” and not “driver = static”. Of course ONLY changing that is not enough; you need to design your database to reflect that. Check Part 4 of this series, just under “Have Dovecot look up accounts in MySQL rather than PAM”.

      The iteration (=looping through all accounts) uses sql, therefor it must be able to look everything up. Either that or you need to write a query that fakes it (e.g. “SELECT 5000 AS uid”, which always returns uid=5000).

      I struggled with this issue myself and it is really confusing and poorly documented throughout the web, *unless* you already know how it works, *then* the documentation makes sense.

      The typos I already found yesterday, coincidentally ;) But thanks anyway.

      As for the Sieve compilation: Sieve rules are compiled on the fly. You only need to precompile them if the user will never run them, which is the case for default rules. But those are deleted for that user when he/she creates his/her own rules which can be very confusing! So I chose not to use that kind of rule. Hence nothing to precompile :)

      I’ll look into the BBCode. I’m not sure how to go about that because for some reason I find it easier to set up a complete mailserver than to configure this WordPress site…

      Thanks for your suggestions!

      • Wannabe SysAdmin

        Unfortunately I can’t change my driver from [b]static[/b] to [b]mysql[/b] because then I get another error about [b]’my_db_name.users don’t exist'[/b].

        Therefore, I went with solution number 2 by just adapting my iteration but nothing seems to work.

        In my nano [b]/etc/dovecot/dovecot-sql.conf.ext[/b] I tried:
        [li]iterate_query = SELECT vmail AS uid[/li]
        [li]iterate_query = SELECT 5000 AS uid[/li]
        [li]iterate_query = SELECT … AS … FROM address[/li]
        As the (…) indicate I tried a lot of variations but nothing seems to work. What do I miss?

        • Kapitein Vorkbaard

          Like I said: you also need to change your database design. You need to have a table with users to select your users from. No table, no select. Merely saying “select from a table” without actually having that table will not work.

          • Wannabe SysAdmin

            Yeah I get that but I do have a table… I just adapted my code above to match your tutorial…
            I have a database with the following:
            [li]domains => my domains[/li]
            [li]users => mail address[/li]
            [li]aliases => aliases for forwarding[/li]
            and for creating a system user to handle the mails i did:
            ~$ groupadd -g 5000 vmail
            ~$ useradd -g vmail -u 5000 vmail -d /var/vmail -m

            To be honest is confusing but as far as I understand I should create an extra table in my db lets say vmail_user_table and select that user in my iteration_query?
            Some thing like:
            [code]iterate_query = SELECT 5000 AS uid FROM new_db_table_that_I_dont_what_to_put[/code]

  2. Wannabe SysAdmin

    Also it might be a good idea to allow users post comments with BBCode or some limited HTML so the spacing preserved. My first comment had spaces between the topics I mentioned with the intention of being easier to read but now it seems pretty messed up…

  3. Stephane

    Very good and educational tutorial! And it works right away!
    Did you try to setup a backup MX server? I would love a Part 9 : “Backup mail server”.

  4. Snapp R

    hey there,

    Thanks for the awesome tutorial.. this is really helpful~ :)

    need some help, i got problem with SpamAssassin.. already follow all the step of configurations, but SpamAssassin isn’t detecting TheGTUBE test Spam.

    checking the Source Config Files, there is spamass-milter there but not on the tutorial(Part 6), so i tried installing spamass-milter and set the config same as yours.. but still not detecting TheGTUBE test spam.

    what did i do wrong here?


      • Snapp R

        opss, sorry.. i looked at other source config when trying to fix it (did clean everything except code in this tutorial) >.\)

        i’m sure copy paste the GTUBE code correctly..
        i’m new on linux & a bit confused about reading the log.. but i think the problem is this, that “failed” word >.<)v :

        Apr 3 14:56:58 mail spamc[30521]: connect(AF_UNIX) to spamd using –socket='/var/spool/postfix/spamass/spamass.sock' failed: No such file or directory
        Apr 3 14:56:58 mail postfix/pickup[30177]: 777CC281BC9: uid=1001 from=
        Apr 3 14:56:58 mail postfix/cleanup[30519]: 777CC281BC9: message-id=
        Apr 3 14:56:58 mail postfix/qmgr[30176]: 777CC281BC9: from=, size=4828, nrcpt=1 (queue active)
        Apr 3 14:56:58 mail postfix/pipe[30520]: 994BB281BC7: to=, relay=spamassassin, delay=0.87, delays=0.86/0/0/0.01, dsn=2.0.0, status=sent (delivered via spamassassin service)
        Apr 3 14:56:58 mail postfix/qmgr[30176]: 994BB281BC7: removed

  5. Snapp R

    ok.. found out the problem, i think i got error cause of different config before i found this tutorial here.. there is this file named spamc.conf (/etc/spamassassin/spamc.conf) with some command.. did purge all of installation from previous tutorial before starting urs, but forget to delete manually created config.. >.<)v

    tried to delete it, and the spamassassin is working right away.. sorry for asking about the error caused by myself.. ur tutorial is totally GOOD!!!! THANKS!! :')

  6. Jeff

    Amazing tutorial! I haven’t finished yet, but wanted to comment. This entire tutorial is a breath of fresh air. Thanks for creating and sharing it!

  7. GREAT guide! I looked to closely to make sure I did not lose any { or } that I forgot one # and broke everything in step 4. For the life of me I couldn’t find it. I had to get my wife to check the files for me. (She is absolutely not an IT person)

    • Kapitein Vorkbaard

      Thanks :) A trick I sometimes use is to read the config backwards. That way you’re not distracted by the meaning of words.

  8. leila

    hey good tuto
    However i did not fid the postfix database?
    why wasn’t it created and what command is suppose to do so?
    Thank you

  9. Followed the entire manual using MariaDB from start and altered the user database using an extra field to set user_quota settings per user.
    Works like a charm!

    Next step: Upgrade the entire environment to Debian 9. Curious if it will keep running ;-)

      • A year ago I would have pointed my finger to my forehead (ben niet gek!) if I told myself (as a Windows guy) I would migrate all Windows 2012R2 servers on my homeserver to Linux…
        This is the last one step hehe!

        • Kapitein Vorkbaard

          Heh :P I used to run hMailserver years ago. It’s ok but the things a Linux server allows you to do..! Documentation is the key :)

          • Well, upgraded it to Debian 9, needed to uninstall php7 and reinstall to get Roundcube and PHPMyadmin running again.
            Needed to alter the postfix config to delete the entry !SSLv2 as it is obsolete. (did an update leaving all configs untouched)
            I can mail again, but I think Spamassasin is not working as the GTUBE fails. Along with the other services a nice task for next Monday. I have the feeling it will work again next week :D

        • Kapitein Vorkbaard

          I need to figure out the WordPress reactions part some day. This is a reaction to your next reaction.

          I’ll be looking into Debian 9 and whatever Ubuntu version is current soon and document accordingly. It’s a dirty job but someone’s gotta do it :P

  10. Erik

    Well, in reaction to that, cause I wish to see where it goes

    I’m going to copy all these pages into one giant PDF and add my own changes, so when the site goes down… I happen to have a backup ;-)

  11. C. Hvilsted

    Great tutorial. You have really invested a lot of time in this. Thank you so much.

    I does not appear to me that Covedot supports UT8 chars? With the Danish layout I get errors if I don’t set smtputf8_enable = no in /etc/postfix/

    If I set smtputf8_enable = no the mail vil get delivered – but the Danish chars in the mail will be gibberish.

    • Kapitein Vorkbaard

      I think you should look at supported charsets on your OS itself. I’m not sure Dovecot really cares. Anyway, I’m not an expert but I can use diacritic characters without a problem. Using Dutch, so some diacritic chars. Anyway I never looked at that in much detail, sorry. It always just worked :P

  12. Hello,
    After a lot of troubleshooting I fixed most of my erros but unfortunately I can’t solve this one.
    When i’m trying to send e-mails i receive the following error message: ‘SMTP-fout (250): Authenticatie mislukt./SMTP-error (250): Authentication failure.’

    Can you please help me in this case?

    Thanks in advance!

  13. Dario

    Hi, very great tutorial!
    Unfortunately i’m stuck on a boring problem.
    I’ve followed each part of the tutorial, but in the end i got a Password mismatch from dovecot.
    Can you please help me to deal with it?
    Thank you in advance for your effort!

  14. Patrik Lantz


    This is one of the best tutorials I’ve found on the net.
    Great work on this.

    I do have some quick questions you might could answer or point me in the right direction.

    * How do I add virtual-users / mailbox without using phpmyadmin.
    – Could I use Webmin, ISP-Config or is there something similar ?

    I’m trying to setup a server LAMP + Mailserver and it would be great if I could you your setup + one of the above Panels to have better control.


    • Kapitein Vorkbaard

      Hi Patrik, there’s a command-line version on the same page as the PhpMyAdmin stuff, but I think you’re not looking for that. You could write a short Bash script to add virtual users and use Webmin’s command option to run it. I’m not very familiar with ISP-Config but I suggest you Google for something like ‘run custom script from ISP-Config’.

      If you find anything please let me know and I’ll happily add it to the tutorial :)

  15. Patrik Lantz

    Thanks, will look into “Run custom script”
    But I hoped that Webmin or ISP-Config automaticly could config it self…

    I wonder if you have any good pointers to solve the, not able to send to

  16. Marouan

    I am sorry i did send a previous message but it didn’t work ?!
    I followed your tutorial wich is great by the way i just have a problem.

    postfix/postdrop[18913]: warning: mail_queue_enter: create file maildrop/924506.18913: Permission denied

    and i can send mails from the command as root but from wordpress for example i get this error.

  17. Marouan

    Hi Vorkbaard and thanks for your reply i changed the files permissions and user to postfix postdrop but the problem remains i will uninstall everything and start from scratch and see if the problem goes away.

  18. Jalisco Autuick

    Absolutely great tutorial. Almost everything worked immediately, first try.

    I had difficulty with the spamassassin setup, but otherwise, got it to work.

    Now, I need to find some way to “manage” the users, because simply adding users doesn’t seem to be simple. I didn’t use the phpmyadmin, because it didn’t work on initial install, and just went with the SQL command line instead, thanks for that btw. Very nice.

    Maybe I will need to re-install phpmyadmin. I don’t know, but gotta figure out how to add users seemlessly. I won’t add tons, but should be easy step.

    Also, suggestion: perhaps how to setup disposable email addresses? =) that would be nice.

  19. Wannabe SysAdmin

    long time no see! To be honest I am glad that I haven’t been in your site for about 3 years! This mean that your tutorial is great and everything works as expected! Thanks for the Debian 9 update as well! I updated my machine and to my surprise nothing got broken!

    However, I do have a problem but of a different nature. I am trying to add a domain to my mailserver that I do not directly host in my VPS. I’ve changed the domain’s mx record to match the one in my main mailserver domain but still does not work. I can send emails via Roundcube but I can’t receive. My mail logs registers nothing about this suggesting that it might be something with the mx? As mx records for my friends domain in his DNS manager I used: but nothing seems to work! I wait for several hours in both cases because it might needed time for propagation but I still can’t send emails.

    Any help, ideas, pointing to the right direction would be greatly appreciated!

    Thanks in advance,
    Wannabe SysAdmin

  20. Jalisco Autuick

    Hi Kapitein,

    I get the following “funny” error.

    Mar 18 19:41:11 mail dovecot: imap( Error: stat(/var/mail/vmail/ failed: Not a directory

    The server has been setup now for a couple of months, and works without any significant issue. I am just going through and clearing any little error, and was trying to figure this one out.

    I double checked that I set up everything per your recommendations. And, yes, in the spam assassin setup part:

    In /etc/dovecot/conf.d/90-sieve.conf:

    //We are instructed to setup the following

    plugin {
    sieve = ~/.dovecot.sieve
    sieve_dir = ~/sieve

    This is one of the rare areas in the entire guide that doesn’t have an explanation as to what is happening.

    Again, everything seems to work, just curious about the error message?

    • Kapitein Vorkbaard

      Hi Jalisco. I ran into the same error a long while back and did not document it here, for which I apologize. It has to do with the automatic import of sieve rules and their pre-compilation, if I remember correctly. Or it is something else completely. I know I figured it out at one point. If you do please let me know :D

      • Jalisco Autuick

        I tried to recompile sieve with the following command, and it seems to fix the error. I will watch it, and report if this was not the case. Here is the command, in case anyone sees the error message.
        sievec /var/lib/dovecot/sieve/default.sieve

        • Jalisco Autuick

          Unfortunately, this didn’t solve the problem. I went through and ensured my configuration files matched the configuration files listed above. That was a mistake. Lesson learned, kind of threw my system a little of out whack. Working again, and the above error is gone. I think just a few minor things were specific to my configuration, that I carefully setup. But, foolishly just went in and replaced variables wasn’t a good idea. Oh well, working again, the above issue is not there anymore.

          • Jalisco Autuick

            In the end, the above error, for me also some how disappeared through other cleanup. I can’t give exact reason why.

            But, kind of related, I was getting an error message similar to the one listed below (found on the postfix mailinglist (

            Dec 9 00:09:59 mailhost dovecot: lda([hidden email]): Error: sieve: binary save: failed to create temporary file: open(/usr/local/etc/dovecot/sieve/ failed: Permission denied (euid=5000(vmail) egid=5000(vmail) missing +w perm: /usr/local/etc/dovecot/sieve, we’re not in group 6(mail), dir owned by 143:6 mode=0775)

            Dec 9 00:09:59 mailhost dovecot: lda([hidden email]): Error: sieve: The LDA Sieve plugin does not have permission to save global Sieve script binaries; global Sieve scripts like `/usr/local/etc/dovecot/sieve/10-move-spam.sieve’ need to be pre-compiled using the sievec tool

            The solution there was:
            1. rm /etc/dovecot/sieve/spamassassin.svbin
            2. sievec -D spamassassin.sieve

            fixed the error message.

  21. Jalisco Autuick

    In case anyone is interested in adding SPF, DKIM, and DMarc to the instructions given on this great tutorial, here is another tutorial which fills in the gaps.

    it more or less worked flawlessly “without issue.”

    For me, took me a while a week or two of pulling out my hair, because I had forgotten that I had installed pi-hole at some point, and it was messing up my dns lookups–mainly that I had upgraded at some point, and didn’t reconfigure, so dns lookups were spotty.

    Once I figured that out, it was smooth sailing.

    • Rof S

      hi jalisco, i’ve been following that tutorial to Configure DKIM.. i’ve got no issue in test configuration.

      but after “Hook OpenDKIM into Postfix” config and restarting postfix.. it not sending the email.
      the email’s sent after i disabled no.3 config and restarting postfix again…

      did u have the same problem?
      why it is not working for me?

    • Rof S

      ok nvm,
      i managed to fix the problem..

      one thing that’s not in the tutorial is to move “example.private” file to “/etc/opendkim/keys”

      after move the file and make sure the permission on /etc/opendkim/keys are correct, i can send the email and got DKIM result “pass” ~

  22. First lets start with this is an absolutely amazing tutorial. Even looking over your config files to make minor adjustments is awesome. Just can’t say enough good things about your tutorial.

    New issue though, MariaDB updated to the 10.38 version and now I am getting mail failures through the SQL system both for aliases and users. I am at a loss because I do not know SQL at all. Here is the blurb it kicks back at me.

    A problem was found with your Postfix alias maps : The map source mysql:/etc/postfix/ cannot be used : Failed to query table : You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ‘from where = limit 1’ at line 1

    Maybe you know enough SQL to help me with this.
    Much thanks in advance.

  23. Wannabe SysAdmin

    Hi! Thanks for the great tutorial! I’ve been running 2 mail servers for several years with no problem.

    However, a new challenge appeared and I would like some help.

    I have two VPS. One with the website files and one as a dedicated mailserver. Both work perfectly. Now, in the latter (i.e. the mailserver) I would like to add Roundcube but I am not sure what to do with the /roundcube /var/lib/roundcube alias or should I install Roundcube in the main VPS (the one with the websites)?

    Thanks in advance for any help!

    • Wannabe SysAdmin

      I did figured that by myself. Installing Roundcube in other VPS with a valid domain and https should do the trick and act as an e-mail hub.

  24. Szabolcs Glazer

    This is a very helpful and grate tutorial. Every function is gone great. I would some help. I’ve need so dovecot/roundcoube plugin and function wich I can maanage users. Example User goups, roles and I would like to set password for other users.

    Thanks for help!

  25. Wannabe SysAdmin

    Hi! Guys when I try to install roundcube I get ‘ERROR 1045 (28000): Access denied for user ‘root’@’localhost’ (using password: NO)’.
    – I do have a password for mysql root.
    – I entered my password during the installation every time.
    – I reset the root password to be sure (and flush privileges etc).
    – I did try to configure the database manually but no luck.

    I am stuck. Any help would be appreciated! Thanks in advance!

  26. Great tutorial! Loved it, was clear as crystal! However, it is a bit outdated I must say in in need of a review. While I managed to setup all of this in a few days, some of the stuff, like spam assassin and clamav had to be reconfigured as they were broken on install – beware. :)

  27. Jalisco Autuick

    I am back here again, after many years, also looking for an update. My old Debian 8 at some point upgrade to 9, email server worked great for years setting it up through this tutorial. But, alas, Debian upgrades to 10 and 11, have not been as easy. i.e. they break my email server =( So, am gonna try to re-engineer this setup on a clean 11 setup.

  28. Gonna do a clean install of Debian 11 this weekend, and gonna use this guide as a base =) it worked in the past, so it likely will still be golden from a methodological aspect, so the end project should work. Will report back if that is the case, and any funky things that appear.

  29. Alex

    Something is wrong with the “next” links at the bottom of pages — for the part 4 clicking “next” brings you to the part 7, then to the part 9.

Comments are closed.

Back to Top