How to Set Up your Own Personal Email Server.


Written by:

Robert McIntyre

Initially, this is going to be a guide for myself and my hacker friends to set up their own private email accounts. Eventually as I get comments and learn the sticking points for others to use these instructions, I will create a new set of instructions and a friendly youtube video to show anyone how to set up their own mail server.

I will recommend various services in this article, because they are services that I use personally. You can of course substitute these for whatever you want.

1 Get a Domain Name

You can buy a domain name from A domain name is like your personal name/the name of your house on the internet. My main domain name is "", because it means "little gold", and because it sounds like my initials, RLM. The steps to getting a domain name for yourself are as follows:

1.) Decide on a domain name. This is an important name that you might be using for a long time, so choose wisely. Be prepared to try multiple variations on your domain name as many domain names are already taken.

2.) Go to and register the domain name. The cost is about $12 per year for a domain name.

2 Get a Virtual Private Server

I recommend Linode, since you can load the server you get with my favorite operating system, Arch GNU/Linux, and because I have experienced stellar service from them for about a year so far.

Steps towards getting a Virtual Private Server:

1.) Go to and buy a Virtual Private Server of your very own.

  • Select the Operating System as "Arch Linux", and set the physical location to the nearest location to you. You will then decide how to partition your server; the defaults that Linode offers are fine. Finally, you will have to set the root password which is how you will access the server from your computer. Be sure to choose a secure password or your server can be easily compromised.

3 Link your domain name with your new server.

This is a two step process – you have to set your domain to point to the nameservers at, and you have to tell to point requests to your new virtual private server that you just bought.

1.) Go to again, select your domain, go to "Domain Name Server Setup", select "Specify Custom DNS Servers" and enter:


    as the 5 DNS servers.

2.) Go back to and go to the "DNS Manager". Select "Add a domain zone" and enter your domain name. Select the defaults to get yourself started.

It may take up to a day for the DNS system to sort itself out and for the entire world to recognize that your new domain name points to your new virtual private server.

After that, you will be able to ssh into your new server using your new domain name. Once you are able to do this, you know that you have properly set up your domain name and new server.

4 Configure MX records for your machine.

I like to use these settings for aesthetic reasons (I don't like to have a separate "mail.domain-name" server.)

1.) Go to and select DNS Manager.

2.) Select your domain name and modify the MX record so that it has a single entry:

Mail Server: <your-domain>
Priority: 10

With the other fields left blank.

3.) Delete the mail.<your-domain> A Record.

5 Set up your new sever.

Login to your shiny new server by using:

ssh root@<your-domain>

You should fully upgrade your system by performing:

pacman -Syyu

Now, you will want to create a new user for your machine.

useradd -m --groups wheel <your-username>

Finally, log off and log back on again as your new user.

ssh <your-username>@<your-domain>

6 Install postfix, a powerful mail server.

You can read for more information.

On your server, install postfix using pacman.

sudo pacman -S postfix

7 Configure /etc/postfic/

Now, you will have to edit the /etc/postfix/ file:

Set myhostname and mydomain to the same value, <your-domain-name>.

# The myhostname parameter specifies the internet hostname of this
# mail system. The default is to use the fully-qualified domain name
# from gethostname(). $myhostname is used as a default value for many
# other configuration parameters.
myhostname = <your-domain-name>

# The mydomain parameter specifies the local internet domain name.
# The default is to use $myhostname minus the first component.
# $mydomain is used as a default value for many other configuration
# parameters.
mydomain = <your-domain-name>

You should also set the mydestination variable to localhost, since this is the most secure option for our setup.

# Specify a list of host or domain names, /file/name or type:table
# patterns, separated by commas and/or whitespace. A /file/name
# pattern is replaced by its contents; a type:table is matched when
# a name matches a lookup key (the right-hand side is ignored).
# Continue long lines by starting the next line with whitespace.
mydestination = localhost

Be sure to set home_mailbox to "Maildir/", since this is the most reliable way of storing your mail on the server.

# The home_mailbox parameter specifies the optional pathname of a
# mailbox file relative to a user's home directory. The default
# mailbox file is /var/spool/mail/user or /var/mail/user.  Specify
# "Maildir/" for qmail-style delivery (the / is required).
#home_mailbox = Mailbox
home_mailbox = Maildir/

