r1 - 07 Jul 2005 - 03:58:44 - CoryOldfordYou are here: TWiki >  Ltsp Web  >  Gentoo > CorysInstallScript
#!/bin/bash
# Distributed under the terms of the GNU General Public License v2
# Written by: Cory Oldford
# Purpose: Install LTSP and related services under Gentoo Linux.

# Todo: 
#  - make memtest optional.
#  - optional installation of memtest from portage.
#  - optional memtest server bootloader option.
#  - figure out how to autodetect dhcp range.
#  - add code to create /opt/ltsp symlink for easy ltsp version switches and testing.
#  - make use of ltsp swap files directory
#  - look at tightening xinetd security 
#  - make freedos optional
#  - optional inclusion of user specified directory in freedos floppy image 
#  - add xdm, gdm, or kdm installation/configuration code.
#  - finalize lts.conf to allow booting to a graphical login.

# Set the interface.
interface='eth0'

# Leave this set to auto if you want the ip settings determined automagically.
interface_detect='auto'

# If interface_detect is set to auto the network configuration
# will be auto configured based on the output of ifconfig, route and dnsdomainname.
# If this value is set to anything other than auto you must
# uncomment the interface_* variables and configure to your needs.
# interface_ip='192.168.0.224'
# interface_broadcast='192.168.0.255'
# interface_netmask='255.255.255.0'
# interface_gateway='192.168.0.1'
# interface_network_ip='192.168.0.0'
# interface_domain='pebcak.ca'
# interface_nameservers='192.168.0.1,www.pebcak.ca'

# variables to set to your needs.
chroot_dir='/chroot'
packages='syslog-ng xinetd tftp-hpa dhcp nfs-utils ltsp'
emerge_command='emerge -va  --usepkg --buildpkg --oneshot'

# urls for extra features.
# todo allow user to opt not to install the memtest and/or 
#      freedos extras by not setting the following variables
# todo memtest_url='portage' to allow grabbing memtest from portage
# todo add optional code to add memtest to servers boot options
memtest_url='http://www.memtest.org/download/1.55.1/memtest86+-1.55.1.bin.gz'
freedos_url='http://www.fdos.org/ripcord/beta9sr1/disksets/ODIN/fdodin91.img'

# Syslog-ng configuration
syslog_seed_config='/usr/portage/app-admin/syslog-ng/files/syslog-ng.conf.gentoo'
syslog_net_source='source net { udp(); };'
syslog_net_destination='destination netlog { file("/var/log/ltsp.messages"); };'
syslog_net_log='log { source(net); destination(netlog); };'

# tftp variables:
tftp_chroot="$chroot_dir/tftpboot"
tftp_user='tftp'
#tftp_args="-u $tftp_user -s $tftp_chroot"     # Normal
tftp_args="-vvvvv -u $tftp_user -s $tftp_chroot"   # Super verbose
#tftp_args="-vvvvv -u $tftp_user -s $tftp_chroot -r blksize"  # fix for some Intel stacks.

# dhcp variables:
dhcp_opts='-q'
dhcp_chroot="$chroot_dir/dhcp"
dhcp_lease_default=1592000
dhcp_lease_max=1592000
dhcp_default_range='192.168.0.144 192.168.0.169' # todo find a way to set this if interface_detect='auto'

# ltsp variables
# todo: add code to create an /opt/ltsp symlink to allow for quick version changes.
ltsp_version=`qpkg -I -v -nc ltsp | awk -F - '{print $3}'`

