<?xml version="1.0" encoding="ISO-8859-1"?>
<chapter>
  <title>Bootstrapping The System</title>

  <section>
    <title>What Is Bootstrapping?</title>

    <para></para>
  </section>

  <section>
    <title>Installing A Development System</title>

    <procedure>
      <step>
        <para>Find a PC that can be dedicated to the purpose of bootstrapping
        a system. Do not try to do this on a dual-boot system or any other
        production system, because it <emphasis>will</emphasis> get broken. If
        only one PC is available consider using a removable hard drive tray
        system to fully remove any valuable data before proceding. (See <ulink
        url="http://www.vantecusa.com/product-storage.html">Vantec's
        site</ulink> for an example of what is available.)</para>
      </step>

      <step>
        <para>Select a modern GNU/Linux distribution and install it onto a
        blank hard disk. Leave about 2G of unpartitioned disk space to be used
        for the bootstrap system.</para>
      </step>
    </procedure>
  </section>

  <section>
    <title>Installing Basic System Packages</title>

    <procedure>
      <step>
        <para>Use architect to build the following binary packages:</para>

        <itemizedlist>
          <listitem>
            <para>bash-static</para>
          </listitem>

          <listitem>
            <para>coreutils</para>
          </listitem>

          <listitem>
            <para>e2fsprogs</para>
          </listitem>

          <listitem>
            <para>ed</para>
          </listitem>

          <listitem>
            <para>glibc</para>
          </listitem>

          <listitem>
            <para>gzip</para>
          </listitem>

          <listitem>
            <para>mdadm (optional for software RAID)</para>
          </listitem>

          <listitem>
            <para>modutils</para>
          </listitem>

          <listitem>
            <para>procps</para>
          </listitem>

          <listitem>
            <para>sysvinit</para>
          </listitem>

          <listitem>
            <para>tar</para>
          </listitem>

          <listitem>
            <para>util-linux</para>
          </listitem>
        </itemizedlist>
      </step>

      <step>
        <para>Create a second extended filesystem of about 2G in size and
        mount it on <filename>/mnt</filename>.</para>

        <para>The following example show this task being done using /dev/hdb2
        as the partition for the bootstrap system. Make changes as needed when
        using a partition that is different than the example.</para>

        <screen><prompt>dev-system#</prompt> mke2fs /dev/hdb2
<prompt>dev-system#</prompt> mount /dev/hdb2 /mnt</screen>
      </step>

      <step>
        <para>Create an FHS compliant directory structure rooted in
        <filename>/mnt</filename>. (See
        <filename>architect/extra/install-tools/mkfhs</filename>)</para>
      </step>

      <step>
        <para>Extract all of the recently created binary packages onto the new
        filesystem mounted on <filename>/mnt</filename>.</para>
      </step>

      <step>
        <para>Create device nodes in /mnt/dev. (See
        <filename>architect/extra/system-scripts/dev/MAKEDEV</filename>)</para>
      </step>
    </procedure>

    <para>Not all of the packages above are absolutely essential for system
    operation. In fact, most of the work is done by bash-static, coreutils and
    util-linux with glibc providing the libraries. The other packages are
    mainly for convenience. For example, packages like mdadm and modutils,
    although not essential, are installed to aid those who would like to use
    kernel features like software RAID and loadable modules. Other packages,
    like ed, gzip, tar and sysvinit will be used in upcoming stages but are
    installed now in order to cut down the number of steps in the bootstrap
    installation.</para>
  </section>

  <section>
    <title>Booting The New System</title>

    <section>
      <title>Booting From Diskette</title>

      <para></para>

      <procedure>
        <step>
          <para>Use architect to build grub (or grub-serial0)</para>
        </step>

        <step>
          <para>Construct a GRUB bootdisk.</para>
        </step>

        <step>
          <para>Boot the system manually using the grub command-line.</para>

          <para>For a serial console system the commands would be similar to
          the following example:</para>

          <screen><prompt>grub&gt;</prompt> kernel (fd0)/boot/vmlinuz console=ttyS0,9600 root=/dev/hdb2 init=/bin/sh
