<?xml version="1.0"?><!-- generator="b2evolution/0.9.0.12" -->
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
	<channel>
		<title>Blog All Title</title>
		<link>http://kimberandjohn.com/blog/index.php?blog=1</link>
		<description>Short description for Blog All</description>
		<language>en-US</language>
		<docs>http://backend.userland.com/rss</docs>
		<admin:generatorAgent rdf:resource="http://b2evolution.net/?v=0.9.0.12"/>
		<ttl>60</ttl>
				<item>
			<title>NFS root mounting using rhel 5.0</title>
			<link>http://kimberandjohn.com/blog/index.php?blog=1&amp;title=nfs_root_mounting_using_rhel_5_1&amp;more=1&amp;c=1&amp;tb=1&amp;pb=1</link>
			<pubDate>Tue, 16 Oct 2007 07:02:35 +0000</pubDate>
						<category domain="main">NFS</category>			<guid isPermaLink="false">23@http://kimberandjohn.com/blog</guid>
			<description>I may be on a wild goose chase but I'm thinking of setting up RHEL 5.0 (actually CentOS 5.0) to boot onto a nfs root mounted file system. Reason: I want a disk-less workstation next to my TV to serve up videos for the kids (I want to rip all of the DVDs to hard disks, and serve them to the quiet laptop next to the TV). Sounds easy, do a google search about linux root nfs and follow the on screen instructions. There appears to be the usual google search problem with a technology, a search may return one or more pages be out of date, and that what's happening here. Therefore the answer is not just on the first 10 pages of a google search.

While it is possible to boot a 2.6 kernel using NFS and, it appears that it requires that NFS be compiled into the kernel and not just a loadable module. RH appears to compile NFS as a loadable module and therefore it is not possible to use a stock RH kernel to boot. OK, so it looks like it's time to configure and re-compile a kernel. I don't like that answer. I've given up on compiling my own kernel. I've been doing Linux since slackware 0.x with kernel 0.9x and I've had enough of re-compiling every time a new patch comes out. I like that RH looks after the kernel for me. I may not get the latest and greatest feature, nor the fastest kernel, but it works and most of the time it's secure. Same goes for packages, I don't want to have to worry about the latest security problem: follow CERT, download, patch, compile, deploy. I've got better things to do with my time. 

Therefore I'm going to set down some ground rules for myself;
   1. No custom kernels. This MUST work with a stock RH kernel.
   2. No re-writing init/rc.system. Everything must run using the stock RH stuff. I don't want to have to worry about losing my changes next time I type yum update.
   3. No custom packages. This must work with things only supplied with RH. See my rant about security patches.
   
I think I can get this to work with rule #1. Rule #2 might be tough, I'm worried about mounts getting in the way. #3 might be right out, RH has their way of doing things and they might not supplied I package I need.

So I starting this project a couple of days ago, and here's how far I've gotten:

1. I have a RH 5.0 box that is serving DHCP, TFTP and NFS.
2. I have a "disk-less" computer with a Intel e100 series ethernet card in it with PXE BIOS.

The idea is to boot the disk-less computer using DHCP (to obtain an IP address), download the kernel and initrd image using TFTP, mount the NFS disk in the initrd ramdisk, then do a switch root to the nfs mount. 

After doing a web search I found LTSP (Linux terminal server project). Basically you install the LTSP on a server, it does the configuration for you. I tried it and got the disk-less work station booting a stand-alone X client. Pretty cool stuff. I tried extending LTSP and quickly found that it is using a glibc that is a rev. back from RH. I quickly gave up on trying to extend it, but it gave me quite a few good leads.

After that I'm now trying to do a roll my own approach.

So here were the steps:

SETUP DHCP

The server in question was already serving DHCP for my home network, so I didn't have to download and install it, I just need to configure it do send the DHCP options for PXE. After some searching I added the following lines.

   
    if substring (option vendor-class-identifier, 0, 9) = "PXEClient" {
        next-server                   172.28.1.1;
        filename "/linux-install/pxelinux.0";
    }


I'm not got to detail how to setup DHCP, there are plenty of other resource for that.

SETUP TFTP Server

Simple "yum install tftp-server", change the disabled = yes to disabled = no in /etc/xinetd.d/tftp and it's up and running. (I also modified /etc/hosts.allow)

INSTALL pxelinux.0

RH didn't include the PXE boot stuff in RH 5.0. The manuals tell you they did, but they didn't. Some web searchs said install the one from FC6. So I found "system-config-netboot-0.1.41-1.FC6" at fedora.org and installed it. 

I created a /tftpboot/linux-install/pxelinux.cfg/default file with the following:


