Mike Chirico (mchirico@users.sourceforge.net) or (mchirico@comcast.net)
Copyright (c) 2005 (GNU Free Documentation License)
Last Updated: Sun Nov 13 09:07:31 EST 2005

The latest version of this document can be found at:

Create a Custom Live Linux CD - Leveraging BusyBox and OpenSSH

These steps will show you how to create a functioning Linux system, with the latest 2.6 kernel compiled from source, and how to integrate the BusyBox utilities including the installation of DHCP. Plus, how to compile in the OpenSSH package. The system will have full ssh capabilities. The techniques for compiling and installing software can be universally applied to your own packages. So, once you understand the process, you are free to recreate your own system -- there is a lot of free space.

On system boot-up a filesystem will be created and the contents from the CD will be uncompressed and completely loaded into RAM -- the CD could be removed at this point for boot-up on a second computer. You can take over any PC assuming you have configured the kernel with the appropriate drivers and the PC can boot from a CD.

QUICK INSTALL: Confirmation that Everything Works - Before Rolling You Own

Quick step 1:

Download "cdrom_linux_boot_proj1.iso" and burn this iso on your cdrom. Next, reboot the system. This is a check to see if the current kernel has been compiled with the necessary network, video, and keyboard (USB included) drivers. If critical drivers are not recognized they can be added into the kernel.

Quick step 2:

Download the complete project environment "proj1.tar.gz." This includes everything used to build and customize "cdrom_linux_boot_proj1.iso", including the BusyBox source, libraries, and ssh. The directory "_install" contains the necessary libraries for ssh, init and tcpdump. The 2.6.11 kernel ".config" can be found in the documents directory. The staging area contains a copy of the kernel bzImage, along with the isolinux boot loader. The "proj1.tar.gz" file is about 13M, since it includes everything you need, except the kernel source, which can be downloaded from the following link:


Step 8 covers the configuration and installation of the latest kernel. At this stage, download the project environment "proj1.tar.gz" from the following link:


You must "tar -xzf" this file as root to get all the necessary character and block devices. Standard user accounts cannot create all the necessary block and character devices that will be needed. Try "tar -xzf" under an account without root privileges to see the differences in the files created under "_install/dev".

If you're curious about the difference between character devices and block devices, you may want to reference the Linux Journal article


In summary, only block devices can mount filesystems. But character devices, such as a tape drive can contain data found on a block device.

Checking the download:

a. Check the md5sum to make sure you got the full copy, then, "tar -xzf" the package.

              $ md5sum proj1.tar.gz

b. Now as root, so that you will get all "dev/" devices, execute the following command.

              [Must be done as root]
               $ su -
               # cd <to project directory>
               # tar -xzf proj1.tar.gz

If you did the above as root, then you should have the following:

                [root@third-fl-71 _install]# ls -l dev
                total 8
                crw-------    1 root     root       5,   1 Feb 25 20:41 console
                lrwxrwxrwx    1 root     root           11 Mar  6 09:22 core -> /proc/kcore
                brw-rw-rw-    1 root     floppy     2,   0 Feb 20 17:37 fd0
                brw-rw----    1 root     disk       3,   0 Mar  5 04:32 hda
                brw-rw----    1 root     disk       3,   1 Mar  5 20:37 hda1
                brw-rw----    1 root     disk       3,   2 Mar  5 20:38 hda2
                brw-rw----    1 root     disk       3,   3 Mar  5 21:02 hda3
                brw-rw----    1 root     disk       3,   4 Mar  5 21:02 hda4
                drwxr-xr-x    2 root     root         4096 Mar  5 21:13 mapper
                crw-rw-rw-    1 root     root       1,   3 Feb 20 17:37 null
                crw-rw-rw-    1 root     tty        5,   2 Feb 26 12:54 ptmx
                drwxr-xr-x    2 root     root         4096 Mar  4 05:33 pts
                brw-------    1 root     disk       1,   0 Feb 20 17:37 ram0
                brw-rw-rw-    1 root     disk       1,   1 Feb 20 17:37 ram1
                brw-rw-rw-    1 root     disk       1,   2 Feb 20 17:37 ram2
                brw-rw-rw-    1 root     disk       1,   3 Feb 20 17:37 ram3
                crw-rw-rw-    1 root     root       1,   8 Feb 26 03:23 random
                brw-rw----    1 root     disk       8,   0 Mar  5 04:32 sda
                brw-rw----    1 root     disk       8,   1 Mar  5 04:32 sda1
                brw-rw----    1 root     disk       8,   2 Mar  5 04:32 sda2
                brw-rw----    1 root     disk       8,   3 Mar  5 21:02 sda3
                brw-rw----    1 root     disk       8,   4 Mar  5 21:02 sda4
                lrwxrwxrwx    1 root     root           15 Mar  6 09:22 stderr -> /proc/self/fd/2
                lrwxrwxrwx    1 root     root           15 Mar  6 09:22 stdin -> /proc/self/fd/0
                lrwxrwxrwx    1 root     root           15 Mar  6 09:22 stdout -> /proc/self/fd/1
                crw-rw-rw-    1 root     root       5,   0 Feb 21 18:32 tty
                crw-rw-rw-    1 root     root       4,   0 Feb 20 17:37 tty0
                crw-rw-rw-    1 root     root       4,   1 Feb 20 22:38 tty1
                crw-rw-rw-    1 root     root       4,   2 Feb 26 08:24 tty2
                crw-rw-rw-    1 root     root       4,   3 Feb 26 08:24 tty3
                crw-rw-rw-    1 root     root       4,   4 Feb 26 08:24 tty4
                crw-rw-rw-    1 root     root       4,   5 Feb 26 08:24 tty5
                crw-------    1 root     root       4,   6 Mar  1 19:34 tty6
                crw-rw----    1 root     root       4,   7 Mar  1 14:33 tty7
                crw-rw----    1 root     root       4,   8 Mar  1 14:33 tty8
                crw-rw----    1 root     tty        4,   9 Mar  1 14:33 tty9
                cr--r--r--    1 root     root       1,   9 Feb 26 03:23 urandom
                crw-------    1 vcsa     tty        7,   0 Mar  1 14:33 vcs
                crw-rw-rw-    1 root     root       1,   5 Feb 26 03:23 zero

