Migrating from a Stretch to a Buster server

Upgrade or reinstall?

I recommend that you set up a new server and make sure that the new mail server is working correctly before you start migrating existing email users to it. You may argue that Debian can be upgraded easily using “apt-get dist-upgrade” but that is very dangerous on a live mail server. Automatic configuration changes may have evil side effects and you will likely lose emails. At least you are causing a serious downtime for your users.

If you follow my advice then get a new server and install Debian Buster on it. Once the users are migrated properly and all works well you can tear down the old server.

Read before you type

Follow this guide to the end. Only then start attempting a migration. Inform your users about the migration and set a time when you intend to move email accounts to the new server. The change will require a DNS change which takes a while to be visible worldwide so your users will have a period when incoming email is delayed. If you proceed properly not a single email will be lost though.

So you have your new server up and running and did everything to make it a working mail server? You really read all the pages in this guide and did what they told you? Okay, then let’s start.

Turn down the TTL of your MX record

The DNS “MX” record for your domain contains the hostname of your mail server. When switching to the new server you need to change the MX record. Every DNS record has a TTL (time-to-live) that defines the period of time that a record will stay valid even after you change it. Usually that TTL is rather high like 86400 seconds (=1 day). This information is used by caching name servers that they can use the cached values for a day. Turn that TTL down temporarily to 60 seconds so that the rest of the internet will pick up your change quicker. However it will take a day.

Migrate the mailserver database

You need to copy the database that contains the control data about your email domains and accounts. Log into the old (Stretch) server as root and back up the mailserver database. That is as easy as running…

mysqldump mailserver > mailserver.sql

Copy that file to the new server (using scp) and import it there:

mysql mailserver < mailserver.sql

Obviously any database changes on the old server from now on will have to be done on the new server as well until the migration is done.

One simple schema change is necessary though. The virtual_users table has a new field called “quota”. This SQL query adds it:

mysql> alter table virtual_users add column quota int(11) not null default 0;

Roundcube contacts

You should consider migrating the contacts that your users manage in Roundcube. I have not done that but it seems that dumping and restoring the roundcube database should do the trick.

Migrate the Maildirs hot

Fortunately Dovecot uses the maildir format that stores emails as plain files on disk. Login to the new (Buster) server and use rsync to copy over the mails from the old (Stretch) mail server:

rsync -va stretchserver:/var/vmail/ /var/vmail/

(Note the trailing slashes. Type them exactly as shown above or your files will end up in wrong places.)

There is no need to shut down Dovecot on your productive Stretch server. Copying the files while Dovecot is running will not break anything. This is called a “hot copy”. It may not be consistent but it will save time during the final synchronisation.


You told your users about the downtime, right? The time has come? Okay. Shut down Dovecot on both servers.

Migrate the emails cold

Let’s synchronize again. rsync will only copy those files that have changed which makes it much faster than the first sync. On your new server run:

rsync -va --delete stretch-server:/var/vmail/ /var/vmail/

(The “–delete” option makes sure that files that have been removed from the old server will also be deleted from the new server.)

Switch the DNS records

For all your domains you will have to change the DNS “MX” or “A” record to point to your new server.

Enable soft_bounce

Accidents happen. And you don’t want to lose emails. So run this command to enable your safety net on the new server:

postconf soft_bounce=yes

Now Postfix will always keep emails in the queue that it would otherwise reject. Start Postfix and Dovecot on the new server. Watch your /var/log/mail.log and run “mailq” from time to time to see what emails get stuck in the queue. If you are certain that emails can be removed then use “postsuper -d QUEUE-ID” (as shown in the “mailq” output).

Once you are certain that emails are properly received and sent you can switch off the soft_bounce mode again:

postconf soft_bounce=no

Shut down the old server

If possible do a final backup of the old server. If users are not complaining then dismiss the old system after a week.