<prompt>grub&gt;</prompt> boot</screen>

          <para>Be sure to change the <parameter>root=</parameter> parameter
          to fit your system setup and leave out the console=ttyS0,9600 for
          non-serial console systems.</para>
        </step>
      </procedure>
    </section>

    <section>
      <title>Exploring Functionality</title>

      <para></para>

      <procedure>
        <step>
          <para>Verify that the system comes up to a <prompt>#</prompt>
          prompt.</para>
        </step>

        <step>
          <para>Set a proper PATH variable.</para>

          <para>Some commands will only be accessible using a fully qualified
          path unless the environmental variable PATH is set to a reasonable
          value. Since the bootstrap system is in superuser mode it is good to
          include all of the various sbin directories as well as the bin
          directories as shown in the example below.</para>

          <screen>sh# export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin</screen>
        </step>

        <step>
          <para>Test basic system commands.</para>
        </step>

        <step>
          <para>Manually remount the root filesystem.</para>

          <para>The example below shows how to do this for a root filesystem
          that is on /dev/hdb2. Adjust accordingly if the root filesystem is
          on a different device.</para>

          <screen><prompt>#</prompt> mount -n -o remount,rw /dev/hdb2 /
<prompt>#</prompt> mount -f -t ext2 /dev/hdb2 /</screen>

          <para>Disregard any warning messages about missing
          <filename>fstab</filename> or <filename>mtab</filename>
          files.</para>
        </step>

        <step>
          <para>Create an <filename>/etc/fstab</filename> file for next
          time.</para>

          <para>Assuming the root filesystem is on /dev/hdb2 as in previous
          examples a simple fstab may be created using the
          <command>cat</command> command.</para>

          <screen><prompt>#</prompt> cat &lt;&lt;EOF &gt;/etc/fstab
<prompt>&gt;</prompt> /dev/hdb2     /          ext2     defaults     1     1
<prompt>&gt;</prompt> proc          /proc      proc     defaults     0     0
<prompt>&gt;</prompt> EOF</screen>

          <para>Test by mounting proc using only the mount-point as an
          argument to the <command>mount</command> command (i.e.
          <command>mount /proc</command>).</para>
        </step>

        <step>
          <para>Unmount filesystems using the <filename>local_fs</filename>
          script.</para>

          <para>Navigate to the /etc/init.d directory and run local_fs with
          the stop command-line argument as shown below.</para>

          <screen><prompt>#</prompt> cd /etc/init.d
<prompt>#</prompt> ./local_fs stop</screen>

          <note>
            <para>If the shell complains about "permission denied" make sure
            the scripts have the execute permission set. <command>chmod
            750</command> will do the trick.</para>
          </note>
        </step>

        <step>
          <para>Reboot the PC and go back the development system.</para>

          <para>For non-serial console systems this can be done with the
          <keycap>CTRL</keycap>-<keycap>ALT</keycap>-<keycap>DELETE</keycap>
          sequence. Systems using a serial console will need a hard reset
          since the three finger salute will reset the system running the
          terminal emmulator rather than the intended host. Remember to remove
          the boot diskette.</para>
        </step>
      </procedure>
    </section>
  </section>

  <section>
    <title>Installing Basic Development Tools</title>

    <para></para>

    <procedure>
      <step>
        <para>Boot into the development system.</para>
      </step>

      <step>
        <para>Use architect to build the following binary packages:</para>

        <itemizedlist>
          <listitem>
            <para>binutils</para>
          </listitem>

          <listitem>
            <para>bison</para>
          </listitem>

          <listitem>
            <para>diffutils</para>
          </listitem>

          <listitem>
            <para>findutils</para>
          </listitem>

          <listitem>
            <para>flex</para>
          </listitem>

          <listitem>
            <para>gawk</para>
          </listitem>

          <listitem>
            <para>gcc</para>
          </listitem>

          <listitem>
            <para>grep</para>
          </listitem>

          <listitem>
            <para>m4</para>
          </listitem>

          <listitem>
            <para>make</para>
          </listitem>

          <listitem>
            <para>patch</para>
          </listitem>

          <listitem>
            <para>sed</para>
          </listitem>
        </itemizedlist>
      </step>

      <step>
        <para>Copy the binary packages to the bootstrap system.</para>

        <para>Mount the bootstrap filesystem on /mnt, create a directory
        called <filename>/mnt/var/spool/packages/</filename> and copy the new
        packages into it.</para>
      </step>

      <step>
        <para>Reboot into the bootstrap system.</para>
      </step>

      <step>
        <para>Extract all of the recently created binary packages onto the
        bootstrap system.</para>

        <para></para>
      </step>

      <step>
        <para>Test the compiler and linker.</para>

        <para>Write a simple hello world program like the one shown below.
        This can be accomplished using the <command>ed</command> editor or the
        old cat &lt;&lt;EOF trick. Save the file as
        <filename>hello.c</filename>.</para>

        <programlisting>#include &lt;stdio.h&gt;

int
main () {
  printf("Hello World!\n");
}</programlisting>

        <para>Build a binary using gcc and run it. Check for any compilation
        or runtime errors. The example below demonstrates a successful
        test.</para>

        <screen><prompt>sh#</prompt> gcc -o hello hello.c
<prompt>sh#</prompt> ./hello
Hello World!</screen>
      </step>
    </procedure>
  </section>

  <section>
    <title>Building A Kernel On The New System</title>

    <procedure>
      <step>
        <para>Download the latest tar.gz kernel source package onto the
        development system.</para>

        <para>This first step is only necessary because the bootstrap system
        cannot download files from the Internet. Once the source is downloaded
        to the development system it is easy to copy it over to the bootstrap
        system.</para>
      </step>

      <step>
        <para>Start up the bootstrap system.</para>

        <para>Use the GRUB boot diskette with the same procedure as when the
        system was booted for the first time. When a shell prompt appears
        remount the root filesystem as read-write and mount the proc
        filesystem.</para>
      </step>

      <step>
        <para>Check the time and timezone setting on the bootstrap
        system.</para>

        <para>The following example shows how to set the proper time zone for
        someone living in Chicago, IL USA (central time zone).</para>

        <screen>bash# cd /usr/share/zoneinfo/US
bash# cp Central /etc/localtime
</screen>

        <para>Once the time zone is set check the time with the
        <command>date</command> command. If the PC's hardware clock is set to
        local time, rather than Greenwich Mean the time will be wrong. In this
        case it is necessary to update the kernel clock to match the hardware
        clock as show in the following example.</para>

        <screen><prompt>bash#</prompt> date
&lt;wrong time shown&gt;
<prompt>bash#</prompt> /sbin/hwclock --hctosys
<prompt>bash#</prompt> date
&lt;correct time shown&gt;</screen>

        <para>If the time is not fixed, there is a chance that the
        <command>make</command> commands we use later could get confused since
        <command>make</command> uses a file's timestamp to see what is
        up-to-date and what needs to be built.</para>
      </step>

      <step>
        <para>Copy the kernel source tarball to the bootstrap system's
        <filename>/usr/src</filename> directory.</para>

        <para>This can be accomplished in a few different ways, but the most
        straightforward may be to mount the development system's root
        filesystem on /mnt and copy the source tarball from there. It is also
        possible to put the source on a CD-ROM or Zip disk. Those looking for
        an extra challenge may want to try using <command>tftp</command> to
        fetch the source from another PC on the local network. This requires a
        tftp server on your network, as well as building the net-tools and
        netkit-tftp packages and setting up
        <filename>/etc/protocols</filename> and
        <filename>/etc/services</filename> on the bootstrap system.</para>
      </step>

      <step>
        <para>Unpack the code and create a symbolic link called
        <filename>linux</filename> that points to the kernel source code
        directory.</para>

        <para>The following example demonstrates what the process looks like
        on the bootstrap system.</para>

        <screen><prompt>bash#</prompt> cd /usr/src