If you repeat the steps above using a standard account, a lot of the files will be missing.

c. Take a look at the file "proj1/createiso". This will create a filesystem on a loop back device with the mount point "./cdrom". Copy the contents of "_install", which has already been compiled with the necessary busybox code. Once it is copied, umount "./cdrom" so that it can be compressed. This will then get copied to the staging area where "mkisofs" will create a bootable CD image. The boot loader isolinux, along with the needed config files can be found in "proj1/staging_iso_image/boot/isolinux/"

There is a bash script "createiso" that performs the above tasks.

               $ cd proj1
               $ su 
               # ./createiso

Take a look at "createiso". This bash script creates a virtual filesystem. For details on creating a virtual filesystem reference the following article on Freshmeat [ http://freshmeat.net/articles/view/1387/ ]

COMPREHENSIVE TUTORIAL: Building Everything from Downloaded Source

You may want to keep the results of the quick install steps above in a separate directory to compare against the completion of each step below.

STEP 1: Download BusyBox

Download BusyBox (http://www.busybox.net/downloads/). These examples were created with http://www.busybox.net/downloads/busybox-1.00.tar.gz.

  $ wget http://www.busybox.net/downloads/busybox-1.00.tar.gz
  $ wget http://www.busybox.net/downloads/busybox-1.00.tar.gz.sign
  $ md5sum busybox-1.00.tar.gz
     fa62459e098fc00b22772aaf2e75bc98  busybox-1.00.tar.gz
Next expand the files:

  $ tar -xzf busybox-1.00.tar.gz 

Note if you want to verify Erik's key:

  $ wget http://codepoet.org/andersen/erik/gpg.asc
  $ gpg --import gpg.asc
  $ gpg --verify busybox-1.00.tar.gz.sign 

Now look inside busybox-1.00.tar.gz.sign for the md5sum. Note, he has done it differently than it's done with the 2.6 kernel (reference step 9).

STEP 2: Configuring BusyBox

You may want to download my config for BusyBox and rename it to ".config". I have the needed features turned on.

My config download can be found here: http://prdownloads.sourceforge.net/souptonuts/chiricobusybox.config

  $ cd busybox-1.00

[Note you may need to select another mirror]
  $ wget http://osdn.dl.sourceforge.net/sourceforge/souptonuts/chiricobusybox.config
  $ cp chiricobusybox.config .config

You should take a look at the options that I have set by running "make menuconfig" or take a look at "chiricobusybox.config" directly.

  $ make menuconfig

In particular, "Support version 2.6.x Linux kernels" is checked. Under "Login/Password Management Utilities" everything is checked EXCEPT "Use internal password and group functions". Note, at this stage you do NOT want to select this option because "/etc/passwd", "/etc/shadow" and "/etc/shadow-", will be copied to the "_install/etc" directory, and used instead.

Also, "lsmod", "modprobe", "rmmod" are checked. Although not essential for the initial build, this system you are building will support networking. You may eventually want to scp in modules and load them, once you get the system running, of course. There is plenty of space for these modules.

After taking a look at ".config", run "make" and "make install", which by default will install everything under "_install".

  $ make
  $ make install

During the final stages of "make install" the following message will be displayed.

  You will probably need to make your busybox binary
  setuid root to ensure all configured applets will
  work properly.

The next command must be executed after each "make install" to setuid root on the BusyBox binary.

  $ chmod 4755 ./_install/bin/busybox

STEP 3: Needed Directories

Several directories need to be created under "_install". Take a look at the current contents.

  $ cd _install
  $ ls 
  bin  linuxrc  sbin  usr

Next create "dev" for "device entries", which will be populated later, "etc", "lib", "proc", "tmp", "var" and "sys" with the following commands.

  $ mkdir -p dev sys etc/init.d lib proc tmp var/lib/misc var/lock var/log var/run var/tmp
  $ chmod 1777 tmp
  $ chmod 1777 var/tmp

STEP 4: Device Entries

The "dev" directory needs to be populated with device entries. They can either be copied from the current system or created with the "mknod -m " command. The following will have to be done as root.

Since there are a lot of files, and you may want to rebuild you "_install", it is recommended that these be put in a file. Below the file createdev is created with the following contents:

  # put this in a file called createdev
  cp -avp /dev/console   dev
  cp -avp /dev/core   dev
  cp -avp /dev/fd0   dev
  cp -avp /dev/null   dev
  cp -avp /dev/ptmx   dev
  cp -avp /dev/pts   dev
  cp -avp /dev/ram0   dev
  cp -avp /dev/ram1   dev
  cp -avp /dev/ram2   dev
  cp -avp /dev/ram3   dev
  cp -avp /dev/random   dev
  cp -avp /dev/stderr   dev
  cp -avp /dev/stdin   dev
  cp -avp /dev/stdout   dev
  cp -avp /dev/tty   dev
  cp -avp /dev/tty0   dev
  cp -avp /dev/tty1   dev
  cp -avp /dev/tty2   dev
  cp -avp /dev/tty3   dev
  cp -avp /dev/tty4   dev
  cp -avp /dev/tty5   dev
  cp -avp /dev/tty6   dev
  cp -avp /dev/tty7   dev
  cp -avp /dev/tty8   dev
  cp -avp /dev/tty9   dev
  cp -avp /dev/urandom   dev
  cp -avp /dev/vcs   dev
  cp -avp /dev/zero dev

Now run the command, as root, in "_install"

  $ su
  # pwd

  # chmod 700 createdev
  # ./createdev

The "ls -al" command now shows the following contents.

  # ls -l dev
  total 4
  crw-------    1 root     root       5,   1 Feb 17 14:49 console
  crw-------    1 root     root       1,   6 Jan 30  2003 core
  brw-rw----    1 root     floppy     2,   0 Jan 30  2003 fd0
  crw-rw-rw-    1 root     root       1,   3 Jan 30  2003 null
  crw-rw-rw-    1 root     root       5,   2 Mar  5 17:16 ptmx
  drwxr-xr-x    2 root     root         4096 Feb 17 09:48 pts
  brw-rw----    1 root     disk       1,   0 Jan 30  2003 ram0
  brw-rw----    1 root     disk       1,   1 Jan 30  2003 ram1
  brw-rw----    1 root     disk       1,   2 Jan 30  2003 ram2
  brw-rw----    1 root     disk       1,   3 Jan 30  2003 ram3
  crw-r--r--    1 root     root       1,   8 Jan 30  2003 random
  lrwxr-xr-x    1 root     root           17 Mar  5 17:16 stderr -> ../proc/self/fd/2
  lrwxr-xr-x    1 root     root           17 Mar  5 17:16 stdin -> ../proc/self/fd/0
  lrwxr-xr-x    1 root     root           17 Mar  5 17:16 stdout -> ../proc/self/fd/1
  crw-rw-rw-    1 root     root       5,   0 Mar  3 21:20 tty
  crw--w----    1 root     root       4,   0 Jan 30  2003 tty0
  crw-------    1 root     root       4,   1 Feb 17 14:49 tty1
  crw-------    1 root     root       4,   2 Feb 17 14:49 tty2
  crw-------    1 root     root       4,   3 Feb 17 14:49 tty3
  crw-------    1 root     root       4,   4 Feb 17 14:49 tty4
  crw-------    1 root     root       4,   5 Feb 17 14:49 tty5
  crw-------    1 root     root       4,   6 Feb 17 14:49 tty6
  crw--w----    1 root     root       4,   7 Oct 24  2003 tty7
  crw--w----    1 root     root       4,   8 Jan 30  2003 tty8
  crw--w----    1 root     tty        4,   9 Jan 30  2003 tty9
  crw-r--r--    1 root     root       1,   9 Feb 17 14:49 urandom
  crw--w----    1 vcsa     tty        7,   0 Jan 30  2003 vcs
  crw-rw-rw-    1 root     root       1,   5 Jan 30  2003 zero

These files could all have been created with the "mknod" command. Taking a look at "tty" above, about half way down, it is a character device with a major number of 5 and a minor number of 0. It has rights rw-rw-rw. So the "tty" device could have been created with the command "mknod -m 666 dev/tty c 5 0" . But, you ask, where can you get a listing of all the major and minor numbers for both block and character devices? This can be found in "/Documentation/devices.txt" in the kernel source. Or, you can see them all here: http://souptonuts.sourceforge.net/devices.txt

So, if you want to mount disk drives, ide (hda) and scsi (sda) consider executing the following commands:

  mknod -m 660 dev/hda  b 3 0
  mknod -m 660 dev/hda1 b 3 1
  mknod -m 660 dev/hda2 b 3 2
  mknod -m 660 dev/hda3 b 3 3
  mknod -m 660 dev/hda4 b 3 4
  chown root.disk  dev/hda*

  mknod -m 660 dev/sda  b 8 0
  mknod -m 660 dev/sda1  b 8 1
  mknod -m 660 dev/sda2  b 8 2
  mknod -m 660 dev/sda2  b 8 3
  mknod -m 660 dev/sda2  b 8 4
  chown root.disk  dev/sda*

After the PC is booted from the CD, you can mount these devices after creating a directory as the mount point "mkdir /h", then, it gets mounted as "mount -t ext2 /dev/hda2 /h".

It is also possible to create volume groups

  mkdir -p dev/mapper
  mknod -m 600 dev/mapper/VolGroup00-LogVol00 b 253 0
  mknod -m 600 dev/mapper/VolGroup00-LogVol01 b 253 1
  chown -R root.root dev/mapper

Create a directory "/v1"

  mkdir -p /v1

The VolGroup would be mounted as ext3, most likely by doing the following after creating a mount point "/v1", then, "mount -t ext3 /dev/VolGroup00/LogVol01 /v1". But, would require the proper device drivers to be loaded in the kernel module, and the needed configuration in "/etc/rc.sysinit", notably the section under "# LVM2 initializtion". All of this will be discussed in a future update of this article.

STEP 5: Needed Files and Directories (files and directories in "etc" and "var")

Create the necessary files in "etc". Exit out of root at this point, so that there is no chance of over-writing you system "/etc" -- note disaster is only a "/" away. WARNING: Never copy anything into a directory that starts with "/", since that is your current running system.

  [Exit out of root]

The "etc/passwd" file is shown below. Since the ssh daemon will run, an account will be created for it. Note for sshd that login is set to "/bin/false"

  root:x:0:0:Linux User,,,:/root:/bin/sh
  sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/bin/false

Below "root" and "sshd" have been added to the group.


Note below that there is a password for the account root. This encrypted password is "root". You could create your own password here by copying an existing account password from "/etc/shadow" and "/etc/shadow-". The account "sshd" should have "*" for the password.



Interesting question regarding sshd: Why is "/dev/pts" necessary when sshing into this computer? If you are uncertain, remove this line and observe the results of the command "ps aux", when attempting to ssh in.

  /dev/ram0 /      ext2    defaults     0      0
  proc  /proc      proc    defaults     0      0
  sysfs /sys       sysfs   defaults     0      0
  none  /dev/pts   devpts  gid=5,mode=620 0    0

The file "etc/inittab" is called by the init program. There are no run levels with BusyBox. The lines "tty2::respawn:/sbin/getty 38400 tty2" allow you to enter "ctl-alt-F2" and get a login screen.

  # This is run first except when booting in single-user mode.
  ::respawn:/sbin/getty 38400 tty1
  # /sbin/getty invocations for selected ttys
  #tty1::respawn:/sbin/getty 38400 tty1
  tty2::respawn:/sbin/getty 38400 tty2
  tty3::respawn:/sbin/getty 38400 tty3
  tty4::respawn:/sbin/getty 38400 tty4
  tty5::respawn:/sbin/getty 38400 tty5
  tty6::respawn:/sbin/getty 38400 tty6
  tty7::respawn:/sbin/getty 38400 tty7
  tty8::respawn:/sbin/getty 38400 tty8
  tty9::respawn:/sbin/getty 38400 tty9
  # Example of how to put a getty on a serial line (for a terminal)
  #::respawn:/sbin/getty -L ttyS0 9600 vt100
  #::respawn:/sbin/getty -L ttyS1 9600 vt100
  # Example how to put a getty on a modem line.
  #::respawn:/sbin/getty 57600 ttyS2
  # Stuff to do when restarting the init process
  # Stuff to do before rebooting
  ::shutdown:/bin/umount -a -r
  ::shutdown:/sbin/swapoff -a

Note above, "inittab" calls "etc/init.d/rcS". The ram drive must be remounted; otherwise, it will be read only. Also, when the system boots, DHCP will be enabled. If the computer is not going to be connected to the network, comment this out, since it will repeatedly attempt to acquire an IP address. Also, if the proper NIC (Network Interface Card) is not found, you will inundated with messages.

  /bin/mount -a
  # below getting rid of ram being mounted ro
  /bin/mount -o remount / 
  # The following is for dhcp
  ifconfig eth0
  # Instead, if you want static IP address
  #ifconfig eth0  netmask
  #route add default gw
  # Run ssh daemon

The file below, along with libraries /lib/libnss_* are necessary for password authentication, since the recent version of GNU Libc (glibc) uses Name Service Switch (NSS). This file can probably be copied from your system's "/etc/nsswitch.conf" file. If you don't have this file on your system, take the necessary files from "proj1.tar.gz".

  # /etc/nsswitch.conf
  # An example Name Service Switch config file. This file should be
  # sorted with the most-used services at the beginning.
  # The entry '[NOTFOUND=return]' means that the search for an
  # entry should stop if the search in the previous entry turned
  # up nothing. Note that if the search failed due to some other reason
  # (like no NIS server responding) then the search continues with the
  # next entry.
  # Legal entries are:
  #       nisplus or nis+         Use NIS+ (NIS version 3)
  #       nis or yp               Use NIS (NIS version 2), also called YP
  #       dns                     Use DNS (Domain Name Service)
  #       files                   Use the local files
  #       db                      Use the local database (.db) files
  #       compat                  Use NIS on compat mode
  #       hesiod                  Use Hesiod for user lookups
  #       [NOTFOUND=return]       Stop searching if not found so far
  # To use db, put the "db" in front of "files" for entries you want to be
  # looked up first in the databases
  # Example:
  #passwd:    db files nisplus nis
  #shadow:    db files nisplus nis
  #group:     db files nisplus nis
  passwd:     files
  shadow:     files
  group:      files
  #hosts:     db files nisplus nis dns
  hosts:      files dns
  # Example - obey only what nisplus tells us...
  #services:   nisplus [NOTFOUND=return] files
  #networks:   nisplus [NOTFOUND=return] files
  #protocols:  nisplus [NOTFOUND=return] files
  #rpc:        nisplus [NOTFOUND=return] files
  #ethers:     nisplus [NOTFOUND=return] files
  #netmasks:   nisplus [NOTFOUND=return] files
  bootparams: nisplus [NOTFOUND=return] files
  ethers:     files
  netmasks:   files
  networks:   files
  protocols:  files
  rpc:        files
  services:   files
  netgroup:   files
  publickey:  nisplus
  automount:  files
  aliases:    files nisplus

This file contains device names that permit root logins. For now, it makes sense for root to have lots of capabilities, for testing. "vc/1","vc/2" stands for virtual consoles.


Below is a minimal hosts file. If you are running on a local LAN without a DNS server, then, add in additional names. Note, if you ping localhost and get nothing, then, lo may need to be configured: "ifconfig lo". If you are not sure what is defined where "ifconfig" will give you a listing.

  [etc/hosts]       localhost
  # Additional names can be added
  # squeezel

This is BusyBox's minimal conf.

  su = ssx root.0 # applet su can be run by anyone and runs with euid=0/egid=0
  su = ssx        # exactly the same

The following is used for acquiring an IP address via dhcp. The important setting here is the interface, which should be set to "eth0". The script that gets run "_install/usr/share/udhcpc/default.script" is the default BusyBox script for acquiring a dhcp address. Note, "etc/init.d/rcS" runs "/sbin/udhcpc", on bootup. You could remove this and assign a static IP address instead.

  # Sample udhcpd configuration file (/etc/udhcpd.conf)
  # The start and end of the IP lease block
  # The interface that udhcpd will use
  interface       eth0            #default: eth0
  # The maximim number of leases (includes addressesd reserved
  # by OFFER's, DECLINE's, and ARP conficts
  #max_leases     254             #default: 254
  # If remaining is true (default), udhcpd will store the time
  # remaining for each lease in the udhcpd leases file. This is
  # for embedded systems that cannot keep time between reboots.
  # If you set remaining to no, the absolute time that the lease
  # expires at will be stored in the dhcpd.leases file.
  #remaining      yes             #default: yes
  # The time period at which udhcpd will write out a dhcpd.leases
  # file. If this is 0, udhcpd will never automatically write a
  # lease file. (specified in seconds)
  #auto_time      7200            #default: 7200 (2 hours)
  # The amount of time that an IP will be reserved (leased) for if a
  # DHCP decline message is received (seconds).
  #decline_time   3600            #default: 3600 (1 hour)
  # The amount of time that an IP will be reserved (leased) for if an
  # ARP conflct occurs. (seconds
  #conflict_time  3600            #default: 3600 (1 hour)
  # How long an offered address is reserved (leased) in seconds
  #offer_time     60              #default: 60 (1 minute)
  # If a lease to be given is below this value, the full lease time is
  # instead used (seconds).
  #min_lease      60              #defult: 60
  # The location of the leases file
  #lease_file     /var/lib/misc/udhcpd.leases     #defualt: /var/lib/misc/udhcpd.leases
  # The location of the pid file
  #pidfile        /var/run/udhcpd.pid     #default: /var/run/udhcpd.pid
  # Everytime udhcpd writes a leases file, the below script will be called.
  # Useful for writing the lease file to flash every few hours.
  #notify_file                            #default: (no script)
  #notify_file    dumpleases      # <--- usefull for debugging
  # The following are bootp specific options, setable by udhcpd.
  #siaddr            #default:
  #sname          zorak                   #default: (none)
  #boot_file      /var/nfs_root           #default: (none)
  # The remainer of options are DHCP options and can be specifed with the
  # keyword 'opt' or 'option'. If an option can take multiple items, such
  # as the dns option, they can be listed on the same line, or multiple
  # lines. The only option with a default is 'lease'.

Copying utmp for the "who" command.

  $ cd proj1/_install/var/run/
  $ cp -pav /var/run/utmp .

STEP 6: Libraries

This configuration uses GNU Libc (glibc). In contrast, "uClibc" is smaller and easier to setup with ssh, since ssh or any program that makes a C call to "getpwname" will fail under glibc, if the appropriate Name Service Switch (NSS) files are not copied. Specifically, "/etc/nsswitch.conf", and "/lib/libnss_*" must be copied. Otherwise, runing the simple ssh command will produce the following error:

  $ ssh 
  you don't exist, go away!

You will get this error even if you have "etc/passwd", "etc/shadow",and "etc/shadow-", because getpwname cannot extract the correct values from "passwd". Here is a sample program to test this behavior. Reference the following program "getpwuid.c" in the following link [ http://prdownloads.sourceforge.net/cpearls/simple_but_common_cpp.tar.gz ] if you are curious about this behavior.

For the most part, you can find which libraries are dynamically linked into a program by issuing the "ldd" command. Try this on your own system.

  $ ldd /usr/bin/ssh
     libcrypto.so.4 => /lib/libcrypto.so.4 (0x003b8000)
     libutil.so.1 => /lib/libutil.so.1 (0x00dee000)
     libz.so.1 => /usr/lib/libz.so.1 (0x00827000)
     libnsl.so.1 => /lib/libnsl.so.1 (0x00d9b000)
     libcrypt.so.1 => /lib/libcrypt.so.1 (0x06182000)
     libselinux.so.1 => /lib/libselinux.so.1 (0x00db3000)
     libgssapi_krb5.so.2 => /usr/lib/libgssapi_krb5.so.2 (0x00d28000)
     libkrb5.so.3 => /usr/lib/libkrb5.so.3 (0x00c95000)
     libk5crypto.so.3 => /usr/lib/libk5crypto.so.3 (0x00cfc000)
     libcom_err.so.2 => /lib/libcom_err.so.2 (0x00c90000)
     libresolv.so.2 => /lib/libresolv.so.2 (0x00966000)
     libc.so.6 => /lib/tls/libc.so.6 (0x00607000)
     libdl.so.2 => /lib/libdl.so.2 (0x00758000)
     /lib/ld-linux.so.2 (0x005ee000)

As you can see above, these are all the libraries needed by ssh. However, again, you have been slightly misled, as there is no listing for "/lib/libnss_*".

All of the dynamically libraries need to be copied. Below is a complete listing of all libraries copied. You will need to copy them from your system or from the proj1 developer environment.

  $ cd <into the proj1 directory>
  $ find . -iname '*\.so\.*'

STEP 7: Compiling and Configuring SSH

Download ssh, configure and make. Next, all files must be installed in the into the respective "_install/*" directories, without changing the keys, configs, or other files installed on your running environment. Furthermore, you'll need to have all the libraries linked correct. Basically, this means running "make install" in a "chroot" environment. But, if you "chroot", "/bin/bash" cannot be found. Plus, there are a few lib's needed with make.

Download the latest version of openssh. Note you should check the signed keys.

       $ wget http://mirror.mcs.anl.gov/openssh/portable/openssh-3.9p1.tar.gz 

[**** Special Security Note ****]

In general it's good to verify keys with a trusted signature. Not covered here; but, it is something like the following. You'll need gpg. See Linux Tips in the reference.

  $ wget http://mirror.mcs.anl.gov/openssh/portable/openssh-3.9p1.tar.gz.sig
  $ wget http://mirror.mcs.anl.gov/openssh/portable/DJM-GPG-KEY.asc
  $ gpg --import DJM-GPG-KEY.asc
  $ gpg --verify openssh-3.9p1.tar.gz.sig  openssh-3.9p1.tar.gz

[**** End Special Security Note *]

If you are working in the "proj1" directory that was downloaded, you'll need to clear out any existing ssh file.

  $ cd proj1
  $ find _install/usr/ -iname 'ssh*' -exec rm -f {} \;
  $ find _install/etc/ -iname 'ssh*' -exec rm -f {} \;
  $ find _install/bin/ -iname 'ssh*' -exec rm -f {} \;
  $ find _install/sbin/ -iname 'ssh*' -exec rm -f {} \;

Reference the file "proj1/removeSSH".

Note, do this in the "proj1/_install" directory as root.

  $ su -
  $ cd proj1/_install
  $ cp <location of openssh>  .
  $ tar -xzf openssh-3.9p1.tar.gz        
  $ cd openssh-3.9p1
  $ ./configure --prefix=

This should leave you with the following. Note the location of the User binaries and "System binaries" when using "--prefix=" without any directory specified.

         OpenSSH has been configured with the following options:
                              User binaries: /bin
                            System binaries: /sbin
                        Configuration files: /etc
                            Askpass program: /libexec/ssh-askpass
                               Manual pages: /man/manX
                                   PID file: /var/run
           Privilege separation chroot path: /var/empty
                     sshd default user PATH: /usr/bin:/bin:/usr/sbin:/sbin
                             Manpage format: doc
                                PAM support: no
                          KerberosV support: no
                          Smartcard support: no
                              S/KEY support: no
                       TCP Wrappers support: no
                       MD5 password support: no
                IP address in $DISPLAY hack: no
                    Translate v4 in v6 hack: yes
                           BSD Auth support: no
                       Random number source: OpenSSL internal ONLY
                       Host: i686-pc-linux-gnu
                   Compiler: gcc
             Compiler flags: -g -O2 -Wall -Wpointer-arith -Wno-uninitialized
         Preprocessor flags:
               Linker flags:
                  Libraries:   -lcrypto -lutil -lz -lnsl  -lcrypt

Now run make

  $ make   

A few files need to change. This assumes your current directory is "_install/openssh-3.9p1"

  $ mv ../../_install/usr/bin/install  ../../_install/usr/bin/installBB
  $ cp /usr/bin/install ../../_install/usr/bin/.

When this is done, "cd" so that your current directory is "_install".

  $ cd ..

Now, "chroot".

   $ chroot . /bin/sh -i
   BusyBox v1.00 (2005.02.21-00:50+0000) Built-in shell (ash)
   Enter 'help' for a list of built-in commands.
   $ cd openssh-3.9p1/
   $ make install

If all goes well, exit out of chroot.

   $ exit
   $ mv usr/bin/installBB usr/bin/install
   mv: overwrite `usr/bin/install'? y
   $ rm -rf openssh-3.9p1*

At this point ssh should be installed with the correct references to "etc", and all other files.

STEP 8: Compiling the Linux Kernel

You do not need to download the full kernel on each revision. Note, with the "linux-2.6.11.tar.gz" there is also a patch "patch-2.6.11.bz2". The patch get's applied to the "linux-2.6.10" kernel, assuming you had already downloaded it.

Assuming you have no linux kernel's downloaded.

  $ wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.11.tar.gz
  $ wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.11.tar.gz.sign

Next, grab the correct key and verify the signature.

  $ gpg --keyserver wwwkeys.pgp.net --recv-keys 0x517D0F0E
  $ gpg --verify linux-2.6.11.tar.gz.sign linux-2.6.11.tar.gz

At this point, you know the source code is valid. Unroll the "tar.gz".

  $ tar -xzf linux-2.6.11.tar.gz

[********** Special Note - What if you had the 2.6.10 kernel source? ***************]

If this is the case, all you need to install is the patch "patch-2.6.11.bz2". This is the preferred method, as it keeps you ".config" settings.

  $ wget http://www.kernel.org/pub/linux/kernel/v2.6/patch-2.6.11.bz2
  $ wget http://www.kernel.org/pub/linux/kernel/v2.6/patch-2.6.11.bz2.sign
  $ gpg --verify patch-2.6.11.bz2.sign patch-2.6.11.bz2

  $ cd linux-2.6.10   <-- note this is my existing source
  $ bzip2 -dc ../patch-2.6.11.bz2 | patch -p1
  $ cd ..

[********************* End Special Note ********************************************]

You may want to copy by kernel ".config", or take a look at it if downloading the ""cdrom_linux_boot_proj1.iso"" found all the drivers on your computer.

  $ wget 
  $ make xconfig   -- This will allow you to graphically look at all 
                      the options.

  $ make bzImage   -- Only do this
  $ cp arch/i386/boot/bzImage ${PROJDIR}/proj1/staging_iso_image/boot/isolinux/linux26

That is it for create the compress kernel image. It may be necessary to add in additional drivers. What driver modules are used by your current system? Check "/etc/modprobe.conf"

  $ cat "/etc/modprobe.conf"
  alias eth0 tg3

Notice above that "eth0", the network interface card on my current system is loading this module. If I look for "tg3" in all the kernel "Makefile's", I can see that "CONFIG_TIGON3" should compiled into the kernel.

  $ find . -iname 'Makefile' -exec grep -H 'tg3' {} \;
  ./drivers/net/Makefile:obj-$(CONFIG_TIGON3) += tg3.o

Check your device drives and set them to yes in the ".config" file. As you can see, the ".config" used for proj1 has this option set to yes so when the kernel boot it will automatically find the needed network drivers. These steps should be performed for any NICs, or USB devices needed at boot time.

  $ cat .config |grep 'CONFIG_TIGON3'

Also, if you want to NFS mount devices, you may want to include the NFS in the kernel

  (see cdrom_linux_boot_unionfs.iso)
For the complete kernel config for NFS see the following link:


UNIONFS (Optional Step)

Unionfs is a utility for merging several directories into a single unified view. For example, if you had directory "/Fruits" and "/Vegetables" then you can combine the contents of those two directories into a third, which will be "/mnt/healthy". For more usage examples, see the following article:


Unionfs will work on the 2.6.9+ kernels. The software can be downloaded from the following site:


Once downloaded, take a look at the Makefile. Below I have edited it to fit my environment, since my 2.6.11 kernel source is currently under "/home/chirico/kernel/BUILD/linux-2.6.11". So this is what my Unionfs Makefile looks like. All I did was change the variable LINUXSRC as shown below:

  # Makefile for the Linux 2.4 unionfs

  # this should point to where your kernel headers are
  #LINUXSRC = /lib/modules/`uname -r`/build
  # Chirico change below - put in your location
  LINUXSRC = /home/chirico/kernel/BUILD/linux-2.6.11

After this change, run "make", which will produce "unionfs.ko".

  # make

I copied "unionfs.ko" to the "_install/unionfs" directory. When you boot-up your cd, you can load this module manually.

  # insmod /unionfs/unionfs.ko

After loading successfully, you see it in "/proc/modules"

  # cat /proc/modules

Now, create the 3 directories.

  # mkdir -p /Fruits /Vegetables /mnt/healthy

And mount

  # mount -t unionfs -o dirs=/Fruits:/Begetables \  
            none /mnt/healthy
By the way, you can combine more than two directories. For example you could have done the following command.

  # mount -t unionfs -o dirs=/Fruits:/Vegetables:/etc \
            none /mnt/healthy

To see the full power of Unionfs, you should create files in each of the individual directories.

The real power of Unionfs comes with NFS. See the proj_unionfs.tar.gz or cdrom_linux_boot_unionfs.iso. There is a special "/sbin/nfsmount", copied from Fedora Core 3 "/bin/mount", that will work with version 4 of NFS. Do NOT copy over the BusyBox mount command.

  $ /sbin/nfsmount -t nfs /home2

See (TIP 104) on the How_to_Linux_and_Open_Source.txt tips in the reference on setting up the server to test the configuration.

STEP 9: The ISOLINUX Boot Loader

This is the boot loader. This is the first program run from the CD.

Note the following directory layout in "proj1/staging_iso_image/"

  $ cd proj1/staging_iso_image
  $ tree .
  `-- boot
      `-- isolinux
          |-- boot.cat
          |-- isolinux.bin
          |-- isolinux.cfg
          |-- linux26
          `-- menu.txt

There are two directories here "boot" and "isolinux", with all of the files under "isolinux". A description of each file is shown below:

boot.cat - The El Torito specification requires a "boot catalog" to be created.

isolinux.bin - This is the ISOLINUX boot loader program

isolinux.cfg - Configuration file that contains the necessary instructions for loading the kernel as shown directly below. The kernel is the file "linux26" and after the kernel loads, the compressed image file "initrd.bin" will be mounted on "/dev/ram0". After it gets mounted the program "/sbin/init", will start.

        default 1
        prompt 1
        timeout 300
        display menu.txt
        label 1
          kernel linux26
          append ramdisk_size=128000 initrd=initrd.bin init=/sbin/init root=/dev/ram0
        label 2
          kernel linux26
          append ramdisk_size=128000 initrd=initrd.bin init=/sbin/init root=/dev/ram0 ramdisk_size=128000 vga=788
        label 3
        kernel linux26
        append ramdisk_size=128000 initrd=initrd.bin init=/sbin/init root=/dev/ram0 ramdisk_size=128000 vga=791

linux26 - This is the kernel image, or the results of "make bzImage".

menu.txt - A menu specified in "isolinux.cfg" is shown directly below:

      Choose Menu Option
         1) Text Mode
         2) 800x600 x 16bit color
         3) 1024x768 x 16bit color
       Copyright GPL (c) Mike Chirico
       For instructions on how to build your own:
       Password for root is root

