<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.1//EN">

<book id="lwce20010827" lang="en">

  <bookinfo>
    <title>LTSP - Linux Terminal Server Project - v3.0</title>

    <authorgroup>
        <author>
           <firstname>James</firstname>
           <surname>McQuillan</surname>
           <affiliation>
              <address><email>jam@LTSP.org</email>
              </address>
           </affiliation>
        </author>
    </authorgroup>

    <revhistory>
       <revision>
         <revnumber>1.0.4&nbsp;</revnumber>
         <date>2002-03-02</date>
         <authorinitials>jam</authorinitials>
       </revision>
    </revhistory>

    <copyright>
        <year>2002</year>
        <holder>James A. McQuillan</holder>
    </copyright>

    <abstract>
       <para>
           GNU/Linux makes a great platform for deploying diskless thin clients.
           The primary purpose of this document is to show you how to deploy
           thin clients using LTSP.  But, this document also covers many issues
           with diskless workstations in general.
       </para>
    </abstract>
  </bookinfo>

<preface>
    <title>Introduction</title>

    <para>
        The LTSP provides a simple way to utilize low cost workstations
        as either graphical or character based terminals on a GNU/Linux server.
    </para>

    <para>
        In a traditional office setting, there are relatively high powered
        Intel based PC's spread around at every desk.  Each with several
        gigabytes of hard disk space.  Users store their own data on the local
        hard drives and backups are rarely (if ever) performed.
    </para>

    <para>
        Does it really make sense to have a full computer at each desk?
    </para>

    <para>
        We say no.
    </para>

    <para>
        Fortunately, there is another way.  Utilizing the LTSP, you can take
        very low-end PCs, remove the hard drive, floppy and CDRom, and add
        a bootable network card.  Many network cards have bootrom sockets,
        just waiting for a bootrom to be inserted.
    </para>

    <para>
        During the boot phase, the diskless workstation obtains its IP info
        and a kernel from the
        server, then mounts the root filesystem from the server via NFS.
    </para>

    <para>
        The workstation can be configured in one of 3 modes:
        <itemizedlist>
            <listitem>
                <para><command>Graphical X Windows</command></para>
                <para>
                    Using X Windows, the workstation can be used to access
                    any applications on the server, or on other servers
                    within the network.
                </para>
            </listitem>
        </itemizedlist>

        <itemizedlist>
            <listitem>
                <para><command>Character based Telnet sessions</command></para>
                <para>
                    The workstation can invoke multiple telnet sessions to the
                    server.  Each Telnet session will be on a separate virtual
                    screen.  Pressing Alt-F1 through Alt-F9 will switch
                    between the telnet sessions.
                </para>
            </listitem>
        </itemizedlist>

        <itemizedlist>
            <listitem>
                <para><command>Shell prompt</command></para>
                <para>
                    The workstation can be configured to drop you right into
                    a bash shell at the console.  This is very useful when
                    debugging problems with X Windows or NFS.
                </para>
            </listitem>
        </itemizedlist>
    </para>

    <para>
        The really neat thing is that you can have lots of workstations served
        by a single GNU/Linux server.  How many workstations?  Well, that
        depends on the size of the server, and the applications that will
        be used.
    </para>

    <para>
        It's not unusual to have 40 workstations, all running Netscape and
        StarOffice from a Dual PIII-650 with 1GB of ram.  We know this works.
        In fact, the load-average is rarely above 1.0!
    </para>

    <sect1>
        <title>Disclaimer</title>
        <para>
            Neither the author nor the distributors, or any other contributor of
            this document are in any way responsible for physical, financial,
            moral or any other type of damage incurred by following the
            suggestions in this text.
        </para>
    </sect1>

    <sect1 id="copyright">
        <title>Copyright and License</title>
        <para>
            This document is copyright 2001 by James McQuillan, and is 
            released under the terms of the GNU Free Documentation License,
            which is hereby incorporated by reference.
        </para>
    </sect1>
</preface>

<chapter>
    <title>Theory of operation</title>
    <para>
        Booting a diskless workstation involves several steps.  Understanding
        what is happening along the way will make it much easier to solve problems,
        should they arise.
    </para>
    <para>
        This example is based on the following configuration:
        <itemizedlist>
            <listitem>
                <para>Standard x86 based workstation</para>
            </listitem>
            <listitem>
                <para>
                    Linksys LNE100TX network card with Etherboot bootrom
                </para>
            </listitem>
            <listitem>
                <para>Intel i810 based graphics chipset</para>
            </listitem>
            <listitem>
                <para>Server running Redhat 7.2</para>
            </listitem>
            <listitem>
                <para>DHCP</para>
            </listitem>
            <listitem>
                <para>Network address of 192.168.0.0/24</para>
            </listitem>
        </itemizedlist>
    </para>

    <para>
    Assuming the server is configured with the LTSP package, this is
    what happens:
    </para>

    <orderedlist spacing="normal">
        <listitem>
            <para>
                When you turn on the workstation, it will go through its
                "Power On Self Test" (POST).
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                During the self test, the bios will search for expansion
                roms.  The network card contains an Etherboot bootrom, which
                is an expansion rom.  The bios will detect the rom on the
                network card.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                Once the POST is complete, execution will jump into the
                Etherboot code.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                The Etherboot code will scan for a network card.  Once it
                detects the card, the card will be initialized.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                The Etherboot code will then broadcast a DHCP request to
                the local network.  The request will include the MAC
                address of the network card.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                The dhcpd daemon on the server will see the broadcast
                request from the workstation, and look in its configuration
                file for an entry that matches the MAC address of that
                workstation.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                The dhcpd daemon will construct a reply packet,
                containing several pieces of information. This packet
                will be sent back to the workstation.
                The reply information includes:
                <itemizedlist>
                    <listitem>
                        <para>
                            IP address for the workstation
                        </para>
                    </listitem>
                    <listitem>
                        <para>
                            NETMASK setting for the local network
                        </para>
                    </listitem>
                    <listitem>
                        <para>
                            Pathname of the kernel to download
                        </para>
                    </listitem>
                    <listitem>
                        <para>
                            Pathname of the root filesystem to mount
                        </para>
                    </listitem>
                    <listitem>
                        <para>
                            Optional parameters to be passed to the kernel,
                            via the kernel command line
                        </para>
                    </listitem>
                </itemizedlist>
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                The Etherboot code will receive the reply from the server,
                and it will configure the TCP/IP interface in the network
                card with the parameters that were supplied.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                Using TFTP (Trivial File Transfer Protocol), the Etherboot
                code will contact the server and begin downloading the kernel.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                Once the kernel has been completely downloaded to the
                workstation, the Etherboot code will place the kernel into
                the correct location in memory.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                Control is then passed to the Kernel.  The kernel will
                initialize the entire system and all of the peripherals
                that it recognizes.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                This is where the fun really begins.  Tacked onto the end
                of the kernel is a filesystem image.  This is loaded into
                memory as a ramdisk, and temporarily mounted as the root
                filesystem. A kernel command line argument of
                <command>root=/dev/ram0</command> tells the kernel to mount
                the image as the root directory.
            </para>
            <para></para>
        </listitem>
                 
        <listitem>
            <para>
                Normally, when the kernel is finished booting, it will launch
                the <command>init</command> program.  But, in this case,
                we've instructed the kernel to load a shell script instead.
                We do this by passing <command>init=/linuxrc</command> on
                the kernel command line.
            </para>
            <para></para>
        </listitem>
                
        <listitem>
            <para>
                The <command>/linuxrc</command> script begins by scanning
                the PCI bus, looking for a network card. For each PCI device
                it finds, it does a lookup in the /etc/niclist file, to see
                if it finds a match.  Once a match is found, the name of
                the NIC driver module is returned, and that kernel module
                is loaded.  For ISA cards, the driver module MUST be specified
                on the kernel command line, along with any IRQ or address
                parameters that are required.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                Once the network card has been identified, the /linuxrc
                script will load the kernel module that supports that card.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                <command>dhclient</command> will then be run, to make another
                query from the DHCP server.  We need to do this separate
                user-space query, because if we depend on the query that comes
                from Etherboot, it will get swallowed up by the kernel.  And,
                the kernel will ignore any NFS server that might have been
                specified in the root-path.  This is important if you want
                the NFS server to be different from the TFTP server.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                When <command>dhclient</command> gets a reply from the server,
                it will run the <command>/etc/dhclient-script</command> file,
                which will take the information retrieved, and configure the
                eth0 interface.
            </para>
            <para></para>
        </listitem>


        <listitem>
            <para>
                Upto this point, the root filesystem has been a ram disk.
                Now, the /linuxrc script will mount a new root filesystem
                via NFS.  The directory that is exported from the server
                is typlically <command>/opt/ltsp/i386</command>.
                It can't just mount the new filesystem as /.  It must
                first mount it as /mnt.  Then, it will do a
                <command>pivot_root</command>.  pivot_root will swap the
                current root filesystem for a new filesystem.  When it
                completes, the NFS filesystem will be mounted on /, and the
                old root filesystem will be mounted on /oldroot.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                Once the mounting and pivoting of the new root filesystem
                is complete, we are done with the /linuxrc shell script and
                we need to invoke the real <command>init</command> program.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                Init will read the <filename>/etc/inittab</filename> file
                and begin setting up the workstation environment.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                Init maintains an idea of <emphasis>runlevel</emphasis>.  Each
                runlevel sets up a different set of services for the
                workstation.
                The LTSP workstation starts in runlevel '2'.  That is set by the
                <emphasis>initdefault</emphasis> line in
                the inittab file.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                One of the first items in the inittab file is the
                <command>rc.local</command>
                command that will be run while the workstation is in the
                '<emphasis role="strong">sysinit</emphasis>' state.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                The rc.local script will create a 1mb ramdisk to contain all of
                the things that need to be written to or modified in any way.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                The ramdisk will be mounted as the
                <filename class="directory">/tmp</filename>
                directory.  Any files that need to be written will actually
                exist in the <filename class="directory">/tmp</filename>
                directory, and there are symbolic links pointing to these files.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                The <filename class="directory">/proc</filename> filesystem
                is mounted.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                If the workstation is configured to swap over NFS, the
                <command>/var/opt/ltsp/swapfiles</command> directory will
                be mounted as /tmp/swapfiles.  Then, if there isn't a 
                swapfile for this workstation yet, it will be created
                automatically.  The size of the swapfile is configured
                in the <filename>lts.conf</filename> file.
            </para>
            <para>
                The swapfile will then be enabled, using the
                <command>swapon</command> command.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                The <emphasis role="strong">loopback</emphasis> network
                interface is configured.  This is the networking interface
                that has <emphasis>127.0.0.1</emphasis> as its IP address.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                If Local apps is enabled, then the <command>/home</command>
                directory will be mounted, so that the apps can access the
                users home directories.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                Several directories are created in the
                <filename class="directory">/tmp</filename> filesystem for
                holding some of the transient files that are needed while
                the system is running.  Directories such as:
                <orderedlist>
                    <listitem>
                        <para>
                            <filename>/tmp/compiled</filename>
                        </para>
                        <para></para>
                    </listitem>
                    <listitem>
                        <para>
                            <filename>/tmp/var</filename>
                        </para>
                        <para></para>
                    </listitem>
                    <listitem>
                        <para>
                            <filename>/tmp/var/run</filename>
                        </para>
                        <para></para>
                    </listitem>
                    <listitem>
                        <para>
                            <filename>/tmp/var/log</filename>
                        </para>
                        <para></para>
                    </listitem>
                    <listitem>
                        <para>
                            <filename>/tmp/var/lock</filename>
                        </para>
                        <para></para>
                    </listitem>
                    <listitem>
                        <para>
                            <filename>/tmp/var/lock/subsys</filename>
                        </para>
                        <para></para>
                    </listitem>
                </orderedlist>
            </para>
            <para></para>

            <para>
                will all be created.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                The X Windows system will now be configured.  In the
                <command>lts.conf</command> file, there is a parameter
                called <command>XSERVER</command>.  If this parameter
                is missing, or set to "<command>auto</command>", then
                an automatic detection will be attempted.  If the card
                is PCI, then we will get the PCI Vendor and Device id, and
                do a lookup in the <command>/etc/vidlist</command> file.
            </para>
            <para>
                If the card is supported by XFree86 4.X, the pci_scan routine
                will return the name of the driver module.  If it is only
                supported by XFree86 3.3.6, pci_scan will return the name of
                the X server to use.  The rc.local script can tell the
                difference because the older 3.3.6 server names start
                with 'XF86_'.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                If XFree86 4.x is used, then the
                <command>/etc/rc.setupx</command> script will be called to
                build an XF86Config file for X4.  If XFree86 3.3.6 is used,
                then <command>/etc/rc.setupx3</command> will be called to
                build the XF86Config file.
            </para>
            <para>
                The XF86Config file will be built, based on entries in the
                <command>/etc/lts.conf</command> file.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                When the rc.setupx script is finished, it will return back to
                rc.local.  Then the <command>/tmp/start_ws</command> script
                will be created.
                This script is responsible for starting the X server.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                The <filename>/tmp/syslog.conf</filename> file will be created.
                This file will contain information telling the
                <command>syslogd</command> daemon which host on the network
                to send the logging information to.  The syslog host is
                specified in the <filename>lts.conf</filename> file.  There
                is a symbolic
                link called <filename>/etc/syslog.conf</filename> that points
                to the <filename>/tmp/syslog.conf</filename> file.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                The <command>syslogd</command> daemon is started, using the
                config file created in the previous step.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                Control is then passed back to <command>init</command>.
                Init will then look at the
                <emphasis role="strong">initdefault</emphasis>
                entry to determine which
                <emphasis role="strong">runlevel</emphasis>
                to enter.  As of lts_core-2.08, the value of initdefault is
                <emphasis role="strong">2</emphasis>.
            </para>
            <para></para>
        </listitem>

        <listitem>
            <para>
                A runlevel of <emphasis role="strong">2</emphasis> will cause
                init to run the
                <command>set_runlevel</command> script which will read
                the lts.conf file and determine what runlevel the workstation
                will actually run in.
            </para>
            <para>
                The standard runlevels for LTSP are
                <emphasis role="strong">3</emphasis>,
                <emphasis role="strong">4</emphasis> and
                <emphasis role="strong">5</emphasis>.
                <itemizedlist>
                    <listitem>
                        <para>
                            <emphasis role="strong">3</emphasis> - This will
                            start a shell.  This is very useful for debugging
                            the workstation.
                        </para>
                        <para></para>
                    </listitem>
                    <listitem>
                        <para>
                            <emphasis role="strong">4</emphasis> - This will
                            run one or more Telnet sessions in character
                            mode.  This is great if you are just replacing
                            old serial terminals.
                        </para>
                        <para></para>
                    </listitem>
                    <listitem>
                        <para>
                            <emphasis role="strong">5</emphasis> - GUI mode.
                            This will bring up X windows, and send an XDMCP
                            query to the server, which will bring up a login
                            dialog box to let you log into the server.  You
                            will need a display manager listening on
                            the server, such as
                            <emphasis role="strong">XDM</emphasis>,
                            <emphasis role="strong">GDM</emphasis> or
                            <emphasis role="strong">KDM</emphasis>.
                        </para>
                        <para></para>
                    </listitem>
                </itemizedlist>
            </para>
            <para></para>
        </listitem>
    </orderedlist>
    <para></para>