24 thoughts on “Migrating from a Stretch to a Buster server”

  1. “If you follow my advice then get a new server and install Debian Stretch on it.”
    You mean Buster, right? =D

  2. Does migrating to a different server (specifically one with a different IP) cause, or have the potential to cause, issues with sent emails being flagged as spam?

    Is there merit to setting up the new mail server in a LXC container so that it’s public IP address doesn’t change?

    1. Christoph Haas

      Hi Adam. A changing IP should not be a problem as long as you are not accidentally getting on IP RBLs (real-time blacklists).

      Using LXC/containers sounds interesting but it would be a lot of work. You would probably need several containers for Postfix, Dovecot, MariaDB (which I would not want to run as a container in production). There are ways to use a systemd emulation to run several processes in a single container. But that sounds like a task that would get you into an “office” with rubbery walls. 🙂

      Maybe your ISP allows you to reserve IP addresses. That way you can migrate the IP to the new server when you are ready.

      1. Hello, about the PBL issue, i really dont know if all smtp servers using the database, but in my case, i manually unblock my IP in the following site:
        ( cause in the postfix logs i see the target mail server reject me because of a call in this place above, and also it was kind enough so to let me know 😉 )
        Even if my IP is a dynamic and i block that day’s IP, since then my IP doesnt block anymore. So, i think that service also looks domain names not only IP address, not matter if the query is IP driven.

        … i enjoy reading your tutorial. I just setup a personal email server on debian 10 using postfix/dovecot, one week now, without know just nothing. An email server is just a whole ‘serverspace’, with its own rules and language. Programming is always as simple as 1+1, but to carry this simplicity and moreover to tranfer it to the other, you must own your subject …
        anyway…, thanks

  3. Bold of you to assume i can just spin another server to migrate my mail server. I have lots of services going on that server 🙁

    1. Herbert Meier

      @al: If you have many services on one server, it is indeed important to move these services one after the other to a new server. If you just upgrade the OS on the one server with (let’s say) 20 services and you only expect 30 minutes per service to check and correct any issues, you will have a downtime of 10 hours for your users. And working under such pressure is error-prone.

      Of course, you can clone the system and do a dry-run with the clone, to see how the upgrade works, but the safe way is to use a new server.

  4. There is missing a step in between exporting and importing the mysql dump.
    You will have to create the database manually before import, or you will be presented with the error:
    ERROR 1049 (42000): Unknown database ‘mailserver’

    Simply run “mysql” followed by “create database mailserver;” before importing it.

  5. Charles Atkinson

    +1 to what GnaXi wrote about creating database “mailserver” before the restore.

    Also the commonly used “mysql mailserver USE mailserver;
    MariaDB [mailserver]> source mailserver.sql;

  6. Charles Atkinson

    My previous reply was garbled on submission. Should have been (hoping it will be OK this time, using an empty line between lines)

    Also the commonly used …

    mysql mailserver USE mailserver;

    MariaDB [mailserver]> source mailserver.sql;

  7. Charles Atkinson

    Agh! On submission the line with the redirect to stdin sign a.k.a less than sign a.k.a ASCII_3C was removed . Trying again using ASCII 3C instead of the glyph

    Also the commonly used …
    mysql mailserver ASCII_3C mailserver.sql
    … can error on unusual characters. So it’s safer to use
    # mysql

    MariaDB [(none)]> USE mailserver;
    MariaDB [mailserver]> source /tmp/mailserver.sql;

  8. hello,
    If for example, you want to change the imap directory structure (replace . with /) instead of using a rsync command on the file system, you can use the imapsync perl utility which allows you to synchronize one imap box to another. Since imap is used and not rsync the structure of the boxes is indifferent. The script is quite sophisticated and allows dry-runs, transfer only directories and resume after interruption. I tried it and it works perfectly.

  9. You should do the bigint change also on this page to be consistent with the database setup.

  10. I.o.w. the guide tells the reader to shut it down but not turn it up. I get that it’s a no-brainer, but for the sake of completeness♥

  11. Hello,
    should be possible, once the new mail server is operational, switch one domain and its email accounts at a time (not all at the same time)?

    Many thanks!

  12. Hi,
    I have perfectly working ISPmail on my very old Wheezy machine which I need to replace with new Buster machine.
    Will the migration procedure above work in this scenario?
    If not, can you advice how to migrate, please?
    Thank you.

    1. Christoph Haas

      Hi Boris. Wheezy is a tad old to be sure. But I don’t see any breaking changes. Just go step by step.

  13. Hi, thank you for the nice tutorial – especially the part on DNS TTL settings which I would have totally overlooked

    One caveat regarding the DNS TTL settings: make sure you lower the TTL of all of the following DNS records regarding your mail server:
    – A (IPv4)
    – AAAA (IPv6)
    – TXT record for SPF, if used

    Maybe you could be so kind and include this in the article.

  14. The above comment was about the migration part from stretch to buster – DKIM/DMARC could also be included, if something changes.

    Also for the migration: make sure to migrate the SSL/TLS private keys – letsencrypt will only work after DNS is configured correctly to the new address

Leave a Reply

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

Scroll to Top