<prompt>bash#</prompt> ls
<computeroutput>linux-2.4.27.tar.gz</computeroutput>
<prompt>bash#</prompt> tar -zxf linux-2.4.27.tar.gz
<prompt>bash#</prompt> ls
<computeroutput>linux-2.4.27/  linux-2.4.27.tar.gz</computeroutput>
<prompt>bash#</prompt> ln -s linux-2.4.27 linux
<prompt>bash#</prompt> ls
<computeroutput>linux@  linux-2.4.27/  linux-2.4.27.tar.gz</computeroutput></screen>
      </step>

      <step>
        <para>Change directory to /usr/src/linux and configure the kernel
        source.</para>

        <para>Since no ncurses library is loaded on the bootstrap system the
        only option for configuring the kernel source is to use <command>make
        config</command> . Anyone who has ever tried this knows that the
        <command>make config</command> method of kernel configuration can be
        slow and very unforgiving of mistakes. But, if things go well it only
        has to be done this way once.</para>
      </step>

      <step>
        <para>Run <command>make dep</command> on the kernel source.</para>

        <para>Many source packages depend upon parts of the kernel source in
        order to build correctly. A lot of this has to do with the symbolic
        links /usr/include/asm and /usr/include/linux pointing to directories
        within the Linux source code. So even if a new kernel is not needed it
        is still necessary to do <command>make dep</command> on the kernel
        source.</para>
      </step>

      <step>
        <para>Run <command>make bzImage</command> to create a new
        kernel.</para>

        <para>Those who are happy with the kernel on the boot disk may be
        tempted to skip this step. However building a kernel is a good way to
        test the development tools on the bootstrap system and shake out any
        bugs. If the kernel build is successful there is a good chance that
        compiling other packages will be successful as well. If there are
        problems with the kernel build the solution should be investigated and
        resolved before moving on to build other packages.</para>
      </step>
    </procedure>
  </section>

  <section>
    <title>Building Additional Development Tools</title>

    <para>There are several packages that need to be built because other
    packages depend upon them. For example, BASH cannot be built without
    having the ncurses library installed first and postfix will not work
    without db.</para>

    <procedure>
      <step>
        <para>Fetch the source code for the db, gettext, ncurses, texinfo and
        zlib packages.</para>

        <para>This can be done is several ways just like the kernel source
        code. Options include mounting the development system's hard drive on
        /mnt of the bootstrap system, burning a CD-ROM, copying to Zip disk or
        using tftp.</para>
      </step>

      <step>
        <para>Unpack the source code tarballs in /usr/src.</para>
      </step>

      <step>
        <para>Install the latest GNU/Linux Architect Toolkit.</para>

        <para>The latest Architect Toolkit is available from SourceForge.
        Architect should be unpacked into the /usr/local hierarchy and a
        symbolic link made for /usr/local/bin/architect. The example below
        shows how to do this via tftp.</para>

        <screen><prompt>sh#</prompt> mkdir /usr/local
<prompt>sh#</prompt> cd /usr/local
<prompt>sh#</prompt> tftp
<prompt>tftp&gt;</prompt> connect 192.168.1.1
<prompt>tftp&gt;</prompt> get architect-0.10a.tar.gz
<prompt>tftp&gt;</prompt> quit
<prompt>sh#</prompt> tar -zxf architect-0.10a.tar.gz
<prompt>sh#</prompt> mkdir /usr/local/bin
<prompt>sh#</prompt> cd /usr/local/bin
<prompt>sh#</prompt> ln -s ../architect/bin/architect architect</screen>
      </step>

      <step>
        <para>Use architect to build the gettext, ncurses and zlib library
        packages.</para>

        <para>The order in which these packages are built is not important.
        However, there is one thing to watch out for. Do not attempt to build
        the ncurses-with-fallbacks package until the regular ncurses package
        has been built and installed. The reason is that using the
        --with-fallbacks option in the configure script of
        ncurses-with-fallbacks requires that the terminfo database be present.
        This creates a paradox since there will not be a terminfo database
        until ncurses is installed. To use fallbacks build and install regular
        ncurses first then build and install ncurses-with-fallbacks.</para>
      </step>

      <step>
        <para>Install the new packages on the bootstrap system.</para>

        <para>Assuming the bootstrap system is currently booted and active the
        following example shows how to quickly install the packages built in
        the previous step.</para>

        <screen>sh# cd /var/tmp/staging
sh# ls *.i386.tar.gz
gettext-0.14.1.i386.tar.gz  ncurses-5.4.i386.tar.gz  zlib-1.2.1.i386.tar.gz
sh# for PKG in *.i386.tar.gz; do echo "Installing $PKG"; tar -C / -zxf $PKG; done
Installing gettext-0.14.1
Installing ncurses-5.4.i386.tar.gz
Installing zlib-1.2.1.i386.tar.gz</screen>
      </step>
    </procedure>
  </section>

  <section>
    <title>Making The System More Friendly</title>

    <para>Most people will probably want to install BASH to take advantage of
    features, like command completion and command-line history, that are not
    present in bash-mini. The vi editor from the Elvis package might be high
    on the list of cool tools as well. This will be no problem since ncurses
    was installed in the previous bootstrap phase. And finally it would be
    great to automate many of the system startup and shutdown tasks.</para>

    <procedure>
      <step>
        <para>Fetch the source code for the bash and elvis packages.</para>

        <para>The example below shows source code being downloaded from a tftp
        server on the local network. Fetching from disk or CD-ROM is even
        easier.</para>

        <screen><prompt>sh#</prompt> cd /usr/src
<prompt>sh#</prompt> tftp
<prompt>tftp&gt;</prompt> connect 192.168.1.1
<prompt>tftp&gt;</prompt> get bash-3.0.tar.gz
Received 2436918 bytes in 1.6 seconds
<prompt>tftp&gt;</prompt> get elvis-2.2_0.tar.gz
Received 1450266 bytes in 1.1 seconds
<prompt>tftp&gt;</prompt> quit
<prompt>sh#</prompt> tar -zxf bash-3.0.tar.gz
<prompt>sh#</prompt> tar -zxf elvis-2.2_0.tar.gz</screen>
      </step>

      <step>
        <para>Build and install both bash and elvis on the bootstrap
        system.</para>

        <para>Typical installation is shown in the following example.</para>

        <screen>sh# cd /var/tmp/staging
sh# tar -C / -zxf bash-3.0.i386.tar.gz
sh# tar -C / -zxf elvis-2.2_0.i386.tar.gz</screen>
      </step>

      <step>
        <para>Use and enjoy BASH.</para>

        <para>Start up bash by typing its name on the command-line. If the
        PATH variable is not set correctly it may be necessary to give the
        full path to the bash binary as shown in the example below.</para>

        <screen><prompt>sh#</prompt> bash
sh: bash: command not found
<prompt>sh#</prompt> /usr/bin/bash
<prompt>bash-3.00#</prompt></screen>
      </step>

      <step>
        <para>Create an <filename>/etc/profile</filename> login script using
        vi.</para>

        <para>A simple /etc/profile script will take care of mundane tasks
        like remembering to set the PATH variable each time. A simple example
        is shown below.</para>

        <programlisting># /etc/profile - system login script

if [ $UID -eq 0 ]; then
  PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
else
  PATH=/usr/bin:/bin:/usr/local/bin
fi

case $0 in
  -sh|sh)
    if [ $UID -eq 0 ]; then
      PS1='# '
    else
      PS1='$ '
    fi
  ;;
  -bash|bash)
    PS1='\h:\w\$ '
    alias ls='ls -F'
  ;;
