Creating a TLS encryption key and certificate

(If you are unfamiliar with the abbreviation “TLS“: it is the successor to SSL.)

The internet is the best invention since sliced bread but it has become an evil place more than ever. We are dealing with script kiddies, out-of-control secret services and organized crime on a large scale. It is completely out of the question to run any unencrypted services over the internet. I consider any password immediately wasted that went through the internet unencryptedly. So let us create an encryption key and a certificate for Postfix (SMTP), Dovecot (IMAP/POP3) and Roundcube (Webmail/HTTPS).

Caveat: do not use different certificates for Postfix and Dovecot. At least the MacOS mail client will refuse your connection with confusing error messages.

There are two factors that make an encryption certificate secure:

(a) – Cryptographical security

The mathematical idea of one-way functions that make it easy to decrypt data if you know the key – but to make it virtually impossible trying to break the decryption without that knowledge. For a couple of years the SHA1 algorithm was famous but thanks to Edward Snowden’s disclosures we assume that it can be broken too easily. So everyone is advised to use at least SHA256 (which is part of the SHA2 algorithm). Also RSA signatures should not be 1024 bits long any more but rather 4096 bits. Creating secure keys and certificates is relatively easy – we have tools for that.

(b) – Trust

The idea of trusting a certificate. What’s the point if the certificate is mathematically good but you don’t know who you are communicating with. You may communicate very securely with the wrong counterpart (called man-in-the-middle). That’s not what you want. (See also my article on creating your own certificate authority.)

So you have to decide whether to buy a certificate or to create one yourself. In comparison:

Type Advantages Disadvantages Application
Self-signed No costs.
Quickly created.
Users will get a warning message about an untrusted certificate. They can accept the certificate manually but you should tell them the certificate’s fingerprint so they can verify it. Private mail server for yourself and friends who don’t mind ignoring the warning message about an unverified identity.
Self-signed with own PKI No costs.
You can create further certificates that your users will consider trusted if they have your root certificate installed. The easy-rsa package is a good start.
Takes 15 minutes longer for you. Requires that all users install your root certificate as trusted on their computers. This may make sense only if you can automatically distribute the certificate in a corporate environment. Private mail server for yourself and friends who don’t mind installing your root certificate once. Or a corporate mail server where you can automatically deploy your root certificate on all client workstations.
No-cost certificate from LetsEncrypt No costs.
Users will likely not get a warning because most software trusts LetsEncrypt.
Certificates are only valid for 90 days. Depending on your network it may be a hassle and cause a downtime to renew a certificate. Public mail server that does not need sugar coating called “extended validation”.
Paid certificate Users will not get a warning. Expensive (50€-200€ per year).
Probably a lengthy registration process.
You support the certificate mafia.
You don’t improve the communication security in any way.
For anyone who has too much money.

Note: Whichever method you use – always create the key on your own server. Never trust a key that has been created by anyone else. It appears simpler because you can omit one step. But the other party now knows your secret key and could in theory intercept your encrypted traffic. I will describe how to do that properly in any of the following sections. Just choose your option and follow the instructions.

Option 1: Self-signed

The simplest option. Just run this command on your server and you have a valid all-purpose certificate that is valid for the next ten years:

openssl req -newkey rsa:4096 -nodes -sha512 -x509 -days 3650 -nodes -out /etc/ssl/certs/mailserver.pem -keyout /etc/ssl/private/mailserver.pem

You will be asked for several pieces of information. Enter whatever you like. The only important field is the “Common Name” that must contain the fully-qualified host name that you want your server to be known on the internet. Fully-qualified means host + domain.

Make sure that the secret key is only accessible by the ‘root’ user:

chmod go= /etc/ssl/private/mailserver.pem

Option 2: Self-signed with own PKI

This option is a bit better than using a simple self-signed certificate. But your users or customers need to install your root certificate manually to establish a trust relationship to your PKI in both their browsers and their email programs.

I suggest you install the “easy-rsa” package and read the documentation:

zless /usr/share/doc/easy-rsa/README-2.0.gz

