Creating your own Mail Server (Amazon ec2, Postfix, Dovecot, Postgresql, Amavis, Spamassassin, Apache, and Squirrelmail) PART 1

Preface

Have you ever wanted to host your own mail server? Have you ever tried to do so and realized that there are a lot of messy moving parts that are difficult to configure? Maybe you’ve scoured the internet for a comprehensive guide that gets you right from point A to point B only to realize everything you find is a little bit wrong or differs slightly from your desired configuration- enough to ruin the entire setup. If that sounds like you, then I can relate to your struggles. My goal is to provide you with an easy guide to get your own mail server up and running in less than an hour. Yes, in less than an hour- because who wants to spend more than an hour being frustrated and confused? A normal human being doesn’t, so I’ll cater my sentiments to the perspective of a normal human being. If you are new to all of this and thinking, “I really just don’t know where to begin!”, then please look no further, you will be happy with what you find here. If you are a veteran of configuring mail servers, then I should still be able to help you get a good jump start with Amazon EC2. You will of course need to eventually understand how everything fits together, especially if you want to make further adjustments to your server later in time, but it’s nice to have something that works first, so you can have a V 1.0 to fall back on.

Important notes about the setup I’ll be providing you;

The system uses:

-Postfix as the smtp agent

-Dovecot as the client-side connect and mailbox manager

-Postgresql database to handle mail users, mail transports and the Spamassassin database

-Amavis (w/ Clamav & Spamassassin) for protection against viruses sent through email, and to facilitate an adaptive spam detection system that learns and corrects its behavior for each individual user

-Spamassassin as the spam filter and bayes to learn spam from ham and ham from spam

-Apache as the web setup, enables http & https connections to your site

-Squirrelmail as the default webmail. After the server is setup you will be able to check your email on yourdomain.com/mail from any browser on any device

The system supports:

-Multiple transports for different domain

Enough blabbering on my part… let’s get to the actual setup. I’m going to write this guide for a beginner so I apologize if my explanations are too lengthy/ specific for your tastes. Feel free to skip over parts you deem irrelevant to you.

Step 1: Getting your own FQDN (Fully Qualified Domain Name)

Unfortunately it is literally impossible to receive mail with your own server if you do not have control over a domain name. Luckily however, it is not hard to get one without emptying your pockets. Since we’ll be using Amazon Web Services (AWS) for just about everything server related, let’s get our domain from them too (Click me). You will need to go through the process of signing up for an AWS account. Even if you already have a domain you will need to do this. It is important to note that they require credit card information and a valid email address. Upon signing up they will bill your credit card $1.00- But the charge will fall off in a matter of days! They do that just to make sure your credit card is actually billable.  Once you have a valid AWS account you’re ready to get started. Log into your developer console and go to Route 53.

route53

Then click on Registered Domains.

Registered Domains

Finally click on Register Domain, and go through the process of grabbing a name that points to you on the internet! You can type in various names and change the site extension as you check which names are available. Note that the site extensions vary greatly in price, so if cost is a concern, it may be best to stick with a .com. Once you have selected your name, give Amazon your contact information. After you have done that and paid for your shiny new domain name, that’s it! Now it’s time to start a server for your domain to point to.

Step 2: Getting your server up and running

Open a new tab back to the AWS Management console, and go to EC2.

EC2-icon

 

Once in that menu, go to Instances and then Launch Instance. When asked to choose an AMI, choose “Amazon Linux”. This part is imperative. If you choose a different AMI, this guide won’t be able to help you.

 

Amazon Linux AMI

 

When it comes to choosing an instance type I recommend going with t2.micro at least to start with. It will likely not cost you more than a dollar a month for the first year of operation if you just signed up for your AWS account. So again if money is something you’re watching right now, go with the micro. It has enough power to run a mail server efficiently. If you want to run a website on top of that, you may require a t2.small but you can easily switch later so I still recommend grabbing a micro before you know how much power your need. If you opt to grab a bigger machine be wary, you will not be covered by the free tier and costs will begin to accumulate. (If you are curious about Amazon Instance pricing -> Click Me ) From personal experience running a t2.small will cost around $200 per year if it’s running every hour of every day.

