From Fedora Project Wiki

Configuring Banani Pi / Jupiter as a Koji Builder

Prepare Fedora

Recommended Steps

  • Resize /boot. (partition 5) The image only has a 256MB /boot partition, which is too small for installing multiple kernels.
  • Move / (partition 6) to an NVME disk and resize it. If you do this mount /boot and update root=/dev/mmcblk0p6 to root=/dev/nvme0n1p1 in extlinux/extlinux.conf

Boot and Complete

  • Install your storage device(s) and boot
  • Replace /etc/yum.repos.d/fedora-riscv-koji.repo with
[fedora-riscv-koji]
name=Fedora RISC-V Koji
baseurl=http://fedora.riscv.rocks/repos/f41-build/latest/riscv64/
enabled=1
gpgcheck=0

[fedora-riscv-openkoji]
name=Fedora RISC-V Koji
baseurl=http://openkoji.iscas.ac.cn/kojifiles/repos/f41-build/latest/riscv64/
enabled=0
gpgcheck=0
  • dnf remove python3-unbound-1.20.0-2.fc41.riscv64 && dnf -y update # It should not be necessary to uninstall python3-unbound, but dnf has a problem resolving a conflict. It can be reinstalled afterward if needed or wanted.

Optional: Install updated SpacemiT kernel repo

Rust projects have been observed failing to build with 6.1.15 kernel that comes on the image. It also does not have selinux enabled, modules necessary for firewalld to run, etc.

I am attempting to maintain and keep up to date an LTS 6.6 kernel that more closely resembles a Fedora config with patches from https://gitee.com/bianbu-linux/linux-6.6/ until we have a proper mainline kernel. The Bianbu repo is based off 6.6.36. At the time of writing I have been able to keep it up to the current LTS release, 6.6.52.

  • Add /etc/yum.repos.d/spacemit.repo
[spacemit]
name=spacemit
enabled=1
gpgcheck=0
baseurl=https://people.redhat.com/jmontleo/fedora/linux/releases/41/spacemit/riscv64/
priority=98

[spacemit-source]
name=spacemit-source
enabled=0
gpgcheck=0
baseurl=https://people.redhat.com/jmontleo/fedora/linux/releases/41/spacemit/source/tree
  • dnf -y downgrade kernel*
  • dnf -y update
  • dnf -y remove kernel-6.1[01]* kernel-core-6.1[01]* kernel-modules-6.1[01]* kernel-modules-core-6.1[01]*
  • This script is not required, but will automatically update /boot/extlinux/extlinux.conf when a new kernel is installed. To use it save it as /etc/kernel/install.d/99-update-extlinux.install, ensuring the cmdline root= settings matches your root device.
cat << EOF > /boot/extlinux/extlinux.conf
menu title Fedora boot menu
prompt 0
timeout 50
default F41S1
EOF

index=0
for i in $(ls -1vr /boot/vmlinuz*); do
  index=$((index+1))
  version=$(echo $i | sed 's,/boot/vmlinuz-,,g' | sed 's,\.unzboot,,g')
  if [ ${index} == 1 ]; then
    unlink /boot/dtb
    ln -sf dtb-${version} /boot/dtb
  fi
  if [ "${version}" == "6.1.15+" ]; then
    export spacemit=spacemit
  else
    export spacemit=dtb/spacemit
  fi
  cat << EOF >> /boot/extlinux/extlinux.conf

label F41S${index}
        menu label Fedora 41 ${version}
        linux /vmlinuz-${version}
        initrd /initramfs-${version}.img
        fdtdir /${spacemit}
        append console=ttyS0,115200 root=/dev/nvme0n1p1 rootfstype=ext4 rootwait rw earlycon clk_ignore_unused quiet
EOF
done
  • chmod +x /etc/kernel/install.d/99-update-extlinux.install
  • Run it now manually; /etc/kernel/install.d/99-update-extlinux.install
  • Change SELINUX=enforcing to SELINUX=permissive in /etc/selinux/config
  • touch /.autorelabel
  • reboot, let relabel complete
  • Change SELINUX=permissive back to SELINUX=enforcing in /etc/selinux/config
  • reboot (or just setenforce 1)

Install and Configure Koji

  • systemctl mask tmp.mount
  • Create /etc/systemd/system/kojid.service.d/override.conf
[Service]
Restart=always
RestartSec=10min
  • reboot
  • Add /etc/yum.repos.d/koji.repo (Nothing past 1.33 works right or me with the current server)
[koji]
name=koji
enabled=1
gpgcheck=0
baseurl=https://people.redhat.com/jmontleo/fedora/linux/releases/41/koji/riscv64/
priority=98

[koji-source]
name=koji-source
enabled=0
gpgcheck=0
baseurl=https://people.redhat.com/jmontleo/fedora/linux/releases/41/koji/source/tree
  • dnf -y install koji-builder koji-builder-plugin-rpmautospec python3-rpmautospec rpmautospec koji-builder-plugins python3-legacy-cgi
  • Add /etc/kojid/kojid.conf.
