How to Migrate Zimbra 8.8.15 from CentOS 6 to Ubuntu 20.04 LTS
- Last updated: Jul 27, 2025

I was running a Zimbra Collaboration Open Source server on an aging CentOS 6 system that I needed to upgrade.
Since CentOS reached its end of life in late , I had to migrate to another GNU/Linux distribution.
Given the limited supported alternatives, I chose to migrate to Ubuntu Server 20.04 LTS
, which is now officially supported by the Zimbra Collaboration Open Source Edition 8.8.15
.
System Requirements and Configuration Checklist
⚠️ Important: To ensure a successful migration, both servers must run the exact same version of Zimbra. ⚠️
- Source Server
- OS:
CentOS 6.10
- Zimbra:
8.8.15_GA_3869
- OS:
- Destination Server
- OS:
Ubuntu 20.04.3 LTS
- Zimbra:
8.8.15.BETA.4155
- OS:
Prepare the Source Server (CentOS 6)
On the old server, we will stop the Zimbra services and transfer the necessary files to the new server.
Once everything is copied, the CentOS server can be safely powered down.
Copy Files to the New Server
- (Optional) Clean up old
zmstat
logs at/opt/zimbra/zmstat
to speed up the file transfer:
zimbra@zcs:~$ /opt/zimbra/libexec/zmstat-cleanup --keep 30
- Stop the
zimbra
services:
root@host:~# su - zimbra
zimbra@zcs:~$ zmcontrol stop
- Copy the main
/opt/zimbra
directory to the destination server:
root@host:~# rsync -e ssh -axvzKHS /opt/zimbra [newserver-IP-address]:/opt/ZIMBRA_TMP
Note: Because rsync
cannot easily write as root
on an Ubuntu system via SSH, it is often easier to initiate the transfer from the new server instead. (More details here).
Export LDAP Databases
- Export the main LDAP database:
zimbra@zcs:~$ /opt/zimbra/libexec/zmslapcat /tmp/LDAP
- Export the configuration database:
zimbra@zcs:~$ /opt/zimbra/libexec/zmslapcat -c /tmp/LDAP
- Export the accesslog database (optional – it was empty in my case):
zimbra@zcs:~$ /opt/zimbra/libexec/zmslapcat -a /tmp/LDAP
- Copy all exported LDAP files to the destination server:
root@host:~# rsync -e ssh -axvzKHS /tmp/LDAP [newserver-IP-address]:/opt/
Retrieve Zimbra Passwords (Optional)
This step is optional, but you may want to retrieve the existing Zimbra service passwords for reference or backup purposes.
- Extract passwords directly from the configuration file
/opt/zimbra/conf/localconfig.xml
. For example:
<key name="zimbra_ldap_password">
<value>TXrP9mSTd</value>
</key>
- Or use the
zmlocalconfig
command to retrieve multiple passwords at once:
zimbra@zcs:~$ zmlocalconfig -s | grep "ldap_amavis_password\|ldap_nginx_password\|ldap_postfix_password\|ldap_replication_password\|ldap_root_password\|zimbra_ldap_password"
Shutdown the Source Server
- First, verify the current hostname (it should match the original configuration):
root@host:~# hostname
zcs.shebangthedolphins.net
- Then shut down the source server:
root@host:~# poweroff
Set Up the Destination Server (Ubuntu 20.04 LTS)
We assume that a fresh installation of Ubuntu Server 20.04 LTS is already in place.
To gain root access, you can use the following command:
Configure the Network
- Edit the Netplan configuration file at
/etc/netplan/00-installer-config.yaml
and assign the same IP address used by the old server:
# This is the network config written by 'subiquity'
network:
ethernets:
ens160:
addresses:
- 192.168.1.10/24
gateway4: 192.168.1.254
nameservers:
search: [shebangthedolphins.net]
addresses: [192.168.1.254]
version: 2
- Apply the new configuration with Netplan or reboot the system:
root@host:~# netplan apply
- Set the hostname to match the old server:
root@host:~# hostnamectl set-hostname zcs.shebangthedolphins.net
Configure /etc/hosts
Edit the /etc/hosts
file to ensure the hostname and local IP address match the old server:
127.0.0.1 localhost
192.168.1.10 zcs.shebangthedolphins.net shebangthedolphins.net
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback localhost
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
Configure systemd-resolved
By default, systemd-resolved
listens on UDP port 53, which conflicts with Zimbra's internal unbound
DNS server. To avoid this, disable DNSStubListener by editing the following file:
- Edit
/etc/systemd/resolved.conf
and setDNSStubListener=no
:
[Resolve]
#DNS=
#FallbackDNS=
#Domains=
#LLMNR=no
#MulticastDNS=no
#DNSSEC=no
#DNSOverTLS=no
#Cache=no-negative
DNSStubListener=no
#ReadEtcHosts=yes
- Stop the
systemd-resolved
service and remove the auto-generated/etc/resolv.conf
file:
root@host:~# systemctl stop systemd-resolved
root@host:~# rm /etc/resolv.conf
- Reboot the server:
root@host:~# reboot
- After reboot, create a new
/etc/resolv.conf
file with the following content:
root@host:~# echo "nameserver 192.168.1.254
search shebangthedolphins.net" > /etc/resolv.conf
- Verify DNS resolution is working:
root@host:~# resolvectl query shebangthedolphins.net
shebangthedolphins.net: 192.168.1.10
-- Information acquired via protocol DNS in 2.4ms.
-- Data is authenticated: yes
Install Zimbra
- Download the appropriate version of Zimbra Collaboration Open Source Edition for Ubuntu 20.04, and extract the archive:
root@host:~# tar xzvf zcs-8.8.15_BETA_4155.UBUNTU20_64.20210924020007.tgz
- Navigate into the extracted directory and start the installer in
software-only
mode using the-s
flag:
root@host:~# cd zcs-8.8.15_BETA_4155.UBUNTU20_64.20210924020007 && ./install.sh -s
During the installation process, you will be prompted to accept the license agreement.
[…]
----------------------------------------------------------------------
PLEASE READ THIS AGREEMENT CAREFULLY BEFORE USING THE SOFTWARE.
SYNACOR, INC. ("SYNACOR") WILL ONLY LICENSE THIS SOFTWARE TO YOU IF YOU
FIRST ACCEPT THE TERMS OF THIS AGREEMENT. BY DOWNLOADING OR INSTALLING
THE SOFTWARE, OR USING THE PRODUCT, YOU ARE CONSENTING TO BE BOUND BY
THIS AGREEMENT. IF YOU DO NOT AGREE TO ALL OF THE TERMS OF THIS
AGREEMENT, THEN DO NOT DOWNLOAD, INSTALL OR USE THE PRODUCT.
License Terms for this Zimbra Collaboration Suite Software:
https://www.zimbra.com/license/zimbra-public-eula-2-6.html
----------------------------------------------------------------------
Do you agree with the terms of the software license agreement? [N] Y
Use Zimbra's package repository [Y] Y
And choose which Zimbra components to install. Be sure to select the same packages that were installed on the old server.
Select the packages to install
Install zimbra-ldap [Y]
Install zimbra-logger [Y]
Install zimbra-mta [Y]
Install zimbra-dnscache [Y] N
Install zimbra-snmp [Y] N
Install zimbra-store [Y]
Install zimbra-apache [Y] N
Install zimbra-spell [Y]
Install zimbra-memcached [Y]
Install zimbra-proxy [Y]
Install zimbra-drive [Y] N
Install zimbra-imapd (BETA - for evaluation only) [N]
Install zimbra-chat [Y] N
Checking required space for zimbra-core
Checking space for zimbra-store
Checking required packages for zimbra-store
zimbra-store package check complete.
Installing:
zimbra-core
zimbra-ldap
zimbra-logger
zimbra-mta
zimbra-store
zimbra-apache
zimbra-spell
zimbra-memcached
zimbra-proxy
zimbra-patch
zimbra-mta-patch
zimbra-proxy-patch
The system will be modified. Continue? [N] Y
- Once the installation is complete, delete the temporary installation directory to clean up:
root@host:~# rm -rf /opt/zimbra/
- Then move the copied
zimbra
directory from the source server into place:
root@host:~# mv /opt/ZIMBRA_TMP/zimbra /opt/
Import LDAP Databases
Preparing the Import
- Rename the existing
mdb
directory to back it up:
root@host:~# cd /opt/zimbra/data/ldap; mv mdb /tmp/mdb.old
- Create a fresh
mdb
directory structure:
root@host:~# mkdir -p mdb/db
- Do the same for the
config
database:
root@host:~# cd /opt/zimbra/data/ldap; mv config /tmp/config.old
root@host:~# mkdir config
- If your setup includes an
accesslog
database, back it up and recreate its structure:
root@host:~# cd /opt/zimbra/data/ldap; mv accesslog /tmp/accesslog.old
root@host:~# mkdir -p accesslog/db
- Finally, fix the permissions for the new LDAP directory structure:
root@host:~# /opt/zimbra/libexec/zmfixperms -e -v
Importing the LDAP Data
- Ensure the
zimbra
user owns the imported LDAP backup directory:
root@host:~# chown -R zimbra:zimbra /opt/LDAP
- Switch to the
zimbra
user:
root@host:~# su - zimbra
- Import the configuration database using the
-c
flag:
zimbra@zcs:~$ /opt/zimbra/libexec/zmslapadd -c /opt/LDAP/ldap-config.bak
- Import the main LDAP database:
zimbra@zcs:~$ /opt/zimbra/libexec/zmslapadd /opt/LDAP/ldap.bak
- If applicable, import the accesslog database:
zimbra@zcs:~$ /opt/zimbra/libexec/zmslapadd -a /opt/LDAP/ldap-accesslog.bak
Upgrade Zimbra
- If not already present, create the
zimbra-stats.log
file and set correct permissions:
root@host:~# touch /var/log/zimbra-stats.log
root@host:~# chown zimbra:zimbra /var/log/zimbra-stats.log
- Add required
sudoers
rules for thezimbra
user to allow passwordless execution of specific commands:
root@host:~# echo "%zimbra ALL=NOPASSWD:/opt/zimbra/libexec/zmstat-fd *
%zimbra ALL=NOPASSWD:/opt/zimbra/libexec/zmslapd
%zimbra ALL=NOPASSWD:/opt/zimbra/postfix/sbin/postfix, /opt/zimbra/postfix/sbin/postalias, /opt/zimbra/postfix/sbin/qshape.pl, /opt/zimbra/postfix/sbin/postconf,/opt/zimbra/postfix/sbin/postsuper
%zimbra ALL=NOPASSWD:/opt/zimbra/libexec/zmqstat,/opt/zimbra/libexec/zmmtastatus
%zimbra ALL=NOPASSWD:/opt/zimbra/amavisd/sbin/amavis-mc
%zimbra ALL=NOPASSWD:/opt/zimbra/libexec/zmunbound
%zimbra ALL=NOPASSWD:/sbin/resolvconf *
%zimbra ALL=NOPASSWD:/opt/zimbra/libexec/zmmailboxdmgr
%zimbra ALL=NOPASSWD:/opt/zimbra/bin/zmcertmgr
%zimbra ALL=NOPASSWD:/opt/zimbra/bin/zmmailboxdctl
%zimbra ALL=NOPASSWD:/opt/zimbra/bin/zmmailbox
%zimbra ALL=NOPASSWD:/opt/zimbra/bin/zmdnscachectl" >> /etc/sudoers
- Restart the installation in software-only mode to complete the setup and trigger the upgrade process:
root@host:~# ./install.sh -s
[…]
The Zimbra Collaboration Server appears to already be installed.
It can be upgraded with no effect on existing accounts,
or the current installation can be completely removed prior
to installation for a clean install.
Do you wish to upgrade? [Y]
[…]
The system will be modified. Continue? [N] Y
- Once the upgrade is complete, switch to the
zimbra
user:
root@host:~# su - zimbra
- Start the Zimbra services:
zimbra@zcs:~$ zmcontrol start
That’s it — the migration is now complete!

Optional: Disable Disk Usage Alerts for Loop Devices
If you are receiving disk space monitoring alerts related to loop devices, you can exclude them from Zimbra's monitoring system:
zimbra@zcs:~$ zmlocalconfig -e zmstat_df_excludes='/dev/loop0:/dev/loop1:/dev/loop2:/dev/loop3:/dev/loop4:/dev/loop5:/dev/loop6'
Then restart the Zimbra services again:
zimbra@zcs:~$ zmcontrol start