Add the following to the end of your file, adjusted to your setup:

# Configure Virtual Mail Addresses

virtual_mailbox_domains = <your-domain-names>
virtual_mailbox_base = /mail
virtual_mailbox_maps = hash:/etc/postfix/vmailbox
virtual_minimum_uid = 50
virtual_uid_maps = static:73
virtual_gid_maps = static:73
virtual_alias_maps = hash:/etc/postfix/virtual
mailbox_size_limit = 0
virtual_mailbox_limit = 0

This tells postfix to use the file /etc/postfix/vmailbox to determine what addresses you wish to support, and where to put the mail on your server. Our next step will be to configure the file /etc/postfix/vmailbox. You can put multiple domains in the virtual_mailbox_domains, separated by spaces.

Here's my section of

virtual_mailbox_domains = 
virtual_mailbox_base = /mail
virtual_mailbox_maps = hash:/etc/postfix/vmailbox
virtual_minimum_uid = 50
virtual_uid_maps = static:73
virtual_gid_maps = static:73
virtual_alias_maps = hash:/etc/postfix/virtual
mailbox_size_limit = 0
virtual_mailbox_limit = 0

This configures my server to receive email for four domains:,, and

Finally, you should add the following to the end of your file to set up the security for all of your email accounts.

smtpd_sasl_auth_enable = yes
smtpd_sasl_local_domain = $myhostname
broken_sasl_auth_clients = no
smtpd_sasl_security_options = noanonymous
smtpd_recipient_restrictions =  permit_sasl_authenticated, permit_mynetworks, check_relay_domains
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_tls_auth_only = yes
smtpd_tls_cert_file = /etc/ssl/certs/server.crt
smtpd_tls_key_file = /etc/ssl/private/server.key

smtpd_tls_loglevel = 1

8 Configure /etc/postfix/vmailbox

This is the file that configures your virtual email addresses, which are all of the addresses to which people can send you email. This file tells postfix what email addresses you wish to use, and where the emails should be placed on the server.

# <your-domain>

<your-email-user>@<your-domain> <your-domain>/<your-email-user>
@<your-domain>                      <your-domain>/anyone/

This setup will give you a single user account at your domain, and any emails that are not sent to that account will be placed in an "anyone" folder on your server. This allows you to give out throw-away emails to services to which you don't want to give your real email.

I usually give out emails that are easily traceable, such as, if I'm going to sign up for the National Science Foundation newsletter.

Here is my own configuration which I use on my own email server.




This configures email for all of my accounts at,, and, and also supplies me with an infinite number of throwaway addresses for each of these domains.

9 Configure /etc/postfix/aliases

Edit /etc/postfix/aliases by changing

this line:

# Person who should get root's mail. Don't receive mail as root!
#root:      you

to this:

# Person who should get root's mail. Don't receive mail as root!
#root:      <your-user-name>

This is what my /etc/postfix/aliases looks like:

# Sample aliases file. Install in the location as specified by the
# output from the command "postconf alias_maps". Typical path names
# are /etc/aliases or /etc/mail/aliases.
#       >>>>>>>>>>      The program "newaliases" must be run after
#       >> NOTE >>      this file is updated for any changes to
#       >>>>>>>>>>      show through to Postfix.

# Person who should get root's mail. Don't receive mail as root!
root:           r

# Basic system aliases -- these MUST be present
MAILER-DAEMON:  postmaster
postmaster:     root

# General redirections for pseudo accounts
bin:            root
daemon:         root
named:          root
nobody:         root
uucp:           root
www:            root
ftp-bugs:       root
postfix:        root

# Put your local aliases here.

# Well-known aliases
manager:        root
dumper:         root
operator:       root
abuse:          postmaster

# trap decode to catch security attacks
decode:         root

Now, you must run

sudo postalias /etc/postfix/aliases

to reload the aliases.

10 Create basic directory structure

You will need to create the directory on your system where your mail will go.

sudo mkdir /mail
sudo chown postfix:postfix /mail

11 Check your work and activate postfix

Run the following command to confirm that all config files are up to spec.

sudo postfix check

Now, generate appropriate database files, without which postfix will not run.

sudo postalias /etc/postfix/aliases
sudo postmap   /etc/postfix/vmailbox
sudo postmap   /etc/postfix/virtual

Then, use systemctl to start postfix

sudo systemctl start postfix

Also use systemctl to start postfix automatically whenever you reboot.

sudo systemctl enable postfix.service

You can confirm that posfix is running on your server by executing:

systemctl status postfix

12 Confirm that you can receive emails.

At this point, you use whatever email you normally use to email yourself at your new email accounts. Try out multiple throwaway email addresses as well as your main email address. After emailing yourself, allow up to a few minutes for the mail to be delivered, then log on to your server and check that postfix received the email and placed it in the appropriate directory.


sudo ls -R /mail

and you should see that one file for each email you sent to yourself has been deposited into an appropriate directory.

For example, on my system, after sending a few test emails, I see:

anyone  rlm

cur  new  tmp




cur  new  tmp




There are 6 emails here, two to "" and four to other addresses at

12.1 If you have problems

Be sure to look at the output of

systemctl status postfix

to see if postfix is running, and if it has experienced critical errors.

Also look at:

sudo journalctl | grep postfix | less

to see postfix specific error messages.

13 Install dovecot, a program for accessing your email.

At this point you can now receive mail at your server, but you have no good way to access those messages, other than logging onto the server and examining the files directly. In this section, we will install dovecot, which is an IMAP (Internet Message Access Protocol) server.

You can learn more about dovecot at

Install dovecot with pacman.

sudo pacman -S dovecot

14 Create authentication files for your server

You will need to create a SSL certificate for your email server so that you can securely connect to it from your home server.

Install openssl to help create this certificate:

sudo pacman -S openssl

Now, you will generate your key and your certificate.

openssl req -new -x509 -nodes -out server.crt -keyout server.key -days 365

This will produce a file called "server.crt" and another called "server.key". The "crt" file is a public file that your email server will share with anything that tries to connect with it. The key file is private and together with the crt file enables secure two way communication.

You should give proper permissions to your keyfile.

chmod 0600 server.key

This will make the file readable and writable only by the root user.

Now that you have generated your server's keyfile and certificate, copy them to the appropriate directories.

sudo cp server.crt /etc/ssl/certs
sudo cp server.key /etc/ssl/private

14.1 Configure /etc/dovecot/dovecot.conf

Dovecot is controlled by the file /etc/dovecot/dovecot.conf. Edit it so that it looks like this:

## Dovecot configuration file

# virtual users

disable_plaintext_auth = yes
auth_verbose = yes

auth_mechanisms = plain cram-md5

