Using netcat to clone a zfs machine in minimal command lines..
The situation was I had a server that was dying slowly. Freezing under memory and cpu pressure. I purchased two machines. A 3U storage server add a 1U virtualization server to replace it. One of the VMs on my old server was a poudriere buildbox for al my FreeBSD jails and vms. During the course of several weeks I had reconfigured poudriere and re distributed new ssl certs 5 times due to machine crashing and my filesystem getting corrupted. I was tired of configuring poudriere. I found myself in the position of taking a VM and wanting it on bare metal hardware. Further, I was going to be going from a single drive VM to a 4 drive raidz1 configuration so no just DDing the zvol to an external drive.
I wanted to do this over the wire and clone the VM to the new to me server. Yes I could ZFS Send the data and redirect it to a file and move said file over to the new machine on a HDD or USB stick. But I wanted to learn something and have a solution that could work over any TCP/IP link..
I found a writeup on doing zfs send over ssh. But getting ssh working is a pain in the ass on a memory stick “live CD”. Also, I’m always looking for netcat tricks..
I turned my attention to the 1U server. I needed to get a raidz configuration on the drives. But I was aiming for as few command lines as possible, so I cheated.
I did a zfs on root install using a FreeBSD 11.1 flash image. I went about a normal install, selected zfs on root, picked my devices and let the install proceed. This is about making a raidz1 not installing the OS.
I didn’t bother entering anything meaningful in the post install configuration. It’s going away right away anyway.
I reboot with the memory stick, this time choosing ‘live cd’.. To get the zfs volume mounted I do the following:
zpool import -o altroot=/mnt -f zroot
This forces the zfs volume to mount under /mnt on the livecd system.
On the receiving end, I need an IP address, and a server to pipe data to zfs receive..
My ethernet interface is bce0-3. using bce0. enter dhclient:
(Making note of the IP address, you’ll need it in a minute). If you don’t have a dhcp server at the handy, assign a static IP…
Here is the magic:
nc -l 1111 | zfs receive -f zroot
Any port in a storm.. I chose something simple to remember.. (1111). -l is for listen..
We specify -f to force overwriting of the existing data for the install we made earlier.
Now go to the sending machine…
I prepared the VM for cloning by using zfs snapshot..
zfs snapshot -r zroot@clone
I specified -r to get all the datasets on the drive under zroot
Now it’s time to send this thing.
zfs send -R zroot@clone | nc 192.168.1.232 1111
Time will pass, data is flowing very quickly..
When the command prompt comes back your system data is cloned. But it’s still not bootable..
gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada0.
* My boot drive is ada0. You might want to do this for all your drives, in case ada0 dies…
This writes bootcode to ada0 so BIOS can handle it..
This makes the zfs on root boot up happen:
zpool set bootfs=zroot/DEFAULT/root zroot
It’s important to export and import the zroot filesystem so it doesn’t require -f at boot up:
zpool export zroot zpool import zroot
Reboot your system and pull the livecd. You’ve got a cloned system
This will work anywhere you have TCP/IP. You could clone a ZFS endowed VPS over your broadband or WAN.
If you use this successfully give me a shout out. Love hearing from people, also I typed this up from memory, any errata would be greatly appreciated.