</chapter>

<chapter>
    <title>Installing LTSP on the server</title>
    <para>
        The LTSP packages are available in both
        <emphasis role="strong">RPM</emphasis> and
        <emphasis role="strong">TGZ</emphasis> formats.  Choose which
        format you prefer to install, and follow the appropriate
        section.
    </para>

    <para>
        If you want to run X windows on the workstation, there are
        4 packages that you will need to
        download.  Keep in mind, for the purposes of this document,
        we have a workstation with a Tulip based network card and an
        Intel i810 based video chipset.
            
        <orderedlist>
            <listitem>
                <para>
                    LTSP Core package
                </para>
            </listitem>
            <listitem>
                <para>
                    Kernel package
                </para>
            </listitem>
            <listitem>
                <para>
                    X Core package
                </para>
            </listitem>
            <listitem>
                <para>
                    X Fonts package
                </para>
            </listitem>
        </orderedlist>

        The X Fonts package isn't really required, but for a first time
        installation, it is recommended.  Once you get the hang of
        setting up a server and diskless workstation, you can setup the
        X Font Server (XFS).
     </para>

     <para>
        After the packages are installed, the LTSP system needs to be
        initialized.  This processes includes making the changes to
        the system configuration files to enable the host system to
        offer the services needed by one or more workstations.
    </para>

    <sect1>
        <title>Installing the RPM packages</title>
        <para>
            Download the latest release of the ltsp packages, and install them
            using the following commands:
            <programlisting>
rpm -ivh ltsp_core-3.0.0-1.i386.rpm

rpm -ivh ltsp_kernel-3.0.1-1.i386.rpm

rpm -ivh ltsp_x_core-3.0.1-1.i386.rpm

rpm -ivh ltsp_x_fonts-3.0.0-0.i386.rpm</programlisting>
            The above commands will install the packages into the
            <filename class="directory">/opt/ltsp/i386</filename> directory.
        </para>
    </sect1>

    <sect1>
        <title>Installing the TGZ packages</title>

        <para>
            Download the latest release of the ltsp packages
            and install them using the following commands:
            <programlisting>
tar xzf ltsp_core-3.0.0-i386.tgz
cd ltsp_core
./install.sh
cd ..

tar xzf ltsp_kernel-3.0.1-i386.tgz
cd ltsp_kernel
./install.sh
cd ..

tar xzf ltsp_x_core-3.0.1-i386.tgz
cd ltsp_x_core
./install.sh
cd ..

tar xzf ltsp_x_fonts-3.0.0-i386.tgz
cd ltsp_x_fonts
./install.sh
cd ..</programlisting>
            The above commands will install the packages into the
            <filename class="directory">/opt/ltsp/i386</filename> directory.
        </para>
    </sect1>

    <sect1>
        <title>Initialization of the server</title>
        <para>
            Once the installation of the above packages is complete,
            you then need to change into the
            <filename class="directory">/opt/ltsp/templates</filename>
            directory.  There are several files there that will configure
            the system files on
            your server.  Each one of these files is responsible for one system
            file.  take a look at those files and make sure that you agree with
            what they are going to do.  They can potentially make your system
            vulnerable to a security attack.  You may wish to make the changes
            to the system files manually.  if you want to do it automatically,
            then, as the superuser, run the ltsp_initialize command:
         
            <programlisting>
cd /opt/ltsp/templates
./ltsp_initialize </programlisting>

            The above command will ask you many questions about which services
            you want to configure.

            It will initialize the following services:

            <itemizedlist>
                <listitem>
                    <para>XDM - X Display Manager</para>
                </listitem>
                <listitem>
                    <para>GDM - Gnome Display Manager</para>
                </listitem>
                <listitem>
                    <para>Display manager startup script</para>
                </listitem>
                <listitem>
                    <para>bootp</para>
                </listitem>
                <listitem>
                    <para>NFS /etc/exports file</para>
                </listitem>
                <listitem>
                    <para>tcpwrappers</para>
                </listitem>
                <listitem>
                    <para>Port mapper</para>
                </listitem>
                <listitem>
                    <para>syslogd</para>
                </listitem>
                <listitem>
                    <para>TFTP startup script</para>
                </listitem>
            </itemizedlist>
        </para>
    </sect1>

    <sect1>
        <title>Workstation specific configuration</title>
        <para>
            Now, it's time to tell the LTSP server about your specific
            workstation.  There are three files that contain information
            about the workstation.

            <orderedlist>

                <listitem>
                    <para>/etc/dhcpd.conf</para>
                </listitem>

                <listitem>
                    <para>/etc/hosts</para>
                </listitem>

                <listitem>
                    <para>/opt/ltsp/i386/etc/lts.conf</para>
                </listitem>

            </orderedlist>

        </para>

        <sect2>
            <title>/etc/dhcpd.conf</title>
            <para>
                The workstation needs an IP address and other information.
                It will get the following from the DHCP server:
                <itemizedlist>
                    <listitem> <para>IP address</para> </listitem>
                    <listitem> <para>hostname</para> </listitem>
                    <listitem> <para>Server IP address</para> </listitem>
                    <listitem> <para>Default gateway</para> </listitem>
                    <listitem> <para>Pathname of kernel to load</para> </listitem>
                    <listitem> <para>Server and directory path
                                     to be mounted as the root filesystem
                               </para> </listitem>
                </itemizedlist>
            </para>
            <para>
                For our example LTSP environment, we have chosen DHCP
                for handling IP address assignment to the workstations.
            </para>
            <para>
                During the ltsp_initialize script, a sample dhcpd.conf file
                is installed.  It is called
                <filename>/etc/dhcpd.conf.example</filename>
                you can copy that file to 
                <filename>/etc/dhcpd.conf</filename> to use it as
                a basis for your dhcp configuration.  You will need to
                modify the parts of this file that pertain to your
                specific workstation and server environment.
                <figure float="1">
                <title>/etc/dhcpd.conf</title>
                <programlisting>
default-lease-time            21600;
max-lease-time                21600;
    
option subnet-mask            255.255.255.0;
option broadcast-address      192.168.0.255;
option routers                192.168.0.254;
option domain-name-servers    192.168.0.254;
option domain-name            "ltsp.org";
option root-path              "192.168.0.254:/opt/ltsp/i386";
    
shared-network WORKSTATIONS {
    subnet 192.168.0.0 netmask 255.255.255.0 {
    }
}
    
group	{
    use-host-decl-names       on;
    option log-servers        192.168.0.254;
    
    host ws001 {
        hardware ethernet     00:E0:18:E0:04:82;
        fixed-address         192.168.0.1;
        filename              "/lts/vmlinuz.ltsp";
    }
} </programlisting>
                </figure>
            </para>

            <para>
                As of LTSP, version 2.09pre2, you no longer have to
                specify a particular kernel to load.  The standard
                kernel package supports all of the network cards that
                Linux supports.  There are two kernel files included
                in the LTSP kernel package.  One kernel has the
                Linux Progress Patch (LPP) applied, and the other
                kernel does not.  The names for the kernels are:
                <programlisting>
vmlinuz-2.4.9-ltsp-5
vmlinuz-2.4.9-ltsp-lpp-5 </programlisting>
            </para>
            <para>
                You may have noticed that the kernel is sitting in
                the <filename class="directory">/tftpboot/lts</filename>
                directory, but in the "filename" entry in the 
                <filename>/etc/dhcpd.conf</filename> file is missing the
                leading <filename class="directory">/tftpboot</filename>
                component of the pathname.  That is because on Redhat 
                versions 7.1 and above,
                TFTP is run with the '-s' option.  That causes the tftpd
                daemon to run in <emphasis role="strong">secure</emphasis>
                mode.  That is, it does a <command>chroot</command> to the
                <filename class="directory">/tftpboot</filename> directory
                when it starts.  Therefore, all files that are available
                to the tftpd daemon are relative to the 
                <filename class="directory">/tftpboot</filename> directory.
            </para>
            <para>
                Other Linux distributions may not have the '-s' option
                set for tftpd, so you will need to add the 
                <filename class="directory">/tftpboot</filename> prefix
                to the kernel pathname.
            </para>
        </sect2>

        <sect2>
            <title>/etc/hosts</title>
            <para>IP address to hostname mapping</para>
            <para>
                Computers generally communicate just fine with IP
                addresses.  Then, us humans come along and 
                need to put names on the computers, because we can't
                remember the numbers.  That's where DNS or the
                <filename>/etc/hosts</filename> file come into play.  This
                IP address to hostname mapping generally isn't required,
                except in an LTSP environment.  That's because without it,
                NFS will give you permissions errors when the workstation
                attempts to mount the root filesystem.
            </para>
            <para>
                In addition to NFS problems, if the workstation is
                not listed in the <filename>/etc/hosts</filename> file,
                you may also have problems with the
                <emphasis role="strong">GDM</emphasis> or
                <emphasis role="strong">KDM</emphasis> display managers.
            </para>
        </sect2>

        <sect2>
            <title>/opt/ltsp/i386/etc/lts.conf</title>
            <para>
                There are a number of configuration entries that can
                be specified in the lts.conf file.
            </para>

            <para>
                The <filename>lts.conf</filename> file has a simple
                syntax, that consists of multiple sections.  There is
                a default section called <command>[default]</command> and
                there can be sections for individual workstations.  The
                workstations can be identified by hostname, IP address or
                MAC address.
            </para>

            <para>
                A typical <filename>lts.conf</filename> file looks like
                this:
                <example>
                    <title>lts.conf file</title>
                    <programlisting>
#
# Config file for the Linux Terminal Server Project (www.ltsp.org)
#

[Default]
        SERVER             = 192.168.0.254
        XSERVER            = auto
        X_MOUSE_PROTOCOL   = "PS/2"
        X_MOUSE_DEVICE     = "/dev/psaux"
        X_MOUSE_RESOLUTION = 400
        X_MOUSE_BUTTONS    = 3
        USE_XFS            = N
        LOCAL_APPS         = N
        RUNLEVEL           = 5

[ws001]
        USE_NFS_SWAP       = Y
        SWAPFILE_SIZE      = 48m
        RUNLEVEL           = 5

[ws002]
        XSERVER            = XF86_SVGA
        LOCAL_APPS         = N
        USE_NFS_SWAP       = Y
        SWAPFILE_SIZE      = 64m
        RUNLEVEL           = 3</programlisting>
                </example>
            </para>

            <para>
                The following is a list of some of those entries:
                <variablelist>
                    <varlistentry>
                        <term><command>XSERVER</command></term>
                        <listitem>
                            <para>
                                If your video card is a PCI card, and if
                                it is supported by XFree86 4.1, then you
                                just need the lts_x_core package.  That
                                contains all of the driver modules for X4.
                            </para>
                            <para>
                                There are several XFree86 3.3.6 packages
                                available for LTSP.  This is in case your
                                card isn't supported by XFree86 4.1.
                            </para>
                            <para>
                                You can make entries in the
                                <filename>lts.conf</filename> for each
                                individual workstation, or you can make
                                default entries that are shared by all
                                workstations.
                            </para>
                            <para>
                                Our workstation has an Intel i810 video
                                chipset, and it can correctly be auto
                                detected, so we don't need any XSERVER
                                entry in the lts.conf file.  The XSERVER
                                entry can be specified, if you want, or it
                                can be set to 'auto' to show that it is
                                going to be auto detected.
                            </para>
                        </listitem>
                    </varlistentry>

                    <varlistentry>
                        <term><command>RUNLEVEL</command></term>
                        <listitem>
                            <para>
                                We want to run the workstation in graphical
                                mode, so we need to set the runlevel to
                                '5'.  This is done by another entry in
                                the <filename>lts.conf</filename> file.
                            </para>
                        </listitem>
                    </varlistentry>
                </variablelist>
            </para>
        </sect2>
    </sect1>
</chapter>



<chapter>
    <title>Setting up the workstation</title>
    <para>
        Once the server is setup, it is time to focus on setting
        up the workstation.
    </para>
    <para>
        The LTSP project is all about what happens after the kernel
        is in memory.  There are several ways to get the kernel
        into memory, including Etherboot, Netboot, PXE and floppy disk.
    </para>

    <para>
        For the purposes of this document, we will use a boot floppy with
        code from the <command>Etherboot</command> project.
    </para>

    <sect1>
        <title>Creating the boot floppy</title>
        <blockquote><attribution>Ken Yap</attribution>
        <para>
            Etherboot is a software package for creating ROM images that
            can download code over an Ethernet network to be executed on
            an x86 computer.  Many network adapters have a socket where
            a ROM chip can be installed.  Etherboot is code that can be
            put in such a ROM.
        </para>
        </blockquote>

        <para></para>

        <para>
            Etherboot is also Open Source, protected under the GNU General
            Public License, Version 2 (GPL2).
        </para>

        <para>
            You can download the Etherboot package and configure it for
            the type of bootrom that you need.  Then, you can compile the
            source to produce a bootrom image that can be written to an
            eprom, or written to a floppy disk for testing.
        </para>

        <para>
            A much simpler alternative is to go to Marty Connor's
            <ulink url="http://www.rom-o-matic.net"><citetitle>www.Rom-O-Matic.net</citetitle></ulink>
            website.
        </para>

        <para>
            Marty has done an excellent job of putting a web based
            front-end on the configuration and compilation process of
            making bootrom images with Etherboot.  On his site, you
            select what type of network card you have, and what kind
            of image you want.  Then, you have an opportunity to
            modify many Etherboot configuration options.  Then, you
            can press the 'Get ROM' button and a custom bootrom image
            will be generated while you wait.
        </para>

        <para>
            Our workstation has a Linksys LNE100TX, version 4.1 card.  This
            card has a ADMTek Centaur-P chipset, so we need to select
            <emphasis role="strong">centaur-p</emphasis> as our NIC/ROM type.
        </para>

        <para>
            We don't need to make any changes from the default configuration,
            so you can skip the 'Configure' button.
        </para>

        <para>
            For the ROM output format, choose 'Floppy Bootable ROM Image'.
            This will cause it to contain a 512 byte header that is a boot
            loader for loading the etherboot image into ram where it can be
            executed.
        </para>

        <para>
            Press the 'Get ROM' button.  The bootrom image will be generated
            while you wait.
            It only takes a few seconds, and when it is done, your browser
            will pop-up a "Save As" window where you can designate where
            you want the bootrom image to be saved on your computer.
        </para>

        <para>
            I usually save the file in the
            <filename class="directory">/tmp</filename>
            directory.  So, for the Centaur-P image, specify something like:
            <filename>/tmp/eb-5.0.2-centaur-p.lzdsk</filename>
        </para>

        <para>
            Once you've saved the image to your hard drive, you need
            to write it out to a floppy disk.  Insert a floppy diskette into
            the drive and run the following
            command to write the floppy:
            <programlisting>
cat   /tmp/eb-5.0.2-centaur-p.lzdsk   >/dev/fd0 </programlisting>
        </para>

    </sect1>

</chapter>

<chapter>
    <title>Running the workstation</title>
    <para>
        Assuming that the server and workstation are configured properly,
        it should just be a matter of inserting the boot floppy in the floppy
        drive and turning on the workstation.
    </para>

    <para>
        The Etherboot code will be read from the floppy into memory, the network
        card will be found and initialized, the dhcp request will be sent on
        the network and a reply will be sent from the server and the kernel will
        be downloaded to the workstation.  Once the kernel has initialized the 
        workstation hardware, X windows will start and a login box should
        appear on the workstation, similar to the example below.
    </para>

    <figure><title>Login screen</title>
        <GRAPHIC FILEREF="ltsplogin1.gif"
                 FORMAT="GIF"
                 SRCCREDIT="James McQuillan, 2001" >
    </figure>

    <para>
        At this point, you can log in.  An important thing to keep in mind
        is that you are logging into the server.  All of the commands that 
        you run are actually running on the server, and displaying their
        output on the workstation.  That's the power of X windows.
    </para>

    <para>
        You can run any program that is supported by the server.
    </para>

</chapter>

<chapter>
    <title>Printing</title>
    <para>
        Aside from the workstation being a fully functioning GUI or
        character mode terminal, it can also act as a print server,
        allowing upto 3 printers to be attached to the parallel and
        serial ports.
    </para>

    <para>
        This is all transparent to the user of the workstation.  They
        won't even notice the small amount of traffic that is going
        through the workstation to the printers.
    </para>

    <sect1>
        <title>Client side setup</title>

        <para>
            LTSP uses the <command>lp_server</command> program on the
            workstation, to redirect print jobs from the server to
            the printer attached to one of the ports on the workstation.
        </para>

        <para>
            To enable the printer on the workstation, there are a set of
            configuration entries in the <command>lts.conf</command> file.
            <programlisting>
[ws001]
    PRINTER_0_DEVICE = /dev/lp0
    PRINTER_0_TYPE   = P </programlisting>
            The above entry will cause the lp_server program to run as a 
            daemon, listening on TCP/IP port 9100 for a print stream from the
            server.  The print data will then be redirected to the printer
            attached to the /dev/lp0 parallel port.
        </para>

        <para>
            There are many more options available.  Check the lts.conf section
            later in this document for more information on printer
            configuration entries.
        </para>
    </sect1>

    <sect1>
        <title>Server side setup</title>

        <para>
            Setting up the printer on the server is a matter of defining a
            print queue, using the printer configuration tool on the server.
        </para>

        <para>
            On Redhat 7.2, there is both a GUI and a Text based printer
            configuration tool.  The GUI tool is called
            <command>printconf-gui</command>, and the text based tool
            is called <command>printconf-tui</command>.  Older versions of
            Redhat have a program called <command>printtool</command>.
            Printtool also exists on Redhat 7.2, but it will call
            printconf-gui.  Other Linux distributions have their own
            printer configuration tool.
        </para>

        <figure>
            <title>Printconf-gui Adding new printer</title>
            <GRAPHIC FILEREF="printconf-gui-add.gif"
                     FORMAT="GIF"
                     SRCCREDIT="James McQuillan, 2001" >
        </figure>

        <para>
            Once you launch the printer configuration tool, you need to
            add a new printer.  The lp_server program allows the workstation
            to emulate an HP JetDirect print server.  You just need to create a
            <command>JetDirect</command> printer.
        </para>

        <para>
            You need to give the printer a Queue name.  The name can be
            anything, but make it a meaningful name, and the name can contain
            only the following characters:
            <itemizedlist>
                <listitem>
                    <para>
                        <computeroutput>
                            "a-z"  lower-case letters
                        </computeroutput>
                    </para></listitem>
                <listitem>
                    <para>
                        <computeroutput>
                            "A-Z"  upper-case letters
                        </computeroutput>
                    </para></listitem>
                <listitem>
                    <para>
                        <computeroutput>
                            "0-9"  numeric digits
                        </computeroutput>
                    </para></listitem>
                <listitem>
                    <para>
                        <computeroutput>
                            "-"    &nbsp;&nbsp;hyphen
                        </computeroutput>
                    </para></listitem>
                <listitem>
                    <para>
                        <computeroutput>
                            "_"    &nbsp;&nbsp;underscore
                        </computeroutput>
                    </para></listitem>
            </itemizedlist>
        </para>
        <para>
            The name chosen in the example above is
            <command>ws001_lp</command>.  This name makes it easy to see
            that the printer is associated with <command>ws001</command>.
        </para>

        <figure>
            <title>Printconf-gui Detail info</title>
            <GRAPHIC FILEREF="printconf-gui-detail.gif"
                     FORMAT="GIF"
                     SRCCREDIT="James McQuillan, 2001" >
        </figure>
        <para>
            There are two fields required to communicate with the printer:
            <orderedlist>
                <listitem>
                    <para>
                        IP Address or hostname of the workstation that
                        the printer is associated with.
                    </para>
                </listitem>
                <listitem>
                    <para>
                        The TCP port that the <command>lp_server</command>
                        daemon is listening on.
                    </para>
                    <para>
                        The first printer you connect to a workstation
                        will be on TCP/IP port <command>9100</command>.  The
                        second printer will be on port <command>9101</command>,
                        and the third printer will be on port
                        <command>9102</command>.
                    </para>
                </listitem>
            </orderedlist>
        </para>
    </sect1>

</chapter>

<chapter>
    <title>Troubleshooting</title>
    <para>
        If, after following through the previous chapters, your workstation
        doesn't boot, then you've got to start the process of troubleshooting
        the installation.
    </para>

    <para>
        The first thing to do is figure out how far through the bootup the
        workstation has gotten.
    </para>

    <sect1>
        <title>Troubleshooting Etherboot floppy image</title>
        <para>
            When you boot from the floppy, you should see something similar
            to this:
        </para>
        <para>
        <screen>
loaded ROM segment 0x0800 length 0x4000 reloc 0x9400
Etherboot 5.0.1 (GPL) Tagged ELF for [LANCE/PCI]
Found AMD Lance/PCI at 0x1000, ROM address 0x0000
Probing...[LANCE/PCI] PCnet/PCI-II 79C970A base 0x1000, addr 00:50:56:81:00:01
Searching for server (DHCP)...
&#60;sleep&#62; </screen>
        </para>
        <para>
            The above example shows what you can expect to see on the
            screen when booting from a floppy.  If you don't see those
            messages, indicating that Etherboot has started, then you
            may have a bad floppy disk, or you didn't write the image
            to it properly.
        </para>

        <para>
        If, you see a message like the following, then it probably
        indicates that the Etherboot image you have generated is not
        the correct image for your network card.
        <screen>
ROM segment 0x0800 length 0x8000 reloc 0x9400
Etherboot 5.0.2 (GPL) Tagged ELF for [Tulip]
Probing...[Tulip]No adapter found
&#60;sleep&#62;
&#60;abort&#62; </screen>
        </para>

        <para>
            If it does get to the point where it detects the network card
            and displays the proper MAC address, then the floppy is probably
            good.
        </para>
 
    </sect1>

    <sect1>
        <title>Troubleshooting DHCP</title>
        <para>
            Once the network card is initialized, it will send out a
            DHCP broadcast on the local network, looking for a DHCP server.
        </para>

        <para>
            If the workstation gets a valid reply from the DHCP server, then it
            will configure the network card.  You can tell if it worked properly
            if the IP address information is displayed on the screen.  Here's an
            example of what it should look like:
            <screen>
ROM segment 0x0800 length 0x4000 reloc 0x9400
Etherboot 5.0.1 (GPL) Tagged ELF for [LANCE/PCI]
Found AMD Lance/PCI at 0x1000, ROM address 0x0000
Probing...[LANCE/PCI] PCnet/PCI-II 79C970A base 0x1000, addr 00:50:56:81:00:01
Searching for server (DHCP)...
&#60;sleep&#62;
Me: 192.168.0.1, Server: 192.168.0.254, Gateway 192.168.0.254 </screen>
            If you see the line that starts with 'Me:', following by an IP
            address, then you know that DHCP is working properly.  You can move
            on to checking to see if TFTP is working.
        </para>

        <para>
            If instead, you see the following message on the workstation,
            followed by lots of &#60;sleep&#62; messages, then something
            is wrong.  Although, it is common to see one or two
            &#60;sleep&#62; messages, after which the dhcp server replies.
            <screen>
Searching for server (DHCP)...  </screen>
        </para>

        <para>
            Figuring out what is wrong can sometimes be difficult, but
            here are some things to look for.
        </para>
            <sect2>
                <title>Check the connections</title>
                <para>
                    Is the workstation physically connected to the same
                    network that the server is connected to?
                </para>
                <para>
                    With the workstation turned on, make sure that the link
                    lights are lit at all of the connections.
                </para>

                <para>
                    If you are connecting directly between the workstation and
                    the server (no hub or switch), make sure that you are using
                    a cross-over cable.  If you are using a hub or switch, then
                    make sure you are using a normal straight-thru cable, both
                    between the workstation and hub, and also between the hub
                    and server.
                </para>

            </sect2>

            <sect2>
                <title>Is dhcpd running?</title>
                <para>
                    You need to determine whether <command>dhcpd</command> is
                    running on the server.  We can find the answer a couple
                    of ways.
                </para>

                <para>
                    <command>dhcpd</command> normally sits in the background,
                    listening on udp port 67.  Try running the
                    <command>netstat</command> command to see if anything
                    is listening on that port:
                    <programlisting>
netstat -an | grep ":67 " </programlisting>
                    You should see output similar to the following:
                    <programlisting>
udp     0    0   0.0.0.0:67         0.0.0.0:*</programlisting>
                    The 4th column contains the IP address and port, separated
                    by a colon (':').  An address of all zeroes ('0.0.0.0')
                    indicates that it is listening on all interfaces.  That
                    is, you may have an <command>eth0</command> and an
                    <command>eth1</command> interface, and
                    <command>dhcpd</command> is listening on both interfaces.
                </para>

                <para>
                    Just because netstat shows that something is listening
                    on udp port 67, it doesn't mean that it is definately
                    <command>dhcpd</command> that is listening.  It could
                    be <command>bootpd</command>, but that is unlikely,
                    because <command>bootp</command> is no longer included
                    on most distributions of Linux.
                </para>

                <para>
                    To make sure that it is the <command>dhcpd</command>
                    that is running, try running the <command>ps</command>
                    command.
                    <programlisting>
ps aux | grep dhcpd </programlisting>

                    You should see something like the following:

                    <programlisting>
root 23814 0.0 0.3 1676 820 ?      S 15:13 0:00 /usr/sbin/dhcpd
root 23834 0.0 0.2 1552 600 pts/0  S 15:52 0:00 grep dhcp </programlisting>

                    The first line shows that <command>dhcpd</command> is 
                    running. The second line is just our <command>grep</command>
                    command.
                </para>

                <para>
                    If you don't see any lines showing that dhcpd is running,
                    then you need to check that the server is configured for
                    runlevel 5, and that <command>dhcpd</command> is configured
                    to start in runlevel 5.  On Redhat based systems, you can
                    run the <command>ntsysv</command> and scroll down to make
                    sure <command>dhcpd</command> is configured to start.
                </para>

                <para>
                    You can try starting <command>dhcpd</command> with
                    this command:
                    <programlisting>
service dhcpd start</programlisting>

                    Pay attention to the output, it may show errors.
                </para>
                
            </sect2>

            <sect2>
                <title>Double-check the dhcpd configuration</title>
                <para>
                    Does the <filename>/etc/dhcpd.conf</filename> file have an
                    entry for our workstation?
                </para>
                <para>
                    You should double-check the 'fixed-address' setting in the
                    config file, to make sure it exactly matches the card in the
                    workstation.
                </para>
            </sect2>
           
            <sect2>
                <title>Is ipchains or iptables blocking the request?</title>
                <sect3>
                    <title>Checking for ipchains</title>
                    <para>
                        Run the following command to see what it says:
                        <programlisting>
ipchains -L -v </programlisting>
                        If you see something like this:
                        <programlisting>
Chain input (policy ACCEPT: 229714 packets, 115477216 bytes):
Chain forward (policy ACCEPT: 10 packets, 1794 bytes):
Chain output (policy ACCEPT: 188978 packets, 66087385 bytes): </programlisting>
                        Then it isn't ipchains that is getting in the way.
                    </para>
                </sect3>
                <sect3>
                    <title>Checking for iptables</title>
                    <para>
                        Run the following command to see what it says:
                        <programlisting>
iptables -L -v </programlisting>
                        If you see something like this:
                        <programlisting>
Chain INPUT (policy ACCEPT 18148 packets, 2623K bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 17721 packets, 2732K bytes)
 pkts bytes target     prot opt in     out     source               destination</programlisting>
                        Then it is not iptables getting in the way.
                    </para>
                </sect3>
            </sect2>
           
            <sect2>
                <title>Is the workstation sending the request?</title>
                <para>
                    Try watching the <filename>/var/log/messages</filename>
                    file while the workstation is booting.  You can do that with
                    the following command:
                    <programlisting>
tail -f /var/log/messages </programlisting>
                    This will 'follow' the log file as new records are
                    written to it.
                    <programlisting>
server dhcpd: DHCPDISCOVER from 00:50:56:81:00:01 via eth0
server dhcpd: no free leases on subnet WORKSTATIONS
server dhcpd: DHCPDISCOVER from 00:50:56:81:00:01 via eth0
server dhcpd: no free leases on subnet WORKSTATIONS </programlisting>
                    If you see messages like those above, saying
                    'no free leases',
                    that indicates that <command>dhcpd</command> is running,
                    but it doesn't know anything about the workstation that
                    is requesting an IP address.
                </para>
            </sect2>
           
    </sect1>

    <sect1>
        <title>Troubleshooting TFTP</title>
        <para>
            Etherboot uses TFTP to retrieve a Linux kernel from the server.
            This is a fairly simple protocol, but sometimes there are problems
            trying to get it to work.
        </para>

        <para>
            If you see a message similar to this:
        <screen>
