Skip to content

Distributions Reference

A distribution in Repod maps to a target operating system release. When you upload a package, you assign it to a distribution. Packages are only visible to clients (apt, dnf, zypper, apk) configured for that specific distribution.

Which distributions are available depends on REPO_FORMAT (apt, rpm, apk, both, or all) — see Getting Started — Step 2.


APT distributions (.deb)

Active when REPO_FORMAT is apt, both, or all.

Codename OS Architecture Component
jammy Ubuntu 22.04 LTS amd64 main
noble Ubuntu 24.04 LTS amd64 main
focal Ubuntu 20.04 LTS amd64 main
bookworm Debian 12 amd64 main

APT repository structure

For each distribution, reprepro manages the following tree under /repos/dists/, served by depot-apt:

/repos/dists/
└── jammy/
    ├── InRelease          ← GPG-signed index (verified by apt clients)
    ├── Release
    ├── Release.gpg
    └── main/
        ├── binary-amd64/
        │   ├── Packages
        │   ├── Packages.gz
        │   └── Packages.xz
        └── Contents-amd64.gz

APT client configuration

# Import the signing key
curl -fsSL http://YOUR_HOST:80/repos/gpg.key \
  | gpg --dearmor \
  | sudo tee /etc/apt/trusted.gpg.d/repod.gpg > /dev/null

# Add the source
echo "deb http://YOUR_HOST:80/repos jammy main" \
  | sudo tee /etc/apt/sources.list.d/repod.list

sudo apt update

RPM distributions (.rpm)

Active when REPO_FORMAT is rpm, both, or all.

Codename OS Architecture Package manager Grype distro ID
almalinux8 AlmaLinux 8 x86_64 dnf almalinux:8
almalinux9 AlmaLinux 9 x86_64 dnf almalinux:9
rocky8 Rocky Linux 8 x86_64 dnf rockylinux:8
rocky9 Rocky Linux 9 x86_64 dnf rockylinux:9
centos-stream9 CentOS Stream 9 x86_64 dnf centos:9
oraclelinux8 Oracle Linux 8 x86_64 dnf oraclelinux:8
fedora Fedora 42 x86_64 dnf fedora:42
opensuse-leap-15.6 openSUSE Leap 15.6 x86_64 zypper opensuse/leap:15.6
opensuse-tumbleweed openSUSE Tumbleweed (rolling) x86_64 zypper opensuse/tumbleweed:latest

Grype distro ID

The Grype distro ID is the identifier passed to grype when scanning a package for that distribution. It determines which CVE advisories are considered relevant — a CVE patched in AlmaLinux 9 may still be open in AlmaLinux 8, so the distro ID ensures accurate matching.

RPM repository structure

For each distribution, createrepo_c manages the following tree under /repos/rpm/, served by depot-rpm:

/repos/rpm/
└── almalinux9/
    └── x86_64/
        ├── repodata/
        │   ├── repomd.xml            ← Main index
        │   ├── repomd.xml.asc        ← GPG detached signature
        │   ├── primary.xml.gz        ← Package metadata
        │   ├── filelists.xml.gz
        │   └── other.xml.gz
        └── *.rpm                     ← Package binaries

DNF / YUM client configuration

/etc/yum.repos.d/repod.repo
[repod-almalinux9]
name=Repod Private Repository — AlmaLinux 9
baseurl=http://YOUR_HOST:8080/repos/almalinux9/x86_64/
enabled=1
gpgcheck=1
gpgkey=http://YOUR_HOST:8080/repos/gpg.key
repo_gpgcheck=0
sudo rpm --import http://YOUR_HOST:8080/repos/gpg.key
sudo dnf makecache

Zypper client configuration (openSUSE)

sudo zypper addrepo \
  --gpgcheck \
  http://YOUR_HOST:8080/repos/opensuse-leap-15.6/x86_64/ \
  repod

sudo rpm --import http://YOUR_HOST:8080/repos/gpg.key
sudo zypper refresh repod

APK distributions (Alpine .apk)

Active when REPO_FORMAT is apk or all.

Codename OS Architecture
alpine3.18 Alpine Linux 3.18 x86_64
alpine3.19 Alpine Linux 3.19 x86_64
alpine3.20 Alpine Linux 3.20 x86_64
alpine3.21 Alpine Linux 3.21 x86_64

APK repository structure

apk index manages the following tree under /repos/apk/, served by depot-apt under /apk/:

/repos/apk/
└── alpine3.20/
    └── main/
        └── x86_64/
            ├── APKINDEX.tar.gz    ← Signed package index
            └── *.apk              ← Package binaries

APK client configuration

# Import the signing key
curl -fsSL http://YOUR_HOST:80/apk/repod.rsa.pub \
  -o /etc/apk/keys/repod.rsa.pub

# Add the repository
echo "http://YOUR_HOST:80/apk/alpine3.20/main" \
  | sudo tee -a /etc/apk/repositories

sudo apk update

Adding a distribution

Distributions are initialized automatically at first startup (auto_init_distributions()), for every format enabled by REPO_FORMAT. To re-initialize manually (e.g. after restoring a backup without the on-disk distribution trees):

curl -X POST http://localhost:8000/api/v1/distributions/init \
  -H "Authorization: Bearer $TOKEN"

Modifying the supported codename list

The codenames above are hard-coded in services/distributions_apt.py, services/distributions_rpm.py, and services/distributions_apk.py. Adding an unsupported codename requires editing the relevant source file and rebuilding the backend-api image, then calling /api/v1/distributions/init. This is intentional — it prevents accidental distribution sprawl in production.


Distribution promotion

Repod supports promoting a package from one distribution to another without re-uploading or re-scanning — the CVE decision and justification are preserved. The promotion endpoint copies the package binary and re-runs reprepro includedeb (APT), createrepo_c --update (RPM), or rebuilds APKINDEX.tar.gz (APK) in the target distribution.

curl -X POST http://localhost:8000/api/v1/distributions/promote \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"package":"mypackage","from_dist":"jammy","to_dist":"noble"}'

Role required

Promotion requires the maintainer or admin role.


Distribution migration

To migrate all packages from one distribution to another (useful when upgrading your OS baseline):

curl -X POST http://localhost:8000/api/v1/distributions/migrate \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"from_dist":"focal","to_dist":"jammy"}'

Migration does not remove the source

The source distribution remains intact after migration. Remove packages manually if needed.