If there is enough interest in this topic I will elaborate on managing your own certificate authority using easy-rsa.

Option 3: No-cost certificate from StartSSL

This is almost always the best option. It doesn’t cost you money and will give you a basic trustworthy certificate that most browsers and email clients will accept.

Create a 4096 bit key file:

openssl genrsa -out /etc/ssl/private/mailserver.pem 4096

Create a certificate signing request (CSR) file from that key:

openssl req -new -key /etc/ssl/private/mailserver.pem -out /etc/ssl/certs/mailserver.csr

You will be asked for several pieces of information. Enter whatever you like. The only important field is the “Common Name” that must contain the fully-qualified host name that you want your server to be known on the internet.

Now go to StartSSL and sign up for an account. First use the “Validation Wizard” to validate your email address first. Then use the validation wizard again to validate the domain you want to use for your email server.

Next use the “Certificates Wizard” to create a “Web Server SSL/TLS certificate”. Choose your email domain, paste the contents of the CSR file (/etc/ssl/certs/mailserver.csr) you created previously and receive your certificate file. Move that file to /etc/ssl/certs/mailserver.pem and set its permissions properly:

chmod go= /etc/ssl/private/mailserver.pem

In addition to the Apache configuration described below please ensure to install the chaining certificate, too. A sample configuration section is available in the StartSSL documentation.

Option 4: Paid certificate

Are you sure you want to do it? Then just search the web for “SSL certificate” and throw your money at any certificate authority.

The key and the certificate request are created as described above in Option 3.

Use the CSR file to request a certificate from the SSL authority. Move that certificate file to /etc/ssl/certs/mailserver.pem and set its permissions properly:

chmod go= /etc/ssl/private/mailserver.pem

Increasing TLS security

By the way – you should forbid communication using potentially insecure encryption methods. There is a way to attack the encryption by pretending that you do not support modern encryption techniques and thus rather want to use SSL version 2 or 3. This is called the POODLE attack. So you better run

postconf 'smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3'

to forbid communication using pre-Snowden protocols that may be abused to attack you. (Thanks for the hint, Guillaume.)

