Tag Archives: poudriere

Keycloak Identity and Access Management on FreeBSD

Many times I wrote about FreeIPA/IDM – but I have one problem with it – its not currently possible to run FreeIPA on FreeBSD … so I searched for other open source alternatives and found Keycloak. What surprised me even more is that its even available in the FreeBSD Ports as net/keycloak port. So I wanted to check how it works/runs on FreeBSD … and this is exactly how this article happened.

keycloak.logo

My earlier FreeIPA/IDM attempts are below.

First – we will create new VM for our server. I will use sysutils/vm-bhyve-devel for Bhyve but feel free to use any other hypervisor (or even w/o one). To not waste time installing I will also use provided by FreeBSD project VM-IMAGE with ZFS enabled – FreeBSD-14.0-RELEASE-amd64-zfs.raw disk0.img

host # cat /vm/.templates/freebsd.conf
loader="bhyveload"
cpu=1
memory=256M
network0_type="virtio-net"
network0_switch="public"
disk0_type="nvme"
disk0_name="disk0.img"

host # vm create -t freebsd -c 2 -m 4G -s 10G keycloak

host # ls -lh /vm/keycloak
total 3402399
-rw-------  1 root wheel   10G Mar 10 10:47 disk0.img
-rw-r--r--  1 root wheel  209B Mar 10 07:20 keycloak.conf
-rw-r--r--  1 root wheel   96B Mar 10 07:22 vm-bhyve.log

host # cd /vm/keycloak

host # rm -f disk0.img

host # cp /vm/TEMPLATE/FreeBSD-14.0-RELEASE-amd64-zfs.raw disk0.img

host # truncate -s 10G disk0.img

host # vm start keycloak
Starting keycloak
  * found guest in /vm/keycloak
  * booting...

host # vm console keycloak

Type root as user and hit [ENTER] for empty password. Now the FreeBSD setup and needed packages.

root@freebsd:~ # :> ~/.hushlogin

root@freebsd:~ # cat << EOF > /etc/rc.conf
hostname="keycloak.lab.org"
ifconfig_DEFAULT="inet 10.1.1.211/24"
defaultrouter="10.1.1.1"
growfs_enable="YES"
zfs_enable="YES"
sshd_enable="YES"
postgresql_enable="YES"
keycloak_enable="YES"
keycloak_env="KEYCLOAK_ADMIN=admin KEYCLOAK_ADMIN_PASSWORD=password"
EOF

root@freebsd:~ # echo 10.1.1.211 keycloak.lab.org keycloak >> /etc/hosts

root@freebsd:~ # mkdir -p /usr/local/etc/pkg/repos

root@freebsd:~ # sed -e s/quarterly/latest/g /etc/pkg/FreeBSD.conf \
                   > /usr/local/etc/pkg/repos/FreeBSD.conf

root@freebsd:~ # echo nameserver 1.1.1.1 > /etc/resolv.conf

root@freebsd:~ # drill freebsd.org | grep '^[^;]'
freebsd.org.        799     IN      A       96.47.72.84

root@freebsd:~ # service netif restart

root@freebsd:~ # service routing restart

root@freebsd:~ # service hostname restart
Setting hostname: keycloak.lab.org.

root@keycloak:~ # passwd
Changing local password for root
New Password:
Retype New Password:

root@keycloak:~ # cat << EOF >> /etc/ssh/sshd_config
PermitRootLogin yes
UseDNS no
EOF

root@keycloak:~ # service sshd enable

root@keycloak:~ # service sshd start

root@keycloak:~ # exit

Now switch to ssh(1) for better experience – needed to paste larger blocks of configs/text.

host % ssh root@10.1.1.211

root@keycloak:~ # pkg install -y keycloak postgresql16-server postgresql16-client

root@keycloak:~ # service postgresql enable

root@keycloak:~ # service postgresql initdb

root@keycloak:~ # service postgresql start

root@keycloak:~ # sockstat -l4
USER     COMMAND    PID   FD  PROTO  LOCAL ADDRESS         FOREIGN ADDRESS      
postgres postgres    2265 7   tcp4   127.0.0.1:5432        *:*
root     syslogd      656 7   udp4   *:514                 *:*

root@keycloak:~ # su - postgres -c psql
psql (16.2)
Type "help" for help.

postgres=# ALTER USER postgres WITH PASSWORD 'password';

postgres=# CREATE DATABASE keycloak with encoding 'UTF8';
CREATE DATABASE

postgres=# GRANT ALL ON DATABASE keycloak TO postgres;
GRANT

postgres=# \q

root@keycloak:~ # cd /usr/local/share/java/keycloak/conf

root@keycloak:~ # openssl req -x509 -newkey rsa:2048 -keyout server.key.pem -out server.crt.pem -days 36500 -nodes -subj "/C=PL/ST=lodzkie/L=Lodz/O=Vermaden/OU=HR/CN=keycloak.lab.org"

root@keycloak:~ # chmod 600 server.crt.pem server.key.pem

root@keycloak:~ # chown keycloak:keycloak server.crt.pem server.key.pem

root@keycloak:~ # cat << EOF > /usr/local/share/java/keycloak/conf/keycloak.conf               
db=postgres
db-username=postgres
db-password=password
db-url=jdbc:postgresql://localhost:5432/keycloak
hostname-strict-https=true
hostname-url=https://keycloak.lab.org:8443/
hostname-admin-url=https://keycloak.lab.org:8443/
https-certificate-file=/usr/local/share/java/keycloak/conf/server.crt.pem
https-certificate-key-file=/usr/local/share/java/keycloak/conf/server.key.pem
proxy=edge
EOF

root@keycloak:~ # echo quarkus.transaction-manager.enable-recovery=true \
                    > /usr/local/share/java/keycloak/conf/quarkus.properties

root@keycloak:~ # chown keycloak:keycloak /usr/local/share/java/keycloak/conf/quarkus.properties

root@keycloak:~ # service keycloak enable

root@keycloak:~ # service keycloak build
The following run time non-cli properties were found, but will be ignored during build time: kc.db-url, kc.db-username, kc.db-password, kc.hostname-url, kc.hostname-admin-url, kc.hostname-strict-https, kc.https-certificate-file, kc.https-certificate-key-file, kc.proxy
Updating the configuration and installing your custom providers, if any. Please wait.
2024-03-10 09:01:17,701 INFO  [io.quarkus.deployment.QuarkusAugmentor] (main) Quarkus augmentation completed in 29796ms
Server configuration updated and persisted. Run the following command to review the configuration:

        kc.sh show-config

root@keycloak:~ # /usr/local/share/java/keycloak/bin/kc.sh show-config
Current Mode: production
Current Configuration:
        kc.config.built =  true (SysPropConfigSource)
        kc.db =  postgres (PropertiesConfigSource)
        kc.db-password =  ******* (PropertiesConfigSource)
        kc.db-url =  jdbc:postgresql://localhost:5432/keycloak (PropertiesConfigSource)
        kc.db-username =  postgres (PropertiesConfigSource)
        kc.hostname-admin-url =  https://keycloak.lab.org:8443/ (PropertiesConfigSource)
        kc.hostname-strict-https =  true (PropertiesConfigSource)
        kc.hostname-url =  https://keycloak.lab.org:8443/ (PropertiesConfigSource)
        kc.https-certificate-file =  /usr/local/share/java/keycloak/conf/server.crt.pem (PropertiesConfigSource)
        kc.https-certificate-key-file =  /usr/local/share/java/keycloak/conf/server.key.pem (PropertiesConfigSource)
        kc.log-console-output =  default (PropertiesConfigSource)
        kc.log-file =  ${kc.home.dir:default}${file.separator}data${file.separator}log${file.separator}keycloak.log (PropertiesConfigSource)
        kc.optimized =  true (PersistedConfigSource)
        kc.proxy =  edge (PropertiesConfigSource)
        kc.spi-hostname-default-admin-url =  https://keycloak.lab.org:8443/ (PropertiesConfigSource)
        kc.spi-hostname-default-hostname-url =  https://keycloak.lab.org:8443/ (PropertiesConfigSource)
        kc.spi-hostname-default-strict-https =  true (PropertiesConfigSource)
        kc.version =  23.0.6 (SysPropConfigSource)

We now have needed packages installed. Self signed certificate for HTTPS generated. PostgreSQL database and Keycloak configured. We will need small patch to enable passing env(1) variables at the Keycloak daemon start. It will allow to use keycloak_env at the /etc/rc.conf main FreeBSD config file. This is needed to configure the initial admin user as sated in the Keycloak documentation.

keycloak-0-initial-admin-user

Now back to the patch.

root@keycloak:~ # cat /root/keycloak.patch
--- /root/keycloak      2024-03-08 11:46:21.847315000 +0000
+++ /usr/local/etc/rc.d/keycloak        2024-03-08 11:47:22.027102000 +0000
@@ -28,6 +28,7 @@
 : ${keycloak_enable:=NO}
 : ${keycloak_user:=keycloak}
 : ${keycloak_group:=keycloak}
+: ${keycloak_env:=""}
 : ${keycloak_flags="start"}
 : ${keycloak_java_home="/usr/local/openjdk17"}
 
@@ -54,6 +55,7 @@
 
        echo "Starting keycloak."
         ${command} ${command_args} \
+                env ${keycloak_env} \
                 /usr/local/share/java/keycloak/bin/kc.sh \
                 ${keycloak_flags}
 }

root@keycloak:~ # cd /usr/local/etc/rc.d

root@keycloak:/usr/local/etc/rc.d # patch < /root/keycloak.patch
Hmm...  Looks like a unified diff to me...
The text leading up to this was:
--------------------------
|--- /root/keycloak      2024-03-08 11:46:21.847315000 +0000
|+++ /usr/local/etc/rc.d/keycloak        2024-03-08 11:47:22.027102000 +0000
--------------------------
Patching file keycloak using Plan A...
Hunk #1 succeeded at 28.
Hunk #2 succeeded at 55 with fuzz 2.
Hmm...  Ignoring the trailing garbage.
done

Now we will start Keycloak. Its possible to track its startup process in the /var/log/keycloak/keycloak.out file. Below You will find last 4 lines that you want to see – with Keycloak 23.0.6 on JVM (powered by Quarkus 3.2.10.Final) started in 19.251s. message πŸ™‚

root@keycloak:~ # service keycloak start

root@keycloak:~ # tail -f /var/log/keycloak/keycloak.out
(...)
2024-03-10 09:12:15,550 INFO  [io.quarkus] (main) Keycloak 23.0.6 on JVM (powered by Quarkus 3.2.10.Final) started in 19.251s. Listening on: http://0.0.0.0:8080 and https://0.0.0.0:8443
2024-03-10 09:12:15,551 INFO  [io.quarkus] (main) Profile prod activated. 
2024-03-10 09:12:15,552 INFO  [io.quarkus] (main) Installed features: [agroal, cdi, hibernate-orm, jdbc-h2, jdbc-mariadb, jdbc-mssql, jdbc-mysql, jdbc-oracle, jdbc-postgresql, keycloak, logging-gelf, micrometer, narayana-jta, reactive-routes, resteasy-reactive, resteasy-reactive-jackson, smallrye-context-propagation, smallrye-health, vertx]
2024-03-10 09:12:16,303 INFO  [org.keycloak.services] (main) KC-SERVICES0009: Added user 'admin' to realm 'master'
[CTRL]-[C]

root@keycloak:~ # top -ab -o res 10
last pid:  3067;  load averages:  0.50,  0.47,  0.42  up 0+02:56:35    09:19:04
18 processes:  1 running, 17 sleeping
CPU:  1.4% user,  0.0% nice,  0.4% system,  0.2% interrupt, 98.0% idle
Mem: 299M Active, 176M Inact, 3247M Wired, 264K Buf, 202M Free
ARC: 2965M Total, 902M MFU, 1982M MRU, 4096B Anon, 12M Header, 50M Other
     2766M Compressed, 2934M Uncompressed, 1.06:1 Ratio
Swap: 1024M Total, 1024M Free

  PID USERNAME    THR PRI NICE   SIZE    RES STATE    C   TIME    WCPU COMMAND
 2981 keycloak     41  68    0  1425M   299M uwait    1   0:37   0.00% /usr/local/openjdk17/bin/java -Dkc.config.built=true -Xms64m -Xmx512m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.err.encoding=UTF-8 -Dstdout.encoding=UTF-8 -Dstderr.encoding=UTF-8 -XX:+ExitOnOutOfMemoryError -Djava.security.egd=file:/dev/urandom -XX:+UseParallelGC -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -XX:FlightRecorderOptions=stackdepth=512 --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.security=ALL-UNNAMED -Dkc.home.dir=/usr/local/share/java/keycloak/bin/.. -Djboss.server.config.dir=/usr/local/share/java/keycloak/bin/../conf -Djava.util.logging.manager=org.jboss.logmanager.LogManager -Dquarkus-log-max-startup-records=10000 -cp /usr/local/share/java/keycloak/bin/../lib/quarkus-run.jar io.quarkus.bootstrap.runner.QuarkusEntryPoint start
 3063 postgres      1  24    0   181M    49M kqread   1   0:00   0.00% postgres: postgres keycloak 127.0.0.1(21936) idle (postgres)
 2266 postgres      1  20    0   178M    48M kqread   1   0:00   0.00% postgres: checkpointer  (postgres)
 3062 postgres      1  20    0   181M    47M kqread   1   0:00   0.00% postgres: postgres keycloak 127.0.0.1(22820) idle (postgres)
 2270 postgres      1  20    0   179M    31M kqread   0   0:00   0.00% postgres: autovacuum launcher  (postgres)
 2271 postgres      1  20    0   179M    31M kqread   0   0:00   0.00% postgres: logical replication launcher  (postgres)
 2269 postgres      1  20    0   178M    31M kqread   0   0:00   0.00% postgres: walwriter  (postgres)
 2267 postgres      1  20    0   178M    31M kqread   0   0:00   0.00% postgres: background writer  (postgres)
 2265 postgres      1  20    0   178M    30M kqread   0   0:00   0.00% /usr/local/bin/postgres -D /var/db/postgres/data16
 2420 root          1  20    0    22M    11M select   1   0:01   0.00% sshd: root@pts/0 (sshd)

Add also on the host system the IP information to the /etc/hosts file and check https://keycloak.lab.org:8443 in your browser.

host # echo 10.1.1.211 keycloak.lab.org keycloak >> /etc/hosts

host % firefox 'https://keycloak.lab.org:8443'

As we use self signed certificate You will be warned by potential security risk. Hit ‘Advanced’ and then ‘Accept the Risk and Continue’ buttons.

keycloak-1-self-cert

Next click the Administration Console link.

keycloak-2-main-page

Login with admin and password (or your password if You used other one).

keycloak-3-admin-login

… and You can now create your new realm, add users, create groups etc. You have fully working Keycloak in production mode.

keycloak-4-admin-console

