From Fedora Project Wiki

Koji maintains repositories of various content types to assist with quickly creating consistent build environments. This page assumes you have read the [use guides] The supported content types today are:

  • RPMs (via yum repositories)
  • Java Artifacts (via Maven repositories)


All repositories are kept under the /mnt/koji/repos directory on shared storage. They are maintained by the Kojira service, which is responsible for regenerating them as needed when the content of a build tag changes (including inheritance changes), and for deleting them when they become stale.

All repositories are associated with a (build) tag, which in turn is associated with a target. Therefore, all Koji targets have a yum repository associate with them. Each one has a single repository that is marked as READY in the database, and those that were created earlier (chronologically) are marked as EXPIRED. Once a repository has been expired long enough, Kojira comes along to delete it from the filesystem and mark it DELETED in the database.

Kojira is a standard service that can be started and stopped as necessary, but leaving it running is the recommended practice. Configuration is controlled in the /etc/kojira/kojira.conf. Like the other Koji services it needs auth configuration set up before it can function, and details about that are in the Run Your Own Koji Build Server page. The two options we will cover here control the lifetimes of the repositories when they are marked EXPIRED.

deleted_repo_lifetime controls the expiry time for unsigned repositories, which are used for normal builds. It accepts a value in seconds, and the default is one week's worth. (604800) Ergo, repositories sit in the EXPIRED state for one week before Kojira deletes them for good.

signed_repo_lifetime controls the expiry time for signed repository of RPM content. These are a new feature in Koji designed to make building images and containers with signed RPMs easier. Like the previous option, the default is one week's worth of seconds.

Manually Creating Repositories

Koji users with the repo permission (or admins) can create repositories manually. To create an unsigned repository (suitable for building RPMs, Maven artifacts, or images for the sake of testing), use the regen-repo command:

$ koji regen-repo <tag>

A few other options are available to this command that generate repositories for source RPMs and debuginfos. You can also specify a target rather than a tag. Pass in --help for more information.

Koji users with the signed permission (or admins) can create signed RPMs repositories as well. This is a new feature in Koji. Kojira does not do this automatically. Signed repositories are suitable for including in images, containers, or installation media. Like unsigned repositories only one is active per-tag, and older repositories will be swept up by Kojira. If you need to keep them for longer than the expiry time, you must copy them to another location.

Signed repositories are written to /mnt/koji/repo/signed. The command to generate one is:

$ koji signed-repo <tag> <keyID> [<keyID>...]

The keyIDs are given in order of preference, so if no RPM that is GPG signed with the first keyID indicated, the next will be searched for. There are many other options to control behaviors such as not failing if a no signed RPMs could be found or substituting unsigned RPMs if no signed RPMs can be found. You can also control content by setting architectures to consider, whether to use delta-rpms, considering inheritance, or enabling multilib. Use --help for more information.

Programmatically Finding Repositories

The Koji Hub API lets you dynamically find repositories if you know the tag you want and the repository ID. A short example follows. This output was captured in a Python shell.

>>> import koji
>>> k = koji.ClientSession('')
>>> k.getRepo('example-tag-fedora23', state=3)
{'create_event': 2670, 'creation_time': '2016-03-11 15:05:16.416925', 'signed': False, 'state': 3, 'create_ts': 1457726716.4169199, 'id': 1376}
>>> k.repoInfo(1384)
{'create_event': 2678, 'creation_time': '2016-03-11 16:24:06.389187', 'state': 3, 'tag_id': 22, 'tag_name': 'example-tag-fedora23', 'signed': True, 'id': 1384, 'create_ts': 1457731446.38919}

Signed repositories are written the following path: /mnt/koji/repo/signed/<tag>/<id>/<arch>. Unsigned follow the form: /mnt/koji/repo/<tag>/<id>/<arch>. Unsigned repositories also have a latest symlink that points to the latest ID.

The pathinfo object understands repositories both unsigned and signed. You will need to know the tag and repository ID you need though, using the calls indicated about.

>>> koji.pathinfo.repo(1387, 'example-tag-fedora23')
>>> koji.pathinfo.signedrepo(1387, 'example-tag-fedora23')

Note that pathinfo is dumb, it returns paths without calling to the hub or checking for their existence on the filesystem.