service auth {
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix        
  unix_listener auth-userdb {
    mode   = 0600
    user   = postfix
    group  = postfix

mail_location = maildir:~/
passdb  {
  args = /etc/dovecot/virtual-users 

userdb {
  args = uid=postfix gid=postfix home=/mail/%d/%n

ssl_cert = </etc/ssl/certs/server.crt
ssl_key = </etc/ssl/private/server.key

first_valid_uid = 73

This file tells dovecot to only allow secure connections to your email. The authentication files we generated in the last step are referenced at the end of the file towards this end. It also tells dovecot to use the file at /etc/dovecot/virtual-users to determine the email users that are allowed to access the system. Now we will configure /etc/dovecot/virtual-users.

15 Configure /etc/dovecot/virtual-users

This file stores the usernames and passwords for all the email users on your system. It does not store the passwords of the users directly, but instead stores a hash of the password.

You will need to decide on passwords for all the email accounts you created in the earlier steps.

For example, I would need to create an account for "", "", "", and "".

I recommend that you generate a long, secure password for each of your email users. You will most likely end up saving these passwords in whatever email client you will use, so you can afford to make them quite complicated.

Here is a good way to generate a secure password:

openssl rand -base64 30

It will produce output like this:


Now that you have that password, you can encode it with MD5 and use it to configure /etc/dovecot/virtual-users.

Encode the password to MD5 using dovecot

doveadm pw

Enter the password you generated. When I do it, I get:

doveadm pw
Enter new password:
Retype new password:

Take the output of this command and insert it into /etc/dovecot/virtual-users.{CRAM-MD5}a7535382e94efc99cd77d9ed64843f2ee2f6d2ecf8a61da6505b2f60027ed3af

Do this again for each user that you wish to configure.

Here is an example file:

15.1 Example /etc/dovecot/virtual-users.{CRAM-MD5}a7535382e94efc99cd77d9ed64843f2ee2f6d2ecf8a61da6505b2f60027ed3af{CRAM-MD5}f5053277d50ce57ad37f32be280068bea32c3d23b6bb22ceccb6415e9e5063a6{CRAM-MD5}947f0c40d388f60ee9227f71bfdf5e5a5ca2061240fa0b3bea661cb79e2f9d30{CRAM-MD5}9186d855e11eba527a7a52ca82b313e180d62234f0acc9051b527243d41e2740

16 Activate dovecot

Make dovecot start automatically whenever you reboot.

sudo systemctl enable dovecot.service

Activate dovecot.

sudo systemctl start dovecot

17 Test dovecot

You can connect locally to your server to make sure that dovecot is listening properly.

openssl s_client -connect localhost:993

You should see




From here you can try to login with your newly created users. Here is a transcript of a session between myself and my new dovecot IMAP server. My inputs are in green. I have left out some text for brevity.

# openssl s_client -connect localhost:993
depth=0 C = US, ST = MA, L = Boston, O = aurellem, CN = Robert McIntyre, emailAddress =
verify error:num=18:self signed certificate
verify return:1
depth=0 C = US, ST = MA, L = Boston, O = aurellem, CN = Robert McIntyre, emailAddress =
verify return:1
Certificate chain
 0 s:/C=US/ST=MA/L=Boston/O=aurellem/CN=Robert McIntyre/
   i:/C=US/ST=MA/L=Boston/O=aurellem/CN=Robert McIntyre/
Server certificate
subject=/C=US/ST=MA/L=Boston/O=aurellem/CN=Robert McIntyre/
issuer=/C=US/ST=MA/L=Boston/O=aurellem/CN=Robert McIntyre/
No client certificate CA names sent
SSL handshake has read 1436 bytes and written 521 bytes
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-GCM-SHA384
Server public key is 1024 bit
Secure Renegotiation IS supported
Compression: zlib compression
Expansion: zlib compression
    Protocol  : TLSv1.2
    Cipher    : DHE-RSA-AES256-GCM-SHA384
    Session-ID: AE7808536EF7B4C4B4BDBCF4BD97A4CE398CBDF0DC66FA9D2C63FF362AE0508B
    Master-Key: 60E947F815FD8ACE5F1BE22ED43ABDE1C8DACCBE6509A0258647A98419C8A8C87CCAC20BF3904B176A127BE0585706E7
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 300 (seconds)
    TLS session ticket:
    0000 - 80 19 ac 16 f2 13 ee 53-ac ef e0 a3 0c 69 2c 16   .......S.....i,.
    0010 - aa f7 c1 cf 12 fc 21 2a-55 94 9a d2 2f b0 75 bf   ......!*U.../.u.
    0020 - 13 74 dd dc a7 f1 d3 60-59 ff 44 81 2e a3 48 c3   .t.....`Y.D...H.
    0030 - 98 59 c5 75 40 28 1c 37-4e 2c 2a b2 12 0f f4 64   .Y.u@(.7N,*....d
    0040 - 1b 30 ac de 00 ae 68 4c-80 c6 62 4e 1c 2d 6e 56   .0....hL..bN.-nV
    0050 - 53 86 a7 d7 6a 4d 64 62-6b 58 10 2f c2 6e c6 56   S...jMdbkX./.n.V
    0060 - 89 d0 b4 29 0b d8 c2 af-c5 8a 06 f6 e9 5e 0f d2   ...).........^..
    0070 - 45 62 c3 68 1b 78 5a 04-82 5f 37 15 05 36 ce 4e   Eb.h.xZ.._7..6.N
    0080 - c0 fb 60 74 c2 de fa d0-22 5b 75 15 f6 ee 7a 49   ..`t...."[u...zI
    0090 - 30 b9 f2 09 57 db b6 de-ca d7 9f c0 2c cd da cb   0...W.......,...

    Compression: 1 (zlib compression)
    Start Time: 1372393095
    Timeout   : 300 (sec)
    Verify return code: 18 (self signed certificate)
# a login "" "password"
# b select inbox
* FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
* OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft \*)] Flags permitted.
* OK [UNSEEN 1] First unseen.
* OK [UIDVALIDITY 1372393112] UIDs valid
* OK [UIDNEXT 5] Predicted next UID
* OK [NOMODSEQ] No permanent modsequences
b OK [READ-WRITE] Select completed (0.023 secs).
c fetch 1 full
* 1 FETCH (FLAGS (\Recent) INTERNALDATE "14-Jun-2013 01:41:02 +0000" RFC822.SIZE 2938 ENVELOPE ("Thu, 13 Jun 2013 21:40:36 -0400" "test4" (("Robert L McIntyre" NIL "rlm" "MIT.EDU")) (("Robert L McIntyre" NIL "rlm" "MIT.EDU")) (("Robert L McIntyre" NIL "rlm" "MIT.EDU")) ((NIL NIL "rlm" "")(NIL NIL "lol" "")(NIL NIL "test" "")) NIL NIL NIL "<>") BODY ("text" "plain" ("charset" "ISO-8859-1") NIL NIL "7bit" 7 1))
c OK Fetch completed.
# d fetch 1 body[header]
* 1 FETCH (FLAGS (\Seen \Recent) BODY[HEADER] {2931}
Return-Path: <>
Received: from ( [])
        by (Postfix) with ESMTP id 979C24D743;
        Fri, 14 Jun 2013 01:41:02 +0000 (UTC)
X-AuditID: 1209190f-b7f556d000007025-55-51ba74968648
Received: from ( [])
        by (Symantec Messaging Gateway) with SMTP id 2B.64.28709.6947AB15; Thu, 13 Jun 2013 21:40:38 -0400 (EDT)
Received: from ( [])
        by (8.13.8/8.9.2) with ESMTP id r5E1ebdt026076;
        Thu, 13 Jun 2013 21:40:38 -0400
Received: from ( [])
        by (8.13.8/8.12.4) with ESMTP id r5E1eaHB025460;
        Thu, 13 Jun 2013 21:40:37 -0400
Received: from ( []) by (8.13.8) with ESMTP
        id r5E1eaDF012547; Thu, 13 Jun 2013 21:40:36 -0400
Received: (from nobody@localhost)
        by (8.13.8/8.13.8/Submit) id r5E1easc012546;
        Thu, 13 Jun 2013 21:40:36 -0400
X-Authentication-Warning: nobody set sender to using -f
Received: from
        ( [])  
        (User authenticated as rlm@ATHENA.MIT.EDU) by (Horde MIME
        library) with HTTP; Thu, 13 Jun 2013 21:40:36 -0400
Message-ID: <>
Date: Thu, 13 Jun 2013 21:40:36 -0400
From: Robert L McIntyre <rlm@MIT.EDU>
Subject: test4
MIME-Version: 1.0
Content-Type: text/plain;
Content-Disposition: inline
Content-Transfer-Encoding: 7bit
User-Agent: Internet Messaging Program (IMP) H3 (4.0.3)
d OK Fetch completed.
# e logout
* BYE Logging out
e OK Logout completed.

18.1 If you have problems


sudo journalctl | grep dovecot | less

to see the logs which dovecot writes when you attempt to connect with openssl.

19 Prepare to send email.

Create a test email (you should of course replace the to: and from: components with addresses of your own).

echo "\
> date: `date`
> subject: whatever
> to:
> from:
> hi
> " > email.txt

And then send that email using sendmail (which is part of postfix which you installed earlier.)

sendmail < email.txt

Confirm that you have received this email.

You are now done setting up your mail server, congratulations.

Your next step is connecting to your mail server using the mail client of your choice, and configuring webmail for your domain if you choose. Those issues will be covered here later.


How do I make it work on windows?

Author: Robert McIntyre

Created: 2015-05-03 Sun 17:18

Emacs 24.4.1 (Org mode 8.3beta)