Tag Archives: linux

Keep FreeBSD Desktop Updated

While its relatively easy (or brain dead easy with GhostBSD or NomadBSD distributions) to install and configure a FreeBSD Desktop – one have to keep in mind that its also important to keep that system updated and secure.

There are many aspects about FreeBSD to keep it updates and secured.

The Table of Contents for this article is shown below:

  • FreeBSD Base System
  • Packages
  • FreeBSD Linux Browser Installer
  • WINE
  • Cargo Packages
  • FreeBSD Ports Tree
  • Summary

Lets now discuss each section one by one.

FreeBSD Base System

First is the FreeBSD Base System which is updated by the frebsd-update(8) utility. It is not often you need to do this – from my experience its once a month need usually.

The list of needed commands are shown below.

# freebsd-version
# frebsd-update fetch
# frebsd-update install

While the freebsd-version(1) will tell you what version you are currently running the freebsd-update(8) will help you to update your FreeBSD system to have latest patches installed.

… but when to update the FreeBSD Base System anyway? Well – its quite simple – check the FreeBSD Security Advisories page – and if something posted there affects you – then you should move your ass and update it πŸ™‚


After you have taken care of the FreeBSD Base System the next one to make sure you are not too much far behind are the FreeBSD packages.

You can of course check if any of your installed packages have any reported security holes as shown below.

# pkg audit -F
vulnxml file up-to-date
0 problem(s) in 0 installed package(s) found.

The above message shows that your installed packages are safe – but its not the message you see the most of the time πŸ™‚

Below are the commands that you would use to update your FreeBSD desktop system.

# pkg upgrade
# pkg autoremove
# pkg clean -y --all

… and yes it does include some extra steps to remove cached packages – and probably now not needed as the are already installed anyway.

I do not think that anything more should be added here – maybe a short mention about the packages branch you are using. The default one is the quarterly branch that has packages build every quarter.

Maybe its sometimes reasonable for the server like environments – but I prefer to have the latest versions of what FreeBSD maintainers do offer in their hard and often underestimated work.

This is why I always use – both on desktop and servers – the latest packages branch.

This means that packages are (re)built once a week or faster and you get what is latest and fresh.

I will not convince you what is better – you will have to decide for yourself.

FreeBSD Linux Browser Installer

The Linux Browser Installer helps a lot on FreeBSD systems. It provides browsers (via the Linux Compatibility Layer) that are not natively available on FreeBSD – but with DRM sh!t needed to access for example Netflix content.

The Linux Browser Installer is easy to install – but its also easy to update.

Below you will find commands that will keep your Linux Browser Installer updated and secure.

# git clone https://github.com/mrclksr/linux-browser-installer.git
# cd linux-browser-installer
# ./linux-browser-installer chroot upgrade


One may think that WINE is just another package and that it was already updated during the # pkg upgrade cycle – it depends – the default WINE package is for 64bit excusables … but its also possible to run (and often needed) the older 32bit executables.

The problem is that the 32bit environment has its own separate root with its own packages set.

To be honest its not a big deal – you just need to remember to update it along with other things you update periodically πŸ™‚

Below is the command that updates the 32bit WINE binaries/packages.

% /usr/local/share/wine/pkg32.sh upgrade

One of the things you need to keep in mind that it is done by you (user) and not the root user of the machine.

Cargo Packages

While 95% of this topic is covered above – no one prevents you from using the additional Cargo packages – and I do it myself also.

Its just that some software is not yet available by the official FreeBSD packages – but its already official by using the Cargo packages.

I personally use about 10 different Cargo packages that are still not available on the FreeBSD packages.


Here are the instructions to keep these Cargo packages updated.

First and most important – you need to install the cargo-update package to be able to update installed Cargo packages.

Then you may just use the other command to have Cargo packages updated.

# cargo install cargo-update
# cargo install-update -a

FreeBSD Ports Tree

Last but not least – the FreeBSD Ports Tree – which even if you only use binary packages – can often come handy in some exceptions.

We all know the ‘default’ rule that mixing Packages and Ports is a bad idea in the FreeBSD world – and I generally agree – its a bad idea if you do not know what you are doing.

If you do know what you are doing – you may mix anything with everything – just do not spam the FreeBSD Forums for help later πŸ™‚

The tool to update the local FreeBSD Ports Tree on your machine is still portsnap(8) and the auto argument is usually more then enough.

# portsnap auto

From the other things – you may want to setup the WRKDIRPREFIX variable to have everything built in the /usr/ports/obj directory – to have everything in one place.

# grep WRKDIRPREFIX /etc/make.conf
# rm -rf \
    /usr/ports/obj \

I often also clean the /usr/ports/obj and /usr/ports/distfiles directories.


Besides the things that I have wrote above I also sometimes save some binaries to the ~/scripts/bin path. There is not upgrade path for them besides manually checking the provider page.

Some examples of such software on my system are doso or cpuc ones.

As I do not have anything more to add here – please feel free to comment what is missing in keeping your workstation updated and secure.



Native Urban Terror on FreeBSD

Welcome to 2023 and let me start a first article of this new year with a … guest post by @NeoMoevius from Twitter. That is right. I did not invented it. I did not created it. I only partially wrote it – treat me as a ghost writer here. ll the thanks and welcomes goes directly to @NeoMoevius – I am just a messenger here πŸ™‚

This post will be about playing (and first building – of course) the Urban Terror game on FreeBSD system. It is about how to build and install Urban Terror 4.3 on FreeBSD without Linux emulation or using WINE. Natively. This will be on the latest and supported FreeBSD 13.1-RELEASE system.

There are not many steps to make it happen. First – just download the official Urban Terror ZIP file.

% mkdir _UT
% cd _UT
% fetch http://cdn.urbanterror.info/urt/43/releases/zips/UrbanTerror434_full.zip
UrbanTerror434_full.zip                         3% of 1403 MB 1836 kBps 11m38s
% unzip UrbanTerror434_full.zip
% cd UrbanTerror43
% pwd

Lets leave that alone for now πŸ™‚

We will also need to install some dependencies.

# pkg install -y \
    devel/sdl20 \
    devel/pkgconf \
    devel/gmake \
    ftp/curl \
    graphics/sdl2_image \
    graphics/sdl2_ttf \
    audio/sdl2_mixer \

We will now need to download and compile source code of ioquake 3 for Urban Terror.

% mkdir _IOQ3
% cd _IOQ3
% git clone https://github.com/mickael9/ioq3.git
Cloning into 'ioq3'...
remote: Enumerating objects: 28169, done.
Receiving objects:  19% (5353/28169), 6.77 MiB | 2.24 MiB/s
% cd ioq3
% gmake
% echo ${?}
% cd build/release-freebsd-x86_64
% ls -l
total 2773K
drwxr-xr-x 2 vermaden vermaden       2 2023-01-20 20:11 autoupdater/
drwxr-xr-x 4 vermaden vermaden     228 2023-01-20 20:12 client/
drwxr-xr-x 2 vermaden vermaden     154 2023-01-20 20:11 ded/
drwxr-xr-x 2 vermaden vermaden     166 2023-01-20 20:12 renderergl1/
drwxr-xr-x 3 vermaden vermaden      77 2023-01-20 20:12 renderergl2/
-rwxr-xr-x 1 vermaden vermaden  862712 2023-01-20 20:12 renderer_opengl1_x86_64.so
-rwxr-xr-x 1 vermaden vermaden 1143552 2023-01-20 20:12 renderer_opengl2_x86_64.so
-rwxr-xr-x 1 vermaden vermaden 2133400 2023-01-20 20:12 urbanterror-m9.x86_64
-rwxr-xr-x 1 vermaden vermaden  970368 2023-01-20 20:11 urbanterror-server-m9.x86_64

The files that are interesting for us are listed below:

  • renderer_opengl1_x86_64.so
  • renderer_opengl2_x86_64.so
  • urbanterror-m9.x86_64
  • urbanterror-server-m9.x86_64

… and now you will need to copy these four files into the Urban Terror folder when you have uncompressed the game.

% cp \
    renderer_opengl1_x86_64.so   \
    renderer_opengl2_x86_64.so   \
    urbanterror-m9.x86_64        \
    urbanterror-server-m9.x86_64 \

% cd /home/vermaden/_UT/UrbanTerror43

% pwd

% ls -l
total 8495K
drwxr-xr-x 2 vermaden vermaden      30 2023-01-20 20:19 q3ut4/
drwxr-xr-x 3 vermaden vermaden       3 2023-01-20 20:19 Quake3-UrT.app/
-rw-r--r-- 1 vermaden vermaden 1082800 2018-06-21 22:08 Quake3-UrT-Ded.exe
-rwxr-xr-x 1 vermaden vermaden  816002 2018-06-21 22:08 Quake3-UrT-Ded.i386
-rwxr-xr-x 1 vermaden vermaden  961958 2018-06-21 22:08 Quake3-UrT-Ded.x86_64
-rw-r--r-- 1 vermaden vermaden 2634689 2018-06-21 22:08 Quake3-UrT.exe
-rwxr-xr-x 1 vermaden vermaden 1702624 2018-06-21 22:08 Quake3-UrT.i386
-rwxr-xr-x 1 vermaden vermaden 1940280 2018-06-21 22:08 Quake3-UrT.x86_64
-rwxr-xr-x 1 vermaden vermaden  862712 2023-01-20 20:20 renderer_opengl1_x86_64.so
-rwxr-xr-x 1 vermaden vermaden 1143552 2023-01-20 20:20 renderer_opengl2_x86_64.so
-rwxr-xr-x 1 vermaden vermaden 2133400 2023-01-20 20:20 urbanterror-m9.x86_64
-rwxr-xr-x 1 vermaden vermaden  970368 2023-01-20 20:20 urbanterror-server-m9.x86_64

We will now try to start that Urban Terror game.

% pwd

% ./urbanterror-m9.x86_64
ioq3-UrT m9-builds/31 freebsd-x86_64 Jan 20 2023
SSE instruction set enabled
----- FS_Startup -----
We are looking in the current search path:
./q3ut4/zUrT43_qvm.pk3 (4 files)
./q3ut4/zUrT43_021.pk3 (85 files)
./q3ut4/zUrT43_020.pk3 (295 files)
./q3ut4/zUrT43_019.pk3 (342 files)
./q3ut4/zUrT43_018.pk3 (801 files)

Seems to start and work properly.

Here are several shots of what I tried to play it for some single online event.





All the screens above are in the windowed more but you can switch between window and full screen with [ALT]+[ENTER] shortcut at anytime. It was just easier for me to catch several shots for this article πŸ™‚

Seems I am definitely not the best at this game :p


The Urban Terror game run smooth on my Intel HD Graphics 3000 card.

Fortunately I did not need to switch BIOS settings to start my decade old Nvidia Quadro 2000M monster :p

Not sure what I can add here – definitely a kind thank You for @NeoMoevius for his offer of making this content available for You πŸ™‚


Connect FreeBSD to FreeIPA/Red Hat Identity Management

Corporate needs are simple – one ring to rule them all place to get users from. On the open source path there are several ways to achieve that. Alongside ‘plain’ OpenLDAP there is also FreeIPA – which is open source and free version of the Red Hat Identity Management (IDM).


This guide will show you how to make basic FreeIPA install and connect a FreeBSD 13.1-RELEASE system to it.


The Table of Contents for this article looks as follows.

  • Connect FreeBSD to FreeIPA/Red Hat Identity Management
  • FreeIPA
    • FreeIPA Requirements
    • FreeIPA Setup
  • FreeBSD Client
    • FreeBSD Packages
    • FreeBSD Setup
    • FreeIPA/IDM Setup Part
    • Finish Setup with Web Browser in FreeIPA/IDM Page
    • FreeBSD FreeIPA Login Test
  • FreeBSD Jail as FreeIPA/IDM Client
    • Basic FreeBSD Jail Preparations
    • Configure FreeBSD Jail to Connect to FreeIPA/IDM Server
  • Linux FreeIPA/IDM Client
    • FreeIPA/IDM Setup Part
    • Linux FreeIPA/IDM Client Setup


As typical CentOS is dead (yes there is CentOS Stream available but its not a RHEL clone) I have two options here. Rocky Linux and Alma Linux. I will use the latter as it seems more popular and more up to date. In this guide the FreeIPA/IDM server will hosted on the Alma Linux 8.6 system.

To make things easier I installed that Alma Linux 8.6 with single 20GB / root on the /dev/sda1 partition. No separate /boot. No LVM. Just good old plain fucking simple single raw partition for everything. Seems no one does it these days πŸ™‚

[root@idm ~]# lsblk
sda      8:0    0   20G  0 disk
└─sda1   8:1    0   20G  0 part /

FreeIPA Requirements

The minimum hardware requirements for installing FreeIPA server are as follows.

CPU: 2
DNS: fully qualified domain name for FreeIPA
     must be resolvable from DNS server configured in system

For this installation I have used the network.

The FreeIPA/IDM server will get the IP.

The FreeIPA/IDM Linux client rhlike.vercorp.org will get the IP.

The FreeIPA/IDM FreeBSD client fbsd.vercorp.org will get the IP.

The FreeIPA/IDM FreeBSD client fbsdjail.vercorp.org will get the IP.

For lack of better ideas I have used vercorp.org/VERCORP.ORG as domain/realm names and idm.vercorp.org as the FreeIPA/IDM hostname.

Details of FreeIPA/IDM idm.vercorp.org system below.

hostname: idm.vercorp.org
  domain: vercorp.org
   realm: VERCORP.ORG

FreeBSD fbsd.vercorp.org system.

hostname: fbsd.vercorp.org

FreeBSD Jail fbsdjail.vercorp.org system.

hostname: fbsdjail.vercorp.org

If you are curious what is hidden in the IP – then its a typical Alma Linux that I first used to try if the FreeIPA/IDM works at all πŸ™‚

FreeIPA Setup

Because Anaconda is far from being a usable installer – this is how the only enp0s3 interface config looks like after manual intervention.

[root@idm ~]# cat /etc/sysconfig/network-scripts/ifcfg-enp0s3

Before we will go into setup procedures – we will update that Alma Linux system.

[root@idm ~]# yum update -y
[root@idm ~]# reboot

After the reboot we will disable the IPv6 stack for main interface (enp0s3) as FreeIPA installer has some problem with it. We do not need IPv6 here anyway so …

[root@idm ~]# cat << EOF >> /etc/sysctl.conf

