# 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](https://github.com/vmware/tdnf).
## Table of Contents
- [Setting Multiple Repositories in the User Template](#setting-multiple-repositories-in-the-user-template)
- [Package Conflict Priority Consideration](#package-conflict-priority-consideration)
- [Priority Rules](#priority-rules)
- [Resolution Process](#resolution-process)
- [Conflict Resolution Examples](#conflict-resolution-examples)
- [Example 1: Different versions across repositories](#example-1-different-versions-across-repositories)
- [Example 2: Same version in multiple repositories](#example-2-same-version-in-multiple-repositories)
- [Example 3: Mixed scenario](#example-3-mixed-scenario)
- [Dependencies Package](#dependencies-package)
- [Dependency Resolution in a Multi-Repository Environment](#dependency-resolution-in-a-multi-repository-environment)
- [Dependency Resolution Rules](#dependency-resolution-rules)
- [Dependency Resolution Examples](#dependency-resolution-examples)
- [Example 1: Parent package with dependencies](#example-1-parent-package-with-dependencies)
- [Example 2: Transitive dependencies](#example-2-transitive-dependencies)
- [Example 3: Fallback to base repository](#example-3-fallback-to-base-repository)
- [Example 4: Unresolvable dependency](#example-4-unresolvable-dependency)
- [Example 5: Conflicting dependency versions](#example-5-conflicting-dependency-versions)
- [Benefits of Repository Affinity](#benefits-of-repository-affinity)
- [AllowPackages White List](#allowpackages-white-list)
- [Architectural Design](#architectural-design)
- [Single Repository Support](#single-repository-support)
- [Multiple Repositories Support](#multiple-repositories-support)
- [Multiple Repository Flow](#multiple-repository-flow)
- [Related Documentation](#related-documentation)
## Setting Multiple Repositories in the User Template
You can specify additional package repositories in the OS Image Composer user
template. Here's an example:
```yaml
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:
1. **Higher numeric priority wins**: repositories with higher `priority`
values are preferred.
2. **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).
3. **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 repository
- `priority = 990`: prefer over default repos
- `priority = 1000`: install even if version is lower
- `priority > 1000`: force preference
### Resolution Process
Decision Flow:
1. Gather all matching candidates across configured repositories.
2. Apply repository `priority` rules.
3. Apply version constraints from dependency metadata.
4. 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.0`
- repoB (`priority: 500`) contains: `curl-8.0.1`
- **Result**: repoA candidate is preferred because repository priority is
higher.
#### Example 2: Same version in multiple repositories
- repoA (`priority: 900`) contains: `mypackage-1.0.0`
- repoB (`priority: 900`) contains: `mypackage-1.0.0`
- **Result**: 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.0`
- repoB (`priority: 500`) contains: `testpackage-1.5.0`
- **Result (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
1. **Repository Affinity**: Dependencies are always pulled from the same
repository as their parent package, regardless of newer versions available
in other repositories.
2. **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.
3. **Conflict Prevention**: This approach prevents version mismatches and
compatibility issues that could arise from mixing dependencies across
different repositories.
4. **Single Version Enforcement**: If different packages require different
versions of the same dependency (e.g., package A needs `libtest=0.1` and
package B needs `libtest=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.0` depends on: `libssl-1.1.0` and `libcrypto-1.1.0`
- Base repo contains: `libssl-1.2.0` (newer version)
- intel1 repo contains: `libssl-1.1.0` and `libcrypto-1.1.0`
- **Result**: The tool pulls `libssl-1.1.0` and `libcrypto-1.1.0` from intel1
repo (same as parent).
##### Example 2: Transitive dependencies
- User specifies: `customtools-1.0.0` (from intel2 repo)
- `customtools-1.0.0` → depends on `libxml-2.0.0` (from intel2)
- `libxml-2.0.0` → depends on `zlib-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.0` depends on `missinglib-1.0.0`
- `missinglib-1.0.0` not available in intel1 repo but exists in base repo
- **Result**: The tool pulls `specialpackage-1.0.0` from intel1 repo and
`missinglib-1.0.0` from the base repo (fallback rule).
##### Example 4: Unresolvable dependency
- User specifies: `anotherpackage-2.0.0` (from intel2 repo)
- `anotherpackage-2.0.0` depends on `unknownlib-3.0.0`
- `unknownlib-3.0.0` not available in any repository
- **Result**: 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 on `libtest=0.1`)
- User also specifies: `packageB-2.0.0` (depends on `libtest=0.2`)
- **Result**: The tool fails with an error—multiple versions of `libtest`
cannot be installed in parallel. You must resolve the conflict by choosing
compatible packages.
- **Alternative Solution**: If both versions of `libtest` are required, you
can package each version under a unique package name, such as `libtest01`
and `libtest02`. 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:
```mermaid
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
(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
```mermaid
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
(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.
## Related Documentation
- [Understanding the Build Process](./os-image-composer-build-process.md)
- [Understanding Templates](./os-image-composer-templates.md)
- [Multiple Package Repository Support](./os-image-composer-multi-repo-support.md)
- [OS Image Composer CLI Reference](./os-image-composer-cli-specification.md)