How to setup your own package repository

Sometimes you'll find you need to be able to collect a bunch of rpm packages you have together in one place and you want to make them available to your systems running yum. It is pretty easy to do.

Overview

A package repository used by yum is simply a directory with one or more RPMs plus some "meta information" used by yum to be able to easily access information (dependencies, file lists, etc.) for the RPMs. yum can then to access this directory over ftp/http or a file URI (including over NFS).

Steps

  1. Collect the packages together in one directory. You can make as many sub-directories as you want, but there needs to be a top level directory where they all live. That's where we're going to form our repository.
  1. Yum uses a digest of the information stored in each RPM to do its work. This information is created using the 'createrepo' program. If you don't have createrepo installed you can install it with:
    yum install createrepo

If you are generating your repository on a machine that doesn't use RPMs, you can download createrepo from http://createrepo.baseurl.org/ and build/install it manually.

Once you have createrepo installed you need to run it. It only requires one argument which is the directory in which you would like to generate the repository data. So if the packages directory we made in step 1 is in /srv/my/repo then you would run:

    createrepo /srv/my/repo

You should see a lot of things fly by but it should finish without an error. In the end you should have a directory named /srv/my/repo/repodata with at least 4 files in it. Maybe more.

  1. To make this repository known to yum you need to add a .repo file to your yum configuration. On the systems where you want to use this repo you need to make a new file in /etc/yum.repos.d/. The file can be named anything but the extension on the file has to be .repo. Let's call this one 'myrepo.repo'.

In the file you just need to include the following:

   [myrepo]
   name = This is my repo
   baseurl = url://to/get/to/srv/my/repo/

That's all you need in that file. The 'baseurl' line is the path that machine uses to get to the repository. If the machine has direct access to it or mounts it as a filesystem you can use a baseurl line like:

     baseurl = file:///srv/my/repo/

NB: there are 3 slashes (/) following the file:, not 2. That is correct.

If you access the file via an http or https server you would use something like:

     baseurl = http://servername/my/repo

More details about client-side repo configuration can be found in the yum.conf man page.

  1. Now, every time you modify, remove or add a new RPM package to /srv/my/repo you need to recreate the repository metadata. You do that by running createrepo the same way you did in step 2.

Recommended options

While running plain createrepo on it's own will work, and is generally the most compatible, it is recommended that you add extra options if you know you've only got newer yum clients.

  1. --database, this creates the .sqlite databases on the server saving time on every client. There is no downside to doing this, as older versions of yum will just ignore the .sqlite files and get the .xml files.
  1. --unique-md-filenames, this names all the metadata files be uniquely. This is most useful if you are using mirrors. Versions of yum before 3.2.10 will not clean up correctly.
  1. --changelog-limit, limit changelog entries to save on download time.
  1. --deltas --oldpackagedirs, this creates delta information, to save on download time. Clients must have yum-presto installed to take advantage of this data.

More Advanced options

  1. createrepo --update: Sometimes you have a lot of packages in your repsitory and regenerating the meta data for each package when only a few packages have been added or changed is just too time consuming. This is where --update comes in handy. You run createrepo just like you did before but you pass the --update flag to it. Like this:

      createrepo --update /srv/my/repo

Now, createrepo will only update the items which have been changed, been added or been removed since the last time the meta data was generated.

  1. createrepo -x package_file_name: Suppose you have a few packages in your repository directory but you really don't want the unsuspecting world to see them. You can exclude packages easily with createrepo:
      createrepo -x filename -x filename2 -x filename* /srv/my/repo
  1. You can sign a repository after it has been created by running:
    gpg --detach-sign --armor repodata/repomd.xml 

This will create a repomd.xml.asc file in the repodata directory which for modern versions of yum this will allow yum to verify that the repository metadata came from the owner of the gpg key.

  1. You can change the internal checksum used
     createrepo --checksum /srv/my/repo

This should only be needed if you are creating the repodata on a machine with a newer version of python than on the clients (or one with python-hashlib installed).

If you want to learn more about using createrepo to create and maintain your own package repository please see the createrepo man page or the other documents in this collection.