STEP 10: mkisofs - command to make CD image

The following command is run from the "proj1" directory. It is helpful to look at the "createiso" file for the complete process, which includes the command for building images/initrd.bin in the compressed format.

      $ mkisofs -R -b isolinux/isolinux.bin -c isolinux/boot.cat \
          -no-emul-boot -boot-load-size 4 -boot-info-table -o \
          iso/cdrom_linux_boot_proj1.iso staging_iso_image/boot



(f.1) Can you store additional data on the cdrom and read it after boot-up? How?

You must have the correct "major" and "minor" numbers for your cdrom device. For example, I have a "Second IDE hard disk/CD-ROM interface." See http://souptonuts.sourceforge.net/devices.txt for the match on that, which tells me I need "22 block 0" for the mknod command. To get this mounted, all the commands are listed here below.

    # mkdir /cdrom
    # mknod -m 600 /dev/hdc b 22 0
    # mount -t iso9660 -r /dev/hdc /cdrom

(f.2) What are all the steps needed for Unionfs?

You should download and burn http://prdownloads.sourceforge.net/souptonuts/cdrom_linux_boot_unionfs.iso

After you boot from the cd, issue the following command to load the unionfs kernel module.

   # insmod /unionfs/unionfs.ko

Now assuming you have an "ext3" filesystem on "/dev/hda2", mount it

   # mkdir /h
   # mount -t ext3 /dev/hda2 /h