Now … like with FreeIPA/IDM – it would be nice to attach FreeBSD to it so one could login to FreeBSD system with Keycloak user … not so fast unfortunately. To make such things be possible You need a PAM module for Keycloak … and I was not able to find one that will work on FreeBSD … and the Keycloak package also comes without one.

root@keycloak:~ # pkg info -l keycloak | grep -i pam
root@keycloak:~ # 

After grepping the Internet I found two solutions … but only for Linux.

One of them was a step by step Keycloak PAM Module Development Tutorial guide which showed you how to write such PAM module.

pam-dev

The other one was Keycloak SSH PAM project on GitHub which provided more or less ready solution for Linux systems.

pam-kc

So while with FreeIPA/IDM we had server on Linux that allowed to connect FreeBSD systems to it – we now hat Keycloak server hosted on FreeBSD that allows connecting Linux systems πŸ™‚

Not much of an improvement – but maybe someone will find that guide useful.

EOF

Connect FreeBSD 14.0-STABLE to FreeIPA/IDM

In the open source world everything lives/evolves/changes. This is why the new version of connecting latest FreeBSD 14.0-STABLE system to the FreeIPA/IDM is needed. One of the things that changed is that security/sssd is now deprecated and security/sssd2 is its successor. Also new version of ports-mgmt/poudriere-devel is available – with needed fixes already merged – and also with new restyled web interface.

FreeIPA-logo

I already messed with that topic several times in the past:

This article will try to address and contain all steps needed – including setting up the FreeIPA/IDM server and including the Poudriere setup. Below You will find Table of Contents for this article. All of these systems will be Bhyve virtual machines.

  • FreeIPA/IDM Server – Installation
  • FreeIPA/IDM Server – Configuration
  • Poudriere Server – Setup
  • Poudriere Server – Build FreeIPA/IDM Client Packages
  • Poudriere Server – Update Repo/Packages
  • FreeBSD 14.0-STABLE Client – Setup
  • FreeBSD 14.0-STABLE Client – Debug Commands
  • Summary

The FreeBSD project recently started to provide ZFS based VM images … but unfortunately only for 14.0-RELEASE and they are not created for 14.0-STABLE or 15-CURRENT versions – so we will use the UFS based ones for both Poudriere server and FreeBSD FreeIPA/IDM client. For the record – https://download.freebsd.org/snapshots/VM-IMAGES/14.0-STABLE/amd64/Latest/ – they are available here.

Some note about commands run in this article – different colors for various hosts.

host # top -ba -o res 3                                  // executed on the host system
[root@idm ~]# yum update -y                              // executed on IDM server
root@freebsd:~ # geom disk list                          // executed on Poudriere server
root@poudriere-devel-14-stable:~ # poudriere ports -l   Β // executed on Poudriere server
root@idm-client:~ # hostname idm-client.lab.org          // executed on IDM client (FreeBSD)
  important information                                  // marked as GREEN color

For the FreeIPA/IDM server I have used Alma Linux RHEL clone – but we know that Rocky Linux or Oracle Linux would also work well. We will use three systems in this article.

FreeIPA/IDM server – with idm.lab.org hostname.

      OS: Alma Linux
      IP: 10.0.0.200/24
      GW: 10.0.0.1
  domain: lab.org
   realm: LAB.ORG
hostname: idm.lab.org

Poudriere builder system – with poudriere-devel-14-stable.lab.org hostname.

      OS: FreeBSD 14.0-STABLE
      IP: 10.0.0.124/24
      GW: 10.0.0.1
     DNS: 1.1.1.1
  domain: -
   realm: -
hostname: poudriere-devel-14-stable.lab.org

FreeBSD client for FreeIPA/IDM system – with idm-client.lab.org hostname.

      OS: FreeBSD 14.0-STABLE
      IP: 10.0.0.233/24
      GW: 10.0.0.1
     DNS: 10.0.0.200
  domain: lab.org
   realm: LAB.ORG
hostname: idm-client.lab.org

I really like the FreeBSD Bhyve memory ballooning – which means the guest VMs only take as much RAM as guest OS allocated and not 12 GB RAM as is configured.

host # vm list | grep -e STATE -e Running
NAME                       DATASTORE  LOADER     CPU  MEMORY  VNC           AUTO     STATE
idm                        default    uefi       2    4g      0.0.0.0:5900  No       Running (25284)
idm-client-14-stable       default    bhyveload  2    1g      -             No       Running (29517)
poudriere-devel-14-stable  default    bhyveload  8    12g     -             Yes [1]  Running (23419)

host # top -ba -o res 3
last pid:  1290;  load averages:  0.09,  0.09,  0.08  up 0+00:47:08    07:05:20
32 processes:  1 running, 31 sleeping
CPU:  0.0% user,  0.0% nice,  0.6% system,  0.0% interrupt, 99.4% idle
Mem: 2983M Active, 463M Inact, 1060M Wired, 56K Buf, 27G Free
ARC: 619M Total, 115M MFU, 497M MRU, 32K Anon, 2346K Header, 4231K Other
     551M Compressed, 1080M Uncompressed, 1.96:1 Ratio
Swap: 4096M Total, 4096M Free

  PID USERNAME    THR PRI NICE   SIZE    RES STATE    C   TIME    WCPU COMMAND
25284 root         13  20    0  4159M  1168M kqread  13   3:12   1.27% bhyve: idm (bhyve)
23419 root         19  20    0    12G   109M kqread  15   0:27   0.00% bhyve: poudriere-devel-14-stable (bhyve)
29517 root         13  20    0  1075M    77M kqread   5   0:20   0.00% bhyve: idm-client-14-stable (bhyve)

As you can see I am using sysutils/vm-bhyve-devel for the Bhyve management – but You may as well use bare /usr/share/examples/bhyve/vmrun.sh instead … or even entirely different hypervisor like KVM on Linux or VirtualBox on Windows – it does not matter as long as machines have access to the Internet and they see each other in the same LAN network.

FreeIPA/IDM Server – Installation

I installed the Alma Linux some time ago – so the screenshot shows older 8.7 version.

LAB.IDM.Server.ROOT

After reboot its network is configured as shown below.

[root@idm ~]# cat /etc/sysconfig/network-scripts/ifcfg-enp0s3
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=none
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=no
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=eui64
NAME=enp0s3
UUID=120efe1f-3cb6-40cf-8aad-b17066c08543
DEVICE=enp0s3
ONBOOT=yes
IPADDR=10.0.0.200
PREFIX=24
GATEWAY=10.0.0.1
DNS1=1.1.1.1
IPV6_DISABLED=yes

Some more basic setup commands below.


[root@idm ~]# echo 10.0.0.200 idm.lab.org idm >> /etc/hosts

[root@idm ~]# cat << EOF >> /etc/sysctl.conf
# DISABLE IPv6 FOR MAIN enp0s3 INTERFACE
net.ipv6.conf.enp0s3.disable_ipv6=1
EOF

[root@idm ~]# hostnamectl set-hostname idm.lab.org

[root@idm ~]# timedatectl set-timezone Europe/Warsaw

[root@idm ~]# timedatectl set-local-rtc 0

[root@idm ~]# yum update -y

[root@idm ~]# reboot

Continuation after reboot.

[root@idm ~]# yum module enable idm:DL1 -y

[root@idm ~]# yum distro-sync -y

[root@idm ~]# yum install -y bind-utils chrony nc

[root@idm ~]# ipa-server-install                        \
                    --domain lab.org                    \
                    --realm LAB.ORG                     \
                    --reverse-zone=0.0.10.in-addr.arpa. \
                    --allow-zone-overlap                \
                    --no-forwarders                     \
                    --ntp-pool pool.ntp.org             \
                    --setup-dns                         \
                    --ds-password    password           \
                    --admin-password password           \
                    --unattended

[root@idm ~]# ipactl status
Directory Service: RUNNING
krb5kdc Service: RUNNING
kadmin Service: RUNNING
named Service: RUNNING
httpd Service: RUNNING
ipa-custodia Service: RUNNING
pki-tomcatd Service: RUNNING
ipa-otpd Service: RUNNING
ipa-dnskeysyncd Service: RUNNING
ipa: INFO: The ipactl command was successful

[root@idm ~]# systemctl list-unit-files | grep ipa | grep service
ipa-ccache-sweep.service                   static   
ipa-custodia.service                       disabled 
ipa-dnskeysyncd.service                    disabled 
ipa-healthcheck.service                    disabled 
ipa-ods-exporter.service                   disabled 
ipa-otpd@.service                          static   
ipa.service                                enabled

[root@idm ~]# systemctl enable --now httpd

[root@idm ~]# systemctl list-unit-files | grep httpd.service
httpd.service                              enabled  

[root@idm ~]# systemctl disable firewalld

[root@idm ~]# systemctl stop    firewalld

[root@idm ~]# cat /etc/sssd/sssd.conf
[domain/lab.org]
  ipa_server_mode                = True
  ipa_server                     = idm.lab.org
  ipa_hostname                   = idm.lab.org
  ipa_domain                     = lab.org
  id_provider                    = ipa
  auth_provider                  = ipa
  chpass_provider                = ipa
  access_provider                = ipa
  cache_credentials              = True
  ldap_tls_cacert                = /etc/ipa/ca.crt
  krb5_store_password_if_offline = True

[sssd]
  services = nss, pam, ifp, ssh, sudo
  domains  = lab.org

[nss]
  homedir_substring = /home
  memcache_timeout  = 600

[pam]

[sudo]

[autofs]

[ssh]

[pac]

[ifp]
  allowed_uids = ipaapi, root

[session_recording]

If you would like to see what a successful ipa-server-install(8) looks like – you can take a look HERE.

We have our FreeIPA/IDM server installed.

You will need to add 10.0.0.200 as idm.lab.org to your /etc/hosts on the system where you will be using the browser (or to your local DNS).

host # grep idm /etc/hosts
10.0.0.200  idm.lab.org  idm

You can login to it typing https://10.0.0.200 at your local browser – you will be redirected to https://idm.lab.org/ipa/ui/ immediately and you will see the login page as shown below.

FreeIPA-login-1

You may login with admin username and the password you specified for the ipa-server-install(8) command (or password if you just copy pasted that command πŸ™‚

FreeIPA/IDM Server – Configuration

… and after logging in I created a regular vermaden user as shown below.

FreeIPA-login-2

Keep in mind to reset your password by connecting to FreeIPA/IDM server.

host # ssh -l vermaden 10.0.0.200
(vermaden@10.0.0.200) Password:
(vermaden@10.0.0.200) Password expired. Change your password now.
Current Password:
(vermaden@10.0.0.200) New password:
(vermaden@10.0.0.200) Retype new password:
Last failed login: Wed Oct 19 00:47:57 CEST 2022 from 10.0.0.33 on ssh:notty
There was 1 failed login attempt since the last successful login.

[vermaden@idm /]$ w
 12:58:50 up  6:39,  1 user,  load average: 0.02, 0.05, 0.00
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
vermaden pts/0    10.0.0.4         12:58    1.00s  0.04s  0.01s w

The more important configuration is in HBAC and Sudo rules.

Here are HBAC related settings.

idm-1-hbac-rules-menu

idm-2-hbac-rules-menu

idm-3-hbac-rules-freebsd-details

… and the Sudo part.

idm-4-sudo-rules-menu

idm-5-sudo-rules-freebsd

idm-6-sudo-rules-freebsd-details

Poudriere Server – Setup

One note for the FreeBSD setups below – please use /bin/sh shell (default for root since 14.0-RELEASE) for the commands … or zsh(1) for example … or other POSIX compatible shell. Some of these commands may not work properly on ‘C’ based shells or in fish(1) shell.

This is the template I used for Bhyve VMs.

host # cat /vm/.templates/freebsd.conf 
loader="bhyveload"
cpu=1
memory=256M
network0_type="virtio-net"
network0_switch="public"
disk0_type="nvme"
disk0_name="disk0.img"

We will now create poudriere-devel-14-stable VM for Poudriere server.

host # vm create -t freebsd -s 20g -m 12g -c 8 poudriere-devel-14-stable

host # du -sgA /vm/poudriere-devel-14-stable/*
20      /vm/poudriere-devel-14-stable/disk0.img
1       /vm/poudriere-devel-14-stable/poudriere-devel-14-stable.conf
1       /vm/poudriere-devel-14-stable/vm-bhyve.log

Now we will replace disk0.img with Latest FreeBSD 14.0-STABLE snapshot.

host # fetch -o - 'https://download.freebsd.org/snapshots/VM-IMAGES/14.0-STABLE/amd64/Latest/FreeBSD-14.0-STABLE-amd64.raw.xz' \
         | xz -d > /vm/poudriere-devel-14-stable/disk0.img

host # file -b /vm/poudriere-devel-14-stable/disk0.img 
DOS/MBR boot sector; partition 1 : ID=0xee, start-CHS (0x0,0,2), end-CHS (0x3ff,255,63), startsector 1, 12649684 sectors

host # du -sgA /vm/poudriere-devel-14-stable/*
7       /vm/poudriere-devel-14-stable/disk0.img
1       /vm/poudriere-devel-14-stable/poudriere-devel-14-stable.conf
1       /vm/poudriere-devel-14-stable/vm-bhyve.log

We now need to add additional disk1.img disk to for ZFS pool.

host # truncate -s 10G /vm/poudriere-devel-14-stable/disk0.img

host # vm add -d disk -t file -s 100g poudriere-devel-14-stable

host # vm info poudriere-devel-14-stable | grep -A 16 virtual-disk
  virtual-disk
    number: 0
    device-type: file
    emulation: nvme
    options: -
    system-path: /vm/poudriere-devel-14-stable/disk0.img
    bytes-size: 10737418240 (10.000G)
    bytes-used: 1720046592 (1.601G)

  virtual-disk
    number: 1
    device-type: file
    emulation: nvme
    options: -
    system-path: /vm/poudriere-devel-14-stable/disk1.img
    bytes-size: 107374182400 (100.000G)
    bytes-used: 1024 (1.000K)

host # du -sgA /vm/poudriere-devel-14-stable/*
10      /vm/poudriere-devel-14-stable/disk0.img
100     /vm/poudriere-devel-14-stable/disk1.img
1       /vm/poudriere-devel-14-stable/poudriere-devel-14-stable.conf
1       /vm/poudriere-devel-14-stable/vm-bhyve.log

Now internally inside VM.

host # vm start poudriere-devel-14-stable                              
Starting poudriere-devel-14-stable
  * found guest in /vm/poudriere-devel-14-stable
  * booting...

host # vm console poudriere-devel-14-stable
(...)
Starting devd.
Starting dhclient.
DHCPDISCOVER on vtnet0 to 255.255.255.255 port 67 interval 4
DHCPOFFER from 10.0.0.1
DHCPREQUEST on vtnet0 to 255.255.255.255 port 67
DHCPACK from 10.0.0.1
bound to 10.0.0.23 -- renewal in 43200 seconds.
add host 127.0.0.1: gateway lo0 fib 0: route already in table
add host ::1: gateway lo0 fib 0: route already in table
add net fe80::: gateway ::1
add net ff02::: gateway ::1
add net ::ffff:0.0.0.0: gateway ::1
add net ::0.0.0.0: gateway ::1
Updating motd:.
Updating /var/run/os-release done.
Clearing /tmp (X related).
Creating and/or trimming log files.
Starting syslogd.
Mounting late filesystems:.
Starting cron.
Starting background file system checks in 60 seconds.

Wed Mar  6 08:23:03 UTC 2024

FreeBSD/amd64 (freebsd) (ttyu0)

login: 


Use the root user with ’empty’ password – just hit [ENTER] key on password prompt.

root@freebsd:~ # :> ~/.hushlogin

root@freebsd:~ # passwd root
Changing local password for root
New Password:
Retype New Password:

root@freebsd:~ # geom disk list
Geom name: nda0
Providers:
1. Name: nda0
   Mediasize: 10737418240 (10G)
   Sectorsize: 512
   Mode: r3w3e8
   descr: bhyve-NVMe
   lunid: 589cfc2012350001
   ident: NVME-4-0
   rotationrate: 0
   fwsectors: 0
   fwheads: 0

Geom name: nda1
Providers:
1. Name: nda1
   Mediasize: 107374182400 (100G)
   Sectorsize: 512
   Mode: r0w0e0
   descr: bhyve-NVMe
   lunid: 589cfc20d2f40001
   ident: NVME-4-1
   rotationrate: 0
   fwsectors: 0
   fwheads: 0

root@freebsd:~ # zpool create zroot nda1
ZFS filesystem version: 5
ZFS storage pool version: features support (5000)

root@freebsd:~ # zfs set mountpoint=none zroot

root@freebsd:~ # zfs list
NAME    USED  AVAIL  REFER  MOUNTPOINT
zroot   100K  96.4G    24K  none

Now some basic configuration.

root@freebsd:~ # cat /etc/rc.conf
hostname="poudriere-devel-14-stable.lab.org"
ifconfig_DEFAULT="inet 10.0.0.124/24 up"
defaultrouter="10.0.0.1"
zfs_enable="YES"
sshd_enable="YES"
nginx_enable="YES"

root@freebsd:~ # cat /etc/hosts
::1         localhost  localhost.my.domain
127.0.0.1   localhost  localhost.my.domain
10.0.0.124  poudriere-devel-14-stable.lab.org  poudriere-devel-14-stable

root@freebsd:~ # service sshd start

root@freebsd:~ # mkdir -p /usr/local/etc/pkg/repos

root@freebsd:~ # sed -e s/quarterly/latest/g /etc/pkg/FreeBSD.conf \
                   > /usr/local/etc/pkg/repos/FreeBSD.conf

root@freebsd:~ # pkg install -y    \
                   beadm           \
                   lsblk           \
                   poudriere-devel \
                   nginx           \
                   git-lite        \
                   ccache4         \
                   tree            \
                   screen

root@freebsd:~ # reboot

Fortunately we do not need to patch ports-mgmt/poudriere-devel anymore as the -u flag for sort(1) is already there.

root@poudriere-devel-14-stable:~ # grep remote_all_ /usr/local/share/poudriere/common.sh | grep sort
            "${remote_all_options}" | sort -k1.2 -u | paste -s -d ' ' -)
            "${remote_all_dept}" | sort -u | paste -s -d ' ' -)