Loading 192.168.0.254:/lts/vmlinuz-2.4.9-ltsp-5 | </screen>
          with the last character on the line (the '|'), rapidly changing
          between a '|', '\', '-' and '/', to form what looks like a
          rotating bar, then the kernel is being downloaded.  Which
          normally indicates that TFTP is working properly.
        </para>

        <para>
          If, instead, you don't see the rotating bar, there is a
          problem.  Possible problems include:
        </para>

        <sect2>
            <title><command>tftpd</command> is not running</title>
            <para>
                On Redhat 7.1, tftp is run by <command>xinetd</command>.  There
                is a startup script called
                <filename>/etc/xinetd.d/tftp</filename> that contains the
                information for running <command>tftpd</command>
            </para>
        </sect2>

        <sect2>
            <title>Kernel not where tftpd expects to find it</title>
            <para>
                The kernel needs to be in a location that the tftpd daemon can
                access it.  If the '-s' option is specified when
                <command>tftpd</command> is run, then whatever the workstation
                is asking for must be relative to the
                <filename class="directory">/tftpboot</filename>.  So, if the
                <command>filename</command> entry in the
                <filename>/etc/dhcpd.conf</filename> file is set to
                <filename>/lts/vmlinuz-2.4.9-ltsp-5</filename>, then the kernel
                actually needs to be
                <filename>/tftpboot/lts/vmlinuz-2.4.9-ltsp-5</filename>
            </para>
        </sect2>
    </sect1>

<!--
    <sect1>
        <title>Troubleshooting Kernel</title>
        <para>
            If you are using one of the standard LTSP supplied kernels, then
            about the only thing that you really need to look out for is that
            you are using the correct kernel that matches your hardware.  Most
            important is that the kernel knows about your network card.
        </para>

        <para>
            The standard LTSP kernel, called <command>vmlinuz.ltsp</command>
            knows about all supported network cards.
        </para>

        <para>
            A real good indicator that you are using the wrong kernel is
            messages like the following:
            <screen>
.
.
.
RAM disk driver initialized:  16 RAM disks of 1024K size
IP-Config: No Network devices available
Root-NFS: No NFS server available, giving up.
VFS: Unable to mount root fs via NFS, trying floppy.
VFS: Cannot open root device 02:00
Kernel panic: VFS: Unable to mount root fs on 02:00 </screen>
            Many people are thrown off by the "NFS" error and they miss
            the <command>No Network devices available</command> message.  That
            is the key to the problem.  The kernel  probed for known network
            cards, and didn't find any.  Keep in mind that the kernels are
            compiled with support for specific network cards.
            (Except the vmlinuz.all kernel, which contains support for ALL
            known cards).
        </para>
    </sect1>
-->

    <sect1>
        <title>Troubleshooting NFS root filesystem</title>
        <para>
            There are several things that can prevent a root filesystem from
            being mounted.  Including the following:
        </para>
        <sect2>
            <title>No init found</title>
            <para>
                If you get the following error:
                <screen>
Kernel panic: No init found.  Try passing init= option to kernel.  </screen>
                Then it is is most likely that either you are mounting
                the wrong directory as the root filesystem, or the
                <filename>/opt/ltsp/i386</filename> directory is empty.
            </para>
        </sect2>

        <sect2>
            <title>Server returned error -13</title>
            <para>
                If you get the following error:
                <screen>
Root-NFS: Server returned error -13 while mounting /opt/ltsp/i386 </screen>
                This indicates that either the
                <filename class="directory">/opt/ltsp/i386</filename>
                directory isn't listed in the <filename>/etc/exports</filename>
                file.
            </para>
            <para>
                Take a look in the <filename>/var/log/messages</filename> file
                to see if there are any clues.  An entry like this:
                <screen>
Jul 20 00:28:39 jamlap rpc.mountd: refused mount request from ws004
                  for /opt/ltsp/i386 (/): no export entry </screen>
                Then it confirms our suspicion that the entry in
                <filename>/etc/exports</filename> isn't correct.
            </para>
        </sect2>

        <sect2>
            <title>NFS Daemon problems (portmap, nfsd &amp; mountd)</title>
            <para>
                NFS can be a complex and difficult service to trouble-shoot, but
                understanding what should be setup and what tools are
                available to diagnose the problems will surely help to
                make it easier.
            </para>
            <para>
                There are three daemons that need to be running on the server
                for NFS to work properly.  <command>portmap</command>,
                <command>nfsd</command> and <command>mountd</command>.
            </para>
            <sect3>
                <title>The Portmapper (portmap)</title>
                <para>
                    If you get the following messages:
                    <screen>
Looking up port of RPC 100003/2 on 192.168.0.254
portmap: server 192.168.0.254 not responding, timed out
Root-NFS: Unable to get nfsd port number from server, using default
Looking up port of RPC 100005/2 on 192.168.0.254
portmap: server 192.168.0.254 not responding, timed out
Root-NFS: Unable to get mountd port number from server, using default
mount: server 192.168.0.254 not responding, timed out
Root-NFS: Server returned error -5 while mounting /opt/ltsp/i386
VFS: unable to mount root fs via NFS, trying floppy.
VFS: Cannot open root device "nfs" or 02:00
Please append a correct "root=" boot option
Kernel panic: VFS: Unable to mount root fs on 02:00 </screen>
                    This most likely is caused by the <command>portmap</command>
                    daemon not running.  You can confirm whether or not the
                    portmapper is running by using the <command>ps</command>
                    command:
                    <screen>
ps -e | grep portmap </screen>
                    If the portmapper is running, you should see output
                    like this:
                    <screen>
30455 ?        00:00:00 portmap </screen>
                    Another test is to use the <command>netstat</command>.
                    The portmapper uses TCP and UDP ports 111.  Try running
                    this:
                    <screen>
netstat -an | grep ":111 " </screen>
                    You should see the following output:
                    <screen>
tcp   0   0 0.0.0.0:111       0.0.0.0:*          LISTEN      
udp   0   0 0.0.0.0:111       0.0.0.0:*                           </screen>
                    If you don't see similar output, then the portmapper
                    isn't running.  You start the portmapper by running:
                    <screen>
/etc/rc.d/init.d/portmap   start </screen>
                    Then, you should make sure that the portmapper is setup to
                    start when the server boots.  Run
                    <command>ntsysv</command> to make sure it is selected to
                    run.
                </para>
            </sect3>

            <sect3>
                <title>The NFS and MOUNT daemons (nfsd &amp; mountd)</title>
                <para>
                    NFS has 2 daemons that need to be running.
                    <command>nfsd</command> and <command>mountd</command>.
                    They are both started by the
                    <filename>/etc/rc.d/init.d/nfs</filename> script.
                </para>
                <para>
                    You can run the <command>ps</command> command to make sure
                    that they are running.
                    <screen>
ps -e | grep nfs
ps -e | grep mountd </screen>
                    If it shows that one or both of the daemons are not
                    running, then you will need to start them.
                </para>

                <para>
                    Normally, you should be able to run the startup script
                    with the <command>restart</command> argument to cause
                    them both to startup, but for some reason, the
                    <filename>/etc/rc.d/init.d/nfs</filename>
                    script doesn't restart <command>nfsd</command> that way.
                    It only restarts <command>mountd</command> (bug?).  So,
                    you should instead run the following sequence of
                    commands:
                    <screen>
/etc/rc.d/init.d/nfs  stop
/etc/rc.d/init.d/nfs  start </screen>
                    You may get errors on the <command>stop</command> command,
                    but that is Ok.  The <command>start</command> command
                    should show <command>OK</command> as the status.
                </para>

                <para>
                    If the daemons are running, but NFS is still not working,
                    you can verify that they have registered themselves with
                    the portmapper by using the <command>rpcinfo</command>
                    command.
                    <screen>
rpcinfo -p localhost </screen>
                    You should see results similar to the following:
                    <screen>
program vers proto   port
 100000    2   tcp    111  portmapper
 100000    2   udp    111  portmapper
 100011    1   udp    856  rquotad
 100011    2   udp    856  rquotad
 100005    1   udp   1104  mountd
 100005    1   tcp   2531  mountd
 100005    2   udp   1104  mountd
 100005    2   tcp   2531  mountd
 100003    2   udp   2049  nfs </screen>
                    This indicates that <command>nfs</command> (nfsd) and
                    <command>mountd</command> are both running and have
                    registered themselves with the portmapper.
                </para>
            </sect3>
        </sect2>
    </sect1>

    <sect1>
        <title>Troubleshooting the Xserver</title>
        <para>
            Oh boy!,  Probably the single most difficult part of setting up an
            LTSP workstation is getting the X server configured properly.  If
            you are using a fairly new video card, and it is supported by
            XFree86, and a fairly new monitor that can handle a large range
            of frequencies and resolutions, then it is pretty straight
            forward.  Usually, in that case, if it doesn't work, it is most
            likely the wrong X server for that card.
        </para>
        <para>
            When an X server doesn't work with your card, it is usually pretty
            obvious.  Either the X server won't start, or the display will be
            incorrect.
        </para>
        <para>
            When the workstation is ready to start the X server,
            it calls the <filename>/tmp/start_ws</filename> script, which
            starts the X server on the local workstation, with a
            <command>-query</command> option pointing to a server, where
            a display manager, such as <command>XDM</command>,
            <command>GDM</command> or <command>KDM</command> is running.
        </para>

        <para>
            Because the X server is started by the <filename>start_ws</filename>
            script, which is itself started by the <command>init</command>
            program, when it fails, <command>init</command> will attempt to
            run it again.  <command>init</command> will continue this loop
            of trying to run the X server 10 times, then give up, because
            it thinks that it is respawning too quickly.  After it finally
            gives up, the error message from the X server should be left
            on the screen.
        </para>

        <para>
            Waiting for the X server to fail 10 times can be rather irritating,
            so a simple way to avoid the repeated failures is to start the
            workstation in runlevel 3, so that the X server is NOT started
            automatically.  Instead, when you boot the workstation, you will
            get a <command>bash</command> prompt.
            From the bash prompt, you can start the X server manually with the
            following command:
            <screen>
sh  /tmp/start_ws </screen>
            The X server will attempt to start, then when it fails, it will
            return back to the bash prompt, so you can see what the reason for
            the failure is.
        </para>
    </sect1>

    <sect1>
        <title>Troubleshooting the Display manager</title>
        <para>
            The display manager is the daemon that runs on the server, waiting
            for an X server to make contact with it.  Once contact has been
            made, it will display a login dialog box on the screen, offering
            the user a chance to log into the server.
        </para>

        <para>
            The three most common display managers are:
            <itemizedlist>
                <listitem>
                    <para>
                        XDM - It's been around forever.  It is included with the
                        standard X windows system.
                    </para>
                </listitem>
                <listitem>
                    <para>
                        GDM - The 'Gnome Display Manager'.  This is part of the
                        Gnome package.
                    </para>
                </listitem>
                <listitem>
                    <para>
                        KDM - The 'KDE Display Manager'.  This is part of the
                        K Desktop system.
                    </para>
                </listitem>
            </itemizedlist>
            Most recent GNU/Linux distributions include all three display
            managers.
        </para>

        <sect2>
            <title>Grey screen with large X cursor</title>
            <para>
                This indicates that the X server is running, but it has not
                been able to make contact with a display manager.  Some possible
                reasons for that are:
                <orderedlist>
                    <listitem>
                        <para>
                            The display manager may not be running
                        </para>
                        <para>
                            On recent versions of Redhat (7.0 and above), the
                            display manager is started from
                            <command>init</command>.  In the
                            <filename>/etc/inittab</filename> file, there is
                            a line that looks like this:
                            <screen>
x:5:respawn:/etc/X11/prefdm -nodaemon </screen>
                            The <command>prefdm</command> script will make
                            the determination of which display manager to run.
                        </para>

                        <para>
                            The default display manager depends on which
                            packages have been installed.  If Gnome is
                            installed, then GDM is the default display
                            manager.  If Gnome is not installed, then the
                            prefdm script will check to see if KDE is
                            installed.  If it is, then KDM will be the default
                            display manager.  If KDE also is not installed,
                            then GDM will be the default display manager.
                        </para>

                        <para>
                            Using the <command>netstat</command> command,
                            you should be able to see if there is a display
                            manager running.  On the server, run the
                            following command:
                            <screen>
netstat -ap | grep xdmcp </screen>
                            You should see results showing that there is
                            a process listening on the xdmcp port (177).
                            <screen>
udp     0   0 *:xdmcp            *:*               1493/gdm </screen>
                            This shows clearly that <command>gdm</command>
                            is running with a PID of 1493, and it is listening
                            on the xdmcp port.
                        </para>

                        <para>
                            If you see a line like the one shown above,
                            indicating that there is definately a display
                            manager listening, then you need to make sure
                            that the workstation is sending the XDMCP query
                            to the correct server.
                        </para>

                        <para>
                            In the <filename>lts.conf</filename> file, you can
                            have an entry which specifies the IP address of the
                            server that is running the display manager.
                            the entry is optional, but if present, should
                            look like this:
                            <screen>
XDM_SERVER  =  192.168.0.254 </screen>
                            of course, the IP address for your network may
                            be different than the example above.
                        </para>

                        <para>
                            If the 'XDM_SERVER' entry is not present, it
                            will then use the value of the 'SERVER' entry,
                            if present.  If that is not present, then it
                            will use <command>192.168.0.254</command>.
                        </para>

                        <para>
                            Which ever way it is specified, you just need
                            to make sure that the IP address is actually
                            the correct address of the server running the
                            display manager.
                        </para>
                    </listitem>
                    <listitem>
                        <para>
                            The display manager may be configured to ignore
                            requests from remote hosts.
                        </para>

                        <para>
                            If you've determined that the display manager
                            is running, then it is possible that it has been
                            configured to ignore XDMCP requests from remote
                            hosts.  You will need to check the configuration
                            files of the particular running display manager,
                            to determine if it is configured properly.
                        </para>

                        <itemizedlist>
                            <listitem>
                                <para><command>XDM</command></para>
                                <para>
                                    The default configuration for Redhat is to
                                    disable the ability for workstations to
                                    get login access from XDM.  The
                                    <command>ltsp_initialize</command> script
                                    will take care of enabling this for you,
                                    but if it's not working, you should check
                                    the
                                    <filename>/etc/X11/xdm/xdm-config</filename>
                                    file.  Look for an entry that looks like
                                    this:
                                    <screen>
DisplayManager.requestPort:     0 </screen>
                                    This entry MUST be commented out in order
                                    for XDM to listen on port 177 for remote
                                    requests.
                                </para>
                                <para>
                                    Another configuration file is also
                                    important for XDM to serve up remote login
                                    requests.  There is a file called
                                    <filename>/etc/X11/xdm/Xaccess</filename>
                                    that MUST have a line that starts with an
                                    asterisk '*'.  the line is normally
                                    included in the file, but Redhat leaves
                                    the line commented out.  the
                                    <command>ltsp_initialize</command> script
                                    will fix the line for you, but if XDM
                                    doesn't seem to be working, you should
                                    check this file.  A valid line should look
                                    like this:
                                    <screen>
*        #any host can get a login window </screen>
                                </para>
                            </listitem>

                            <listitem>
                                <para><command>KDM</command></para>
                                <para>
                                    Newer versions of KDM have a file
                                    called <command>kdmrc</command>.  Different
                                    Linux distributions store that file in 
                                    different locations.  For Redhat 7.2,
                                    it is <command>/etc/kde/kdm/kdmrc</command>.
                                    For the other distros, you should run
                                    the <command>locate</command> command to
                                    find out where it is stored.
                                </para>
                                <para>
                                    The entry that controls whether remote
                                    workstations can get a login is in
                                    the <command>[Xdmcp]</command> section.
                                    Make sure that the <command>Enable</command>
                                    entry is set to <command>true</command>.
                                </para>
                                <para>
                                    Older versions of KDM use the XDM
                                    configuration files, located in
                                    /etc/X11/xdm.
                                </para>
                            </listitem>

                            <listitem>
                                <para><command>GDM</command></para>
                                <para>
                                    GDM uses a different set of configuration
                                    files.  They are located in the
                                    <filename class="directory">/etc/X11/gdm</filename>
                                    directory.
                                </para>

                                <para>
                                    The main file to look at is the
                                    <filename>gdm.conf</filename> file.  Look for the
                                    <command>[xdmcp]</command> section.  you should
                                    see an entry within that section called 'Enable'.  It
                                    must be set to '1' or 'true', depending on
                                    the version of GDM.  Here is an example:
                                    <screen>
[xdmcp]
Enable=true
HonorIndirect=0
MaxPending=4
MaxPendingIndirect=4
MaxSessions=16
MaxWait=30
MaxWaitIndirect=30
Port=177 </screen>
                                </para>
                                <para>
                                    Notice the 'Enable=true' line.
                                    Older versions of GDM use '0' and '1' to
                                    signify whether to Disable or Enable the
                                    remote XDMCP.  Newer versions use 'false'
                                    and 'true'.
                                </para>
                            </listitem>
                        </itemizedlist>
                    </listitem>

                    <listitem>
                        <para>
                            If the Display manager is definately running,
                            and it is listening for requests from remote
                            workstations, it may be a simple problem that
                            the display manager is unable to map the IP
                            address to a hostname.  The workstation either
                            needs to be listed in the 
                            <filename>/etc/hosts</filename> file, or 
                            it needs to be correctly setup in the DNS tables.
                        </para>
                    </listitem>

                </orderedlist>
            </para>
        </sect2>
    </sect1>
</chapter>

<chapter>
    <title>Kernels</title>
    <para>
        There are a few decisions that need to be made about the kernel
        that is run on the workstation.  You need to decide whether you
        want to run one of the standard kernels available for download,
        or build your own.  And, you need to decide if you want to display
        the graphic screen, complete with the progress bar which, which
        is made possible by the <command>Linux Progress Patch (LPP)</command>.
    </para>

    <sect1>
        <title>Standard LTSP supplied kernels</title>
        <para>
            The kernel package that is available with LTSP actually includes
            two kernels.  One has the Linux Progress Patch already applied
            and configured, and the other does not have the patch applied.
        </para>

        <para>
            Both of the kernels already have the NFS Swap patch applied.
        </para>
    </sect1>

    <sect1>
        <title>Build your own kernel</title>
        <para>
            There are a few choices you can make, when deciding whether to use
            the standardwhich  for the kernel
        </para>
        <para>
            There are two ways to configure a kernel for LTSP.  The default
            method is to use something called an 'Initial Ram Disk', or
            <command>initrd</command> for short.  The initrd image is a small
            filesystem that appended to the kernel.  The initrd filesystem
            image is loaded into memory, and once the kernel is booted, it
            will mount the ramdisk as its root filesystem.  There are a
            couple of advantages of using an initrd image.  First, we can
            compile the network drivers as modules and load the correct
            module during bootup.  This allows a single kernel which will
            support virtually all network cards.  The other advantage is that
            we can run the DHCP client as a "user-land" program rather than
            in kernel-space.  Running the client in user-land provides
            better control over the options requested and received from the
            server.  Also, it makes the kernel slightly smaller.  The other way
            to configure the kernel is without the initrd.  Building a kernel
            without an initrd requires that the specific network card driver
            be statically linked into the kernel, and it also requires that
            IP-Autoconfig and "Root filesystem on NFS" are set when building
            the kernel.  The advantage of not using an initrd is that the
            kernel is slightly smaller, and it will boot slightly faster.
            once the workstation is up and running, there is virtually no
            difference in how the workstation functions.
        </para>

        <para>
            The standard kernel for LTSP includes an Initial Ramdisk
            (initrd) that takes care of detecting the network card, and
            making a user-space DHCP request.  A major goal for the image
            was to make it as small as possible.  So, we chose the uClinux
            libc replacement library, and busybox for the utilities that
            we need during the boot.
        </para>

        <para>
            If you want to build your own kernels, you should download the
            ltsp_initrd_kit package.  It contains the root filesystem hierarchy,
            and a script for building the image.
        </para>

        <sect2>
            <title>Obtaining the source for the kernel</title>
 
            <para>
                When building a custom kernel, it's usually a good idea to
                start with fresh kernel sources direct from the
                <command>ftp.kernel.org</command> site.  The reason for this
                is that the distributions, like Redhat, apply many patches to
                their kernel sources, leaving you with a set of source code
                that really doesn't match that of the official kernel.
            </para>
    
            <para>
                Download the kernel source package of your choice, and save
                it in the <filename class="directory">/usr/src</filename>
                directory.  The kernels are located in the
                <filename class="directory">/pub/linux/kernel</filename>
                directory of the ftp.kernel.org ftp server.  You will need to
                grab a recent 2.4.x series kernel, because you need to include
                <command>devfs</command> support.
            </para>

            <para>
                Also, if you want to include support for swapping over NFS or
                the Linux Progress Patch (LPP), you will need to make sure that
                you get the patches and kernel sources that are all the same.
                At the time of this writing, the 2.4.9 kernel is the latest to
                support those features.
            </para>

            <para>
                For our example, we will use the 2.4.9 kernel.  The entire
                path is
                <filename>ftp://ftp.kernel.org/pub/linux/kernel/v2.4/linux-2.4.9.tar.bz2</filename>
            </para>

            <para>
                Unpack the kernel sources in the
                <filename class="directory">/usr/src</filename>
                directory.  You need to be careful, because when you un-tar the
                package, it will be in a directory called
                <filename>linux</filename>.  You may already have a
                directory called <filename>linux</filename> with a different
                set of source code, and you don't want to clobber it.  So,
                check for an existing directory, and if it is there, rename it
                to something else before unpacking the sources.
            </para>

            <para>
                The source package we downloaded had been compressed with the
                <command>bzip2</command> compression utility.  So, we need
                to uncompress it before we feed it to the <command>tar</command>
                program.  You can use the following command to unpack it:
                <screen>
bunzip2 &#60;linux-2.4.9.tar.bz2 | tar xf - </screen>
                When the unpacking completes, you will have a directory called 
                <filename>linux</filename> containing the entire source tree.
                At this point, I usually like to rename the directory to
                something more meaningful.
                <screen>
mv linux linux-2.4.9 </screen>
                Once the directory has been renamed, then change into the
                new directory:
                <screen>
cd linux-2.4.9 </screen>
            </para>
            <para>
                I usually like to modify the <filename>Makefile</filename>
                before I start configuring the new kernel.  Near the top
                of the file is a variable named
                <command>EXTRAVERSION</command>.  I set this to 'ltsp-1', so
                that the actual version number of the kernel will be
                '2.4.9-ltsp-1', which makes it easier to identify the kernel
                later.  The top of the Makefile should look like this when you
                are done:
                <screen>
VERSION = 2
PATCHLEVEL = 4
SUBLEVEL = 9
EXTRAVERSION = -ltsp-1

KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) </screen>
            </para>
        </sect2>

        <sect2>
            <title>Kernel Patches</title>
            <para>
                After unpacking the kernel, you may have various patches
                you want to apply.  For example, the NFS Swap patch or
                the Linux Progress Patch.  These patches MUST be applied
                before configuring the kernel.
            </para>
            <sect3>
                <title>NFS Swap patch</title>
                <para>
                    The NFS Swap patch will allow the workstation kernel
                    to use a swapfile located on an NFS server.  While it
                    usually recommended to have enough memory in the
                    workstation to not require swapping, it can sometimes
                    be difficult to add more memory, especially on older
                    computers.  So, the ability to swap over NFS can make
                    an otherwise unuseable computer actually useable.
                </para>
                <para>
                    If the current directory is /usr/src/linux-2.4.9, and the
                    patch is in /usr/src, you can do the following to test
                    the patch:
                    <screen>
patch -p1 --dry-run &#60;../linux-2.4.9-nfs-swap.diff </screen>
                    This will test the patch, to make sure it can be applied
                    cleanly.  If it finishes with no errors, then you can
                    apply the patch without the <command>--dry-run</command>
                    option.
                    <screen>
patch -p1 &#60;../linux-2.4.9-nfs-swap.diff </screen>
                </para>
            </sect3>
            <sect3>
                <title>Linux Progress Patch (LPP)</title>
                <para>
                    The Linux Progress Patch (LPP) will allow you to configure
                    a graphic logo to display during the boot process.  The
                    normal kernel boot messages are redirected to another
                    tty screen, and special instructions are added to the
                    boot scripts to cause the Progress bar to reflect how far
                    along the boot process is.
                </para>
                <para>
                    Like the NFS Swap patch, you can test the LPP patch by
                    issuing this command:
                    <screen>
patch -p1 --dry-run &#60;../lpp-2.4.9 </screen>
                    If the test completes successfully, then you can apply
                    the patch with:
                    <screen>
patch -p1 &#60;../lpp-2.4.9 </screen>
                </para>
            </sect3>
        </sect2>

        <sect2>
            <title>Configuring kernel options</title>
            <para>
                You can now run the kernel configuration program of your choice.
                Available choices are:
                <itemizedlist>
                    <listitem>
                        <para>make xconfig</para>
                        <para>
                            This will invoke the X Windows version of the kernel
                            configuration utility.
                        </para>
                    </listitem>
                    <listitem>
                        <para>make menuconfig</para>
                        <para>
                            This will invoke the curses based version of the
                            kernel configuration utility.
                        </para>
                    </listitem>
                    <listitem>
                        <para>make config</para>
                        <para>
                            This will invoke the simple line-at-a-time version
                            of the kernel configuration utility.
                        </para>
                    </listitem>
                </itemizedlist>
            </para>
 
            <sect3>
                <title>Kernel configuration for use with an initrd</title>
                <para>

                    Configuring the kernel for use with an initrd requires
                    the following options to be set:
                    <itemizedlist>

                        <listitem>
                            <para>
                                File systems -> /dev filesystem support
                            </para>
                            <para>
                                /dev file system support must be enabled.  This
                                is selected in the 'File systems' section.
                                Do NOT specify 'Automatically mount at boot'.
                                The mount will be performed by the /linuxrc
                                script.
                            </para>
                        </listitem>
                        <listitem>
                            <para>
                                Block devices -> RAM disk support
                            </para>
                            <para>
                                LTSP workstations require that the kernel
                                support a RAM disk.  this is set in the
                                'Block devices' section.
                            </para>
                        </listitem>
                        <listitem>
                            <para>
                                Block devices -> Initial RAM disk (initrd)
                                support
                            </para>
                            <para>
                                This must also be enabled.
                            </para>
                        </listitem>
                        <listitem>
                            <para>
                                Processor type and features -> Processor family
                            </para>
                            <para>
                                You need to make sure that the kernel
                                you build can actually run on the CPU in
                                the workstation.  This is done in the
                                'Processor type and features'
                                section.  You should also turn off SMP
                                support, unless you actually have multiple
                                CPUs.
                            </para>
                        </listitem>
                        <listitem>
                            <para>
                                File systems -> Network file systems -> NFS
                                Client support
                            </para>
                            <para>
                                The workstation will be mounting its root
                                filesystem via NFS, so NFS client support
                                is required.
                            </para>
                        </listitem>
                    </itemizedlist>
                    That should take care of the required options.  You can
                    also turn off many features of the kernel, to reduce the
                    size of the kernel.
                </para>
            </sect3>

            <sect3>
                <title>Kernel configuration for use without an initrd</title>
                <para>
                    Configuring the kernel for use wihout an initrd differs
                    from a kernel with an initrd in a few ways:
                    <itemizedlist>
                        <listitem>
                            <para>
                                Block devices -> RAM disk support
                            </para>
                            <para>
                                LTSP workstations require that the kernel
                                support a RAM disk.
                            </para>
                        </listitem>

                        <listitem>
                            <para>
                                Block devices -> Initial RAM disk (initrd)
                                support
                            </para>
                            <para>
                                This needs to be disabled.
                            </para>
                        </listitem>
                        <listitem>
                            <para>
                                Networking options -> IP:kernel level
                                autoconfiguration
                            </para>
                            <para>
                                This needs to be enabled.  This will instruct
                                the kernel to automatically configure the eth0
                                ethernet interface, based on values passed on
                                the kernel command line.
                            </para>
                            <para>
                                It is not necessary to specify the DHCP, BOOTP
                                or RARP options because the Etherboot bootrom
                                has already done a DHCP or BOOTP request, and
                                it will make the IP parameters available on
                                the kernel command line.  This saves the
                                kernel from going through the trouble of
                                doing its own query.
                            </para>
                        </listitem>
                        <listitem>
                            <para>
                                Network device support -> Ethernet (10 or
                                100Mbit)
                            </para>
                            <para>
                                When not using an initrd, you must choose
                                the specific network card driver that matches
                                the network card.  This MUST be statically
                                linked into the kernel, because the ethernet
                                interface is needed before mounting the root
                                filesystem.  This is a major difference between
                                how a kernel with an initrd works.
                            </para>
                        </listitem>
                        <listitem>
                            <para>
                                File systems -> /dev filesystem support
                            </para>
                            <para>
                                As of LTSP version 2.09pre2,
                                <command>devfs</command>
                                support is needed.  This is true, regardless
                                of whether an initrd is used or not.
                            </para>
                        </listitem>
                        <listitem>
                            <para>
                                File systems -> Automatically mount at boot
                            </para>
                            <para>
                                When NOT using an initrd, the /dev filesystem
                                must be mounted by the kernel, during the boot
                                process.  So, say 'Y' here.
                            </para>
                        </listitem>
                        <listitem>
                            <para>
                                File systems -> Network file systems -> NFS
                                Client support
                            </para>
                            <para>
                                The workstation will be mounting its root
                                filesystem via NFS, so NFS client support
                                is required.
                            </para>
                        </listitem>
                    </itemizedlist>
                </para>
            </sect3>
        </sect2>

        <sect2>
            <title>Building the kernel</title>
 
            <para>
                To make things easier, a copy of the
                <filename>.config</filename>
                file is included in the ltsp_initrd_kit package.  You can
                copy that to the <filename>/usr/src/linux-2.4.9</filename>
                directory.
            </para>

            <para>
                Once you are done selecting or de-selecting the kernel options,
                you need to build the kernel.  The following commands need
                to be executed to build the kernel:
                <screen>