# If interface_detect is auto configure based on ifconfig, route, dnsdomainname output and /etc/resolv.conf
# Todo: add code to verify detected settings with user prior to continuing.
if [ $interface_detect ] && [ $interface_detect =  'auto' ] ; then
    # Grab the ip, broadcast and netmask from the output of ifconfig <interface>
    interface_ifconfig=`ifconfig $interface`
    interface_ip=`echo "$interface_ifconfig" | awk '/Bcast/ { x=substr($2, 6) } END { print x }'`
    interface_broadcast=`echo "$interface_ifconfig" | awk '/Bcast/ { x=substr($3, 7) } END { print x }'`
    interface_netmask=`echo "$interface_ifconfig" | awk '/Bcast/ { x=substr($4, 6) } END { print x }'`

    # Grab the network ip and gateway from the output of route -n
    interface_route=`route -n`
    interface_gateway=`echo "$interface_route" | awk '/UG/ && /'$interface'/ { print $2 }'`
    interface_network_ip=`echo "$interface_route" | awk '! /UG/ && /'$interface'/ { print $1 }'`

    # Grab the domainname and nameservers
    interface_domain=`dnsdomainname`
    interface_nameservers=`awk '/nameserver/ {num_ns++; if(num_ns == 1) {ns=$2} else {ns=sprintf("%s,%s",ns,$2)}} END {print ns}' /etc/resolv.conf`
fi

# Display a nice green asterisk followed by $1
function display_info () {
    echo -e "\n \033[32;01m*\033[0m" "$1"
}

# Get the last line number starting with $1 in file $2
function get_last_occur () {
   awk 'BEGIN{x=0}{if($1 == "'$1'") x = NR}END{print x}' $2
}

# Insert line $1 after line $2 in file $3
function insert_line_after () {
   echo "Inserting \"$1\" into $3 after line $2"
   newline=`echo -E $1 | awk '{ gsub(/"/, "\\\\\""); print }'`
   newconfig=`awk '{if(NR=='$2'){print $0; print "'"$newline"'"} else print $0 }' $3`
   echo "$newconfig" > $3
}

# Swap line $1 with $2 in file $3
function swap_line () {
   echo "swapping $1 with \"$2\" in file $3"
   cat $3 | awk '{if(NR=='$1'){print "'"$2"'"} else print $0 }' > $3
}

# stop services to be installed if currently running
for x in syslog-ng portmap nfs dhcp xinetd; do /etc/init.d/$x stop; done;

# Install the necessary packages
display_info "Installing $packages"
echo 'net-misc/ltsp snmp -nas esd audiofile' >> /etc/portage/package.use
$emerge_command $packages

# Copy seed syslog-ng.conf to /etc/syslog-ng/syslog-ng.conf
display_info "Creating /etc/syslog/syslog-ng.conf using $syslog_seed_config as a base."
cp -v $syslog_seed_config /etc/syslog-ng/syslog-ng.conf

# Check if syslog is configured to accept udp connections.
# If the system logger is already configured to accept udp connections
# assume the user has already configured syslog-ng appropriately for network logging.
target=`awk 'BEGIN{x=0}/udp()/{if($1 == "source") x = NR}END{print x}' /etc/syslog-ng/syslog-ng.conf`
if [ $target -eq 0 ]; then
   echo "Syslog-ng not configured for network logging"
   target=`get_last_occur source /etc/syslog-ng/syslog-ng.conf`
   insert_line_after "$syslog_net_source" $target /etc/syslog-ng/syslog-ng.conf
   target=`get_last_occur destination /etc/syslog-ng/syslog-ng.conf`
   insert_line_after "$syslog_net_destination" $target /etc/syslog-ng/syslog-ng.conf
   target=`get_last_occur log /etc/syslog-ng/syslog-ng.conf`
   insert_line_after "$syslog_net_log" $target /etc/syslog-ng/syslog-ng.conf
else
   echo "Syslog-ng seems to configured to accept udp connections"
fi

# Create log directories and files using /var/log entries in syslog-ng
syslog_files=`awk -F \" '/\/var\/log/ && !/# / && !/tty/ {print $2}' /etc/syslog-ng/syslog-ng.conf`
syslog_dirs=`for x in $syslog_files; do dirname $x; done | sort | uniq`
display_info "Creating the syslog-ng directories and files"
for x in $syslog_dirs; do mkdir -p --verbose $x; done
echo $syslog_files
touch $syslog_files

