This is a collection of informal notes on the subject of getting a netwinder to boot and mount a large root directory via NFS, READ-ONLY. By large I mean more than can be run entirely in ram. This is useful if you want to run a buttload of diskless 'winders. The concern here is merely on getting them to run, not getting a minimal install. There are other pages for that. See Mike Montour's, Tim Potter's pages. http://www.netwinder.org/~mmontour/ http://www.netwinder.org/~tpot/ -----------------NFS I won't spend too much time here. Get NFS working. Then get your /etc/exports file on the NFS server to have a line like this: /exports/netwinder babbage(rw, no_root_squash) where /exports/netwinder is the full linux distribution you want to run on the client machine (babbage), then say exportfs (or send -HUP to rpc.mountd and rpc.nfsd) I have shamelessly glossed over this, and as punishment you should STOP reading and go directly to Stan Vardomskiy's Netwinder Rescue HOWTO. http://www.netwinder.org/~stany/ -----------------DHCP Network Config on the Client - Here also I won't go into it too much. I use DHCP, which means all I have to set on the client is netconfig_eth0 dhcp, kernconfig tftp, rootconfig nfs. This means of course that you need dhcpd on your server. In any case you can find out that stuff elsewhere. One tip, tail -f /var/log/messages to see what's happening during boot, and to find out hardware addresses. ----------------KERNEL ISSUES You need a ramdisk-ready kernel, which means NOT vmlinux.rescue from netwinder.org. You also need the kernel compiled without root path specified, which I think means no kernel from netwinder.org. We have successfully compiled 2.2.2 on the dm 12, using this configuration: http://www.netwinder.org/~ira/dot_config_arm_2.2.2 ----------------MAKING THE IMAGE READ-ONLY--------------- I will assume from this point that you have successfully booted an image READ-WRITE. Here's how to get a read-only bootable image. The basic strategy is to mount a ramdisk on the client where whatever has to be written can be written. For convenience we will use /var, and symlink any other written-to files into /var. This should be done early in the boot process, but not too early! Here is what I did first. I chose to alter /etc/rc.d/rc.sysinit, since that is where all the serious mounting and checking goes on. Right after the root directory is remounted, which is the line: mount -n -o remount,rw / I added: # ADDED TO FACILITATE MULTIPLE NET-BOOTING. echo "creating RAMDISK for /var..." dd if=/dev/zero of=/dev/ram2 bs=1k count=4096 mke2fs -v /dev/ram2 4096 rm -rf /var/* mount -t ext2 /dev/ram2 /var cp -pRd /var.ro/* /var/. This will create a 4M ramdisk mounted in the directory /var. Note that you have to RENAME the real, read-only var to something else like /var.ro, and create an empty directory called /var in the exported image: cd /exports/netwinder mv var var.ro mkdir var There are things that get written in other places like /tmp, so I just moved the /tmp dir into /var.ro as fake_tmp, and symlinked like so: mv tmp var.ro/fake_tmp ln -s var/fake_tmp tmp This can get tricky because the symlinks point to nothing on the server machine; they are only valid on the client, after the ramdisk has been created and mounted. After you have succeeded in the above, you are ready to try it read-only. First change the 'rw' in /etc/exports to 'ro': /exports/netwinder babbage(ro, no_root_squash) Then say exportfs, then boot the client. It didn't boot, did it? Surprise surprise. Mostly it is a matter of studying the init procedure and taking away any excuse for the damn thing not to boot. The initialization process goes like this. According to Saddam Hussein, 'init' is the 'Mother of all processes', since it is executed by the kernel immediately. 1. The 'init' program reads /etc/inittab and does what it says. 2. One thing inittab says is basically "do sysVinit", which means A. Execute /etc/rc.d/rc.sysinit B. Execute the programs pointed to by the symlinks in /etc/rc.d/rc3.d/, since 3 is the default runlevel set in inittab, C. Execute /etc/rc.d/rc.local 3. Spawn a bunch of mingettys. Simple, no? Simple enough for an unemployed programmer to figure out. Here I will simply recount some things I did to make it boot. I'm creating a special-purpose machine so I had some leeway in the things I could throw out. Here is a list of packages that got in the way: bind caching-nameserver gpm nfs-server bootparamd atalk sysklogd That last one may give you pause. I don't need it and you probably don't either if you're bothering with this document. In any case it insists on CREATING a socket "log" in /dev, which really cheesed me off. Most of the other problematic actions take place in rc.sysinit or rc.local. Look for "cp", ">", "rm", etc, all the writing commands, and either symlink the files or get rid of the action. Now for the whodunnit: mingetty seems to require a writable filesystem! Recall that mingettys are spawned from inittab. Here's what I did. I nuked them. That's right, no console access, but I'm not hooking monitors to these things anyway. As soon as I commented out these lines, like so: # Run gettys in standard runlevels #1:12345:respawn:/sbin/mingetty tty1 #2:2345:respawn:/sbin/mingetty tty2 #3:2345:respawn:/sbin/mingetty tty3 #4:2345:respawn:/sbin/mingetty tty4 #5:2345:respawn:/sbin/mingetty tty5 #6:2345:respawn:/sbin/mingetty tty6 I was able to boot multiple clients and telnet into them. Whoopee! Netwinders... taste gooood.
Ira Joseph Woodhead <firstname.lastname@example.org>