esac
</programlisting>

        <para>This script also found in the
        <filename>/usr/local/architect/extra/config-files/etc/</filename>
        directory.</para>
      </step>

      <step>
        <para>Restart BASH to make /etc/profile take effect.</para>

        <para>Using the <option>--login</option> option when invoking bash
        will cause it to read and execute the contents of
        <filename>/etc/profile</filename> as the following example
        demonstrates.</para>

        <screen>bash-3.00# exit
sh# /usr/bin/bash --login
(none):/#</screen>
      </step>

      <step>
        <para>Create <filename>/etc/passwd</filename> and
        <filename>/etc/group</filename>.</para>
      </step>

      <step>
        <para>Create additional <filename>init.d</filename> scripts to
        automate startup tasks.</para>
      </step>

      <step>
        <para>Write an <filename>/etc/inittab</filename> file and make rc.d
        symlinks.</para>

        <para>There is no networking support yet so only runlevels S, 0, 1, 2
        and 6 are of any concern.</para>
      </step>
    </procedure>
  </section>

  <section>
    <title>Taking Care Of Package Dependencies</title>

    <para>Some packages depend upon other packages being present in order to
    build correctly. For example the at daemon will send an email when an at
    job finishes so it needs to have sendmail (postfix) installed in order to
    work.</para>

    <procedure>
      <step>
        <para>Fetch the source code for the following packages.</para>

        <itemizedlist>
          <listitem>
            <para>groff</para>
          </listitem>

          <listitem>
            <para>less</para>
          </listitem>

          <listitem>
            <para>postfix</para>
          </listitem>
        </itemizedlist>
      </step>
    </procedure>
  </section>

  <section>
    <title>Installing The Remaining Packages</title>

    <para></para>

    <procedure>
      <step>
        <para>Build the packages listed below.</para>

        <para>The remaining packages required for a full-featured system are
        listed below. These can be built in any order.</para>

        <itemizedlist>
          <listitem>
            <para>bc</para>
          </listitem>

          <listitem>
            <para>cpio</para>
          </listitem>

          <listitem>
            <para>dcron</para>
          </listitem>

          <listitem>
            <para>file</para>
          </listitem>

          <listitem>
            <para>iptables</para>
          </listitem>

          <listitem>
            <para>LPRng</para>
          </listitem>

          <listitem>
            <para>man</para>
          </listitem>

          <listitem>
            <para>netkit-base</para>
          </listitem>

          <listitem>
            <para>netkit-ftp</para>
          </listitem>

          <listitem>
            <para>netkit-telnet</para>
          </listitem>

          <listitem>
            <para>netkit-tftp</para>
          </listitem>

          <listitem>
            <para>net-tools</para>
          </listitem>

          <listitem>
            <para>psmisc</para>
          </listitem>

          <listitem>
            <para>rsync</para>
          </listitem>

          <listitem>
            <para>shadow</para>
          </listitem>

          <listitem>
            <para>sysklogd</para>
          </listitem>

          <listitem>
            <para>time</para>
          </listitem>
        </itemizedlist>

        <para>Some of the packages in the list contain commands that are
        required by the Linux Standard Base (LSB) specification.</para>
      </step>

      <step>
        <para>Install the packages onto the running bootstrap system.</para>
      </step>

      <step>
        <para>Test the new packages.</para>
      </step>
    </procedure>
  </section>

  <section>
    <title>Finalizing System Configuration</title>

    <para></para>

    <procedure>
      <step>
        <para>Add support for runlevel 3.</para>

        <para>Create directory, symlinks</para>
      </step>

      <step>
        <para>Create configuration files for basic network
        connectivity.</para>

        <para>IP address, route, firewall</para>
      </step>

      <step>
        <para>Configure network services.</para>

        <para>Enable telnet, rsync</para>
      </step>
    </procedure>
  </section>
</chapter>