make dep
make clean
make bzImage
make modules
make modules_install </screen>
                You can string them all together like this:
                <screen>
make dep &amp;&amp; make clean &amp;&amp; make bzImage &amp;&amp; make modules &amp;&amp; make modules_install </screen>
                The double ampersand (&amp;) means that if the first command
                completes successfully, then the second command will
                be executed. 
                If the second command completes successfully, then the third
                command will be executed, and so on.
            </para>
            <para>
                When the kernel compilation is finished, the new kernel will be
                sitting in
                <filename class="directory">/usr/src/linux-2.4.7/arch/i386/boot/bzImage</filename>.
            </para>
        </sect2>

        <sect2>
            <title>Tagging the kernel for Etherboot</title>
            <para>
                For Etherboot to handle a Linux kernel, it needs to be prepared. 
                This is called 'Tagging' the kernel.  This process will add
                some additional code to the kernel that is executed before
                control is passed to the kernel.  The tool for tagging a
                kernel is called '<command>mknbi-linux</command>'.
            </para>
            <para>
                The ltsp_initrd_kit includes a shell script called
                <command>buildk</command> that includes all of the commands
                that you need to prepare the kernel image for network booting.
            </para>
        </sect2>
    </sect1>
</chapter>

<!--
<chapter>
    <title>Advanced Topic: Making bootroms</title>
    <para>
        Burning eproms with Etherboot code
    </para>
</chapter>
-->

<!--
<chapter>
    <title>Advanced Topic: Display Managers</title>
    <para>
        Burning eproms with Etherboot code
    </para>
</chapter>
-->

<!--
<chapter>
    <title>Advanced Topic: Font Server</title>
    <para>
        Burning eproms with Etherboot code
    </para>
</chapter>
-->

<!--
<chapter>
    <title>Advanced Topic: Configuring a Chooser</title>
    <para>
        Burning eproms with Etherboot code
    </para>
</chapter>
-->

<!--
<chapter>
    <title>Advanced Topic: Local Applications</title>
    <para>
        Burning eproms with Etherboot code
    </para>
</chapter>
-->

<!--
<chapter>
    <title>Advanced Topic: Accessing local peripherals</title>
    <para>
        Burning eproms with Etherboot code
    </para>
</chapter>
-->

<chapter>
    <title>lts.conf entries</title>
    <para>
        When we designed the LTSP, one of the issues that we knew that we
        would have to deal with varying hardware configurations for the
        workstations.  Certainly, whatever combination of processor, network
        card and video card available today would not be available in 3
        months, when we want to add more workstations to the network.
    </para>
    <para>
        So, we devised a way of specifying the configuration of each
        workstation.  The configuration file is called
        <filename>lts.conf</filename> and it lives in the
        <filename class="directory">/opt/ltsp/i386/etc</filename> directory.
    </para>

    <para>
        The format of the lts.conf allows for 'default' settings and
        individual workstation settings.  If all of your workstations are
        identical, you could specify all of the configuration settings in
        the '[Default]' section.
    </para>

    <sect1>
        <title>Sample lts.conf file</title>
        <para>
            Here is an example of the lts.conf file:
            <screen>
[Default]
        SERVER             = 192.168.0.254
        X_MOUSE_PROTOCOL   = "PS/2"
        X_MOUSE_DEVICE     = "/dev/psaux"
        X_MOUSE_RESOLUTION = 400
        X_MOUSE_BUTTONS    = 3
        USE_XFS            = N
        RUNLEVEL           = 5

[ws001]
        XSERVER            = auto
        X_MOUSE_PROTOCOL   = "Microsoft"
        X_MOUSE_DEVICE     = "/dev/ttyS1"
        X_MOUSE_RESOLUTION = 50
        X_MOUSE_BUTTONS    = 3
        X_MOUSE_BAUD       = 1200

[ws002]
        XSERVER            = XF86_Mach64

[ws003]
        RUNLEVEL           = 3 </screen>
        </para>
    </sect1>

    <sect1>
        <title>Available lts.conf parameters</title>
        <sect2>
            <title>General parameters</title>
            <variablelist>

                <varlistentry>
                    <term><command>Comments</command></term>
                    <listitem>
                        <para>
                            Comments start with the hash '#' sign and continue
                            through the end of the line.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>LTSP_BASEDIR</command></term>
                    <listitem>
                        <para>
                            This indicates where the LTSP root filesystems
                            are located.  The default value is
                            <filename>/opt/ltsp</filename>
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>SERVER</command></term>
                    <listitem>
                        <para>
                            This is the server that is used for the XDM_SERVER,
                            TELNET_HOST, XFS_SERVER and SYSLOG_HOST, if any of
                            those are not specified explicitly.  If you have
                            one machine that is acting as the server for
                            everything, then you can just specify the address
                            here and omit the other server parameters.  If
                            this value is not set,
                            <command>192.168.0.254</command> will be used.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>SYSLOG_HOST</command></term>
                    <listitem>
                        <para>
                            If you want to send logging messages to a machine
                            other than the default server, then you can
                            specify the machine here.  If this parameter is
                            NOT specified, then it will use the 'SERVER'
                            parameter described above.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>NFS_SERVER</command></term>
                    <listitem>
                        <para>
                            This specifies the IP address of the NFS server
                            used when the <filename>/home</filename> filesystem
                            is mounted.  The default is whatever the
                            <command>SERVER</command> is set to.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>USE_NFS_SWAP</command></term>
                    <listitem>
                        <para>
                            Set this to <command>Y</command> if you want to
                            turn on NFS swap.  The default is
                            <command>N</command>
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>SWAPFILE_SIZE</command></term>
                    <listitem>
                        <para>
                            This is how you can control the size of the
                            swapfile.  The default is <command>64m</command>.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>SWAP_SERVER</command></term>
                    <listitem>
                        <para>
                            The swapfile can exist on any server on the
                            network that is capable of handling it.  You
                            can specify the IP address of that server.  The
                            default is whatever the value of NFS_SERVER 
                            set to.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>NFS_SWAPDIR</command></term>
                    <listitem>
                        <para>
                            The directory on the server that is being
                            exported via NFS.  The default is
                            <filename>/var/opt/ltsp/swapfiles</filename>.
                            Make sure that the directory is being exported
                            in the <filename>/etc/exports</filename> file.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>TELNET_HOST</command></term>
                    <listitem>
                        <para>
                            If the workstation is setup to have a character
                            based interface, then the value of this parameter
                            will be used as the host to telnet into.  If this
                            value is NOT set, then it will use the value of
                            <command>SERVER</command> above.
                        </para>
                        <para>
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>DNS_SERVER</command></term>
                    <listitem>
                        <para>
                            Used to build the resolv.conf file.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>SEARCH_DOMAIN</command></term>
                    <listitem>
                        <para>
                            Used to build the resolv.conf file.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>MODULE_01</command> thru
                          <command>MODULE_10</command></term>
                    <listitem>
                        <para>
                            Upto 10 kernel modules can be loaded by using
                            these configuration entries.  The entire command
                            line that you would use when running insmod can
                            be specified here.  For example:
                            <screen>
MODULE_01   = uart401.o
MODULE_02   = sb.o io=0x220 irq=5 dma=1
MODULE_03   = opl3.o </screen>
                        </para>

                        <para>
                            If the value of this parameter is an absolute
                            pathname, then <command>insmod</command> will
                            be used to load the module.  Otherwise,
                            <command>modprobe</command> will be used.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>RAMDISK_SIZE</command></term>
                    <listitem>
                        <para>
                            When the workstation boots, it creates a ramdisk
                            and mounts it on the /tmp directory.  You can
                            control the size of the filesystem with this
                            parameter.  Specify it in units of kbytes
                            (1024 bytes).  To create a ramdisk of 1 megabyte,
                            specify <command>RAMDISK_SIZE = 1024</command>
                        </para>
                        <para>
                            If you change the size of the ramdisk here, you
                            will also need to change the size of the ramdisk
                            within the kernel. This can be compiled in, or if
                            you are using Etherboot or Netboot, you tell the
                            kernel the ramdisk size when you tag the kernel
                            with mknbi-linux.
                        </para>
                        <para>
                            The default value for this is 1024 ( 1 mb )
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>RCFILE_01</command> thru
                          <command>RCFILE_10</command></term>
                    <listitem>
                        <para>
                            Additional RC scripts can be executed by the
                            rc.local script.  Just put the script in
                            the /etc/rc.d directory, and specify the name of
                            the script in one of these entries.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>SOUND</command></term>
                    <listitem>
                        <para>
                            If the LTSP Sound package is installed, you need
                            to set this entry to <command>Y</command> and it
                            will execute the <command>rc.sound</command>
                            script to setup the sound card and daemon.
                            The default is <command>N</command>.
                        </para>
                    </listitem>
                </varlistentry>

            </variablelist>
        </sect2>

        <sect2>
            <title>X-Windows parameters</title>
            <variablelist>
                <varlistentry>
                    <term><command>XDM_SERVER</command></term>
                    <listitem>
                        <para>
                            If you want to point XDM to a machine other than
                            the default server, then you can specify the
                            server here.  If this parameter is NOT specified,
                            then it will use the 'SERVER' parameter described
                            above.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>XSERVER</command></term>
                    <listitem>
                        <para>
                            This defines which X server the workstation will
                            run.  For PCI and AGP video cards, this parameter
                            should not be required.  The rc.local script should
                            be able to auto-detect the card.  You can also set
                            this value to <command>auto</command> to indicate
                            that it should attempt to auto-detect the card.
                        </para>

                        <para>
                            For ISA video cards, or to force a specific
                            X server, you can specify the name of the driver
                            or Xserver in this entry.
                        </para>
                        <para>
                            If the value begins with <command>XF86_</command>,
                            then XFree86 3.3.6 will be used.  Otherwise,
                            XFree86 4.1.x will be used.
                            The default value for this is
                            <command>auto</command>.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>X_MODE_0</command> through
                          <command>X_MODE_2</command></term>
                    <listitem>
                        <para>
                            Up to 3 Modelines or resolutions can be configured
                            for the workstation.  This entry can take two
                            different types of values.  It can take either
                            a resolution, or a complete modeline.
                            <programlisting width=80>
X_MODE_0 = 800x600

   or

X_MODE_0 = 800x600 60.75 800 864 928 1088 600 616 621 657 -HSync -VSync
                            </programlisting>
                        </para>
                        <para>
                            If none of the X_MODE_x entries are not specified,
                            then it will use the built-in modelines, and
                            the resolutions of 1024x768, 800x600 and 640x480.
                        </para>
                        <para>
                            If one or more X_MODE_x entries are specified, they
                            will completely override any built-in modelines.
                        </para>
                          
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>X_MOUSE_PROTOCOL</command></term>
                    <listitem>
                        <para>
                            Any value that will work for the XFree86 Pointer
                            Protocol keyword can be put here.  Typical values
                            include "Microsoft" and "PS/2".  The default value
                            for this is <command>"PS/2"</command>.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>X_MOUSE_DEVICE</command></term>
                    <listitem>
                        <para>
                            This is the device node that the mouse is
                            connected to.  If it is a serial mouse, this
                            would be a serial port, such as
                            <command>/dev/ttyS0</command> or
                            <command>/dev/ttyS1</command>.  If it is a PS/2
                            keyboard mouse, this value would be
                            <command>/dev/psaux</command>.  The default
                            value for this is <command>/dev/psaux</command>.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>X_MOUSE_RESOLUTION</command></term>
                    <listitem>
                        <para>
                            This is the 'Resolution' value in the
                            <command>XF86Config</command> file. A typical
                            value for a serial mouse is <command>50</command>
                            and a typical value for a PS/2 mouse would be
                            <command>400</command>.  The default value for
                            this is <command>400</command>.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>X_BUTTONS</command></term>
                    <listitem>
                        <para>
                            This tells the system how many buttons the mouse
                            has.  Usually set to <command>2</command> or
                            <command>3</command>.  The default value for
                            this is <command>3</command>.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>X_MOUSE_EMULATE3BTN</command></term>
                    <listitem>
                        <para>
                            This tells the X server to emulate a 3-button
                            mouse by accepting a click of both the right and
                            left mouse buttons simultaneously.
                            The default value is <command>N</command>.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>X_MOUSE_BAUD</command></term>
                    <listitem>
                        <para>
                            For serial mice, this defines the baud rate.
                            The default value for this is
                            <command>1200</command>.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>X_COLOR_DEPTH</command></term>
                    <listitem>
                        <para>
                            This is the number of bits to use for the color
                            depth.  Possible values are <command>8</command>,
                            <command>15</command>, <command>16</command>,
                            <command>24</command> and <command>32</command>. 
                            8 bits will give 256 colors, 16 will give 65536
                            colors, 24 will give 16 million colors and 32 bits
                            will give 4.2 billion colors!  Not all X servers
                            support all of these values.  The default value
                            for this is <command>16</command>
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>USE_XFS</command></term>
                    <listitem>
                        <para>
                            You have a choice of running the X Font Server
                            (XFS) or reading the fonts through the NFS
                            filesystem.  The font server should provide
                            a simple way of keeping all of the fonts in
                            one place, but there has been some problems
                            when the number of workstations grows past
                            about 40.  The 2 values for this option are
                            <command>Y</command> and <command>N</command>.
                            The default value is <command>N</command>. 
                            If you do want to use a font server, then you
                            can use the <command>XFS_SERVER</command> entry
                            to specify which host will act as the font server.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>XFS_SERVER</command></term>
                    <listitem>
                        <para>
                            If you are using an X Font Server to serve fonts,
                            then you can use this entry to specify the IP
                            address of the host that is acting as the font
                            server.  If this is not specified, it will use
                            the default server, which is specified with the
                            <command>SERVER</command> entry described above.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>X_HORZSYNC</command></term>
                    <listitem>
                        <para>
                            This sets the XFree86 <command>HorizSync</command>
                            configuration parameter.  It defaults to
                            <command>"31-62"</command>.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>X_VERTREFRESH</command></term>
                    <listitem>
                        <para>
                            This sets the XFree86 <command>VertRefresh</command>
                            configuration parameter.  It defaults
                            to <command>"55-90"</command>.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>XF86CONFIG_FILE</command></term>
                    <listitem>
                        <para>
                            If you want to create your own complete
                            XF86Config file you can do so and place it in
                            the <command>/opt/ltsp/i386/etc</command>
                            directory.  Then, whatever you decide to call
                            it needs to be entered as a value for this
                            configuration variable.  For example:
                            <screen>