Unless you know what you are doing it would probably be best to skip configuring the instance and adding storage. When it gives you a chance to tag the instance, you can name it by typing something in the box next to “Name”.

For security groups I would add a new one, and add the following rules: SSH, HTTP, HTTPS, SMTP, SMTPS, IMAP, IMAPS, PostgreSQL, Custom TCP Rule (Port: 587). For each of those rules the set the Source to “Anywhere”. Next, review and launch the instance!

When launching, Amazon will ask you to create or use an existing key pair. If you’re creating one for the first time, give it a suitable name and download the file.

Next, open a terminal window (ctrl+alt+T) (ctrl+meta+T)

mv /path/to/downloaded/key ~/.ssh/name_of_key

Then open up the file located at ~/.ssh/config and add the following entry:


Host nameOfServer (Arbitrary)
   User ec2-user
   HostName serverName (example.com)
   IdentityFile /Path/To/Keyfile

After the next step, you should be able to ssh into your new server by just typing in the terminal;

ssh nameOfServer

You can always start, stop, reboot, terminate, and generate new instances from the amazon console, so don’t worry if you didn’t get something quite right. There will be plenty of chances to fix the settings or launch a new server. As long as you’re smart about how many instances you have running at once you probably won’t incur any charges. When I was experimenting with AWS I launched and terminated at least 30 instances before getting it right, and they didn’t charge me a penny.

Once you have at least one instance running you can begin step 3.

Step 3: Configuring your domain to have an IP address and relevant records

Okay, so now your very own domain, server, and a way to log in. The next step is to connect all of these pieces and have them work in tandem! The first thing to do is go back into Amazon’s EC2 menu, and select the Elastic IPs tab. Once everything loads you will see a button Allocate New Address, go ahead and grab a new IP. Once you have it, select the IP and go to the Actions menu and select Associate Address. Click on the Instance window and select the Amazon EC2 instance you would like to use as your server. Note that you can re-associate the elastic IP if you need to switch to a new or different server in the future, it’s easy and free (for the first 100 switches each month). Awesome! You’ve just put a big name tag on your server for the whole internet to see, now we need to make it one that humans will like using.

Copy the Elastic IP address one way or another (write it down, highlight and copy… whatever you’d like). After doing that return to Route 53 on the Amazon Console. Once there, select Hosted Zones. Amazon most likely created a hosted zone for your domain when you bought it from them, but if they didn’t, go ahead and create a new one.

You will need to create 4 new records for your domain:

1. no name; A – IPv4; Alias NO; TTL 60 secs; Value PASTE ELASTIC IP HERE

2. no name; MX – Mail Exchange; Alias NO; TTL 60 secs; Value 10 mail.yourdomain.com

3. name *; A – IPv4; Alias NO; TTL 60 secs; Value PASTE ELASTIC IP HERE 

4. name mail; A -IPv4; Alias NO; TTL 60 secs; Value PASTE ELASTIC IP HERE

After these records have been set, your domain name should point to the elastic IP address, which in turn points to your Amazon EC2 server. This makes switching servers easy- all you have to do is re-associate the elastic IP and within a minute your domain should be pointing to your selected server.

You’ve done it! You have your very own domain, and a server that it points to. Try to ssh into your server and make sure you can connect. As long as you can, you’re ready to build your mail server!

Continue to PART 2 >>

12 thoughts on “Creating your own Mail Server (Amazon ec2, Postfix, Dovecot, Postgresql, Amavis, Spamassassin, Apache, and Squirrelmail) PART 1

  1. httpd wont start after installing this, seeing error
    Starting httpd: AH00526: Syntax error on line 1 of /etc/httpd/conf.d/ssl.conf:

    Also its changed httpd.conf to change doc root to /var/www/vhosts/mydomain/httpdocs from /var/www/http/
    My cron job stopped working. complete disaster 🙁

  2. Hi Avix,

    Thanks for your post.

    I created a similar setup as you have described and my postfix SMTP is working fine. I am able to send emails everywhere, just not to the customer domain which has a trust relationship with my AWS domain directory service.

    The only issue is that when postfix try to relay to my customer domain, it resolves it as the local IP of customer’s domain controllers, instead of the public IP of the domain and all emails to the users in customer domain are ending with below error:

    Dec 16 15:30:21 mail amavis[3126]: (03126-06) Passed CLEAN {RelayedOpenRelay}, -> , Message-ID: , mail_id: RsCOtq7FVxxs, Hits: 0.962, size: 477, queued_as: A1FAF62F98, 11254 ms
    Dec 16 15:30:21 mail postfix/smtp[5477]: 617E462FB1: to=, relay=127.0.0.1[127.0.0.1]:10024, delay=11, delays=0.04/0/0/11, dsn=2.0.0, status=sent (250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as A1FAF62F98)
    Dec 16 15:30:21 mail postfix/qmgr[5464]: 617E462FB1: removed
    Dec 16 15:30:21 mail postfix/smtp[5488]: connect to customerdomain.com[10.16.162.36]:25: Connection refused
    Dec 16 15:30:21 mail postfix/smtp[5488]: connect to customerdomain.com[10.16.162.41]:25: Connection refused
    Dec 16 15:30:21 mail postfix/smtp[5488]: A1FAF62F98: to=, relay=none, delay=0.04, delays=0.01/0.01/0.02/0, dsn=4.4.1, status=deferred (connect to customerdomain.com[10.16.162.41]:25: Connection refused)

    I will really appreciate if you could help me out with this.

    thanks,
    Jit

    • Hello Vicky,

      I’m glad the mail server installed successfully! When you specify your domain name in super.sh, if you enter “example.com” and not “mail.example.com”, your default email account will be admin@example.com and future email accounts will be something@example.com.

      To ensure this change happens properly you can either start a new instance and rerun the script or edit the file located at “/etc/postfix/main.cf”.

      The setting “mydomain” should be “example.com”.
      The setting “myhostname” should be “mail.example.com”

      If you had to change those settings, run “sudo service postfix restart” and if that doesn’t work correctly, please try restarting your instance with “sudo reboot”. If you are still experiencing this issue upon reboot, I strongly recommend starting a new instance and ensuring that super.sh is filled out to your liking before running the script.

      Let me know if you have further questions!

      Avix

  3. Regarding: https://avix.co/blog/creating-your-own-mail-server-amazon-ec2-postfix-dovecot-postgresql-amavis-spamassassin-apache-and-squirrelmail-part-1/

    Does not work right now as I”m getting clashing dependencies and other problems. Determined that some of the URLs in your document no longer work.

    For my reference I’ve forked your code to make some small changes before I hit the big problems. I’m going to give finding the right packages a try then run your script again (thank goodness for snapshots).

    If you can fix it soon, GREAT! If not, any hints to help in my struggle?

    Bitfully yours,
    Gιlβεrτ Hεαlτοπ

    • Hello Gilbert,

      I’m sorry to hear that the URLs don’t work, I’ll look into that. Yes please feel free to fork my code and fix the problems, as your solutions may help future users. It should be noted that this script is intended for new instances of EC2, so be warned of the risks, as it is likely to override potentially critical sections of code for a user who has already configured their instance. But yes, always use snapshots!!

      There was a suggestion made by Alex in this comment section about how to correctly install Amavis now, I would give that a try. Beyond that I’m not sure at the moment. The issue with setting up security features is that they are always changing. This script is a bit old now and thus certain parts are likely broken because software packages have been updated since.

      I hope you are able to fix the issues!

      -Avix

    • Hello Gilbert,

      I know that you commented this over a month ago, but I wanted to let you know that recent revisions to the script should fix any issues that you were having. I do recommend running it on a new instance instead of an already established one, as otherwise I have no idea what kinds of dependency clashes could occur.

      Let me know if you are still having issues.

      Avix

  4. The script gets stuck at:
    Hit http://security.ubuntu.com trusty-security/main Sources
    Hit http://security.ubuntu.com trusty-security/universe Sources
    Hit http://security.ubuntu.com trusty-security/main amd64 Packages
    Hit http://security.ubuntu.com trusty-security/universe amd64 Packages
    Hit http://security.ubuntu.com trusty-security/main Translation-en
    Hit http://security.ubuntu.com trusty-security/universe Translation-en
    Reading package lists… Done

    it doesnt move past this point?

Leave a Comment