Assuming the above filesystem has "/h/etc", "/h/bin", "/h/lib" and "/h/usr" these directories can be union mounted on top of "/etc","/bin", "/lib" and "/usr" as follows:

   # mount -t unionfs -o dirs=/etc:/h/etc=ro none /etc
   # mount -t unionfs -o dirs=/bin:/h/bin=ro none /bin
   # mount -t unionfs -o dirs=/lib:/h/lib=ro none /lib
   # mount -t unionfs -o dirs=/usr:/h/usr=ro none /usr

So what does this do? Well, now you can use gcc, emacs and a lot of the applications on the hard drive.

(f.3) How do I create the compressed initrd.bin file?

This is done in the script createiso.


To receive email when when substantial updates occur, or corrections are found, click here.


Websites For Downloading Software

BusyBox (No need to install tinylogin, everything is included here)

Isolinux ( software can be found on www.kernel.org )

Linux Kernel



Linux from Scratch

Recommended Reading

Virtual Filesystem: Building A Linux Filesystem From An Ordinary File

"Building Embedded Linux Systems", by Karim Yaghmour O'Reilly, 2003
ISBN 0-596-00222-X, pages 416.

BusyBox FAQ

100+ Linux Tips

Kernel Korner - Unionfs: Bringing Filesystems Together