[kojid]
; The number of seconds to sleep between tasks
; sleeptime=15

; The maximum number of jobs that kojid will handle at a time
maxjobs=1

; The minimum amount of free space (in MBs) required for each build root
; minspace=8192

; The directory root where work data can be found from the koji hub
topdir=/mnt/koji

; The directory root for temporary storage
workdir=/tmp/koji

; The temporary directory in buildroot
; chroot_tmpdir = /chroot_tmpdir

; The directory root for mock
; mockdir=/var/lib/mock

; The user to run as when doing builds
; mockuser=kojibuilder

; The vendor to use in rpm headers
vendor=Fedora Project

; The packager to use in rpm headers
packager=Fedora Project

; The distribution to use in rpm headers
distribution=Fedora Project

; The _host string to use in mock
; mockhost=koji-linux-gnu
mockhost=redhat-linux-gnu

; Timeout for build duration (7 days, RISCV)
rpmbuild_timeout=604800

; Install timeout(seconds) for image build
; Default value is 0, which means using the number in /etc/oz/oz.cfg,
; supported since oz-0.16.0
; oz_install_timeout=7200

; The URL for the xmlrpc server
server=http://fedora.riscv.rocks/kojihub

; The URL for the file access
topurl=http://fedora.riscv.rocks/kojifiles

; use createrepo_c rather than createrepo
use_createrepo_c=True

