Introduction

Ghost4Linux (or more accurately, GhostInLinux) is a collection of scripts, programs and kernel modules for network booting Norton Ghost on a given target machine and backing up or restoring that machine. It is built from a net booting Linux, which runs DosEmu, the DOS emulator for Linux, which in turn runs Norton Ghost with the appropriate options. It then automatically chooses the first drive and writes out its contents to an image. The image directory is a separate NFS file system, including a different machine. The overall result is a backup/restore system for NTFS and FAT file systems that can backup to/restore from a NFS file server.

What is required

1. The client machines must be PXE boot capable, with modern on board NICs this is not normally a problem as the boot rom is a bios option.

2. The server side of the above, a dhcp server and tftp server. The backup trigger script must have access to (and the ability to restart) the dhcpd server.

3. Need to prepare a Linux system that can be remotely booted. In my case a copy of my firewall machine was a good starting point.

4. Need to prepare a working bootable Ghost floppy, as I can't supply you with one. Norton Ghost 2003 is known to work. Ghost V8 is known to die shortly after starting ghost. Linux is used for the networking, so this only needs to know about hard drives, not dos network stacks. This is modified to take advantage of it running under emulation.

5. Minor but very essential programs like ether-wake and ethtool.

General idea

The overall idea is to use Linux for its network stack and general scripting capabilities to run a complete diskless system. It is only really diskless from the point of view of Linux, any harddisk in the system is a data sink or source that Linux itself does not care about. Once booted, we can then have a script run DosEmu, which can then be setup to autorun Ghost and backup the drive to image files.

The devil here is in the details: changing the dhcpd config so the system normally boots its HD based OS, but then loads the remote Linux system when required; checking the machine has started, and then changing the dhcpd config back to allow the user to boot into the native OS.

1.1. PXE on the client side

The client needs to have PXE capable boot rom, which allows it to boot without local data on the HD, or even a HD at all. If the motherboard has an on-board NIC, chances are there is a 'Boot ROM' option next to the 'Enable LAN' option. The boot order also needs changing so LAN is first, and a local harddisk is second.

1.2. dhcpd

The dhcpd configuration is all in /etc/dhcpd.conf, using the standard RedHat distro DHCP server (Written by Ted Lemon for Vixie Labs, ISC). The layout follows the form:
default-lease-time 86400;
max-lease-time 86400;
option routers 192.168.7.1;
option domain-name-servers 192.168.7.1;
option domain-name "flint";
option subnet-mask 255.255.255.128;
option broadcast-address 192.168.7.127;

subnet 192.168.7.0 netmask 255.255.255.128 { range 192.168.7.64 192.168.7.126 ; }
host john { fixed-address 192.168.7.100; hardware ethernet 00:01:80:5C:37:D4; filename "nobackup"; }
host joe { fixed-address 192.168.7.15; hardware ethernet 00:20:ED:6F:30:61; filename "nobackup"; }
host linuxbox { fixed-address 192.168.7.10; hardware ethernet 00:01:80:53:FA:A6; filename "nobackup"; }
host fakebox { fixed-address 192.168.7.10; hardware ethernet 01:80:53:FA:A6:00; filename "pxelinux.0"; }

The layout of the last four lines is important, the backup script changes the "nobackup" filename to "pxelinux.0" as the first step into booting Linux remotely. The host name, IP, MAC address and filename must be valid as the backup script uses all these details at some point. The other lines are free format as far as the backup is concerned, and obviously must be adapted to your scenario.

Under normal operation, the client machine will boot up, DHCP would reply with the "nobackup" name, and the PXE boot would fail and then boot the local HD. When the backup script is run, it changes the dhcpd.conf, restarts the dhcpd daemon and sends a wake up packet to the MAC. The machine will then power on, boot the pxelinux.0 image (the next step), and meanwhile the script changes the dhcpd server back to "nobackup". The script creates a lock file so there are no race conditions when changing the daemon configuration.

1.3. tftp

PXE uses the tftp protocol to fetch files from the server. The setup here used the HP tftp server (tftp-hpa), not the RedHat supplied server. The backup script assumes the base path is /tftpboot , which is normally the default.

1.4. SYSLinux

The PXE boot process needs a loader to boot the Linux kernel, which is also an opportunity to pass arguments to the kernel. We use the same options for all machines (/tftpboot/pxelinux.cfg/default):
DEFAULT vmlinuz IPAPPEND 1
APPEND root=/dev/nfs nfsroot=192.168.7.1:/home/pxe/,wsize=8192,rsize=8192,hard,intr ip=dhcp