Related Websites


Other Tutorials

Gmail on Home Linux Box using Postfix and Fetchmail: If you have a Gmail account and would like to use it in conjunction with your personal computers, this tutorial will walk you through configuring and installing the latest version of Postfix with SASL authentication and TLS encryption necessary for connecting and relaying mail to smtp.gmail.com and configuring fetchmail with STARTTLS to fetch messages from your Gmail account to your local system. It will also discuss how to forward mail to other computers and how to automatically backup copies of email messages.

Breaking Firewalls with OpenSSH and PuTTY: If the system administrator deliberately filters out all traffic except port 22 (ssh), to a single server, it is very likely that you can still gain access other computers behind the firewall. This article shows how remote Linux and Windows users can gain access to firewalled samba, mail, and http servers. In essence, it shows how openSSH and Putty can be used as a VPN solution for your home or workplace.

SQLite Tutorial : This article explores the power and simplicity of sqlite3, first by starting with common commands and triggers, then the attach statement with the union operation is introduced in a way that allows multiple tables, in separate databases, to be combined as one virtual table, without the overhead of copying or moving data. Next, the simple sign function and the amazingly powerful trick of using this function in SQL select statements to solve complex queries with a single pass through the data is demonstrated, after making a brief mathematical case for how the sign function defines the absolute value and IF conditions.