default linux
prompt 0
label linux
   kernel vmlinuz-2.6.18-8.1.14.el5
   append initrd=initrd-2.6.18-8.1.14.el5.img


I used the vmlinuz and initrd found in /boot of my server as a test


# cp /boot/vmlinuz-2.6.18-8.1.14.el5 /tftpboot/linux-install/
# cp /boot/initrd-2.6.18-8.1.14.el5.img /tftpboot/linux-install/


Booted up the "disk-less" client, and it started booting using the kernel. It utterly failed when it tried to mount LVM partitions, it was the initrd for the server after all.

OK now I've got a "disk-less" configuration on my server that at least loads on the client. Now all I've got to do is to get to work with the client NFS config.

SETTING UP MY OWN initrd

Turns out that the initrd format is just a gzip-ed cpio archive. Cool last time I was doing initrd they were compressed disk images. This makes life a little easier, no more losetup, mount, unmount for testing.

SO I checked out the one with my server


  [~]# mkdir initrd
  [~]# cd initrd
  [initrd]# gzip -dc /boot/initrd-`uname -r`.img | cpio -i


I thinking about scripts so I'll start to use `uname -r` to be more generic.

Looking at the files that came out there is a file called init which is run soon right after it is loaded on the "disk-less" client. Turns out that this is nash script (nash appears to be some sort of minimalist shell meant for booting). Looks like it does normal looking mount commands. The mount for nash doesn't support NFS. So looks like I'll have to do something different. 

BOOTING THE CLIENT WITH BASH

So I tried just having the init run bash once it starts.


#!/bin/bash
exec bash


So i copied bash over to the image


[inirrd]# cp /bin/bash bin/  


Bash uses dynamic link libraries, so I'll need all of them to. After some experimenting I found the following works the best

[OMITTED]

Basically this takes the output of ldd (which shows the shared libs that a executable needs) and reformats it to copy commands. I know I could do the entire thing in perl but I'm in the lazy stage.

Now I've got the format need to create a new initrd

After some web searching the following worked for me.
  

[initrd#] find ./ | cpio -H newc -o | gzip -c > /tftpboot/linux-install/initrd-`uname -r`.img


Wait for the command to complete. Then boot the client.

WAIT. WAIT. Watch all of the kernel messages go by WAIT. WAIT.

Kernel panic. Failed to load init. 

HMM. Try using chroot to see what's wrong.


[initrd#] chroot .
chroot: cannot run command `/bin/bash': No such file or directory


Rerun


[initrd#] ldd /bin/bash
        linux-gate.so.1 =>  (0x0051e000)
        libtermcap.so.2 => /lib/libtermcap.so.2 (0x004a2000)
        libdl.so.2 => /lib/libdl.so.2 (0x00110000)
        libc.so.6 => /lib/libc.so.6 (0x00114000)
        /lib/ld-linux.so.2 (0x008c6000)


Great turns out I'm missing /lib/ld-linux.so.2 it didn't match my regex. Just copy it over


[initrd#] cp /lib/ld-linux.so.2 lib/


Rerun the chroot to check that this worked, cpio to create the initrd, Reboot the client

WAIT. WAIT. Watch all of the kernel messages go by WAIT. WAIT.

HMM looks likes it hung with some message about the mouse pad on the client. Hit enter.


bash-3.1#


Cool a bash prompt 

Looking at the messages a bash prompt is a couple of lines up. Looks like the bash loaded while something was still initializing and I missed it.

So the first thing I always do:


bash-3.1# ls
bash: ls: command not found


Yeah that's right ls is an external command. Need some commands to try.


[initrd#] cp /bin/{cp,ls,rm,mkdir,rmdir,vi} bin
[PERL COMMAND]


Re-cpio and reboot the client, WAIT WAIT.


bash-3.1# ls
bin dev etc init lib proc root sbin sys sysroot


Cool try vi


bash-3.1# vi
[SOME MESSAGES ABOUT TERM TYPE SUPPORTED]


Then a vi screen.

Cool. This will let me experiment and see if I can get NFS to work.

TO BE CONTINUED....



</description>
			<content:encoded><![CDATA[	<p>I may be on a wild goose chase but I'm thinking of setting up RHEL 5.0 (actually CentOS 5.0) to boot onto a nfs root mounted file system. Reason: I want a disk-less workstation next to my TV to serve up videos for the kids (I want to rip all of the DVDs to hard disks, and serve them to the quiet laptop next to the TV). Sounds easy, do a google search about linux root nfs and follow the on screen instructions. There appears to be the usual google search problem with a technology, a search may return one or more pages be out of date, and that what's happening here. Therefore the answer is not just on the first 10 pages of a google search.</p>
	<p>While it is possible to boot a 2.6 kernel using NFS and, it appears that it requires that NFS be compiled into the kernel and not just a loadable module. RH appears to compile NFS as a loadable module and therefore it is not possible to use a stock RH kernel to boot. OK, so it looks like it's time to configure and re-compile a kernel. I don't like that answer. I've given up on compiling my own kernel. I've been doing Linux since slackware 0.x with kernel 0.9x and I've had enough of re-compiling every time a new patch comes out. I like that RH looks after the kernel for me. I may not get the latest and greatest feature, nor the fastest kernel, but it works and most of the time it's secure. Same goes for packages, I don't want to have to worry about the latest security problem: follow CERT, download, patch, compile, deploy. I've got better things to do with my time. </p>
	<p>Therefore I'm going to set down some ground rules for myself;<br />
   1. No custom kernels. This MUST work with a stock RH kernel.<br />
   2. No re-writing init/rc.system. Everything must run using the stock RH stuff. I don't want to have to worry about losing my changes next time I type yum update.<br />
   3. No custom packages. This must work with things only supplied with RH. See my rant about security patches.</p>
	<p>I think I can get this to work with rule #1. Rule #2 might be tough, I'm worried about mounts getting in the way. #3 might be right out, RH has their way of doing things and they might not supplied I package I need.</p>
	<p>So I starting this project a couple of days ago, and here's how far I've gotten:</p>
	<p>1. I have a RH 5.0 box that is serving DHCP, TFTP and NFS.<br />
2. I have a "disk-less" computer with a Intel e100 series ethernet card in it with PXE BIOS.</p>
	<p>The idea is to boot the disk-less computer using DHCP (to obtain an IP address), download the kernel and initrd image using TFTP, mount the NFS disk in the initrd ramdisk, then do a switch root to the nfs mount. </p>
	<p>After doing a web search I found LTSP (Linux terminal server project). Basically you install the LTSP on a server, it does the configuration for you. I tried it and got the disk-less work station booting a stand-alone X client. Pretty cool stuff. I tried extending LTSP and quickly found that it is using a glibc that is a rev. back from RH. I quickly gave up on trying to extend it, but it gave me quite a few good leads.</p>
	<p>After that I'm now trying to do a roll my own approach.</p>
	<p>So here were the steps:</p>
	<p>SETUP DHCP</p>
	<p>The server in question was already serving DHCP for my home network, so I didn't have to download and install it, I just need to configure it do send the DHCP options for PXE. After some searching I added the following lines.</p>
<pre>   
    if substring (option vendor-class-identifier, 0, 9) = "PXEClient" {
        next-server                   172.28.1.1;
        filename "/linux-install/pxelinux.0";
    }
</pre>	<p>
I'm not got to detail how to setup DHCP, there are plenty of other resource for that.</p>
	<p>SETUP TFTP Server</p>
	<p>Simple "yum install tftp-server", change the disabled = yes to disabled = no in /etc/xinetd.d/tftp and it's up and running. (I also modified /etc/hosts.allow)</p>
	<p>INSTALL pxelinux.0</p>
	<p>RH didn't include the PXE boot stuff in RH 5.0. The manuals tell you they did, but they didn't. Some web searchs said install the one from FC6. So I found "system-config-netboot-0.1.41-1.FC6" at fedora.org and installed it. </p>
	<p>I created a /tftpboot/linux-install/pxelinux.cfg/default file with the following:</p>
<pre>
default linux
prompt 0
label linux
   kernel vmlinuz-2.6.18-8.1.14.el5
   append initrd=initrd-2.6.18-8.1.14.el5.img
</pre>	<p>
I used the vmlinuz and initrd found in /boot of my server as a test</p>
<pre>
# cp /boot/vmlinuz-2.6.18-8.1.14.el5 /tftpboot/linux-install/
# cp /boot/initrd-2.6.18-8.1.14.el5.img /tftpboot/linux-install/
</pre>	<p>
Booted up the "disk-less" client, and it started booting using the kernel. It utterly failed when it tried to mount LVM partitions, it was the initrd for the server after all.</p>
	<p>OK now I've got a "disk-less" configuration on my server that at least loads on the client. Now all I've got to do is to get to work with the client NFS config.</p>
	<p>SETTING UP MY OWN initrd</p>
	<p>Turns out that the initrd format is just a gzip-ed cpio archive. Cool last time I was doing initrd they were compressed disk images. This makes life a little easier, no more losetup, mount, unmount for testing.</p>
	<p>SO I checked out the one with my server</p>
<pre>
  [~]# mkdir initrd
  [~]# cd initrd
  [initrd]# gzip -dc /boot/initrd-`uname -r`.img | cpio -i
</pre>	<p>
I thinking about scripts so I'll start to use `uname -r` to be more generic.</p>
	<p>Looking at the files that came out there is a file called init which is run soon right after it is loaded on the "disk-less" client. Turns out that this is nash script (nash appears to be some sort of minimalist shell meant for booting). Looks like it does normal looking mount commands. The mount for nash doesn't support NFS. So looks like I'll have to do something different. </p>
	<p>BOOTING THE CLIENT WITH BASH</p>
	<p>So I tried just having the init run bash once it starts.</p>
<pre>
#!/bin/bash
exec bash
</pre>	<p>
So i copied bash over to the image</p>
<pre>
[inirrd]# cp /bin/bash bin/  
</pre>	<p>
Bash uses dynamic link libraries, so I'll need all of them to. After some experimenting I found the following works the best</p>
	<p>[OMITTED]</p>
	<p>Basically this takes the output of ldd (which shows the shared libs that a executable needs) and reformats it to copy commands. I know I could do the entire thing in perl but I'm in the lazy stage.</p>
	<p>Now I've got the format need to create a new initrd</p>
	<p>After some web searching the following worked for me.</p>
<pre>
[initrd#] find ./ | cpio -H newc -o | gzip -c > /tftpboot/linux-install/initrd-`uname -r`.img
</pre>	<p>
Wait for the command to complete. Then boot the client.</p>
	<p>WAIT. WAIT. Watch all of the kernel messages go by WAIT. WAIT.</p>
	<p>Kernel panic. Failed to load init. </p>
	<p>HMM. Try using chroot to see what's wrong.</p>
<pre>
[initrd#] chroot .
chroot: cannot run command `/bin/bash': No such file or directory
</pre>	<p>
Rerun</p>
<pre>
[initrd#] ldd /bin/bash
        linux-gate.so.1 <img src="http://kimberandjohn.com/blog/img/smilies/icon_arrow.gif" alt="&#61;&#62;" class="middle" />  (0x0051e000)
        libtermcap.so.2 <img src="http://kimberandjohn.com/blog/img/smilies/icon_arrow.gif" alt="&#61;&#62;" class="middle" /> /lib/libtermcap.so.2 (0x004a2000)
        libdl.so.2 <img src="http://kimberandjohn.com/blog/img/smilies/icon_arrow.gif" alt="&#61;&#62;" class="middle" /> /lib/libdl.so.2 (0x00110000)
        libc.so.6 <img src="http://kimberandjohn.com/blog/img/smilies/icon_arrow.gif" alt="&#61;&#62;" class="middle" /> /lib/libc.so.6 (0x00114000)
        /lib/ld-linux.so.2 (0x008c6000)
</pre>	<p>
Great turns out I'm missing /lib/ld-linux.so.2 it didn't match my regex. Just copy it over</p>
<pre>
[initrd#] cp /lib/ld-linux.so.2 lib/
</pre>	<p>
Rerun the chroot to check that this worked, cpio to create the initrd, Reboot the client</p>
	<p>WAIT. WAIT. Watch all of the kernel messages go by WAIT. WAIT.</p>
	<p>HMM looks likes it hung with some message about the mouse pad on the client. Hit enter.</p>
<pre>
bash-3.1#
</pre>	<p>
Cool a bash prompt </p>
	<p>Looking at the messages a bash prompt is a couple of lines up. Looks like the bash loaded while something was still initializing and I missed it.</p>
	<p>So the first thing I always do:</p>
<pre>
bash-3.1# ls
bash: ls: command not found
</pre>	<p>
Yeah that's right ls is an external command. Need some commands to try.</p>
<pre>
[initrd#] cp /bin/{cp,ls,rm,mkdir,rmdir,vi} bin
[PERL COMMAND]
</pre>	<p>
Re-cpio and reboot the client, WAIT WAIT.</p>
<pre>
bash-3.1# ls
bin dev etc init lib proc root sbin sys sysroot
</pre>	<p>
Cool try vi</p>
<pre>
bash-3.1# vi
[SOME MESSAGES ABOUT TERM TYPE SUPPORTED]
</pre>	<p>
Then a vi screen.</p>
	<p>Cool. This will let me experiment and see if I can get NFS to work.</p>
	<p>TO BE CONTINUED....</p>
]]></content:encoded>
			<comments>http://kimberandjohn.com/blog/index.php?blog=1&amp;p=23&amp;c=1&amp;tb=1&amp;pb=1#comments</comments>
		</item>
			</channel>
</rss>