We will now setup actual Poudriere server.

root@poudriere-devel-14-stable:~ # export SSL=/usr/local/etc/ssl

root@poudriere-devel-14-stable:~ # mkdir -p \
                                     /usr/ports/distfiles \
                                     ${SSL}/keys \
                                     ${SSL}/certs

root@poudriere-devel-14-stable:~ # chmod 0600 ${SSL}/keys

root@poudriere-devel-14-stable:~ # openssl genrsa -out ${SSL}/keys/poudriere.key 4096

root@poudriere-devel-14-stable:~ # openssl rsa \
                                     -in  ${SSL}/keys/poudriere.key -pubout \
                                     -out ${SSL}/certs/poudriere.cert

root@poudriere-devel-14-stable:~ # zfs create -p -o mountpoint=/var/ccache zroot/var/ccache

root@poudriere-devel-14-stable:~ # zfs list
NAME               USED  AVAIL  REFER  MOUNTPOINT
zroot              213K  96.4G    24K  none
zroot/var           48K  96.4G    24K  none
zroot/var/ccache    24K  96.4G    24K  /var/ccache

root@poudriere-devel-14-stable:~ # export IP=10.0.0.124

root@poudriere-devel-14-stable:~ # cat << EOF > /usr/local/etc/poudriere.conf
ZPOOL=zroot
BASEFS=/usr/local/poudriere
ZROOTFS=/usr/local/poudriere
FREEBSD_HOST=ftp://ftp.freebsd.org
POUDRIERE_DATA=/usr/local/poudriere/data
CHECK_CHANGED_OPTIONS=verbose
CHECK_CHANGED_DEPS=yes
PKG_REPO_SIGNING_KEY=/usr/local/etc/ssl/keys/poudriere.key
URL_BASE=http://${IP}/
USE_TMPFS=no
TMPFS_LIMIT=12
MAX_MEMORY=12
PARALLEL_JOBS=8
PREPARE_PARALLEL_JOBS=8
MAX_FILES=4096
DISTFILES_CACHE=/usr/ports/distfiles
KEEP_OLD_PACKAGES=yes
KEEP_OLD_PACKAGES_COUNT=3
CHECK_CHANGED_OPTIONS=verbose
CHECK_CHANGED_DEPS=yes
CCACHE_DIR=/var/ccache
RESTRICT_NETWORKING=no
EOF

root@poudriere-devel-14-stable:~ # mkdir -p /usr/local/poudriere/data/logs/bulk

root@poudriere-devel-14-stable:~ # ln -s \
                                     /usr/local/etc/ssl/certs/poudriere.cert \
                                     /usr/local/poudriere/data/logs/bulk/poudriere.cert

root@poudriere-devel-14-stable:~ # service nginx enable

root@poudriere-devel-14-stable:~ # sed -i '' -E 's|text/plain[\t\ ]*txt|text/plain txt log|g' /usr/local/etc/nginx/mime.types

root@poudriere-devel-14-stable:~ # export IP=10.0.0.124

root@poudriere-devel-14-stable:~ # cat << EOF > /usr/local/etc/nginx/nginx.conf
events {
  worker_connections 1024;
}

http {
  include      mime.types;
  default_type application/octet-stream;

  server {
    listen 80 default;
    server_name ${IP};
    root /usr/local/share/poudriere/html;

    location /data {
      alias /usr/local/poudriere/data/logs/bulk;
      autoindex on;
    }

    location /packages {
      root /usr/local/poudriere/data;
      autoindex on;
    }
  }
}
EOF

root@poudriere-devel-14-stable:~ # service nginx restart

root@poudriere-devel-14-stable:~ # mkdir -p /root/.cache/ccache                                  

root@poudriere-devel-14-stable:~ # ln -sf /var/ccache /root/.cache/ccache

root@poudriere-devel-14-stable:~ # cat << EOF > /usr/local/etc/poudriere.d/make.conf
ALLOW_UNSUPPORTED_SYSTEM=yes
DISABLE_LICENSES=yes
EOF

root@poudriere-devel-14-stable:~ # cat << EOF > /var/ccache/ccache.conf
max_size = 0
cache_dir = /var/ccache
base_dir = /var/ccache
hash_dir = false
EOF

root@poudriere-devel-14-stable:~ # poudriere jail -c -j 14-0-S-amd64 -v 14.0-STABLE
(...)
[00:20:45] Jail 14-0-S-amd64 14.0-STABLE amd64 is ready to be used

root@poudriere-devel-14-stable:~ # poudriere jail -l
JAILNAME     VERSION     ARCH  METHOD TIMESTAMP           PATH
14-0-S-amd64 14.0-STABLE amd64 http   2024-03-06 09:44:27 /usr/local/poudriere/jails/14-0-S-amd64

root@poudriere-devel-14-stable:~ # poudriere ports -c -p idm
[00:00:00] Creating idm fs at /usr/local/poudriere/ports/idm... done
[00:00:00] Cloning the ports tree... done

root@poudriere-devel-14-stable:~ # poudriere ports -l
PORTSTREE METHOD    TIMESTAMP           PATH
idm       git+https 2024-03-06 10:10:53 /usr/local/poudriere/ports/idm


Poudriere Server – Build FreeIPA/IDM Client Packages

Now we will choose needed options for our FreeBSD Ports and then start the bulk process of fetching and building them.

root@poudriere-devel-14-stable:~ # poudriere options -c -n -p idm security/cyrus-sasl2-gssapi
//   SELECT: (*) GSSAPI_MIT

root@poudriere-devel-14-stable:~ # poudriere options -c -n -p idm net/openldap26-client
//   SELECT: [x] GSSAPI

root@poudriere-devel-14-stable:~ # poudriere options -c -n -p idm security/sudo
// DESELECT: [ ] PAM
//   SELECT: (*) GSSAPI_MIT
//   SELECT: (*) SSSD2

root@poudriere-devel-14-stable:~ # cat << EOF > /usr/local/etc/poudriere.d/idm
security/krb5
security/sudo
security/sssd2
security/cyrus-sasl2
security/cyrus-sasl2-gssapi
security/pam_mkhomedir
net/openldap26-client
net/samba416
EOF

root@poudriere-devel-14-stable:~ # poudriere bulk -j 14-0-S-amd64 -b latest -p idm -f /usr/local/etc/poudriere.d/idm

root@poudriere-devel-14-stable:~ # zfs list
NAME                                           USED  AVAIL  REFER  MOUNTPOINT
zroot                                         1.51G  94.9G    24K  none
zroot/usr                                     1.39G  94.9G    24K  none
zroot/usr/local                               1.39G  94.9G    24K  none
zroot/usr/local/poudriere                     1.39G  94.9G    24K  none
zroot/usr/local/poudriere/jails               1.07G  94.9G    24K  none
zroot/usr/local/poudriere/jails/14-0-S-amd64  1.07G  94.9G  1.07G  /usr/local/poudriere/jails/14-0-S-amd64
zroot/usr/local/poudriere/ports                328M  94.9G    24K  none
zroot/usr/local/poudriere/ports/idm            328M  94.9G   328M  /usr/local/poudriere/ports/idm
zroot/var                                      117M  94.9G    24K  none
zroot/var/ccache                               117M  94.9G   117M  /var/ccache


This is how the Poudriere build process looks like from the terminal … and a view for its new ZFS datasets that Poudriere created.

xterm-poudriere

It was 2nd or 3rd run so when You first will run the bulk there will be more information about fetching packages etc.

Below You can see what processes are running in htop(1) during the build.

xterm-htop

You can also follow the status of the build process in the browser at https://10.0.0.124 page.

poudriere-devel-100-latest-builds

Generally the new Poudriere interface is quite ‘large’ I would say – so I use it at 70% scale/zoom on Firefox and IMHO its more usable like that.

poudriere-devel-70-latest-builds

And below are the details about our build job.

poudriere-devel-70-build-complete

Poudriere Server – Update Repo/Packages

Everytime you will need to update the packages in that FreeIPA/IDM repo You will need to run these commands.

root@poudriere-devel-14-stable:~ # poudriere ports -u -p idm

root@poudriere-devel-14-stable:~ # poudriere bulk -j 14-0-S-amd64 -b latest -p idm -f /usr/local/etc/poudriere.d/idm

You may as well update the FreeBSD Jail when needed.

root@poudriere-devel-14-stable:~ # poudriere jail -u -j 14-0-S-amd64

FreeBSD 14.0-STABLE Client – Setup

I will not repeat the process – but the same as with Poudriere server – you need to create FreeBSD client – for example as Bhyve VM.

Now – the needed configuration on FreeBSD 14.0-STABLE system to connect it to FreeIPA/IDM server.

root@idm-client:~ # :> ~/.hushlogin

root@idm-client:~ # mkdir -p              \
                     /usr/local/etc/ipa   \
                     /var/log/sssd        \
                     /var/run/sss/private \
                     /var/db/sss

root@idm-client:~ # echo '10.0.0.233  idm-client.lab.org  idm-client' >> /etc/hosts

root@idm-client:~ # echo '10.0.0.200  idm.lab.org         idm'        >> /etc/hosts

root@idm-client:~ # hostname idm-client.lab.org

root@idm-client:~ # sysrc hostname=idm-client.lab.org

root@idm-client:~ # fetch -o /usr/local/etc/ipa/ca.crt http://idm.lab.org/ipa/config/ca.crt

Now we will need to add or FreeBSD client to FreeIPA/IDM. Instructions below.

[root@idm ~]# kinit admin

[root@idm ~]# ipa dnsrecord-add lab.org idm-client --a-rec=10.0.0.233 --a-create-reverse
  Record name: idm-client
  A record: 10.0.0.233

[root@idm ~]# ipa host-add idm-client.lab.org
-------------------------------
Added host "idm-client.lab.org"
-------------------------------
  Host name: idm-client.lab.org
  Principal name: host/idm-client.lab.org@LAB.ORG
  Principal alias: host/idm-client.lab.org@LAB.ORG
  Password: False
  Keytab: False
  Managed by: idm-client.lab.org

[root@idm ~]# ipa-getkeytab -s idm.lab.org -p host/idm-client.lab.org@LAB.ORG -k /root/idm-client.lab.org.keytab
Keytab successfully retrieved and stored in: /root/idm-client.lab.org.keytab

[root@idm ~]# cp /root/idm-client.lab.org.keytab /usr/share/ipa/html/

[root@idm ~]# chmod 644 /usr/share/ipa/html/idm-client.lab.org.keytab

Now lets get back to our FreeBSD client.

root@idm-client:~ # fetch -o /usr/local/etc/ipa/krb5.keytab \
                      http://idm.lab.org/ipa/config/idm-client.lab.org.keytab

root@idm-client:~ # chmod 600 /usr/local/etc/ipa/krb5.keytab

root@idm-client:~ # mkdir -p /usr/local/etc/ssl/certs

root@idm-client:~ # mkdir -p /usr/local/etc/pkg/repos

root@idm-client:~ # sed -e 's|quarterly|latest|g' /etc/pkg/FreeBSD.conf \
                      > /usr/local/etc/pkg/repos/FreeBSD.conf

root@idm-client:~ # pkg install -y beadm

root@idm-client:~ # fetch -o /usr/local/etc/ssl/certs/poudriere.cert \
                      http://poudriere-devel-14-stable.lab.org/data/poudriere.cert

root@idm-client:~ # export IP=10.0.0.124