The Lemon Parser Tutorial: This article explains how to build grammars and programs using the lemon parser, which is faster than yacc. And, unlike yacc, it is thread safe.

How to Compile the 2.6 kernel for Red Hat 9 and 8.0 and get Fedora Updates: This is a step by step tutorial on how to compile the 2.6 kernel from source.

Linux System Admin Tips: There are over 160 linux tips and tricks in this article. This article is updated weekly.

Virtual Filesystem: Building A Linux Filesystem From An Ordinary File. You can take a disk file, format it as ext2, ext3, or reiser filesystem and then mount it, just like a physical drive. Yes, it then possible to read and write files to this newly mounted device. You can also copy the complete filesystem, sinc\ e it is just a file, to another computer. If security is an issue, read on. This article will show you how to encrypt the filesystem, and mount it with ACL (Access Control Lists), which give you rights beyond the traditional read (r) write (w) and execute (x) for the 3 user groups file, owner and other.

Working With Time: What? There are 61 seconds in a minute? We can go back in time? We still tell time by the sun?

Chirico img Mike Chirico, a father of triplets (all girls) lives outside of Philadelphia, PA, USA. He has worked with Linux since 1996, has a Masters in Computer Science and Mathematics from Villanova University, and has worked in computer-related jobs from Wall Street to the University of Pennsylvania. His hero is Paul Erdos, a brilliant number theorist who was known for his open collaboration with others.

Mike's notes page is souptonuts. For open source consulting needs, please send an email to mchirico@comcast.net. All consulting work must include a donation to SourceForge.net.

SourceForge.net Logo