; A space-separated list of tuples from which kojid is allowed to checkout.
; The format of those tuples is:
;
;     host:repository[:use_common[:source_cmd]]
;
; Incorrectly-formatted tuples will be ignored.
;
; If use_common is not present, kojid will attempt to checkout a common/
; directory from the repository.  If use_common is set to no, off, false, or 0,
; it will not attempt to checkout a common/ directory.
;
; source_cmd is a shell command (args separated with commas instead of spaces)
; to run before building the srpm. It is generally used to retrieve source
; files from a remote location.  If no source_cmd is specified, "make sources"
; is run by default.
;allowed_scms=scm.example.com:/cvs/example git.example.org:/example svn.example.org:/users/*:no

; copied from https://infrastructure.fedoraproject.org/cgit/ansible.git/tree/roles/koji_builder/templates/kojid.conf
allowed_scms=
    !src.fedoraproject.org:/pagure/fork/*
    !src.fedoraproject.org:/pagure/forks/*
    !pkgs.fedoraproject.org:/pagure/fork/*
    !pkgs.fedoraproject.org:/pagure/forks/*
    !src.fedoraproject.org:/fork/*
    !src.fedoraproject.org:/forks/*
    !src.fedoraproject.org:/cgit/*
    !src.fedoraproject.org:/git/*
    !pkgs.fedoraproject.org:/fork/*
    !pkgs.fedoraproject.org:/forks/*
    !pkgs.fedoraproject.org:/cgit/*
    !pkgs.fedoraproject.org:/git/*
    pkgs.fedoraproject.org:/*:false:fedpkg,sources
    pagure.io:/fedora-kickstarts.git:false
    src.fedoraproject.org:/*:false:fedpkg,sources
    pagure.io:/fork/*/fedora-kickstarts.git:false
    fedora.riscv.rocks*:/*:false:fedpkg,sources

; The mail host to use for sending email notifications
;smtphost=example.com

; The From address used when sending email notifications
;from_addr=Koji Build System <buildsys@example.com>

;configuration for Kerberos authentication

;the format of the principal used by the build hosts
;%s will be replaced by the FQDN of the host
;host_principal_format = compile/%s@EXAMPLE.COM

;location of the keytab
;keytab = /etc/kojid/kojid.keytab

;the service name of the principal being used by the hub
;krbservice = host

;configuration for SSL authentication

;client certificate
cert = /etc/kojid/builder.pem

;certificate of the CA that issued the HTTP server certificate
serverca = /etc/kojid/koji_ca_cert.crt

;if set to True, failing subtask will not automatically cancel other siblings
;build_arch_can_fail = False

;if set to True additional logs with timestamps will get created and uploaded
;to hub. It could be useful for debugging purposes, but creates twice as many
;log files
;log_timestamps = False

;plugins = rpmautospec_builder runroot
plugins = rpmautospec_builder
  • Save /etc/mock/sites-default.cfg
# mock defaults
# vim:tw=0:ts=4:sw=4:et:
#
# If you want to alter just some setting for one user, you can put the
# configuration in:
#    ~/.config/mock.cfg
#
# This config file is for site-specific default values that apply across all
# configurations. Options specified in this config file can be overridden in
# the individual mock config files.
#
# The site-defaults.cfg delivered by default has NO options set. Only set
# options here if you want to override the defaults.
#
# It's possible to use include statement in order to make one config included to another:
# include('/path/to/included/config.cfg')
#
# Entries in this file follow the same format as other mock config files.
# config_opts['foo'] = bar

#############################################################################
#
# Things that we recommend you set in site-defaults.cfg:
#
# config_opts['basedir'] = '/var/lib/mock/'
# config_opts['cache_topdir'] = '/var/cache/mock'
#  Note: the path pointed to by basedir and cache_topdir must be owned
#        by group 'mock' and must have mode: g+rws
# config_opts['rpmbuild_timeout'] = 0
# Using --enable-network sets use_host_resolv True, overriding the value set here.
# config_opts['use_host_resolv'] = False

# You can configure log format to pull from logging.ini formats of these names:
# config_opts['build_log_fmt_name'] = "unadorned"
# config_opts['root_log_fmt_name']  = "detailed"
# config_opts['state_log_fmt_name'] = "state"
#
# By default, mock only prints the build log to stderr if it is a tty. You can
# force it on here (for CI builds where there is no tty, for example) by
# setting this to True, or force it off by setting it to False. Setting it to
# None or leaving it undefined uses the default behavior.
# config_opts['print_main_output'] = None
#
# mock will normally set up a minimal chroot /dev.
# If you want to use a pre-configured /dev, disable this and use the bind-mount
# plugin to mount your special /dev
# config_opts['internal_dev_setup'] = True
#
# the cleanup_on_* options allow you to automatically clean and remove the
# mock build directory, but only take effect if --resultdir is used.
# config_opts provides fine-grained control. cmdline only has big hammer
#
# config_opts['cleanup_on_success'] = 1
# config_opts['cleanup_on_failure'] = 1

# The build user's homedir is partially cleaned up even when --no-clean is
# specified in order to prevent garbage from previous builds from altering
# successive builds. Mock can be configured to exclude certain files/directories
# from this. Default is SOURCES directory to support nosrc rpms. Paths are
# relative to build user's homedir
# config_opts['exclude_from_homedir_cleanup'] = ['build/SOURCES']

# Mock uses systemd-nspawn(1) by default. When use_nspawn is set to False,
# simple os.chroot() is used instead.
# config_opts['use_nspawn'] = False
# If you're using nspawn, then by default networking will be turned off
# for rpmbuild.  This helps ensure more reproducible builds.
config_opts['rpmbuild_networking'] = True
# Additional args for nspawn
# config_opts['nspawn_args'] = ['--capability=cap_ipc_lock']
## When RPM is build in container then build hostname is set to name of
## container. This sets the build hostname to name of container's host.
## Works only in F25+ chroots
# config_opts['use_container_host_hostname'] = True

# This works unconditionally by calling sethostname(), however
# variable use_container_host_hostname or %_buildhost macro can override this
# config_opts['hostname'] = 'my.own.hostname'

# The default package manager is Yum
# config_opts['package_manager'] = 'yum'
# If you want to use DNF, set it to 'dnf'. To use DNf you need to have dnf and
# dnf-plugins-core installed

# You can configure Yum, DNF, rpm and rpmbuild executable paths if you need to
# use different versions that the system-wide ones
# config_opts['yum_command'] = '/usr/bin/yum'
# config_opts['yum_builddep_command'] = '/usr/bin/yum-builddep'
# config_opts['dnf_command'] = '/usr/bin/dnf'
# config_opts['rpm_command'] = '/bin/rpm'
# config_opts['rpmbuild_command'] = '/usr/bin/rpmbuild'
# config_opts['target_dir'] = '/var/cache/%(package_manager)s/'
#
# By default a Yum/DNF update is performed before each rebuild
# config_opts['update_before_build'] = True

# If you want mock to bootstrap a chroot with
# the target yum/dnf version in, before using
# that chroot to make the actual build chroot, set this to True.
# This is useful when the target may require newer RPM features
# than are available on the host.
# config_opts['use_bootstrap_container'] = False

# when 'use_bootstrap_container' is True, these commands are used to build
# the minimal chroot for the respective package manager
# config_opts['yum_install_command'] = 'install yum yum-utils shadow-utils distribution-gpg-keys'
# config_opts['dnf_install_command'] = 'install dnf dnf-plugins-core distribution-gpg-keys'
# config_opts['system_yum_command'] = '/usr/bin/yum'
# config_opts['system_dnf_command'] = '/usr/bin/dnf'

# anything you specify with 'bootstrap_*' will be copied to bootstrap config
# e.g. config_opts['bootstrap_system_yum_command'] = '/usr/bin/yum-deprecated' will become
# config_opts['system_yum_command'] = '/usr/bin/yum-deprecated' for bootstrap config
config_opts['bootstrap_chroot_additional_packages'] = []
config_opts['bootstrap_module_enable'] = []
config_opts['bootstrap_module_install'] = []

# if you want mock to automatically run createrepo on the rpms in your
# resultdir.
# config_opts['createrepo_on_rpms'] = False
# config_opts['createrepo_command'] = '/usr/bin/createrepo_c -d -q -x *.src.rpm'

# You can configure which tar is used (for root cache and SCM plugin)
# valid options are: "gnutar" or "bsdtar"
# config_opts['tar'] = "gnutar"

# if you want mock to backup the contents of a result dir before clean
# config_opts['backup_on_clean'] = False
# config_opts['backup_base_dir'] = config_opts['basedir'] + "backup"

# if you want to speed up the package installation and the build process, mock
# can use nosync library to skip fsync and related calls from programs called
# from within mock. It needs nosync library to be installed and for multilib
# target, it requires both architectures of nosync to be present. If these
# conditions aren't met, it won't be enabled
# config_opts['nosync'] = False
# if you cannot or don't want to install both architectures of nosync and still
# want mock to use it, you can force it, but then expect a lot of (generally
# harmless) error messages from ld.so when a 32bit program is executed
# config_opts['nosync_force'] = False

# By default Mock unshare namespace so it is different from your other application
# in unpriviliged container, this is skipped. We will warn you that running mock
# and some other applications in the same container is not good idea and
# can be security risk. If you are fully aware of this risk or mock is your
# only one application in that container you can disable the warning here.
# config_opts['docker_unshare_warning'] = True

#############################################################################
#
# plugin related. Below are the defaults. Change to suit your site
# policy. site-defaults.cfg is a good place to do this.
#
# NOTE: Some of the caching options can theoretically affect build
#  reproducability. Change with care.
#
config_opts['plugin_conf']['package_state_enable'] = False
# config_opts['plugin_conf']['package_state_opts'] = {}
# config_opts['plugin_conf']['package_state_opts']['available_pkgs'] = False
# config_opts['plugin_conf']['package_state_opts']['installed_pkgs'] = True
config_opts['plugin_conf']['ccache_enable'] = False
# config_opts['plugin_conf']['ccache_opts'] = {}
# config_opts['plugin_conf']['ccache_opts']['max_cache_size'] = '4G'
# config_opts['plugin_conf']['ccache_opts']['compress'] = None
# config_opts['plugin_conf']['ccache_opts']['dir'] = "%(cache_topdir)s/%(root)s/ccache/u%(chrootuid)s/"
# config_opts['plugin_conf']['yum_cache_enable'] = True
# config_opts['plugin_conf']['yum_cache_opts'] = {}
# config_opts['plugin_conf']['yum_cache_opts']['max_age_days'] = 30
# config_opts['plugin_conf']['yum_cache_opts']['max_metadata_age_days'] = 30
# config_opts['plugin_conf']['yum_cache_opts']['dir'] = "%(cache_topdir)s/%(root)s/%(package_manager)s_cache/"
# config_opts['plugin_conf']['yum_cache_opts']['target_dir'] = "/var/cache/%(package_manager)s/"
# config_opts['plugin_conf']['yum_cache_opts']['online'] = True
# config_opts['plugin_conf']['root_cache_enable'] = True
# config_opts['plugin_conf']['root_cache_opts'] = {}
# config_opts['plugin_conf']['root_cache_opts']['age_check'] = True
# config_opts['plugin_conf']['root_cache_opts']['max_age_days'] = 15
# config_opts['plugin_conf']['root_cache_opts']['dir'] = "%(cache_topdir)s/%(root)s/root_cache/"
# config_opts['plugin_conf']['root_cache_opts']['compress_program'] = "pigz"
# config_opts['plugin_conf']['root_cache_opts']['extension'] = ".gz"
# config_opts['plugin_conf']['root_cache_opts']['exclude_dirs'] = ["./proc", "./sys", "./dev",
#                                                                  "./var/tmp/ccache", "./var/cache/yum" ]
# config_opts['plugin_conf']['hw_info_enable'] = True
# config_opts['plugin_conf']['hw_info_opts'] = {}
#
# bind mount plugin is enabled by default but has no configured directories to
# mount
# config_opts['plugin_conf']['bind_mount_enable'] = True
# config_opts['plugin_conf']['bind_mount_opts']['dirs'].append(('/host/path', '/bind/mount/path/in/chroot/' ))
#
# config_opts['plugin_conf']['tmpfs_enable'] = False
# config_opts['plugin_conf']['tmpfs_opts'] = {}
# config_opts['plugin_conf']['tmpfs_opts']['required_ram_mb'] = 1024
# config_opts['plugin_conf']['tmpfs_opts']['max_fs_size'] = '768m'
# config_opts['plugin_conf']['tmpfs_opts']['mode'] = '0755'
# config_opts['plugin_conf']['tmpfs_opts']['keep_mounted'] = False
#
# config_opts['plugin_conf']['chroot_scan_enable'] = False
# config_opts['plugin_conf']['chroot_scan_opts'] = {
## Regexp of files which should be copied from buildroot to resultdir.
#    'regexes': [ "^[^k]?core(\.\d+)?", "\.log$",],
## If set to True files are copied only if build failed.
#    'only_failed': True,
#}
#
# lvm_root plugin is not enabled by default and is distributed in separate
# subpackage mock-lvm. If you want to use it, it's recommended to disable the
# root_cache plugin, otherwise you'd be caching twice.
# config_opts['plugin_conf']['lvm_root_enable'] = False
# config_opts['plugin_conf']['lvm_root_opts'] = {}
# You need to give it a volume group with sufficient space. It won't touch any
# of the existing logical volumes, so you can use the same volume group you use
# for other purposes. It requires a name of the VG (not device path).
# config_opts['plugin_conf']['lvm_root_opts']['volume_group'] = 'my_vg'
# You need to specify the size that will mock's thinpool occupy. For regular
# packages with small set of dependencies, 2G should suffice. For large packages
# such as libreoffice, you should set it to at least 5 GB otherwise you may run
# out of space and the build process will be blocked
# config_opts['plugin_conf']['lvm_root_opts']['size'] = '2G'
# You can specify alternative pool metadata size, format is the same as size.
# Default value is determined by lvcreate based on size
# config_opts['plugin_conf']['lvm_root_opts']['poolmetadatasize'] = None
# When thin pool utilization is over 90% mock will refuse to continue.
# Because once it reach 100% utilization weird things will happens.
# config_opts['plugin_conf']['lvm_root_opts']['check_size'] = True
# Specifying whether the buildroot volume should stay mounted after mock exits.
# config_opts['plugin_conf']['lvm_root_opts']['umount_root'] = False
# Filesystem name that will be used for the volume. It will use mkfs.$filesystem binary to create it.
# config_opts['plugin_conf']['lvm_root_opts']['filesystem'] = "ext4"
# The whole command for creating the filesystem that will get the volume path as an argument. When set, overrides above
# option.
# config_opts['plugin_conf']['lvm_root_opts']['mkfs_command'] = None
# Additional arguments passed to mkfs command.
# config_opts['plugin_conf']['lvm_root_opts']['mkfs_args'] = []
# Will be passed to -o option of mount when mounting the volume. String or None.
# config_opts['plugin_conf']['lvm_root_opts']['mount_opts'] = None
# How long to sleep when waiting for concurrent LVM initialization.
# config_opts['plugin_conf']['lvm_root_opts']['sleep_time'] = 1
#
# overlayfs plugin
# It is recomended to disable root_cache plugin, when overlayfs plugin
# is enabled since overlayfs plugin implicitly creates postinit snapshot
# ( similary to lvm_root plugin), which makes root cache pointless.
# ( Recomended with: config_opts['plugin_conf']['root_cache_enable'] = False )
# config_opts['plugin_conf']['overlayfs_enable'] = False
# config_opts['plugin_conf']['overlayfs_opts']['base_dir'] = /some/directory
# config_opts['plugin_conf']['overlayfs_opts']['touch_rpmdb'] = False

### pm_request plugin can install packages requested from within the buildroot
# It is disabled by default, as it affects build reproducibility. It can be enabled
# by setting the following to True, but it's not advised to have it enabled globally.
# It's better to enable it per build by using --enable-plugin pm_request
# config_opts['plugin_conf']['pm_request_enable'] = False
# config_opts['plugin_conf']['pm_request_opts'] = {}

### If you want to compress mock log, enable this plugin
# config_opts['plugin_conf']['compress_logs_enable'] = False
# config_opts['plugin_conf']['compress_logs_opts'] = {}
### Command used to compress logs - e.g. "/usr/bin/xz -9 --force"
# config_opts['plugin_conf']['compress_logs_opts']['command'] = ""
#
# Configuration options for the sign plugin:
# config_opts['plugin_conf']['sign_enable'] = False
# config_opts['plugin_conf']['sign_opts'] = {}
# config_opts['plugin_conf']['sign_opts']['cmd'] = 'rpmsign'
# The options to pass to the signing command. %(rpms)s will be expanded to
# the rpms in the results folder.
# config_opts['plugin_conf']['sign_opts']['opts'] = '--addsign %(rpms)s -D "%%_gpg_name your_name" -D "%%_gpg_path /home/your_name/.gnupg"'

#############################################################################
#
# environment for chroot
#
# config_opts['environment']['TERM'] = 'vt100'
# config_opts['environment']['SHELL'] = '/bin/bash'
# config_opts['environment']['HOME'] = '/builddir'
# config_opts['environment']['HOSTNAME'] = 'mock'
# config_opts['environment']['PATH'] = '/usr/bin:/bin:/usr/sbin:/sbin'
# config_opts['environment']['PROMPT_COMMAND'] = r'printf "\033]0;<mock-chroot>\007"'
# config_opts['environment']['PS1'] = r'<mock-chroot> \s-\v\$ '
# config_opts['environment']['LANG'] = os.environ.setdefault('LANG', 'en_US.UTF-8')
# config_opts['environment']['TZ'] = os.environ.setdefault('TZ', 'EST5EDT')
#
## other example for PS1
# config_opts['environment']['PS1'] = r'[\u@\h<mock-chroot>/\w]\[\033[01;31m\]${?/#0/}\[\033[00m\]\$'
# feel free to craft your own at: http://bashrcgenerator.com/

#############################################################################
#
# Things that you can change, but we dont recommend it:
# config_opts['chroothome'] = '/builddir'
# config_opts['clean'] = True
## you could not really use substitution here so it will not work if overridden:
# config['rootdir'] = '/var/lib/mock/<CONFIG>/root/'
## This works in F25+ chroots. This overrides 'use_container_host_hostname' option
# config_opts['macros']['%_buildhost'] = 'my.own.hostname'
config_opts['macros']['%bugurl'] = 'https://bugz.fedoraproject.org/%name'

#############################################################################
#
# Things that must be adjusted if SCM integration is used:
#
# config_opts['scm'] = True
# config_opts['scm_opts']['method'] = 'git'
# config_opts['scm_opts']['cvs_get'] = 'cvs -d /srv/cvs co SCM_BRN SCM_PKG'
# config_opts['scm_opts']['git_get'] = 'git clone SCM_BRN git://localhost/SCM_PKG.git SCM_PKG'
# config_opts['scm_opts']['svn_get'] = 'svn co file:///srv/svn/SCM_PKG/SCM_BRN SCM_PKG'
# config_opts['scm_opts']['distgit_get'] = 'rpkg clone -a --branch SCM_BRN SCM_PKG SCM_PKG'
# config_opts['scm_opts']['distgit_src_get'] = 'rpkg sources'
# config_opts['scm_opts']['spec'] = 'SCM_PKG.spec'
# config_opts['scm_opts']['ext_src_dir'] = '/dev/null'
# config_opts['scm_opts']['write_tar'] = True
# config_opts['scm_opts']['git_timestamps'] = True
# config_opts['scm_opts']['exclude_vcs'] = True

# These options are also recognized but usually defined in cmd line
# with --scm-option package=<pkg> --scm-option branch=<branch>
# config_opts['scm_opts']['package'] = 'mypkg'
# config_opts['scm_opts']['branch'] = 'master'

#############################################################################
#
# Things that are best suited for individual chroot config files:
#
# MUST SET (in individual chroot cfg file):
# config_opts['root'] = 'name-of-yum-build-dir'
# Mock will set architecture to 'target_arch' using personality(2) syscall.
# config_opts['target_arch'] = 'i386'
# When host system architecture is not in 'legal_host_arches' list, mock will refuse to switch to
# 'target_arch' and will raise error.
# config_opts['legal_host_arches'] = ('i386', 'i586', 'i686', 'x86_64')
# Contains content of $CHROOT/etc/yum/yum.conf or $CHROOT/etc/dnf/dnf.conf. If DNF is used and
# 'dnf.conf' is not set, then content of 'yum.conf' is used to populate $CHROOT/etc/dnf/dnf.conf
# config_opts['yum.conf'] = ''
# or
# config_opts['dnf.conf'] = ''
# Important! You must use 'assumeyes=1' in yum/dnf.conf otherwise Mock will fail.
#
# Flip this if you want to get rid of warning message on systems which does not support DNF
# Warning! Setting this to False will automatically use Yum on RHEL{6,7} platforms.
# config_opts['dnf_warning'] = True
#
# CAN SET, defaults usually work ok:
# config_opts['chroot_setup_cmd'] = 'install buildsys-build'
# config_opts['chroot_additional_packages'] = ''
# config_opts['log_config_file'] = 'logging.ini'
# config_opts['more_buildreqs']['srpm_name-version-release'] = 'dependency'
# config_opts['more_buildreqs']['srpm_name-version-release'] = ['dependency1', 'dependency2']
# config_opts['macros']['%Add_your_macro_name_here'] = "add macro value here"
# config_opts['files']['path/name/no/leading/slash'] = "put file contents here."
# config_opts['chrootuid'] = os.getuid()
# config_opts['releasever'] = '20'
# config_opts['yum_common_opts'] = []
# config_opts['dnf_common_opts'] = ['--disableplugin=local', '--setopt=deltarpm=False']
config_opts['dnf_common_opts'] = ['--setopt=install_weak_deps=0']
# config_opts['yum_builddep_opts'] = []
# config_opts['dnf_builddep_opts'] = []
# config_opts['microdnf_command'] = '/usr/bin/microdnf'
## "dnf-install" is special keyword which tells mock to use install but with DNF
# config_opts['microdnf_install_command'] = 'dnf-install microdnf dnf dnf-plugins-core distribution-gpg-keys'
# config_opts['microdnf_builddep_command'] = '/usr/bin/dnf'
# config_opts['microdnf_builddep_opts'] = []
# config_opts['microdnf_common_opts'] = []
# config_opts['priorities.conf'] = 'put file contents here.'
# config_opts['rhnplugin.conf'] = 'put file contents here.'
## Important! You should register your host machine first!
# config_opts['subscription-manager.conf'] = 'put file contents here.'
## This will only work with DNF and when repo is configured with modules=1 for repo in dnf.conf.
## This is executed just before 'chroot_setup_cmd'.
# config_opts['module_enable'] = ['list', 'of', 'modules']
# config_opts['module_install'] = ['module1/profile', 'module2/profile']
## Use this to force foreing architecture (requires qemu-user-static)
# config_opts['forcearch'] = None
# If you change chrootgid, you must also change "mock" to the correct group
# name in this line of the mock PAM config:
#   auth  sufficient pam_succeed_if.so user ingroup mock use_uid quiet
# config_opts['chrootgid'] = grp.getgrnam("mock")[2]
# name of user that is used when executing commands inside the chroot
# config_opts['chrootuser'] = 'mockbuild'
# name of the group inside of chroot
# config_opts['chrootgroup'] = 'mock'

# config_opts['useradd'] = '/usr/sbin/useradd -m -u %(uid)s -g %(gid)s -d %(home)s -n %(user)s' # Fedora/RedHat
#
# Security related
# config_opts['no_root_shells'] = False
#
# Proxy settings (https_proxy, ftp_proxy, and no_proxy can also be set)
# You can set a specific proxy: 'http://localhost:3128'
# But by default, the existing environment variables are re-used
# config_opts['http_proxy']  = os.getenv("http_proxy")
# config_opts['ftp_proxy']   = os.getenv("ftp_proxy")
# config_opts['https_proxy'] = os.getenv("https_proxy")
# config_opts['no_proxy']    = os.getenv("no_proxy")

#
# Extra dirs to be created when the chroot is initialized
# This is just a list of strings representing chroot paths such as:
#  [ '/run/lock', ]
# config_opts['extra_chroot_dirs'] = []
#
# Set timeout in seconds for common mock operations
# if 0 is set, then no time limit is used
# config_opts['opstimeout'] = 0
  • Save /etc/kojid/koji_ca_cert.crt
-----BEGIN CERTIFICATE-----
MIIGNDCCBBygAwIBAgIUKVcZFGOmmvUebGQTQpP4NyovL/kwDQYJKoZIhvcNAQEL
BQAwZzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEDAOBgNVBAcT
B0ZyZW1vbnQxFDASBgNVBAoTC0ZlZG9yYVJJU0NWMRswGQYDVQQDExJmZWRvcmEu
cmlzY3Yucm9ja3MwHhcNMTkwOTExMDkxNTE1WhcNMjkwOTA4MDkxNTE1WjBnMQsw
CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEQMA4GA1UEBxMHRnJlbW9u
dDEUMBIGA1UEChMLRmVkb3JhUklTQ1YxGzAZBgNVBAMTEmZlZG9yYS5yaXNjdi5y
b2NrczCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOhtebDIDwX7RNq3
3kstNhJY6IGynIvmFBNjh/JAvp23mVEZTLAAbLYaOjDavcLBQan5NUglKsw07Upb
c3BxqzyKyCmVFCrGVwl+1ZalpaVSrZBan/T2adaHKGIWq8Me+yNjY0avB8ZEO28T
1t+6d6XNw+8SUm6MSEdjxxvpoO2BxbVKe5heDvsE8sVjgUnWVRQYQJZtcCUMhVAm
ZPHi8JrcKY9xv2xS6L1QurhHBZJ5/ol6L7zS2fXzeiuUd7qcTd2DKwlm8GQgUAx6
9X9+/dGnblM3OqplhUQqVb4MQqpuishG9z0OwJmnskcbZtqBjMfGXGcq6+5I7Qq5
srDHL2QBfYpJi8qJtzEu+Q8Q9mfsyPhnF/NZ2sXn8QKoB8FEL+F2Sq1zsanZRVud
33Lpg3PupbbHtIfjNX9zRPOnC7cozR6RfUsSpNZIUnMPf2VeOuTbNV+Br1ts2Eco
E6QYzSqGLL0LuFmuJImXwC91m+XvXumkcWWCrzhkRIz4kOxZlSL1O+wAzvRfd4v7
Xw6bzDMa9k1GSbAvbt6AGwOAzVj+ChQINl7mgukRDIWUx1GJl1Vy8WCWv8ZXuks8
+UETPb4FMNqZSattOqVQT1FSUqV7N1ioJjD4pId44V8ggTsnucgtt5s9Jb7p0d6r
gtJFvANg1gkIgNBWgtbQyDqrTRjxAgMBAAGjgdcwgdQwHQYDVR0OBBYEFHzXu2cB
yQQLiTY5wt4cHtyyhBlpMIGkBgNVHSMEgZwwgZmAFHzXu2cByQQLiTY5wt4cHtyy
hBlpoWukaTBnMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEQMA4G
A1UEBxMHRnJlbW9udDEUMBIGA1UEChMLRmVkb3JhUklTQ1YxGzAZBgNVBAMTEmZl
ZG9yYS5yaXNjdi5yb2Nrc4IUKVcZFGOmmvUebGQTQpP4NyovL/kwDAYDVR0TBAUw
AwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAssgxTb/CVh+Ha2Zm8v6UnvmedkX4U2O9
1HEvotd9so5XeA3TBRdynusCYN9O7d043YFZEErJZq7rNXCAcry1cIqutzjHaYIV
4xVEYxF/xseUy33zp8G8ltDQyITbfwPAjvQRXFsOSlNy5YJxijRHoI+gd3hqRQL0
OZxx+pOfL/8FkdTuh3kCmcyWi2CNKiD7uVYsdukoDIg2poXeC4kAWSxnC0iwdiXV
sfB7KyCmo82arjkv9LkCFNq/W9510F5QP98TGRRCCcg5X16ND4etrfoyLSB3/RlL
tlPdNFPVi8POK5NIuX50D2TOx/kws2/ontcqZXNFGQWRO0CPJM+/sIQoknHgU5rJ
rIML6Up7HW7eJmqaQjJj7smKvG7ynlMBg7F+R7BpZOUgsGKgztyAoLLnvONqzna3
qpWW6JhOyJU717hSGmiQ9N1B3jl48nS+3XBcboYdxMbayPbq+KLEJs0HQrBQTFwN
Pq21D0ot9B4ZSYgSTM7s5YAESD/ymwsQnhm31BKvuyZMi7xsaI7dA4UYswm4xlGM
tLMCW2BOX+lilj+HfS0SSdvxD+ltspumiJeGtoxAtoVzQalqAesl0iq1pUNKQ/GW
uMldYbUupNYP37uUdfztNGPFLaqtSAvRlWBCasHJKqp+3908fP82boMk64NPhXb0
a8AGvJJc79Q=
-----END CERTIFICATE-----
  • Once you obtain a cert for the koji builder save it as /etc/kojid/builder.pem
  • systemctl enable --now kojid.conf

Proxy Configuration

Builders can use a lot of bandwidth. A squid proxy can cut this down substantially

http_port 3128

cache_mem 400 MB
maximum_object_size 2000 MB
maximum_object_size_in_memory 1024 KB

cache_dir ufs /var/spool/squid 300000 16 256

# Average object size, used to estimate number of objects your
# cache can hold.  The default is 13 KB.
store_avg_object_size 817 KB

# We want to keep the largest objects around longer, and just download the smaller objects if we can. 
cache_replacement_policy heap LFUDA

memory_replacement_policy heap GDSF

# cache repodata only few minutes and then query parent whether it is fresh
refresh_pattern /XMLRPC/GET-REQ/.*/repodata/.*$ 0 1% 1440 ignore-no-cache reload-into-ims refresh-ims
# rpm will hardly ever change, force to chache it for very long time
refresh_pattern  \.rpm$  44640 100% 525960 override-expire override-lastmod ignore-reload reload-into-ims
refresh_pattern 	.		0	100%	525960