root@idm-client:~ # cat << EOF > /usr/local/etc/pkg/repos/14-0-S-amd64.conf
14-0-S-amd64-idm: {
  url: "http://${IP}/packages/14-0-S-amd64-idm/",
  mirror_type: "http",
  signature_type: "pubkey",
  pubkey: "/usr/local/etc/ssl/certs/poudriere.cert",
  enabled: yes,
  priority: 100
}
EOF

root@idm-client:~ # pkg update -f

root@idm-client:~ # pkg install -y      \
                      krb5              \
                      sudo              \
                      sssd2             \
                      cyrus-sasl        \
                      cyrus-sasl-gssapi \
                      openldap26-client \
                      pam_mkhomedir

root@idm-client:~ # cat << EOF >> /etc/ssh/ssh_config
GSSAPIAuthentication yes
EOF

root@idm-client:~ # cat << EOF >> /etc/ssh/sshd_config
GSSAPIAuthentication yes
UsePAM yes
EOF

root@idm-client:~ # cat << EOF > /usr/local/etc/sssd/sssd.conf
[sssd]
  config_file_version      = 2
  services                 = pam, ssh, sudo, ifp, pac, nss
  domains                  = lab.org
  timeout                  = 20

[domain/lab.org]
  ipa_server               = idm.lab.org
  ipa_domain               = lab.org
  pam_gssapi_services      = sudo, sudo-i
  enumerate                = True
  cache_credentials        = True
  override_shell           = /usr/local/bin/bash
  override_homedir         = /home/%u
  default_shell            = /bin/sh
  ldap_group_nesting_level = 10
  default_ccache_template  = FILE:/tmp/krb5cc_:%U

  krb5_ccache_template     = FILE:/tmp/krb5cc_:%U
  krb5_server              = idm.lab.org:88
  krb5_realm               = LAB.ORG
  krb5_keytab              = /usr/local/etc/ipa/krb5.keytab
  krb5_auth_timeout        = 20

  id_provider              = ipa
  sudo_provider            = ipa
  access_provider          = ipa
  subdomains_provider      = ipa
  auth_provider            = ipa
  chpass_provider          = ipa
  selinux_provider         = none
EOF

root@idm-client:~ # chmod 600 /usr/local/etc/sssd/sssd.conf

root@idm-client:~ # cat << EOF > /etc/nsswitch.conf
#
# nsswitch.conf(5) - name service switch configuration file
# $FreeBSD$
#
group: files sss
group_compat: nis
hosts: files dns
networks: files
passwd: files sss
passwd_compat: nis
shells: files
services: compat
services_compat: nis
protocols: files
rpc: files
sudoers: sss files
netgroup: files
EOF

root@idm-client:~ # cat /etc/rc.conf
hostname="idm-client.lab.org"
ifconfig_vtnet0="inet 10.0.0.233/24"
defaultrouter="10.0.0.1"
syslogd_flags="-ss"
clear_tmp_enable="YES"
sshd_enable="YES"
zfs_enable="YES"
sssd_enable="YES"

root@idm-client:~ # cat << EOF > /usr/local/etc/openldap/ldap.conf
BASE        dc=org,dc=lab
URI         ldap://idm.lab.org/
SASL_MECH   GSSAPI
SASL_REALM  LAB.ORG
ssl         start_tls
TLS_CACERT  /usr/local/etc/ipa/ca.crt
EOF

root@idm-client:~ # cat << EOF > /etc/krb5.conf
[libdefaults]
  default_realm        = LAB.ORG
  default_keytab_name  = FILE:/usr/local/etc/ipa/krb5.keytab
  default_tkt_enctypes = aes256-cts des-cbc-crc aes128-cts arcfour-hmac
  default_tgs_enctypes = aes256-cts des-cbc-crc aes128-cts arcfour-hmac
  dns_lookup_realm     = false
  dns_lookup_kdc       = false
  rdns                 = false
  ticket_lifetime      = 24h
  forwardable          = yes

[realms]
  LAB.ORG = {
    kdc            = idm.lab.org:88
    master_kdc     = idm.lab.org:88
    admin_server   = idm.lab.org:749
    default_domain = lab.org
    pkinit_anchors = FILE:/usr/local/etc/ipa/ca.crt
  }

[domain_realm]
  .lab.org = LAB.ORG
   lab.org = LAB.ORG

[logging]
  kdc          = FILE:/var/log/krb5/krb5kdc.log
  admin_server = FILE:/var/log/krb5/kadmin.log
  kadmin_local = FILE:/var/log/krb5/kadmin_local.log
  default      = FILE:/var/log/krb5/krb5lib.log
EOF

root@idm-client:~ # cat << EOF > /etc/pam.d/system
#
#
# System-wide defaults
#

# AUTH
  auth      sufficient  pam_krb5.so                      no_warn try_first_pass
# auth      sufficient  pam_ssh.so                       no_warn try_first_pass
  auth      sufficient  /usr/local/lib/pam_sss.so        no_warn use_first_pass
  auth      required    pam_unix.so                      no_warn try_first_pass nullok

# ACCOUNT
# account   required    pam_krb5.so
  account   required    pam_login_access.so
  account   required    /usr/local/lib/pam_sss.so        ignore_unknown_user ignore_authinfo_unavail
  account   required    pam_unix.so

# SESSION
# session   optional    pam_ssh.so                       want_agent
  session   required    pam_lastlog.so                   no_fail
  session   required    /usr/local/lib/pam_mkhomedir.so  mode=0700

# PASSWORD
# password  sufficient  pam_krb5.so                      no_warn try_first_pass
  password  sufficient  /usr/local/lib/pam_sss.so        no_warn use_authtok
  password  required    pam_unix.so                      no_warn try_first_pass
EOF

root@idm-client:~ # cat << EOF > /etc/pam.d/sshd
#
#
# PAM configuration for the "sshd" service
#

# AUTH
  auth      sufficient  pam_krb5.so                      no_warn try_first_pass
# auth      sufficient  pam_ssh.so                       no_warn try_first_pass
  auth      sufficient  /usr/local/lib/pam_sss.so        no_warn use_first_pass
  auth      required    pam_unix.so                      no_warn try_first_pass

# ACCOUNT
  account   required    pam_nologin.so
# account   required    pam_krb5.so
  account   required    pam_login_access.so
  account   required    pam_unix.so
  account   required    /usr/local/lib/pam_sss.so        ignore_unknown_user ignore_authinfo_unavail

# SESSION
# session   optional    pam_ssh.so                       want_agent
  session   required    pam_permit.so
  session   required    /usr/local/lib/pam_mkhomedir.so  mode=0700
  session   optional    /usr/local/lib/pam_sss.so

# PASSWORD
# password  sufficient  pam_krb5.so                      no_warn try_first_pass
  password  sufficient  /usr/local/lib/pam_sss.so        no_warn use_authtok
  password  required    pam_unix.so                      no_warn try_first_pass
EOF

Our idm-client.lab.org in the FreeIPA/IDM below.

idm-hosts

Now reboot your idm-client.lab.org and You should be able to login to it with FreeIPA/IDM account.

host # ssh vermaden@10.0.0.233
(vermaden@10.0.0.233) Password:
Last login: Wed Mar  6 07:04:42 2024

vermaden@idm-client:~ $ id
uid=1374600003(vermaden) gid=1374600000(admins) groups=1374600000(admins)

vermaden@idm-client:~ $ klist
Credentials cache: FILE:/tmp/krb5cc_1374600003
        Principal: vermaden@LAB.ORG

  Issued                Expires               Principal
Mar  6 07:04:34 2024  Mar  7 06:19:19 2024  krbtgt/LAB.ORG@LAB.ORG

vermaden@idm-client:~ $ sudo -i
Password for vermaden@LAB.ORG:

root@idm-client:~ # id
uid=0(root) gid=0(wheel) groups=0(wheel),5(operator)

FreeBSD 14.0-STABLE Client – Debug Commands

Below are some commands that you may (or may not) find useful.

root@idm-client:~ # sssctl user-checks vermaden
user: vermaden
action: acct 
service: system-auth

SSSD nss user lookup result:
 - user name: vermaden
 - user id: 1374600003
 - group id: 1374600000
 - gecos: Vermaden Nedamrev
 - home directory: /home/vermaden
 - shell: /bin/sh
  
Unable to connect to system bus!
InfoPipe User lookup with [vermaden] failed.
testing pam_acct_mgmt   
  
pam_acct_mgmt: Success  
  
PAM Environment:
 - no env -

  
  
root@idm-client:~ # ldapsearch -H ldap://idm.lab.org -x -b "" -s base -LLL supportedSASLMechanisms
dn:
supportedSASLMechanisms: EXTERNAL
supportedSASLMechanisms: GSS-SPNEGO                      
supportedSASLMechanisms: GSSAPI
supportedSASLMechanisms: DIGEST-MD5
supportedSASLMechanisms: CRAM-MD5
supportedSASLMechanisms: LOGIN
supportedSASLMechanisms: PLAIN
supportedSASLMechanisms: ANONYMOUS






root@idm-client:~ # ldapsearch -x -v -W -D 'cn=Directory Manager' uid=vermaden
ldap_initialize(  )
Enter LDAP Password: 
filter: uid=vermaden
requesting: All userApplication attributes
# extended LDIF
#
# LDAPv3
# base  (default) with scope subtree
# filter: uid=vermaden
# requesting: ALL
#

# search result
search: 2
result: 32 No such object

# numResponses: 1





root@idm-client:~ # ldapsearch -Y GSSAPI -Omaxssf=0 -H ldaps://idm.lab.org -b dc=lab,dc=org CN=vermaden
SASL/GSSAPI authentication started
SASL username: vermaden@LAB.ORG
SASL SSF: 0
# extended LDIF
#
# LDAPv3
# base  with scope subtree
# filter: CN=vermaden
# requesting: ALL
#

# vermaden, groups, compat, lab.org
dn: cn=vermaden,cn=groups,cn=compat,dc=lab,dc=org
objectClass: posixGroup
objectClass: ipaOverrideTarget
objectClass: ipaexternalgroup
objectClass: top
gidNumber: 1374600003
ipaAnchorUUID:: OklQQTpsYWIub3JnOjcyN2FlMjM2LTMyMTktMTFlZS04OGMyLTU4OWNmYzA4MW
 QzNQ==
cn: vermaden

# vermaden, groups, accounts, lab.org
dn: cn=vermaden,cn=groups,cn=accounts,dc=lab,dc=org
objectClass: posixgroup
objectClass: ipaobject
objectClass: mepManagedEntry
objectClass: top
cn: vermaden
gidNumber: 1374600003
description: User private group for vermaden
mepManagedBy: uid=vermaden,cn=users,cn=accounts,dc=lab,dc=org
ipaUniqueID: 727ae236-3219-11ee-88c2-589cfc081d35

# search result
search: 4
result: 0 Success

# numResponses: 3
# numEntries: 2


Thats it – you have FreeBSD 14.0-STABLE connected to FreeIPA/IDM server.

Summary

Let me know in comments how it went.

EOF

Personal FreeBSD PKGBASE Update Server

FreeBSD UNIX system can be updated in many ways. You can use freebsd-update(8) command to fetch and install the official binary patches. You can download the FreeBSD sources and compile your new version. You can download and install base.txz and kernel.txz sets in a new ZFS Boot Environment along with copying over your config files there – Other FreeBSD Version in ZFS Boot Environment – as documented here.

While for most users these three options will be more then enough – there is a small group or people that need something else. Companies. People that like to use custom FreeBSD version or enterprise corporate world that needs to fulfill many compliance regulations. For their multiple reasons – including but not limited to – security – they want to have their own trusted FreeBSD update infra under their control.

Recently I was seeking any possible way to build and serve my own FreeBSD versions and making updates of it possible – either with freebsd-update(8) command or with new PKGBASE concept that utilizes the pkg(8) command.

I first started with the official FreeBSD project article titled Build Your Own FreeBSD Update Server – but it was last updated … 10 years ago. I still persisted to try it as there were no other places that documented this and while I tried it – I figured out that instead of *-disc1.iso I should use *-dvd.iso image and that these scripts use SHA512 checksums and not SHA256 (as described in its comments) … but that still did not make it work for 13.2-RELEASE – hence the bug report – Broken for 13.2-RELEASE? … with zero replies … and its still open.

The only thing that changed was an addition of Warning to the article that “The instructions in this article refer to an older version of FreeBSD and may not work properly on recent versions of the OS. With the availability of pkgbase, the freebsd-update utility is scheduled to be removed from FreeBSD in the future. When that happens, this article is either updated to reflect the new procedures or removed entirely”. Seems this is NOT the way.

In the mean time – as FreeBSD 14.0-RELEASE was prepared with its ALPHA/BETA/RC releases – some FreeBSD developers started to share new info about long awaited PKGBASE solution. Seeing that personal freebsd-update(8) based solution seems to be a dead end – I reached out for some PKGBASE info with Personal FreeBSD PKGBASE Server message on the freebsd-pkgbase FreeBSD Mailing Lists. Encouraged by the responses I tried various solutions – and this article will summarize what I was able to achieve – with what I know. I assume that I am far from being PKGBASE expert – so its possible that there are more optimized ways to do what I try to achieve here – hence the article will probably be updated.

While investigating the topic and writing it I also followed the FreeBSD Wiki PKGBASE Page – that helped.

This is the Table of Contents for this article.

  • Personal FreeBSD PKGBASE Update Server
  • Personal freebsd-update(8) Server
  • GhostBSD Way
  • Enter PKGBASE
    • Setup Build Server
    • CCACHE Improvement
    • PKGBASE First Build
    • Update PKGBASE Packages
    • Update PKGBASE Packages on Client System
    • Poudriere Automation
  • Summary

Personal freebsd-update(8) Server

The title of this section – Personal freebsd-update(8) Server – was meant to be the title of that article – I really wanted to utilize the known and tested freebsd-update(8) tool – but as You see even the official way is doomed to failure. While I still believed it is possible – I also reached to other then official sources for that topic. For the record – this is not a sponsored article nor advertisement or a marketing attempt – but I would like to share that I am really grateful to Ganbold Tsagaankhuu and A-Team Systems that they shared their solution to mirror official freebsd-update(8) servers content. The A-Team Systems has been working with FreeBSD for over 20 years and has the experience to provide enterprise level support for it … and they have been a proud sponsor of the FreeBSD Foundation for years. Not to mention that Adam Strohl was FreeBSD project contributor since 1996.

The FreeBSD Update Mirroring solution is ready to use and available – if You just want to mirror the official FreeBSD updates for freebsd-update(8) tool. You can also use another third party tool called freebsd-update-probe.sh that will speed up the check if the freebsd-update(8) updates are available at all.

GhostBSD Way

While I was seeking for some silver bullet for FreeBSD personal upgrade server I also asked Eric Turgeon – the GhostBSD creator – how the GhostBSD does and maintains its update and upgrades.

xfce-ghostbsd

To be honest GhostBSD solution here is really nice and interesting. The GhostBSD project maintains its own Ports tree – https://github.com/ghostbsd/ghostbsd-ports – available here. For the GhostBSD system updates there is just a separate os category – https://github.com/ghostbsd/ghostbsd-ports/tree/main/os – shown here.

Its quite convenient – as they are ‘just’ Ports – they are Poudriere friendly.

Here are the instructions (shared by Eric Turgeon) I used to test the GhostBSD build process.

# // CREATE GhostBSD PORTS MIRROR //
builder # poudriere ports -c -p ghostbsd -m git -U "https://github.com/ghostbsd/ghostbsd-ports" -B main

# // UPDATE GhostBSD PORTS MIRROR //
builder # poudriere ports -u -p ghostbsd -m git -U "https://github.com/ghostbsd/ghostbsd-ports" -B main

# // BUILD GhostBSD os BASE PORTS //
builder # poudriere bulk -j 13-2-R-amd64-src -p ghostbsd \
    os/buildkernel \
    os/buildkernel-debug \
    os/buildworld \
    os/kernel \
    os/kernel-debug \
    os/kernel-debug-symbols \
    os/kernel-symbols \
    os/userland \
    os/userland-base \
    os/userland-base-bootstrap \
    os/userland-bin \
    os/userland-boot \
    os/userland-conf \
    os/userland-debug \
    os/userland-devtools \
    os/userland-docs \
    os/userland-lib \
    os/userland-lib32 \
    os/userland-lib32-development \
    os/userland-rescue \
    os/userland-sbin \
    os/userland-tests \
    os/ports \
    os/src

The good part of that approach is that You just build the Base System parts as any other packages – and then update them in a new ZFS Boot Environment without interfering with running system. After the update process is complete You can reboot to a fresh and updated ZFS BE.

To create a new GhostBSD ISO you will have to use GhostBSD build.sh script … or at least some personal modification of it – but at least its all there and available.

Enter PKGBASE

The idea is not special in any way – to be honest its just a ‘way’ of what most Linux distributions do in their idea of operating system distribution management. The only thing that is different – is that on most Linux systems all packages (even kernel) are treated the same while on FreeBSD the PKGBASE is still in the faith of Base System concept – thus there would be BASE packages and all other packages of third party software … and this is very healthy and good separation. Using FreeBSD for almost two decades I definitely believe that “This is the way!” – to have separate packages for the system and separate for the additional optional packages that anyone can install or not.

Setup Build Server

We will use just released FreeBSD 14.0-RELEASE for the build system – along with some packages installed. Here are the instructions that will get us into that. Without an idea for a better name I will just call it builder … yes I am not the best at naming systems – not to mention that my laptop hostname is named after its model – w520 πŸ™‚

We will install the following pkg(8) packages.

builder # pkg install -y   \
            devel/ccache4  \
            devel/git      \
            net/gitup      \
            sysutils/beadm \
            sysutils/htop  \
            www/nginx

builder # cp /usr/local/etc/gitup.conf.sample \
             /usr/local/etc/gitup.conf

As You probably guessed from the added packages above – we will use CCACHE 4.x to speed up the build process. How much CCACHE helps here? A lot!

The CCACHE config on the host /etc/make.conf file looks as follows.

builder # cat /etc/make.conf
CCACHE_DIR=/var/cache/ccache
WITH_CCACHE_BUILD=yes

You can also make additional time gains by using ramdisk for WRKDIRPREFIX option in the /etc/make.conf file.

builder # cat /etc/make.conf
CCACHE_DIR=/var/cache/ccache
WITH_CCACHE_BUILD=yes
WRKDIRPREFIX=/RAM

You will need that config in the /etc/fstab file.

builder # grep -e RAM -e MNT /etc/fstab
#DEV  #MNT  #FS    #OPTS                  #DUMP/PASS
none  /RAM  tmpfs  rw,size=10g,mode=1777  0 0

The www/nginx and sysutils/htop are optional – first is to eventually share the built pkg(8) repo over the network and htop(1) to check how much the machine is utilized during the build process.

If you want to check how to share this repo with www/nginx then check FreeBSD on FreeIPA/IDM with Poudriere Repo article for the details.

CCACHE Improvement

Below is a simple benchmark showing how much CCACHE helps in build times. It measures time to buildworld and buildkernel of FreeBSD using 8 CPUs in a Bhyve VM – as showed below.

builder # cd /usr/src

builder # rm -rf /usr/obj

builder # time make -j 8 buildworld buildkernel

Below are the timed results of 3 builds.

34018.13s user 1769.90s system 781% cpu 1:16:16.91 total # // 1st // simplified result: ~75 minutes
 1159.49s user  545.14s system 595% cpu    4:46.35 total # // 2nd // simplified result:  ~5 minutes (15 times faster)
 1133.67s user  531.76s system 595% cpu    4:39.73 total # // 3rd // simplified result:  ~5 minutes (15 times faster)

Before doing the benchmark I expected CCACHE to cut the build times in half or something like that – I never expected such a good improvement of 15 times faster build times. From hours to minutes – literally – and this is on older (now budget option) AMD Ryzen 7 1700 8C/16T CPU that cost me $45 a year ago and it is not even fully utilized as I make the build in a 8 CPU Bhyve VM. For storage on that system I have some cheap 512 GB NVMe SSD in M.2 slot on the motherboard and that Bhyve VM have a file based disk with type of virtual NVMe … and also 12 GB RAM … and my RAM is not one of the most expensive gaming one shelf. Does not seem like a huge and expensive build machine to me.

games

If You are curious how is the games system built – AMD Based FreeBSD Desktop – its described here … and Yes I upgraded CPU since the article release πŸ™‚ My CCACHE config is the same as the one used in the FreeBSD on FreeIPA/IDM with Poudriere Repo article.

I started to use ‘external’ machine instead of my ThinkPad W520 for such more heavy loads as I do not like my laptop trying to become a drone with its fan to cool the things I ask it to do while doing other regular work πŸ™‚

PKGBASE First Build

First we need to fetch the FreeBSD source code (if we do not have them already) with gitup(1) command.

builder # gitup release

builder # grep -e '^REVISION' -e '^BRANCH' /usr/src/sys/conf/newvers.sh
REVISION="14.0"
BRANCH="RELEASE"

We will create new pkgbase empty ZFS Boot Environment for our tests.

builder # zfs create -o mountpoint=/ -o canmount=off zroot/ROOT/pkgbase

builder # beadm mount pkgbase /var/tmp/pkgbase

Our new empty ZFS BE is mounted at /var/tmp/pkgbase dir.

Now we will build the world and kernel and then create the packages with make(1) command.


builder # cd /usr/src

builder # rm -rf /usr/obj /var/tmp/pkgbase/repo

builder # mkdir -p /var/tmp/pkgbase/repo

builder # time make REPRODUCIBLE_BUILD=1 REPODIR=/var/tmp/pkgbase/repo -j 10 buildworld buildkernel

builder # time make REPRODUCIBLE_BUILD=1 REPODIR=/var/tmp/pkgbase/repo -j 10 packages

Now we should have our new PKGBASE packages ready.

builder # ls /var/tmp/pkgbase/repo
FreeBSD:14:amd64

builder # ls -l /var/tmp/pkgbase/repo/FreeBSD:14:amd64             
total 17
drwxr-xr-x  2 root wheel 424 2023.12.08 06:37 14/
lrwxr-xr-x  1 root wheel   2 2023.12.08 06:37 latest -> 14

The latest points to our (currently one and only) 14 branch.

Now we will install world and kernel into the new ZFS BE. We also need to make(1) the distribution target to have /etc populated with default configs.

builder # cd /usr/src

builder # make DESTDIR=/var/tmp/pkgbase installworld

builder # make DESTDIR=/var/tmp/pkgbase installkernel

builder # make DESTDIR=/var/tmp/pkgbase distribution

Next we will chroot(8) into new pkgbase ZFS BE and bootstrap the default pkg(8).


builder # env PS1='BE # ' chroot /var/tmp/pkgbase /bin/sh

BE # echo nameserver 1.1.1.1 > /etc/resolv.conf

BE # mount -t devfs devfs /dev

BE # pkg 
The package management tool is not yet installed on your system.
Do you want to fetch and install it now? [y/N]: y

Next – still being in the chroot(8) world – we will create our local PKGBASE repo config and update its metadata.

BE # mkdir -p /usr/local/etc/pkg/repos

BE # cat < /usr/local/etc/pkg/repos/FreeBSD-base.conf
FreeBSD-base: {
  url: "file:///repo/\${ABI}/latest",
  mirror_type: "none",
  enabled: yes
}
EOF

BE # pkg update -r FreeBSD-base
Updating FreeBSD-base repository catalogue...
Fetching meta.conf: 100%    163 B   0.2kB/s    00:01    
Fetching packagesite.pkg: 100%   31 KiB  31.6kB/s    00:01    
Processing entries: 100%
FreeBSD-base repository update completed. 417 packages processed.
All repositories are up to date.

We have our PKGBASE pkg(8) repo metadata – we may now install all the PKGBASE packages over our pkgbase system.

BE # pkg install -g 'FreeBSD-*'

More details below.

BE # pkg install -g 'FreeBSD-*'
Updating FreeBSD repository catalogue...
Fetching meta.conf: 100%    163 B   0.2kB/s    00:01    
Fetching packagesite.pkg: 100%    7 MiB   1.0MB/s    00:07    
Processing entries: 100%
FreeBSD repository update completed. 33994 packages processed.
Updating FreeBSD-base repository catalogue...
FreeBSD-base repository is up to date.
All repositories are up to date.
Updating database digests format: 100%
Checking integrity... done (0 conflicting)
The following 417 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:
        FreeBSD-acct: 14 [FreeBSD-base]
        FreeBSD-acct-dbg: 14 [FreeBSD-base]
        FreeBSD-acpi: 14 [FreeBSD-base]
        FreeBSD-acpi-dbg: 14 [FreeBSD-base]
        FreeBSD-apm: 14 [FreeBSD-base]
        FreeBSD-apm-dbg: 14 [FreeBSD-base]
        FreeBSD-at: 14 [FreeBSD-base]
        FreeBSD-at-dbg: 14 [FreeBSD-base]
        FreeBSD-autofs: 14 [FreeBSD-base]
        FreeBSD-autofs-dbg: 14 [FreeBSD-base]
        FreeBSD-bhyve: 14 [FreeBSD-base]
        FreeBSD-bhyve-dbg: 14 [FreeBSD-base]
        FreeBSD-bluetooth: 14 [FreeBSD-base]
        FreeBSD-bluetooth-dbg: 14 [FreeBSD-base]
        FreeBSD-bluetooth-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-bluetooth-dev: 14 [FreeBSD-base]
        FreeBSD-bluetooth-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-bluetooth-lib32: 14 [FreeBSD-base]
        FreeBSD-bootloader: 14 [FreeBSD-base]
        FreeBSD-bsdinstall: 14 [FreeBSD-base]
        FreeBSD-bsdinstall-dbg: 14 [FreeBSD-base]
        FreeBSD-bsnmp: 14 [FreeBSD-base]
        FreeBSD-bsnmp-dbg: 14 [FreeBSD-base]
        FreeBSD-bsnmp-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-bsnmp-dev: 14 [FreeBSD-base]
        FreeBSD-bsnmp-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-bsnmp-lib32: 14 [FreeBSD-base]
        FreeBSD-caroot: 14 [FreeBSD-base]
        FreeBSD-ccdconfig: 14 [FreeBSD-base]
        FreeBSD-ccdconfig-dbg: 14 [FreeBSD-base]
        FreeBSD-certctl: 14 [FreeBSD-base]
        FreeBSD-clang: 14 [FreeBSD-base]
        FreeBSD-clang-dbg: 14 [FreeBSD-base]
        FreeBSD-clibs: 14 [FreeBSD-base]
        FreeBSD-clibs-dbg: 14 [FreeBSD-base]
        FreeBSD-clibs-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-clibs-dev: 14 [FreeBSD-base]
        FreeBSD-clibs-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-clibs-lib32: 14 [FreeBSD-base]
        FreeBSD-console-tools: 14 [FreeBSD-base]
        FreeBSD-console-tools-dbg: 14 [FreeBSD-base]
        FreeBSD-csh: 14 [FreeBSD-base]
        FreeBSD-csh-dbg: 14 [FreeBSD-base]
        FreeBSD-ctf-tools: 14 [FreeBSD-base]
        FreeBSD-ctf-tools-dbg: 14 [FreeBSD-base]
        FreeBSD-cxgbe-tools: 14 [FreeBSD-base]
        FreeBSD-cxgbe-tools-dbg: 14 [FreeBSD-base]
        FreeBSD-devd: 14 [FreeBSD-base]
        FreeBSD-devd-dbg: 14 [FreeBSD-base]
        FreeBSD-devmatch: 14 [FreeBSD-base]
        FreeBSD-devmatch-dbg: 14 [FreeBSD-base]
        FreeBSD-devmatch-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-devmatch-dev: 14 [FreeBSD-base]
        FreeBSD-devmatch-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-devmatch-lib32: 14 [FreeBSD-base]
        FreeBSD-dhclient: 14 [FreeBSD-base]
        FreeBSD-dhclient-dbg: 14 [FreeBSD-base]
        FreeBSD-dma: 14 [FreeBSD-base]
        FreeBSD-dma-dbg: 14 [FreeBSD-base]
        FreeBSD-dpv: 14 [FreeBSD-base]
        FreeBSD-dpv-dbg: 14 [FreeBSD-base]
        FreeBSD-dpv-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-dpv-dev: 14 [FreeBSD-base]
        FreeBSD-dpv-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-dpv-lib32: 14 [FreeBSD-base]
        FreeBSD-dtrace: 14 [FreeBSD-base]
        FreeBSD-dtrace-dbg: 14 [FreeBSD-base]
        FreeBSD-dtrace-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-dtrace-dev: 14 [FreeBSD-base]
        FreeBSD-dtrace-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-dtrace-lib32: 14 [FreeBSD-base]
        FreeBSD-dwatch: 14 [FreeBSD-base]
        FreeBSD-ee: 14 [FreeBSD-base]
        FreeBSD-ee-dbg: 14 [FreeBSD-base]
        FreeBSD-efi-tools: 14 [FreeBSD-base]
        FreeBSD-efi-tools-dbg: 14 [FreeBSD-base]
        FreeBSD-efi-tools-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-efi-tools-dev: 14 [FreeBSD-base]
        FreeBSD-efi-tools-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-efi-tools-lib32: 14 [FreeBSD-base]
        FreeBSD-elftoolchain: 14 [FreeBSD-base]
        FreeBSD-elftoolchain-dbg: 14 [FreeBSD-base]
        FreeBSD-fetch: 14 [FreeBSD-base]
        FreeBSD-fetch-dbg: 14 [FreeBSD-base]
        FreeBSD-fetch-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-fetch-dev: 14 [FreeBSD-base]
        FreeBSD-fetch-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-fetch-lib32: 14 [FreeBSD-base]
        FreeBSD-ftp: 14 [FreeBSD-base]
        FreeBSD-ftp-dbg: 14 [FreeBSD-base]
        FreeBSD-ftpd: 14 [FreeBSD-base]
        FreeBSD-ftpd-dbg: 14 [FreeBSD-base]
        FreeBSD-fwget: 14 [FreeBSD-base]
        FreeBSD-games: 14 [FreeBSD-base]
        FreeBSD-games-dbg: 14 [FreeBSD-base]
        FreeBSD-geom: 14 [FreeBSD-base]
        FreeBSD-geom-dbg: 14 [FreeBSD-base]
        FreeBSD-geom-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-geom-lib32: 14 [FreeBSD-base]
        FreeBSD-ggate: 14 [FreeBSD-base]
        FreeBSD-ggate-dbg: 14 [FreeBSD-base]
        FreeBSD-hast: 14 [FreeBSD-base]
        FreeBSD-hast-dbg: 14 [FreeBSD-base]
        FreeBSD-hostapd: 14 [FreeBSD-base]
        FreeBSD-hostapd-dbg: 14 [FreeBSD-base]
        FreeBSD-hyperv-tools: 14 [FreeBSD-base]
        FreeBSD-inetd: 14 [FreeBSD-base]
        FreeBSD-inetd-dbg: 14 [FreeBSD-base]
        FreeBSD-ipf: 14 [FreeBSD-base]
        FreeBSD-ipf-dbg: 14 [FreeBSD-base]
        FreeBSD-ipfilter: 14 [FreeBSD-base]
        FreeBSD-ipfw: 14 [FreeBSD-base]
        FreeBSD-ipfw-dbg: 14 [FreeBSD-base]
        FreeBSD-iscsi: 14 [FreeBSD-base]
        FreeBSD-iscsi-dbg: 14 [FreeBSD-base]
        FreeBSD-jail: 14 [FreeBSD-base]
        FreeBSD-jail-dbg: 14 [FreeBSD-base]
        FreeBSD-kerberos: 14 [FreeBSD-base]
        FreeBSD-kerberos-dbg: 14 [FreeBSD-base]
        FreeBSD-kerberos-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-kerberos-lib: 14 [FreeBSD-base]
        FreeBSD-kerberos-lib-dbg: 14 [FreeBSD-base]
        FreeBSD-kerberos-lib-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-kerberos-lib-dev: 14 [FreeBSD-base]
        FreeBSD-kerberos-lib-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-kerberos-lib-lib32: 14 [FreeBSD-base]
        FreeBSD-kerberos-lib32: 14 [FreeBSD-base]
        FreeBSD-kernel-generic: 14 [FreeBSD-base]
        FreeBSD-kernel-generic-dbg: 14 [FreeBSD-base]
        FreeBSD-lib9p: 14 [FreeBSD-base]
        FreeBSD-lib9p-dbg: 14 [FreeBSD-base]
        FreeBSD-lib9p-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-lib9p-dev: 14 [FreeBSD-base]
        FreeBSD-lib9p-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-lib9p-lib32: 14 [FreeBSD-base]
        FreeBSD-libarchive: 14 [FreeBSD-base]
        FreeBSD-libarchive-dbg: 14 [FreeBSD-base]
        FreeBSD-libarchive-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-libarchive-dev: 14 [FreeBSD-base]
        FreeBSD-libarchive-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-libarchive-lib32: 14 [FreeBSD-base]
        FreeBSD-libbegemot: 14 [FreeBSD-base]
        FreeBSD-libbegemot-dbg: 14 [FreeBSD-base]
        FreeBSD-libbegemot-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-libbegemot-dev: 14 [FreeBSD-base]
        FreeBSD-libbegemot-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-libbegemot-lib32: 14 [FreeBSD-base]
        FreeBSD-libblocksruntime: 14 [FreeBSD-base]
        FreeBSD-libblocksruntime-dbg: 14 [FreeBSD-base]
        FreeBSD-libblocksruntime-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-libblocksruntime-dev: 14 [FreeBSD-base]
        FreeBSD-libblocksruntime-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-libblocksruntime-lib32: 14 [FreeBSD-base]
        FreeBSD-libbsdstat: 14 [FreeBSD-base]
        FreeBSD-libbsdstat-dbg: 14 [FreeBSD-base]
        FreeBSD-libbsdstat-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-libbsdstat-dev: 14 [FreeBSD-base]
        FreeBSD-libbsdstat-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-libbsdstat-lib32: 14 [FreeBSD-base]
        FreeBSD-libbsm: 14 [FreeBSD-base]
        FreeBSD-libbsm-dbg: 14 [FreeBSD-base]
        FreeBSD-libbsm-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-libbsm-dev: 14 [FreeBSD-base]
        FreeBSD-libbsm-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-libbsm-lib32: 14 [FreeBSD-base]
        FreeBSD-libbz2: 14 [FreeBSD-base]
        FreeBSD-libbz2-dbg: 14 [FreeBSD-base]
        FreeBSD-libbz2-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-libbz2-dev: 14 [FreeBSD-base]
        FreeBSD-libbz2-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-libbz2-lib32: 14 [FreeBSD-base]
        FreeBSD-libcasper: 14 [FreeBSD-base]
        FreeBSD-libcasper-dbg: 14 [FreeBSD-base]
        FreeBSD-libcasper-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-libcasper-dev: 14 [FreeBSD-base]
        FreeBSD-libcasper-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-libcasper-lib32: 14 [FreeBSD-base]
        FreeBSD-libcompat: 14 [FreeBSD-base]
        FreeBSD-libcompat-dev: 14 [FreeBSD-base]
        FreeBSD-libcompat-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-libcompiler_rt: 14 [FreeBSD-base]
        FreeBSD-libcompiler_rt-dev: 14 [FreeBSD-base]
        FreeBSD-libcompiler_rt-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-libcompiler_rt-lib32: 14 [FreeBSD-base]
        FreeBSD-libcuse: 14 [FreeBSD-base]
        FreeBSD-libcuse-dbg: 14 [FreeBSD-base]
        FreeBSD-libcuse-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-libcuse-dev: 14 [FreeBSD-base]
        FreeBSD-libcuse-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-libcuse-lib32: 14 [FreeBSD-base]
        FreeBSD-libdwarf: 14 [FreeBSD-base]
        FreeBSD-libdwarf-dbg: 14 [FreeBSD-base]
        FreeBSD-libdwarf-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-libdwarf-dev: 14 [FreeBSD-base]
        FreeBSD-libdwarf-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-libdwarf-lib32: 14 [FreeBSD-base]
        FreeBSD-libevent1: 14 [FreeBSD-base]
        FreeBSD-libevent1-dbg: 14 [FreeBSD-base]
        FreeBSD-libevent1-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-libevent1-dev: 14 [FreeBSD-base]
        FreeBSD-libevent1-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-libevent1-lib32: 14 [FreeBSD-base]
        FreeBSD-libexecinfo: 14 [FreeBSD-base]
        FreeBSD-libexecinfo-dbg: 14 [FreeBSD-base]
        FreeBSD-libexecinfo-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-libexecinfo-dev: 14 [FreeBSD-base]
        FreeBSD-libexecinfo-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-libexecinfo-lib32: 14 [FreeBSD-base]
        FreeBSD-libipt: 14 [FreeBSD-base]
        FreeBSD-libipt-dbg: 14 [FreeBSD-base]
        FreeBSD-libipt-dev: 14 [FreeBSD-base]
        FreeBSD-libldns: 14 [FreeBSD-base]
        FreeBSD-libldns-dbg: 14 [FreeBSD-base]
        FreeBSD-libldns-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-libldns-dev: 14 [FreeBSD-base]
        FreeBSD-libldns-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-libldns-lib32: 14 [FreeBSD-base]
        FreeBSD-liblzma: 14 [FreeBSD-base]
        FreeBSD-liblzma-dbg: 14 [FreeBSD-base]
        FreeBSD-liblzma-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-liblzma-dev: 14 [FreeBSD-base]
        FreeBSD-liblzma-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-liblzma-lib32: 14 [FreeBSD-base]
        FreeBSD-libmagic: 14 [FreeBSD-base]
        FreeBSD-libmagic-dbg: 14 [FreeBSD-base]
        FreeBSD-libmagic-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-libmagic-dev: 14 [FreeBSD-base]
        FreeBSD-libmagic-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-libmagic-lib32: 14 [FreeBSD-base]
        FreeBSD-libpathconv: 14 [FreeBSD-base]
        FreeBSD-libpathconv-dbg: 14 [FreeBSD-base]
        FreeBSD-libpathconv-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-libpathconv-dev: 14 [FreeBSD-base]
        FreeBSD-libpathconv-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-libpathconv-lib32: 14 [FreeBSD-base]
        FreeBSD-librpcsec_gss: 14 [FreeBSD-base]
        FreeBSD-librpcsec_gss-dbg: 14 [FreeBSD-base]
        FreeBSD-librpcsec_gss-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-librpcsec_gss-dev: 14 [FreeBSD-base]
        FreeBSD-librpcsec_gss-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-librpcsec_gss-lib32: 14 [FreeBSD-base]
        FreeBSD-librss: 14 [FreeBSD-base]
        FreeBSD-librss-dbg: 14 [FreeBSD-base]
        FreeBSD-librss-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-librss-dev: 14 [FreeBSD-base]
        FreeBSD-librss-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-librss-lib32: 14 [FreeBSD-base]
        FreeBSD-libsdp: 14 [FreeBSD-base]
        FreeBSD-libsdp-dbg: 14 [FreeBSD-base]
        FreeBSD-libsdp-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-libsdp-dev: 14 [FreeBSD-base]
        FreeBSD-libsdp-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-libsdp-lib32: 14 [FreeBSD-base]
        FreeBSD-libsqlite3: 14 [FreeBSD-base]
        FreeBSD-libsqlite3-dbg: 14 [FreeBSD-base]
        FreeBSD-libsqlite3-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-libsqlite3-dev: 14 [FreeBSD-base]
        FreeBSD-libsqlite3-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-libsqlite3-lib32: 14 [FreeBSD-base]
        FreeBSD-libstdbuf: 14 [FreeBSD-base]
        FreeBSD-libstdbuf-dbg: 14 [FreeBSD-base]
        FreeBSD-libstdbuf-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-libstdbuf-dev: 14 [FreeBSD-base]
        FreeBSD-libstdbuf-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-libstdbuf-lib32: 14 [FreeBSD-base]
        FreeBSD-libstdthreads: 14 [FreeBSD-base]
        FreeBSD-libstdthreads-dbg: 14 [FreeBSD-base]
        FreeBSD-libstdthreads-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-libstdthreads-dev: 14 [FreeBSD-base]
        FreeBSD-libstdthreads-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-libstdthreads-lib32: 14 [FreeBSD-base]
        FreeBSD-libthread_db: 14 [FreeBSD-base]
        FreeBSD-libthread_db-dbg: 14 [FreeBSD-base]
        FreeBSD-libthread_db-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-libthread_db-dev: 14 [FreeBSD-base]
        FreeBSD-libthread_db-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-libthread_db-lib32: 14 [FreeBSD-base]
        FreeBSD-libucl: 14 [FreeBSD-base]
        FreeBSD-libucl-dbg: 14 [FreeBSD-base]
        FreeBSD-libucl-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-libucl-dev: 14 [FreeBSD-base]
        FreeBSD-libucl-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-libucl-lib32: 14 [FreeBSD-base]
        FreeBSD-libvgl: 14 [FreeBSD-base]
        FreeBSD-libvgl-dbg: 14 [FreeBSD-base]
        FreeBSD-libvgl-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-libvgl-dev: 14 [FreeBSD-base]
        FreeBSD-libvgl-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-libvgl-lib32: 14 [FreeBSD-base]
        FreeBSD-libvmmapi: 14 [FreeBSD-base]
        FreeBSD-libvmmapi-dbg: 14 [FreeBSD-base]
        FreeBSD-libvmmapi-dev: 14 [FreeBSD-base]
        FreeBSD-liby-dev: 14 [FreeBSD-base]
        FreeBSD-liby-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-lld: 14 [FreeBSD-base]
        FreeBSD-lld-dbg: 14 [FreeBSD-base]
        FreeBSD-lldb: 14 [FreeBSD-base]
        FreeBSD-lldb-dbg: 14 [FreeBSD-base]
        FreeBSD-locales: 14 [FreeBSD-base]
        FreeBSD-mlx-tools: 14 [FreeBSD-base]
        FreeBSD-mlx-tools-dbg: 14 [FreeBSD-base]
        FreeBSD-mtree: 14 [FreeBSD-base]
        FreeBSD-mtree-dbg: 14 [FreeBSD-base]
        FreeBSD-natd: 14 [FreeBSD-base]
        FreeBSD-natd-dbg: 14 [FreeBSD-base]
        FreeBSD-natd-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-natd-dev: 14 [FreeBSD-base]
        FreeBSD-natd-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-natd-lib32: 14 [FreeBSD-base]
        FreeBSD-netmap: 14 [FreeBSD-base]
        FreeBSD-netmap-dbg: 14 [FreeBSD-base]
        FreeBSD-netmap-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-netmap-dev: 14 [FreeBSD-base]
        FreeBSD-netmap-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-netmap-lib32: 14 [FreeBSD-base]
        FreeBSD-newsyslog: 14 [FreeBSD-base]
        FreeBSD-newsyslog-dbg: 14 [FreeBSD-base]
        FreeBSD-nfs: 14 [FreeBSD-base]
        FreeBSD-nfs-dbg: 14 [FreeBSD-base]
        FreeBSD-nvme-tools: 14 [FreeBSD-base]
        FreeBSD-nvme-tools-dbg: 14 [FreeBSD-base]
        FreeBSD-openssl: 14 [FreeBSD-base]
        FreeBSD-openssl-dbg: 14 [FreeBSD-base]
        FreeBSD-openssl-lib: 14 [FreeBSD-base]
        FreeBSD-openssl-lib-dbg: 14 [FreeBSD-base]
        FreeBSD-openssl-lib-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-openssl-lib-dev: 14 [FreeBSD-base]
        FreeBSD-openssl-lib-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-openssl-lib-lib32: 14 [FreeBSD-base]
        FreeBSD-periodic: 14 [FreeBSD-base]
        FreeBSD-pf: 14 [FreeBSD-base]
        FreeBSD-pf-dbg: 14 [FreeBSD-base]
        FreeBSD-pf-dev: 14 [FreeBSD-base]
        FreeBSD-pkg-bootstrap: 14 [FreeBSD-base]
        FreeBSD-pkg-bootstrap-dbg: 14 [FreeBSD-base]
        FreeBSD-ppp: 14 [FreeBSD-base]
        FreeBSD-ppp-dbg: 14 [FreeBSD-base]
        FreeBSD-quotacheck: 14 [FreeBSD-base]
        FreeBSD-quotacheck-dbg: 14 [FreeBSD-base]
        FreeBSD-rc: 14 [FreeBSD-base]
        FreeBSD-rc-dbg: 14 [FreeBSD-base]
        FreeBSD-rcmds: 14 [FreeBSD-base]
        FreeBSD-rcmds-dbg: 14 [FreeBSD-base]
        FreeBSD-rdma: 14 [FreeBSD-base]
        FreeBSD-rdma-dbg: 14 [FreeBSD-base]
        FreeBSD-rescue: 14 [FreeBSD-base]
        FreeBSD-resolvconf: 14 [FreeBSD-base]
        FreeBSD-runtime: 14 [FreeBSD-base]
        FreeBSD-runtime-dbg: 14 [FreeBSD-base]
        FreeBSD-runtime-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-runtime-dev: 14 [FreeBSD-base]
        FreeBSD-runtime-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-runtime-lib32: 14 [FreeBSD-base]
        FreeBSD-sendmail: 14 [FreeBSD-base]
        FreeBSD-sendmail-dbg: 14 [FreeBSD-base]
        FreeBSD-sendmail-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-sendmail-dev: 14 [FreeBSD-base]
        FreeBSD-sendmail-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-sendmail-lib32: 14 [FreeBSD-base]
        FreeBSD-smbutils: 14 [FreeBSD-base]
        FreeBSD-smbutils-dbg: 14 [FreeBSD-base]
        FreeBSD-smbutils-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-smbutils-dev: 14 [FreeBSD-base]
        FreeBSD-smbutils-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-smbutils-lib32: 14 [FreeBSD-base]
        FreeBSD-ssh: 14 [FreeBSD-base]
        FreeBSD-ssh-dbg: 14 [FreeBSD-base]
        FreeBSD-ssh-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-ssh-dev: 14 [FreeBSD-base]
        FreeBSD-ssh-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-ssh-lib32: 14 [FreeBSD-base]
        FreeBSD-syscons: 14 [FreeBSD-base]
        FreeBSD-syslogd: 14 [FreeBSD-base]
        FreeBSD-syslogd-dbg: 14 [FreeBSD-base]
        FreeBSD-tcpd: 14 [FreeBSD-base]
        FreeBSD-tcpd-dbg: 14 [FreeBSD-base]
        FreeBSD-tcpd-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-tcpd-dev: 14 [FreeBSD-base]
        FreeBSD-tcpd-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-tcpd-lib32: 14 [FreeBSD-base]
        FreeBSD-telnet: 14 [FreeBSD-base]
        FreeBSD-telnet-dbg: 14 [FreeBSD-base]
        FreeBSD-tests: 14 [FreeBSD-base]
        FreeBSD-tests-dbg: 14 [FreeBSD-base]
        FreeBSD-tests-dev: 14 [FreeBSD-base]
        FreeBSD-ufs: 14 [FreeBSD-base]
        FreeBSD-ufs-dbg: 14 [FreeBSD-base]
        FreeBSD-ufs-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-ufs-dev: 14 [FreeBSD-base]
        FreeBSD-ufs-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-ufs-lib32: 14 [FreeBSD-base]
        FreeBSD-unbound: 14 [FreeBSD-base]
        FreeBSD-unbound-dbg: 14 [FreeBSD-base]
        FreeBSD-unbound-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-unbound-dev: 14 [FreeBSD-base]
        FreeBSD-unbound-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-unbound-lib32: 14 [FreeBSD-base]
        FreeBSD-utilities: 14 [FreeBSD-base]
        FreeBSD-utilities-dbg: 14 [FreeBSD-base]
        FreeBSD-utilities-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-utilities-dev: 14 [FreeBSD-base]
        FreeBSD-utilities-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-utilities-lib32: 14 [FreeBSD-base]
        FreeBSD-vi: 14 [FreeBSD-base]
        FreeBSD-vi-dbg: 14 [FreeBSD-base]
        FreeBSD-vt-data: 14 [FreeBSD-base]
        FreeBSD-wpa: 14 [FreeBSD-base]
        FreeBSD-wpa-dbg: 14 [FreeBSD-base]
        FreeBSD-yp: 14 [FreeBSD-base]
        FreeBSD-yp-dbg: 14 [FreeBSD-base]
        FreeBSD-zfs: 14 [FreeBSD-base]
        FreeBSD-zfs-dbg: 14 [FreeBSD-base]
        FreeBSD-zfs-dbg-lib32: 14 [FreeBSD-base]
        FreeBSD-zfs-dev: 14 [FreeBSD-base]
        FreeBSD-zfs-dev-lib32: 14 [FreeBSD-base]
        FreeBSD-zfs-lib32: 14 [FreeBSD-base]
        FreeBSD-zoneinfo: 14 [FreeBSD-base]