PXELinux (part of SYSLinux) passes these options to the kernel found at /tfptboot/vmlinuz, so just remember when building a new kernel to update this copy of the kernel too.

2. Setting up a bootable Linux system.

When each backup client boots, its root directory is a directory on the server. The root needs to contain all the usual startup software that will allow it to boot up, startup networking (which is somehow separate from the NFS root that will already be running) and mount the backup image NFS mount. For debugging, a working ssh daemon might also be useful.

For my base system I used my firewall machine, which is a RedHat 7.3 install with many small additions and a kernel.org kernel. This was simply copied to a subdirectory of the same machine, /home/pxe, which is the NFS root. The bash was something like:
cd /
mkdir /home/pxe
find / | grep -v "^/home/pxe/" | cpio -padmu /home/pxe/

Some of the large and unnecessary installed software, such as the browser and Java were then deleted. How much time you want to spend removing software is up to you, storage costs being what they are, there is no real point in deleting anything.

At this point it might be worth changing the root (chroot /home/pxe ; passwd), and setting the run level to 3 (vi /etc/inittab). Note, 'chroot /home/pxe' is a handy way of working on the NFS root.

3 Preparing a bootable Linux

3.1

Look at the NFS ROOT HOWTO for the details. In short, configure the kernel for an i386 processor (or the lowest common denominator) with IP auto configuration and NFS ROOT enabled and built into the kernel. Also, build into the kernel the NFS client options and the network cards. Modules are a bad idea for anything but optional extras. Your new kernel should be copied to this directory in /home/pxe/boot and to the /tftpboot directory.

3.2

Setup /etc/fstab to use the NFS drives as root and as the /backup mount point, which will later be used by Ghost. In my case this looks like:
PXEADDR:PXEBASE    /                nfs     wsize=8192,rsize=8192,hard,intr     0 0
none               /dev/pts         devpts  gid=5,mode=620  0 0
proc               /proc            proc    defaults        0 0
tmpfs              /tmp             tmpfs   size=128m       0 0
tmpfs              /var/tmp         tmpfs   size=128m       0 0
GHSTNFS            /backup          nfs  rsize=8192,wsize=8192,hard,intr,tcp  0 0

Where PXEADDR:PXEBASE refers to the NFS server and where on that machine the root can be found. GHSTNFS refers to the NFS server for backup images, it can be different to the PXE server. In my case, PXEADDR is 192.168.7.1 (my firewall and dhcp server) and PXEBASE is /home/pxe. As we need to modify the dhcpd configuration and restart dhcpd, the backup scripts need to be on that machine. GHSTNFS (192.168.7.9:/home/backup) is the file server, so it has storage space but nothing else.

Note also the use of tmpfs for temporary storage. The key words PXEADDR, PXEBASE and GHSTNFS are edited by the server side scripts, the actual values from the configuration file.

3.3

When a backup operation is started, separate directories are created for /etc and /var, this is the minimum necessary change. But, as we need those directories at boot time, it is a little awkward to create extra mount points and have separate /etc and /var mounted after / has been mounted. The solution is to use the --bind option of mount. The separate directories created by the backup script are in a directory accessible via the NFS mount of /home/pxe and called <client ip>/etc and <client ip>/var.

Consequently, the moment /etc/rc.sysinit is read, it is reading the original /home/pxe/etc/rc.sysinit. But, we add the lines:
echo "Binding custom /var and /etc"
ADDR=`/sbin/ifconfig eth0 | grep "inet addr:" | sed "s/.*inet addr: *\([0-9\.][0-9\.]*\) .*/\1/"`
mount --bind /${ADDR}etc /etc
mount --bind /${ADDR}var /var

just after / is remounted read/write.

So by the time rc.sysinit runs anything that will daemonise etc, it will be running from a now distinct /etc and /var.

3.4

The net effect of these steps should be a Linux system that operates entirely over NFS and uses around 50 megabytes for its individual /etc and /var. You should also have /backup available over NFS. You should check it all works as expected, Ghost needs all this to be setup.

4 Preparing Ghost

4.1 Setup DOSEmu

Download a copy of DOSEmu from http://www.dosemu.org/, I used version 1.2.1 (stable) and then version 1.2.2 (stable), both without problems. It should be installed as root, for root, into /home/pxe (chroot into /home/pxe before building it).

4.2 Make a template boot disk

My boot disk uses MS-DOS as created by a Windows 98 machine. I've had reports of FreeDOS working. Format a bootable (with system files) floppy in Win98. Once you have a bootable disk (floppies being what they are, check that it works), create an image file of it with:
dd if=/dev/fd0 bs=512 of=/home/pxe/root/.dosemu/ghost.img

The correct path is important as all the scripts and DOSEmu asssume the image will be there.

4.3 Edit the boot disk

Mount the boot disk with:
mount -o loop /home/pxe/root/.dosemu/ghost.img /mnt/floppy
and edit AUTOEXEC.BAT to look like:
@echo off
SET TZ=GHO+00:00
rem MOUSE.COM
echo Adding NFS dir as drive
lredir z: LINUX\FS\backup\BackUpName\
echo Loading...
CD GHOST
echo > z:\BackUpName.sta
BackUpCommand
type a:ghosterr.txt >> z:\BackUpName.end
echo Ghost exited >> z:\BackUpName.end
a:\exitemu


The backup script creates individual boot disk images, and so BackUpCommand and BackUpName are replaced with the real command and name when needed.

You also need to copy some files to the boot disk, namely those used above (exitemu, lredir) to /mnt/floppy and GHOST.EXE (I used Norton Ghost 2003) to /mnt/floppy/ghost/.

When done, unmount the image with:
umount /mnt/floppy

4.4 Edit the DOSEmu config file

DOSEmu needs some configuration options to be set. These are:
$_cpu = "80586"
$_rdtsc = (on)
disk {wholedisk "/dev/hda"}


Although I've not tested it much, I suspect the $_cpu should match your kernel. With a 386 kernel, $_cpu = "80386" was stable, but then compiling a 586 kernel I had to also use $_cpu = "80586" to remain stable. The only symptom was hanging at one of a random few points during an image dump.

The _rdtsc line was added while testing for the processor issue. As we only use 586 or more processors, it seems like a good idea.

The wholedisk option lets Ghost see the real HD as a real HD. Contrary to the docs, this option is supported, they just consider it such a security risk that it is left undocumented. We want unrestricted access to the harddisk, so their security risk is our essential feature.

5.0 Other bits

5.1 Kernel module

When Ghost loads, it normally ask "Mark these drives as Ghost?". It does this even when run in batch mode, so is a small problem for our purposes as nobody will be there to select "Don't mark as Ghost". DOSEmu provides some options for sending key presses to the running program, but unfortunately they don't work with Ghost. This kernel module does the job instead, it sends key presses as if they were pressed on the keyboard, not far above the level of keyboard interrupt.

The source for the module is sendscancode.c. It can be compiled with:
chroot /home/pxe
cd /root
gcc -nostdinc -I/usr/src/linux/include -I/usr/lib/gcc-lib/i686-pc-linux-gnu/3.2.3/include sendscancode.c -c -o sendscancode.o
cp sendscancode.o /lib/modules/2.4.27/kernel/drivers/input/
depmod -ra

# and ignore the symbols msg

insmod sendscancode thechar=0xf ; sends a tab

It will probably be obvious that I don't really know how to write kernel modules. This is good enough, as it works and doesn't do anything bad for your health. If somebody knows how to program a module and wants to give me a better solution, I'd be happy to accept it.

5.2 Screen dump

As the backup/restore process will be left unattended, I thought it would be a good idea to have some log. The best way forward here was a screen dump of the running Ghost. The program rdvga.c does just that and is used by the client side scripts to keep a short recent history of what the screen looked like. It is in black and white, but it gives the general idea. Compile with:
gcc -Wall rdvga.c -o /home/pxe/root/rdvga

It will also be obvious that this is a massive hack and only works because ancient backward compatibility is still supporting an MGA screen (I /think/ thats why it works). It has been tested with recent Nvidia graphics cards and old cards of various makers.

A better solution would be using a kernel module to save out the real video memory, as it exists outside of user mode address space. If you know how to do that and send me a solution, I'd be happy to accept it.

5.3 etherwake and miitools

You also need the etherwake program (for sending magic wake up packets) and the miitools package, which contains ethtool that is essential for setting up a NIC to remote wake up. etherwake is used on the server side, so needs to be accessible there. ethtool is used on the client side, so needs to be accessible to /home/pxe.

5.4 netmon

This program monitors the rate of traffic flow ever a network connection. The main client side script uses this to detect problems during the Ghosting process. Its source is available here. As this is run by the client, it needs to be in (say) /home/pxe/bin.

6 The controlling bash scripts

The last few sections have described the programs and configuration that need to be present. This section talks about the high level scripts that pull it together.

6.1 Client side

There are two additional scripts on the client side, a modified /home/pxe/etc/rc.local which has this appended to the end:
# enable WOL for next time
/usr/local/sbin/ethtool -s eth0 wol g