# secure squid
acl builder1 src 192.168.1.151/32
acl builder2 src 192.168.1.152/32
acl builder3 src 192.168.1.153/32
acl builder4 src 192.168.1.154/32
acl builder5 src 192.168.1.155/32
acl SSL_ports port 443
acl Safe_ports port 80          # http
acl Safe_ports port 443         # https
acl CONNECT method CONNECT

http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access allow builder1
http_access allow builder2
http_access allow builder3
http_access allow builder4
http_access allow builder5
http_access deny all
icp_access allow all
miss_access allow all

# if transport is canceled, finish downloading anyway
quick_abort_pct -1
quick_abort_min -1 KB

# when range is required, download whole file anyway
# when we request rpm header, we will nearly always get
# request for the rest of the file
#range_offset_limit none

# we download only from 1 server, default is 1024
# which is too much for us
fqdncache_size 4
  • Add a line to the end of /etc/kojid/kojid.conf
yum_proxy = http://your.squid-proxy.address:3128
  • If you want to run squid in podman or docker it can be run like so. Increasing the stop timeout is important, as squid can take almost a minute to shutdown and killing it early causes problems. Adjust the storage location and networking to suit your preference. The example below uses macvlan, but you can also just expose the port with -p 3128:3128, for example.
podman run \
  --detach \
  --name=squid \
  --stop-timeout 360 \
  --restart unless-stopped \
  -v /you-container-storage-location/squid/var/log/squid:/var/log/squid:rw \
  -v /you-container-storage-location/squid/var/spool/squid:/var/spool/squid:rw \
  -v /you-container-storage-location/squid/etc/squid/squid-repos.conf:/etc/squid/squid-repos.conf:ro \
  --network=macvlan \
  --ip 192.168.1.150 \
  quay.io/fedora/fedora:latest \
  bash -c "dnf -y update && dnf -y install squid && squid -f /etc/squid/squid-repos.conf -NYd1"

TODO

  • Run thru this and check for accuracy.