Skip to content

Instantly share code, notes, and snippets.

@sickbock
Last active November 6, 2024 16:21
Show Gist options
  • Save sickbock/6b6a5df9a9d2286ebc1a to your computer and use it in GitHub Desktop.
Save sickbock/6b6a5df9a9d2286ebc1a to your computer and use it in GitHub Desktop.
VirtualBox PXE boot
#!/bin/bash
cd ${myVMs}
MyVM=testvm
vboxmanage unregistervm ${MyVM} --delete
rm -rf ${MyVM}
mkdir ${MyVM}
cd ${MyVM}
vboxmanage createhd --filename ${MyVM}.vdi --size 30720
vboxmanage createvm --name ${MyVM} --ostype RedHat_64 --register
vboxmanage modifyvm ${MyVM} --memory 6172 --vram=12 --acpi on --nic1 NAT # optional second NIC # --nic2 bridged --bridgeadapter2 enp0s25
vboxmanage modifyvm ${MyVM} --nictype1 virtio
# optional second NIC # vboxmanage modifyvm ${MyVM} --nictype2 virtio
vboxmanage modifyvm ${MyVM} --boot1 net --boot2 disk --boot3 none --boot4 none # to do PXE boot
# or for normal boot: # vboxmanage modifyvm ${MyVM} --boot1 disk --boot2 net --boot3 dvd --boot4 none
vboxmanage storagectl ${MyVM} --name "SATA Controller" --add sata --controller IntelAHCI
vboxmanage storageattach ${MyVM} --storagectl "SATA Controller" --port 0 --device 0 --type hdd --medium `pwd`/${MyVM}.vdi
default vesamenu.c32
timeout 300
ONTIMEOUT local
display boot.msg
menu resolution 640 480
menu clear
menu title PXE boot menu
LABEL local
menu label Boot from ^local drive
`localboot 0xffff
LABEL Kickstart CentOS 7 x86_64
MENU LABEL ^Kickstart CentOS 7 x86_64
KERNEL vmlinuz
APPEND initrd=initrd.img ks=http://<host IP>/kickstart.cfg ramdisk_size=131072 ip=dhcp lang=en_US keymap=us hostname=mypxetest
# or, if you can not use a webserver or have not yet created your own Kickstart configuration:
#APPEND initrd=initrd.img https://github.com/sickbock/el7_kickstart/raw/master/kickstart-el7-netboot-basic-install.cfg ramdisk_size=131072 ip=dhcp lang=en_US keymap=us hostname=mypxetest

The VirtualBox NAT contains a built-in TFTP and DHCP server that allow you to boot the first interface if you make it a NAT interface.

Define a virtual machine using VirtualBox

E.g. see the create_vm.sh example or use the GUI

VirtualBox configuration

You can boot any OS supported by VirtualBox. In this example we configure SysLinux. Get the required boot files (usually available on Linux, else download from kernel.org)

Create a TFTP root directory in your VirtualBox configuration directory (usually ~/.config/VirtualBox/VirtualBox.xml on Linux or ~/Library/VirtualBox on OS X)

Copy the boot files:

mkdir ~/.config/VirtualBox/TFTP
cd /usr/share/syslinux/
cp pxelinux.0 ldlinux.c32 libcom32.c32 libutil.c32 vesamenu.c32 \
    ~/.config/VirtualBox/TFTP/

create a directory “pxelinux,cfg”

mkdir ~/.config/VirtualBox/TFTP/pxelinux.cfg

creat a menu - see isolinux.cfg or the example on your Linux mirror (when you are done testing, you can set it to network-boot with no timeout for hands free network installation):

vi ~/.config/VirtualBox/TFTP/pxelinux.cfg/default

Copy the kernel and initrd + upgrade images, e.g. from the mounted installation media or from the web, e.g.:

cd ~/.config/VirtualBox/TFTP/
curl -O http://mirror.centos.org/centos/7/os/x86_64/images/pxeboot/vmlinuz
curl -O http://mirror.centos.org/centos/7/os/x86_64/images/pxeboot/initrd.img
curl -O http://mirror.centos.org/centos/7/os/x86_64/images/pxeboot/upgrade.img

The relevant above steps for OS X (translate to Windows speak if you are using that):

cd ~/Downloads
curl -O https://www.kernel.org/pub/linux/utils/boot/syslinux/syslinux-6.03.zip
mkdir ~/syslinux
cd syslinux
unzip -q ~/Downloads/syslinux-6.03.zip
mkdir ~/Library/VirtualBox/TFTP
mv -i bios/com32/lib/libcom32.c32 bios/com32/menu/vesamenu.c32 \
  bios/com32/libutil/libutil.c32 bios/com32/elflink/ldlinux/ldlinux.c32 \
  bios/core/pxelinux.0 ~/Library/VirtualBox/TFTP/
cd
rm -rf syslinux
mkdir ~/Library/VirtualBox/TFTP/pxelinux,cfg
vi ~/.config/VirtualBox/TFTP/pxelinux.cfg/default
cd ~/Library/VirtualBox/TFTP/
curl -O http://mirror.centos.org/centos/7/os/x86_64/images/pxeboot/vmlinuz
curl -O http://mirror.centos.org/centos/7/os/x86_64/images/pxeboot/initrd.img

Virtual machine configuration

To configure a virtual machine to boot creat a link to the pxeboot.0 with the name you used (e.g. $MyVM)

MyVM=testvm
cd ~/.config/VirtualBox/TFTP/ # cd ~/Library/VirtualBox/TFTP/
ln -s pxelinux.0 ${MyVM}.pxe

If needed, reconfigure your VM for network boot using NAT:

vboxmanage modifyvm ${MyVM} --nic1 NAT --nictype1 virtio
vboxmanage modifyvm ${MyVM} --boot1 net --boot2 disk --boot3 none --boot4 none

Now you should be able to boot the VM (and at least show the SysLinux menu and eventually continu with your APPEND line ..)

vboxmanage startvm ${MyVM}

Or, as soon as you have automated everything:

vboxheadless --startvm ${MyVM}

Post install VirtualBox configurations

For most of these configurations your virtual machine needs to be off line:

vboxmanage controlvm ${MyVM} acpipowerbutton

Boot configuration: The localboot item in the sample menu is a bit redundand when using VirtualBox since this hypervisor refuses to honour such a request! Nothing changed since 2008! Only thing you can do is change your boot order again after installation (if this is not done by VirtualBox) e.g.:

vboxmanage modifyvm ${MyVM} --boot1 disk --boot2 dvd --boot3 none --boot4 none

NAT: With the NAT configuartion on just one interface the virtual machine can reach the outside world but you cannot access it directly from your host. A neat trick is to assign the machine an address on your loopback network:

  • Get the next available 127.0.0.* address from your /etc/hosts (or windows equivalent)
  • Add the name your want to use with that address to your /etc/hosts
  • Configure portforwarding e.g. forward ssh to listen on 127.0.0.4:2222 for your "third" VM in /etc/hosts

Implement the portforwarding rule and, add the VM to your /etc/hosts, start your VM and use the rule

vboxmanage modifyvm ${MyVM} --natpf1 "ssh,tcp,127.0.0.4,2222,,22"
echo "127.0.0.4 ${MyVM}" >> /etc/hosts
vboxmanage startvm ${MyVM}
ssh -p 2222 root@${MyVM}

NB: the fifth field could contain the guest's IP addres. Leave it blank to use the DHCP address.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment