echo "

Zimbra to Zimbra migration using Zextras and SSHFS

This is only an extension to a normal installation. So you should have your new Zimbra environment ready to move the data of your current Zimbra environment to it.

In the past we did an in-place upgrade of our Zimbra and the Ubuntu it was residing on. The last upgrade from 8.5.1 on Ubuntu 14.04 to 8.7.1 on Ubuntu 16.04 was such a drama that I started looking for an easier solution that would give me a fresh Zimbra with all my settings, accounts, mails, calendar items ... without too much fuzz.

To prevent inconsistency please stop your old Zimbra and afterwards make a snapshot and/or backup before you continue.

/etc/init.d/zimbra stop

OR

su - zimbra -c "zmcontrol stop"

Also stop and disable fetchmail if you're using it

/etc/init.d/fetchmail stop 
sed -i "s/START_DAEMON=yes/START_DAEMON=no/g" /etc/default/fetchmail

Next change the IP because the Zimbra will need to be started again to do the export

sed -i "s/old_ip/temporary_ip/g" /etc/hosts /etc/network/interfaces
reboot

Next on both Zimbras create a folder to store the migration data on

su - zimbra -c "mkdir /opt/zimbra/backup/exports /opt/zimbra/backup/zextras"

Next mount this folder as the user zimbra on the new Zimbra (don't set a password on the zimbra user, just create a key pair and share the SSH public key). This will save you time to move the data.

 sshfs zimbra@temporary_ip:/opt/zimbra/backup/exports/ /opt/zimbra/backup/exports/

Next install the migration tool on the old Zimbra

cd /tmp && wget https://download.zextras.com/zextras_migration_tool-latest.tgz
tar xvzf zextras_migration_tool-*.tgz
cd zextras_migration_tool-*/
./install all

Now open the Zimbra admin page (https://temporary_ip:7071) and start exporting the domains and user you want to keep. Through ZeXtras -> ZxMig -> Start Migration

undefined

undefinedundefined

 Change the folder to the newly created /opt/zimbra/backup/exports

undefined

Select the domains you want to move

undefined

Under ZxNotifications check for any error during the export

undefined

When this finishes you can start importing on the new Zimbra. First install the Zextra suite (this is free for 30 days and we will remove it after we finish to get rid of warnings afterwards)

cd /tmp && wget http://download.zextras.com/zextras_suite-latest.tgz 
tar xvzf zextras_suite-*.tgz
cd zextras_suite-*/
./install all

Open the Zimbra admin page (https://new_ip:7071) and open the ZeXtas -> ZxBackup -> select Import Backup

 undefinedundefinedundefined

Change the path to /opt/zimbra/backup/exports

undefined

Select the domains you want to import

undefinedundefined

Select the accounts you want to import

undefined

And check if the restore started without warnings

undefined

After this finished you can clean up and give your new Zimbra the IP of the old one to start sending and receiving mails again.

If you had an SSL certificate installed now is the time to move that as well. Do this as user zimbra!

On the old zimbra

rsync -au /opt/zimbra/ssl/ zimbra@new_ip:/tmp/ssl/

On the new Zimbra

cp /tmp/ssl/zimbra/commercial/commercial.key /opt/zimbra/ssl/zimbra/commercial/ 
./zmcertmgr deploycrt comm /tmp/ssl/zimbra/commercial/commercial.crt /tmp/ssl/zimbra/commercial/commercial_ca.crt

In any case I would also enable HTTP -> HTTPS redirection

zmprov ms "FQDN" zimbraReverseProxyMailMode redirect

Let's finish:

FIRST: shutdown the old Zimbra machine and make sure it won't boot by itself. Don't forget to copy any backup settings, fetchmail config, cron jobs, ...

On the new Zimbra

cd /tmp/zextras_suite-*/ 
./install -u all
sed -i "s/new_ip/old_ip/g" /etc/hosts /etc/network/interfaces
reboot

Now your new Zimbra should be available with all the settings, accounts and mails just like it was when you stopped your old Zimbra.

Upgrading Ubuntu to 16.04 on OpenVZ (Proxmox <=3.4)

Stop any service and create a "snapshot". Since my Proxmox doesn't have a snapshot solution yet I specifically choose to use the local (SSD) storage without compression to get the backup to finish as fast as possible, we can't afford unnecessary downtime and in the next generation of our servers we will be using file system based snasphots (LVM or ZFS) which makes waiting for a backup to finish something of the past. I created my snapshot using the web interface of Proxmox 3.4 but this is what happens in the background after stopping the container.

vzdump 113 --remove 0 --mode stop --storage local --node duff-prox-01

I changed the IP of my VPS during the entire upgrade.

sed -i "s/old_ip/temporary_ip/g" /etc/network/interfaces /etc/hosts
/etc/init.d/networking restart

Next upgrade Ubuntu (this application is in the update-manager-core package)

do-release-upgrade

You will get a warning and we will address this by replacing Systemd with the legacy Upstart before rebooting in Ubuntu 16.04

apt-get install upstart-sysv

After the reboot, check with netstat if everything started fine, change the IP again and reboot to start using a fully up to data Ubuntu in a dated VPS environment.

netstat -atnp 
apt-get -y upgrade
apt-get -y dist-upgrade
sed -i "s/temporary_ip/old_ip/g" /etc/network/interfaces /etc/hosts
reboot

Benchmarking Linux bonding with cheap NICs

Since a couple of years I have been using bonding to achieve load balancing, higher bandwidth and redundancy on Linux (and BSD, Windows, Solaris, ...). At home this can be rather challenging since lots of consumer switches don't understand all the bonding methods and Realtek adapters have the unpleasant habit of keeping the spoofed MAC address after a reboot which messes things up.

For this set up I will use a bunch of cheap Realtek and Intel NICs to connect 2 PC's using 4 NICs on every side to benchmark the actual speed.

I already mentioned that my Realtek adapters tend to remember the spoofed MAC address during reboot which causes UDEV to give the adapters a new name and rendering your config worthless. To prevent this I added some lines inside /etc/network/interfaces that start and stop the bond and load and unload the bonding module which causes the NIC to have it's factory MAC address back before rebooting.

This is my basic config using bonding mode 0 (round-robin). I only changed the mode= or in case of mode=2 and mode=4 with L3+L4 hashing I uncommented the xmit_hash_policy variable. All benchmarked modes give fault tolerance and load balancing (albeit not always visible in the results)

# The primary network interface
auto bond0
iface bond0 inet static
pre-up modprobe bonding mode=0 miimon=100 #xmit_hash_policy=layer3+4
pre-up ip link set enp4s0 master bond0
pre-up ip link set enp6s0 master bond0
pre-up ip link set enp8s0 master bond0
pre-up ip link set enp9s0 master bond0
mtu 9000
address 10.0.0.1
netmask 255.255.255.0
up /bin/true
down /bin/true
post-down ip link set enp4s0 nomaster
post-down ip link set enp6s0 nomaster
post-down ip link set enp8s0 nomaster
post-down ip link set enp9s0 nomaster
post-down ip link set dev bond0 down
post-down rmmod bonding

Mode=0 is only good for connecting 2 systems with multiple NICs directly to each other to achieve a single connection with a higher bandwidth. In switched environments or even worse in a bridge this method will really mess up your connections. In a switched connection you will see random packet loss and out of order packets. In a bridge you are lucky if you even get some packages over.

To get the most out of this I set the MTU to 9000 (jumbo frames) and connected 2 systems directly to each other. My NICs are all auto sensing so I didn't have to use crossed cables.

I used these scripts to run multiple instances of iperf (network benchmark tool) in parallel https://sandilands.info/sgordon/multiple-iperf-instances

method mode 0 (Round Robin) mode 2 (XOR) mode 2 (XOR L3+L4) mode 4 (LACP L2) mode 4 (LACP L3+L4)
single connection speed 3.14 Gbits/sec 719 Mbits/sec 661 Mbits/sec 730 Mbits/sec 725 Mbits/sec
total speed of 4 simultaneous connections 3.157 Gbits/sec 722 Mbits/sec 2.107 Gbit/s 735 Mbits/sec 1.484 Gbits/sec
ethtool advertised speed 4000Mb/s 4000Mb/s 4000Mb/s 4000Mb/s 4000Mb/s
Where to use inter system connection only

inter system connection OR on a switch that only supports static LAGs

inter system connection OR on a L3 switch than only supports static LAGs (...)

inter system connection OR on a L2 managed switch that supports LACP inter system connection OR on a L3 switch that supports LACP

As you can see mode=0 wins the benchmark but as I already said that comes with a price. Netgear for instance will recommend mode=2 for unmanaged switches or switches that only can handle static LAGs and mode=4 for switches that support LACP.

But in real life you should always use LACP since it is the most robust method out there and if you really need higher single connection speed you will have to invest in 10, 25, 40 or 100Gbit connections.

LACP can combine any form of hashing. You can combine hashing the MAC address (L2), the IP address (L3) or the UDP/TCP session (L4). This isn't only the case for Linux. Solaris and derivates like SmartOS just as well give you the option to combine any of these 3 hashing methods in your LACP aggregate. In Solaris L4 hashing is the default one, in Linux it is L2.

You can see in my result that running multiple iperf sessions on different ports really does make a difference if you use L4 hashing since we have 4 different TCP sessions. In the real world LACP will rarely be used for single connection configurations. If you use LACP underneath a bridge for your hypervisor for instance, since all your VMs and containers will have their own MAC address, IP address and use their own UDP/TCP sessions all your physical connections will be actually used and you will get a higher total bandwidth (albeit hard to benchmark) but you will never get more than 1 Gbit per session.

To finish, one mode that doesn't have anything to do with load balancing but can be nice is mode=1. I used this in the past to set up a fiber connection as primary link with a WiFi link as backup. In case the fiber stops working, traffic would be send over the WiFi link. Of course this kind of behavior can be achieved by using STP as well if you have a managed switch on both ends.

Fully encrypted ZFS root on Linux using LUKS (Ubuntu 16.04)

Since I wanted to have the joy of compression, fast resilvering, caches, ... on my workstation I started to look to use ZFS with LZ4 compression on top of a bunch of LUKS devices. I used 6 * 128GB MLC SSDs and put them in this great backplane IcyDock MB996SP-6SB

Plain ZFS with an eCryptFS home folder on top wasn't a good solution because that would render the LZ4 compression useless -> If you can compress encrypted data, your encryption method is useless...

So this are the steps I took to get it working:

Get a Ubuntu desktop live USB/CD and boot it. Next do this to get the necessary packages

sudo apt-get update
sudo apt-get install cryptsetyp debootstrap zfs mdadm

Get started by making a DOS-type partition table on /dev/sda with a 80MB primary partition and a second primary partition that uses all that is left. Afterwards you can copy the partition table using this simple dd command to copy only the first sector.

sudo dd if=/dev/sda of=/dev/sdb bs=512 count=1

Please notice that this only works for a DOS table with primary partitions. For logical partitions and GPT you will have to use something more advanced:

Backup

sfdisk -d /dev/sda > part_table

Restore

sfdisk /dev/sda < part_table

But this is what I did, since I only used primary partitions anyway.

dd if=/dev/sda of=/dev/sdb bs=512 count=1
dd if=/dev/sda of=/dev/sdc bs=512 count=1
dd if=/dev/sda of=/dev/sdd bs=512 count=1
dd if=/dev/sda of=/dev/sdf bs=512 count=1
dd if=/dev/sda of=/dev/sdg bs=512 count=1

Next encrypt your second primary partitions using luksFormat. By default LUKS will use AES with a 256bit key. You can benchmark to see which is the fastest encryption to use. Either way make sure your CPU has AES encryption and that this function is enabled in the BIOS/EFI otherwise you will have a lot of overhead!

Benchmark

cryptsetup benchmark

Check if AES is enabled (works on AMD and Intel CPU's)

grep -m1 -o aes /proc/cpuinfo

The actual formatting with the default settings (in my case the once with the best performance)

cryptsetup luksFormat /dev/sda2
cryptsetup luksFormat /dev/sdb2
cryptsetup luksFormat /dev/sdc2
cryptsetup luksFormat /dev/sdd2
cryptsetup luksFormat /dev/sdf2
cryptsetup luksFormat /dev/sdg2

Now Open (decrypt) to use them

cryptsetup luksOpen /dev/sdg2 crypt_sdg2
cryptsetup luksOpen /dev/sde2 crypt_sde2
cryptsetup luksOpen /dev/sdf2 crypt_sdf2
cryptsetup luksOpen /dev/sdd2 crypt_sdd2
cryptsetup luksOpen /dev/sdc2 crypt_sdc2
cryptsetup luksOpen /dev/sdb2 crypt_sdb2
cryptsetup luksOpen /dev/sda2 crypt_sda2

And create a zpool with 3 mirrors (VDEVs) to create a RAID10. I know you loose a lot of space this way but the LZ4 makes up a little for that and the increased speed, reliability and most important resilvering time makes using mirrors preferable over RAIDZ[1-3]

Aside I see a lot of tutorials where they ask you to set the ashift (sector alignment) to 12 (4k native) but since all my SSDs have a physical and logical sector size of 512 (ashift=9) I don't see why you would like to do that. Anyway ZFS should detect the sector size and align automatically.

zpool create rpool mirror crypt_sda2 crypt_sdb2 mirror crypt_sdc2 crypt_sde2 mirror crypt_sdd2 crypt_sdg2

Next we will enable compression on the pool (LZ4 is the default compression and the best/fastest one available)

zfs set compression=on rpool

Now create a / mountpoint make it bootable, make sure that the pool itself isn't mounted and export (stop) the entire pool

zfs create rpool/ROOT
zfs set mountpoint=/ rpool/ROOT
zpool set bootfs=rpool/ROOT rpool
zfs set mountpoint=none rpool
zpool export rpool

Next create a RAID10 of the first primary partitions to use as /boot

mdadm --create /dev/md0 --level=10 --raid-devices=6 /dev/sda1 /dev/sdb1 /dev/sdc1 /dev/sdd1 /dev/sdf1 /dev/sdg1
mkfs.ext4 /dev/md0

Next import (start) your pool and redirect all mounting points to /mnt

zpool import -R /mnt rpool

And prepare a basic Ubuntu 16.04

debootstrap xenial /mnt

Get the UUIDs

blkid | grep LUKS

Next parse all the UUID of your LUKS containers in /etc/crypttab inside your target directory.

echo "crypt_sda2 UUID=b86435dd-71cd-45cf-abde-ee373554915b none luks" >> /mnt/etc/crypttab
echo "crypt_sdb2 UUID=8d370731-8b6c-4789-9d15-68b5c6a8d74f none luks" >> /mnt/etc/crypttab
echo "crypt_sdc2 UUID=260bb228-a1b8-4739-8ce7-a4671b4d723b none luks" >> /mnt/etc/crypttab
echo "crypt_sdd2 UUID=9e35fc89-bd1c-4db6-b9fc-15d311652f0b none luks" >> /mnt/etc/crypttab
echo "crypt_sde2 UUID=35129e92-3fb6-4118-aada-5dc2be628c05 none luks" >> /mnt/etc/crypttab
echo "crypt_sdg2 UUID=3ef442d5-ed6e-4a4a-bcce-84f3c31acf32 none luks" >> /mnt/etc/crypttab

Set your hostname

echo "SoloTheatre" > /mnt/etc/hostname
echo "127.0.1.1 SoloTheatre" >> /mnt/etc/hosts

Prepare a chroot environment and enter it

mount /dev/md0 /mnt/boot
mount --bind /dev /mnt/dev
mount --bind /dev/pts /mnt/dev/pts
mount --bind /proc /mnt/proc
mount --bind /sys /mnt/sys
chroot /mnt /bin/bash --login

Force initramfs to be cryptsetup aware

echo "export CRYPTSETUP=y" >> /usr/share/initramfs-tools/conf-hooks.d/forcecryptsetup

Now push all the LUKS containers inside a initramfs config to make sure they are being picked up and presented for decryption when booting

echo "target=crypt_sda2,source=UUID=b86435dd-71cd-45cf-abde-ee373554915b,key=none,rootdev,discard" >> /etc/initramfs-tools/conf.d/cryptroot
echo "target=crypt_sdb2,source=UUID=8d370731-8b6c-4789-9d15-68b5c6a8d74f,key=none,rootdev,discard" >> /etc/initramfs-tools/conf.d/cryptroot
echo "target=crypt_sdc2,source=UUID=260bb228-a1b8-4739-8ce7-a4671b4d723b,key=none,rootdev,discard" >> /etc/initramfs-tools/conf.d/cryptroot
echo "target=crypt_sdd2,source=UUID=9e35fc89-bd1c-4db6-b9fc-15d311652f0b,key=none,rootdev,discard" >> /etc/initramfs-tools/conf.d/cryptroot
echo "target=crypt_sdf2,source=UUID=35129e92-3fb6-4118-aada-5dc2be628c05,key=none,rootdev,discard" >> /etc/initramfs-tools/conf.d/cryptroot
echo "target=crypt_sdg2,source=UUID=3ef442d5-ed6e-4a4a-bcce-84f3c31acf32,key=none,rootdev,discard" >> /etc/initramfs-tools/conf.d/cryptroot

link all the LUKS containers since grub-update doesn't care about the default /dev/mapper/ directory

ln -sf /dev/mapper/crypt_sda2 /dev/crypt_sda2
ln -sf /dev/mapper/crypt_sdb2 /dev/crypt_sdb2
ln -sf /dev/mapper/crypt_sdc2 /dev/crypt_sdc2
ln -sf /dev/mapper/crypt_sdd2 /dev/crypt_sdd2
ln -sf /dev/mapper/crypt_sdf2 /dev/crypt_sdf2
ln -sf /dev/mapper/crypt_sdg2 /dev/crypt_sdg2

Next set up apt repositories

echo "deb http://be.archive.ubuntu.com/ubuntu/ xenial main universe restricted multiverse
deb http://security.ubuntu.com/ubuntu/ xenial-security universe multiverse main restricted
deb http://be.archive.ubuntu.com/ubuntu/ xenial-updates universe multiverse main restricted
" > /etc/apt/sources.list

And install the bare necessities to get started. Replace ubuntu-minimal with ubuntu-desktop if you are planning to use this system as a desktop computer.

apt-get install mdadm zfs zfs-initramfs grub-pc linux-image-generic ubuntu-minimal
#install grub to all the disks you used for the /boot mdadm RAID
apt-get upgrade
apt-get dist-upgrade

When you see the ncursus window for grub-pc make sure grub uses the ZFS as root and select all your physical disks to install grub on (/dev/sda,/dev/sdb,/dev/sdc,/dev/sdd,/dev/sdf,/dev/sdg). If you didn't get this window you can run:

sudo dpkg-reconfigure grub-pc

undefinedundefinedundefined

Force initramfs and grub update

update-initramfs -k all -c
update-grub

set the root password and exit + unmount everything before rebooting in your new invironment

passwd
exit
umount /mnt/boot
umount /mnt/dev/pts
umount /mnt/dev
umount /mnt/proc
umount /mnt/sys
zfs umount -a
zpool export rpool
reboot
Home ← Older posts