Difference between revisions of "Diskless network boot NBD root"

From ArchWiki
Jump to: navigation, search
m (kernel 3.0 kernel and initrd name changes)
(Server-Side Setup: added lots of Template:ic updated install stuff to better comply with new style guide; removed tons of <pre> tags)
Line 11: Line 11:
 
==Server-Side Setup==
 
==Server-Side Setup==
 
===Install syslinux===
 
===Install syslinux===
The syslinux package will be needed later for the boot configuration:
+
The {{Pkg|syslinux}} package will be needed later for the boot configuration.
<pre>
+
 
pacman -S syslinux
+
</pre>
+
 
===Create the NBD File and Boot Directory===
 
===Create the NBD File and Boot Directory===
 
Create a directory that will hold the boot directory and the NBD file.
 
Create a directory that will hold the boot directory and the NBD file.
<pre>
+
mkdir -p /nbd/boot/
mkdir -p /nbd/boot/
+
 
</pre>
+
Next, create the actual file that will be shared via NBD. Of course you can also use an actual block device (a hard drive) instead of creating a file on your filesystem. Just replace {{ic|/nbd/root}} with the block device.
Next, create the actual file that will be shared via NBD. Of course you can also use an actual block device (a hard drive) instead of creating a file on your filesystem. Just replace /nbd/root with the block device.
+
 
In this example we are going to create a file with a size of 5GB.
 
In this example we are going to create a file with a size of 5GB.
<pre>
+
dd if=/dev/zero of=/nbd/root bs=1M count=5000
dd if=/dev/zero of=/nbd/root bs=1M count=5000
+
 
</pre>
+
 
Now you can create a filesystem on the file.
 
Now you can create a filesystem on the file.
<pre>
+
mkfs.ext4 /nbd/root
mkfs.ext4 /nbd/root
+
 
</pre>
+
mkfs will show you warning about the fact that the file is no actual block device. You can ignore this and simply press {{Keypress|y}} to continue.
mkfs will show you warning about the fact that the file is no actual block device. You can ignore this and simply press y to continue.
+
  
 
Alternatively, if you want to create an encrypted NBD device:
 
Alternatively, if you want to create an encrypted NBD device:
<pre>
+
cryptsetup luksFormat -s 256 /nbd/root
cryptsetup luksFormat -s 256 /nbd/root
+
cryptsetup luksOpen /nbd/root nbdcrypt
cryptsetup luksOpen /nbd/root nbdcrypt
+
mkfs.ext4 /dev/mapper/nbdcrypt
mkfs.ext4 /dev/mapper/nbdcrypt
+
 
</pre>
+
{{Note|Be aware that the rest of the article will use {{ic|/nbd/root}}. If your NBD file is encrypted,  
{{note|Be aware that the rest of the article will use /nbd/root. If your NBD file is encrypted,  
+
replace it with {{ic|/dev/mapper/nbdcrypt}}, if you use an actual block device, with {{ic|/dev/sdX}}.}}
replace it with /dev/mapper/nbdcrypt, if you use an actual block device, with /dev/sdX.}}
+
  
 
===Install ArchLinux on the NBD filesystem===
 
===Install ArchLinux on the NBD filesystem===
 
Mount the filesystem:
 
Mount the filesystem:
<pre>
+
mount /nbd/root /mnt
mount /nbd/root /mnt
+
 
</pre>
+
 
Now follow the instructions [[Diskless network boot NFS root#Create Client Root Directory|here]], but be aware of three things:
 
Now follow the instructions [[Diskless network boot NFS root#Create Client Root Directory|here]], but be aware of three things:
# make sure you use /mnt instead of /disklessroot
+
# make sure you use {{ic|/mnt}} instead of {{ic|/disklessroot}}
# you are going to have to install the mkinitcpio-nbd package from AUR before recreating the kernel image (see below)
+
# you are going to have to install the {{AUR|mkinitcpio-nbd}} package from the [[Arch User Repository|AUR]] before recreating the kernel image (see below)
# the editing of /mnt/etc/mkinitcpio.conf is different for NBD (see below)
+
# the editing of {{ic|/mnt/etc/mkinitcpio.conf}} is different for NBD (see below)
 +
 
 
====Installing mkinitcpio-nbd====
 
====Installing mkinitcpio-nbd====
Download [http://aur.archlinux.org/packages.php?ID=50479 mkinitcpio-nbd] from the AUR, move the package to /mnt and install it with:
+
Download {{AUR|mkinitcpio-nbd}} from the [[Arch User Repository|AUR]], move the package to {{ic|/mnt}} and install it with:
<pre>
+
chroot /mnt
chroot /mnt
+
pacman -U mkinitcpio-nbd-[...].tar.xz
pacman -U mkinitcpio-nbd-[...].tar.xz
+
exit
exit
+
 
</pre>
+
 
====Editing mkinitcpio.conf====
 
====Editing mkinitcpio.conf====
Set the following hook list in /mnt/etc/mkinitcpio.conf:
+
Set the following hook list in {{ic|/mnt/etc/mkinitcpio.conf}}:
<pre>
+
HOOKS="base udev net nbd filesystems"
HOOKS="base udev net nbd filesystems"
+
 
</pre>
+
 
If you use an encrypted NBD device, use this:
 
If you use an encrypted NBD device, use this:
<pre>
+
HOOKS="base udev net nbd usbinput keymap encrypt filesystems"
HOOKS="base udev net nbd usbinput keymap encrypt filesystems"
+
 
</pre>
+
 
Then continue with the instructions about recreating the kernel image in the NFS article.
 
Then continue with the instructions about recreating the kernel image in the NFS article.
  
After leaving the chroot, the kernel image will be in /mnt/boot/. We are going to need it in /nbd/boot:
+
After leaving the chroot, the kernel image will be in {{ic|/mnt/boot/}}. We are going to need it in {{ic|/nbd/boot}}:
<pre>
+
cp /mnt/boot/vmlinuz-linux /nbd/boot/
cp /mnt/boot/vmlinuz-linux /nbd/boot/
+
cp /mnt/boot/initramfs-linux.img /nbd/boot/
cp /mnt/boot/initramfs-linux.img /nbd/boot/
+
 
</pre>
+
 
====Editing rc.conf====
 
====Editing rc.conf====
Make sure you set NETWORK_PERSIST="yes" and your own settings in /mnt/etc/rc.conf. You will also have to remove/disable the network daemon. The net hook will set the IP on boot, so there is no point in using it. Additionaly, if you would change your IP with the network daemon, the connection to the root device would break. If you want a static IP, use the ip kernel parameter (see [[Diskless network boot NBD root#Boot Configuration|Boot Configuration]]).
+
Make sure you set {{ic|1=NETWORK_PERSIST="yes"}} and your own settings in {{ic|/mnt/etc/[[rc.conf]]}}. You will also have to remove/disable the network daemon. The net hook will set the IP on boot, so there is no point in using it. Additionaly, if you would change your IP with the network daemon, the connection to the root device would break. If you want a static IP, use the ip kernel parameter (see [[Diskless network boot NBD root#Boot Configuration|Boot Configuration]]).
 +
 
 +
You should also edit {{ic|/mnt/etc/locale.gen}} and make sure your locales are enabled.
  
You should also edit /mnt/etc/locale.gen and make sure your locales are enabled.
 
 
===Configuring the NBD server===
 
===Configuring the NBD server===
nbd-server is supposed to be configured with the config file /etc/nbd-server/config, but [https://bbs.archlinux.org/viewtopic.php?id=121956 this doesn't seem to work] at the moment. Instead, you have to start NBD manually:
+
nbd-server is supposed to be configured with the config file {{ic|/etc/nbd-server/config}}, but [https://bbs.archlinux.org/viewtopic.php?id=121956 this does not seem to work] at the moment. Instead, you have to start NBD manually:
<pre>
+
nbd-server -C " " 10809 /nbd/root
nbd-server -C " " 10809 /nbd/root
+
 
</pre>
+
 
You can choose whatever port number you want, you will just have to set it right in the [[Diskless network boot NBD root#Boot Configuration|Boot Configuration]].
 
You can choose whatever port number you want, you will just have to set it right in the [[Diskless network boot NBD root#Boot Configuration|Boot Configuration]].
 
By default, nbd-server will start the share with read/write support. If you have more than one client you want to boot from, this will break your filesystem (see [[Diskless network boot NBD root#Updating the Client System|Updating the Client System]] for details).
 
By default, nbd-server will start the share with read/write support. If you have more than one client you want to boot from, this will break your filesystem (see [[Diskless network boot NBD root#Updating the Client System|Updating the Client System]] for details).
  
You could enable read-only mode (-r) but this is not recommended because there are just too many things that want to write to /var, /etc or other directories. You could partially work around this with tmpfs, but some things might still break.
+
You could enable read-only mode ({{ic|-r}}) but this is not recommended because there are just too many things that want to write to {{ic|/var}}, {{ic|/etc}} or other directories. You could partially work around this with tmpfs, but some things might still break.
  
Another interesting option is NBD's "copy on write"-mode (-c). From the [http://linux.die.net/man/1/nbd-server manual]:
+
Another interesting option is NBD's "copy on write"-mode ({{ic|-c}}). From the [http://linux.die.net/man/1/nbd-server manual]:
<pre>
+
{{bc|"When this option is provided, write-operations are not done to the exported file, but to a separate file.  
"When this option is provided, write-operations are not done to the exported file, but to a separate file.  
+
 
This separate file is removed when the connection is closed, which means that serving this way will make  
 
This separate file is removed when the connection is closed, which means that serving this way will make  
 
nbd-server slow down (especially on large block devices with lots of writes), and that after disconnecting
 
nbd-server slow down (especially on large block devices with lots of writes), and that after disconnecting
and reconnecting the client or the server, all changes are lost."
+
and reconnecting the client or the server, all changes are lost."}}
</pre>
+
 
 
It has not been tested yet how much this really affects performance, but if you want to boot from multiple clients, this is probably your best option.
 
It has not been tested yet how much this really affects performance, but if you want to boot from multiple clients, this is probably your best option.
 +
 
===PXE/TFTP Setup===
 
===PXE/TFTP Setup===
Follow the instructions [[Diskless network boot NFS root#PXE/TFTP Setup|here]]. Just make sure you use /nbd/boot/ instead of /disklessroot/boot/ for the TFTP-Root.
+
Follow the instructions [[Diskless network boot NFS root#PXE/TFTP Setup|here]]. Just make sure you use {{ic|/nbd/boot/}} instead of {{ic|/disklessroot/boot/}} for the TFTP-Root.
 +
 
 
==Boot Configuration==
 
==Boot Configuration==
 
Copy the pxelinux.0 boot file from syslinux to /nbd/boot and create the pxelinux.cfg directory:
 
Copy the pxelinux.0 boot file from syslinux to /nbd/boot and create the pxelinux.cfg directory:

Revision as of 18:29, 14 November 2011

Boot from a NBD root device

This article will explain how to boot an ArchLinux Installation from a Network Block Device (NBD).

Much of the work to be done is based on the article Diskless network boot NFS root, so this will be referenced several times within the article.

Advantages over NFS

The main advantages are that NBD is faster and that you can boot from an encrypted or LVM-based NBD root device. One disadvantage is that you cannot easily update your kernel from within the running diskless client, although there is a workaround for this.

Server-Side Setup

Install syslinux

The syslinux package will be needed later for the boot configuration.

Create the NBD File and Boot Directory

Create a directory that will hold the boot directory and the NBD file.

mkdir -p /nbd/boot/

Next, create the actual file that will be shared via NBD. Of course you can also use an actual block device (a hard drive) instead of creating a file on your filesystem. Just replace /nbd/root with the block device. In this example we are going to create a file with a size of 5GB.

dd if=/dev/zero of=/nbd/root bs=1M count=5000

Now you can create a filesystem on the file.

mkfs.ext4 /nbd/root

mkfs will show you warning about the fact that the file is no actual block device. You can ignore this and simply press Template:Keypress to continue.

Alternatively, if you want to create an encrypted NBD device:

cryptsetup luksFormat -s 256 /nbd/root
cryptsetup luksOpen /nbd/root nbdcrypt
mkfs.ext4 /dev/mapper/nbdcrypt
Note: Be aware that the rest of the article will use /nbd/root. If your NBD file is encrypted, replace it with /dev/mapper/nbdcrypt, if you use an actual block device, with /dev/sdX.

Install ArchLinux on the NBD filesystem

Mount the filesystem:

mount /nbd/root /mnt

Now follow the instructions here, but be aware of three things:

  1. make sure you use /mnt instead of /disklessroot
  2. you are going to have to install the mkinitcpio-nbdAUR package from the AUR before recreating the kernel image (see below)
  3. the editing of /mnt/etc/mkinitcpio.conf is different for NBD (see below)

Installing mkinitcpio-nbd

Download mkinitcpio-nbdAUR from the AUR, move the package to /mnt and install it with:

chroot /mnt
pacman -U mkinitcpio-nbd-[...].tar.xz
exit

Editing mkinitcpio.conf

Set the following hook list in /mnt/etc/mkinitcpio.conf:

HOOKS="base udev net nbd filesystems"

If you use an encrypted NBD device, use this:

HOOKS="base udev net nbd usbinput keymap encrypt filesystems"

Then continue with the instructions about recreating the kernel image in the NFS article.

After leaving the chroot, the kernel image will be in /mnt/boot/. We are going to need it in /nbd/boot:

cp /mnt/boot/vmlinuz-linux /nbd/boot/
cp /mnt/boot/initramfs-linux.img /nbd/boot/

Editing rc.conf

Make sure you set NETWORK_PERSIST="yes" and your own settings in /mnt/etc/rc.conf. You will also have to remove/disable the network daemon. The net hook will set the IP on boot, so there is no point in using it. Additionaly, if you would change your IP with the network daemon, the connection to the root device would break. If you want a static IP, use the ip kernel parameter (see Boot Configuration).

You should also edit /mnt/etc/locale.gen and make sure your locales are enabled.

Configuring the NBD server

nbd-server is supposed to be configured with the config file /etc/nbd-server/config, but this does not seem to work at the moment. Instead, you have to start NBD manually:

nbd-server -C " " 10809 /nbd/root

You can choose whatever port number you want, you will just have to set it right in the Boot Configuration. By default, nbd-server will start the share with read/write support. If you have more than one client you want to boot from, this will break your filesystem (see Updating the Client System for details).

You could enable read-only mode (-r) but this is not recommended because there are just too many things that want to write to /var, /etc or other directories. You could partially work around this with tmpfs, but some things might still break.

Another interesting option is NBD's "copy on write"-mode (-c). From the manual:

"When this option is provided, write-operations are not done to the exported file, but to a separate file. 
This separate file is removed when the connection is closed, which means that serving this way will make 
nbd-server slow down (especially on large block devices with lots of writes), and that after disconnecting
and reconnecting the client or the server, all changes are lost."

It has not been tested yet how much this really affects performance, but if you want to boot from multiple clients, this is probably your best option.

PXE/TFTP Setup

Follow the instructions here. Just make sure you use /nbd/boot/ instead of /disklessroot/boot/ for the TFTP-Root.

Boot Configuration

Copy the pxelinux.0 boot file from syslinux to /nbd/boot and create the pxelinux.cfg directory:

cp /usr/lib/syslinux/pxelinux.0 /nbd/boot/
mkdir /nbd/boot/pxelinux.cfg/

Now create and edit /nbd/boot/pxelinux.cfg/default, which contains the boot configuration for the client. Replace the value for nbd_server with the IP and Port your NBD server will be running on.

default linux

label linux
kernel vmlinuz-linux
append initrd=initramfs-linux.img ip=::::::dhcp nbd_server=192.168.0.1:10809 root=/dev/nbd0

See here for details about the ip option.

If your NBD device is encrypted, use the following append line instead:

append initrd=initramfs-linux.img ip=::::::dhcp nbd_server=192.168.0.1:10809 cryptdevice=/dev/nbd0:nbdcrypt root=/dev/mapper/nbdcrypt

Testing

Before you boot your client, make sure you unmount everything on the server:

umount /mnt/proc /mnt/sys /mnt/dev /mnt

If your NBD device is encrypted, close the LUKS device as well:

cryptsetup luksClose nbdcrypt

Using a Swap Partition

Although this has not been tested yet, you should be able to do this by creating a LVM volume group on /dev/nbd0 that contains the root and swap partition and adding lvm2 before the filesystems hook in /mnt/etc/mkinitcpio.conf.

Updating the Client System

Quote from the NBD homepage:

"[...] if someone has mounted NBD read/write, you must assure that no one else will have it mounted."

In other words, if you want to be able to update from your client system, you have to make sure that the NBD device is not mounted on any other system, not even read-only. If your NBD device is encrypted, make sure to not just unmount it, but also close it with 'cryptsetup luksClose'. Otherwise, you may break your filesystem. If you keep that in mind, everything except kernel updates should work fine.

Alternatively you can mount the NBD device on the server and then update it (again, make sure it is not mounted anywhere else!):

mount /nbd/root /mnt
# proc, dev and sys should only neccessary for kernel upgrades, but just in case...
mount -t proc none /mnt/proc
mount -t sysfs none /mnt/sys
mount -o bind /dev /mnt/dev
chroot /mnt
pacman -Syu
exit
umount /mnt/proc /mnt/sys /mnt/dev /mnt

Kernel Updates

Since the kernel the client system boots from is on the server and not in the NBD device itself, you will not be able to simply update your kernel with pacman. There are several other ways to do this:

  • If you update from the client system:
    • share /nbd/boot on the server via NFS, mount it to /boot and then update your kernel
    • copy vmlinuz-linux and initramfs-linux.img from /boot back to the server to /nbd/boot after the kernel update
  • if you update from the server:
    • copy vmlinuz-linux and initramfs-linux.img from /mnt/boot to /nbd/boot after the kernel update

Known Problems

Resume from Suspend causes I/O errors

When resuming the machine from suspend, the NBD connection drops and the root device is lost, causing I/O errors. There is currently no fix or workaround for this.