Use RPM package collections to build self-contained, portable application bundles that run across different Linux distributions without depending on system libraries.
← Back to Main PageModern applications often need to run across multiple Linux distributions, each with different versions of system libraries. Package collections provide a solution by bundling variable dependencies with your application.
A portable application is one that can run on multiple Linux distributions without modification. It achieves this by:
Standard RPM packages installed to /usr are ideal when:
Limitation: Different distributions may have incompatible library versions, making cross-distribution deployment difficult.
Self-contained collections in /opt are ideal when:
Benefit: Works across any distribution with compatible glibc, giving you maximum portability.
Let's build a Python application that needs Python 3.12 and several libraries, deployable across Fedora, RHEL, Ubuntu, and Debian.
Your application requires:
Target distributions: Fedora 39+, RHEL 9, Ubuntu 22.04+, Debian 12+
Using rpm-build-assist with the package-collection type:
# build-assist.yaml
base: fedora-43-x86_64
build:
- type: dist-git
url: https://src.fedoraproject.org/rpms/
packages:
- python3.12:release-3.12
- python3.12-pip:release-24.0
- python3.12-numpy:release-1.26
- python3.12-pandas:release-2.1
- type: git
url: https://github.com/myorg/myapp.git
packages:
- myapp:main
install:
type: package-collection
collection: myapp
prefix: /opt/myapp
packages:
- python3.12
- python3.12-pip
- python3.12-numpy
- python3.12-pandas
- myapp
The package-collection build creates a self-contained directory structure:
/opt/myapp/
├── bin/
│ ├── python3.12 # Python interpreter
│ ├── pip3.12 # Package installer
│ └── myapp # Your application
├── lib/
│ ├── libpython3.12.so # Python runtime library
│ └── python3.12/ # Python standard library
│ └── site-packages/ # Installed packages
│ ├── numpy/
│ ├── pandas/
│ └── myapp/
└── share/
└── myapp/ # Application data
Key feature: All executables in /opt/myapp/bin have rpath set to find libraries in /opt/myapp/lib automatically.
rpath (runtime path) is an ELF binary attribute that tells the dynamic linker where to find shared libraries. When building a package collection, rpm-build-assist automatically:
Example rpath in /opt/myapp/bin/python3.12:
$ readelf -d /opt/myapp/bin/python3.12 | grep RPATH
0x000000000000000f (RPATH) Library rpath: [/opt/myapp/lib]
The package collection includes:
The RPM spec files control this split:
# In python3.12.spec
BuildRequires: gcc, make, openssl-devel
Requires: glibc >= 2.34
# Does NOT require specific system Python
# Collection build includes python3.12 and its libs
# Runtime only requires compatible glibc (available everywhere)
The resulting package collection can be distributed as:
Users can run your application simply:
# After extracting to /opt/myapp
$ /opt/myapp/bin/myapp
# Or add to PATH
$ export PATH="/opt/myapp/bin:$PATH"
$ myapp
Package collections excel when you need to bundle multiple interdependent components.
Build a complete web application stack with specific versions:
# build-assist.yaml
base: fedora-43-x86_64
build:
- type: dist-git
url: https://src.fedoraproject.org/rpms/
packages:
- nodejs:release-20
- postgresql:release-16
- nginx:release-1.25
- type: git
url: https://github.com/myorg/
packages:
- myapp-frontend:main
- myapp-backend:main
- myapp-database:main
install:
type: package-collection
collection: myapp-stack
prefix: /opt/myapp-stack
packages:
- nodejs
- postgresql
- nginx
- myapp-frontend
- myapp-backend
- myapp-database
This creates a complete, portable application stack at /opt/myapp-stack with:
Approach: Compile all dependencies into the executable.
Advantages:
Disadvantages:
Approach: Distribution-specific packaging formats.
Advantages:
Disadvantages:
Approach: Bundle application with entire userspace.
Advantages:
Disadvantages:
Approach: Bundle variable dependencies with rpath.
Advantages:
Disadvantages:
Include in your package collection:
Rely on system packages for:
Why: Bundling too much increases size and can cause compatibility issues with system-level features.
Before distributing your package collection:
ldd that bundled executables find their librariesrpm -qpR