XF86CONFIG_FILE = XF86Config.ws004 </screen>
                        </para>
                    </listitem>
                </varlistentry>
            </variablelist>
        </sect2>

        <sect2>
            <title>Touch screen parameters</title>
            <variablelist>
                <varlistentry>
                    <term><command>USE_TOUCH</command></term>
                    <listitem>
                        <para>
                            If you are connecting a touch screen to the
                            workstation, you can enable it by setting this
                            entry to <command>Y</command>.  If enabled,
                            additional configuration entries will configure
                            specific aspects of the touch screen.  The
                            default value is <command>N</command>.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>X_TOUCH_DEVICE</command></term>
                    <listitem>
                        <para>
                            A touch screen works like a mouse and usually
                            is interfaced with the workstation through a
                            serial port.  You can specify which serial port
                            with this entry.  For example, you could set it
                            equal to <command>/dev/ttyS0</command>.  There
                            is no default value for this entry.
                        </para>
                    </listitem>
                </varlistentry>
    
                <varlistentry>
                    <term><command>X_TOUCH_MINX</command></term>
                    <listitem>
                        <para>
                            Callibration entry for an EloTouch touch screen.
                            Defaults to <command>433</command>.
                        </para>
                    </listitem>
                </varlistentry>
         
                <varlistentry>
                    <term><command>X_TOUCH_MAXX</command></term>
                    <listitem>
                        <para>
                            Callibration entry for an EloTouch touch screen.
                            Defaults to <command>3588</command>.
                        </para>
                    </listitem>
                </varlistentry>
         
                <varlistentry>
                    <term><command>X_TOUCH_MINY</command></term>
                    <listitem>
                        <para>
                            Callibration entry for an EloTouch touch screen.
                            Defaults to <command>569</command>.
                        </para>
                    </listitem>
                </varlistentry>
         
                <varlistentry>
                    <term><command>X_TOUCH_MAXY</command></term>
                    <listitem>
                        <para>
                            Callibration entry for an EloTouch touch screen.
                            Defaults to <command>3526</command>.
                        </para>
                    </listitem>
                </varlistentry>
         
                <varlistentry>
                    <term><command>X_TOUCH_UNDELAY</command></term>
                    <listitem>
                        <para>
                            Callibration entry for an EloTouch touch screen.
                            Defaults to <command>10</command>.
                        </para>
                    </listitem>
                </varlistentry>
         
                <varlistentry>
                    <term><command>X_TOUCH_RPTDELAY</command></term>
                    <listitem>
                        <para>
                            Callibration entry for an EloTouch touch screen.
                            Defaults to <command>10</command>.
                        </para>
                    </listitem>
                </varlistentry>
            </variablelist>
        </sect2>

        <sect2>
            <title>Local apps parameters</title>
            <variablelist>
                <varlistentry>
                    <term><command>LOCAL_APPS</command></term>
                    <listitem>
                        <para>
                            If you want the ability to run applications
                            locally on a workstation, set this variable to
                            <command>Y</command>.  Several additional steps
                            must be taken on the server to enable local apps. 
                            See the 'Local Apps' section in the LTSP manual
                            for more information.  The default value is
                            <command>N</command>.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>NIS_DOMAIN</command></term>
                    <listitem>
                        <para>
                            If you do setup LOCAL_APPS, then you need to have
                            an NIS server on the network.  The NIS_DOMAIN
                            entry is where you specify the NIS domain name. 
                            It needs to match a domain name that has been
                            defined on the NIS server.  This is NOT the same
                            thing as an internet DOMAIN.  The default value
                            is <command>ltsp</command>.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>NIS_SERVER</command></term>
                    <listitem>
                        <para>
                            Set this to the IP address of your NIS server if
                            you don't want it to send a broadcast looking for
                            an NIS server.
                        </para>
                    </listitem>
                </varlistentry>
            </variablelist>
        </sect2>

        <sect2>
            <title>Keyboard parameters</title>
            <para>
                All of the keyboard support files are now copied into the
                /opt/ltsp/i386 hierarchy so configuring international keyboard
                support
                is now a matter of configuring XFree86.  Several configuration
                parameters are available to make this possible.
            </para>
            <para>
                The values for the above parameters are from the XFree86
                documentation.  Whatever is valid for XFree86 is valid for
                these parameters.
            </para>
            <para>
                We would like to add documentation to show what values are
                needed for each type of international keyboard.  If you work
                with this and can configure your international keyboards,
                feedback to the ltsp core group would be greatly appreciated.
            </para>
            <variablelist>
                <varlistentry>
                    <term><command>XkbTypes</command></term>
                    <listitem>
                        <para>
                            The default value for this is the
                            word '<command>default</command>'.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>XkbCompat</command></term>
                    <listitem>
                        <para>
                            The default value for this is
                            the word '<command>default</command>'.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>XkbSymbols</command></term>
                    <listitem>
                        <para>
                            The default value for this is
                            '<command>us(pc101)</command>'.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>XkbModel</command></term>
                    <listitem>
                        <para>
                            The default value for this
                            is '<command>pc101</command>'.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>XkbLayout</command></term>
                    <listitem>
                        <para>
                            The default value for this
                            is '<command>us</command>'.
                        </para>
                    </listitem>
                </varlistentry>
            </variablelist>
        </sect2>

        <sect2>
            <title>Printer configuration parameters</title>
            <para>
                Upto three printers can be connected to a diskless workstation.
                A combination of serial and parallel printers can be configured
                via the following entries in the <command>lts.conf</command>
                file:
            </para>

            <variablelist>
                <varlistentry>
                    <term><command>PRINTER_0_DEVICE</command></term>
                    <listitem>
                        <para>
                            The device name of the first printer. Names such as
                            <command>/dev/lp0</command>,
                            <command>/dev/ttyS0</command> or
                            <command>/dev/ttyS1</command> are allowed.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>PRINTER_0_TYPE</command></term>
                    <listitem>
                        <para>
                            The type of the printer.  Valid choices are
                            '<command>P</command>' or for Parallel,
                            and '<command>S</command>' for Serial.
                        </para>
                    </listitem>
                </varlistentry>
               
                <varlistentry>
                    <term><command>PRINTER_0_PORT</command></term>
                    <listitem>
                        <para>
                            The TCP/IP Port number to use. By default, it will
                            use '<command>9100</command>'
                        </para>
                    </listitem>
                </varlistentry>
                   
                <varlistentry>
                    <term><command>PRINTER_0_SPEED</command></term>
                    <listitem>
                        <para>
                            If the printer is serial, this is the setting
                            that will select the baud rate.  By default,
                            '<command>9600</command>' will be used.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>PRINTER_0_FLOWCTRL</command></term>
                    <listitem>
                        <para>
                            For serial printers, the flow control can be
                            specified.  Either '<command>S</command>' for
                            Software (XON/XOFF) flow control, or
                            '<command>H</command>' for Hardware (CTS/RTS)
                            flow control.  If neither is specified,
                            '<command>S</command>' will be used.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>PRINTER_0_PARITY</command></term>
                    <listitem>
                        <para>
                            For serial printers, the Parity can be specified. 
                            The choices are: '<command>E</command>'-Even,
                            '<command>O</command>'-Odd or
                            '<command>N</command>'-None.  If not specified,
                            '<command>N</command>' will be used.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>PRINTER_0_DATABITS</command></term>
                    <listitem>
                        <para>
                            For serial printers, the number of data bits can
                            be specified.  The choices are: 
                            '<command>5</command>', '<command>6</command>',
                            '<command>7</command>' and '<command>8</command>'. 
                            If not specified, '<command>8</command>' will be
                            used.
                        </para>
                    </listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>PRINTER_1_DEVICE</command></term>
                    <listitem><para>Second printer device name</para></listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>PRINTER_1_TYPE</command></term>
                    <listitem><para>Second printer device type</para></listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>PRINTER_1_PORT</command></term>
                    <listitem><para>Second printer device TCP/IP
                             port</para></listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>PRINTER_1_SPEED</command></term>
                    <listitem><para>Second printer baud
                            rate (serial)</para></listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>PRINTER_1_FLOWCTRL</command></term>
                    <listitem><para>Second printer flow
                            control (serial)</para></listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>PRINTER_1_PARITY</command></term>
                    <listitem><para>Second printer
                             parity (serial)</para></listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>PRINTER_1_DATABITS</command></term>
                    <listitem><para>Second printer data
                              bits (serial)</para></listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>PRINTER_2_DEVICE</command></term>
                    <listitem><para>Third printer device
                              name</para></listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>PRINTER_2_TYPE</command></term>
                    <listitem><para>Third printer device
                              type</para></listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>PRINTER_2_PORT</command></term>
                    <listitem><para>Third printer device
                              TCP/IP port</para></listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>PRINTER_2_SPEED</command></term>
                    <listitem><para>Third printer baud
                              rate (serial)</para></listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>PRINTER_2_FLOWCTRL</command></term>
                    <listitem><para>Third printer flow
                              control (serial)</para></listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>PRINTER_2_PARITY</command></term>
                    <listitem><para>Third printer parity (serial)</para></listitem>
                </varlistentry>

                <varlistentry>
                    <term><command>PRINTER_2_DATABITS</command></term>
                    <listitem><para>Third printer data
                              bits (serial)</para></listitem>
                </varlistentry>
            </variablelist>
        </sect2>
    </sect1>
</chapter>

<chapter>
    <title>Local Applications</title>
    <para>
        In an LTSP environment, you have a choice of running the applications
        locally on the workstation, or remotely on the server.
    </para>

    <para>
        By far, the easiest way to setup an LTSP environment is to run the
        apps on the server.  That is, the client application runs on the
        server, using the servers' CPU and memory, while it displays its output
        on the workstation and uses the workstations' keyboard and mouse.
    </para>

    <para>
        This is a fundamental capability of X Windows.  The workstation works
        just like a standard X Windows terminal.
    </para>

    <para>
        In order for a user to run an application on the workstation, the
        workstation needs to know some information about the user.  Info such
        as the following:
        <itemizedlist>
            <listitem>
                <para>
                    User id
                </para>
            </listitem>
            <listitem>
                <para>
                    Primary group that the user belongs to
                </para>
            </listitem>
            <listitem>
                <para>
                    The users home directory
                </para>
            </listitem>
        </itemizedlist>
        LTSP relies on the Network Information Service - NIS, (formerly
        called <emphasis role="strong">Yellow Pages</emphasis>) to make
        the user and group information available to the workstations.
    </para>

    <sect1>
        <title>Benefits of running apps locally</title>
        <para>
            There are benefits to running applications on the workstation.
        </para>
        <para>
            <itemizedlist>
                <listitem>
                    <para>
                        Reduces the load on the server.  In large networks
                        with memory intensive applications, such as Netscape,
                        running the app on the workstation can provide better
                        performance, as long as the workstation is powerful
                        enough to handle it.
                    </para>
                </listitem>
                <listitem>
                    <para>
                        Runaway apps will not affect other users.
                    </para>
                </listitem>
                <listitem>
                    <para>
                        Sound support is much easier to configure when the
                        application that plays the sound is running on the
                        workstation.
                    </para>
                </listitem>
            </itemizedlist>
        </para>
    </sect1>

    <sect1>
        <title>Issues with setting up support for local apps</title>
        <para>
            Setting up the ability to run applications locally requires
            much more.
            <itemizedlist>
                <listitem>
                    <para>
                        Greater demaind on the workstation.  It needs more
                        RAM and a more powerful CPU.  64mb of ram on the 
                        workstation is a pretty good starting point.
                    </para>
                </listitem>
                <listitem>
                    <para>
                        NIS - To run the apps on the workstation, you first
                        must identify yourself to the workstation.  That is,
                        the workstation needs to know who you are.  This
                        requires some form of password authentication.  NIS
                        has been chosen as the method of authenticating users
                        over the network.
                    </para>
                </listitem>
                <listitem>
                    <para>
                        Additional directories need to be exported from the
                        workstation to mount via NFS.
                    </para>
                </listitem>
                <listitem>
                    <para>
                        Slower startup of applications, because they need to
                        be read via NFS, causing increased network activity.
                        Also, because each copy of the program is running on
                        its own CPU, you won't get the advantage of the
                        ability of Linux/Unix to share code segments between
                        multiple instances of the same program, which would
                        reduce the time it takes for second and succeeding
                        invocations of the program.
                    </para>
                </listitem>
            </itemizedlist>
        </para>
    </sect1>

    <sect1>
        <title>Server Configuration for Local Apps</title>
        <sect2>
            <title>lts.conf entries</title>
            <para>
                A few entries need to be setup in the
                <filename>lts.conf</filename> file:
                <variablelist>
                  <varlistentry>
                    <term><command>LOCAL_APPS</command></term>
                    <listitem>
                      <para>
                        This must be set to <command>Y</command>.  It
                        will cause the following to happen during the
                        workstation boot process:
                        <orderedlist>
                          <listitem>
                            <para>
                              The <filename>/home</filename>
                              directory on the server will be 
                              mounted via NFS.
                            </para>
                          </listitem>
                          <listitem>
                            <para>
                              The <filename>/var/yp/nicknames</filename>
                              will be created on the workstation.
                            </para>
                          </listitem>
                          <listitem>
                            <para>
                              The <command>portmapper</command>
                              will be started on the workstation.
                            </para>
                          </listitem>
                          <listitem>
                            <para>
                              <command>xinetd</command> will be
                              started on the workstation.
                            </para>
                          </listitem>
                          <listitem>
                            <para>
                              The <filename>/etc/yp.conf</filename>
                              file will be created on the
                              workstation.
                            </para>
                          </listitem>
                          <listitem>
                            <para>
                              The <command>domainname</command>
                              command will be run with the
                              value of the <command>NIS_DOMAIN</command>
                              lts.conf entry.
                            </para>
                          </listitem>
                          <listitem>
                            <para>
                              The <command>ypbind</command>
                              will be run on the workstation.
                            </para>
                          </listitem>
                        </orderedlist>
                      </para>
                    </listitem>
                  </varlistentry>
                  <varlistentry>
                    <term><command>NIS_DOMAIN</command></term>
                    <listitem>
                      <para>
                        With NIS, all of the nodes on the network that want
                        to be associated with a specific NIS server need to
                        belong to the same NIS domain (this is not related
                        in any way to a DNS Domain).  You use the NIS_DOMAIN
                        entry to specify the name of the NIS domain that the
                        workstation will belong to.
                      </para>
                    </listitem>
                  </varlistentry>
                  <varlistentry>
                    <term><command>NIS_SERVER</command></term>
                    <listitem>
                      <para>
                        NIS will either attempt to bind with a specific NIS
                        server, or it will send a broadcast out to the network,
                        looking for a server.  If you want to choose a specific
                        server, then enter the IP address of that server in the
                        NIS_SERVER entry.
                      </para>
                    </listitem>
                  </varlistentry>
                </variablelist>
            </para>
        </sect2>

        <sect2>
            <title>Network Information Service - NIS</title>
            <para>
                NIS is a Client/Server type of service.  On the server,
                there is a daemon running, that will accept requests from
                the clients (workstations).  The daemon on the server is
                called <command>ypserv</command>.
            </para>
            <para>
                On the workstation, there is a process called
                <command>ypbind</command>.  When the workstation needs to
                lookup information about a user, such as verifying a password
                or finding the users home directory, it will use ypbind to
                establish a connection to ypserv, on the server.
            </para>
            <para>
                If you are already running NIS in your network environment,
                then there is no need to configure the LTSP server to
                also run ypserv.  You can just configure the NIS_DOMAINNAME
                and NIS_SERVER entries in lts.conf to match your current
                NIS scheme.
            </para>
            <para>
                If you are NOT already running NIS in your network, then you
                will need to configure the server to run
                <command>ypserv</command>.
            </para>
            <para>
                For complete information on setting up an NIS server, refer
                to the HOWTO document on the LDP site called 
                <emphasis role="strong">The Linux NIS(YP)/NYS/NIS+ HOWTO</emphasis>.
                Refer to the list of other sources of information at the
                end of this document.
            </para>
        </sect2>
    </sect1>

    <sect1>
        <title>Application Configuration</title>
        <para>
            To setup an application to run on the workstation, you need to
            put all of the components of the application in a place where
            the workstation can see it.
        </para>

        <para>
            With older versions of LTSP (2.08 and earlier), lots of directories
            were exported on the server and mounted by the workstation.  
            Directories such as <filename>/bin</filename>,
            <filename>/usr/bin</filename>, <filename>/lib</filename> and
            <filename>/usr</filename> were exposed to the workstation.
        </para>

        <para>
            The problem with that scheme is that it only works if the
            workstation and the server are the same architecture.  In fact,
            even differences, like the server being a Pentium II (i686) and
            the workstation being a classic Pentium (i586) can be a problem,
            because the server will likely have the i686 libraries and not
            the i386, i486 or i586 libraries.
        </para>

        <para>
            So, the cleanest way to handle this is to have a complete
            tree with all of the binaries and libraries that the workstation
            will need, independent of the server binaries and libraries.
        </para>

        <para>
            Configuring an application for local execution requires putting
            all of the required pieces in the tree.  One of the packages
            available for download from the LTSP site is the Local netscape
            package, installs alot of files into the
            <filename>/opt/ltsp/i386/usr/local/netscape</filename> directory.
            Things like java classes, help files, executable binary files and
            scripts are put there.
        </para>

        <para>
            Netscape doesn't need any additional system libraries, so there
            is nothing to add to the <filename>/opt/ltsp/i386/lib</filename>
            directory.  Many applications do require additional libraries.
        </para>

        <para>
            So, how can you determine what libraries are needed?  That's where
            the <command>ldd</command> command comes in handy.
        </para>
        <para>
            Lets assume that you want to setup a certain application to
            run locally.  We'll pick <command>gaim</command> as an example.
            <command>gaim</command> is an AOL Instant Messenger client, that
            will allow you to communicate with other people on AOL forums.
        </para>
        <para>
            The first thing you need to do is find the <command>gaim</command>
            executable binary file.  On a Redhat 7.2 system, it is located
            in the <filename>/usr/bin</filename> directory.
        </para>
        <para>
            Once you locate the <command>gaim</command> binary, you can
            run <command>ldd</command> against it:
            <programlisting>
