Why you might want to do this

You have installed a Linux OS in a VirtualBox VM and it works well. Now
you want to copy it on a real machine without having to redo the
install. Or perhaps you have a VM that you want to clone to a number of
real machines.

If you have other interesting uses for this technique I would like to
hear about them.

Sorry, as the title says this is for Linux. This technique won't work at
all for Windows. The general principle should work for other Unix-type
OSes but there will be a lot of OS specifc details to adjust.

Prerequisites

This HOWTO assumes familiarity with command line Linux. Also many steps
will not be described in detail. In some places the instructions will
say: make the appropriate choices and adjustments. So an intermediate
level of Linux expertise is required. If you have problems with
particular situations, please post your question to the OpenSUSE forums
under Networking and I will try to help, and any important notes
collected will go into future versions of this HOWTO.

You will need a VirtualBox instance of your Linux OS, of course, a
target machine with a network interface that is reachable by the
VirtualBox host OS. You will also need a LiveCD distro. I often use
Puppy Linux, but other distros like SystemRescueCd or Knoppix could be
used too, depending on the capability of your target machine. The main
requirement of the LiveCD distro used is the presence of the tar and
netcat utilities.

Principle

The principle is simple. We set up a TCP pipe between the VM and the
real machine, hereafter just called RM, and copy the OS over using tar.
Then we fix up things for the OS in its new environment so that it will
boot and run.

Worked example

The process is best illustrated by a real example. The one I will
present is one I actually did: copying a VM installation of AntiX-M8 (a
Mepis/Debian based lightweight distro) to a RM which is an AMD-K6 350MHz
machine with 192MB RAM.

1. Install in VM

First install AntiX-M8 in a VM with the VM specs the same as the target
RM, in this case 192MB. I chose a VDI size of 4GB which is adequate for
this distro. It doesn't matter if your RM has more disk space, you will
see later that the partitions sizes don't have to correspond one-to-one.

Use a unambitious video mode like 1024x768 in the VM. It will help the
video fixup on the RM later.

2. Prepare RM to receive OS

Boot up the RM with Puppy Linux. Set up networking on Puppy Linux. This
involves going into the network wizard, detecting your NIC and getting a
DHCP lease. Note the IP address assigned to the RM. Say for this
example it's 192.168.10.10.

It's recommended that you sync the time roughly on the RM to avoid
warning messages from tar about time skew. Puppy Linux has the rdate
command, but you need a port 37 time server running on your LAN. If you
are doing it by hand, a little ahead of the correct time is better than
a little behind.

Partition the disk with the same partitions as the VM. For AntiX-M8,
there are 3 partitions on the VM:

/dev/hda1 / (3GB, ext3)
/dev/hda2 swap (128MB)
/dev/hda3 /home (750MB, ext3)
Using fdisk on Puppy, create these partitions:

/dev/sda1 / (3GB, ext3)
/dev/sda2 swap (128MB)
/dev/sda3 /home (rest of space, ext3)
Notice a couple of things, we didn't use the same size /home as the RM,
and the partition naming is the SD convention because Puppy is running
Linux 2.6.

Format the ext3 partitions with mke2fs -j and the swap partition with
mkswap.

All this is done from a terminal window on Puppy, if that wasn't clear
already.

3. Mount the partitions on the RM

mkdir /antix
mount /dev/sda1 /antix
mkdir /antix/home /antix/proc /antix/sys
mount /dev/sda3 /antix/home
We mkdir proc and sys because these are not created by the transfer nor
do they contain anything when the system is not running.

4. Start a TCP receiver feeding into tar on the VM

cd /antix
netcat -l -p 2000 | tar ztvf -
This creates a netcat process listening on port 2000 on IP address
192.168.10.10. In some LiveCD distros, netcat is called nc.

The command above is for a dry run. For a real transfer substitute zxvf for ztvf.

5. Run a TCP sender on the VM fed from tar

First shutdown all unused services on the AntiX-M8 VM so that we have as
few files as possible changing during the transfer. It's ok to leave
syslog running. You may lose a recent entry or two from the log file,
but it's not critical.

First of all AntiX-M8 doesn't have netcat installed out of the box. So
we do:

apt-get install netcat
Now we connect outside of the VM using NAT networking in VirtualBox:

cd /
tar zcf - boot etc bin dev home lib media mnt opt root sbin selinux tmp usr var | \
netcat 192.168.10.10 2000
That list of directories is distro dependent. Essentially it's everything
in / except proc and sys.

If you were doing a dry run you should see a list of files scroll past
quickly in the Puppy Linux terminal window. To kill or end the tar
process hit Ctrl-C.

Now start the transfer for real and go away for a tea or coffee.

When it gets to the last file in /var, which you'll have to guess by no
further network or disk activity in the RM for a while, kill the tar and
netcat pipe with Ctrl-C.

Congratulations, you have transferred the files over.

6. Fix up the GRUB bootloader

On the RM now, run grub from the CLI and enter:

device (hd0) /dev/sda
root (hd0,0)
setup (hd0)
That last setup command should print some messages about finding the
GRUB stages and writing the boot block successfully. Exit grub with
"quit".

The real device name is /dev/sda because that's what Puppy Linux calls
the disk, despite AntiX-M8 using /dev/hda when it's running. The (hd0,0)
should be changed as necessary if the root partition is not /dev/hda1.

7. Fix up device paths

Fortunately AntiX-M8 uses device paths like /dev/hda1 in
/boot/grub/menu.lst and /etc/fstab. If not, and your distro uses id or
label paths you will have to edit those files to suit. Finding the right
id or label path is not easy without the target OS running, so I
recommend you use device paths temporarily to get the system up and
running first.

8. Boot the RM

cd /
umount /antix/home /antix
(shutdown Puppy Linux)
(remove Puppy Linux CD and boot off HD)
Go on, it won't spew out smoke. At least I hope not.

9. Fix up networking and video

The NIC on the RM will obviously be different. On udev systems you have
to edit /etc/udev/rules.d/70-persistent-net.rules and change the MAC
address there. Most likely the RM's NIC was detected and assigned eth1.
So delete the rule for eth0 and change the device in the eth1 rule to
eth0.

Fixing up the video is somewhat distro dependent. Hopefully it will
start up in the mode you installed on the VM and then you can tweak it
from there. For OpenSUSE there is the sax2 tool.

10. Variations

As you have seen, the VM and RM partitions don't have to correspond in
size. You can be more ambitions and change the partition layout, say
merge / and /home, or separate / and /home in the RM, or other
earrangements of partitions. But you will have to edit /etc/fstab in
the RM to suit to boot successfully.

11. Caveats

I have noticed with some old distros, e.g. IPCop with Linux 2.4, use
ext3 partitions that don't support some features. For instance to make
an IPCop compatible ext3 FS I had to use:

mke2fs -j -O none,filetype,sparse_super /dev/sda1
That is, we turn off ext3 options, then enable filetype and sparse_super.

You just have to try with your distro and see.

12. More steps?

Did I miss anything?

13. Future

Write the converse HOWTO, cloning a RM to a VM, yes it can be done too.