Number of packages to be installed: 417

The process will require 3 GiB more space.

Proceed with this action? [y/N]: y


Voila! We have fresh FreeBSD 14.0-RELEASE system installed with new PKGBASE way.

Some pkg(8) stats below.

BE # pkg stats
Local package database:
        Installed packages: 418
        Disk space occupied: 3 GiB

Remote package database(s):
        Number of repositories: 2
        Packages available: 34411
        Unique packages: 34411
        Total size of packages: 121 GiB

BE # pkg -vv | grep -A 99 '^Repositories:'
Repositories:
  FreeBSD: { 
    url             : "pkg+http://pkg.FreeBSD.org/FreeBSD:14:amd64/quarterly",
    enabled         : yes,
    priority        : 0,
    mirror_type     : "SRV",
    signature_type  : "FINGERPRINTS",
    fingerprints    : "/usr/share/keys/pkg"
  }
  FreeBSD-base: { 
    url             : "file:///repo/FreeBSD:14:amd64/latest",
    enabled         : yes,
    priority        : 0
  }


Update PKGBASE Packages

Now – when the new version arrives – or just we want to add some changes and reflect them in the packages – we would like to update our PKGBASE packages and update the pkgbase system.

With my limited knowledge of C I will modify our /usr/src source tree and then build updated packages.

First – we need to change BRANCH into something different – so that it will be obvious for the PKGBASE build method that packages needs to be updated.

builder # vi /usr/src/sys/conf/newvers.sh

builder # grep -e '^REVISION' -e '^BRANCH' /usr/src/sys/conf/newvers.sh
REVISION="14.0"
BRANCH="RELEASE-p1"

I have changed BRANCH="RELEASE" into BRANCH="RELEASE-p1" for the record.

Now lets modify some FreeBSD tool to check if it will be updated in the process – lets try ls(1).

I will add an EMPTY and useless function to it.


builder # vi /usr/src/bin/ls/ls.c

builder # grep -n -A 4 EMPTY /usr/src/bin/ls/ls.c
100:int          EMPTY(int);
101-static void  traverse(int, char **, int);
102-
103-#define     COLOR_OPT       (CHAR_MAX + 1)
104-
--
1033:int EMPTY(int nope)
1034-{
1035-   return nope;
1036-}

Lets update the PKGBASE packages.

builder # rm -rf /usr/obj

builder # cd /usr/src

builder # time make REPRODUCIBLE_BUILD=1 REPODIR=/var/tmp/pkgbase/repo -j 10 buildworld buildkernel

builder # time make REPRODUCIBLE_BUILD=1 REPODIR=/var/tmp/pkgbase/repo -j 10 update-packages

Lets see how our /repo looks like now.

builder # find /var/tmp/pkgbase/repo -maxdepth 2 -ls | sed -e 's.      ..g'
     2  1 drwxr-xr-x    3 root     wheel     3 Dec  8 06:31 /var/tmp/pkgbase/repo
   128  1 drwxr-xr-x    4 root     wheel     5 Dec  8 21:48 /var/tmp/pkgbase/repo/FreeBSD:14:amd64
 32768 33 drwxr-xr-x    2 root     wheel   424 Dec  8 21:48 /var/tmp/pkgbase/repo/FreeBSD:14:amd64/14p1
   129 33 drwxr-xr-x    2 root     wheel   424 Dec  8 06:37 /var/tmp/pkgbase/repo/FreeBSD:14:amd64/14
 33907  1 lrwxr-xr-x    1 root     wheel     4 Dec  8 21:48 /var/tmp/pkgbase/repo/FreeBSD:14:amd64/latest -> 14p1

So the latest now points to the 14p1 branch. Looks promising.

Update PKGBASE Packages on Client System

Now – as our /repo is updated – we will do the usual update process with pkg(8) tool.

I assume that pkgbase is still mounted at the /var/tmp/pkgbase place and that devfs is still mounted /dev inside pkgbase ZFS BE.

builder # env PS1='BE # ' chroot /var/tmp/pkgbase /bin/sh

BE # mount | grep -q /var/tmp/pkgbase/dev || mount -t devfs devfs /dev

BE # pkg update -f -r FreeBSD-repo
Updating FreeBSD-base repository catalogue...
Fetching meta.conf: 100%    163 B   0.2kB/s    00:01    
Fetching packagesite.pkg: 100%   31 KiB  31.7kB/s    00:01    
Processing entries: 100%
FreeBSD-base repository update completed. 417 packages processed.
All repositories are up to date.

BE # pkg upgrade
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
Updating FreeBSD-base repository catalogue...
FreeBSD-base repository is up to date.
All repositories are up to date.
Checking for upgrades (8 candidates): 100%
Processing candidates (8 candidates): 100%
Checking integrity... done (0 conflicting)
The following 7 package(s) will be affected (of 0 checked):

Installed packages to be UPGRADED:
        FreeBSD-ftpd: 14 -> 14p1 [FreeBSD-base]
        FreeBSD-ftpd-dbg: 14 -> 14p1 [FreeBSD-base]
        FreeBSD-kernel-generic: 14 -> 14p1 [FreeBSD-base]
        FreeBSD-kernel-generic-dbg: 14 -> 14p1 [FreeBSD-base]
        FreeBSD-rescue: 14 -> 14p1 [FreeBSD-base]
        FreeBSD-runtime: 14 -> 14p1 [FreeBSD-base]
        FreeBSD-runtime-dbg: 14 -> 14p1 [FreeBSD-base]

Number of packages to be upgraded: 7

Proceed with this action? [y/N]: y
[1/7] Upgrading FreeBSD-runtime from 14 to 14p1...
[1/7] Extracting FreeBSD-runtime-14p1: 100%
[2/7] Upgrading FreeBSD-ftpd from 14 to 14p1...
[2/7] Extracting FreeBSD-ftpd-14p1: 100%
[3/7] Upgrading FreeBSD-kernel-generic-dbg from 14 to 14p1...
[3/7] Extracting FreeBSD-kernel-generic-dbg-14p1: 100%
[4/7] Upgrading FreeBSD-ftpd-dbg from 14 to 14p1...
[4/7] Extracting FreeBSD-ftpd-dbg-14p1: 100%
[5/7] Upgrading FreeBSD-rescue from 14 to 14p1...
[5/7] Extracting FreeBSD-rescue-14p1: 100%
[6/7] Upgrading FreeBSD-runtime-dbg from 14 to 14p1...
[6/7] Extracting FreeBSD-runtime-dbg-14p1: 100%
[7/7] Upgrading FreeBSD-kernel-generic from 14 to 14p1...
[7/7] Extracting FreeBSD-kernel-generic-14p1: 100%

So we just did our first binary pkg(8) update using PKGBASE packages created on our personal build system.

Lets check where /bin/ls has been packaged.

BE # pkg which -o /bin/ls
/bin/ls was installed by package base

Not much of a help. Lets check if its one of the updated FreeBSD-runtime PKGBASE packages.

BE # pkg info -l FreeBSD-runtime | grep /bin/ls
        /bin/ls

Yep. That is the one.

We can also check what freebsd-version(1) thinks about it.

BE # freebsd-version -k
14.0-RELEASE-p1

BE # freebsd-version -u
14.0-RELEASE-p1

BE # freebsd-version 
14.0-RELEASE-p1

Seems legit.

Poudriere Automation

I did not (yet) persuaded the Poudriere way of doing it – but Mina Galic was kind enough to share his HOWTO on the topic – PKGBASE HOWTO – but besides reading it – I did not yet persuaded its instructions live.

Summary

These are early stages of PKGBASE (especially for me) so way of things may change in the future – but for now – this one should just work.

Being here – I would like to help all people that helped me with this topic – You know who You are πŸ™‚

Feel free to share your experiences about it.

EOF

FreeBSD on FreeIPA/IDM with Poudriere Repo

I already wrote twice about this topic:

FreeIPA-logo

In both earlier attempts I compiled and configured everything by hand – at it was a very interactive time consuming process. This time – after having some poudriere(8) experience – Simple FreeBSD Poudriere Harvester Guide – as shared here – I will now automate customized FreeIPA/IDM packages creation in a FreeBSD Poudriere tool.

One final note for the rest of the guide – please use /bin/sh shell for the commands … or zsh(1) for example πŸ™‚

This is the Table of Contents for this article.

  • FreeBSD on FreeIPA/IDM with Poudriere Repo
  • Poudriere Setup
    • FreeBSD Config
    • Development Poudriere Version
    • Nginx Setup
    • Latest Ccache Version
    • FreeIPA/IDM Repo
    • FreeIPA/IDM Configure Options
    • Repo Update
  • FreeBSD Client

Poudriere Setup

For a start lets switch to latest branch for more fresh pkg(8) packages.

# mkdir -p /usr/local/etc/pkg/repos

# sed s-quarterly-latest-g /etc/pkg/FreeBSD.conf > /usr/local/etc/pkg/repos/FreeBSD.conf

We will now install the needed packages.

# pkg install -y \
    poudriere-devel \
    nginx           \
    git-lite        \
    ccache4         \
    tree

FreeBSD Config

Main FreeBSD config.

# cat /etc/rc.conf
# NETWORK
  hostname="poudriere.lab.org"
  ifconfig_vtnet0="inet 10.0.0.122/24"
  defaultrouter="10.0.0.1"

# DAEMONS
  syslogd_flags="-ss"
  sshd_enable="YES"
  zfs_enable="YES"
  ntpdate_enable="YES"
  nginx_enable="YES"

# OTHER
  clear_tmp_enable="YES"
  dumpdev="AUTO"

… and /etc/hosts file.

# cat /etc/hosts
::1              localhost  localhost.my.domain
127.0.0.1        localhost  localhost.my.domain
10.0.0.122       poudriere-devel.lab.org  poudriere-devel

Development Poudriere Version

Contrary to my earlier guide I used the development ports-mgmt/poudriere-devel package because it offers more features.

The most interesting one is -b latest for the poudriere-bulk(8) command. For packages that you do not modify and only need as dependencies – Poudriere will just fetch them from the latest repository using pkg(8) and then (re)build the customized packages you want.

