Multiple Package Repo Support#
A major feature of the OS Image Composer tool is its ability to let you add multiple package repositories to the OS build. These repositories often contain in-house proprietary packages or upstream packages pending integration. By supporting multiple repositories, the tool enables rapid deployment, experimentation, and validation of custom software alongside standard OS components. This document describes the key aspects of the multiple package repo:
Configuration: Describes how to add and configure extra package repositories, enabling the OS Image Composer tool to access and pull custom packages that are unavailable in the base repository.
Package conflict priority consideration: Outlines how the tool determines which package to use when duplicates exist across repositories using per-repository
priority.Allow-list support: Describes
allowPackages(white list) to restrict which packages are indexed from a repository.Architectural design: Describes how the design extends the tool’s package and dependency pre-download framework to resolve dependencies without relying on package managers like APT or tdnf.
Table of Contents#
Setting Multiple Repositories in the User Template#
You can specify additional package repositories in the OS Image Composer user template. Here’s an example:
packageRepositories:
- codename: "repoA"
url: "https://repo.example.com/os/base"
pkey: "https://repo.example.com/keys/RPM-GPG-KEY"
priority: 1001
allowPackages:
- kernel-6.17.11
- kernel-drivers-gpu-6.17.11
- libva*
- wayland*
- codename: "repoB"
url: "https://repo2.example.com/os/extra"
pkey: "https://repo2.example.com/keys/RPM-GPG-KEY"
priority: 500
systemConfig:
packages:
- kernel-6.17.11
- libva-utils
- my-custom-package
Each repository must follow the standard Debian or RPM structure, including all required metadata. The OS Image Composer tool performs sanity checks to ensure repository URLs are valid before proceeding. See the following repository setup references:
Debian repo setup: https://wiki.debian.org/DebianRepository/Setup
RPM repo setup: https://wiki.centos.org/HowTos/CreateLocalRepos
Package Conflict Priority Consideration#
When multiple repositories contain packages with the same name, the OS Image
Composer tool uses repository priority to select candidates.
Priority Rules#
The OS Image Composer tool follows these rules:
Higher numeric priority wins: repositories with higher
priorityvalues are preferred.Version tie-breaker: when candidates are in the same priority class, the resolver picks the most suitable version (usually the newest one that satisfies constraints).
Repository affinity for dependencies: when possible, dependencies are chosen from the same repository family as the parent package.
Debian resolver supports additional APT-like priority behavior:
priority < 0: block packages from that repositorypriority = 990: prefer over default repospriority = 1000: install even if version is lowerpriority > 1000: force preference
Resolution Process#
Decision Flow:
Gather all matching candidates across configured repositories.
Apply repository
priorityrules.Apply version constraints from dependency metadata.
Select candidate with best priority/constraint fit; use repository affinity for transitive dependencies when available.
Conflict Resolution Examples#
Example 1: Different versions across repositories#
repoA (
priority: 1001) contains:curl-7.68.0repoB (
priority: 500) contains:curl-8.0.1Result: repoA candidate is preferred because repository priority is higher.
Example 2: Same version in multiple repositories#
repoA (
priority: 900) contains:mypackage-1.0.0repoB (
priority: 900) contains:mypackage-1.0.0Result: resolver uses tie-breakers (version/equivalent candidate and repository affinity when resolving dependencies).
Example 3: Mixed scenario#
repoA (
priority: -1, Debian/APT-based builds only) contains:testpackage-2.0.0repoB (
priority: 500) contains:testpackage-1.5.0Result (Debian/APT): repoA package is blocked due to APT’s negative-priority semantics; repoB package is selected.
Result (RPM-based): RPM tooling does not treat negative priorities as a hard block. For RPM-based builds, use non-negative priorities together with
allowPackages(or omit the repository) to prevent selection from a repo.
These priority semantics provide explicit control for pinning and preference in
multi-repo builds. Repository blocking via negative priority is a Debian/APT-
specific behavior; RPM-based builds should rely on priorities and allowPackages
for equivalent control.
AllowPackages White List#
allowPackages is an optional per-repository white list in
packageRepositories.
If omitted or empty, all packages from that repository metadata are eligible.
If provided, only matching package names are indexed from that repository.
Matching supports:
exact names (for example
spice-server)prefix/version pin patterns (for example
kernel-6.17.11)glob patterns (for example
libva*,wayland*)
This filtering happens during repository metadata parsing, before package matching and dependency resolution. It is useful for tightening repository scope and reducing accidental package selection.
Dependencies Package#
What are Dependencies? In simple terms, dependencies are other packages that a software package needs to work properly. Think of it like cooking a recipe: If you want to make a cake, you need ingredients like flour, eggs, and sugar. Similarly, when you install a software package, it often needs other software packages (dependencies) to function correctly.
Here are several examples: A web browser might depend on graphics libraries to display images; a media player might depend on codec packages to play different video formats; a database application might depend on networking libraries to communicate over the internet.
Dependency Resolution in a Multi-Repository Environment#
The OS Image Composer tool automatically resolves dependencies according to the rules below, ensuring package consistency by keeping parent packages and their dependencies from the same repository.
Dependency Resolution Rules#
Repository Affinity: Dependencies are always pulled from the same repository as their parent package, regardless of newer versions available in other repositories.
Fallback to Base Repository: If a dependency cannot be resolved within the same repository as the parent package (i.e., it was not found at all), the tool will attempt to resolve the dependency from the base OS repository.
Conflict Prevention: This approach prevents version mismatches and compatibility issues that could arise from mixing dependencies across different repositories.
Single Version Enforcement: If different packages require different versions of the same dependency (e.g., package A needs
libtest=0.1and package B needslibtest=0.2), the tool will fail with an error. Multiple versions of the same dependency cannot be installed in parallel.
Dependency Resolution Examples#
Example 1: Parent package with dependencies#
User specifies:
myapp-2.0.0(available in intel1 repo)myapp-2.0.0depends on:libssl-1.1.0andlibcrypto-1.1.0Base repo contains:
libssl-1.2.0(newer version)intel1 repo contains:
libssl-1.1.0andlibcrypto-1.1.0Result: The tool pulls
libssl-1.1.0andlibcrypto-1.1.0from intel1 repo (same as parent).
Example 2: Transitive dependencies#
User specifies:
customtools-1.0.0(from intel2 repo)customtools-1.0.0→ depends onlibxml-2.0.0(from intel2)libxml-2.0.0→ depends onzlib-1.2.5(available in base repo as 1.2.8 and intel2 as 1.2.5)Result: All dependencies (
libxml-2.0.0,zlib-1.2.5) are pulled from the intel2 repo.
Example 3: Fallback to base repository#
User specifies:
specialpackage-1.0.0(from intel1 repo)specialpackage-1.0.0depends onmissinglib-1.0.0missinglib-1.0.0not available in intel1 repo but exists in base repoResult: The tool pulls
specialpackage-1.0.0from intel1 repo andmissinglib-1.0.0from the base repo (fallback rule).
Example 4: Unresolvable dependency#
User specifies:
anotherpackage-2.0.0(from intel2 repo)anotherpackage-2.0.0depends onunknownlib-3.0.0unknownlib-3.0.0not available in any repositoryResult: The tool reports dependency resolution failure and suggests adding missing package to the relevant repository or using an alternative.
Example 5: Conflicting dependency versions#
User specifies:
packageA-1.0.0(depends onlibtest=0.1)User also specifies:
packageB-2.0.0(depends onlibtest=0.2)Result: The tool fails with an error—multiple versions of
libtestcannot be installed in parallel. You must resolve the conflict by choosing compatible packages.Alternative Solution: If both versions of
libtestare required, you can package each version under a unique package name, such aslibtest01andlibtest02. This approach allows both versions to co-exist and satisfy the dependencies for different packages.
Benefits of Repository Affinity#
Consistency: Ensures all related packages come from the same tested source.
Compatibility: Prevents version conflicts between interdependent packages.
Predictability: Identifies exactly which repository provides your complete package stack.
Maintainability: Simplifies troubleshooting when issues arise with custom packages.
This dependency-resolution strategy maintains package integrity while supporting the multi-repository architecture.
Architectural Design#
The design integrates with the tool’s package and dependency pre-download framework for a single repository and then extends it to support multiple packages.
Single Repository Support#
Here’s a quick description of the single repository model so you can envision how it extends to support multiple repositories, which are described in the next section.
The core concept of the single repository model is to build a metadata list of all available packages from a single repository, with this list only containing one repo metadata, and using it as a database of sorts to validate user package requests and resolve dependencies at each subsequence step. The high-level single repositiory flow proceeds like this:
graph TD
A[Base Repo Metadata] --> B(full package list)
C[User Package List] --> D{Check if user list is available?}
B -- Pass full list --> D
B -- Pass full list --> E[Resolve dependencies]
D -- Yes --> E
D -- No --> F[Throw Error: User list not found]
E --> G["Create full download list<br> (user packages + dependencies)"]
G --> H[Download packages]
H --> I[Validate package signatures]
Multiple Repositories Support#
The enhanced design extends the tool’s package and dependency pre-download framework to support multiple repositories. Instead of building a metadata list from a single source, the tool aggregates metadata from all the configured repositories into a unified package database. This consolidated list enables validation of user package requests and accurate dependency resolution across repositories. The high-level flow remains similar, but now operates on combined metadata to seamlessly support multiple repositories. The high-level flow is described below.
Multiple Repository Flow#
graph TD
subgraph Repo Metadata Sources
A[Base Repo Metadata]
B[Customer Repo Metadata 1]
C[Customer Repo Metadata 2]
end
subgraph Process
D(Full package list with multiple repos)
E[User Package List]
F{Check if user list is available?}
G[Resolve dependencies and version conflicting]
H["Create full download list<br> (user packages + dependencies)"]
I[Download packages]
J[Validate package signatures]
end
subgraph Error Handling
K[Throw Error: User list not found]
end
A --> D
B --> D
C --> D
E --> F
D -- Pass full list --> F
D -- Pass full list --> G
F -- Yes --> G
F -- No --> K
G --> H
H --> I
I --> J
Package manager independence is a key benefit of this design: The tool’s package downloading framework remains independent from third-party package managers, such as APT, DNF, and tdnf. The result delivers flexibility for non-traditional requirements and future customizations.