Overview
The Builder component consists of ephemeral machines (VMs or containers) that execute the actual package builds. The core tool is copr-rpmbuild, which handles:
Source package acquisition (from dist-git, URLs, etc.)
Mock chroot preparation
RPM/SRPM building
Build artifact collection
Live build log streaming
The copr-builder package has been deprecated and merged into copr-rpmbuild.
For historical reference, see the builder/ directory which now just points to the rpmbuild component.
Architecture
┌──────────────┐
│ Backend │ allocates builder via Resalloc
└──────┬───────┘
│
▼
┌────────────────────────────────────────┐
│ Builder Machine (VM) │
│ │
│ ┌──────────────────────────────────┐ │
│ │ copr-rpmbuild │ │
│ ├──────────────────────────────────┤ │
│ │ 1. Fetch sources │ │
│ │ 2. Setup mock chroot │ │
│ │ 3. Build SRPM (if needed) │ │
│ │ 4. Build RPMs │ │
│ │ 5. Collect results │ │
│ └──────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────┐ │
│ │ Mock Chroot │ │
│ │ (/var/lib/mock/...) │ │
│ │ │ │
│ │ - buildroot RPMs │ │
│ │ - build environment │ │
│ │ - rpmbuild execution │ │
│ └──────────────────────────────────┘ │
└─────────────────────────────────────────┘
Basic Usage # Build from task ID (fetches config from frontend)
copr-rpmbuild < build_i d > --chroot < chroot_nam e >
# Example
copr-rpmbuild 12345 --chroot fedora-39-x86_64
Common Options # Verbose output
copr-rpmbuild 12345 --chroot fedora-39-x86_64 --verbose
# Detached mode (background)
copr-rpmbuild 12345 --chroot fedora-39-x86_64 --detached
# Drop result directory after build
copr-rpmbuild 12345 --chroot fedora-39-x86_64 --drop-resultdir
# Enable networking in buildroot
copr-rpmbuild 12345 --chroot fedora-39-x86_64 --enable-net
# Custom timeout (seconds)
copr-rpmbuild 12345 --chroot fedora-39-x86_64 --timeout 7200
Build Process
1. Source Acquisition From DistGit :# Clone from dist-git
git clone http://copr-dist-git/git/@copr/project/package.git
cd package
# Download sources from lookaside
pkgname = $( rpmspec -q --qf '%{name}' * .spec )
wget http://copr-dist-git/repo/pkgs/@copr/project/ $pkgname /...
From URL :# Direct SRPM download
wget https://example.com/package.src.rpm
From Git + Tito :git clone https://github.com/user/package
cd package
tito build --srpm
2. Mock Preparation # Initialize mock chroot
mock -r < confi g > --init
# Install build dependencies from spec
mock -r < confi g > --installdeps package.src.rpm
# Configure mock with:
# - Additional repos (copr://, external URLs)
# - Build requires
# - Network settings (disabled by default)
# - Bootstrap image (if specified)
3. SRPM Build (if needed) # Build SRPM from spec + sources
mock -r < confi g > --buildsrpm \
--spec package.spec \
--sources .
4. RPM Build # Build binary RPMs from SRPM
mock -r < confi g > --rebuild package.src.rpm
5. Result Collection # Collect from mock result directory
cp /var/lib/mock/ < confi g > /result/ * .rpm ./results/
cp /var/lib/mock/ < confi g > /result/ * .log ./results/
# Generate results.json with metadata
cat > results/results.json << EOF
{
"packages": [
{"name": "package", "version": "1.0", "release": "1", ...}
],
"built_packages": ["package-1.0-1.fc39.x86_64.rpm", ...],
"source_package": "package-1.0-1.fc39.src.rpm"
}
EOF
Mock Configuration
Mock Config Customization
copr-rpmbuild generates mock config with Copr-specific settings: # Base config
config_opts[ 'root' ] = 'fedora-39-x86_64'
config_opts[ 'chroot_setup_cmd' ] = 'install @buildsys-build'
# Additional repositories
config_opts[ 'yum.conf' ] += """
[copr:repo1]
name=Copr repo
baseurl=https://copr-be.cloud.fedoraproject.org/results/@copr/project/fedora-39-x86_64/
gpgcheck=0
enabled=1
[external-repo]
name=External repository
baseurl=https://example.com/repo/
gpgcheck=1
enabled=1
"""
# Networking (disabled by default for security)
config_opts[ 'use_host_resolv' ] = False
config_opts[ 'rpmbuild_networking' ] = False
# Bootstrap image (optional)
config_opts[ 'bootstrap_image' ] = 'registry.fedoraproject.org/fedora:39'
# Isolation (nspawn, simple, or none)
config_opts[ 'isolation' ] = 'simple'
Build Results
Result Directory Structure
results/
├── package-1.0-1.fc39.src.rpm # Source RPM
├── package-1.0-1.fc39.x86_64.rpm # Binary RPM
├── package-devel-1.0-1.fc39.x86_64.rpm # Subpackage
├── build.log.gz # Full build log
├── backend.log.gz # Backend processing log
├── builder-live.log.gz # Live streaming log
├── root.log.gz # Mock root.log
├── state.log.gz # Mock state.log
├── results.json # Structured metadata
└── configs/ # Mock configs used
└── child.cfg
{
"packages" : [
{
"name" : "package" ,
"epoch" : 0 ,
"version" : "1.0" ,
"release" : "1.fc39" ,
"arch" : "x86_64"
}
],
"built_packages" : [
"package-1.0-1.fc39.x86_64.rpm" ,
"package-devel-1.0-1.fc39.x86_64.rpm"
],
"source_package" : "package-1.0-1.fc39.src.rpm" ,
"source_package_name" : "package" ,
"source_package_version" : "1.0-1.fc39"
}
Live Log Streaming
Real-time Build Monitoring
Builders stream build progress to backend: # Builder pushes log lines to backend
import requests
with open ( '/var/lib/mock/build.log' ) as f:
for line in f:
requests.post(
f ' { backend_url } /update' ,
data = { 'log' : line, 'build_id' : build_id}
)
Backend stores in Redis and serves via HTTP: # View live log
curl https://copr-be.cloud.fedoraproject.org/results/ \
@copr/copr-dev/fedora-39-x86_64/12345-package/builder-live.log
Builder Provisioning
Virtual Machines Managed by Resalloc with various providers: OpenStack (Nova) :# Resalloc pool configuration
pools :
x86_64 :
max : 20
max_starting : 5
max_prealloc : 2
tags :
- arch_x86_64
cmd_new : |
nova boot \
--flavor m1.large \
--image fedora-39 \
--key-name copr-builder \
builder-{id}
AWS EC2 :pools :
x86_64_aws :
max : 50
tags :
- arch_x86_64
- aws
cmd_new : |
aws ec2 run-instances \
--image-id ami-xxxxx \
--instance-type t3.large \
--key-name copr-builder
Containers Podman :pools :
x86_64_container :
max : 100
tags :
- arch_x86_64
- container
cmd_new : |
podman run -d \
--name builder-{id} \
--privileged \
quay.io/copr/copr-builder:latest
Builder Image
Builder images include:
mock - Build system
rpmbuild - RPM building
rpm-build - RPM creation
dnf or yum - Package manager
createrepo_c - Repository generation
Version Control
git - Git repositories
tito - Tag and build RPMs from git
rpkg - RPM packaging toolkit
Scripting
python3 - Python runtime
python3-copr-rpmbuild - Build orchestration
bash - Shell scripting
Networking
openssh-server - SSH access
rsync - File synchronization
curl, wget - File download
Build Requirements
Common build dependencies (gcc, make, etc.)
Language-specific tools (python3-devel, ruby-devel, etc.)
Security Considerations
Network Restrictions
Default : Networking disabled in buildroot
Rationale : Prevent untrusted code from accessing network
Override : --enable-net flag (requires user permission)
User Separation # Builds run as mockbuild user (UID 1000)
config_opts[ 'chrootuid' ] = 1000
config_opts[ 'chrootgid' ] = 135 # mockbuild group
Filesystem Isolation
Mock uses systemd-nspawn or chroot for isolation
Buildroot has no access to host filesystem
Only result directory is accessible after build
Ephemeral Machines
Builder VMs are destroyed after each build
No persistence between builds
Prevents cross-contamination
SSH Access for Debugging
Copr allows users to SSH into their builder machines for debugging: Enable SSH Access # In build submission (API or Web UI)
{
"ssh_public_keys" : [
"ssh-rsa AAAAB3NzaC1yc2EA... user@host"
]
}
Connection Process
Backend notifies user of SSH connection details:
User connects and can:
Inspect mock chroot: /var/lib/mock/<config>/root/
View build logs: /var/lib/mock/<config>/result/
Re-run build commands manually
Debug build failures
Builder is automatically terminated after expiration
Troubleshooting
Build Dependency Problems Problem : Missing build dependenciesERROR: Failed build dependencies:
package-devel is needed by package-1.0-1.fc39.src
Solution : Add BuildRequires to spec file or external repositoryNetwork Access Errors Problem : Network unreachable during buildError: Failed to download https://example.com/file.tar.gz
Solution :
Enable networking with --enable-net (requires permission)
Pre-download and include in dist-git
Mock Initialization Failures Problem : Cannot initialize chrootERROR: Failed to initialize chroot
Solution :
Check mock configuration
Verify repository availability
Ensure sufficient disk space
Architecture Mismatches Problem : Package excludes architectureSolution : Build will be skipped, not an error
Use Bootstrap Images Pre-built container images speed up chroot initialization: config_opts[ 'bootstrap_image' ] = \
'registry.fedoraproject.org/fedora:39'
Enable Build Caching Mock can cache downloaded packages: config_opts[ 'plugin_conf' ][ 'ccache_enable' ] = True
config_opts[ 'plugin_conf' ][ 'root_cache_enable' ] = True
Parallel Builds Increase parallel make jobs: # In spec file
%make_build -j%{_smp_build_ncpus}
See Also