[jam@server /]$ ldd /usr/bin/gaim
        libaudiofile.so.0    => /usr/lib/libaudiofile.so.0 (0x40033000)
        libm.so.6            => /lib/i686/libm.so.6 (0x40051000)
        libnsl.so.1          => /lib/libnsl.so.1 (0x40074000)
        libgnomeui.so.32     => /usr/lib/libgnomeui.so.32 (0x4008a000)
        libart_lgpl.so.2     => /usr/lib/libart_lgpl.so.2 (0x4015d000)
        libgdk_imlib.so.1    => /usr/lib/libgdk_imlib.so.1 (0x4016c000)
        libSM.so.6           => /usr/X11R6/lib/libSM.so.6 (0x40191000)
        libICE.so.6          => /usr/X11R6/lib/libICE.so.6 (0x4019a000)
        libgtk-1.2.so.0      => /usr/lib/libgtk-1.2.so.0 (0x401b1000)
        libdl.so.2           => /lib/libdl.so.2 (0x402df000)
        libgdk-1.2.so.0      => /usr/lib/libgdk-1.2.so.0 (0x402e3000)
        libgmodule-1.2.so.0  => /usr/lib/libgmodule-1.2.so.0 (0x40319000)
        libXi.so.6           => /usr/X11R6/lib/libXi.so.6 (0x4031d000)
        libXext.so.6         => /usr/X11R6/lib/libXext.so.6 (0x40325000)
        libX11.so.6          => /usr/X11R6/lib/libX11.so.6 (0x40333000)
        libgnome.so.32       => /usr/lib/libgnome.so.32 (0x40411000)
        libgnomesupport.so.0 => /usr/lib/libgnomesupport.so.0 (0x40429000)
        libesd.so.0          => /usr/lib/libesd.so.0 (0x4042e000)
        libdb.so.2           => /usr/lib/libdb.so.2 (0x40436000)
        libglib-1.2.so.0     => /usr/lib/libglib-1.2.so.0 (0x40444000)
        libcrypt.so.1        => /lib/libcrypt.so.1 (0x40468000)
        libc.so.6            => /lib/i686/libc.so.6 (0x40495000)
        libz.so.1            => /usr/lib/libz.so.1 (0x405d1000)
        /lib/ld-linux.so.2   => /lib/ld-linux.so.2 (0x40000000) </programlisting>
        </para>
        <para>
            The listing above shows all of the libraries that the
            <command>gaim</command> program is dynamically linked against.
        </para>
        <para>
            Most programs that use shared libs, rely on the dynamic loader
            <command>ld-linux</command> to locate and load each of the
            shared libraries.  Some programs, however, load the libraries
            manually with the <command>dlopen()</command> function call.
            For those applications, <command>ldd</command> will not show
            the libraries.  In that case, <command>strace</command> can be
            used to trace the execution of the program, and you will see
            the <command>dlopen()</command> calls, with the name of the
            library listed in the arguments.
        </para>
        <para>
            Once the list of libraries has been collected, the required
            libraries will need to be copied to the appropriate places in the
            <filename>/opt/ltsp/i386</filename> tree.
        </para>
        
    </sect1>

    <sect1>
        <title>Launching local applications</title>
        <para>
            In X Windows, programs typically run relative to where the
            window manager runs.  That is, if the window manager is running
            on the server, displaying its output on the workstation, then any
            programs that are launched, will also run on the server, sending
            their output to the workstation.
        </para>
        <para>
            The trick is having the server tell the workstation to launch the
            program.  This is typically done with the <command>rsh</command>
            command.
        </para>
        <para>
            Here's an example of how to run the <command>gaim</command> program
            on the workstation:
            <programlisting>
HOST=`echo $DISPLAY | awk -F: '{ print $1 }'`
rsh ${HOST} /usr/bin/gaim -display ${DISPLAY} </programlisting>
        </para>
        <para>
            The above example can be entered in an
            <command>xterm</command> window, or it can be put into a shell
            script, and be launched by an icon on the desktop.
        </para>
        <para>
            Launching local Netscape is done in a similar way, but an 
            additional environment variable needs to be set, before running
            the program.
            <programlisting>
HOST=`echo $DISPLAY | awk -F: '{ print $1 }'`
rsh ${HOST} MOZILLA_HOME=/usr/local/netscape \
       /usr/local/netscape/netscape -display ${DISPLAY} </programlisting>
        </para>
    </sect1>

</chapter>

<chapter>
    <title>Configuration examples</title>
    <para>
        Almost any aspect of the workstation can be configured with entries
        in the <filename>lts.conf</filename>, which is usually located in
        the <filename>/opt/ltsp/i386/etc</filename> directory.
    </para>
    <sect1>
        <title>Serial Mouse</title>
        <para>
            Here is an example of the <filename>lts.conf</filename> entries for
            a standard 2-button serial mouse:
            <screen>
X_MOUSE_PROTOCOL    = "Microsoft"
X_MOUSE_DEVICE      = "/dev/ttyS0"
X_MOUSE_RESOLUTION  = 400
X_MOUSE_BUTTONS     = 2
X_MOUSE_EMULATE3BTN = Y
</screen>
        </para>
    </sect1>

    <sect1>
        <title>PS/2 Wheel mouse</title>
        <para>
            Here is an example of the <filename>lts.conf</filename> entries for
            an Intellimouse:
            <screen>
X_MOUSE_PROTOCOL    = "IMPS/2"
X_MOUSE_DEVICE      = "/dev/psaux"
X_MOUSE_RESOLUTION  = 400
X_MOUSE_BUTTONS     = 5
X_ZAxisMapping      = "4 5"
</screen>
        </para>
    </sect1>

    <sect1>
        <title>USB printer on a ThinkNic</title>
        <para>
            The ThinkNIC workstation has a USB port, which can be used
            for attaching a local printer.  Here is an example of the
            entries required in the <filename>lts.conf</filename> file:
            <screen>
MODULE_01           = usb-ohci
MODULE_02           = printer
PRINTER_0_DEVICE    = /dev/usb/lp0
PRINTER_0_TYPE      = S
</screen>
        </para>
    </sect1>

    <sect1>
        <title>Forcing a workstation to load a XFree86 3.3.6 Xserver</title>
        <para>
            By default, XFree86 4.1.0 will be used for a workstation.
            If you want to force the workstation to use an older
            X3.3.6 Xserver, you first need to load the proper
            version 3.3.6 Xserver package.  Then, you need to add
            the entry in the <filename>lts.conf</filename> file.
            This is an example of specifying the <command>SVGA</command>
            Xserver:
            <screen>
XSERVER             = XF86_SVGA
</screen>
        </para>
    </sect1>


</chapter>

<chapter>
    <title>Other sources of information</title>
    <sect1>
        <title>Online references</title>
        <para>
            <orderedlist>
                <listitem>
                    <para>
                        The LTSP home page&nbsp;&nbsp;
                    </para>
                    <para>
                        <ulink url="http://www.LTSP.org">
                            <citetitle>www.LTSP.org</citetitle>
                        </ulink>
                    </para>
                    <para>
                    </para>
                </listitem>
                        
                <listitem>
                    <para>
                        Diskless-Nodes HOW-TO document for Linux&nbsp;&nbsp;
                    </para>
                    <para>
                        <ulink url="http://www.linuxdoc.org/HOWTO/Diskless-HOWTO.html">
                            <citetitle>www.linuxdoc.org/HOWTO/Diskless-HOWTO.html</citetitle>
                        </ulink>
                    </para>
                    <para>
                    </para>
                </listitem>

                <listitem>
                    <para>
                        Etherboot Home Page&nbsp;&nbsp;
                    </para>
                    <para>
                        <ulink url="http://etherboot.sourceforge.net">
                            <citetitle>etherboot.sourceforge.net</citetitle>
                        </ulink>
                    </para>
                    <para>
                    </para>
                </listitem>

                <listitem>
                    <para>
                        The Rom-O-Matic site&nbsp;&nbsp;
                    </para>
                    <para>
                        <ulink url="http://www.rom-o-matic.net">
                            <citetitle>www.Rom-O-Matic.net</citetitle>
                        </ulink>
                    </para>
                    <para>
                    </para>
                </listitem>

                <listitem>
                    <para>
                        XFree86 Mouse Support&nbsp;&nbsp;
                    </para>
                    <para>
                        <ulink url="http://www.xfree86.org/current/mouse.html">
                            <citetitle>www.xfree86.org/current/mouse.html</citetitle>
                        </ulink>
                    </para>
                    <para>
                    </para>
                </listitem>

                <listitem>
                    <para>
                        XFree86-Video-Timings-HOWTO&nbsp;&nbsp;
                    </para>
                    <para>
                        <ulink url="http://www.linuxdoc.org/HOWTO/XFree86-Video-Timings-HOWTO.html">
                            <citetitle>www.linuxdoc.org/HOWTO/XFree86-Video-Timings-HOWTO.html</citetitle>
                        </ulink>
                    </para>
                    <para>
                    </para>
                </listitem>

                <listitem>
                    <para>
                        The Linux NIS(YP)/NYS/NIS+ HOWTO&nbsp;&nbsp;
                    </para>
                    <para>
                        <ulink url="http://www.linuxdoc.org/HOWTO/NIS-HOWTO.html">
                            <citetitle>www.linuxdoc.org/HOWTO/NIS-HOWTO.html</citetitle>
                        </ulink>
                    </para>
                    <para>
                    </para>
                </listitem>


            </orderedlist>
        </para>
    </sect1>

    <sect1>
        <title>Print publications</title>
        <para>
            <orderedlist>
                <listitem>
                    <para>
                        <literalLayout>
Managing NFS and NIS
Hal Stern
O'Reilly &amp; Associates, Inc.
1991
ISBN 0-937175-75-7
                        </literalLayout>
                    </para>                        
                </listitem>

                <listitem>
                    <para>                        
                        <literalLayout>
TCP/IP Illustrated, Volume 1
W. Richard Stevens
Addison-Wesley
1994
ISBN 0-201-63346-9
                        </literalLayout>
                    </para>                        
                </listitem>

                <listitem>
                    <para>                        
                        <literalLayout>
X Window System Administrator's Guide
Linda Mui and Eric Pearce
O'Reilly &amp; Associates, Inc.
1993
ISBN 0-937175-83-8
(Volume 8  of the The Definitive Guides to the X Window System)
                        </literalLayout>
                    </para>                        
                </listitem>
            </orderedlist>
        </para>
    </sect1>
</chapter>

</book>
