UbuntuJauntyInstallationHowTo
Introduction
Goal: Using FAI to install ubuntu 9.04 'Jaunty Jackalope' (heck, any other distribution). I'm assuming that you want to run FAI server on an ubuntu 9.04 server, however, the procedures are very similiar if you want to use debian on the server side.
Since I know how frustrating it can be for a novice user to try to understand the many bits and pieces of this powerful technology, the intention of this howto is to get you quickly to a working basic FAI configuration on which you can build up your knowledge. It is intentionally very verbose, describing and explaining *every* step necessary to reach this goal. So don't be put off by the length of this howto; you should be up&running fairly quickly.
Feel free to edit this article as you see fit, after all, it's a wiki!
Credits go, among many others, to Henning Glawe, Richard Grant and Henning Sprang, who helped me figuring out my way to this solution. Thanks for your friendly support!
Note: Before we dive into the subject, please note that due to a current lack of physical machines, all my testing was done in a VirtualBox environment, with both the ubuntu server and the target client in a vm on the same host. The steps described here should work no matter what, but please keep these special circumstances in mind should something not work as expected.
Disclaimer: You use this howto on your own risk! I don't and can't take any responsibility in case your whole IT blows up!
Now, I'll walk you step-by-step to setting up a complete FAI infrastructure from ground up. This means, some of the steps may already be implemented in your network, such as a DHCP server, but you may still want to check your existing configuration to see if it corresponds to the config described here.
Assumptions
I assume that you are building a separate testing environment to follow the procedures below. That's not a bad idea for the first time anyway, and a very good way to do this is installing both the ubuntu server as well as the target clients in a VirtualBox (or any other VM) environment.
VirtualBox config
Edit the VirtualBox virtual machine settings as follows:
- ubuntu server
- At least 5 GB of disk space
- NIC 1 (aka eth0): Connected to: Bridged mode, Name: [name of your physical network adapter, e.g. 'eth0' or 'wlan0']
- NIC 2 (aka eth1): Connected to: Internal network, Name: intnet
- ubuntu client
- NIC 1 (aka eth0): Connected to: Internal network, Name: intnet, MAC: 112233445566
Then you'll have a separate network for your FAI testing:
- ubuntu server will have the IP 192.168.0.1 and act as a router to the outside world (i.e. the rest of the network).
- the ubuntu example client we are going to install will have the IP 192.168.0.10.
- All other clients will be assigned an IP from the range 192.168.0.20 - 192.168.0.30.
VMware config
If you use VMware Workstation, use the following configuration (thanks to Bashar Ewaida for providing this!):
- ubuntu server
- At least 8 GB of disk space
- NIC 1 (aka eth0): Connected to: Bridged
- NIC 2 (aka eth1): Connected to: Custom: Specific virtual network: VMnet1 (Host-only)
- ubuntu client
- NIC 1 (aka eth0): Connected to: Custom: Specific virtual network: VMnet1 (Host-only)
- Disable host DHCP for vmnet1 host-only network.
Bashar also added:
"The configurations are close to what you have, however the very important thing here is disabling VMware DHCP service/daemon for host-only network (in the example below vmnet1), otherwise the fai clients will use the host as their DHCP server and FAI installation will fail at the nfsroot step."
ubuntu Server installation
First things first. Remember, this is a ground-up tutorial, so let's make sure we use the same environment.
Enter the ubuntu install CD into the ubuntu server and start the install. During install, answer the question as follows (in this tutorial I'll assume a german setup. Why? Because I want to point out how to get the german keyboard layout working on the client console, which is a bit tricky. The same principles apply for any language other than en_US. If you want to use the default en_US setup, just don't use the LANG_GERMAN class and you're on your way).
- Choose Language
- Wählen Sie ein Land oder Gebiet: Deutschland
- ubuntu-Installer-Hauptmenü
- Tastaturmodell erkennen: Nein
- Herkunft der Tastatur: Germany
- Tastenbelegung: Germany
- Netzwerk einrichten
- Primäre Netzwerk-Schnittstelle: eth0
- Rechnername: vm-ubuntuserver
- Festplatten partitionieren
- Partitionsmethode: Geführt - gesamte Platte verwenden und LVM einrichten
- Wählen Sie die zu partitionierende Festplatte: SCSI2 (0,0,0) (sda)
- Änderungen auf die Speichergeräte schreiben und LVM einrichten: Ja
- Amount of volume group to use for guided partitioning: 4.0 GB
- Änderungen auf die Festplatten schreiben: Ja
- Benutzer und Passwörter einrichten
- Voller Name des neuen Benutzers: John Doe
- Benutzername für Ihr Konto: john
- Wählen Sie ein Passwort für den neuen Benutzer: [Enter password]
- Ihren persönlichen Ordner verschlüsseln: Nein
- Den Paketmanager konfigurieren
- HTTP-Proxy-Daten:
- Software auswählen und installieren
- Wie möchten Sie Aktualisierungen auf diesem System verwalten: Keine automatischen Aktualisierungen
- Softwareauswahl
- Welche Software soll installiert werden:
- [ ] DNS server
- [ ] LAMP server
- [ ] Mail server
- [*] OpenSSH server
- [ ] PostgreSQL database
- [ ] Print server
- [ ] Samba file server
- [ ] Tomcat Java server
- [ ] Virtual Machine host
- [ ] Manual package selection
- Welche Software soll installiert werden:
Now reboot the machine.
Configure your ubuntu server
Log in with your username and change to user root:
sudo su
Configuring the network
I assume the ubuntu server has two NICs, eth0 with contact to the outside world, and eth1 with contact to the internal network. Edit the following file:
vi /etc/network/interfaces
and replace the content with the following lines:
# The loopback network interface auto lo iface lo inet loopback # The primary network interface # The external network auto eth0 iface eth0 inet static address 192.168.178.2 netmask 255.255.255.0 broadcast 192.168.178.255 network 192.168.178.0 gateway 192.168.178.1 # The internal network auto eth1 iface eth1 inet static address 192.168.0.1 netmask 255.255.255.0 broadcast 192.168.0.255 network 192.168.0.0
Restart the server. If you use ubuntu server in a VM, it may be practical to create a snapshot now. Once restarted, log in with your username and change to user root as before:
sudo su
Install apt-proxy
You'll need quite a few packages for your server and clients. Let's be clever and use a proxy which caches the packages for you so they don't have to be downloaded from the internet each time, thus speeding up the process to a great extend.
Install apt-proxy:
apt-get -y install apt-proxy
Open the following file:
vi /etc/apt-proxy/apt-proxy-v2.conf
and replace the line:
;dynamic_backends = on
with the following line:
dynamic_backends = on
Restart apt-proxy:
/etc/init.d/apt-proxy restart
Change your sources.list, so it uses the apt-proxy you've installed earlier:
vi /etc/apt/sources.list
and replace the content with the following lines (where 192.168.0.1 is the IP of your apt-proxy):
## Main Repositories deb http://192.168.0.1:9999/de.archive.ubuntu.com/ubuntu/ jaunty main restricted deb-src http://192.168.0.1:9999/de.archive.ubuntu.com/ubuntu/ jaunty main restricted ## Major bug fix updates produced after the final release of the ## distribution. deb http://192.168.0.1:9999/de.archive.ubuntu.com/ubuntu/ jaunty-updates main restricted deb-src http://192.168.0.1:9999/de.archive.ubuntu.com/ubuntu/ jaunty-updates main restricted ## Universe Repositories deb http://192.168.0.1:9999/de.archive.ubuntu.com/ubuntu/ jaunty universe deb-src http://192.168.0.1:9999/de.archive.ubuntu.com/ubuntu/ jaunty universe deb http://192.168.0.1:9999/de.archive.ubuntu.com/ubuntu/ jaunty-updates universe deb-src http://192.168.0.1:9999/de.archive.ubuntu.com/ubuntu/ jaunty-updates universe ## Multiverse Repositories deb http://192.168.0.1:9999/de.archive.ubuntu.com/ubuntu/ jaunty multiverse deb-src http://192.168.0.1:9999/de.archive.ubuntu.com/ubuntu/ jaunty multiverse deb http://192.168.0.1:9999/de.archive.ubuntu.com/ubuntu/ jaunty-updates multiverse deb-src http://192.168.0.1:9999/de.archive.ubuntu.com/ubuntu/ jaunty-updates multiverse ## Security Updates deb http://192.168.0.1:9999/security.ubuntu.com/ubuntu jaunty-security main restricted deb-src http://192.168.0.1:9999/security.ubuntu.com/ubuntu jaunty-security main restricted deb http://192.168.0.1:9999/security.ubuntu.com/ubuntu jaunty-security universe deb-src http://192.168.0.1:9999/security.ubuntu.com/ubuntu jaunty-security universe deb http://192.168.0.1:9999/security.ubuntu.com/ubuntu jaunty-security multiverse deb-src http://192.168.0.1:9999/security.ubuntu.com/ubuntu jaunty-security multiverse # FAI Repository deb http://192.168.0.1:9999/www.informatik.uni-koeln.de/fai/download lenny koeln
Import the GPG-key of the FAI repository:
apt-key adv --recv-keys --keyserver keyserver.ubuntu.com AB9B66FD
Update the sources and install any security fixes that might be out there:
apt-get update && apt-get -y upgrade
Installing and configuring DHCP
Now it's time to install a DHCP server:
apt-get -y install dhcp3-server
The DHCP server should only listen to the internal network interface in order to not interfere with the external's network DHCP server (e.g. your internet router). To accomplish this, open the following file:
vi /etc/default/dhcp3-server
and replace the content with the following line:
INTERFACES="eth1"
Configure your new DHCP server:
vi /etc/dhcp3/dhcpd.conf
and replace the content with the following lines:
# Do not attempt tu do a DNS update when a lease is confirmed ddns-update-style none; # DNS server option domain-name-servers 192.168.0.1; # Other global options default-lease-time 42300; max-lease-time 84600; # This DHCP server is the official DHCP server for # the local network authoritative; # Send DHCP log messages to a different log file log-facility local7; # Declare the subnets subnet 192.168.0.0 netmask 255.255.255.0 { # The Domain name option domain-name "domainname.local"; # The DHCP range range 192.168.0.20 192.168.0.30; # Subnet mask option subnet-mask 255.255.255.0; # The Gateway (i.e. internet router) option routers 192.168.0.1; # Broadcast address option broadcast-address 192.168.0.255; # NTP server option ntp-servers 192.168.0.1; # TFTP-Server for PXE-Boot next-server 192.168.0.1; filename "pxelinux.0"; # Set the hostnames globally use-host-decl-names on; # Assign this client a specific IP host vm-ubuntu904 { # Define the MAC-Address of the client hardware ethernet 11:22:33:44:55:66; # Assign the static IP fixed-address 192.168.0.10; } }
The lines next-server 192.168.0.1; and filename "pxelinux.0"; point to your FAI-Server which will get the IP 192.168.0.1. The option use-host-decl-names on; specifies that the host vm-ubuntu904 statement sets the hostname for your clients. Setting the correct hostnames is very important in your FAI environment, because the classes depend on the hostname!
Restart the DHCP daemon:
/etc/init.d/dhcp3-server restart
Installing DNS
In order for your clients to use DNS (e.g. resolving google.com), you need to install a DNS server:
apt-get -y install bind9
Activate routing (optional)
If you install the ubuntu server on your existing network (with both the FAI server and the target clients on the same subnet as the rest of the network), you can safely skip this step.
However, if you want to have a safe testing environment with the ubuntu server and FAI in a separate subnet (say, running them in virtual machines), you'll need to activate routing on the ubuntu server, because all network connections from your testing network will go over the ubuntu server.
Activating IP-Forwarding:
sysctl -w net.ipv4.ip_forward=1
Activating IP-Masquerading:
apt-get -y install ipmasq
Restart IPmasq:
/etc/init.d/ipmasq restart
Installing and configuring a TFTP server
For PXE boot you'll need a TFTP server.
apt-get -y install tftpd-hpa
To teach the TFTP server to start as a daemon, edit the following file:
vi /etc/default/tftpd-hpa
and replace the content with the following lines:
# Defaults for tftpd-hpa RUN_DAEMON="yes" OPTIONS="-l -s /srv/tftp/fai"
Then, edit this file:
vi /etc/inetd.conf
and comment out the following line (=put a hash sign # in front of the line):
tftp dgram udp wait root /usr/sbin/in.tftpd /usr/sbin/in.tftpd -s /var/lib/tftpboot
Restart the TFTP-server:
/etc/init.d/tftpd-hpa restart
Setting up FAI
Congratulations, if you've made it this far, all the boring basic task are mastered. Let's get on with the really exciting stuff, that is, installing and configuring FAI!
Install FAI:
apt-get -y install fai-server fai-doc syslinux
Open the FAI config file:
vi /etc/fai/fai.conf
and replace the content with the following lines:
# an account on the install server which saves all log-files # and which can change the kernel that is booted via network. LOGUSER=fai # set protocol type for saving logs. Values: ssh, rsh, ftp FAI_LOGPROTO=ssh # the install server SERVER=192.168.0.1 # the configuration space on the install server FAI_CONFIGDIR=/srv/fai/config # access the config space on the specified install server # using NFS FAI_CONFIG_SRC=nfs://192.168.0.1$FAI_CONFIGDIR # mount point where the mirror will be mounted MNTPOINT=/media/mirror # the local configuration directory on the install client FAI=/var/lib/fai/config
Open the nfsroot config file:
vi /etc/fai/make-fai-nfsroot.conf
and replace the content with the following lines:
# the directory on the install server which contains # the nfsroot NFSROOT=/srv/fai/nfsroot # TFTP root directory TFTPROOT=/srv/tftp/fai # Where to get the packages needed to build the # nfsroot FAI_DEBOOTSTRAP="lenny http://ftp.debian.org/debian" # the encrypted (with md5 or crypt) root password on all install clients during # installation process; used when log in via ssh; default pw is: fai FAI_ROOTPW='$1$kBnWcO.E$djxB128U7dMkrltJHPf6d1' # following lines should be read only for most of you FAI_DEBOOTSTRAP_OPTS="--exclude=dhcp-client,info"
We purposely create a Debian NFSroot here, so it is important to leave the line FAI_DEBOOTSTRAP as in the example above!
If you look careful enough, you'll note that I didn't use our apt-proxy for the FAI_DEBOOTSTRAP option. This is because I had problems building the nfsroot if an apt-proxy was specified. Not using the apt-proxy here won't hurt much anyway, because the nfsroot has to be built only once - no matter how many distributions you are going to install afterwards.
Correct the owner settings of the directory /var/log/fai (the logs will be written to this directory):
chown -R fai /var/log/fai
It's time to run fai-setup for the first (and hopefully the only) time. Get yourself a nice cup of coffee and relax, as this will take a while (for troubleshooting purposes run fai-setup -v
to get a verbose output):
fai-setup
After this is finished, make sure you see both the following messages in the log:
make-fai-nfsroot finished properly. FAI setup finished.
Also, check the log for any other suspicious messages.
fai-setup was so friendly to setup our NFS exports for us. However, you might want to double-check if the exports are correct for your network implementation. Example given, in our environment we have to change the exports to fit our network structure. Open the following file:
vi /etc/exports
uncomment the following lines:
/srv/fai/config 192.168.178.2/255.255.255.0(async,ro,no_subtree_check) /srv/fai/nfsroot 192.168.178.2/255.255.255.0(async,ro,no_subtree_check,no_root_squash)
and add the following lines below:
# NFS3 exports for FAI and PXE boot /srv/fai/config 192.168.0.0/24(ro,nohide,insecure,no_subtree_check,async) /srv/fai/nfsroot 192.168.0.0/24(ro,nohide,insecure,no_subtree_check,async,no_root_squash)
Re-read the exports file:
exportfs -rv
Building your configspace
As already mentioned, this howto tries to accomplish three things:
- Getting FAI up&running fairly quickly
- Being client distribution agnostic (in this specific case, installing ubuntu 9.04 on the clients; in more general terms, installing any other distribution on the clients - keyword multi-distribution)
- Using german keyboard layout on the client's console
You can of course adapt the settings to your specific setup, which I encourage you to do anyway. There's no better learning than hands-on experience!
Creating the directory structure
The first, and most important step is to configure your configspace. Prepare your configspace by creating the following directories in /srv/fai/config/ (I can post a tar.gz file with all the files as described below if someone offers a serious, permanent public hosting for this file):
cd /srv/fai/config/ mkdir basefiles && mkdir class && mkdir debconf && mkdir disk_config && mkdir -p files/etc/apt/secring.gpg && mkdir files/etc/apt/sources.list && mkdir files/etc/apt/trustdb.gpg && mkdir files/etc/apt/trusted.gpg && mkdir -p files/etc/default/console-setup && mkdir files/etc/default/locale && mkdir -p files/etc/network/interfaces && mkdir hooks && mkdir package_config && mkdir -p scripts/BC_BASE && mkdir scripts/GRUB && mkdir scripts/LAST
This will give you the following directory strucure:
|-- basefiles |-- class |-- debconf |-- disk_config |-- files | `-- etc | |-- apt | | |-- secring.gpg | | |-- sources.list | | |-- trustdb.gpg | | `-- trusted.gpg | |-- default | | |-- console-setup | | `-- locale | `-- network | `-- interfaces |-- hooks |-- package_config `-- scripts |-- BC_BASE |-- GRUB `-- LAST
Creating files in the configspace
We have the directory structure set up, let's fill it with life!
The basefiles directory:
- We'll leave this empty for now; later the base.tar.gz file of each client distribution is copied in here
The class directory:
vi class/10-base-classes
Paste the following lines:
#! /bin/bash # Echo architecture and OS name in uppercase. Do NOT remove these two lines. uname -s | tr '[:lower:]' '[:upper:]' [ -x "`which dpkg`" ] && dpkg --print-installation-architecture | tr a-z A-Z [ -f /etc/RUNNING_FROM_FAICD ] && echo "FAICD" exit 0
vi class/20-hwdetect.source
Paste the following lines:
#! /bin/bash # (c) Thomas Lange, 2002-2008, lange@informatik.uni-koeln.de # NOTE: Files named *.source will be evaluated, but their output ignored. Instead # the contents of $newclasses will be added to the list of defined classes. [ "$action" = "dirinstall" ] && return 0 # Do not execute when doing dirinstall echo 0 > /proc/sys/kernel/printk # load all IDE drivers # DMA does not work if we load all modules in drivers/ide, so only try pci modules mod=$(find /lib/modules/$(uname -r)/kernel/drivers/ide/pci -type f | sed 's/\.o$//' | sed 's/\.ko$//' | sed 's/.*\///') for i in $mod; do modprobe $i 1>/dev/null 2>&1 done # Booting from CD does not always enable DMA. for d in $( echo /proc/ide/hd[a-z] 2>/dev/null); do [ -d $d ] && echo "using_dma:1" > $d/settings done # load additional kernel modules (from old 11modules.source) # this order should also enable DMA for all IDE drives kernelmodules="usbkbd ide-disk ide-cd" case $(uname -r) in 2.6*) kernelmodules="$kernelmodules ohci-hcd usbhid usbmouse ide-generic mptspi ata_piix dm-mod md-mod aes dm-crypt" ;; esac for mod in $kernelmodules; do [ "$verbose" ] && echo loading kernel module $mod modprobe -a $mod 1>/dev/null 2>&1 done # let discover do most of the job #[ -x /sbin/discover-modprobe ] && /sbin/discover-modprobe # now we can mount the USB filesystem mount -t usbfs usbfs /proc/bus/usb modprobe -a sd_mod sr_mod echo $printk > /proc/sys/kernel/printk set_disk_info # calculate number of available disks save_dmesg # save new boot messages (from loading modules)
vi class/50-host-classes
Paste the following lines:
#! /bin/bash # assign classes hosts # use a list of classes for our demo machine case $HOSTNAME in vm-ubuntu904) echo "BC_BASE HDD_SINGLE NW_DHCP LANG_GERMAN OS_UBUNTU_904_X32" ;; *) echo "BC_BASE HDD_SINGLE NW_DHCP LANG_GERMAN OS_UBUNTU_904_X32" ;; esac (ifclass I386 || ifclass AMD64) && echo GRUB exit 0
vi class/BC_BASE.var
Paste the following lines:
# Base class which is shared among clients (which includes servers) # may be overridden with custom *.var files # allow installation of packages from unsigned repositories FAI_ALLOW_UNSIGNED=1 KEYMAP=de-latin1-nodeadkeys # set UTC=yes if your system clock is set to UTC (GMT), and UTC=no if not. UTC=yes TIMEZONE=Europe/Berlin # root password for the new installed linux system; md5 and crypt are possible # pw is "fai" ROOTPW='$1$kBnWcO.E$djxB128U7dMkrltJHPf6d1' # MODULESLIST contains modules that will be loaded by the new system, # not during installation these modules will be written to /etc/modules # If you need a module during installation, add it to $kernelmodules # in 20-hwdetect.source. But discover should do most of this job MODULESLIST="usbkbd ehci-hcd ohci-hcd uhci-hcd usbhid psmouse" # erros in tasks greater than this value will cause the installation to stop STOP_ON_ERROR=700 LOGSERVER=$SERVER LOGPASSWD='$1$kBnWcO.E$djxB128U7dMkrltJHPf6d1' # use the new partitioning tool USE_SETUP_STORAGE=1 # limit the number of packages install added to apt-get or aptitude #MAXPACKAGES= # if fai is usded to do softupdates, any local changes on the # install clients are lost. However, fai makes backup copies of # locally changed files; by default, they are written to the same # directory as the original file, with .pre_fcopy appended. # If you wish to save them together with the logfiles, this will # do the job: #FAI_BACKUPDIR=$LOGDIR/backup # if log files are saved via FTP on the server, this specifies the # path to save logfiles to. Not needed if $FAI_LOGPROTO in file # fai.conf is set to 'ssh'. #LOGREMOTEDIR= #CONSOLEFONT= #liloappend=
The debconf directory:
vi debconf/LANG_GERMAN
Paste the following lines:
locales locales/default_environment_locale select de_DE.UTF-8 locales locales/locales_to_be_generated multiselect de_DE.UTF-8 UTF-8 xserver-xorg xserver-xorg/config/inputdevice/keyboard/layout string de xserver-xorg xserver-xorg/config/inputdevice/keyboard/model string pc105 xserver-xorg xserver-xorg/config/inputdevice/keyboard/options string lv3:ralt_switch xserver-xorg xserver-xorg/autodetect_monitor boolean false xserver-xorg xserver-xorg/autodetect_keyboard boolean true xserver-xorg xserver-xorg/autodetect_mouse boolean true xserver-xorg xserver-xorg/autodetect_video_card boolean true console-setup console-setup/variant select Germany console-setup console-setup/charmap select UTF-8 console-setup console-setup/layoutcode string de console-setup console-setup/compose select No compose key console-setup console-setup/fontsize-text select 16 console-setup console-setup/optionscode string lv3:ralt_switch console-setup console-setup/layout select Germany console-setup console-setup/detected note console-setup console-setup/variantcode string console-setup console-setup/codesetcode string Lat15 console-setup console-setup/modelcode string pc105 console-setup console-setup/ask_detect boolean false console-setup console-setup/altgr select Right Alt console-setup console-setup/ttys string /dev/tty[1-6] console-setup console-setup/model select Generic 105-key (Intl) PC console-setup console-setup/fontsize-fb select 16 console-setup console-setup/switch select No temporary switch console-setup console-setup/codeset select # Latin1 and Latin5 - western Europe and Turkic languages console-setup console-setup/toggle select No toggling console-setup console-setup/fontface select VGA console-setup console-setup/fontsize string 16
The disk_config directory:
vi disk_config/HDD_SINGLE
Paste the following lines:
# Standard client formatting using setup-storage # # <type> <mountpoint> <size> <fs type> <mount options> <misc options> disk_config disk1 disklabel:msdos primary / 4G ext3 rw,relatime,errors=remount-ro primary - 1G swap sw
The files directory:
- files/etc/apt/*: You have to copy the files from the /etc/apt/-directory from an existing reference client with the desired distribution version to this directory. Let's say, you want to use this FAI configuration to install ubuntu 9.04 on the client. Then you boot to a reference client (a live CD will suffice) and copy the following files from the reference client to this directory:
- secring.gpg
- sources.list
- trustdb.gpg
- trusted.gpg
- Don't forget to rename the files accordingly. E.g. secring.gpg will be files/etc/apt/secring.gpg/OS_UBUNTU_904_X32!
However, you might want to edit the apt/sources.list (vi files/etc/apt/sources.list/OS_UBUNTU_904_X32
) so it points to your apt-proxy. If you've followed the steps above, you will be already familiar with that. In the case of ubuntu 9.04 you paste the following lines:
deb http://192.168.0.1:9999/de.archive.ubuntu.com/ubuntu/ jaunty main restricted deb-src http://192.168.0.1:9999/de.archive.ubuntu.com/ubuntu/ jaunty main restricted deb http://192.168.0.1:9999/de.archive.ubuntu.com/ubuntu/ jaunty-updates main restricted deb-src http://192.168.0.1:9999/de.archive.ubuntu.com/ubuntu/ jaunty-updates main restricted deb http://192.168.0.1:9999/de.archive.ubuntu.com/ubuntu/ jaunty universe deb-src http://192.168.0.1:9999/de.archive.ubuntu.com/ubuntu/ jaunty universe deb http://192.168.0.1:9999/de.archive.ubuntu.com/ubuntu/ jaunty-updates universe deb-src http://192.168.0.1:9999/de.archive.ubuntu.com/ubuntu/ jaunty-updates universe deb http://192.168.0.1:9999/de.archive.ubuntu.com/ubuntu/ jaunty multiverse deb-src http://192.168.0.1:9999/de.archive.ubuntu.com/ubuntu/ jaunty multiverse deb http://192.168.0.1:9999/de.archive.ubuntu.com/ubuntu/ jaunty-updates multiverse deb-src http://192.168.0.1:9999/de.archive.ubuntu.com/ubuntu/ jaunty-updates multiverse deb http://192.168.0.1:9999/security.ubuntu.com/ubuntu jaunty-security main restricted deb-src http://192.168.0.1:9999/security.ubuntu.com/ubuntu jaunty-security main restricted deb http://192.168.0.1:9999/security.ubuntu.com/ubuntu jaunty-security universe deb-src http://192.168.0.1:9999/security.ubuntu.com/ubuntu jaunty-security universe deb http://192.168.0.1:9999/security.ubuntu.com/ubuntu jaunty-security multiverse deb-src http://192.168.0.1:9999/security.ubuntu.com/ubuntu jaunty-security multiverse # FAI Repository deb http://192.168.0.1:9999/www.informatik.uni-koeln.de/fai/download lenny koeln
All other files in the files/etc/apt/-directory are binaries!
vi files/etc/default/console-setup/LANG_GERMAN
Paste the following lines:
# A configuration file for setupcon # Change to "yes" and setupcon will explain what is being doing VERBOSE_OUTPUT=no # Setup these consoles. Most people do not need to change this. ACTIVE_CONSOLES="/dev/tty[1-6]" # Put here your encoding. Valid charmaps are: UTF-8 ARMSCII-8 CP1251 # CP1255 CP1256 GEORGIAN-ACADEMY GEORGIAN-PS IBM1133 ISIRI-3342 # ISO-8859-1 ISO-8859-2 ISO-8859-3 ISO-8859-4 ISO-8859-5 ISO-8859-6 # ISO-8859-7 ISO-8859-8 ISO-8859-9 ISO-8859-10 ISO-8859-11 ISO-8859-13 # ISO-8859-14 ISO-8859-15 ISO-8859-16 KOI8-R KOI8-U TIS-620 VISCII CHARMAP="UTF-8" # The codeset determines which symbols are supported by the font. # Valid codesets are: Arabic Armenian CyrAsia CyrKoi CyrSlav Ethiopian # Georgian Greek Hebrew Lao Lat15 Lat2 Lat38 Lat7 Thai Uni1 Uni2 Uni3 # Vietnamese. Read README.fonts for explanation. CODESET="Lat15" # Valid font faces are: VGA (sizes 8, 14 and 16), Terminus (sizes # 12x6, 14, 16, 20x10, 24x12, 28x14 and 32x16), TerminusBold (sizes # 14, 16, 20x10, 24x12, 28x14 and 32x16), TerminusBoldVGA (sizes 14 # and 16), Fixed (sizes 13, 14, 15, 16 and 18), Goha (sizes 12, 14 and # 16), GohaClassic (sizes 12, 14 and 16). FONTFACE="VGA" FONTSIZE="16" # You can also directly specify nonstandard font and ACM to load: # FONT=/usr/local/share/funnyfonts/sarge16.psf # ACM=/usr/local/share/consoletrans/my_special_encoding.acm # The following variables describe your keyboard and can have the same # values as the XkbModel, XkbLayout, XkbVariant and XkbOptions options # in /etc/X11/xorg.conf. XKBMODEL="pc105" XKBLAYOUT="de" XKBVARIANT="" XKBOPTIONS="" # Do not update the following md5 sum if you change # /etc/console-setup/boottime.kmap.gz and Debconf will not overwrite # your custom keymap. Do not update it even if you want to make # Debconf overwrite it. Instead simply specify the empty string as # a md5 sum. BOOTTIME_KMAP_MD5=""
vi files/etc/default/locale/LANG_GERMAN
Paste the following lines:
LANG="de_DE.UTF-8"
vi files/etc/ntework/interfaces/NW_DHCP
Paste the following lines:
# The loopback network interface auto lo iface lo inet loopback # The primary network interface auto eth0 iface eth0 inet dhcp
The hooks directory:
vi hooks/savelog.LAST.source
Paste the following lines:
#! /bin/bash # parse all log files for error messages # print errors and warnings found to error.log # WARNING: This will only work with english error messages! errfile=$LOGDIR/error.log # Define grep patterns. Do not start or end with an empty line! globalerrorpatterns="error fail warn bad no space syntax Couldn't stat Cannot access is bigger than the limit did not exist non existent not found couldn't can't E: Sorry, broken packages operator expected ambiguous redirect No previous regular expression No such Device or resource busy unknown option [a-z]\+\.log:E: No candidate version found segfault Couldn't find any package whose name or description matched cannot create The following packages have unmet dependencies" globalignorepatterns="[a-z]\+\.log:# :+ error=0 :+ trap error= task_error_func= STOP_ON_ERROR= courier-webadmin gstreamer0.10-plugins-bad ibwebadmin kernel-patch-badram kolab-webadmin kolabadmin gstreamer0.10-plugins-really-bad gsambad libad libtest-nowarnings-perl libtest-warn-perl libclass-errorhandler-perl zope-ploneerrorreporting libroxen-errormessage liberror-perl libgpg-error-dev libgpg-error0 ^fstab.\+errors=remount [RT]X packets: WARNING: unexpected IO-APIC warned about = ( ) daemon.warn kern.warn rw,errors= Expect some cache no error failmsg RPC call returned error 101 deverror.out (floppy), sector 0 mount version older than kernel Can't locate module Warning only 896MB will be used. hostname: Host name lookup failure I can't tell the difference. warning, not much extra random data, consider using the -rand option confC._FILE Warning: 3 database(s) sources were not found, (but were created) removing exim The home dir you specified already exists. No Rule for /usr/lib/ispell/default.hash. /usr/sbin/update-fonts-.\+: warning: absolute path hostname: Unknown server error EXT2-fs warning: checktime reached RPC: sendmsg returned error 101 can't print them to stdout. Define these classes warning: downgrading suppress emacs errors echo Error: Can't open dependencies file documents in /usr/doc are no longer supported if you have both a SCSI and an IDE CD-ROM Warning: /proc/ide/hd?/settings interface is obsolete, and will be removed soon Monitoring disabled Error: only one processor found. Error Recovery Strategy: sector 0 does not have an syslogin_perform_logout: logout() returned an error grub is not in an XFS filesystem. is harmless not updating .\+ font directory data. register_serial(): autoconfig failed Fontconfig error: Cannot load default config file asking for cache data failed However, I can not read the target: fai-kernels/modules.dep: No such file Warning: The partition table looks like it was made task_error=0 ^info: Trying to set warning: /usr/lib/X11/fonts can't read /etc/udev/rules.d/z25_persistent-net.rules /cow': No such file or directory Dummy start-stop-daemon called cdrom: open failed." # add pattern on some conditions if [ -n $FAI_ALLOW_UNSIGNED ] ; then globalignorepatterns="$globalignorepatterns WARNING: untrusted versions Ignoring these trust violations" fi # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Here you can define your own patterns. Put one pattern in a line, # do not create empty lines. myerrorpatterns="XXXXX" myignorepatterns="XXXXX" # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # The main routine errorpatterns="$globalerrorpatterns $myerrorpatterns" ignorepatterns="$globalignorepatterns $myignorepatterns" cd $LOGDIR || exit 3 if [ -s $errfile ]; then echo "Errorfile already exists. Aborting." exit fi grep -i "$errorpatterns" *.log | grep -vi "$ignorepatterns" > $errfile if [ "$verbose" ]; then egrep -v '^software.log:' $errfile > $LOGDIR/tempfile mv $LOGDIR/tempfile $errfile fi if [ -s $errfile ]; then echo "ERRORS found in log files. See $errfile" else echo "Congratulations! No errors found in log files." export flag_reboot=1 fi
vi hooks/updatebase.OS_UBUNTU_904_X32
Paste the following lines:
#! /bin/bash # Import custom apt sources.list and apt keys. echo "Preparing apt" fcopy -v /etc/apt/secring.gpg fcopy -v /etc/apt/sources.list fcopy -v /etc/apt/trustdb.gpg fcopy -v /etc/apt/trusted.gpg # Initialize apt-key before apt is called the first time if [ -x $target/usr/bin/apt-key ]; then echo "Apt: list of keys" $ROOTCMD /usr/bin/apt-key list fi # Copy the console-setup file early to avoid unnecessary # error messages fcopy -v /etc/default/console-setup
The package_config directory:
vi package_config/BC_BASE
Paste the following lines:
PACKAGES aptitude apt apt-utils cfengine2 console-setup debconf-utils dhcp3-client fai-client grub language-pack-de less locales openssh-server vi
vi package_config/LANG_GERMAN
Paste the following lines:
PACKAGES aptitude language-pack-de
vi package_config/OS_UBUNTU_904_X32
Paste the following lines:
PACKAGES aptitude linux-image-generic
The scripts directory:
vi scripts/BC_BASE/10-misc
Paste the following lines:
#! /bin/bash # (c) Thomas Lange, 2001-2008, lange@debian.org error=0 ; trap "error=$((error|1))" ERR # a list of modules which are loaded at boot time fcopy -i /etc/modules for module in $MODULESLIST; do ainsl -a $target/etc/modules "^$module$" done fcopy /etc/hostname || echo $HOSTNAME > $target/etc/hostname echo $TIMEZONE > $target/etc/timezone ln -fs /usr/share/zoneinfo/${TIMEZONE} $target/etc/localtime fcopy -iM /etc/hosts /etc/motd # set root password echo "root:$ROOTPW" | $ROOTCMD chpasswd --encrypted # make /root accessible only by root chmod 0700 $target/root chown root:root $target/root # copy default dotfiles for root account fcopy -ir /root exit $error
vi scripts/BC_BASE/20-fcopy
Paste the following lines:
#! /bin/bash # Copy files from $FAI/files fcopy -v /etc/network/interfaces fcopy -v /etc/ssh_known_hosts fcopy -v /etc/default/locale
vi scripts/GRUB/10-setup
Paste the following lines:
#! /bin/bash error=0 ; trap "error=$((error|1))" ERR # Eventual source the disk_var.sh just in case # the BOOT_DEVICE/BOOT_PARTITION/ROOT_PARTITION # variables are overwritten [ -r /tmp/fai/disk_var.sh ] && . /tmp/fai/disk_var.sh ifclass NOMBR && BOOT_DEVICE=$BOOT_PARTITION [ -z "$BOOT_DEVICE" ] && exit 701 [ -z "$BOOT_PARTITION" ] && exit 702 # call grub-install from ubuntu $target/usr/sbin/grub-install --no-floppy --root-directory=/$target $BOOT_DEVICE # call update-grub inside ubuntu chroot with special "no user questions" flag $ROOTCMD /usr/sbin/update-grub -y exit $error
vi scripts/GRUB/20-initramfs
Paste the following lines:
#! /bin/bash error=0 ; trap "error=$((error|1))" ERR not_up2date() { if [ $# -eq 0 ] ; then echo "No package name given!" return 127 fi egrep -q "(^Unpacking $1 |^Unpacking replacement $1 )" $LOGDIR/*.log return $? } if [ `not_up2date lvm2` -o `not_up2date mdadm` ] ; then $ROOTCMD update-initramfs -k all -u fi exit $error
vi scripts/LAST/50-misc
Paste the following lines:
#! /bin/bash # copyright Thomas Lange 2001-2007, lange@debian.org error=0 ; trap "error=$((error|1))" ERR # remove backup files from cfengine dirs="root etc var" for path in $dirs; do find $target/$path -maxdepth 20 -name \*.cfedited -o -name \*.cfsaved | xargs -r rm done [ "$FAI_DEBMIRROR" ] && echo "#$FAI_DEBMIRROR $MNTPOINT nfs ro 0 0" >> $target/etc/fstab # set bios clock if [ $do_init_tasks -eq 1 ] ; then case "$UTC" in no|"") hwopt="--localtime" ;; yes) hwopt="--utc" ;; esac $ROOTCMD hwclock $hwopt --systohc || true fi # Make sure everything is configured properly echo "Running \"apt-get -f install\" for the last time." $ROOTCMD apt-get -f install lskernels=$(echo $target/boot/vmlinu*) [ -f ${lskernels%% *} ] || echo "ERROR: No kernel was installed. Have a look at shell.log" exit $error
Whew! That was a lot of copy&pasting! After making the scripts executable by issuing
chmod -R 755 /srv/fai/config
it's time to create our distribution-specific base.tar.gz.
Create a custom base.tgz
For each distribution that you want to roll out with FAI, you have to create a separate base.tgz. This is the most critical part in order for FAI to go multi-distribution!
First off, you have to boot into the exact distribution with the exact same version that you want to roll out on your clients. If you want to roll out ubuntu 9.04, you have to boot into an ubuntu 9.04 environment.
Once you've booted to your selected distribution, switch to root first:
sudo su
and update the distribution to be sure you use the most up-to-date packages (you might want to edit the distributions /etc/apt/sources.list first to use your apt-proxy; see above):
apt-get update && apt-get -y upgrade
Now install pbuilder and debootstrap. You'll need these two for creating your base.tgz.
apt-get -y install pbuilder debootstrap
You have to modify these packages a bit. Open the file:
vi /etc/pbuilder/pbuilderrc
and change the following two lines (note that we'll use our apt-proxy):
MIRRORSITE=http://192.168.0.1:9999/archive.ubuntu.com/ubuntu DISTRIBUTION=jaunty
Copy needed files from /etc/apt to your pBuilder-directory:
mkdir /etc/pbuilder/apt.config/ cp -ar /etc/apt/* /etc/pbuilder/apt.config/
It is important to make sure that the file 99update-notifier is not contained in the folder /etc/pbuilder/apt.config/apt.conf.d/. This file could complicate things later on. So do a:
rm /etc/pbuilder/apt.config/apt.conf.d/99update-notifier
Open this file:
vi /etc/pbuilder/apt.config/apt.conf.d/allow-unauthenticated
and add the following line:
APT::Get::AllowUnauthenticated 1;
With the following command the chroot-environment will be created:
pbuilder create
Time for another coffee.
Once finished, the base-image is created in /var/cache/pbuilder/base.tgz. This file has to be copied to the $FAI/config/basefiles/-dir we created above above, e.g.:
scp /var/cache/pbuilder/base.tgz root@192.168.0.1:/srv/fai/config/basefiles/OS_UBUNTU_904_X32.tar.gz
What happened here? Well, if you want to roll out multiple distributions with FAI, how does FAI know which distribution to apply to which client? The answer is simple: by applying a class. Say, you want to roll out Ubuntu 9.04 x32 and Debian Lenny x32. Then you could name your classes e.g. OS_UBUNTU_904_X32 and OS_DEBIAN_LENNY_X32 and apply them to your hosts in the 50-host-classes file. Upon installation, FAI looks for base.tgz files named OS_UBUNTU_904_X32.tar.gz and OS_DEBIAN_LENNY_X32.tar.gz See the connection? So a client with the class OS_UBUNTU_904_X32 will be served the base.tgz named OS_UBUNTU_904_X32.tar.gz. Thus, you have to rename your base.tgz-file to the name of your class (which is what we already did within the scp-command above).
The basic process should be the same for other distributions as well; that is, creating a base.tgz file with pbuilder and copy this file to $FAI/basefiles/OS_DEBIAN_LENNY_X64.tar.gz. Just make sure you specify and apply the needed classes.
Let's roll!
Tired eyes and many sore fingers later, we are finally finished!
All that is left to do is to tell FAI which clients should be used for installation. You do this with this command:
fai-chboot -IB 192.168.0.10
Where 192.168.0.10 is the IP address of the target client. You can assign a client a specific IP by using its NIC's MAC address in the DHCP config. See the appropriate chapter in this howto for how it is done.
Should you experience problems at this point, e.g. the client not finding the TFTP server, restart the ubuntu server and try again. More than once, this worked wonders for me.
I recommend to use a test client for testing. If no physical client is available, you could use VirtualBox or any other virtualization product.
Now, when the target client is booted the next time, make sure it is set to boot from the network (either with a setting in its BIOS or by temporarily selecting a boot device if your client supports this). WARNING: All the client's data - that is, the whole hard disk - will be erased in the process! Make sure you are fully aware of the consequences!
If everything went well, once the client is installed, you can log in with username root' and password fai. Check the logs at /var/log/fai/vm-ubuntu904/last/error.log for any errors.
Congratulations! You've completed your first FAI install!
Thanks for reading!
Comments and feedback are always welcome (please see my profile for contact information), however, please direct any technical questions or comments to the mailinglist.