# create /etc/exports and ltsp swap directory
# todo: actually put /var/opt/ltsp/swapfiles to use
display_info "Creating default /etc/exports and ltsp swap directory"
cat <<- EOF > /etc/exports
/opt/ltsp-$ltsp_version/i386         $interface_network_ip/$interface_netmask(ro,no_root_squash,async)
/var/opt/ltsp/swapfiles    $interface_network_ip/$interface_netmask(rw,no_root_squash,async)
EOF
cat /etc/exports
mkdir -p --verbose /var/opt/ltsp/swapfiles

# create default /etc/xinetd.d/tftp 
display_info "Creating default /etc/xinetd.d/tftp file."
cat <<- EOF > /etc/xinetd.d/tftp
service tftp
{
    disable = no
    socket_type = dgram
    protocol = udp
    wait = yes
    user = root
    group = $tftp_user
    server = `which in.tftpd`
    server_args = $tftp_args
}
EOF
cat /etc/xinetd.d/tftp

# setup xinetd
# todo: look at locking things down more.
display_info "Configuring xinetd."
cat <<- EOF > /etc/xinetd.conf
defaults
{
    instances      = 60
    log_type       = SYSLOG authpriv info
    log_on_success = HOST PID
    log_on_failure = HOST
    cps            = 25 30
}
includedir /etc/xinetd.d
EOF
cat /etc/xinetd.conf

# create chroot directory
rm -rf $chroot_dir
mkdir -p --verbose $chroot_dir

# Move /tftpboot to tftp chroot
display_info "Moving /tftpboot to $chroot_dir directory"
mv -v /tftpboot $chroot_dir
mv -v $chroot_dir/tftpboot/pxelinux.cfg $chroot_dir/tftpboot/pxe

# The pxelinux included with ltsp is lacking some nice extras like
# menu.c32, memdisk and chain.c32 emerging syslinux temporarily will resolve this
display_info "Emerging syslinux and copying pxelinux bootloader and related files to tftp chroot."
$emerge_command syslinux

cp -v /usr/lib/syslinux/pxelinux.0 $tftp_chroot/pxe
cp -v /usr/lib/syslinux/{memdisk,menu.c32,chain.c32} $tftp_chroot/pxe
 
display_info "Removing syslinux as required files have been obtained"
emerge -Ca syslinux

# might as well grab memtest as a boot option..
# todo: make this optional
# todo: add optional code to grab this from portage and include it in the servers bootloader options
display_info "Grabbing memtest+ "
wget -O memtest86+.gz $memtest_url
gunzip memtest86+.gz
mv -v memtest86+ $tftp_chroot/pxe/memtest86+

# I'll grab a freedos odin floppy image as a boot option.
# todo: make this optional
# todo: add optional code to add the contents of a directory to the floppy image
display_info "Grabbing freedos "
wget -O freedos $freedos_url
mv -v freedos $tftp_chroot/pxe/freedos

# create the default pxelinux config file
# todo: add code to only add freedos and memtest if user wants.
display_info "Creating $tftp_chroot/pxe/pxelinux.cfg/default"
cat  <<- EOF > $tftp_chroot/pxe/pxelinux.cfg/default
default menu.c32
prompt 0
timeout 100
ontimeout harddrive

menu title Choose a boot option....
label ltsp
menu label ^ltsp
kernel `basename $tftp_chroot/pxe/bzImage-*`
append init=/linuxrc rw root=/dev/ram0 initrd=`basename $tftp_chroot/pxe/initrd-*`

label floppy
menu label ^floppy
kernel chain.c32
append fd0

label harddrive
menu label ^harddrive
kernel chain.c32
append hd0

label memtest
menu label ^memtest
kernel memtest86+

label freedos
menu label free^dos
kernel memdisk
append initrd=freedos
EOF
cat $tftp_chroot/pxe/pxelinux.cfg/default

# create tftp group and user account.
display_info "Creating $tftp_user group and user."
groupadd $tftp_user
useradd -d $tftp_chroot -s /bin/false -G $tftp_user -g $tftp_user $tftp_user

# change ownership of tftp chroot and files.
display_info "Changing ownership of $tftp_chroot to $tftp_user:$tftp_user."
chown -R $tftp_user:$tftp_user $tftp_chroot