Lets set our FreeIPA/IDM hostname if we missed that at the Anaconda installer part. We will also setup the system time zone.

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

[root@idm ~]# hostnamectl
   Static hostname: idm.vercorp.org
         Icon name: computer-vm
           Chassis: vm
        Machine ID: b8bfb8bcc23147eb9cc7b62c72a09c32
           Boot ID: 06158ef430d9467d959076ab4396314e
    Virtualization: oracle
  Operating System: AlmaLinux 8.6 (Sky Tiger)
       CPE OS Name: cpe:/o:almalinux:almalinux:8::baseos
            Kernel: Linux 4.18.0-372.26.1.el8_6.x86_64
      Architecture: x86-64

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

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

[root@idm ~]#Β timedatectl
               Local time: Mon 2022-10-17 15:08:28 CEST
           Universal time: Mon 2022-10-17 13:08:28 UTC
                 RTC time: Sat 2022-10-15 00:28:10
                Time zone: Europe/Warsaw (CEST, +0200)
System clock synchronized: yes
              NTP service: inactive
          RTC in local TZ: no

Lets add the system IP and name to the /etc/hosts file now.

[root@idm ~]# echo "$( hostname -i | awk '{print $NF}' )   $( hostname ) $( hostname -s )" >> /etc/hosts

[root@idm ~]# grep idm /etc/hosts   idm.vercorp.org idm

[root@idm ~]# cat /etc/hosts   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6   idm.vercorp.org idm

We need to enable the FreeIPA/IDM module in yum(8).

[root@idm ~]# yum module list idm
Last metadata expiration check: 0:00:31 ago on Tue 18 Oct 2022 01:02:51 PM CEST.
AlmaLinux 8 - AppStream
Name  Stream      Profiles                                  Summary
idm   DL1         adtrust, client, common [d], dns, server  The Red Hat Enterprise Linux Identity Management system module
idm   client [d]  common [d]                                RHEL IdM long term support client module

Hint: [d]efault, [e]nabled, [x]disabled, [i]nstalled

[root@idm ~]# yum module enable idm:DL1 -y
Last metadata expiration check: 0:01:06 ago on Tue 18 Oct 2022 01:02:51 PM CEST.
Dependencies resolved.
 Package                 Architecture           Version                  Repository              Size
Enabling module streams:
 389-ds                                         1.4
 httpd                                          2.4
 idm                                            DL1
 pki-core                                       10.6
 pki-deps                                       10.6

Transaction Summary


Some additional step needed.

[root@idm ~]# yum distro-sync
Last metadata expiration check: 0:10:07 ago on Mon 17 Oct 2022 03:14:32 PM CEST.
Dependencies resolved.
Nothing to do.

We will now install FreeIPA/IDM with DNS as this setup is the most simplistic one. We focus on FreeBSD part here in that article.

[root@idm ~]# yum install -y bind-utils chrony nc
[root@idm ~]# yum module install idm:DL1/dns -y

One can use the ‘interactive’ installer and answer ‘by hand’ for all the asked questions – but to be honest I prefer to type my command once and make it ‘happen’ altogether without my time wasted.

As you probably guessed – we will use the unattended mode for the FreeIPA/IDM installer.

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

Checking DNS domain 0.0.10.in-addr.arpa., please wait ...

The log file for this installation can be found in /var/log/ipaserver-install.log
This program will set up the IPA Server.
Version 4.9.8

This includes:
  * Configure a stand-alone CA (dogtag) for certificate management
  * Create and configure an instance of Directory Server
  * Create and configure a Kerberos Key Distribution Center (KDC)
  * Configure Apache (httpd)
  * Configure DNS (bind)
  * Configure SID generation
  * Configure the KDC to enable PKINIT

Excluded by options:
  * Configure the NTP client (chronyd)

Warning: skipping DNS resolution of host idm.vercorp.org
Checking DNS domain vercorp.org., please wait ...
Checking DNS domain 0.0.10.in-addr.arpa., please wait ...
Checking DNS domain 0.0.10.in-addr.arpa., please wait ...
Using reverse zone(s) 0.0.10.in-addr.arpa.
Trust is configured but no NetBIOS domain name found, setting it now.

The IPA Master Server will be configured with:
Hostname:       idm.vercorp.org
IP address(es):
Domain name:    vercorp.org
Realm name:     VERCORP.ORG

The CA will be configured with:
Subject DN:   CN=Certificate Authority,O=VERCORP.ORG
Subject base: O=VERCORP.ORG
Chaining:     self-signed

BIND DNS server will be configured to serve IPA domain with:
Forwarders:       No forwarders
Forward policy:   only
Reverse zone(s):  0.0.10.in-addr.arpa.

Disabled p11-kit-proxy
Configuring directory server (dirsrv). Estimated time: 30 seconds
  [1/41]: creating directory server instance
Validate installation settings ...
Create file system structures ...
Perform SELinux labeling ...
Create database backend: dc=vercorp,dc=org ...
Perform post-installation tasks ...
  [2/41]: tune ldbm plugin
  [3/41]: adding default schema
  [4/41]: enabling memberof plugin
  [5/41]: enabling winsync plugin
  [6/41]: configure password logging
  [7/41]: configuring replication version plugin
  [8/41]: enabling IPA enrollment plugin
  [9/41]: configuring uniqueness plugin
  [10/41]: configuring uuid plugin
  [11/41]: configuring modrdn plugin
  [12/41]: configuring DNS plugin
  [13/41]: enabling entryUSN plugin
  [14/41]: configuring lockout plugin
  [15/41]: configuring topology plugin
  [16/41]: creating indices
  [17/41]: enabling referential integrity plugin
  [18/41]: configuring certmap.conf
  [19/41]: configure new location for managed entries
  [20/41]: configure dirsrv ccache and keytab
  [21/41]: enabling SASL mapping fallback
  [22/41]: restarting directory server
  [23/41]: adding sasl mappings to the directory
  [24/41]: adding default layout
  [25/41]: adding delegation layout
  [26/41]: creating container for managed entries
  [27/41]: configuring user private groups
  [28/41]: configuring netgroups from hostgroups
  [29/41]: creating default Sudo bind user
  [30/41]: creating default Auto Member layout
  [31/41]: adding range check plugin
  [32/41]: creating default HBAC rule allow_all
  [33/41]: adding entries for topology management
  [34/41]: initializing group membership
  [35/41]: adding master entry
  [36/41]: initializing domain level
  [37/41]: configuring Posix uid/gid generation
  [38/41]: adding replication acis
  [39/41]: activating sidgen plugin
  [40/41]: activating extdom plugin
  [41/41]: configuring directory to start on boot
Done configuring directory server (dirsrv).
Configuring Kerberos KDC (krb5kdc)
  [1/10]: adding kerberos container to the directory
  [2/10]: configuring KDC
  [3/10]: initialize kerberos container
  [4/10]: adding default ACIs
  [5/10]: creating a keytab for the directory
  [6/10]: creating a keytab for the machine
  [7/10]: adding the password extension to the directory
  [8/10]: creating anonymous principal
  [9/10]: starting the KDC
  [10/10]: configuring KDC to start on boot
Done configuring Kerberos KDC (krb5kdc).
Configuring kadmin
  [1/2]: starting kadmin
  [2/2]: configuring kadmin to start on boot
Done configuring kadmin.
Configuring ipa-custodia
  [1/5]: Making sure custodia container exists
  [2/5]: Generating ipa-custodia config file
  [3/5]: Generating ipa-custodia keys
  [4/5]: starting ipa-custodia
  [5/5]: configuring ipa-custodia to start on boot
Done configuring ipa-custodia.
Configuring certificate server (pki-tomcatd). Estimated time: 3 minutes
  [1/29]: configuring certificate server instance
  [2/29]: stopping certificate server instance to update CS.cfg
  [3/29]: backing up CS.cfg
  [4/29]: Add ipa-pki-wait-running
  [5/29]: secure AJP connector
  [6/29]: reindex attributes
  [7/29]: exporting Dogtag certificate store pin
  [8/29]: disabling nonces
  [9/29]: set up CRL publishing
  [10/29]: enable PKIX certificate path discovery and validation
  [11/29]: authorizing RA to modify profiles
  [12/29]: authorizing RA to manage lightweight CAs
  [13/29]: Ensure lightweight CAs container exists
  [14/29]: Ensuring backward compatibility
  [15/29]: starting certificate server instance
  [16/29]: configure certmonger for renewals
  [17/29]: requesting RA certificate from CA
  [18/29]: publishing the CA certificate
  [19/29]: adding RA agent as a trusted user
  [20/29]: configure certificate renewals
  [21/29]: Configure HTTP to proxy connections
  [22/29]: updating IPA configuration
  [23/29]: enabling CA instance
  [24/29]: importing IPA certificate profiles
  [25/29]: migrating certificate profiles to LDAP
  [26/29]: adding default CA ACL
  [27/29]: adding 'ipa' CA entry
  [28/29]: configuring certmonger renewal for lightweight CAs
  [29/29]: deploying ACME service
Done configuring certificate server (pki-tomcatd).
Configuring directory server (dirsrv)
  [1/3]: configuring TLS for DS instance
  [2/3]: adding CA certificate entry
  [3/3]: restarting directory server
Done configuring directory server (dirsrv).
Configuring ipa-otpd
  [1/2]: starting ipa-otpd
  [2/2]: configuring ipa-otpd to start on boot
Done configuring ipa-otpd.
Configuring the web interface (httpd)
  [1/22]: stopping httpd
  [2/22]: backing up ssl.conf
  [3/22]: disabling nss.conf
  [4/22]: configuring mod_ssl certificate paths
  [5/22]: setting mod_ssl protocol list
  [6/22]: configuring mod_ssl log directory
  [7/22]: disabling mod_ssl OCSP
  [8/22]: adding URL rewriting rules
  [9/22]: configuring httpd
Nothing to do for configure_httpd_wsgi_conf
  [10/22]: setting up httpd keytab
  [11/22]: configuring Gssproxy
  [12/22]: setting up ssl
  [13/22]: configure certmonger for renewals
  [14/22]: publish CA cert
  [15/22]: clean up any existing httpd ccaches
  [16/22]: enable ccache sweep
  [17/22]: configuring SELinux for httpd
  [18/22]: create KDC proxy config
  [19/22]: enable KDC proxy
  [20/22]: starting httpd
  [21/22]: configuring httpd to start on boot
  [22/22]: enabling oddjobd
Done configuring the web interface (httpd).
Configuring Kerberos KDC (krb5kdc)
  [1/1]: installing X509 Certificate for PKINIT
Done configuring Kerberos KDC (krb5kdc).
Applying LDAP updates
Upgrading IPA:. Estimated time: 1 minute 30 seconds
  [1/10]: stopping directory server
  [2/10]: saving configuration
  [3/10]: disabling listeners
  [4/10]: enabling DS global lock
  [5/10]: disabling Schema Compat
  [6/10]: starting directory server
  [7/10]: upgrading server
  [8/10]: stopping directory server
  [9/10]: restoring configuration
  [10/10]: starting directory server
Restarting the KDC
dnssec-validation yes
Configuring DNS (named)
  [1/12]: generating rndc key file
  [2/12]: adding DNS container
  [3/12]: setting up our zone
  [4/12]: setting up reverse zone
  [5/12]: setting up our own record
  [6/12]: setting up records for other masters
  [7/12]: adding NS record to the zones
  [8/12]: setting up kerberos principal
  [9/12]: setting up named.conf
created new /etc/named.conf
created named user config '/etc/named/ipa-ext.conf'
created named user config '/etc/named/ipa-options-ext.conf'
created named user config '/etc/named/ipa-logging-ext.conf'
  [10/12]: setting up server configuration
  [11/12]: configuring named to start on boot
  [12/12]: changing resolv.conf to point to ourselves
Done configuring DNS (named).
Restarting the web server to pick up resolv.conf changes
Configuring DNS key synchronization service (ipa-dnskeysyncd)
  [1/7]: checking status
  [2/7]: setting up bind-dyndb-ldap working directory
  [3/7]: setting up kerberos principal
  [4/7]: setting up SoftHSM
  [5/7]: adding DNSSEC containers
  [6/7]: creating replica keys
  [7/7]: configuring ipa-dnskeysyncd to start on boot
Done configuring DNS key synchronization service (ipa-dnskeysyncd).
Restarting ipa-dnskeysyncd
Restarting named
Updating DNS system records
Configuring SID generation
  [1/8]: creating samba domain object
  [2/8]: adding admin(group) SIDs
  [3/8]: adding RID bases
  [4/8]: updating Kerberos config
'dns_lookup_kdc' already set to 'true', nothing to do.
  [5/8]: activating sidgen task
  [6/8]: restarting Directory Server to take MS PAC and LDAP plugins changes into account
  [7/8]: adding fallback group
  [8/8]: adding SIDs to existing users and groups
This step may take considerable amount of time, please wait..
Configuring client side components
This program will set up IPA client.
Version 4.9.8

Using existing certificate '/etc/ipa/ca.crt'.
Client hostname: idm.vercorp.org
DNS Domain: vercorp.org
IPA Server: idm.vercorp.org
BaseDN: dc=vercorp,dc=org

Configured /etc/sssd/sssd.conf
Systemwide CA database updated.
Adding SSH public key from /etc/ssh/ssh_host_ed25519_key.pub
Adding SSH public key from /etc/ssh/ssh_host_ecdsa_key.pub
Adding SSH public key from /etc/ssh/ssh_host_rsa_key.pub
SSSD enabled
Configured /etc/openldap/ldap.conf
Configured /etc/ssh/ssh_config
Configured /etc/ssh/sshd_config
Configuring vercorp.org as NIS domain.
Client configuration complete.
The ipa-client-install command was successful

Setup complete

Next steps:
  1. You must make sure these network ports are open:
    TCP Ports:
      * 80, 443: HTTP/HTTPS
      * 389, 636: LDAP/LDAPS
      * 88, 464: kerberos
      * 53: bind
    UDP Ports:
      * 88, 464: kerberos
      * 53: bind

  2. You can now obtain a kerberos ticket using the command: 'kinit admin'
     This ticket will allow you to use the IPA tools (e.g., ipa user-add)
     and the web user interface.
  3. Kerberos requires time synchronization between clients
     and servers for correct operation. You should consider enabling chronyd.

Be sure to back up the CA certificates stored in /root/cacert.p12
These files are required to create replicas. The password for these
files is the Directory Manager password
The ipa-server-install command was successful
[root@idm ~]#

Seems that all went well and now we have our FreeIPA/IDM installed.

Lets check several things.

[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                   disabled
ipa-custodia.service                       disabled
ipa-dnskeysyncd.service                    disabled
ipa-healthcheck.service                    disabled
ipa-ods-exporter.service                   disabled
ipa-otpd@.service                          static
ipa.service                                enabled

Seems to be installed and working.

What about the /etc/sssd/sssd.conf config.

[root@idm ~]# cat /etc/sssd/sssd.conf

id_provider = ipa
ipa_server_mode = True
ipa_server = idm.vercorp.org
ipa_domain = vercorp.org
ipa_hostname = idm.vercorp.org
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
services = nss, pam, ifp, ssh, sudo

domains = vercorp.org
homedir_substring = /home
memcache_timeout = 600






allowed_uids = ipaapi, root


There is also /etc/ssh/ssh_config.d/04-ipa.conf file …

[root@idm ~]# cat /etc/ssh/ssh_config.d/04-ipa.conf
# IPA-related configuration changes to ssh_config
PubkeyAuthentication yes
GlobalKnownHostsFile /var/lib/sss/pubconf/known_hosts
#VerifyHostKeyDNS yes

# assumes that if a user does not have shell (/sbin/nologin),
# this will return nonzero exit code and proxy command will be ignored
Match exec true
  ProxyCommand /usr/bin/sss_ssh_knownhostsproxy -p %p %h

For some reason we need to manually enable and start the Apache HTTP server.

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

You can now access the FreeIPA/IDM at your browser on the http://idm.vercorp.org address. If you use the IP then you will be redirected to the http://idm.vercorp.org address so make sure you have added that host to your local /etc/hosts file.



On the second screen you will see that I have already created the vermaden user.

FreeBSD Client

We will get straight into the point. After having FreeBSD 13.1-RELEASE installed in the most ‘default’ way in the bsdinstall(8) installer – the Auto ZFS road – we will now fetch the up to date FreeBSD Ports tree with portsnap(8) tool.

This is the main /etc/rc.conf config file.

# cat /etc/rc.conf
ifconfig_vtnet0="inet netmask"

FreeBSD Packages

We need to have FreeBSD Ports tree.

# portsnap auto

Lets check what is the current default SAMBA version on FreeBSD.

# grep -i samba /usr/ports/Mk/*default*
SAMBA_DEFAULT?=         4.12

To omit a lot of pointless compilation I will first install all precompiled packages – that would also install needed dependencies. Then we will rebuild just the several needed packages.

# pkg install krb5 sudo cyrus-sasl cyrus-sasl-gssapi pam_mkhomedir openldap26-client samba412

Settings in the /etc/make.conf file.

# cat /etc/make.conf
# USE /usr/ports/obj PLACE

WITH_GSSAPI=         yes

Lets configure the needed ports.

# \
for I in /usr/ports/security/sudo \
         /usr/ports/security/sssd \
         /usr/ports/security/krb5 \
         /usr/ports/security/cyrus-sasl2-gssapi \
         /usr/ports/security/pam_mkhomedir \
  make -C ${I} rmconfig

# \
for I in /usr/ports/security/sudo \
         /usr/ports/security/sssd \
         /usr/ports/security/krb5 \
         /usr/ports/security/cyrus-sasl2-gssapi \
         /usr/ports/security/pam_mkhomedir \
  make -C ${I} config-recursive

The curses(3X) selection will look more or less like these below.

=> security/sudo | OPTIONS___________________________________________________________________________
[x] AUDIT              Enable BSM audit support
[ ] DISABLE_AUTH       Do not require authentication by default
[ ] DISABLE_ROOT_SUDO  Do not allow root to run sudo
[ ] DOCS               Build and/or install documentation
[ ] EXAMPLES           Build and/or install examples
[ ] INSULTS            Enable insults on failures
[x] LDAP               LDAP protocol support
[ ] NLS                Native Language Support
[ ] NOARGS_SHELL       Run a shell if no arguments are given
[ ] OPIE               Enable one-time passwords (no PAM support)
[ ] PAM                Pluggable authentication module support
[ ] PYTHON             Enable python plugin support
[x] SSSD               Enable SSSD backend support.
=> security/sudo | Kerberos 5 Authentication (no PAM support)
( ) GSSAPI_BASE        GSSAPI support via base system (needs Kerberos)
( ) GSSAPI_HEIMDAL     GSSAPI support via security/heimdal
(*) GSSAPI_MIT         GSSAPI support via security/krb5

=> security/sssd | OPTIONS___________________________________________________________________________
[ ] DOCS  Build and/or install documentation
[x] SMB   Install IPA and AD providers (requires Samba4)

=> security/cyrus-sasl2-gssapi | OPTIONS_____________________________________________________________
( ) GSSAPI_BASE     GSSAPI support via base system (needs Kerberos)
( ) GSSAPI_HEIMDAL  GSSAPI support via security/heimdal
(*) GSSAPI_MIT      GSSAPI support via security/krb5

=> net/openldap26-client | OPTIONS___________________________________________________________________
[ ] DEBUG   Build with debugging support
[ ] DOCS    Build and/or install documentation
[ ] FETCH   Enable fetch(3) support
[x] GSSAPI  With GSSAPI support

=> security/krb5 | OPTIONS___________________________________________________________________________
[ ] DNS_FOR_REALM  Enable DNS lookups for Kerberos realm names
[ ] EXAMPLES       Build and/or install examples
[x] KRB5_HTML      Install krb5 HTML documentation
[x] KRB5_PDF       Install krb5 PDF documentation
[x] LDAP           LDAP protocol support
[ ] LMDB           OpenLDAP Lightning Memory-Mapped Database support
[ ] NLS            Native Language Support
=> security/krb5 | Command Line Editing for kadmin and ktutil
(*) READLINE       Command line editing via libreadline
( ) LIBEDIT        Command line editing via libedit

We can now check what options have been saved.

# cat /var/db/ports/security_sudo-sssd/options

# cat /var/db/ports/security_sssd/options

# cat /var/db/ports/security_cyrus-sasl2/options

# cat /var/db/ports/net_openldap26-client/options

# cat /var/db/ports/security_krb5/options
# This file is auto-generated by 'make config'.
# Options for krb5-1.20

… and build them.

# \
for I in /usr/ports/security/sudo \
         /usr/ports/security/sssd \
         /usr/ports/security/cyrus-sasl2-gssapi \
         /usr/ports/security/pam_mkhomedir \
         /usr/ports/net/openldap26-client \
  make -C ${I} build

… unsinstall them and create their packages.

# \
for I in /usr/ports/security/sudo \
         /usr/ports/security/sssd \
         /usr/ports/security/cyrus-sasl2-gssapi \
         /usr/ports/security/pam_mkhomedir \
         /usr/ports/net/openldap26-client \
  make -C ${I} deinstall package

After some time we have our built packages.

# find /usr/ports/obj/ -name \*.pkg

In the future I need to add some short guide to build them regularly with Synth or Poudriere πŸ™‚

Now we need to install these packages in quite nontypical way. One by one – in specified order. It will not be needed it we would have a separate additional pkg(8) repository with Poudriere build packages.

Our packages:

# ls -1 *.pkg

… and their install process.

# pkg install -y c-ares

# pkg add sssd-smb4-1.16.5_6.pkg

# pkg install -y cyrus-sasl-gssapi-2.1.28.pkg
New packages to be INSTALLED:
        cyrus-sasl: 2.1.28
        cyrus-sasl-gssapi: 2.1.28
        krb5: 1.20

# pkg delete -f -y krb5
Installed packages to be REMOVED:
        krb5: 1.20

# pkg add krb5-1.20.pkg

# pkg install -y sssd

# pkg add sudo-sssd-1.9.11p3.pkg

# pkg delete -f -y sssd
Installed packages to be REMOVED:
        sssd: 1.16.5_6

# pkg install ding-libs ldb21 nspr nss pcre samba412

# pkg add sssd-smb4-1.16.5_6.pkg

FreeBSD Setup

Create needed dirs.

# mkdir -p \
    /usr/local/etc/ipa \
    /var/log/sssd \
    /var/run/sss/private \

Set system hostname.

# hostname fbsd.vercorp.org

# hostname

Fetch the FreeIPA/IDM certificate.

# fetch -o /usr/local/etc/ipa/ca.crt

FreeIPA/IDM Setup Part

We need to execute several instructions on the FreeIPA/IDM to connect FreeBSD client to it.

Its adding the A and PTR records in DNS for the address and adding the fbsd.vercorp.org host.

We also need to generate the key for our fbsd.vercorp.org system.

[root@idm ~]# kinit admin
Password for admin@VERCORP.ORG:

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

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

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

Now we need to get ‘our’ key from FreeIPA/IDM server … along with proper /etc/hosts file.

# scp root@ /usr/local/etc/ipa/krb5.keytab

# cat << EOF > /etc/hosts
::1              localhost localhost.my.domain        localhost localhost.my.domain        idm.vercorp.org  idm        fbsd.vercorp.org fbsd

Now the /usr/local/etc/openldap/ldap.conf file.

# cat << EOF > /usr/local/etc/openldap/ldap.conf
BASE        dc=org,dc=vercorp
URI         ldap://idm.vercorp.org/
#DEREF      never
ssl         start_tls
TLS_CACERT  /usr/local/etc/ipa/ca.crt

… and /etc/krb5.conf file.

# cat << EOF > /etc/krb5.conf
  default_realm = VERCORP.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

    kdc = idm.vercorp.org:88
    master_kdc = idm.vercorp.org:88
    admin_server = idm.vercorp.org:749
    default_domain = vercorp.org
    pkinit_anchors = FILE:/usr/local/etc/ipa/ca.crt

  .vercorp.org = VERCORP.ORG
  vercorp.org = VERCORP.ORG

  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

… and /usr/local/etc/sssd/sssd.conf file.

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

# debug_level = 9
cache_credentials = True
krb5_store_password_if_offline = True
krb5_realm = VERCORP.ORG
ipa_domain = vercorp.org
id_provider = ipa
auth_provider = ipa
access_provider = ipa
ipa_hostname = fbsd.vercorp.org
chpass_provider = ipa
ipa_server = _srv_, idm.vercorp.org
ldap_tls_cacert = /usr/local/etc/ipa/ca.crt
krb5_keytab = /usr/local/etc/ipa/krb5.keytab

services = nss, pam, ssh, sudo
config_file_version = 2
domains = vercorp.org

filter_users = root,toor
homedir_substring = /usr/home/%u


# debug_level = 0x3ff0


# chmod 600 /usr/local/etc/sssd/sssd.conf

FreeBSD have user account under /usr/home to make sure /home also points there.

# ln -s /usr/home /home

The automatic startup of sssd(8) daemon (not to confuse with sshd(8)) needs to be also configured.

# sysrc sssd_enable=YES
# service sssd start

We also need to configure /etc/nsswitch.conf file.

# cp /etc/nsswitch.conf /etc/nsswitch.conf.BCK

# diff -u /etc/nsswitch.conf.BCK /etc/nsswitch.conf
--- /etc/nsswitch.conf.BCK      2022-10-24 20:10:09.163251000 +0200
+++ /etc/nsswitch.conf  2022-10-24 20:10:57.207406000 +0200
@@ -2,15 +2,17 @@
 # nsswitch.conf(5) - name service switch configuration file
 # $FreeBSD$
-group: compat
+group: files sss
 group_compat: nis
 hosts: files dns
-netgroup: compat
+# netgroup: compat
 networks: files
-passwd: compat
+passwd: files sss
 passwd_compat: nis
 shells: files
 services: compat
 services_compat: nis
 protocols: files
 rpc: files
+sudoers: sss files
+netgroup: files

The final /etc/nsswitch.conf file looks as follows.

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

Now the /etc/pam.d/system file.

# cp /etc/pam.d/system /root/etc---pam.d---system.BCK

# diff -u  /root/etc---pam.d---system.BCK /etc/pam.d/system
--- /root/etc---pam.d---system.BCK      2022-10-24 20:13:05.546657000 +0200
+++ /etc/pam.d/system   2022-10-24 20:16:36.722666000 +0200
@@ -7,19 +7,23 @@
 # auth
 auth           sufficient      pam_opie.so             no_warn no_fake_prompts
 auth           requisite       pam_opieaccess.so       no_warn allow_local
-#auth          sufficient      pam_krb5.so             no_warn try_first_pass
+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       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        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_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       use_authtok
 password       required        pam_unix.so             no_warn try_first_pass

The final /etc/pam.d/system file looks as follows.

# cat /etc/pam.d/system
# $FreeBSD$
# System-wide defaults

# auth
auth            sufficient      pam_opie.so             no_warn no_fake_prompts
auth            requisite       pam_opieaccess.so       no_warn allow_local
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       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        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_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       use_authtok
password        required        pam_unix.so             no_warn try_first_pass

Now its time for /etc/pam.d/sshd file.

# cp /etc/pam.d/sshd /root/etc---pam.d---sshd.BCK

# diff -u /root/etc---pam.d---sshd.BCK /etc/pam.d/sshd
--- /root/etc---pam.d---sshd.BCK        2022-10-24 20:17:34.063630000 +0200
+++ /etc/pam.d/sshd     2022-10-24 20:19:16.165810000 +0200
@@ -7,8 +7,9 @@
 # auth
 auth           sufficient      pam_opie.so             no_warn no_fake_prompts
 auth           requisite       pam_opieaccess.so       no_warn allow_local
-#auth          sufficient      pam_krb5.so             no_warn try_first_pass
+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       use_first_pass
 auth           required        pam_unix.so             no_warn try_first_pass

 # account
@@ -16,11 +17,14 @@
 #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

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

Final /etc/pam.d/sshd file below.

# cat /etc/pam.d/sshd
# $FreeBSD$
# PAM configuration for the "sshd" service

# auth
auth            sufficient      pam_opie.so             no_warn no_fake_prompts
auth            requisite       pam_opieaccess.so       no_warn allow_local
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       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

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

Small modification in the /etc/ssh/ssh_config and /etc/ssh/sshd_config files.

# cat << EOF >> /etc/ssh/ssh_config
GSSAPIAuthentication yes

# cat << EOF >> /etc/ssh/sshd_config
GSSAPIAuthentication yes
UsePAM yes

Finish Setup with Web Browser in FreeIPA/IDM Page

Visit the https://idm.vercorp.org/ipa/ui/#/e/hbacrule/details/freebsd page.

Next create the HBAC Rule named freebsd as showed below.




… and the Sudo Rule named freebsd name.




FreeBSD FreeIPA Login Test

After all these time consuming and pointless instructions we can now finally try to login to our FreeBSD client.

% ssh -l vermaden
(vermaden@ Password:
Last login: Mon Oct 24 21:06:36 2022 from
FreeBSD 13.1-RELEASE releng/13.1-n250148-fc952ac2212 GENERIC

Welcome to FreeBSD!

Release Notes, Errata: https://www.FreeBSD.org/releases/
Security Advisories:   https://www.FreeBSD.org/security/
FreeBSD Handbook:      https://www.FreeBSD.org/handbook/
FreeBSD FAQ:           https://www.FreeBSD.org/faq/
Questions List: https://lists.FreeBSD.org/mailman/listinfo/freebsd-questions/
FreeBSD Forums:        https://forums.FreeBSD.org/

Documents installed with the system are in the /usr/local/share/doc/freebsd/
directory, or can be installed later with:  pkg install en-freebsd-doc
For other languages, replace "en" with a language code like de or fr.

Show the version of FreeBSD installed:  freebsd-version ; uname -a
Please include that output and any error messages when posting questions.
Introduction to manual pages:  man man
FreeBSD directory layout:      man hier

To change this login announcement, see motd(5).
You can upload the dmesg of your system to help developers get an overview of commonly
used hardware and peripherals for FreeBSD. Use the curl package to upload it like this:
curl -v -d "nickname=$USER" -d "description=FreeBSD/$(uname -m) on \
$(kenv smbios.system.maker) $(kenv smbios.system.product)" -d "do=addd" \
--data-urlencode 'dmesg@/var/run/dmesg.boot' http://dmesgd.nycbug.org/index.cgi

vermaden@fbsd:~ $ :> ~/.hushlogin

vermaden@fbsd:~ $ id
uid=1408200003(vermaden) gid=1408200000(admins) groups=1408200000(admins)

vermaden@fbsd:~ $ pwd

vermaden@fbsd:~ $ grep vermaden /etc/passwd /etc/group
vermaden@fbsd:~ $

vermaden@fbsd:~ $ getent passwd vermaden
vermaden:*:1408200003:1408200000:vermaden vermaden:/home/vermaden:/bin/sh

vermaden@fbsd:~ $ sudo su -
Password for vermaden@VERCORP.ORG:

root@fbsd:~ # logout

vermaden@fbsd:~ $ sudo -i

root@fbsd:~ #

Strange … seems to work properly πŸ™‚

FreeBSD Jail as FreeIPA/IDM Client

As ‘full’ FreeBSD system is able to connect to the FreeIPA/IDM server we will not configure FreeBSD Jail to do the same.

The FreeIPA/IDM FreeBSD client fbsdjail.vercorp.orgwill get the IP.

Basic FreeBSD Jail Preparations

Lets setup the Jail for a start.

# mkdir -p /jail/fbsdjail /jail/BASE

# cd /jail/fbsdjail

# fetch -o /jail/BASE/13.1-RELEASE-base.txz https://download.freebsd.org/ftp/releases/amd64/13.1-RELEASE/base.txz

# tar --unlink -xvf ../BASE/13.1-RELEASE-base.txz

# cat << EOF > /etc/jail.conf
  exec.start = "/bin/sh /etc/rc";
  exec.stop = "/bin/sh /etc/rc.shutdown";
  exec.consolelog = "/var/log/jail_${name}_console.log";
  host.hostname = ${name};
  path = /jail/${name};

  fbsdjail {
    ip4.addr =;
    host.hostname = fbsdjail.vercorp.org;
    interface = wlan0;

# cat /etc/resolv.conf | tee /jail/fbsdjail/etc/resolv.conf

# echo fbsdjail.vercorp.org fbsdjail | tee -a /etc/hosts | tee -a /jail/fbsdjail/etc/hosts

# cat /etc/hosts /jail/fbsdjail/etc/hosts fbsdjail.vercorp.org fbsdjail fbsdjail.vercorp.org fbsdjail

# cat << EOF > /jail/fbsdjail/etc/rc.conf
# DAEMONS | yes


# sed -i '' s/quarterly/latest/g /jail/fbsdjail/etc/pkg/FreeBSD.conf

# grep latest /jail/fbsdjail/etc/pkg/FreeBSD.conf
  url: "pkg+http://pkg.FreeBSD.org/${ABI}/latest",

Now we can start our FreeBSD Jail.

# service jail onestart fbsdjail
Starting jails: fbsdjail.

# jls
   JID  IP Address      Hostname                      Path
     1       fbsdjail.vercorp.org          /jail/fbsdjail

# jls -v
   JID  Hostname                      Path
        Name                          State
        IP Address(es)
     1  fbsdjail.vercorp.org          /jail/fbsdjail
        fbsdjail                      ACTIVE

# jexec fbsdjail

root@fbsdjail:/ #

Our FreeBSD Jail works. Lets move to next steps.

Configure FreeBSD Jail to Connect to FreeIPA/IDM Server

I could not repaste all of the instructions above – the ones that we used for a ‘full’ FreeBSD system – but the same applies to a FreeBSD Jail. πŸ™‚

This means that earlier Basic FreeBSD Jail Preparations section covers all that is needed in case of ‘full’ FreeBSD versus FreeBSD Jail when it comes to the FreeIPA/IDM connection.

Linux FreeIPA/IDM Client

This article is not about Linux client – which is pretty straight-forward to connect to the FreeIPA/IDM server – but for the completness of the topic – here are the instructions I used to attach Alma Linux to the FreeIPA/IDM server.

Linux rhlike.vercorp.org system.

hostname: rhlike.vercorp.org

First – install the @idm:client and sssd packages.

client # yum -y install @idm:client sssd

FreeIPA/IDM Setup Part

Now – as earlier with FreeBSD – the FreeIPA/IDM part comes to play.

[root@idm ~]# kinit admin
Password for admin@VERCORP.ORG:

[root@idm ~]# klist
Ticket cache: KCM:0
Default principal: admin@VERCORP.ORG

Valid starting       Expires              Service principal
10/19/2022 13:33:52  10/20/2022 13:11:28  krbtgt/VERCORP.ORG@VERCORP.ORG

[root@idm ~]# ipa user-find
2 users matched
  User login: admin
  Last name: Administrator
  Home directory: /home/admin
  Login shell: /bin/bash
  Principal alias: admin@VERCORP.ORG, root@VERCORP.ORG
  UID: 1896600000
  GID: 1896600000
  Account disabled: False

  User login: vermaden
  First name: vermaden
  Last name: vermaden
  Home directory: /home/vermaden
  Login shell: /bin/sh
  Principal name: vermaden@VERCORP.ORG
  Principal alias: vermaden@VERCORP.ORG
  Email address: vermaden@vercorp.org
  UID: 1896600003
  GID: 1000
  Account disabled: False
Number of entries returned 2

[root@idm ~]# id vermaden
uid=1408200003(vermaden) gid=1408200000(admins) groups=1408200000(admins)

[root@idm ~]# ipa dnsrecord-add vercorp.org rhlike --a-rec
  Record name: rhlike
  A record:

We are done on the FreeIPA/IDM side.

Linux FreeIPA/IDM Client Setup

We will now continue our work on the Linux client.

client # echo "   idm.vercorp.org"    >> /etc/hosts

client # echo "   rhlike.vercorp.org" >> /etc/hosts

client # hostnamectl set-hostname rhlike.vercorp.org

client # cat /etc/hosts   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6   idm.vercorp.org   rhlike.vercorp.org

client # ipa-client-install --uninstall

client # ipa-client-install \
           --hostname=rhlike.vercorp.org \
           --mkhomedir \
           --server=idm.vercorp.org \
           --domain vercorp.org \
           --realm VERCORP.ORG

This program will set up IPA client.
Version 4.9.8

Autodiscovery of servers for failover cannot work with this configuration.
If you proceed with the installation, services will be configured to always access the discovered server for all operations and will not fail over to other servers in case of failure.
Proceed with fixed values and no DNS discovery? [no]: yes
Do you want to configure chrony with NTP server or pool address? [no]: no
Client hostname: rhlike.vercorp.org
DNS Domain: vercorp.org
IPA Server: idm.vercorp.org
BaseDN: dc=vercorp,dc=org

Continue to configure the system with these values? [no]: yes
Synchronizing time
No SRV records of NTP servers found and no NTP server or pool address was provided.
Using default chrony configuration.
Attempting to sync time with chronyc.
Time synchronization was successful.
User authorized to enroll computers: admin
Password for admin@VERCORP.ORG:
Successfully retrieved CA cert
    Subject:     CN=Certificate Authority,O=VERCORP.ORG
    Issuer:      CN=Certificate Authority,O=VERCORP.ORG
    Valid From:  2022-10-18 14:52:50
    Valid Until: 2042-10-18 14:52:50

Enrolled in IPA realm VERCORP.ORG
Created /etc/ipa/default.conf
Configured /etc/sssd/sssd.conf
Configured /etc/krb5.conf for IPA realm VERCORP.ORG
Systemwide CA database updated.
Hostname (rhlike.vercorp.org) does not have A/AAAA record.
Failed to update DNS records.
Missing A/AAAA record(s) for host rhlike.vercorp.org:
Missing reverse record(s) for address(es):
Adding SSH public key from /etc/ssh/ssh_host_ed25519_key.pub
Adding SSH public key from /etc/ssh/ssh_host_ecdsa_key.pub
Adding SSH public key from /etc/ssh/ssh_host_rsa_key.pub
Could not update DNS SSHFP records.
SSSD enabled
Configured /etc/openldap/ldap.conf
Configured /etc/ssh/ssh_config
Configured /etc/ssh/sshd_config
Configuring vercorp.org as NIS domain.
Client configuration complete.
The ipa-client-install command was successful

client # reboot

Now we will test how it goes with login against the FreeIPA/IDM server.

laptop % ssh -l vermaden
(vermaden@ Password:
(vermaden@ Password expired. Change your password now.
Current Password:
(vermaden@ New password:
(vermaden@ Retype new password:
Last failed login: Wed Oct 19 00:47:57 CEST 2022 from on ssh:notty
There was 1 failed login attempt since the last successful login.
/usr/bin/id: cannot find name for group ID 1000

[vermaden@rhlike ~]$ w
 00:48:16 up 29 min,  2 users,  load average: 0.22, 0.13, 0.16
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0         00:40   58.00s  0.03s  0.03s -bash
vermaden pts/1         00:48    0.00s  0.02s  0.01s w

[vermaden@rhlike ~]$ sudo su -

[root@rhlike ~]# getent passwd admin

[root@rhlike ~]# getent passwd vermaden
vermaden:*:1896600003:1000:vermaden vermaden:/home/vermaden:/bin/sh

Seems to work at least OK πŸ™‚

I do not have anything more to add to this guide.

If you have – then please let me know in comments πŸ™‚



Split Audio Files into Parts

I recently got in the need of splitting quite large amount of audio files into smaller equal parts. The first thought that came to my mind was – probably thousand or more people had similar problem in the past so its already solved – so I went directly to the web search engine.

The found solutions seem not that great or work partially only … or not work like I expected them to work. After looking at one of the possible solutions in a bash(1) script I started to modify it … but it turned out that writing my own solution was faster and easier … and simpler.

Today I will share with you my solution to automatically split audio files into small equal parts.

Existing Solutions

In my search for existing solutions I indeed found some tools that will allow me to achieve what I need. I will not try to talk them one after another.


The first one I found was the audio/mp3splt port (and package) available on FreeBSD. So I installed it with typical pkg(8) command as shown below.

# pkg install mp3splt

It installed properly … but returned Segmentation Fault instead of actually working. I even submitted a PR for that in the FreeBSD Bugzilla – 264866 – but no update till now.

Thus I removed that package and went to search for something that works.


Someone on some forum suggested using CD/DVD burning software – Brasero – because one of its features is audio splitting – so I installed the sysutils/brasero package now.

# pkg install brasero

It turns out that it really works. Some screenshots below.



… but that did not satisfied my because I wanted an automated/unattended solution instead of ‘clicking’ each file separately to split them. I also did not liked the fact that I needed to specify time in seconds.


Do not confuse with mentioned earlier mp3splt command. The mp3split is a unattended one created in a bash(1) script – https://diegosanchezp.github.io/blog/mp3split/ – available and described here. One of its downsides (for me) was that it needed additional external ‘list’ file with times and titles for the parts.

I did not wanted to write this each time so I generated a long enough list file that will cover any possible file no matter the length with the following loop.

% seq 0 10 10000 \
    | while read MIN
        seq 0 10 50 \
          | while read SEC
              echo ${MIN}:${SEC}
      done > list.txt

% head list.txt

I needed to split these audio files every 10 minutes. I redirected that output into the list.txt file. I then fetched and made executable the mentioned mp3split script.

% fetch https://raw.githubusercontent.com/diegosanchezp/mp3split/master/mp3split.sh

% chmod +x mp3split.sh

% ./mp3split.sh --help
zsh: ./mp3split.sh: bad interpreter: /bin/bash: no such file or directory

% head -1 ./mp3split.sh

So now we will have to remove linuxisms from the script. Lets hope its only the interpreter part.

% head -1 ./mp3split.sh
#! /usr/bin/env bash

% ./mp3split.sh --help
./mp3split.sh: illegal option -- -
Invalid option: -
  mp3split [OPTIONS] inputaudio tracklist
  -s: do a simulation without writing anything to disk
  -h: print this help
  -e extension: set output extension, if extension is equal to "" keep extension of input file
  The script will output all the splitted files in the
  current/working directory.

Better. Lets try to use it.

% ./mp3split.sh LARGE-AUDIO-FILE.mp3 list.txt

=== Begin to create mp3 split files ===
0:0.mp3: Protocol not found
Processed 0:0 to 0:10; 0:0.mp3
0:10.mp3: Protocol not found
Processed 0:10 to 0:20; 0:10.mp3
0:20.mp3: Protocol not found
Processed 0:20 to 0:30; 0:20.mp3
0:30.mp3: Protocol not found
Processed 0:30 to 0:40; 0:30.mp3
0:40.mp3: Protocol not found
Processed 0:40 to 0:50; 0:40.mp3
0:50.mp3: Protocol not found
Processed 0:50 to 10:0; 0:50.mp3
10:0.mp3: Protocol not found
Processed 10:0 to 10:10; 10:0.mp3
10:10.mp3: Protocol not found
Processed 10:10 to 10:20; 10:10.mp3
10:20.mp3: Protocol not found
Processed 10:20 to 10:30; 10:20.mp3
10:30.mp3: Protocol not found
Processed 10:30 to 10:40; 10:30.mp3
10:40.mp3: Protocol not found
Processed 10:40 to 10:50; 10:40.mp3
10:50.mp3: Protocol not found
Processed 10:50 to 20:0; 10:50.mp3
20:0.mp3: Protocol not found
Processed 20:0 to 20:10; 20:0.mp3
20:10.mp3: Protocol not found
Processed 20:10 to 20:20; 20:10.mp3
20:20.mp3: Protocol not found
Processed 20:20 to 20:30; 20:20.mp3

Some strange error message Protocol not found … after small investigation it turns out that two characters fix for the ffmpeg(1) command will do. The diff(1) is available below.

% diff -u mp3split.sh mp3split.sh.FIXED.sh
--- mp3split.sh 2022-06-25 22:34:25.499718000 +0200
+++ mp3split.sh.FIXED.sh        2022-06-25 22:37:45.580845000 +0200
@@ -25,7 +25,7 @@

   # Begin splitting files with ffmpeg
-  [ ! "$simulate" = true ] && ffmpeg -nostdin -y -loglevel error -i "$inputaudio" -ss "$start" -to "$end" -acodec copy "$outfile"
+  [ ! "$simulate" = true ] && ffmpeg -nostdin -y -loglevel error -i "$inputaudio" -ss "$start" -to "$end" -acodec copy ./"$outfile"

   echo "Processed $start to $end; $outfile"

Now lets try to use the fixed version.

% ./mp3split.sh.FIXED.sh LARGE-AUDIO-FILE.mp3 list.txt

=== Begin to create mp3 split files ===
Processed 0:0 to 0:10; 0:0.mp3
Processed 0:10 to 0:20; 0:10.mp3
Processed 0:20 to 0:30; 0:20.mp3
Processed 0:30 to 0:40; 0:30.mp3
Processed 0:40 to 0:50; 0:40.mp3
Processed 0:50 to 10:0; 0:50.mp3
Processed 10:0 to 10:10; 10:0.mp3
Processed 10:10 to 10:20; 10:10.mp3
Processed 10:20 to 10:30; 10:20.mp3
Processed 10:30 to 10:40; 10:30.mp3
Processed 10:40 to 10:50; 10:40.mp3
Processed 10:50 to 20:0; 10:50.mp3
Processed 20:0 to 20:10; 20:0.mp3
Processed 20:10 to 20:20; 20:10.mp3
Processed 20:20 to 20:30; 20:20.mp3
Processed 20:30 to 20:40; 20:30.mp3
Processed 20:40 to 20:50; 20:40.mp3
Processed 20:50 to 30:0; 20:50.mp3
Processed 30:0 to 30:10; 30:0.mp3
Processed 30:10 to 30:20; 30:10.mp3
Processed 30:20 to 30:30; 30:20.mp3
Processed 30:30 to 30:40; 30:30.mp3
Processed 30:40 to 30:50; 30:40.mp3
Processed 30:50 to 40:0; 30:50.mp3
Processed 40:0 to 40:10; 40:0.mp3
Processed 40:10 to 40:20; 40:10.mp3
Processed 40:20 to 40:30; 40:20.mp3
Processed 40:30 to 40:40; 40:30.mp3
Processed 40:40 to 40:50; 40:40.mp3
Processed 40:50 to 50:0; 40:50.mp3
Processed 50:0 to 50:10; 50:0.mp3
Processed 50:10 to 50:20; 50:10.mp3
Processed 50:20 to 50:30; 50:20.mp3
Processed 50:30 to 50:40; 50:30.mp3
Processed 50:40 to 50:50; 50:40.mp3
Invalid duration specification for to: 60:0
Processed 50:50 to 60:0; 50:50.mp3
Invalid duration specification for ss: 60:0
Processed 60:0 to 60:10; 60:0.mp3
Invalid duration specification for ss: 60:10
Processed 60:10 to 60:20; 60:10.mp3
Invalid duration specification for ss: 60:20
Processed 60:20 to 60:30; 60:20.mp3
Invalid duration specification for ss: 60:30
Processed 60:30 to 60:40; 60:30.mp3
Invalid duration specification for ss: 60:40
Processed 60:40 to 60:50; 60:40.mp3
Invalid duration specification for ss: 60:50
Processed 60:50 to 70:0; 60:50.mp3
Invalid duration specification for ss: 70:0
Processed 70:0 to 70:10; 70:0.mp3
Invalid duration specification for ss: 70:10
Processed 70:10 to 70:20; 70:10.mp3

Great … so after the file ended it will still try EVERY goddamn position from the list.txt file. It was also not able to reach the final ‘ending’ part without ‘visiting’ each time from the list.txt file. Enough is enough. I tried.

Custom Script Solution

After trying to modify the mp3split script even more I came to the conclusion that it will take less time to write my own solution from scratch … and this is exactly what I did. I wrote the audio-split.sh in POSIX /bin/sh interpreter for portability. After an hour later 50 lines of code did exactly what I needed – not counting the __usage() function for help information.


Here is the __usage() contents by the way.


The idea/needs were:

  • split large file automatically/unattended into equal parts
  • create new dir in which these parts are created
  • new dir must have same name as specified file (without extension)
  • each part will get a ' - xxx' suffix (like ' - 001' for first part) with original extension

… and they were met.

Here is the output of running audio-split.sh command.

% ffmpeg -i LARGE-AUDIO-FILE.mp3 2>&1 | grep Duration
  Duration: 00:44:55.99, start: 0.025057, bitrate: 171 kb/s

% audio-split.sh 10 LARGE-AUDIO-FILE.mp3

% du -sm LARGE-AUDIO-FILE.mp3
56      LARGE-AUDIO-FILE.mp3

% du -smc LARGE-AUDIO-FILE/*
56      total

The total size is the same (or similar in larger files). After listening to the parts I came to the conclusion that it works properly. The audio file is about 45 minutes long and the script created 4 10 minutes long files and 1 that is less then 5 minutes. Not sure if you also have such needs but if yes then you may now use another solution – audio-split.sh – for it πŸ™‚


Is FreeBSD a Real UNIX?

That question has been asked and answered many times … but the answer was not always obvious to everyone.

Also today is the FreeBSD day – FreeBSD was created exactly 29 years ago – also on 19th on June.

UNIX System

The first UNIX was the AT&T UNIX whose development started in 1969 at Bell Labs. Then AT&T licensed UNIX to outside parties in late 1970s which have life many UNIX variants like:

  • AIX from IBM
  • BSD (Berkeley Software Distribution) at University of California
  • SunOS/Solaris from Sun Microsystems
  • HP-UX from HP
  • Xenix from Microsoft

Of course AT&T also worked on UNIX and in the late 1980s jointly with Sun Microsystems they released the UNIX System V Release 4 (SVR4). Then in early 1990s the AT&T company sold its UNIX rights to Novell. Then Novell sold UNIX trademark to Open Group. This UNIX journey ends here as its Open Group ownership and they allow the use of the UNIX trademark for certified operating systems that comply with the Single UNIX Specification (SUS) (and pay $100 000 in the certification process).


The BSD UNIX had quite unusual version numbering with 1BSD, 2BSD, 3BSD for subsequent releases.

Below you will find most of them listed with some of their features.


  • run PDP-11
  • ex(1) editor


  • run PDP-11
  • vi(1) editor
  • C shell


  • run VAX-11
  • DEC VT100 terminal


  • run VAX-11
  • DARPA funding for CSRG
  • job control in C shell
  • delivermail(8) – antecedent of sendmail(8)
  • improved signals
  • Curses programming library


  • performance improvements
  • on par with VMS on many benchmarks


  • BBN preliminary TCP/IP implementation
  • Berkeley Fast File System
  • disk quotas
  • job control
  • run Motorola 68000
  • introduction of Daemon mascot



  • improved performance
  • more diverged TCP/IP implementation from BBN


  • move towards POSIX compliance
  • NFS implementation
  • status key (CTRL-T)
  • run HP 9000
  • named as “Greatest Software Ever Written”


  • most standard UNIX utilities reimplemented without AT&T code
  • nvi(1) – new vi(1)
  • only few AT&T files remained in kernel


  • all AT&T standard UNIX utilities reimplemented without AT&T code
  • nearly complete operating system that was freely distributable

386BSD (sometimes also called 386/BSD)

  • run Intel 80386
  • basically 4.3BSD-Net/2 ported to x86
  • base for NetBSD
  • base for FreeBSD on 1.0-2.2.8 releases

BSD/386 (later renamed BSD/OS) by BSDi

  • legal trouble with AT&T
  • AT&T USL versus BSDi lawsuit filed against 4.3BSD-Net/2
  • from 18,000 files only 3 had to be removed and 70 modified to show AT&T USL copyright.


  • released only to AT&T USL licensees


  • no longer requires AT&T USL license
  • contained other changes over 4.4BSD-Encumbered


  • last BSD UNIX release
  • after this release CSRG was dissolved
  • FreeBSD since 3.0 also used that code

Intel/x86 Port

The 386BSD UNIX (sometimes also called 386/BSD) was port of the 4.3BSD-Net/2 UNIX to the Intel/x86 architecture. Like recently FreeBSD added support for RISC-V or ARM64. When 386BSD UNIX existed – a group of people took that code and decided that they will develop it under FreeBSD name with their our own way of doing things like serving packages etc.

As you can see the FreeBSD UNIX is – with large simplification – nothing more then 4.3BSD-Net/2 ported to the x86 architecture. But can you call it UNIX? That depends.


Let me give you an example from other industry. Can you call Tesla a ‘car’? Yes. Why? Because no one has the copyright for the ‘car’ term. Now imagine this – some company owns the copyright to the ‘car’ term. Now you would not be allowed to call Tesla a ‘car’ without first asking that company for permission. Without such permission you could name Tesla only a car-like vehicle … or automobile – but not simply a ‘car’.

Lets get back to the computing world. Can you officially name FreeBSD a UNIX? No. That is because Open Group company owns copyright to the ‘UNIX’ term. You can call it only a UNIX-like system … but that does not mean its not UNIX. You just can not call it like that because of the lawyers.

NetBSD team also gave good example with their ‘duck’ explanation – https://mollari.netbsd.org/about/call-it-a-duck.html – available here.

Apple paid $100 000 to call their Mac OS X (now macOS) system a UNIX officially.

Linux UNIX

Can you call Linux a UNIX system? Depends which one πŸ™‚ Currently RHEL (Red Hat Enterprise Linux) is not a certified UNIX – Red Hat did not made the $100 000 worth official certification process with Open Group – you can not name RHEL a UNIX system … but RHEL fork can be called officially UNIX. The Inspur-UX is official UNIX because they did that $100 000 certification with Open Group. Probably because they thought that calling their RHEL fork ‘UNIX’ will make their business better.

Does it makes sense? No. But that is just business. Do not seek logic here. Money only.


Depends if you want the truth or just what the law officially allows πŸ™‚ If you want the truth then yes – FreeBSD is a UNIX system – same as NetBSD or OpenBSD for example. But if you want to obey the law then you can not name these systems UNIX.


Automated Kickstart Install of RHEL/Clones

There are two approaches to making your life more automated about installing multiple instances of operating systems. You can either maintain up-to-date templates for them or you can have automated/scripted installations. In this article I will share how to generate ISO image and Kickstart configuration to install Red Hat Enterprise Linux (and its clones such as Alma/Rocky/CentOS/Scientific/…) in easy and fast way. For the process I will use 8.5 version of RHEL.

Here is the Table of Contents for this article.

  • Logo
  • Possibilities
  • Environment
    • FreeBSD – www
    • RHEL Client – kickme
  • Validate
  • Generation
    • kickstart.config
    • kickstart.skel
    • kickstart.sh
    • ISO
  • Result
  • Alternatives
  • Summary


Shortly after IBM acquisition Red Hat started to use kinda boring ‘just a red hat’ logo – but its earlier logo – shown below – was more interesting.


If you stare long enough you will see two dinosaurs. The Tyrannosaurus (red) punching a Triceratops (white) in the head. Once you see it you will not be able to unsee it πŸ™‚


There are many ways to do that automated Kickstart installation. You can use NFS/HTTP/FTP/HTTPS or your own generated DVD media … or use ‘stock’ DVD and Kickstart config available somewhere on the network.

I will use the following method that I find currently is best suited for my needs:

  • FreeBSD host with NGINX serving RHEL 8.5 DVD content (rhel-8.5-x86_64-dvd.iso) over HTTP.
  • Generate small (less then 1 MB in size) ISO with Kickstart config on it.
  • Boot from small rhel-8.5-x86_64-boot.iso ISO and also with generated Kickstart ISO.


I will use VirtualBox for this demo with NAT Network configuration for the virtual machines network adapters. The nat0 VirtualBox network is defined as and I use Port Forwarding to access these machines from the FreeBSD host system.


  • - www – FreeBSD system with NGINX to serve RHEL 8.5 DVD contents
  • - kickme – RHEL machine that would be installed with automated Kickstart install

FreeBSD – www

Below you will find the FreeBSD machine configuration as seen on VirtualBox.


Its default FreeBSD ZFS install on single disk. Nothing fancy here to be honest. Below you will find its configuration from /etc/rc.conf file. I also installed the nginx package but the only thing I did with NGINX was to enable it to start automatically. I used the default stock config that points at /usr/local/www/nginx place. I later copied the RHEL 8.5 DVD contents to the /usr/local/www/nginx/rhel-8.5 directory. It takes about 10 GB.

www # cat /etc/rc.conf
ifconfig_em0="inet netmask"

Here is the unmodified NGINX config but with comments non displayed.

www # grep -v '#' /usr/local/etc/nginx/nginx.conf | grep '^[^#]'
worker_processes  1;
events {
    worker_connections  1024;
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    server {
        listen       80;
        server_name  localhost;
        location / {
            root   /usr/local/www/nginx;
            index  index.html index.htm;
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/local/www/nginx-dist;

Here are the contents of the /usr/local/www/nginx/rhel-8.5 directory after copying here contents of RHEL 8.5 DVD.

www:~ # ls -l /usr/local/www/nginx/rhel-8.5/
total 71
-r--r--r--  1 root  wheel     60 Apr  6 21:34 .discinfo
-r--r--r--  1 root  wheel   1560 Apr  6 21:34 .treeinfo
dr-xr-xr-x  4 root  wheel      4 Apr  6 21:50 AppStream
dr-xr-xr-x  4 root  wheel      4 Apr  6 21:53 BaseOS
dr-xr-xr-x  3 root  wheel      3 Apr  6 21:53 EFI
-r--r--r--  1 root  wheel   8154 Apr  6 21:53 EULA
-r--r--r--  1 root  wheel  18092 Apr  6 21:53 GPL
-r--r--r--  1 root  wheel   1669 Apr  6 21:53 RPM-GPG-KEY-redhat-beta
-r--r--r--  1 root  wheel   5135 Apr  6 21:53 RPM-GPG-KEY-redhat-release
-r--r--r--  1 root  wheel   1796 Apr  6 21:53 TRANS.TBL
-r--r--r--  1 root  wheel   1455 Apr  6 21:53 extra_files.json
dr-xr-xr-x  3 root  wheel      6 Apr  6 21:54 images
dr-xr-xr-x  2 root  wheel     16 Apr  6 21:54 isolinux
-r--r--r--  1 root  wheel    103 Apr  6 21:54 media.repo

RHEL Client – kickme

Below you will find the RHEL machine that will be used for the automated Kickstart installation – also as seen on VirtualBox.


To make that example more interesting (and more corporate) I added second NIC for the backup network – so we will also have to generate additional route for it in the Kickstart config.

The kickme RHEL machine needs to have two (2) CD-ROM drives. In the PRIMARY (the one to boot from) we will load the rhel-8.5-x86_64-boot.iso ISO file. In the SECONDARY one we will load our generated kickme.oemdrv.iso ISO file containing Kickstart config file.


There also exists pykickstart package which offers ksvalidator tool. Theoretically it allows you to make sure that your Kickstart config has proper syntax and that it would work – but only in theory. Here is what it RHEL documentation states about its accuracy.


It means that you will not know if your Kickstart config will work until you really try it – thus I do not cared that much about this tool as is not available on FreeBSD.


Now to the most important part – Kickstart generation and ISO generation. Probably the easiest way to create new Kickstart config is to install ‘by hand’ new RHEL system under virtual machine and then take the generated by Anaconda /root/anaconda-ks.cfg file as a starting point. This is what I also did.

When you would like to install next host you will have to edit the hostname and IP addresses for next host in that Kickstart file – which seems not very convenient to say the least. In order to make that less PITA I created a kickstart.sh script that will read values from kickstart.config file and then put them into the kickstart.skel file that would be base for our future installations. Then the kickstart.sh will copy the generated Kickstart file and used Kickstart config with that hostname as a backup or for future reference – or for example for documentation purposes.


Here is how such kickstart.config file looks like.

# cat kickstart.config


The kickstart.skel file is little longer – this is our barebone for the Kickstart configs.

# cat kickstart.skel

# USE sda DISK
ignoredisk --only-use=sda

clearpart --all --initlabel


url --url=http://REPO_SERVER_IP/rhel-8.5/BaseOS --noverifyssl

keyboard --vckeymap=us --xlayouts='us','pl'

lang en_US.UTF-8

network --bootproto=static --device=INTERFACE1 --ip=IP_ADDRESS1 --netmask=NETMASK1 --gateway=GATEWAY --nameserver=NAMESERVER1,NAMESERVER2 --noipv6 --activate
network --bootproto=static --device=INTERFACE2 --ip=IP_ADDRESS2 --netmask=NETMASK2 --noipv6 --activate --onboot=on
network --hostname=SYSTEM_NAME

repo --name="AppStream" --baseurl=http://REPO_SERVER_IP/rhel-8.5/AppStream

rootpw --plaintext asd

firstboot --disable

selinux --disabled
firewall --disabled

# OMIT X11

reboot --eject

timezone Europe/Warsaw --isUtc --nontp

part   /boot/efi --fstype="efi"   --size=600  --ondisk=sda --label=EFI  --fsoptions="umask=0077,shortname=winnt"
part   /boot     --fstype="xfs"   --size=1024 --ondisk=sda --label=BOOT --fsoptions="rw,noatime,nodiratime"
part   pv.475    --fstype="lvmpv" --size=1    --ondisk=sda --grow

volgroup rootvg --pesize=4096 pv.475
logvol /         --fstype="xfs"   --size=1024 --name=root --label="ROOT" --vgname=rootvg --fsoptions="rw,noatime,nodiratime"
logvol /usr      --fstype="xfs"   --size=5120 --name=usr  --label="USR"  --vgname=rootvg --fsoptions="rw,noatime,nodiratime"
logvol /var      --fstype="xfs"   --size=3072 --name=var  --label="VAR"  --vgname=rootvg --fsoptions="rw,noatime,nodiratime"
logvol /tmp      --fstype="xfs"   --size=1024 --name=tmp  --label="TMP"  --vgname=rootvg --fsoptions="rw,noatime,nodiratime"
logvol /opt      --fstype="xfs"   --size=1024 --name=opt  --label="OPT"  --vgname=rootvg --fsoptions="rw,noatime,nodiratime"
logvol /home     --fstype="xfs"   --size=1024 --name=home --label="HOME" --vgname=rootvg --fsoptions="rw,noatime,nodiratime"
logvol swap      --fstype="swap"  --size=4096 --name=swap --label="SWAP" --vgname=rootvg


%addon com_redhat_kdump --enable --reserve-mb='auto'

%post --log=/root/ks-post.log --interpreter=/usr/bin/bash

  # POST: route
  echo ROUTE_NET via ROUTE_VIA > /etc/sysconfig/network-scripts/route-INTERFACE2

  # POST: chrony CONFIG
  cat << TIME > /etc/chrony.conf
server NTP1 iburst
server NTP2 iburst
driftfile /var/lib/chrony/drift
makestep 1.0 3
logdir /var/log/chrony
keyfile /etc/chrony.keys
leapsectz right/UTC

  # POST: chrony SERVICE
  systemctl enable chronyd


pwpolicy root --minlen=6 --minquality=1 --notstrict --nochanges --notempty
pwpolicy user --minlen=6 --minquality=1 --notstrict --nochanges --emptyok
pwpolicy luks --minlen=6 --minquality=1 --notstrict --nochanges --notempty


… and last but not least – the kickstart.sh script. It does not take any arguments – it just loads the kickstart.config file variables and then replaces all config options in kickstart.skel with sed(1) to generate new Kickstart file as files/${SYSTEM_NAME}.cfg file. It also copies that config into files/${SYSTEM_NAME}.config for convenience.

# cat kickstart.sh
#! /bin/sh

if [ ! -f kickstart.config ]
  echo "ERROR: file 'kickstart.config' not available"
  exit 1

if [ ! -f kickstart.skel ]
  echo "ERROR: file 'kickstart.skel' not available"
  exit 1

. "$( pwd )/kickstart.config"

mkdir -p files ksfloppy iso

cp kickstart.config files/${SYSTEM_NAME}.config

if [ ${?} -eq 0 ]
  echo "INFO: kickstart config copied to 'files/${SYSTEM_NAME}.config' location"
  echo "ERROR: could not copy config to 'files/${SYSTEM_NAME}.config' location"
  exit 1

sed                                           \
  -e s@SYSTEM_NAME@${SYSTEM_NAME}@g           \
  -e s@RHEL_MAJOR@${RHEL_MAJOR}@g             \
  -e s@RHEL_VERSION@${RHEL_VERSION}@g         \
  -e s@RHEL_ARCH@${RHEL_ARCH}@g               \
  -e s@INTERFACE1@${INTERFACE1}@g             \
  -e s@IP_ADDRESS1@${IP_ADDRESS1}@g           \
  -e s@NETMASK1@${NETMASK1}@g                 \
  -e s@INTERFACE2@${INTERFACE2}@g             \
  -e s@IP_ADDRESS2@${IP_ADDRESS2}@g           \
  -e s@NETMASK2@${NETMASK2}@g                 \
  -e s@GATEWAY@${GATEWAY}@g                   \
  -e s@NAMESERVER1@${NAMESERVER1}@g           \
  -e s@NAMESERVER2@${NAMESERVER2}@g           \
  -e s@NTP1@${NTP1}@g                         \
  -e s@NTP2@${NTP2}@g                         \
  -e s@ROUTE_NET@${ROUTE_NET}@g               \
  -e s@ROUTE_VIA@${ROUTE_VIA}@g               \
  kickstart.skel > files/${SYSTEM_NAME}.cfg

if [ ${?} -eq 0 ]
  echo "INFO: kickstart file 'files/${SYSTEM_NAME}.cfg' generated"
  echo "ERROR: failed to generate 'files/${SYSTEM_NAME}.cfg' kickstart file"
  exit 1

echo "INFO: mkisofs(8) output BEGIN"
echo "-----------------------------"

mkisofs -J -R -l -graft-points -V "OEMDRV" \
        -input-charset utf-8 \
        -o iso/${SYSTEM_NAME}.oemdrv.iso \
        ks.cfg=files/${SYSTEM_NAME}.cfg ksfloppy

echo "-----------------------------"
echo "INFO: mkisofs(8) output ENDED"

if [ ${?} -eq 0 ]
  echo "INFO: ISO image 'iso/${SYSTEM_NAME}.oemdrv.iso' generated"
  echo "ERROR: failed to generate 'iso/${SYSTEM_NAME}.oemdrv.iso' ISO image"
  exit 1


It finishes its work in less then a second. Here is its output.


… and the generated ISO file.

# ls -lh iso/kickme.oemdrv.iso
-rw-r--r--  1 root  wheel   366K Apr 10 21:57 iso/kickme.oemdrv.iso


Now – when you boot the kickme VirtualBox virtual machine with CD-ROM devices loaded you will end up with RHEL system installed according to your generated Kickstart config. Here are some files from the kickme RHEL installed system.

Filesystems with LABELs such as BOOT or VAR defined.

# lsblk -i -f
NAME            FSTYPE      LABEL UUID                                   MOUNTPOINT
|-sda1          xfs         BOOT  b5c66ea5-b38a-4072-b1a8-0d5882ace179   /boot
|-sda2          vfat        EFI   BB7A-4BFD                              /boot/efi
`-sda3          LVM2_member       e9BwIq-4I2W-zX6y-As42-f9N2-WTTR-WfHKdC
  |-rootvg-root xfs         ROOT  dbf8dd30-51cc-408a-9d05-b1ae67c0637c   /
  |-rootvg-swap swap        SWAP  c8a016b5-f43d-4510-9703-e9c68f02ae64   [SWAP]
  |-rootvg-usr  xfs         USR   c6694796-a5bd-4833-9a6b-a740e8bf83bf   /usr
  |-rootvg-home xfs         HOME  5264afe6-5d9c-4dc3-9d8d-e19078864aea   /home
  |-rootvg-opt  xfs         OPT   039e9575-3af8-4a8b-95c0-54fb8a515f70   /opt
  |-rootvg-tmp  xfs         TMP   11709a48-a64f-4b93-86a3-e943ff9ecf01   /tmp
  `-rootvg-var  xfs         VAR   ed20343c-b915-4234-b13e-0c6c94e03edc   /var

The /etc/fstab file with rw,noatime,nodiratime mount options.

# grep '^[^#] /etc/fstab
/dev/mapper/rootvg-root /                       xfs     rw,noatime,nodiratime 0 0
UUID=b5c66ea5-b38a-4072-b1a8-0d5882ace179 /boot xfs     rw,noatime,nodiratime 0 0
UUID=BB7A-4BFD          /boot/efi               vfat    defaults,uid=0,gid=0,umask=077,shortname=winnt 0 2
/dev/mapper/rootvg-home /home                   xfs     rw,noatime,nodiratime 0 0
/dev/mapper/rootvg-opt  /opt                    xfs     rw,noatime,nodiratime 0 0
/dev/mapper/rootvg-tmp  /tmp                    xfs     rw,noatime,nodiratime 0 0
/dev/mapper/rootvg-usr  /usr                    xfs     rw,noatime,nodiratime 0 0
/dev/mapper/rootvg-var  /var                    xfs     rw,noatime,nodiratime 0 0
/dev/mapper/rootvg-swap none                    swap    defaults        0 0

Networking on two network interfaces and additional route generated.

# cat /etc/sysconfig/network-scripts/ifcfg-enp0s3
# Generated by parse-kickstart
NAME="System enp0s3"

# cat /etc/sysconfig/network-scripts/ifcfg-enp0s8
# Generated by parse-kickstart
NAME="System enp0s8"

# cat /etc/sysconfig/network-scripts/route-enp0s8 via

# cat /etc/resolv.conf
# Generated by NetworkManager


Its also possible to use the livemedia-creator from the lorax package … but I would omit it. To be honest I tried it – and it did not worked at all. I started the following process … and it run for more then a DAY and produced NOTHING.

# livemedia-creator \
    --make-iso \
    --ram 4096 \
    --vcpus 4 \
    --iso=/mnt/rhel-8.5-x86_64-boot.iso \

The log file for the operation was also EMPTY. At least that was the run when using the virt-install option with creating everything under virtual machine. This also intrigue me a lot. Why use virtual machines just to create installation media? Its just a bunch of files. There are better options available such as chroot(8) for example … or even so glorified containers such as Docker or Podman. Why use fully fledged virtual machine just to create ISO image? This is a big mystery for me.

Seems that livemedia-creator also has --no-virt option available … but as documentation states – it can “render the entire system unusable” – not very production ready solution for my taste. Below is a screenshot from the official RHEL documentation.


Pity that livemedia-creator did not worked for me – but I already have a working process for that.

Some people also suggested these as valuable alternatives:

Maybe some day I will find time to check them out.


I am not the best at summaries so I will just write here that the article has ended successfully πŸ™‚



ZFS Compatibility

The best free filesystem on Earth – ZFS – also often named OpenZFS recently – has also become very portable in recent years of its development. The OpenZFS Distributions page lists 6 (six) operating systems already.

They are:

  • FreeBSD
  • Illumos
  • Linux
  • MacOS
  • NetBSD
  • Windows

… but if you would like to create a ZFS pool compatible with all of them … which options and ZFS features should you choose? There is OpenZFS Feature Flags page dedicated exactly to that topic.


These are the ones that have yes value in all operating systems.

  • async_destroy
  • bookmarks
  • empty_bpobj
  • enabled_txg
  • filesystem_limits
  • lz4_compress
  • hole_birth
  • multi_vdev_crash_dump
  • spacemap_histogram

I would also include these as only older NetBSD 4.0.5 version does not support them – but they are supported in newer NetBSD 5.3 version.

  • embedded_data
  • large_blocks
  • sha512
  • skein

There is also a dedicated zpool-features(7) man page for that information on the OpenZFS page and also zpool-features(7) man page on the FreeBSD page.

On the FreeBSD system the /usr/share/zfs/compatibility.d directory has files with supported ZFS Feature Flags for many major operating systems and ZFS versions.

% ls /usr/share/zfs/compatibility.d

Unfortunately it misses NetBSD and Illumos systems for example … but having information from the OpenZFS Feature Flags page we can find Feature Flags set that will be supported everywhere.

Here are the stats for supported ZFS Feature Flags. The higher the number the more operating systems and ZFS version it covers.

% grep -h '^[^#]' /usr/share/zfs/compatibility.d/* \
    | sort -n \
    | uniq -c \
    | sort -n
   2 draid
   5 bookmark_written
   5 device_rebuild
   5 livelist
   5 log_spacemap
   5 redacted_datasets
   5 redaction_bookmarks
   5 zstd_compress
   9 allocation_classes
   9 bookmark_v2
   9 project_quota
   9 resilver_defer
  10 edonr
  10 encryption
  11 large_dnode
  11 userobj_accounting
  18 spacemap_v2
  20 device_removal
  20 obsolete_counts
  20 zpool_checkpoint
  31 sha512
  31 skein
  32 multi_vdev_crash_dump
  36 filesystem_limits
  36 large_blocks
  37 embedded_data
  37 enabled_txg
  37 extensible_dataset
  37 hole_birth
  37 spacemap_histogram
  38 async_destroy
  38 empty_bpobj
  38 lz4_compress

As the GNU GRUB is very outdated when it comes to ZFS support it should be pretty bulletproof to use it as a starting point of limited ZFS Feature Flags support.

% cat /usr/share/zfs/compatibility.d/grub2
# Features which are supported by GRUB2

To make sure we are compatible we will now cross-link the GNU GRUB data.

First we will ‘generate’ the grep(1) command arguments that we will use in the next command.

% grep '^[^#]' /usr/share/zfs/compatibility.d/grub2 \
  | while read I
      echo "-e ' ${I}' \\"
-e ' async_destroy' \
-e ' bookmarks' \
-e ' embedded_data' \
-e ' empty_bpobj' \
-e ' enabled_txg' \
-e ' extensible_dataset' \
-e ' filesystem_limits' \
-e ' hole_birth' \
-e ' large_blocks' \
-e ' lz4_compress' \
-e ' spacemap_histogram' \

Lets now use these arguments to filter the ZFS features.

% grep -h '^[^#]' /usr/share/zfs/compatibility.d/grub2/* \
    | sort -n \
    | uniq -c \
    | sort -n \
    | grep -e ' async_destroy' \
           -e ' bookmarks' \
           -e ' embedded_data' \
           -e ' empty_bpobj' \
           -e ' enabled_txg' \
           -e ' extensible_dataset' \
           -e ' filesystem_limits' \
           -e ' hole_birth' \
           -e ' large_blocks' \
           -e ' lz4_compress' \
           -e ' spacemap_histogram' \
    | wc -l

% grep -h '^[^#]' /usr/share/zfs/compatibility.d/grub2 | wc -l

So if seems that GRUB list of ZFS Feature Flags seems pretty compatible.

Lets now cross-reference that GRUB data with the data from the OpenZFS Feature Flags page.

I will create new /usr/share/zfs/compatibility.d/OZFF file that has these ZFS Feature Flags as content.

% cat /usr/share/zfs/compatibility.d/OZFF

% wc -l /usr/share/zfs/compatibility.d/OZFF

So there are 11 GRUB ZFS Feature Flags and 13 OpenZFS ‘Compatible’ Feature Flags.

Lets see how it they compare.

% cat /usr/share/zfs/compatibility.d/OZFF \
    | grep -e async_destroy \
           -e bookmarks \
           -e embedded_data \
           -e empty_bpobj \
           -e enabled_txg \
           -e extensible_dataset \
           -e filesystem_limits \
           -e hole_birth \
           -e large_blocks \
           -e lz4_compress \
           -e spacemap_histogram \
    | wc -l

I expected 11 here instead of 10 … we will not have to compare GRUB results to the OpenZFS Feature Flags section.

% grep -h '^[^#]' /usr/share/zfs/compatibility.d/{grub2,OZFF} \
    | sort -n \
    | uniq -c \
    | sort -n
   1 extensible_dataset
   1 multi_vdev_crash_dump
   1 sha512
   1 skein
   2 async_destroy
   2 embedded_data
   2 empty_bpobj
   2 enabled_txg
   2 filesystem_limits
   2 hole_birth
   2 large_blocks
   2 lz4_compress
   2 spacemap_histogram

Seems that we finally got our 10 most compatible OpenZFS Feature Flags set.

Its this set:

  • async_destroy
  • bookmarks
  • embedded_data
  • empty_bpobj
  • enabled_txg
  • filesystem_limits
  • hole_birth
  • large_blocks
  • lz4_compress
  • spacemap_histogram

To make it more comfortable to use we will put them it into the separate /usr/share/zfs/compatibility.d/COMPATIBLE file.

# cat /usr/share/zfs/compatibility.d/COMPATIBLE

Lets now try to make that best effort most-compatible ZFS pool.

I will use one of my scripts – mdconfig.sh – to easy manipulate md(4) memory disks on FreeBSD.

# truncate -s 1g FILE
# mdconfig.sh -c FILE
IN: created vnode at /dev/md0
# zpool create -o compatibility=COMPATIBLE compatible /dev/md0
# zpool list
compatible   960M   116K   960M        -         -     0%     0%  1.00x    ONLINE  -
zroot        118G  48.6G  69.4G        -         -    36%    41%  1.00x    ONLINE  -

Now lets see what is zpool upgrade command showing us.

# zpool upgrade
This system supports ZFS pool feature flags.

All pools are formatted using feature flags.

Some supported features are not enabled on the following pools. Once a
feature is enabled the pool may become incompatible with software
that does not support the feature. See zpool-features(7) for details.

Note that the pool 'compatibility' feature can be used to inhibit
feature upgrades.


There are LOTS of ZFS Feature Flags to be activated but if we want to have our ZFS pool keep compatible – we will have to stay away from it πŸ™‚


You may get impression that you miss a lot … but you do not miss that much. Here are the ZFS Feature Flags you can fully utilize.

# zpool get all compatible | grep -v disabled
NAME        PROPERTY                       VALUE                          SOURCE
compatible  size                           960M                           -
compatible  capacity                       0%                             -
compatible  altroot                        -                              default
compatible  health                         ONLINE                         -
compatible  guid                           5395735446052695775            -
compatible  version                        -                              default
compatible  bootfs                         -                              default
compatible  delegation                     on                             default
compatible  autoreplace                    off                            default
compatible  cachefile                      -                              default
compatible  failmode                       wait                           default
compatible  listsnapshots                  off                            default
compatible  autoexpand                     off                            default
compatible  dedupratio                     1.00x                          -
compatible  free                           960M                           -
compatible  allocated                      116K                           -
compatible  readonly                       off                            -
compatible  ashift                         0                              default
compatible  comment                        -                              default
compatible  expandsize                     -                              -
compatible  freeing                        0                              -
compatible  fragmentation                  0%                             -
compatible  leaked                         0                              -
compatible  multihost                      off                            default
compatible  checkpoint                     -                              -
compatible  load_guid                      17463015630652190527           -
compatible  autotrim                       off                            default
compatible  compatibility                  COMPATIBLE                     local
compatible  feature@async_destroy          enabled                        local
compatible  feature@empty_bpobj            enabled                        local
compatible  feature@lz4_compress           active                         local
compatible  feature@spacemap_histogram     active                         local
compatible  feature@enabled_txg            active                         local
compatible  feature@hole_birth             active                         local
compatible  feature@extensible_dataset     enabled                        local
compatible  feature@embedded_data          active                         local
compatible  feature@bookmarks              enabled                        local
compatible  feature@filesystem_limits      enabled                        local
compatible  feature@large_blocks           enabled                        local

You get the very decent LZ4 compression and also ZFS Bookmarks feature which are very useful feature for sync|recv mechanism.

Keep in mind that the -o compatibility= switch for zpool(8) is available on OpenZFS 2.1 or newer. The 2.1 version is already available on the FreeBSD 13.1-BETA* releases and will be part of the FreeBSD 13.1-RELEASE systems. To make use of it on older FreeBSD releases you will have to use openzfs and openzfs-kmod packages and also use the following settings in the /boot/loader.conf file.

From that one:


Into that one:


With these openzfs and openzfs-kmod packages and above settings in the /boot/loader.conf file you can use this OpenZFS 2.1 on FreeBSD 12.2 – on FreeBSD 12.3 – and on FreeBSD 13.0 … and of course on upcoming FreeBSD 13.1 release.

Not sure if I should have add anything more here. Feel free to remind me in the commends πŸ™‚


Sensors Information on FreeBSD

I remember vigorous discussions that were taken several years ago about monitoring hardware sensors on FreeBSD system. Back then I never really needed them. Not that I need them now but I recently got to know the sensors(1) command on Linux. Without any arguments it just prints the available sensors data on the screen and exits. Like example output from ThinkPad T14 laptop.

RHEL % sensors
Adapter: ISA adapter
Package id 0:  +51.0Β°C  (high = +100.0Β°C, crit = +100.0Β°C)
Core 0:        +49.0Β°C  (high = +100.0Β°C, crit = +100.0Β°C)
Core 1:        +50.0Β°C  (high = +100.0Β°C, crit = +100.0Β°C)
Core 2:        +51.0Β°C  (high = +100.0Β°C, crit = +100.0Β°C)
Core 3:        +49.0Β°C  (high = +100.0Β°C, crit = +100.0Β°C)

Adapter: Virtual device
temp1:        +54.0Β°C  (crit = +128.0Β°C)

Adapter: Virtual device
temp1:        +54.0Β°C

Adapter: ISA adapter
fan1:        2873 RPM

Nothing spectacular to be honest – but also a nice single place to check all temperatures instead of filtering endless sysctl(8) output.

The FreeBSD framework was known as bsdhwmon name and last available version is from somewhere in 2015. Its even available in the FreeBSD packages and I tried to install it and use.

FreeBSD # pkg search hwmon
bsdhwmon-20151206              Hardware sensor monitoring utility for FreeBSD

FreeBSD # pkg install -y bsdhwmon
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
All repositories are up to date.
The following 1 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:
        bsdhwmon: 20151206

Number of packages to be installed: 1

12 KiB to be downloaded.

[1/1] Fetching bsdhwmon-20151206.pkg: 100%   12 KiB  12.0kB/s    00:01
Checking integrity... done (0 conflicting)
[1/1] Installing bsdhwmon-20151206...
[1/1] Extracting bsdhwmon-20151206: 100%

FreeBSD # pkg info -l bsdhwmon-20151206

FreeBSD # /usr/local/sbin/bsdhwmon
Your motherboard does not appear to be supported.  Please visit
https://github.com/koitsu/bsdhwmon to see if support for your motherboard
and/or system is under development.

I do not want to be harsh but not very useful. I expected at least something … anything. Seems that the project is dead for 7 years not without a reason.

I checked what is already available in several places of the FreeBSD system that may be used as data source to create something similar to the sensors(1) command. I started with sysctl(8) output and later went to smartctl(8) command from the smartmontools package. This data was more then enough to start with something.

Meet the first version of small sensors.sh script that gathers all these data sources and prints them all on screen.


Below you will find output from my elderly ThinkPad W520 laptop.

FreeBSD # sensors.sh

                       hw.acpi.acline: 1
                 hw.acpi.battery.time: 274
                 hw.acpi.battery.life: 99
                hw.acpi.cpu.cx_lowest: C1
                   dev.acpi_ibm.0.fan: 0
             dev.acpi_ibm.0.fan_level: 0
             dev.acpi_ibm.0.fan_speed: 2454

      hw.acpi.thermal.tz0.temperature: 48.1C
                dev.cpu.7.temperature: 47.0C
                dev.cpu.6.temperature: 47.0C
                dev.cpu.5.temperature: 46.0C
                dev.cpu.4.temperature: 47.0C
                dev.cpu.3.temperature: 46.0C
                dev.cpu.2.temperature: 47.0C
                dev.cpu.1.temperature: 48.0C
                dev.cpu.0.temperature: 48.0C

   smart.ada0.airflow_temperature_cel: 36.0C

Another example output from my home NAS with two 5TB SATA disks – Silent Fanless FreeBSD Server – described here more.

FreeBSD # sensors.sh

                hw.acpi.cpu.cx_lowest: C1

      hw.acpi.thermal.tz0.temperature: 26.9C
                dev.cpu.3.temperature: 50.0C
                dev.cpu.2.temperature: 50.0C
                dev.cpu.1.temperature: 48.0C
                dev.cpu.0.temperature: 49.0C

   smart.ada1.airflow_temperature_cel: 33.0C
       smart.ada1.temperature_celsius: 33.0C
   smart.ada0.airflow_temperature_cel: 33.0C
       smart.ada0.temperature_celsius: 33.0C

You can grab it from my scripts site – sensors.sh – I did not created separate GitHub page for it.

It comes with some simple builtin help message that I think explains everything.


Please check how it works on your system and let me know if it would be useful to add something more to it. As I not so long ago changed employer to the one that uses SLES and RHEL systems I can not test it on physical FreeBSD servers. Not that my earlier employer would be a huge help here as only several physical machines were FreeBSD based – but at least they were the biggest ones – FreeBSD Enterprise 1 PB Storage – you can read about these here. I also made a PBUG presentation later partially about that machine. You can find it – FreeBSD Enterprise Storage at PBUG – here.

UPDATE 1 – Screenshot After Updates

Many people suggested and submitted some interesting updates to the – sensors.sh – script – thank you for that. The script remains in the same place but here is how it looks and behave now.



UNIX Mouse Shootout

While most hardcore UNIX users prefer keyboard shortcuts over anything else – and I often align with that view – I really do appreciate good mouse on my UNIX system. In the end its close to impossible to edit images in GIMP without mouse for example. This ‘shootout’ will definitely be subjective as it will be limited only to mice that I own(ed). I will not bore you with all the technical specifications of these devices – you can check them on your own.

Besides – UNIX has two copy/paste buffers instead of just one like in most systems. There is PRIMARY and SECONDARY buffers in X11 for mouse. One is used when you use Copy/Paste options from menus and/or keyboard shortcuts like [CTRL]+[C] and [CTRL]+[V] ones. The other one is used when you just SELECT the text. After releasing the left mouse button (and finishing the selection) you have that text stored in your SECONDARY buffer. You may now paste that with pressing the third/middle mouse button. But the PRIMARY buffer did not changed during that operation so you can also paste the other text you had in your PRIMARY buffer from the earlier [CTRL]+[C] operation. This makes mouse on UNIX more useful – definitely bigger then in other systems.

While Bluetooth is widely used on most mobile phones/tables and even cars now I do not find it desired as the only protocol for the mouse. I do not have anything against it when it comes as an additional possibility like with the Logitech M720 Triathlon mouse – its even nice that way – but I would not use mouse that the only possible way to connect/operate is by Bluetooth protocol. Maybe on a macOS UNIX but definitely not on FreeBSD UNIX πŸ™‚

AMIGA ‘Tank’ Mouse

The first mouse device that I used was the oldschool AMIGA ‘Tank’ Mouse which I used alongside my first computer – AMIGA A600. When I used it or played Cannon Fodder it felt more then up to the task but using only two buttons mouse (without any scroll and third button) in 2021 feels almost impossible for me.


It was possible to run AMIGA UNIX (also known as Amix) on AMIGA hardware. That was an AT&T Unix System V Release 4 developed as alternative to default AmigaOS but you needed Amiga A3000UX hardware for that.


Unfortunately the AMIGA A600 was not supported 😦

Lenovo and ThinkPad Twins

One of my older/earlier mouse models that I used were quite ‘identical’ mouse models Lenovo Wireless USB Mouse (0A36188) and ThinkPad Wireless USB Mouse (0A36193) – both made by Lenovo for the record. They have the same size and work mostly the same but the older one – ThinkPad model (0A36193) – had more responsive third button (the one under the wheel) – the Lenovo (0A36188) kinda needed real strength to press it – that was its downside.


I still own the ThinkPad one (0A36193) and use it from time to time when I travel – the two AA batteries allow quite long operation of more then a month – which is more then enough for my standards.

Its my first mouse that got additional buttons on the scroll wheel for left and right operations – I used it for volume control on my UNIX system which was (and still is) VERY convenient.

While I really like its/their small size – but after some longer use I really miss some more ergonomic shape under my hand. That means that it ‘will do’ for short periods of usage in travel situations but for long work use something more ergonomic then these.

Logitech Marathon M705 (GEN 1)

I got it after more then a year of using Lenovo and ThinkPad mice. It was real upgrade with quite nice profiled shape to the right hand. It was also quite heavy – but that was good – it felt really good to operate in hand. It was branded as very long to use without changing or charging the batteries and it really did provided in that department – I needed to change/charge the batteries maybe once a year or less often. It was also more precise then simple ThinkPad/Lenovo mouse.


The volume buttons from the wheel that I used on the Lenovo and ThinkPad mice was not quite possible here. While the mouse have these left/right buttons on the wheel they were clumsy and not very precise – so you loss more time trying to press them properly then doing it the other way. With Logitech M705 I ‘moved’ my volume controls to other two buttons that were available under the thumb button. Fortunately there are two of those additional buttons so it was perfect for volume up and volume down actions.

This is also the first mouse that allowed to toggle the wheel to be ‘clickless’ – you can literally spin it for several seconds without any resistance – it just keeps rolling itself – and to be honest – that is one of the features I now DEMAND from any mouse. It makes life so much better (and faster). Instead of scrolling many – many times to get where its needed – you just spin it once and wait till you get there – and even a lot faster then with ‘traditional’ clicking mouse wheel.

Another advantage of that approach is that tip of your finger does not hurt after all day long of scrolling … and if you need precision clicking wheel – then just toggle it and you can click-scroll as usual.

With LogitechΒ Marathon M705 mouse I also grow another ‘useful’ habit (or need) in a mouse. I started to use the lower thumb button to toggle between pause/play for my Deadbeef music player. Before that I used to switch to Workspace 3 where it plays music and press [C] key to toggle pause/play. After adding additional deadbeef --play-pause action to my xbindkeys(1) config now all I have to do to toggle between play and pause is to just push my thumb mouse button. Way faster πŸ™‚

Logitech Performance MX

After reading many comparisons with Logitech MX Master generations I finally settled on the Logitech Performance MX mouse. It is really big and that is really big advantage. It handles/lies really nice in a hand and being quite large and heavy it is very precise and you got ‘good’ feeling and confidence of using it. I really liked it till I got to know its two big downsides … first was the battery time. I needed to change/charge battery about once a week. That was REALLY disappointing. The other downside was that it was not able to properly operate on a flat WOOD surface (like on the photo below). Plain simple flat wood. All other mice worked well on this surface while this one did not. The marketed Darkfield sensor was useless. These were the two reasons that I got rid of it.


Same as with M705 the left/right buttons on the wheel were not very precise so I used the additional thumb buttons for volume management. The Logitech Performance MX mouse also comes with micro USB port at the front so you may use the mouse while you are charging it. Its real pity that Logitech did not used two (or even three) AA batteries for this mouse to make it last longer … but that would not resolve the Darkfield sensor not able to cope with movement on the wood πŸ™‚

Logitech Marathon M705 (GEN 2)

I have read a lot of hate and disappointment about the latest generation of Logitech Marathon M705 mouse. Also the lower thumb button is missing and currently it uses only one AA battery. It still provides very long time without the need to change/charge and its lighter now. Its neither bad nor good – its just different. The precision is similar but after using Logitech Performance MX you really miss that big size.


The second generation of M705 did not improved the left/right buttons on the wheel so I decided to stick with additional thumb buttons for volume management.

I also really missed that lower thumb button that is gone from the GEN 2 Logitech Marathon M705 mouse – needed to go back to my [C] routine …

Logitech Triathlon M720

I recently got the possibility to check and use the Logitech Triathlon M720 mouse and I must say that I am positively surprised. Its both Bluetooth and USB dongle mouse so you can choose which way you would like to connect it to your computers. The plural form is intended here as the Logitech M720 allows you to switch between 3 computers with additional dedicated button. It also got ‘back’ the lower thumb button that was missing on the latest generation of the Logitech M705 mouse. The light/white lower bottom of the mouse looks little strange though … but its kinda not visible when it is laying on the table.


The M720 has more precise left/right buttons on the wheel but I got so used to manage volume with my thumb that I currently keep these ‘wheel’ buttons unused.

Having the lower thumb button again I was also able to get back to my toggle play/pause Deadbeef operation. Yay!

Another useful use case I discovered recently is the ‘misuse’ of the button that switches between 3 computers. I started to use it to ‘suspend’ (generally off) the mouse if I do not want the mouse to ‘wake’ the screen – to not accidentally turn on the screen when I move the mouse accidentally. I mean – sometimes I turn off the screen (with shortcut that executes xset dpms force off command) and then I switch the mouse M720 mouse to channel number 2 to it will not be able to communicate with USB receiver and turn on my screen in again accidentally.


I never owned Logitech MX Master mouse. I used version ‘3’ for short time as one of my buddies own it and it felt quite similar to Logitech Performance MX in operation but not quite the same. Similar but different. I think that it would be comfortable but not sure about the precision on wood and battery time. Maybe I will got it some day and add an update here.


… but given the fact that Logitech MX Master mouse also has micro USB port at its front for charging I would suspect that battery time is also not that great. Similarly like the Logitech Triathlon M720 it also allows to switch its presence between 3 computers. There is also additional wheel for vertical scrolling. Never used that but maybe it would be useful in GIMP for example.


So what does a good UNIX mouse feature? I would summarize all the needed (or at least useful) feats in a list below.

  • needs to be at lest a little ergonomic
  • allows to toggle wheel between click and clickless operation
  • have additional buttons for custom actions
  • allows more then one month of work on batteries
  • works on different surfaces without a problem
  • has a USB dongle so Bluetooth is not needed

What other features you desire in mouse? I also thought about ‘vertical’ mouse type/shape and also about trackball. I tried my neighbor Logitech trackball several times but I am not sure I would get used to it after so many years of ricing the mice πŸ™‚

External Discussions


FreeBSD Desktop – Part 27 – Configuration – Netflix Signal Telegram

In this article you will learn how to use Netflix (also other streaming services that require Widevine DRM) and Signal/Telegram on FreeBSD desktop.

You may want to check other articles in the FreeBSD Desktop series on the FreeBSD Desktop – Global Page where you will find links to all episodes of the series along with table of contents for each episode’s contents.

The Table of Contents for the article:



While Netflix serves their content using FreeBSD servers the Netflix streaming service itself is not available on the FreeBSD platform because Widevine DRM does not support browsers on FreeBSD system.


We will use one of the more known FreeBSD features – the Linux Compatibility Layer. When FreeBSD 13.0-RELEASE was introduced the LINUX_COMPAT support was greatly improved. To the point where you can swap the default CentOS 7 based layer into the newer and more suited for desktop – the Ubuntu based layer.

Thank to author of NomadBSD system – mrclksr – we can now install needed Chrome/Brave/Vivaldi browser with automatic install and setup of that Ubuntu layer under /compat/ubuntu path. Its available on the GitHub https://github.com/mrclksr/linux-browser-installer page. First we will clone this repository with git(1) command.

# pkg install git-lite

# exit

% git clone git@github.com:mrclksr/linux-browser-installer.git
Cloning into 'linux-browser-installer'...
remote: Enumerating objects: 158, done.
remote: Counting objects: 100% (158/158), done.
remote: Compressing objects: 100% (95/95), done.
remote: Total 158 (delta 91), reused 114 (delta 54), pack-reused 0
Receiving objects: 100% (158/158), 25.59 KiB | 323.00 KiB/s, done.
Resolving deltas: 100% (91/91), done.

Some notes before starting it. You need to choose which LINUX_COMPAT are you using on FreeBSD. You can not use both the default CentOS based layer under /compat/linux and another one with Ubuntu based layer under /compat/ubuntu for example. To use the Ubuntu based layer the script will set the compat.linux.emul_path variable to /compat/ubuntu dir. Also under the /etc/rc.conf variable linux_enable=YES will be replaced by ubuntu_enable=YES one.


Lets run it then.

From available browsers I have chosen to install and run Chrome.

It will take about 10-15 minutes to download and setup all needed packages.

% cd linux-browser-installer

% ls -l
total 24K
drwxr-xr-x 2 vermaden vermaden    5 2021-08-06 22:06 bin/
drwxr-xr-x 3 vermaden vermaden    3 2021-08-06 22:06 chroot/
drwxr-xr-x 2 vermaden vermaden    3 2021-08-06 22:06 rc.d/
-rw-r--r-- 1 vermaden vermaden  350 2021-08-06 22:06 linux-brave.desktop
-rwxr-xr-x 1 vermaden vermaden 9363 2021-08-06 22:06 linux-browser-installer
-rw-r--r-- 1 vermaden vermaden  362 2021-08-06 22:06 linux-chrome.desktop
-rw-r--r-- 1 vermaden vermaden  348 2021-08-06 22:06 linux-vivaldi.desktop
-rw-r--r-- 1 vermaden vermaden 3200 2021-08-06 22:06 README.md

% ./linux-browser-installer install chrome

Now reboot(8) please. After you started your system you should be able to start Linux version of Chrome.

This command below is started from the host system – not from within the Ubuntu compat layer at the /compat/ubuntu path.

% /usr/local/bin/linux-chrome


Sometimes applications in that Ubuntu compat layer yield about no knowing you hostname. I usually add that hostname as alias as shown below.

% doas chroot /compat/ubuntu bash

root@w520:/# cat /etc/hosts       localhost
::1             localhost ip6-localhost ip6-loopback
ff02::1         ip6-allnodes
ff02::2         ip6-allrouters

root@w520:/# vi /etc/hosts

root@w520:/# cat /etc/hosts       localhost w520.local
::1             localhost ip6-localhost ip6-loopback
ff02::1         ip6-allnodes
ff02::2         ip6-allrouters

Now Netflix will just work. Just go to the Netflix page, login and start some movie.




Signal – the trusted and encrypted communicator – provides a dedicated Debian/Ubuntu repository for installation … but not for FreeBSD systems.

As the Signal packages are dedicated for Ubuntu systems we will use out just created Ubuntu compat layer from the previous step and will use it to install and setup Signal on FreeBSD.

On the https://www.signal.org/download/linux/ page you will find official Signal install instructions.

I will paste them here so you will not have to go to another page just to copy them.

wget -O- https://updates.signal.org/desktop/apt/keys.asc \
  | gpg --dearmor > signal-desktop-keyring.gpg

cat signal-desktop-keyring.gpg \
  | sudo tee -a /usr/share/keyrings/signal-desktop-keyring.gpg > /dev/null

echo 'deb [arch=amd64 signed-by=/usr/share/keyrings/signal-desktop-keyring.gpg] https://updates.signal.org/desktop/apt xenial main' \
  | sudo tee -a /etc/apt/sources.list.d/signal-xenial.list

sudo apt update \
  && sudo apt install signal-desktop

The installation of that signal-desktop package will take quite some space – more then 820 MB – but with ZFS compression enabled it should be only half of that πŸ™‚

You may encounter this problem just after the signal-desktop installation.

Errors were encountered while processing:

The solution is quite simple – remove these packages shown below.

root@w520:/# apt remove libpam-fprintd:amd64 libfprint-2-2:amd64

root@w520:/# apt autoremove

root@w520:/# apt install signal-desktop

On the contrary to the Chrome the Signal is located within the Ubuntu compat layer /compat/ubuntu path.

To make it work it needs to be started with the --no-sandbox argument – like that.

% /compat/ubuntu/opt/Signal/signal-desktop --no-sandbox

To make it work you still need to have Signal installed and configured on your phone and also add that Signal Desktop application as Linked Device to make it work. I was able to set it up without any problems. Below you will find configured and working Signal Desktop on FreeBSD.



Telegram – the other secure messenger – is available in the FreeBSD Ports tree and packages.


This means you do not have to make any additional steps and you can just install and run it.

# pkg install telegram-desktop
# exit
% telegram-desktop

Here is Telegram Desktop working flawlessly under FreeBSD.



This section summarized this article – hope that it will help some of you to expand you FreeBSD system possibilities.