… currently this feature is broken and requires small fix/patch to work properly πŸ™‚

The sort(1) command needs to have -u flag added in two places as described here:

We will now apply this patch.

# pkg info -l poudriere-devel | grep common.sh
        /usr/local/share/poudriere/common.sh
        /usr/local/share/poudriere/include/common.sh.dragonfly
        /usr/local/share/poudriere/include/common.sh.freebsd

# cd /usr/local/share/poudriere/

# cp common.sh common.sh.NEW

# cp common.sh common.sh.OLD

# vi common.sh.NEW

# diff -u common.sh common.sh.NEW | tee PATCH
--- common.sh   2023-08-09 15:08:29.831701000 +0200
+++ common.sh.NEW       2023-08-09 14:49:22.097238000 +0200
@@ -3672,7 +3672,7 @@
            $1 == pkgbase && $3 == "off" {print "-"$2;printed=1}
            $1 != pkgbase && printed == 1 {exit}
            ' \
-           "${remote_all_options}" | sort -k1.2 | paste -s -d ' ' -)
+           "${remote_all_options}" | sort -k1.2 -u | paste -s -d ' ' -)
 
        shash_get pkgname-options "${pkgname}" selected_options || \
            selected_options=
@@ -3698,7 +3698,7 @@
            $1 == pkgbase {print $2;printed=1}
            $1 != pkgbase && printed == 1 {exit}
            ' \
-           "${remote_all_deps}" | sort | paste -s -d ' ' -)
+           "${remote_all_deps}" | sort -u | paste -s -d ' ' -)
        case "${local_deps}" in
        ${remote_deps}) ;;
        *)

# grep sort common.sh | grep -- -u | wc -l
       9

# grep sort common.sh.NEW | grep -- -u | wc -l
      11

# grep sort common.sh.OLD | grep -- -u | wc -l
       9

# patch < PATCH
Hmm...  Looks like a unified diff to me...
The text leading up to this was:
--------------------------
|--- common.sh  2023-08-09 15:08:29.831701000 +0200
|+++ common.sh.NEW      2023-08-09 14:49:22.097238000 +0200
--------------------------
Patching file common.sh using Plan A...
Hunk #1 succeeded at 3672.
Hunk #2 succeeded at 3698.
done

# grep sort common.sh | grep -- -u | wc -l
      11

# grep sort common.sh.NEW | grep -- -u | wc -l
      11

# grep sort common.sh.OLD | grep -- -u | wc -l
       9

Now the SSL keys.

# SSL=/usr/local/etc/ssl

# mkdir -p            /usr/ports/distfiles \
                      ${SSL}/keys \
                      ${SSL}/certs

# chmod 0600          ${SSL}/keys

# openssl genrsa -out ${SSL}/keys/poudriere.key 4096

# openssl rsa     -in ${SSL}/keys/poudriere.key -pubout \
                 -out ${SSL}/certs/poudriere.cert

… and ZFS datasets.

# zfs create -o mountpoint=/usr/local/poudriere zroot/poudriere

# zfs create -o mountpoint=/var/ccache          zroot/var/ccache

Now the Poudriere config.

# IP=10.0.0.122

# cat << EOF > /usr/local/etc/poudriere.conf
ZPOOL=zroot
BASEFS=/usr/local/poudriere
ZROOTFS=/usr/local/poudriere
FREEBSD_HOST=ftp://ftp.freebsd.org
POUDRIERE_DATA=/usr/local/poudriere/data
CHECK_CHANGED_OPTIONS=verbose
CHECK_CHANGED_DEPS=yes
PKG_REPO_SIGNING_KEY=/usr/local/etc/ssl/keys/poudriere.key
URL_BASE=http://${IP}/
USE_TMPFS=no
TMPFS_LIMIT=12
MAX_MEMORY=12
PARALLEL_JOBS=4
PREPARE_PARALLEL_JOBS=4
MAX_FILES=4096
DISTFILES_CACHE=/usr/ports/distfiles
KEEP_OLD_PACKAGES=yes
KEEP_OLD_PACKAGES_COUNT=3
CHECK_CHANGED_OPTIONS=verbose
CHECK_CHANGED_DEPS=yes
CCACHE_DIR=/var/ccache
RESTRICT_NETWORKING=no
EOF

… and symlink for certificate that we will use later.

# mkdir -p /usr/local/poudriere/data/logs/bulk

# ln -s /usr/local/etc/ssl/certs/poudriere.cert \
        /usr/local/poudriere/data/logs/bulk/poudriere.cert

Nginx Setup

Simple Nginx config to host the packages.

# IP=10.0.0.122

# service nginx enable

# sed -i '' -E 's|text/plain[\t\ ]*txt|text/plain txt log|g' /usr/local/etc/nginx/mime.types

# cat << EOF > /usr/local/etc/nginx/nginx.conf

events {
  worker_connections 1024;
}

http {
  include      mime.types;
  default_type application/octet-stream;

  server {
    listen 80 default;
    server_name ${IP};
    root /usr/local/share/poudriere/html;

    location /data {
      alias /usr/local/poudriere/data/logs/bulk;
      autoindex on;
    }

    location /packages {
      root /usr/local/poudriere/data;
      autoindex on;
    }
  }
}
EOF

# service nginx restart

# sockstat -l4
USER     COMMAND    PID   FD PROTO  LOCAL ADDRESS         FOREIGN ADDRESS      
www      nginx      83135 7  tcp4   *:80                  *:*
root     nginx      82843 7  tcp4   *:80                  *:*
root     sendmail   67293 5  tcp4   127.0.0.1:25          *:*
root     sshd       66135 5  tcp4   *:22                  *:*

Latest Ccache Version

Previous guide used older Ccache version 3.x along with some small Memcached addition/modification. I wrote that article just 4 months ago but even after such short period of time the ccache-memcached is not longer available.

I could use ‘generic’ Ccache 3.x or I could move to latest 4.x branch. I have chosen the latter.

It seems a wise decision as the last Ccache release from the 3.x tree (3.7.12) was released almost 3 years ago – on 2020/10/01.

Below we will configure Ccache to our needs.


# mkdir -p /var/ccache

# cat << EOF > /var/ccache/ccache.conf
max_size = 0
cache_dir = /var/ccache
base_dir = /var/ccache
hash_dir = false
EOF

We can check Ccache settings with -p option.

# ccache -p
(default) absolute_paths_in_stderr = false
(/var/ccache/ccache.conf) base_dir = /var/ccache
(/var/ccache/ccache.conf) cache_dir = /var/ccache
(default) compiler = 
(default) compiler_check = mtime
(default) compiler_type = auto
(default) compression = true
(default) compression_level = 0
(default) cpp_extension = 
(default) debug = false
(default) debug_dir = 
(default) depend_mode = false
(default) direct_mode = true
(default) disable = false
(default) extra_files_to_hash = 
(default) file_clone = false
(default) hard_link = false
(/var/ccache/ccache.conf) hash_dir = false
(default) ignore_headers_in_manifest = 
(default) ignore_options = 
(default) inode_cache = true
(default) keep_comments_cpp = false
(default) log_file = 
(default) max_files = 0
(/var/ccache/ccache.conf) max_size = 0 bytes
(default) msvc_dep_prefix = Note: including file:
(default) namespace = 
(default) path = 
(default) pch_external_checksum = false
(default) prefix_command = 
(default) prefix_command_cpp = 
(default) read_only = false
(default) read_only_direct = false
(default) recache = false
(default) remote_only = false
(default) remote_storage = 
(default) reshare = false
(default) run_second_cpp = true
(default) sloppiness = 
(default) stats = true
(default) stats_log = 
(default) temporary_dir = /var/ccache/tmp
(default) umask = 

… and its Ccache cache stats – currently empty as its a fresh install.


# ccache -s
Local storage:
  Cache size (GiB): 0.0

FreeIPA/IDM Repo

Now options to setup for our customized pkg(8) repo.

# cat << EOF > /usr/local/etc/poudriere.d/make.conf
ALLOW_UNSUPPORTED_SYSTEM=yes
DISABLE_LICENSES=yes
EOF

We will now create new jail(8) where our packages will be built.

# poudriere jail -c -j 13-2-R-amd64 -v 13.2-RELEASE
(...)

# poudriere jail -l
13-2-R-amd64 13.2-RELEASE-p1 amd64 http   2023-08-08 20:36:49 /usr/local/poudriere/jails/13-2-R-amd64

Up to date FreeBSD Ports tree will also be needed – we will create a separate idm profile for it.

# poudriere ports -c -p idm
(...)

# poudriere ports -l
idm       git+https 2023-08-09 20:31:07 /usr/local/poudriere/ports/idm

FreeIPA/IDM Configure Options

Below are the options we will have to choose to make our FreeBSD systems be able to join FreeIPA/IDM domain.

# poudriere options -c -n -p idm security/cyrus-sasl2-gssapi
//   SELECT: (*) GSSAPI_MIT

# poudriere options -c -n -p idm net/openldap26-client
//   SELECT: [x] GSSAPI

# poudriere options -c -n -p idm security/sudo
// DESELECT: [ ] PAM
//   SELECT: (*) GSSAPI_MIT
//   SELECT: (*) SSSD

# poudriere options -c -n -p idm security/sssd
//   SELECT: [x] SMB

These options were stored below.

I needed to replace the ANSI line graphics with universal ‘-‘ and ‘+‘ characters as WordPress had issues with them.


# tree /usr/local/etc/poudriere.d/idm-options
/usr/local/etc/poudriere.d/idm-options
+-- net_openldap26-client
|   +-- options
+-- security_cyrus-sasl2-gssapi
|   +-- options
+-- security_sssd
|   +-- options
+-- security_sudo
    +-- options

5 directories, 4 files

We will now specify packages that we want to be sure will be built of fetched from the latest branch.

# cat << EOF > /usr/local/etc/poudriere.d/idm
security/krb5
security/sudo
security/sssd
security/cyrus-sasl2
security/cyrus-sasl2-gssapi
security/pam_mkhomedir
net/openldap26-client
net/samba413
EOF


We can now start the build process.

# poudriere bulk -j 13-2-R-amd64 -b latest -p idm -f /usr/local/etc/poudriere.d/idm

The simplified output with (...) edits in between is shown below.

poudriere-devel-build-log-cut
The full log of such build process is available here.

If not much (or nothing) changed then the following update build process is very short and fast.

poudriere-devel-build-log-rebuild

This is how the built FreeIPA/IDM repo looks like in the Nginx interface.

poudriere-devel-built

After several such builds you will see historic versions as shown below.

poudriere-devel-several-times

Now – below is a summary about our created packages.

[13-2-R-amd64-idm] [2023-08-08_11h15m23s] [committing:] Queued: 197 Built: 11  Failed: 0   Skipped: 0   Ignored: 0   Fetched: 186 Tobuild: 0    Time: 00:17:17

To summarize:

  • From needed 197 packages only 11 were sent to compilation which means about 5.6% of them needed compilation.
  • During compilation of these 11 packages Ccache hit ratio was at 54.4% rate.

To make you visualize how much time was save here – let me just remind you that lang/gcc12 would need 12-16 hours of compilation and another 6-10 hours would be needed for lang/rust. These were only two packages … and the whole process tool about quarter of hour with these optimizations. Not to mention that compilation can sometimes fail – which leaves you without repo and needed packages and with even more work to figure out why it failed. Not worth the hassle IMHO.

The Ccache stats below.

# ccache -s
Cacheable calls:      44834 / 68237 (65.70%)
  Hits:               24389 / 44834 (54.40%)
    Direct:           21118 / 24389 (86.59%)
    Preprocessed:      3271 / 24389 (13.41%)
  Misses:             20445 / 44834 (45.60%)
Uncacheable calls:    23319 / 68237 (34.17%)
Errors:                  84 / 68237 ( 0.12%)
Local storage:
  Cache size (GiB): 65536.0

Some more Ccache stats and disk usage below.

# du -smA /var/ccache
1593    /var/ccache

# du -sm /var/ccache
827     /var/ccache

# zfs get compressratio zroot/var/ccache
NAME              PROPERTY       VALUE  SOURCE
zroot/var/ccache  compressratio  2.35x  -

# zfs list zroot/var/ccache
NAME               USED  AVAIL     REFER  MOUNTPOINT
zroot/var/ccache   841M  28.2G      841M  /var/ccache

Repo Update

Every time you will need to update the packages in that FreeIPA/IDM repo You will need to run these commands.

# poudriere ports -p idm -u

# poudriere jail -j 13-2-R-amd64 -u

# poudriere bulk -j 13-2-R-amd64 -b latest -p idm -f /usr/local/etc/poudriere.d/idm

Which means:

  • Update the idm FreeBSD Ports tree.
  • Update the 13.2-RELEASE 13-2-R-amd64 FreeBSD Jail container.
  • Rebuild/refetch packages against updated idm Ports and 13-2-R-amd64 Jail.

FreeBSD Client

This section would show how to use our newly create pkg(8) repo to install custom packages.

Lets bootstrap pkg(8) for a start with some random package.

# pkg install -y beadm

Copy repo certificate from Poudriere server.

# IP=10.0.0.122

# mkdir -p /usr/local/etc/ssl/certs

# fetch -o /usr/local/etc/ssl/certs/poudriere.cert http://${IP}/data/poudriere.cert

Disable default pkg(8) repo.

# mkdir -p /usr/local/etc/pkg/repos

# echo "FreeBSD: { enabled: no }" > /usr/local/etc/pkg/repos/FreeBSD.conf

Add our custom pkg(8) repository.


# IP=10.0.10.122

# mkdir -p /usr/local/etc/pkg/repos

# cat << EOF > /usr/local/etc/pkg/repos/13-2-R-amd64.conf
13-2-R-amd64-idm: {
    url: "http://${IP}/packages/13-2-R-amd64-idm/",
    mirror_type: "http",
    signature_type: "pubkey",
    pubkey: "/usr/local/etc/ssl/certs/poudriere.cert",
    enabled: yes,
    priority: 100
}
EOF

Update the pkg(8) metadata.

# pkg update

# pkg -vv | grep -A 99 Repositories:
Repositories:
  13-2-R-amd64-idm: { 
    url             : "http://10.0.0.122/packages/13-2-R-amd64-idm/",
    enabled         : yes,
    priority        : 100,
    mirror_type     : "HTTP",
    signature_type  : "PUBKEY",
    pubkey          : "/usr/local/etc/ssl/certs/poudriere.cert"
  }

Install the FreeIPA/IDM required client packages.

# pkg install -y      \
    krb5              \
    sudo              \
    sssd              \
    cyrus-sasl        \
    cyrus-sasl-gssapi \
    openldap26-client \
    pam_mkhomedir

… and now please continue with the FreeBSD Setup section of the older Connect FreeBSD 13.2 to FreeIPA/IDM guide because the client addon process did not changed.

Let me know in comments if something is not clear … or when You have better ideas then me πŸ™‚

EOF