# configure dhcp chroot
display_info "Configuring dhcp chroot: $dhcp_chroot"
dhcp_version=`qpkg -I -v -nc dhcp | awk '/dhcp-/ {print substr($0,10)}'`
ebuild /var/db/pkg/net-misc/$dhcp_version/$dhcp_version.ebuild config
touch $dhcp_chroot/var/lib/dhcp/dhcpd.leases
ln -s /dev/log $dhcp_chroot/dev/log

# change ownership of dhcp chroot
display_info "Changing ownership of $dhcp_chroot to dhcp:dhcp."
chown -R dhcp:dhcp $dhcp_chroot

# configure dhcp
display_info "Creating default $dhcp_chroot/etc/conf.d/dhcp file."
cat <<- EOF >  /etc/conf.d/dhcp
IFACE="$interface"
DHCPD_OPTS="$dhcp_opts"
CHROOT="$dhcp_chroot"
export LD_PRELOAD="/usr/lib/libresolv.so /usr/lib/libnss_dns.so"
EOF
cat /etc/conf.d/dhcp

# create dhcpd.conf
display_info  "Creating $dhcp_chroot/etc/dhcp/dhcpd.conf"
cat <<- EOF > $dhcp_chroot/etc/dhcp/dhcpd.conf
ddns-update-style none;
authoritative;

option pxelinuxmagic code 208 = string;
option pxelinuxpathprefix code 210 = text;
option pxelinuxreboottime code 211 = unsigned integer 32;

use-host-decl-names on;

group "network-boot"{
    class "PXE" {
        match if substring(option vendor-class-identifier, 0, 9) = "PXEClient";
    }
    class "Etherboot" {
        match if substring (option vendor-class-identifier, 0, 9) = "Etherboot";
    }
    if exists dhcp-parameter-request-list {
        option dhcp-parameter-request-list = concat(option dhcp-parameter-request-list,d0,d2,d3);
    }
    option pxelinuxmagic f1:00:74:7e;
    option pxelinuxpathprefix         "/pxe/";
    option pxelinuxreboottime          30;
    filename "/pxe/pxelinux.0";
}

shared-network "local" {
    subnet $interface_network_ip netmask $interface_netmask {
        default-lease-time              $dhcp_lease_default;
        max-lease-time                  $dhcp_lease_max;
        option subnet-mask              $interface_netmask;
        option broadcast-address        $interface_broadcast;
        option routers                  $interface_gateway;
        option domain-name-servers      $interface_nameservers;
        option domain-name              "$interface_domain";
        option root-path                "$interface_ip:/opt/ltsp-$ltsp_version/i386";
        range                           $dhcp_default_range;
    }
}
EOF
cat $dhcp_chroot/etc/dhcp/dhcpd.conf

# Necessary because of Gentoo bug 39809 :(
if ! [ -e /opt/ltsp-$ltsp_version/i386/dev ]; then
    display_info  "Gentoo bug 39809 detected creating necessary dirs to compensate"
    mkdir --verbose /opt/ltsp-$ltsp_version/i386/{dev,oldroot,proc}
fi

# We need a basic lts.conf.
cat <<- EOF > /opt/ltsp-$ltsp_version/i386/etc/lts.conf
[DEFAULT]
    SERVER          = $interface_ip
    RUNLEVEL        = 3 
    SCREEN_01        = "shell"
EOF

# Add services to default runlevel and start.
for x in syslog-ng nfs dhcp xinetd; do rc-update add $x default; /etc/init.d/$x start; done;
toggleopenShow attachmentstogglecloseHide attachments
Topic attachments
I Attachment Action Size Date Who Comment
shsh ltsp-install.sh manage 12.9 K 07 Jul 2005 - 03:59 CoryOldford Read before using!!!!
Edit | Attach | Printable | Raw View | Backlinks: Web, All Webs | History: r1 | More topic actions
 
Powered by TWiki
This site is powered by the TWiki collaboration platformCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback