UbuntuJauntyInstallationHowTo: Difference between revisions

From FAIWiki
Jump to navigation Jump to search
(Using FAI on the Ubuntu server directly)
m (minor corrections and inconsistencies that slipped through the initial proof-reading)
Line 1: Line 1:
= Introduction =
= Introduction =


Goal: Using FAI to install Ubuntu 9.04 'Jaunty Jackalope' (heck, any other distribution). Support for a multidistribution setup.
Goal: Using FAI to install ubuntu 9.04 'Jaunty Jackalope' (heck, any other distribution).


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 our goal. So don't be put off by the length of this howto; you should reach your goal fairly quickly.
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 reach be up&running fairly quickly.


Feel free to edit this article as you see fit, after all, it's a wiki!
Feel free to edit this article as you see fit, after all, it's a wiki!
Line 9: Line 9:
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!
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.
''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!
''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!
Line 16: Line 16:




= Ubuntu Server installation =
= ubuntu Server installation =


First things first. Remember, this is a ground-up tutorial, so let's make sure we use the same environment.
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).
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'''
* '''Choose Language'''
** Wählen Sie ein Land oder Gebiet: ''Deutschland''
** Wählen Sie ein Land oder Gebiet: ''Deutschland''
* ''' Ubuntu-Installer-Hauptmenü'''
* ''' ubuntu-Installer-Hauptmenü'''
** Tastaturmodell erkennen: ''Nein''
** Tastaturmodell erkennen: ''Nein''
** Herkunft der Tastatur: ''Germany''
** Herkunft der Tastatur: ''Germany''
Line 61: Line 61:
Now reboot the machine.
Now reboot the machine.


== Configure your Ubuntu server ==
== Configure your ubuntu server ==


Log in with your username and change to user root:
Log in with your username and change to user root:
Line 69: Line 69:
=== Configuring the network ===
=== 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:
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:


<code>vi /etc/network/interfaces</code>
<code>vi /etc/network/interfaces</code>
Line 98: Line 98:
</pre>
</pre>


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:
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:


<code>sudo su</code>
<code>sudo su</code>
Line 266: Line 266:
=== Activate routing ===
=== Activate routing ===


Since all internet connections from your internal network will go over the Ubuntu server, you need to activate routing so the packages will be passed over.
Since all internet connections from your internal network will go over the ubuntu server, you need to activate routing so the packages will be passed over.


Activating IP-Forwarding:
Activating IP-Forwarding:
Line 288: Line 288:
To teach the TFTP server to start as a daemon, edit the following file:
To teach the TFTP server to start as a daemon, edit the following file:


<code>vim /etc/default/tftpd-hpa</code>
<code>vi /etc/default/tftpd-hpa</code>


and replace the content with the following lines:
and replace the content with the following lines:
Line 300: Line 300:
Then, edit this file:
Then, edit this file:


<code>vim /etc/inetd.conf</code>
<code>vi /etc/inetd.conf</code>


and comment out the following line (=put a hash sign # in front of the line):
and comment out the following line (=put a hash sign # in front of the line):
Line 321: Line 321:
Open the FAI config file:
Open the FAI config file:


<code>vim /etc/fai/fai.conf</code>
<code>vi /etc/fai/fai.conf</code>


and replace the content with the following lines:
and replace the content with the following lines:
Line 352: Line 352:
Open the nfsroot config file:
Open the nfsroot config file:


<code>vim /etc/fai/make-fai-nfsroot.conf</code>
<code>vi /etc/fai/make-fai-nfsroot.conf</code>


and replace the content with the following lines:
and replace the content with the following lines:
Line 397: Line 397:
''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:
''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:


<code>vim /etc/exports</code>
<code>vi /etc/exports</code>


uncomment the following lines:
uncomment the following lines:
Line 423: Line 423:


# Getting FAI up&running fairly quickly
# 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'')
# 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
# Using german keyboard layout on the client's console


Line 474: Line 474:
==== The '''class''' directory: ====
==== The '''class''' directory: ====


* <code>vim class/10-base-classes</code>
* <code>vi class/10-base-classes</code>


Paste the following lines:
Paste the following lines:
Line 489: Line 489:
</pre>
</pre>


* <code>vim class/20-hwdetect.source</code>
* <code>vi class/20-hwdetect.source</code>


Paste the following lines:
Paste the following lines:
Line 544: Line 544:
</pre>
</pre>


* <code>vim class/50-host-classes</code>
* <code>vi class/50-host-classes</code>


Paste the following lines:
Paste the following lines:
Line 565: Line 565:
</pre>
</pre>


* <code>vim class/BC_BASE.var</code>
* <code>vi class/BC_BASE.var</code>


Paste the following lines:
Paste the following lines:
Line 623: Line 623:
==== The '''debconf''' directory: ====
==== The '''debconf''' directory: ====


* <code>vim debconf/LANG_GERMAN</code>
* <code>vi debconf/LANG_GERMAN</code>


Paste the following lines:
Paste the following lines:
Line 662: Line 662:
==== The '''disk_config''' directory: ====
==== The '''disk_config''' directory: ====


* <code>vim disk_config/HDD_SINGLE</code>
* <code>vi disk_config/HDD_SINGLE</code>


Paste the following lines:
Paste the following lines:
Line 678: Line 678:
==== The '''files''' directory: ====
==== 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:
* ''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
** secring.gpg
** sources.list
** sources.list
Line 685: Line 685:
* Don't forget to rename the files accordingly. E.g. ''secring.gpg'' will be ''files/etc/apt/secring.gpg/OS_UBUNTU_904_X32''!
* 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'' (<code>vim files/etc/apt/sources.list/OS_UBUNTU_904_X32</code>) so it points to your apt-proxy. If you've followed the steps [[#Use apt-proxy|above]], you will be already familiar with that. In the case of Ubuntu 9.04 you paste the following lines:
However, you might want to edit the ''apt/sources.list'' (<code>vi files/etc/apt/sources.list/OS_UBUNTU_904_X32</code>) so it points to your apt-proxy. If you've followed the steps [[#Use apt-proxy|above]], you will be already familiar with that. In the case of ubuntu 9.04 you paste the following lines:


<pre>
<pre>
Line 717: Line 717:
All other files in the ''files/etc/apt/''-directory are binaries!
All other files in the ''files/etc/apt/''-directory are binaries!


* <code>vim files/etc/default/console-setup/LANG_GERMAN</code>
* <code>vi files/etc/default/console-setup/LANG_GERMAN</code>


Paste the following lines:
Paste the following lines:
Line 773: Line 773:
</pre>
</pre>


* <code>vim files/etc/default/locale/LANG_GERMAN</code>
* <code>vi files/etc/default/locale/LANG_GERMAN</code>


Paste the following lines:
Paste the following lines:
Line 781: Line 781:
</pre>
</pre>


* <code>vim files/etc/ntework/interfaces/NW_DHCP</code>
* <code>vi files/etc/ntework/interfaces/NW_DHCP</code>


Paste the following lines:
Paste the following lines:
Line 797: Line 797:
==== The '''hooks''' directory: ====
==== The '''hooks''' directory: ====


* <code>vim hooks/savelog.LAST.source</code>
* <code>vi hooks/savelog.LAST.source</code>


Paste the following lines:
Paste the following lines:
Line 958: Line 958:
</pre>
</pre>


* <code>vim hooks/updatebase.OS_UBUNTU_904_X32</code>
* <code>vi hooks/updatebase.OS_UBUNTU_904_X32</code>


Paste the following lines:
Paste the following lines:
Line 989: Line 989:
==== The '''package_config''' directory: ====
==== The '''package_config''' directory: ====


* <code>vim package_config/BC_BASE</code>
* <code>vi package_config/BC_BASE</code>


Paste the following lines:
Paste the following lines:
Line 1,007: Line 1,007:
locales
locales
openssh-server
openssh-server
vim
vi
</pre>
</pre>


* <code>vim package_config/LANG_GERMAN</code>
* <code>vi package_config/LANG_GERMAN</code>


Paste the following lines:
Paste the following lines:
Line 1,019: Line 1,019:
</pre>
</pre>


* <code>vim package_config/OS_UBUNTU_904_X32</code>
* <code>vi package_config/OS_UBUNTU_904_X32</code>


Paste the following lines:
Paste the following lines:
Line 1,030: Line 1,030:
==== The '''scripts''' directory: ====
==== The '''scripts''' directory: ====


* <code>vim scripts/BC_BASE/10-misc</code>
* <code>vi scripts/BC_BASE/10-misc</code>


Paste the following lines:
Paste the following lines:
Line 1,064: Line 1,064:
</pre>
</pre>


* <code>vim scripts/BC_BASE/20-fcopy</code>
* <code>vi scripts/BC_BASE/20-fcopy</code>


Paste the following lines:
Paste the following lines:
Line 1,077: Line 1,077:
</pre>
</pre>


* <code>vim scripts/GRUB/10-setup</code>
* <code>vi scripts/GRUB/10-setup</code>


Paste the following lines:
Paste the following lines:
Line 1,105: Line 1,105:
</pre>
</pre>


* <code>vim scripts/GRUB/20-initramfs</code>
* <code>vi scripts/GRUB/20-initramfs</code>


Paste the following lines:
Paste the following lines:
Line 1,132: Line 1,132:
</pre>
</pre>


* <code>vim scripts/LAST/50-misc</code>
* <code>vi scripts/LAST/50-misc</code>


Paste the following lines:
Paste the following lines:
Line 1,182: Line 1,182:
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!''
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.
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:
Once you've booted to your selected distribution, switch to root first:
Line 1,198: Line 1,198:
You have to modify these packages a bit. Open the file:
You have to modify these packages a bit. Open the file:


<code>vim /etc/pbuilder/pbuilderrc</code>
<code>vi /etc/pbuilder/pbuilderrc</code>


and change the following two lines (note that we'll use our apt-proxy):
and change the following two lines (note that we'll use our apt-proxy):
Line 1,220: Line 1,220:
Open this file:
Open this file:


<code>vim /etc/pbuilder/apt.config/apt.conf.d/allow-unauthenticated</code>
<code>vi /etc/pbuilder/apt.config/apt.conf.d/allow-unauthenticated</code>


and add the following line:
and add the following line:
Line 1,249: Line 1,249:
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 [[#Installing and configuring DHCP|appropriate chapter]] in this howto for how it is done.
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 [[#Installing and configuring DHCP|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.
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 settings|VirtualBox]] or any other virtualization product.
I recommend to use a test client for testing. If no physical client is available, you could use [[#VirtualBox settings|VirtualBox]] or any other virtualization product.
Line 1,270: Line 1,270:
If you want to test everything in a safe VirtualBox environment like I did, these are the required network settings for the machines:
If you want to test everything in a safe VirtualBox environment like I did, these are the required network settings for the machines:


* '''Ubuntu server'''
* '''ubuntu server'''
** At least 5 GB of disk space
** 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 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''
** '''NIC 2''' (aka eth1): Connected to: ''Internal network'', Name: ''intnet''


* '''Ubuntu client'''
* '''ubuntu client'''
** '''NIC 1''' (aka eth0): Connected to: ''Internal network'', Name: ''intnet'', MAC: ''112233445566''
** '''NIC 1''' (aka eth0): Connected to: ''Internal network'', Name: ''intnet'', MAC: ''112233445566''

Revision as of 08:37, 28 June 2009

Introduction

Goal: Using FAI to install ubuntu 9.04 'Jaunty Jackalope' (heck, any other distribution).

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 reach 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.


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

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.2; and filename "pxelinux.0"; point to your FAI-Server which will get the IP 192.168.0.2. 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

Since all internet connections from your internal network will go over the ubuntu server, you need to activate routing so the packages will be passed over.

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"

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:

  1. Getting FAI up&running fairly quickly
  2. 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)
  3. 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

# Import FAI repository keys
echo "Importing FAI repository keys"
apt-key adv --recv-keys --keyserver keyserver.ubuntu.com AB9B66FD

# 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:

scp /var/cache/pbuilder/base.tgz root@192.168.0.2:/srv/fai/config/basefiles/OS_UBUNTU_904_X32.tar.gz

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.


Appendix

VirtualBox settings

If you want to test everything in a safe VirtualBox environment like I did, these are the required network settings for the machines:

  • 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