2. Building a Yum Repository

OK, now for the hands on stuff. We'll set up a local yum repository. In this example, the server is a Red Hat 8.0 box, as updated. The client runs Fedora Beta 2, or version number 0.94. This will be a base repository, for initial installations. You can also build an updates repository, but we'll leave that as an exercise for the student.

2.1. On the Server

2.1.1. Get The ISO Images

Get the CD-ROM ISO images for the distribution you want to install. See http://fedora.redhat.com/download/ for the gory details.

2.1.2. Getting At the Packages

Figure out how to extract the RPM packages you want from the images. This may involve burning the images onto CD-RW platters and then mounting them. Somewhat more elegant: implement a CD-ROM server, or jukebox, using Linux. See Randolph J Tata's CDServer-HOWTO, available at Linux Documentation Project mirrors near you. I'm lazy; I don't like swapping CD-ROMs in and out of drives on target computers. I took the latter route so I could install over NFS (not covered here).

If you are going to make the ISO images available via FTP (see below), you must put the ISO images under ftp/pub. If you put them outside the FTP tree, and symlink to them from inside the FTP tree, the FTP server won't follow the links. And hard linking directories is not a good idea.

2.1.3. Set Up Your Server

Set up your FTP or HTTP server. Most Linux installations have one or both already enabled. See your local documentation for details. We'll show how to do this with FTP. HTTP should be similar.

2.1.4. Set Up your Directory Tree

Under ftp/pub, set up your tree. ftp/pub is under /var on Red Hat 8, but your location may be different. Imitating the directory tree of the yum mother repository at Duke, I made ftp/pub/yum-repository/redhat/. The next two directories you need will be resolved by yum as $releasever/$basearch/. For example, for Fedora Beta 2 on i386, they are 0.94 and i386 respectively. I found this out by firing up Mozilla and looking to see how the folks at Duke had laid out their server. So the commands I used were:

mkdir -p /var/ftp/pub/yum-repository/redhat/0.94/i386
cd /var/ftp/pub/yum-repository/redhat/0.94/i386

(This is where tab completion comes in handy. :-)

If you are going to make the ISO images available via FTP, you must put the ISO images under ftp/pub. If you put them outside the FTP tree, and symlink to them from inside the FTP tree, the FTP server won't follow the links. And hard linking directories is not a good idea.

2.1.5. Accessing the Packages

There are two ways (at least) to access the packages. You can mount them once and extract the packages with cp to some other suitable location. The other is to mount the ISO images via loopback devices. The first has the disadvantage that you have two copies of almost everything: the copy in the ISO, and the one you extracted. So you can save almost 2 GB with the latter technique, even if it is more convoluted. Another advantage is that once you have learned the second technique you can use it to make other ISO images and their content available across your network.

Again, you must put the loopback directory under ftp/pub. If you put it outside the FTP tree, and symlink to it from inside the FTP tree, the FTP server won't follow the links. And hard linking directories is not a good idea.

2.1.5.1. Mounting the ISOs

Mounting the ISO images means that you mount the ISO files as though they were files. Remember, in Unix everything is a file. If you can mount a floppy drive, which is just another file, why can't you mount a file? That's what the loopback device does.

I'm not going to go into gory detail here on how to set up the loopback devices here. Instead, see Randolph J Tata's CDServer-HOWTO, available at Linux Documentation Project mirrors near you. Also see Jeremy Impson's Build a Virtual CD-ROM Jukebox. The techniques are very similar. The major advantage of the latter is that it conserves loopback devices (although you can make more up to the kernel's limit).

I will add a constraint to both of these documents. Put both the ISO images and their mount points in either your HTTP or FTP server's tree. I put them in the FTP tree so that I could use FTP for fresh installations.

I also suggest you export the directory where the ISOs reside via NFS so that you can also install via NFS. Whether you use NFS or FTP is your choice.

When I built my server for Fedora Core Release 1 (Yarrow), I used Impson's method. I ended up with three directories in /var/ftp/pub. You will probably want to change the base file names to reflect whatever you are exporting.

  • fc1 has the symlinks (into fc1_auto). This is the directory to export via Samba or NFS to allow access to the contents of the ISOs. This is also the the directory in which to make the headers for the yum repository, and the directory you will use in client computers' yum.conf.

  • fc1_auto is a "hidden" directory in the sense that once it is set up and working we pretty much ignore it. This is where the automounter daemon actually mounts the ISO images. However, because we export fc1, users see the symlinks. When the kernel follows the symlinks, the automounter can mount the images.

  • fc1.isos is where the ISOs reside. Export this directory to allow users to download the ISOs ready for their own CD burners. Export this directory via NFS to allow installation via NFS.

2.1.5.2. Extract the packages

The following command copies everything from the ISO images. The source directory will be different on your system.

cp --reply=no -rp /mnt/isosrv/severn.disc*/RedHat .

Then, just to be neat and conserve disk space:

find -name TRANS.TBL | xargs rm

If you don't plan to use FTP or NFS for your installations, you don't need the 127 MB in RedHat/base.

rm -r RedHat/base/

2.1.6. Install Yum

You were wondering if I'd remember this, weren't you? It's easier once you've extracted it from the ISO images.

rpm -ivh RedHat/RPMS/yum-2.0.3-1.noarch.rpm

If you are mounting the ISO images,

cd fc1;rpm -ivh yarrow-i386-disc1.iso/Fedora/RPMS/yum-2.0.4-2.noarch.rpm

2.1.7. Make the Header Files

Create the separate header files for each package in the repository. This is the step that makes a yum repository different from a plain vanilla RPM mirror.

yum-arch .

And you should see something like:

Digesting rpms 3 % complete: comps-0.94-0.20030924.i386.rpm
Already found tuple: comps i386:
RedHat/RPMS/comps-0.94-0.20030924.i386.rpm
Digesting rpms 100 % complete: zsh-4.0.7-1.1.i386.rpm
Total: 1467
Used: 1467
Src: 0

Writing header.info file

If you have yum version 2.1 or higher, yum-arch will complain and refer you to a completely useless web page. You should install the createrepo RPM package. Then the command will be:

createrepo .

And again, you should see something like:

1653/1653 - FC3-i386-disc4.iso/Fedora/RPMS/zsh-html-4.2.0-3.i386.rpm
Saving Primary metadata
Saving file lists metadata
Saving other metadata

(For more on yum 2.1 and up, see http://www.redhat.com/archives/fedora-devel-list/2004-September/msg00187.html, How to build a custom Yum Repository in FC3, or the appropriate man pages.)

Since yum-arch and createrepo create their data in different directories, it is harmless to run both. If you are building things manually, this would be a waste of cycles. But you might want to do this if you are maintaining systems that use several versions of yum, e.g. FC1, FC2 and FC3.

We should be done on the server. Now let us turn to the client.

2.2. On the Client

Install the minimal base system on the client. You can build and use a kickstart file or do it manually. In fact, do both: do it manually the first time and use the resulting /root/anaconda-ks.cfg as the basis for your own kickstart file.

2.2.1. Edit Yum.conf

Edit the client's /etc/yum.conf file. I first save the original off as yum.conf.au (au for golden). Because paranoids live longer, I add the following to both the [base] and [updates] sections: "gpgcheck=1". This turns on gpg signature checking. You can use the kickstart post script to import the gpg signatures during installation. Then I edit the baseurl portion of the [base] section as follows (where yumserver is the name of my yum repository server):

[base]
gpgcheck=1
name=Red Hat Linux $releasever - $basearch - Base
baseurl=ftp://yumserver/pub/yum-repository/redhat/$releasever/$basearch/

If you are mounting the ISOs as I showed above, the path will be a bit different.

[base]
gpgcheck=1
name=Red Hat Linux $releasever - $basearch - Base
baseurl=ftp://yumserver/pub/fc1/

2.2.2. The Smoke Test

Now for the smoke test (as hardware engineers say). See if our repository is working. On the client, run:

yum list

and you should see:

Gathering header information file(s) from server(s)
yada,yada,yada...
getting /var/cache/yum/base/headers/gtk+-devel-1-1.2.10-27.i386.hdr
getting /var/cache/yum/base/headers/macutils-0-2.0b3-25.i386.hdr
getting /var/cache/yum/base/headers/octave-6-2.1.50-3.i386.hdr
getting /var/cache/yum/base/headers/g-wrap-0-1.3.4-4.i386.hdr
Server: Red Hat Linux 0.94 - i386 - Base
Server: Red Hat Linux 0.94 - Updates
Finding updated packages
Downloading needed headers
Name                        Arch   Version            Repo
--------------------------------------------------------------------------------
Canna                       i386   3.6-20.1           base
Canna-devel                 i386   3.6-20.1           base
Canna-libs                  i386   3.6-20.1           base
yada, yada, yada...

At this point, you should be able to install away.

2.3. To Do

We have one repository installed and working. Things yet to do: