Image Configuration Reference
Complete reference for configuring container images via properties.yml.
properties.yml Overview
Each image can have custom settings via a properties.yml file. This reference documents all
available configuration options.
Minimal example:
---
rpm_packages:
all:
- nginx
main_package: nginx
tags:
- value: latest
Complete structure:
---
# Distro configuration (see Image Variants section)
# distros: [hummingbird] # Override default distros (use when package unavailable in some distros)
# Image variants (see Image Variants section)
# Use additional_variants to extend defaults, or variants to override completely
additional_variants: [fpm, fpm-builder] # Adds to default variants
# variants: [default, builder] # Alternative: completely replaces defaults
# Container runtime configuration (see Container Configuration section)
user: default # Optional: 'default' for default_user (65532), or literal user ID/name
# Package management (see Package Management section)
rpm_packages:
build-deps: [...]
all:
- package-name # All architectures
- name: arch-specific-package # Arch-specific (see Package Management)
arches:
only: x86_64
<distro>: [...]
<variant>: [...]
additional_repos: [...]
allow_fedora_repos: true # Optional: allow Fedora repos for hummingbird images (temporary workaround)
# Build configuration (see Build Configuration section)
hermetic: false
build_from_source: true
prefetch_gomod_path: xcaddy-upstream
# Versioning (see Versioning section)
main_package: package-name
# version_package: # Optional: override package for version lookup per variant/distro
# fips: package-fips-name # Example: variant-specific package name
# Testing configuration (see Testing Configuration section)
reverse_dependency_tests: false # Optional: disable for images like curl
# Release configuration (see Release Configuration section)
repository: image-name # Required: Quay.io repository name
# <reasoning for stream choice>
stream: "latest" # Required: version series identity for the image catalog
application_category: "Storage" # Required: Pyxis application category
# supported-by: community # Optional: community-supported image (default: Red Hat supported)
# Image metadata (see Image Metadata section)
summary: "Short one-liner description" # Required when adding labels
description: >- # Required when adding labels
Short paragraph describing the image.
1-2 sentences about key features.
url: "https://upstream-project.org" # Required when adding labels
tags:
- value: latest
- value: '{{ package_major_version("package-name") }}'
label: io.hummingbird-project.major-version
Image Metadata
Images can declare metadata fields for container image labels:
summary
- Type: String
- Required: When adding image labels (currently caddy only, expanding to all)
- Length: ~40-80 characters (one-liner)
Short phrase describing what the image is. Used in table/list views and catalog cards.
Do not start with the image name – the name is always visible from context
(UI headings, name label, inspect output).
Example: "Web server with automatic HTTPS"
description
- Type: String (use
>-YAML scalar for multi-line readability) - Required: When adding image labels
- Length: ~100-250 characters (1-2 sentences)
Short paragraph for card views, podman inspect, and Kubernetes UIs
(io.k8s.description). Describes what the software is and its key
distinguishing features.
Use >- (folded scalar) in YAML to keep the
value readable across multiple lines – it folds to a single-line string. Do not
use | (literal block) as embedded newlines break label syntax.
Avoid embedded double quotes and backslashes – values are emitted as-is in Containerfile LABEL instructions with no escaping.
The same description value is used when generating the image README: the
readme_description() macro in README.md.j2 templates renders it as the
introductory paragraph. Do not duplicate this text in the template; use
{{ readme_description() }}.
Example:
description: >-
Extensible server platform with automatic HTTPS by default.
Provides HTTP/3, reverse proxying, load balancing, and static
file serving with minimal configuration.
url
- Type: String (URL)
- Required: When adding image labels
URL for the upstream project homepage. Used in
org.opencontainers.image.url and the Conforma url label.
Example: "https://caddyserver.com"
Image Variants
Images can have multiple variants (e.g., default and builder):
- default: Minimal runtime environment
- builder: Includes development tools and build dependencies
- custom: Define custom variants in
properties.yml
Each variant gets its own:
- Containerfile in
images/<name>/<variant>/Containerfile - RPM lockfiles in
images/<name>/<variant>/rpms - Build pipeline and release tags (non-default variants get
-<variant>suffix)
variants
- Type: Array of strings
- Default:
[default, builder] - Description: List of image variants to generate. Completely overrides the default variants.
Each variant gets its own Containerfile, lockfiles, build pipeline, and release tags. Non-default
variants get a
-<variant>suffix in their image tags. - Example:
[default](CI images that only need the default variant) - Note: Prefer
additional_variantswhen extending defaults; usevariantsonly when you need to exclude default variants.
additional_variants
- Type: Array of strings or objects
- Default: None
- Description: Additional variants to add to the base variants. The base is
variantsif specified, otherwise the default variants. Use this when you want to extend without repeating.
Simple format (string array):
additional_variants: [fpm, fpm-builder] # Adds FPM variants to base variants for all distros
Object format with distro restrictions:
Each variant can be an object with name and optional distros fields to restrict which distros
the variant is built for:
additional_variants:
- name: fips
distros: [hummingbird] # Only build fips variant for hummingbird distro
- name: fpm # Simple string still works in array
- name: fpm-builder
distros: [hummingbird, rawhide] # Build for specific distros
The distros field supports glob patterns:
additional_variants:
- name: fips
distros: ["*bird"] # Matches hummingbird
- name: special
distros: ["raw*"] # Matches rawhide
When to use distro restrictions:
Use distro restrictions when a variant requires packages or features only available in specific distros. For example, FIPS variants may only be available for Hummingbird where FIPS-validated packages are present
variant_descriptions
- Type: Object (string-to-string mapping)
- Required: When image has
descriptionand definesadditional_variantswith non-default base specializations - Description: Maps base variant names to human-readable descriptions. These descriptions are
emitted as the
io.hummingbird-project.variant.descriptionlabel on each container image. The global description fordefaultis defined inimages/variables.yml; image-specific entries add descriptions for bases likefpm,runtime, oropenssl. Modifier display (builder, fips) is handled by catalog consumers using the boolean variant labels, not by these descriptions.
Writing guidelines:
- Describe the variant holistically — what the image variant is, not just what packages it
adds on top of
default. Someone reading the description with no surrounding context (e.g., viapodman inspect) should understand the variant’s identity. - Use a noun phrase (2-6 words), not a full sentence.
- Do not start with the image name (the image context is already provided by the image name label).
- Avoid the word “runtime” in the
defaultdescription (the OpenJDKruntimevariant is a separate base, and OpenJDK’sdefaultincludes the full JDK). - Avoid expanding abbreviations redundantly (e.g., “JRE runtime” is redundant because JRE already means “Java Runtime Environment”).
- Prefer functional descriptions (what capability the variant provides) over repeating the variant name as a product name.
Example (PHP image with FPM base):
variant_descriptions:
fpm: "PHP FastCGI process manager"
Example (OpenJDK image with runtime base):
variant_descriptions:
runtime: "Headless Java runtime"
distros
- Type: Array of strings
- Default:
[rawhide, hummingbird](fromimages/variables.yml) - Description: List of distros to build for this image. Overrides the global
default_distros. Use this to disable a distro for images where a required package is not available in that distro. - Example:
[hummingbird]disables Rawhide builds for this image - Note: Each enabled distro creates a full set of variants, so the final combinations are distros × variants.
Container Configuration
user
- Type: String, integer, or object (per-variant dict)
- Required: No (defaults to
default) - Description: Specifies which user the container runs as. The
USERdirective is rendered via the{{ set_user() }}macro at the end of Containerfile templates. The special (and default) valuedefaultmaps to thedefault_uservariable (UID 65532). Foruser: default, the{{ final_stage() }}macro setsHOME=/tmpandWORKDIR /tmpearly in the image to ensure unprivileged users have a writable default environment. Images can overrideWORKDIRlater in their Containerfile.j2. For builder variants withuser: default, it additionally setsENV CONTAINER_DEFAULT_USER=65532.
Same user for all variants:
user: default
user: root # Root user
user: postgres # Literal username
Per-variant configuration:
Use when different variants need different users:
user:
default: root
builder: root
fpm: default
fpm-builder: default
Package Management
Packages are defined in properties.yml under rpm_packages:
rpm_packages:
build-deps: # Build-time dependencies (installed in builder layer, not in final
# image). Included in lockfiles for hermetic builds.
- golang # Example: Go compiler for building from source
- rpm-build # Example: Tools for building RPMs during image construction
all: # Included in all variants (Containerfiles and lockfiles)
- coreutils-single
- your-main-package
- name: grub2-efi-x64 # Arch-specific: only on x86_64
arches:
only: x86_64
- name: grub2-efi-aa64 # Arch-specific: only on aarch64
arches:
only: aarch64
hummingbird: # Included in all Hummingbird variants (distro-level key)
- versioned-package-1.2
rawhide: # Included in all Rawhide variants (distro-level key)
- unversioned-package
builder: # Included only in "builder" variant
- compiler-packages
- debug-tools
custom-variant: # Included only in "custom-variant" variant
- variant-specific-packages
Package entry format
Each entry in an rpm_packages list can be either a string (installed on all architectures) or
an object with architecture constraints:
String entry (all architectures):
- coreutils-single
Object entry (arch-specific):
- name: grub2-efi-x64
arches:
only: x86_64 # Install only on x86_64
- name: some-package
arches:
not: aarch64 # Install on all architectures except aarch64
The arches.only and arches.not fields accept either a single string or a list of strings.
Supported architectures: aarch64, x86_64.
How arch-specific packages work:
- Lockfiles: Arch-specific entries are passed to rpm-lockfile-prototype using its native per-arch package format. The lockfile resolver only includes matching packages for each architecture.
- Containerfiles: Arch-specific packages are installed via a
casestatement onTARGETARCH, so the correct packages are installed during multi-arch builds.
rpm_packages.build-deps
- Type: Array of strings or arch-specific objects
- Description: Build-time dependencies needed during image construction. Automatically installed in the builder layer (not in the final image) and included in lockfiles for hermetic builds. Use for compilers, build tools, and other packages needed only during the build process.
rpm_packages.all
- Type: Array of strings or arch-specific objects
- Description: Packages included in all variants, in both Containerfiles and lockfiles
rpm_packages.<distro>
- Type: Array of strings or arch-specific objects
- Description: Packages included in all variants for the specified distro. Useful when different distros ship different package names (e.g. versioned vs unversioned) and the packages should apply to every variant within that distro.
rpm_packages.<variant>
- Type: Array of strings or arch-specific objects
- Description: Packages included only in the specified variant, regardless of distro
additional_repos
- Type: Array of strings (repository filenames)
- Default: None
- Description: Additional yum repository files from
yum-repos/to include in the RPM lockfile generation. These repos are added to the variant-specific repos (see [Global Variables Reference- default_variant_repos]default-variant-repos). Specify only the filename, not the full path.
- Example:
[konflux-ci-rpm-lockfile-prototype-main-fedora-rawhide.repo] - Usage: Only needed for packages not available in standard Fedora repos or variant-specific repos
allow_fedora_repos
- Type: Boolean
- Default:
false - Description: Allow Fedora repositories during lockfile generation for Hummingbird production
images. By default, production Hummingbird images exclude Fedora repos to ensure packages come
only from the Hummingbird repository. Set to
trueto temporarily allow Fedora repos when required packages are not yet available in the Hummingbird repository. - Example:
true - Usage: Typically used temporarily for packages not yet built for Hummingbird (e.g., .NET runtime on x86_64, OpenJDK packages). Should be removed once packages are available in the Hummingbird repository.
- Note: CI images (in
ci/images/) always have access to Fedora repos regardless of this setting, as they requirefedora-gpg-keysfor signature validation.
Hermetic Builds
For hermetic builds (enabled by default), all packages from:
rpm_packages.build-deps- included in lockfiles and Containerfiles (builder layer only)rpm_packages.all- included in lockfiles and Containerfiles (final image)rpm_packages.<distro>- included in lockfiles and Containerfiles for all variants of a distrorpm_packages.<variant>- included in lockfiles and Containerfiles for matching variantsdefault_rpm_packages.builder- automatically added for builder variants (see Global Variables Reference - default_rpm_packages)
are added to rpms.lock.yaml and prefetched using cachi2 for offline builds.
Build-time vs Runtime Packages:
rpm_packages.build-deps: Installed in the builder layer only (not in final image)rpm_packages.all: Installed in${NEWROOT}(the final image)rpm_packages.<distro>: Installed in${NEWROOT}for all variants of the specified distrorpm_packages.<variant>: Installed in${NEWROOT}for the specified variant
Build Configuration
hermetic
- Type: Boolean
- Default:
true - Description: Controls whether the Konflux build pipeline passes
HERMETIC=trueto the buildah task, enabling hermetic (offline, network-isolated) builds with prefetched dependencies. - Important: Images with
hermetic: falseare blocked from release by the Conforma hermetic_task policy. Only usehermetic: falsefor non-production images inci/images/.
build_from_source
- Type: Boolean
- Default:
false - Description: Controls version extraction in the
package_version()macro. Whentrue, extracts version from.gitmodulesfor images built from git submodules. Whenfalse, extracts version from RPM package metadata. Does not control whether source code is compiled in the Containerfile.
prefetch_gomod_path
- Type: String (path relative to image directory)
- Default: None
- Description: Path to a Golang project directory (typically a git submodule) for prefetching Go
modules via cachi2. Enables hermetic builds for Go projects without a vendor tree. The path is
relative to the image directory (e.g.,
xcaddy-upstreamforimages/xcaddy/xcaddy-upstream). - Example:
xcaddy-upstream - Usage: Only needed for images that build Go projects from source
Versioning
main_package
- Type: String
- Description: Specifies the main package for version labeling
For RPM-based images:
Set to the package name. Version is extracted from RPM package metadata.
main_package: nginx
For source-built images:
Set to the submodule path. Version is extracted from the branch field in .gitmodules.
main_package: images/xcaddy/xcaddy-upstream
build_from_source: true
Example .gitmodules entry:
[submodule "images/xcaddy/xcaddy-upstream"]
path = images/xcaddy/xcaddy-upstream
url = https://github.com/caddyserver/xcaddy
branch = v0.4.5
version_constraints
- Type: String (glob pattern)
- Default: None (no constraints)
- Description: Defines a version constraint pattern to prevent unwanted major or minor
version updates. The constraint applies to all distros for this image. Constraints are validated
during
make check, and builds fail if VERSION files violate the constraint. Primarily used for multi-version images (e.g., python-3-11, nodejs-20) to ensure they stay on their intended version family.
Constraint patterns:
Patterns use glob-style matching:
3.11.*- Match any 3.11.X version (recommended)20.*- Match any 20.X version8.*- Match any 8.X version1.25.*- Match any 1.25.X version (for 3-part versioning like Go)
The pattern matches against the content of VERSION files generated during the build process.
Example:
main_package: python3.11
version_constraints: '3.11.*' # Ensure python-3-11 stays on 3.11.X across all distros
main_package: dotnet-sdk-8.0
version_constraints: '8.*' # Applies to rawhide, hummingbird, and any other distros
When to use:
- Multi-version images where each image targets a specific version family
- Preventing automatic major/minor version bumps during Renovate updates
- Ensuring version tags remain accurate (e.g.,
python:3.11doesn’t becomepython:3.12)
Violation handling:
When a constraint is violated, make check fails with a detailed error message showing:
- The VERSION file path
- The actual version found
- The constraint that was violated
- The properties.yml file where the constraint is defined
Options for resolution:
- Create a new image for the new version (recommended for major/minor bumps)
- Exclude the violating version via
yum-repos/*.repoexcludepkgs - Update the constraint to allow the new version
See Version Constraints for detailed documentation.
version_package
- Type: Object (string-to-string mapping)
- Default: None
- Description: Override the package name used for version extraction on a per-distro, per-variant,
or per-distro/variant basis. When a variant or distro installs a different package that provides the
same software (e.g., a FIPS-enabled build), this field tells the version/tag macros which package
name to look up in the lockfile. The lookup order is:
distro/variant, thenvariant, thendistro, thenmain_package.
Per-variant override:
Use when a variant installs a differently-named package (e.g., FIPS variant):
main_package: golang1.25
version_package:
fips: golang-fips1.25 # fips variant resolves version from golang-fips1.25
Per-distro override:
Use when different distros ship the same software under different package names:
main_package: ruby
version_package:
hummingbird: ruby4.0 # hummingbird ships ruby4.0, rawhide ships ruby
Per-distro/variant override:
Use when both distro and variant affect the package name:
main_package: golang1.25
version_package:
hummingbird/fips: golang-fips1.25
Usage in templates:
The resolved package name is available as package_name_for_version in Jinja2 templates:
tags:
- value: '{{ package_version(package_name_for_version) }}'
label: org.opencontainers.image.version
ENV GOLANG_VERSION={{ package_version(package_name_for_version) }}
Testing Configuration
reverse_dependency_tests
- Type: Boolean
- Default:
true - Description: Controls whether this image participates in reverse dependency workflows (both
building and testing). When
true, changes to this image trigger rebuilds and tests of all images that depend on it. Dependencies are detected by searching forTEST_IMAGES[...]references in test scripts. Set tofalsefor images that should not trigger reverse dependency workflows when changed. - Example: Set to
falseforcurlto avoid triggering unnecessary reverse dependency tests
How it works in CI:
When an image is tested, the CI pipeline performs two phases:
-
Build Phase: Builds all dependencies needed for testing
- Uses
ci/build_images.sh --build-depsto build:- Forward dependencies (images the main image’s tests depend on)
- Reverse dependencies (images that depend on the main image, filtered by
reverse_dependency_tests: true) - Forward dependencies of those reverse dependencies
- Automatically deduplicates to ensure each image is built exactly once
- Uses
-
Test Phase: Runs tests on the main image and its reverse dependencies
- Uses
ci/run_tests_container.shandci/run_tests_k8s.shwith--include-reverse-depsto test:- The main image
- All reverse dependencies (filtered by
reverse_dependency_tests: true)
- Uses
Why set to false?
Set reverse_dependency_tests: false for images like curl that are:
- Used pervasively across many images (too many reverse dependencies)
- Have a small, stable API that can be fully tested in their own tests
- Would cause excessive CI load if every dependent image were tested on each change
Release Configuration
The repository and stream fields together define the release identity for an image. Both are
required and validated during CI. The repository specifies the Quay.io repository name, and the
stream specifies the version series within that repository.
repository
- Type: String
- Required: Yes
- Description: The Quay.io repository name for this image. For images where the directory name
matches the desired repository name (e.g.,
images/nginx/→repository: nginx), this is redundant but still required for explicitness. For versioned image directories, this groups multiple versions under one repository (e.g.,nodejs-20andnodejs-24both userepository: nodejs). - Example:
nodejs(used bynodejs-20andnodejs-24directories)
stream
- Type: String
- Required: Yes
- Description: The version series identity for this image within its repository. Emitted as
the
io.hummingbird-project.streamlabel on the container image, enabling the image catalog to provide consistent structured data about multi-stream repositories.
The stream value must reflect upstream’s actual branch structure at the granularity where parallel security-maintained branches exist. Use endoflife.date to determine the correct granularity.
Key rules:
- The stream is never derived from the image directory name. The directory name is not evidence
for stream granularity (e.g., a directory named
foo/for an upstream with branches2.8,3.0,3.2still requires a major.minor stream like"3.0"). - The purpose of upstream branches is irrelevant to granularity. Whether upstream calls them “LTS”, “stable”, “mainline”, or “STS” does not matter. If they are parallel branches receiving security updates, the stream granularity must match.
- Match the upstream project’s version naming convention. If the project identifies branches
as
8.0,9.0(not8,9), use that format even if endoflife.date abbreviates it. - Sequential minor versions are not parallel branches. If endoflife.date lists minor versions that each immediately supersede the previous with no support overlap, the minor is a release counter. Use the major version as the stream.
- Use
"latest"only for images where no meaningful version series identity exists: rolling-release tools with date-based versioning (e.g., minio) or base images that track the distro rather than independent software (e.g., core-runtime). - For unversioned images (no version in directory name, no version constraints), the stream value reflects the version currently shipped and must be updated when the upstream version changes.
See the stream assignment guidelines for the full decision process and rationale.
Document the reasoning for the stream choice as a YAML comment above the stream field.
This ensures future maintainers understand why a particular granularity was chosen.
Examples:
# endoflife.date: parallel at major (Docker Hub + Debian + Wolfi)
stream: "24"
# endoflife.date: parallel at major.minor (Docker Hub + Debian + Wolfi)
stream: "3.11"
# endoflife.date: branches are 10.1, 11.0, not 10, 11
stream: "10.1"
# rolling release with date-based versions, no version branches
stream: "latest"
application_category
- Type: String
- Required: Yes
- Description: The Pyxis application category for the image’s delivery repository. Emitted as
the
io.hummingbird-project.application-categorylabel on the container image and used in the generated Pyxis repo config. All images sharing the samerepositorymust use the same value. Validated duringmake checkagainst the list inci/application-categories.txt.
Common values for Hummingbird images:
"Programming Languages & Runtimes"– language runtimes and SDKs (Go, Python, Node.js, .NET, Ruby, etc.)"Web Services"– web servers, reverse proxies, and load balancers (Nginx, httpd, Caddy, HAProxy, Tomcat)"Database & Data Management"– databases and caches (PostgreSQL, MariaDB, Valkey, Memcached)"Developer Tools"– CLI utilities and build tools (git, curl, jq)"Storage"– object storage (MinIO, MinIO Client)"Operating System"– base runtime images (core-runtime)
Example:
application_category: "Web Services"
tags
- Type: Array of objects
- Description: Define image tags for Quay.io releases. Each variant gets these tags, with
non-default variants receiving a
-<variant>suffix.
Tag Object Fields:
value(required): The tag value. Can be a literal string (e.g.,latest) or a Jinja2 template using helper functions.label(optional): If specified, the tag value is written as aLABELin the Containerfile, and the actual rendered value from the label is used as the image tag. This ensures version tags match the actual package versions in the image.
Tag Helper Functions:
package_version("<package-name>")- Full version (e.g.,1.2.3-4.fc42)package_major_version("<package-name>")- Major version only (e.g.,1)package_major_minor_version("<package-name>")- Major.minor version (e.g.,1.2)
Example:
tags:
- value: latest # Literal tag, no label
- value: '{{ package_major_version("nginx") }}' # Template tag with label
label: io.hummingbird-project.major-version
- value: '{{ package_major_minor_version("nginx") }}' # Tag becomes actual version from label
label: io.hummingbird-project.major-minor-version
- value: '{{ package_version("nginx") }}'
label: org.opencontainers.image.version
Note: For images with multiple versions, only set latest on the latest version.
supported-by
- Type: String
- Default: Omitted (image is Red Hat supported)
- Description: Controls the support level and Konflux application assignment for
hummingbird-distro images. When set to
community, the image is assigned to thecontainers-ci-hummingbirdKonflux application, excluded from the Red Hat release pipeline, and labeled withio.hummingbird-project.supported-by: community. When omitted, the image is Red Hat supported and assigned tocontainers-hummingbird. Rawhide images are implicitly community-only and always assigned tocontainers-rawhideregardless of this property. - Example:
supported-by: community - Usage: Use for images that are not Red Hat supported, such as internal CI tooling or
community-maintained images. These images are built and tested normally but published only
to the
quay.io/hummingbird-ciregistry, not to the official Red Hat registry.
How Labels Work:
- Template is rendered and written to Containerfile:
LABEL org.opencontainers.image.version=1.27.3-1.fc42 - Build system extracts the actual value from the image label
- Image is tagged with the extracted value:
quay.io/hummingbird/nginx:1.27.3-1.fc42
This ensures tags always match the actual package versions built into the image.
Next Steps
- Adding Images - Step-by-step guide for adding new images
- Image Pipeline - How the complete pipeline works