Koji Build Farm
Official Koji documentation can be found at: https://docs.pagure.org/koji/
Building blocks
A Koji Build farm is comprised of a number of components that work together.
Major Koji components:
- hub (koji-hub)
- web server (koji-web)
- builders
- build daemon (kojid)
- Dnf|Yum repository creation and maintenance daemon (kojira)
You need at least the one server which can perform all functions, or split it into a hub, web plus 1+ build servers.
A typical scenario will be to have 2+ servers.
- hub - which will run the hub, web and dnf|Yum repository daemon
- builders - there can be multiple of these
For our purposes, all of these servers will be based on bare Rocky 8 - minimal install, servers.
Install
Create your hub, web and build servers (Rocky 8 minimal install).
On all servers enable the network and name the servers as the FQDN (the servers need to be accessible via their FQDN's, so either via DNS or you need to add them to your /etc/hosts files).
It's also a good idea to update them to the latest
nmtui
dnf update
Log into the hub server, download and run the install script
curl https://src.koozali.org/smedev/smeserver-koji/raw/branch/master/install-koji-farm.sh > install-koji-farm.sh
chmod o+x install-koji-farm.sh
./install-koji-farm.sh
The install-koji-farm.sh script will accept multiple parameters
install-koji-farm.sh [web=<web FQDN> | build=<build FQDN> | scm=<scm ip or name>:/* | debug]
- web=<FQDN> - defaults to hub FQDN
- build=<FQDN> - multiple allowed
- scm=<IP or Name of SCM>:/* - multiple allowed
- debug - will list each line executed, plus lots of other gunk (very noisy)
You will be prompted for various items
- values for your ssl certificates (e.g. Country, State, City, Organization, Organisational Unit)
- For the web server (unless it's the hub)
- to accept the build server signature
- for the root password on the web server
- For each build server
- to accept the build server signature
- for the root password on the build server
The web interface will be available via http://<your hub server>/koji
Build Targets
This will have created 6 build targets with various build tags to use
- smeserver10 (smeserver10-build)
- smecontribs10 (smecontribs10-build)
- smeserver11 (smeserver11-build)
- smecontribs11 (smecontribs11-build)
- smeserver12 (smeserver12-build)
- smecontribs12 (smecontribs12-build)
There is a hierarchy inheritance structure for each release (see 10, 11 & 12), where the basic settings are inherited (e.g. yum or dnf, centos:7 or rockylinux:8 bootstrap image for mock) as well as which external repositories to use (e.g. centos7/el7 versions or rocky8/el8 versions)
+ smeserver<release>
++ smeserver<release>-build
++ smeserver<release>-testing
+ smecontribs<release>
++ smecontribs<release>-build
++ smecontribs<release>-testing
How to build etc. is covered in Howto interact with gitea and koji to do an rpm build for SME11
Additional Builders
You can add additional build servers later, via
koji-add-builder.sh <FQDN of build server> [debug]
Additional Users
You can add end Users via
koji-add-user.sh <User Name> [ permission=<permission> | debug ]
Where <permission> could be "admin".
This will add the user into the koji db and generate ssl CLI and browser keys, which will be bundled up in a tgz file at /etc/pki/koji/bundle/koji-<User Name>-bundle.tgz.
This bundle should be copied and extracted into their home (~) directory and will create a .koji directory containing config and keys.This can be on a remote machine with the koji client installed.
cd ~
tar -zxf koji-<User Name>-bundle.tgz
koji moshimoshi
Bootstrap
The setup of the repos used for building SME10, SME11 & SME12 are all included in the install script, but a brief description of what has been setup seems sensible.
Plugins
At this time, we are using the following koji plugins to manage our builds:
- koji-plugin-sign (to sign all built rpms with the appropriate koozali gnupg key)
- tag2distrepo (to automatically regenerate external repositories, when we have included a new build)
These have been installed manually, using the following instructions, but should be included in the install scripts in the future
- Copy the tag2distrepo.py and sign.py programs into /usr/lib/koji-hub-plugins
- Set the configurations as per the directions for each plugin below
- Edit the following settings in /etc/koji-hub/hub.conf to enable the plugins:
PluginPath = /usr/lib/koji-hub-plugins Plugins = tag2distrepo sign
- Reload Apache
systemctl reload httpd
koji-sign-rpm
- Make sure that the koji-sign selinux policy is installed and enabled
semodule --list-modules=full | grep koji-sign
- If it's not listed, copy down the koji-sign.te file, compile and install it
checkmodule -M -m -o koji-sign.mod koji-sign.te semodule_package -o koji-sign.pp -m koji-sign.mod semodule -i koji-sign.pp
- Copy your gpg keys etc. into /etc/koji-hub/plugins/gnupg/
- Copy sign.conf into /etc/koji-hub/plugins/
- Edit /etc/koji-hub/plugins/sign.conf to have the correct gpg key names for each tag and set enabled, when ready
tag2distrepo
- Set the extra options on the tag so the plugin will generate the repository: where ONLY those rpms signed with that key will be included in the generated external repositoryYou can check by doing:
koji edit-tag -x tag2distrepo.enabled=True -x tag2distrepo.keys='44922a28' smecontribs11
and you should seekoji taginfo smecontribs11
Tag: smecontribs11 [38] Arches: x86_64 Groups: Tag options: mock.bootstrap_image : 'rockylinux:8' mock.package_manager : 'dnf' rpm.macro.dist : '.el8.sme' rpm.macro.distribution : 'SME Server v11' rpm.macro.packager : 'Koozali.org <http://www.koozali.org>' rpm.macro.vendor : 'Koozali.org <http://www.koozali.org>' tag2distrepo : '44922a28' tag2distrepo.enabled : True Inheritance:
Install - The long way (Beware: Demons lurk here)
Hub/Web Server
OS: Rocky 8.8-minimal
Memory: 8GB
Disk: 20GB (but I'm only using ~25%)
FQDN: koji.koozali.org
You'll need to set up your network: either during install or post install (enable adapter, FQDN, IP address, Gateway, DNS)
Log into your server as root and
nmtui
ip addr
ping google.com
Let's bring the server up to date
dnf update
I installed and configured some basic tools and settings to help manage and debug the server (Cockpit can be accessed at http://<ip address or name>:9090)
systemctl enable --now cockpit.socket
systemctl start cockpit.socket
dnf config-manager --set-enabled powertools
dnf install epel-release
dnf install policycoreutils-python-utils
dnf install setools-console
dnf install rsyslog
dnf install setroubleshoot-server
reboot
SSL preparations
We'll be using ssl certificates so let's create the koji ssl working directories and edit the koji ssl config file
Log back into your server as root and
mkdir -p /etc/pki/koji/{certs,private,confs}
cd /etc/pki/koji
and create ssl.cnf
cat <<_EOT > /etc/pki/koji/ssl.cnf
HOME = .
RANDFILE = .rand
[ca]
default_ca = ca_default
[ca_default]
dir = .
certs = \$dir/certs
crl_dir = \$dir/crl
database = \$dir/index.txt
new_certs_dir = \$dir/newcerts
certificate = \$dir/%s_ca_cert.pem
private_key = \$dir/private/%s_ca_key.pem
serial = \$dir/serial
crl = \$dir/crl.pem
x509_extensions = usr_cert
name_opt = ca_default
cert_opt = ca_default
default_days = 3650
default_crl_days = 30
default_md = sha256
preserve = no
policy = policy_match
[policy_match]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[req]
default_bits = 2048
default_keyfile = privkey.pem
default_md = sha256
distinguished_name = req_distinguished_name
attributes = req_attributes
x509_extensions = v3_ca # The extensions to add to the self signed cert
string_mask = MASK:0x2002
[req_distinguished_name]
countryName = Country Name (2 letter code)
countryName_default = AU
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Victoria
localityName = Locality Name (eg, city)
localityName_default = Melbourne
0.organizationName = Organization Name (eg, company)
0.organizationName_default = Koozali
organizationalUnitName = Organizational Unit Name (eg, section)
commonName = Common Name (eg, your name or your server\'s hostname)
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 64
[req_attributes]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20
unstructuredName = An optional company name
[usr_cert]
basicConstraints = CA:FALSE
nsComment = "OpenSSL Generated Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
[v3_ca]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
basicConstraints = CA:true
_EOT
Create the ca key for the server
cd /etc/pki/koji
touch index.txt
echo 01 > serial
openssl genrsa -out private/koji_ca_cert.key 2048
openssl req -config ssl.cnf -new -x509 -days 3650 -key private/koji_ca_cert.key -out koji_ca_cert.crt -extensions v3_ca
You will have to enter your details, but make sure the commonName is the full server name (e.g. koji.koozali.org).
Create a script to make certs and make it executable
mkdir -p ~/bin
cat <<_EOT > ~/bin/koji_make_cert.sh
#!/bin/bash
# if you change your certificate authority name to something else you will
# need to change the caname value to reflect the change.
caname=koji
# user is equal to parameter one or the first argument when you actually
# run the script
user=\$1
openssl genrsa -out private/\${user}.key 2048
cat ssl.cnf | sed 's/insert_hostname/'\${user}'/'> ssl2.cnf
openssl req -config ssl2.cnf -new -nodes -out certs/\${user}.csr -key private/\${user}.key
openssl ca -config ssl2.cnf -keyfile private/\${caname}_ca_cert.key -cert \${caname}_ca_cert.crt \
-out certs/\${user}.crt -outdir certs -infiles certs/\${user}.csr
cat certs/\${user}.crt private/\${user}.key > \${user}.pem
mv ssl2.cnf confs/\${user}-ssl.cnf
_EOT
chmod a+x ~/bin/koji_make_cert.sh
Lets create some certificates and add our admin user
koji_make_cert.sh kojihub
koji_make_cert.sh kojiweb
koji_make_cert.sh kojira
koji_make_cert.sh kojid
koji_make_cert.sh kojiadmin
Koji Hub
Install koji hub and pre-requisites
dnf install koji-hub mod_ssl
dnf module enable postgresql:10
dnf install postgresql-server
dnf install koji
POSTGRES setup
As root we need to do the initial config
postgresql-setup --initdb --unit postgresql
systemctl enable postgresql --now
We have a different account for managing the database (i.e. create the koji user and add a password)
useradd koji
passwd koji
Create the koji user and database and add password for user
su - postgres
createuser --no-superuser --no-createrole --no-createdb koji
createdb -O koji koji
psql -c "alter user koji with encrypted password 'mypassword';"
logout
Create the koji db schema from the included script (need to be the koji user)
su - koji
psql koji koji < /usr/share/doc/koji*/docs/schema.sql
exit
Authorize the Koji-hub service to PostgreSQL. As the hub and DB are on the same server we are using Unix sockets for connection
nano /var/lib/pgsql/data/pg_hba.conf
and add the following lines (before the other settings)
#TYPE DATABASE USER CIDR-ADDRESS METHOD
local koji koji trust
local all postgres peer
and blank out the listen address (we are using sockets, not via IP)
nano /var/lib/pgsql/data/postgresql.conf
by changing this line
listen_addresses = ''
and reload the PostgreSQL daemon
systemctl reload postgresql
add the initial admin user manually to the user database (we need to be the koji user to do this)
We can add additional users and change privileges of those users via the koji command line tool after this
su - koji
psql
koji=> insert into users (name, status, usertype) values ('kojiadmin', 0, 0);
koji=> select * from users;
koji=> insert into user_perms (user_id, perm_id, creator_id) values (1, 1, 1);
\q
exit
Koji hub setup
We can now set up the hub itself.
As we are using SSL certificates, we need to tweak the httpd configs
nano /etc/httpd/conf.d/kojihub.conf
and uncomment the lines as below
# uncomment this to enable authentication via SSL client certificates
<Location /kojihub/ssllogin>
# SSLVerifyClient require
# SSLVerifyDepth 10
SSLOptions +StdEnvVars
</Location>
Setup the SSL certificates required
nano /etc/httpd/conf.d/ssl.conf
and add these lines and comment out any existing sample lines that do NOT point at valid certs etc.
SSLCertificateFile /etc/pki/koji/certs/kojihub.crt
SSLCertificateKeyFile /etc/pki/koji/private/kojihub.key
SSLCertificateChainFile /etc/pki/koji/koji_ca_cert.crt
SSLCACertificateFile /etc/pki/koji/koji_ca_cert.crt
and uncomment the following lines
SSLVerifyClient require
SSLVerifyDepth 10
Point Koji Hub to the database
nano /etc/koji-hub/hub.conf
and set these parameters. Make sure that DBHost and DBPass are commented out as we are using the DB on the same host
DBName = koji
DBUser = koji
# If PostgreSQL is on another host, set that here:
#DBHost = db.example.com
#DBPass = mypassword
KojiDir = /mnt/koji
LoginCreatesUser = On
KojiWebURL = http://koji.koozali.org/koji
ProxyDNs should be set to the DN of the kojiweb certificate. For example:
DNUsernameComponent = CN
ProxyDNs = /C=AU/ST=Victoria/L=Melbourne/O=koji/OU=kojiweb/CN=koji.koozali.org
SELinux changes to allow access
setsebool -P httpd_can_network_connect_db 1
Restart httpd
systemctl restart httpd
Create the koji skeleton file system
cd /mnt
mkdir koji
cd koji
mkdir {packages,repos,work,scratch,repos-dist}
chown apache:apache *
and tweak SELinux to allow apache write access
setsebool -P allow_httpd_anon_write=1
semanage fcontext -a -t public_content_rw_t "/mnt/koji(/.*)?"
restorecon -r -v /mnt/koji
Make sure that the firewall will allow http & https access
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
Koji CLI client
Let's configure the cli client. The system setting is in /etc/koji.conf, individual user settings can be set in ~/.koji/config
nano /etc/koji.conf
We define the urls of each component and tell it where to find the SSL certificates (we copied them across earlier)
[koji]
;url of XMLRPC server
server = http://koji.koozali.org/kojihub
;url of web interface
weburl = https://koji.koozali.org/koji
;url of package download site
topurl = http://koji.koozali.org/kojifiles
;path to the koji top directory
topdir = /mnt/koji
; configuration for SSL athentication
;client certificate
cert = ~/.koji/client.crt
;certificate of the CA that issued the HTTP server certificate
serverca = ~/.koji/serverca.crt
Now we create the koji administration user (kojiadmin) and set up the certs. We need to be the kojiadmin user to get the right permissions when we copy over the required certs, so...
useradd kojiadmin
su - kojiadmin
mkdir ~/.koji
cp /etc/pki/koji/kojiadmin.pem ~/.koji/client.crt # NOTE: It is IMPORTANT you use the PEM and NOT the CRT
cp /etc/pki/koji/koji_ca_cert.crt ~/.koji/clientca.crt
cp /etc/pki/koji/koji_ca_cert.crt ~/.koji/serverca.crt
chmod 0600 ~/.koji/*.crt
Test the connection
koji moshimoshi
you should see
zdravstvuite, kojiadmin!
You are using the hub at https://koji.koozali.org/kojihub
Authenticated via client certificate /home/kojiadmin/.koji/client.crt
and don't forget to logout from the kojiadmin user :)
exit
Koji Web Service
Install the koji web components
dnf install koji-web mod_ssl
edit the web config file to point at the right urls and SSL certificates
nano /etc/kojiweb/web.conf
Please insert a random string into the secret (replace CHANGE_ME)
[web]
SiteName = koji
# KojiTheme =
# Necessary urls
KojiHubURL = http://koji.koozali.org/kojihub
KojiFilesURL = http://koji.koozali.org/kojifiles
## Kerberos authentication options
; WebPrincipal = koji/web@EXAMPLE.COM
; WebKeytab = /etc/httpd.keytab
; WebCCache = /var/tmp/kojiweb.ccache
## SSL authentication options
WebCert = /etc/kojiweb/client.crt
KojiHubCA = /etc/kojiweb/clientca.crt
LoginTimeout = 72
# This must be set before deployment
Secret = CHANGE_ME
LibPath = /usr/share/koji-web/lib
Copy the certificates into the /etc/kojiweb dir and give the correct permissions
cp /etc/pki/koji/kojiweb.pem /etc/kojiweb/client.crt
cp /etc/pki/koji/koji_ca_cert.crt /etc/kojiweb/clientca.crt
cp /etc/pki/koji/koji_ca_cert.crt /etc/kojiweb/serverca.crt
chmod 0600 /etc/kojiweb/*.crt
Edit the httpd file
nano /etc/httpd/conf.d/kojiweb.conf
and uncomment the required ssl options
# uncomment this to enable authentication via SSL client certificates
<Location /koji/login>
# SSLVerifyClient require
# SSLVerifyDepth 10
SSLOptions +StdEnvVars
</Location>
Restart the httpd daemon
systemctl restart httpd
Koji Builders
For this exercise I only created 1 build server. You can have as many as you like...
OS: Rocky 8.8-minimal
Memory: 8GB
Disk: 20GB (can apparently use a lot of disk, depending on how active a build server it is)
FQDN: build1.koozali.org
Koji Hub setup for build server
First off, set up some items on the koji hub for your build server/s
Create a ssl cert for the build server with CN=build1.koozali.org
koji_make_cert.sh build1.koozali.org
Add the build server into the koji database
su - kojiadmin
koji add-host build1.koozali.org x86_64 noarch
koji add-host-to-channel build1.koozali.org createrepo
exit
We'll want the build servers to have access to the koji filesystem via nfs, so on the koji hub server (koji.koozali.org)
dnf install nfs-utils
systemctl enable --now nfs-server
systemctl start nfs-server
nano /etc/exports
we only have one build server, but you can add additional build servers to the line, separated by a space
/mnt/koji build1.koozali.org(rw,sync,root_squash)
export, verify and allow Apache access via SELinux
exportfs -ra
exportfs -v
setsebool -P httpd_use_nfs=1
Allow nfs access through the firewall
firewall-cmd --permanent --add-service=nfs
firewall-cmd --permanent --add-service=mountd
firewall-cmd --permanent --add-service=rpc-bind
firewall-cmd --reload
Builder setup
You'll need to set up your network: You can do this during the install or post install (ensure network activated, IP address, FQDN, Gateway, DNS)
Log into your build server as root and
nmtui
ip addr
ping google.com
Let's bring the server up to date
dnf update
Add the epel repository and some tools to help with debugging (cockpit available at http://<IP addr or FQDN>:9090
systemctl enable --now cockpit.socket
systemctl start cockpit.socket
dnf config-manager --set-enabled powertools
dnf install epel-release
dnf install rsyslog
dnf install setroubleshoot-server
Install the koji build daemon
dnf install koji-builder
Edit the kojid config file
nano /etc/kojid/kojid.conf
Point the builder at your koji hub and setup user/SSL credentials
; 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 URL for the xmlrpc server
server=http://koji.koozali.org/kojihub
user=build1.koozali.org
; The URL for the file access
topurl=http://koji.koozali.org/kojifiles
;client certificate
cert = /etc/kojid/client.crt
;certificate of the CA that issued the HTTP server certificate
serverca = /etc/kojid/serverca.crt
Copy over your ssl certs from your koji hub and set their correct permissions
scp root@koji.koozali.org:/etc/pki/koji/build1.koozali.org.pem /etc/kojid/client.crt
scp root@koji.koozali.org:/etc/pki/koji/koji_ca_cert.crt /etc/kojid/serverca.crt
chmod 0600 /etc/kojid/*.crt
Enable and start the kojid service
systemctl enable kojid --now
systemctl start kojid