# identify the name of the machine, as found in /etc/dhcpd.conf
MAC=`ifconfig eth0 | grep HWaddr | head -n 1 | sed "s/.*HWaddr //"`
BACKUP=`grep -i $MAC /etc/dhcpd.conf | head -n 1 | sed "s/^host  *\([^ ]*\) .*$/\1/"`

# start the script that runs and then monitors Ghost
export BACKUP
(
sleep 10
export BACKUP
/etc/init.d/ghost start
) &


Also on the client side is the main script that runs and then monitors Ghost. Obviously it needs to go in /home/pxe/etc/init.d because the above script expects it to be there. This script does all the real work of supporting Ghost, so chances are, if you miss something out then it will break here. It is this script that:
1. Copies /root/.dosemu/ghost.img to /root/.dosemu/ghost-<client hostname>.img and modifies the copy for use on this client.
2. Runs DOSEmu and points it at the new boot disk image.
3. Runs the key press simulation to skip the "Mark drives as Ghost?" message.
4. Monitors the network and hard drive access statistics for signs of a trouble, which can be implied by there being very little data flow on the network card or hard drive.
5. Takes screen shots at 1 minute intervals.
And finally,
6. If Ghost quits, for whatever reason, or the statistics indicate trouble, the machine is shutdown.

6.2 Server side

The server side scripts are fairly simple, as their main goals are:

1. Modify /etc/dhcpd.conf to boot Linux remotely rather than whatever is on the local harddisk.
2. Create copies of /home/pxe/{etc,var} called /home/pxe/<client IP>{etc,var}
3. Create the directories for the backup images and screen dumps.
4. Wake up the machine.
5. Undo the changes made to /etc/dhcpd.conf, so the machine now boots locally.
6. Make sure the machine came up, and then wait for it to shut down.

The server side scripts go in /home/pxe/root, but that is just to keep the ghost4linux system together in one place. The scripts are backup.sh, verify.sh, test.sh ghost.sh and restore.sh. But for test.sh and ghost.sh, the meaning of each is obvious. test.sh uses all the same mechanisms to bring up the machine, but doesn't run Ghost. Instead the machine is left running for an hour, giving you the chance to ssh into it and do whatever you like. Killing the running 'sleep 3600' will then shut down the machine within 20 seconds.

ghost.sh also brings up the machine using all the same mechanisms, but runs Ghost with no parameters. This gives you the chance to fiddle with the user interface (ie do a disk to disk copy) without using any boot media.

All the scripts and programs are available here: ghost4linux-1.1.tar.gz

The scripts use a config file /etc/ghostrc to find the right paths. The client also uses this file, so it is copied into /home/pxe/etc by the server side scripts. The config file looks like this:
#!/bin/bash

# IP and path to NFS mounted Linux client
PXEADDR=192.168.7.1
PXEBASE=/home/pxe/

# These two must be the same place or bad things will happen
GHSTBASE=/net/backup/    # image path rel to server
GHSTNFS=192.168.7.9:/home/backup/   # image path when mounted over NFS

# paths
DHCPD=/etc/init.d/dhcpd
ETHERWAKE=/sbin/ether-wake

and obviously needs to be edited for your environment.

To use, you would run:
cd /home/pxe/root
./backup.sh john
./verify.sh john

which should do everything required to backup the machine called john to the file server and then shut down john. The final line would use john to verify the image on the file server and then shut down john.

7.0 Other issues

Note that some ditributions will use different paths, or slightly different names for executables. ether-wake is the standard name, but under Debian it is etherwake. Also, RedHat's dhcpd startup script is /etc/init.d/dhcpd, but under Debian it is /etc/init.d/dhcp. The config file /etc/ghostrc is there to account for these differences.

The End

That should be all you need. If you want more explanation or have ideas, email me on greg at csc liv ac uk.

Ideally all this messing about could be reduced to a patch set agaisnt a small linux distribution. As this is a reasonably large amount of extra work, I'll only do it if several people ask.

History

23/8/2005
  Initial release of complete HOWTO.

26/8/2005
  Fixed some small typos. Added history and license sections.

17/11/2005
  DOS limitations meant using hostnames as filenames broke too easily. As far as DOS is concerned, have now avoided all use dynamic filenames.
  Fixed broken links.
  Added link to tar ball containing all the scripts, calling it V1.1

22/2/2008
  Clayton Craft pointed out a typo, Ghost V8 does not work with DosEmu.

License

This documentation is released under GNU FDL Version 1.2 or later. The programs are released under the GNU GPL.


Last changed 17/11/2005.