47 thoughts on “Creating a TLS encryption key and certificate”

  1. You have wrong paths to mailserver.pem in your last two commands.
    You should NOT use this:
    chmod go= /etc/ssl/private/mailserver.pem

    You should use this:
    chmod go= /etc/ssl/certs/mailserver.pem

    1. Christoph Haas

      Why? The certificate is the “public key” so to say. It does not need to be protected. It contains the data that is sent first when a secure connection is opened anyway. The private key however (located in /etc/ssl/private) must not be read by anyone except the mail server. Anyone who would have the private key could decrypt your otherwise secure traffic.

      1. I think the confusion is caused by the sentences above those two commands. They state “Move that certificate file to /etc/ssl/certs/mailserver.pem and set its permissions properly:”. The command that follows it then refers to the keyfile in /etc/ssl/private, instead of the certificate file that you just moved to /etc/ssl/certs. So the command is correct, but the sentence above it is confusing.

        Great guide by the way!

  2. Thanks for the great tutorial, I was wondering, if I wanted to host mail for several domains, ie:, etc would a single ssl cert for work for and others?

    Also, how would email be handled at a domain level? and point to the same ip?

    1. Christoph Haas

      You could in theory create a certificate for several domains. But I haven’t seen a certificate authority that would sign such a certificate. When dealing with web servers you can get several certificates and thanks to modern SNI (server name indication) the web server can figure out which certificate it should use. But that won’t work for secure IMAP, POP3 and SMTP communication.

      If several MX servers point to the same IP that’s no problem. If one server sends email to another then nowadays it will accept any certificate and initiate an encrypted connection.

  3. By the way, you should add smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3 in your to avoir the Poodle SSLv3 vulnerability

      1. Hi Christoph,
        in your (awesome) guide Postfix has an opportunistic use of TLS (in the chapter about relaying you set “smtpd_tls_security_level” to “may”).
        So the correct parameter is
        smtpd_tls_protocols = !SSLv2, !SSLv3 # Postfix as SMPT Server
        smtp_tls_protocols = !SSLv2, !SSLv3 # Postfix as SMTP client
        But don’t be afraid, this is the default value for all Postfix releases after the middle of 2015. 😉

  4. Hi,

    Just to mention that is issuing free certs that are validated, a good alternative to the commercial things and to the self signed.


  5. Keith Vella


    First of all thanks for the amazing tutorial. I am stuck trying to install the chain certificate. On StartSSL it is not so clear and I don’t have any experience setting this up.


    1. Christoph Haas

      HI Keith. When StartSSL offers you to download (copy/paste) the actual certificate then there are links to the CA and the Intermedia certificates. Download both. And then put these two plus your own certificate all into one “mailserver.crt” file. That will do it.

      1. Jon Singer

        Hi Christoph, Thank you for this wonderful guide. I am confused slightly because I believe the StartSSL website has changed. I am trying to properly install certificates. When I receive my certificates from StartSSL I get a downloaded file called “” inside that file are three more .zip files:,, and Inside each of those four zip files are: 1_root_bundle.crt,, 1_Intermediate.crt,, 1_mydomain.com_bundle.crt and 1_Intermediate.crt,, root.crt.

        What do I put where? I currently have /etc/ssl/certs/mailserver.csr and /etc/ssl/private/mailserver.pem. I am confused about your instructions as well as the comments as they seem to conflict. I would also like to know how and where I should put the intermediate certificate.
        Thank you for your tutorial!

  6. Hey Christoph,

    I’ve read through the entire tutorial and I’ve got to say, this is astounding! I do want to leave a bit of extra info on installing the chaining cert though. I feel like this will be a massive roadblock for a lot of readers. So hopefully this saves some time…


    # cd /etc/ssl/private

    Next, we’re going to obtain the Class 1 Intermediate Server CA by typing,

    # wget

    To combine your certificate with the newly obtained “” certificate, you’re going to use the cat command as follows (assuming YOUR certificate is still in /etc/ssl/certs)

    # cat /etc/ssl/certs/mailserver.pem > ssl-chain-mail-yourdomain.pem

    This should place the new chaining certificate in your /etc/ssl/private directory.

    Let me know if you disagree with this.


  7. Peter Gutwein

    A very good alternative way is to use a letsencrypt certificate. It’s free of cost, trusted and very easy to install on a modern Debian Server (automatic Installation via cert Client). In the meantime the letsencrypt Project is in Status Open Beta. It worked fine for me. Have a look at if u are interested.
    Regards Peter

  8. Said El Mazghari

    Hey could anyobody please tell me what/where to find the “certificate wizard” is?

  9. have launched a new website. The old certificate wizard is no longer there.

    You need to click on “Start Now for Free SSL Certificate” and then “Sign Up” to validate who you are.

    But be warned, the site at the moment is at a crawl.

    1. I think this is worth including in this or the next tutorial. The letsencrypt packages are now in debian-backports, so the setup is actually quite easy.

  10. Peter Thylander

    I Went for option three, but not ran into problems.
    § Dns records need to be set.
    § A running mailserver needs to be online on the domain you need to validate (accordning to godaddy).

    Therefore, I suggest that you move at least option three and four until the mail server is online.

  11. I am trying to use option 3 (startssl), but it seems that something changed in their system (or i made a big mistake).
    I didnt got a pem-file, i got a zip with many crt-files and now i dont understand how to install this (which file did i have to use for replace my /etc/ssl/private/mailserver.pem) ?

    Thanks in advance

    1. It seems i got it:

      unzip File from StartSSL
      unzip Apache file and got 2 files – used the second (2_myhost.mydomain.somewhere)

      wget # its PEM Version
      cat 2_myhost.mydomain.somewhere sca.server1.crt > /etc/ssl/certs/mailserver.pem

      to test it u have to get the root-ca file from startssl
      mv ca.crt /etc/ssl/certs/ca.pem
      openssl s_client -connect localhost:25 -starttls smtp -CAfile /etc/ssl/certs/ca.pem

      or use the existing one:
      openssl s_client -connect localhost:25 -starttls smtp -CAfile /etc/ssl/certs/StartCom_Certification_Authority.pem

      I hope thats the correct way – any advices?

      1. Christoph Haas

        Thanks for the reminder and the pointers. As much as I liked StartCom I have replaced the recommendation by LetsEncrypt. Also I consider LetsEncrypt pretty much a mess of scripts and a hassle of downtimes every 90 days. 🙁

        1. Hi Christoph – thanks so much for the tutorials, I’ve been using them for years – since sarge I think?

          Just a couple of things – using certbot as instructed on the letsencrypt site works perfectly with your guide, is fully automated and extremely simple to install.

          Also can I recommend BitDefender rather than spamassassin? Free, great WebGUI and does a much better job for me out of the box (with daily updates) than feeding SA 10,000 of good and bad mail.

  12. Made another cert for my webserver. After i compared the files, i noticed:
    U can use both files from Apache folder (maybe one of the other files are ready to use, but this way you may better understand the cert things):

    cat 2_myhost.mydomain.somewhere 1_root_bundle.crt > /etc/ssl/certs/mailserver.pem

    still learning every day 🙂

    1. In case anyone else is confused about the meaning of the certificate files that you receive from startssl and why these can be concatenated: I found this page very informative: A brief summary: it is advised that you not only provide your own certificate, but also the intermediate certificate. If you don’t provide the latter, most browsers will download it themselves, but it is not best practice.

      In our scenario we need both the 1_root_bundle.crt and the 2_myhost.mydomain.somewhere and they can indeed be combined into a single PEM file as per instructions of Jan above here. But you can also keep them in two separate files. I have renamed the 1_root_bundle.crt file to mailserver_intermediate.pem. In this case you need to enable the following in the /etc/apache2/sites-enabled/default-ssl.conf file:

      SSLCertificateFile /etc/ssl/certs/mailserver.pem
      SSLCertificateKeyFile /etc/ssl/private/mailserver.pem
      SSLCertificateChainFile /etc/ssl/certs/mailserver_intermediate.pem

      In case some other component needs the concatenated pem file it can’t hurt to keep this one as well. Mine is called mailserver_with_chain.pem.

  13. Davide Marchi

    Hey Christoph,
    Thanks very much for your great tutorial, which is very special because it describes the procedures considering the person on the other side. Which is rather rare and denoting great sensitivity and a real educational spirit!

    With regard to the question SSL instead, I would like to suggest this project: “”.

    What do you think about this? Could be useful to integrate your tutorial with this resource?

    Thank you


  14. Xandor Schiefer

    Perhaps you could update the guide to include Let’s Encrypt as an option? I’ve been using one of their certificates without issue (for mail).

  15. I was a big fan of StartSSL until Google stopped trusting them. For ubuntu 16.10 with apache2 working (http:), LetsEncrypt setup took 3 commands:

    # Get the certification bot:
    sudo apt-get install python-certbot-apache
    # Run the bot, answer questions, it even configures apache:
    certbot –apache
    # Load the updated apache site config file:
    sudo service apache2 restart

    After that, browser refresh returns https:// – that’s all it took!
    For background, see
    which should guide you to:
    Pick your configuration and go.

  16. Leigh the noob

    Great Tutorial here so far. I am a bit of a noob with linux and using it to host my own mail server as MS Exchange has become way too expensive now days. Kinda dumb question, but hostnames:

    I have set the servers hostname as: ServerName.MyDomain.local
    When setting up postfix, do i still use the .local FQDM or a .com to match my owned public domain?
    and when it comes to the certificate FQDN, do i want it to be a .local or or a DNS A Record that points to my server (eg

    Probably a really dumb question but always had a bit of confusion in this area if someone can clear it up for me please?


    1. Hi
      I have finished the setup about 3 weeks ago. Also ‘noobs level’ – and on a different OS (openSUSE).
      Took me about a month to do it.
      I found best is to have a FQDN server name (thus in your case of the .com domain). Though it is also ok with a .local. But than chances are higher that you will end up on blacklists and/or spamlists.

      I also use a PTR record in DNS (DNS reverse lookup) and also a SPF record to prevent ending up on those lists.
      I also have added the hostname to my certificate.

      1. Leigh the noob

        Thanks for the reply Ralf.

        So are you saying on the certificate you used the servers actual hostnamename (eg or a a record that points to that server (eg or both? I guess putting both could not hurt…

        I am using cloudflare for my DNS hosting (because its free) and cannot create a PTR record. is there any way I can get around this without switching to another DNS host that you are aware of? I am guessing adding the entry to my domain local DNS wont do the trick?

        1. You definitely want your SSL cert to read the mail server name. as in, when you setup thunderbird, if your incoming mail server is then your SSL certificate should be for because that’s what email clients will check against when they talk to your server, i used let’s encrypt and did and both in the cert so the webpage is covered as well for my webmail users.

          Another thing that stumped me and I think is confusing you as well I think the creator of these wonderful guides explains very well on the page about types of email domains. Read through that page again. He recommends a setting for ‘mydestination’ to be sure all incoming email is seen as virtual domains. The recommendation comes in the guide before you actually install the OS on your server so i hadn’t gone back to change that setting until much later. I think the explaination about types of domains and server names will help you better than i can explain. But the actual name you give your server locally shouldn’t cause problems as long as you have dns records that points emails to your server, a mx record and then a matching A record for that. I hope this helps.

          1. Leigh the noob

            Thanks for the advice Jeff. Very helpful although still a little bit of confusion. From what I have gathered from your advice, my setup I presume should be as follows (might help some other noobs):

            – hostname = MyServer.MyDomain.local

            – FQDN for postfix = MyServer.MyDomain.local (you dont use becasue you would have to create system accounts for each user, it is impractical and postfix cant distinguish the local domains)

            – mydestination = localhost (because we are using virtual domains)

            – virtual_mailbox_domains =,, etc… (defines the domains the server will receive mail to)

            – My certificate will have the name: (becasue that is what email setup will use and it will match the cert) I am unsure how you said you put just on a cert as they do not allow wildcards?? Did you mean a for your website??

            I gather this is the correct way to go about things? Confirmation would be great although trying again now using this config anyway.

        2. oh, also, as far as the PTR setup, the host of your DNS cannot do that, so switching DNS hosts wont help, the owner of your IP address has to do that. I.E. your internet provider, or if you’re renting a VPS, the company that’s coming from might let you. Godaddy for example doesn’t allow PTR’s for their servers, but they allow you to use their outgoing email server so you’d need to configure your mail server to relay through godaddys mail server instead of sending directly.

        3. – I use ‘’ as my hostname
          – from the register of my domain I point my domain to the DNS of my VPS provider
          – I use my hostname and public IP from my VPS for a PTR record. I have a VPS hosted and the provider allows me to set this myself on their system.
          – What helped me to test the server is this site:

          Hope you will be able to work everything out. Like I said. It took me about 4 weeks to understand, test and adapt to my situation (since I do not use Debian – though the differences are minor).

          1. Leigh the noob

            Thanks again Ralf. So are you only hosting emails for one domain? not multiple? From what was mentioned on the page about different domains I got the impression that using your had 3 drawbacks.

            Your PTR record I think might only be relevant in a VPS scenario where there are multiple domains and such sharing one IP. I dont think I should need it in my case as it is to be hosted from my home office (hopefully). So long as I have MX and possibly an autodiscover record (or is that just a microsoft exchange thing?) I should be ok I think.

            Damn linux can be frustrating 😛 Problem is once you start you become determined to make the damn thing work!

          2. Hi Leigh

            I use 3 domain. (lets say,,
            See below a port of my for postfix:

            myhostname =
            #mydomain =
            mydestination = localhost
            mynetworks =
            inet_interfaces = all
            virtual_mailbox_domains = mysql:/etc/postfix/

            As of this manual the virtual mailbox domain will be looked up from the database.

            This is what a received e-mail header looks like from my server:

            Received: from
            by (Dovecot) with LMTP id codyIx4BiViheQAAAMb7Tw
            for ; Wed, 25 Jan 2017 20:48:46 +0100
            Received: from localhost (localhost [])
            by (Postfix) with ESMTP id 6BB3432013B
            for ; Wed, 25 Jan 2017 20:48:46 +0100 (CET)
            dkim=pass (1024-bit key) header.b=ZuTgtk9W;
            X-Virus-Scanned: amavisd-new at
            Received: from ([])
            by localhost ( []) (amavisd-new, port 10024)
            with ESMTP id Jkolz7z9Ogn7 for ;
            Wed, 25 Jan 2017 20:48:42 +0100 (CET)

            The PTR: Even though I use 3 domains – it is ‘’ which always sends my mail, therefor my public IP resolves to in the PTR. If a receiving party can not resolve my public IP to (lets say you set it to server.mydomain.local) it might be considered as spam and rejected (depending on how strict their server is setup to accept mail). So ‘myhostname=’ in postfix is the same as in your PTR record.

            {Hosting the server at your home on a DSL/cable connecting can have serious drawbacks. You should do some reseach before you go ahead. For example my porvider would not allow me to send mail from my home (smtp from my server). I would have to specify another smtp server to send mail from in my case. But what is the point than if I am only allowed to do half of the setup from my home?}

  17. Hello again,
    Some more feedback:
    I know you’re going to include details of how to use Letsencrypt (LE) certificates in your tutorial for Debian “stretch” so I’d just like to comment in case anyone’s interested in doing this in “jessie.” Let me say first—just to clear any lingering doubts any readers may have—that a LE certificate will work perfectly for providing LS – standard encryption.

    I have to make do with only one dedicated server with one 1 IP address. In order to successfully use a Letsencrypt certificate for both the website and the first virtual domain I can confirm that the configuration given at works. I used the configuration for postfix without any changes, but had to make a minor change in the path in dovecot from the path given in the referenced howto, otherwise I couldn’t log in to Roundcube. I also had to disable inward bound spf, configured as per

    # path to the certificate file, should be root:root and 0444
    ssl_cert = </etc/letsencrypt/live/

    # path to the private key file, should be root:root and 0400
    ssl_key = </etc/letsencrypt/live/

    So at present I can now send email, for for example to gmail without the Red (no encryption) padlock appearing informing the recipient that such mail is not secure.

    So far so good; at least I've secured my most important email account with LE so now it's a question of getting the other accounts to work with the same certificate, assuming this is possible since —I assume—the other virtual domains included in the certificate are technically aliases of the base domain. They all get the green light when checking at
    At present I'm not sure how this may be done —if it can be done— for the devil is in the detail.


  18. To add to my last post where I said that I could only get my primary domain to work and hadn’t figured out how to use ONE Letsencrypt (LE) certificate for multiple virtual domains.
    Well, I ‘ve now figured it out as I posted on the Debian forums at where I tried, without success to date, to get a discussion going about the the subject of self-issued, paid and unpaid certificates. The way I did it is posted there.
    All virtual hosts work sharing only one IP work with one LE Certificate, the primary domain and all the others. I have tested this thoroughly with several domains and so I can confirm it.

  19. I left another reply but may have appended the wrong extension to my email address because so far it hasn’t appeared here.
    Anyway, I’d just like to add to my previous reply to say that I’ve got ONE Letsencrypt Certificate issued for my primary domain to work with multiple virtual hosts which all sharing only one IP address. No problems at all with the certificate. The same little dedicated server also doubles as a web server, again using the same certificate. I wrote about it recently on the Debian forums at:
    But now that everything’s working as it should and email passes all the tests with the LE certificate, spf, dkim & dmarc—and the server is not blacklisted anywhere— yet, to my surprise, several emails sent to a hotmail account got blocked when they get delivered immediately to gmail accounts.

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to Top