Tag Archives: unix

Scripts Stats

I have grown many scripts in my UNIX life – close to 500 that I still use daily and even more then 700 in my 18 years time at various jobs … and also often for personal daily reasons.

% find ~/scripts -maxdepth 1 | wc -l
     492

% find ~/scripts -type f | wc -l
     702

All (or most) of these scripts are available on my https://github.com/vermaden/scripts GitHub page.

Feel free to ask me about ones I did not added there.

… and while having all of them – I was curious … how often I use them.

Are they still useful? Should I delete them? Phase out? Archive?

There was time that You probably seen the following code part in some of my scripts.

echo '1' 2> /dev/null >> ~/scripts/stats/${0##*/}

It is/was for stats.

I have created a ~/scripts/stats directory in which I stored stats for how often I executed my scripts … and gathered these stats for 3 years.

The start date of the experiment was on 2020/10/17 day.

To be honest – the code snipped should have looked like that one below – to make sure its possible to store the stats and the dir exists πŸ™‚

mkdir -p                 ~/scripts/stats || exit 0
echo '1' 2> /dev/null >> ~/scripts/stats/${0##*/}

The complete stats are below – but be advised that they contain various scripts I run using cron(8) or that they are part of my 5 minutes or less Dzen2 information bar.

5800969  TOTAL
1074619  desktop-kill-shit.sh
 506653  __conky_if_dns.sh
 506485  __conky_if_ping.sh
 506466  __conky_if_gw.sh
 506357  dzen2-update.sh
 499821  __conky_if_ip.sh
 493590  __conky_battery_separate.sh
 484046  desktop-battery-warning.sh
 363833  __conky_if_xfer.sh
 207484  rsync-delete.sh
 132050  acpi-thinkpad-fan.sh
 155405  random-wallpaper.sh
  94059  rsync-delete-before.sh
  42239  xdotool.sh
  41625  to-ascii.sh
  37234  random.sh
  25154  xterm.sh
  20593  random-wallpaper-always.sh
  12811  __conky_battery.sh
  11162  todo.sh
  11135  cal.sh
   8634  network.sh
   6303  mpv.sh
   6249  ff.mp3.320.sh
   6017  mupdf.sh
   4771  see.sh
   3565  shot.sh
   2977  __openbox_lock.sh
   2034  urxvt.sh
   2024  aero-snap.sh
   1702  terminal.sh
   1236  desktop-debug.sh
   1082  photo-unsharp-mask-JPG.sh
   1073  dzen2-fifo.sh
   1073  __openbox_restart_dzen2.sh
   1072  __openbox_restart_tint2.sh
    788  thunar-mass-rename.sh
    741  __openbox_freebsd_sound.sh
    724  __openbox_lock_zzz.sh
    694  generate-links.sh
    683  __openbox_cpufreq_dynamic.sh
    682  __openbox_delete_wallpaper.sh
    655  __openbox_restart_conky.sh
    637  backup-cfg.sh
    620  photo-movie-audio-ac3.sh
    508  __openbox_virtualbox.sh
    503  to-lower.sh
    483  desktop-pause.sh
    468  __openbox_clean_tmp.sh
    460  ncdu.sh
    434  __openbox_cpufreq.sh
    420  firefox.sh
    384  rsync-delete-checksum.sh
    377  nfs.sh
    365  __openbox_edit_screenshot.sh
    342  games-sensible-world-of-soccer-SFX.sh
    322  sumatra.sh
    291  mdconfig.sh
    286  __openbox_dmenu.sh
    285  __random.sh
    284  mouse-move.sh
    277  photo-movie-audio-copy.sh
    272  mp3-EYE3D-remove-id.sh
    231  photo-movie-audio-copy-x265.sh
    226  __openbox_restart_redshift.sh
    208  __openbox_edit_wallpaper_gimp.sh
    205  __openbox_show_screenshot.sh
    188  __openbox_current_wallpaper.sh
    184  mpv-shuffle.sh
    183  __openbox_trash_delete.sh
    182  games-baldurs-gate-II-ee-fullscreen.sh
    162  __openbox_phaseout_wallpaper.sh
    161  files-count.sh
    152  photo-movie-half-audio-copy-x265.sh
    142  rsync.sh
    142  pdf-split.sh
    135  rdesktop-mine.sh
    135  pdf-pts-scale.sh
    135  __openbox_restart_plank.sh
    118  to-ascii-all.sh
    102  battery-capacity.sh
     93  __openbox_reload_wallpaper.sh
     89  jhead.sh
     86  tile.sh
     77  photo-requality.sh
     74  photo-rename-images.sh
     68  zip.sh
     68  pdf-concat.sh
     66  colors.sh
     65  games-baldurs-gate-I-ee-fullscreen.sh
     64  thunar.sh
     57  smartwear.sh
     57  photo-rename-movies.sh
     53  tcpkill.sh
     53  fastdiff.sh
     49  __openbox_restart_compton.sh
     48  pkg-recompile.sh
     47  sensors.sh
     45  vbox-suid.sh
     45  __openbox_restart_xbindkeys.sh
     42  games-baldurs-gate-I-fullscreen.sh
     41  contacts-convert-vcf-from.sh
     40  games-baldurs-gate-I-ee-window.sh
     40  contacts-check.sh
     38  dedup.sh
     36  pdf-extract.sh
     35  photo-unsharp-mask-PNG.sh
     35  games-colin-mcrae-rally-2.0-window.sh
     32  files-big.sh
     32  epiphany.sh
     31  photo-flow.sh
     31  backup-remote-checksum.sh
     30  loop.sh
     30  firefox-clean.sh
     27  idle.sh
     24  games-icewind-dale-ee-fullscreen.sh
     23  games-sensible-world-of-soccer.sh
     23  games-heroes-of-might-and-magic-III-window.sh
     22  fc-cache.sh
     20  xnview.sh
     20  __openbox_stop_compton.sh
     19  key.sh
     18  winscp.sh
     18  games-heroes-of-might-and-magic-III-HotA-window.sh
     18  __openbox_restart_squid.sh
     17  ports-generate-distinfo.sh
     17  games-swing.sh
     16  games-diablo.sh
     15  games-baldurs-gate-II-ee-window.sh
     15  backup-sys.sh
     11  pdf-rotate-right.sh
     11  games-DOSBOX.sh
     10  nfs-clean.sh
     10  http.sh
     10  games-pro-pinball-timeshock-window.sh
     10  games-lionheart-window.sh
      9  games-heroes-of-might-and-magic-III-HotA-fullscreen.sh
      9  ff.mp3.160.sh
      9  contacts-convert-vcf-to.sh
      9  __xterm_link_open.sh
      8  sshfs.sh
      8  lsblk.sh
      8  html-strip-script.sh
      8  games-fallout-2-window.sh
      8  games-fallout-2-fullscreen.sh
      8  games-canyon-defence.sh
      8  games-all-terrain-racing.sh
      8  __openbox_monitor_off_auto.sh
      7  games-sensible-world-of-soccer-UPG.sh
      7  games-pinball-space-cadet-NATIVE.sh
      6  rdesktop_1800_1000.sh
      6  netstat.sh
      6  games-colin-mcrae-rally-2.0-fullscreen.sh
      6  games-baldurs-gate-I-window.sh
      6  __openbox_virtualbox_vmctrl.sh
      6  __openbox_stop_plank.sh
      6  __openbox_stats_top_cpu_RENICE.sh
      6  __openbox_stats_ps_KILLALL.sh
      5  vergallery.sh
      5  rsync-delete-linux.sh
      5  games-worms-armageddon-fullscreen.sh
      5  games-robokill-1.sh
      5  games-heroes-of-might-and-magic-II.sh
      5  freebsd-lists.sh
      5  detox.sh
      5  __openbox_virtualbox_reload.sh
      5  __openbox_stats_top_cpu_KILL.sh
      5  __conky_top.sh
      4  wm_names.sh
      4  photo-movie-half-audio-copy-x264.sh
      4  photo-movie-audio-ac3-CRF.sh
      4  gg-log.sh
      4  games-sensible-golf.sh
      4  games-robokill-2.sh
      4  games-pinball-short-circuit.sh
      4  games-lionheart-fullscreen.sh
      4  __xterm_set_title.sh
      4  __openbox_stop_dzen2.sh
      4  __openbox_stats_top_mem_RENICE.sh
      3  see-open.sh
      3  photo-FLOW.sh
      3  jail.sh
      3  jail-version.sh
      3  games-theme-hospital.sh
      3  games-supercars-international.sh
      3  games-governor-of-poker.sh
      3  games-carmageddon.sh
      3  ext-maxtor.sh
      3  __openbox_stop_tint2.sh
      3  __openbox_stats_top_mem_KILL.sh

The same list without the stuff that runs periodically in cron(8) is below.

235624  TOTAL
 42239  xdotool.sh
 41625  to-ascii.sh
 37234  random.sh
 25154  xterm.sh
 11162  todo.sh
 11135  cal.sh
  8634  network.sh
  6303  mpv.sh
  6249  ff.mp3.320.sh
  6017  mupdf.sh
  4771  see.sh
  3565  shot.sh
  2977  __openbox_lock.sh
  2034  urxvt.sh
  2024  aero-snap.sh
  1702  terminal.sh
  1236  desktop-debug.sh
  1082  photo-unsharp-mask-JPG.sh
  1073  __openbox_restart_dzen2.sh
  1072  __openbox_restart_tint2.sh
   788  thunar-mass-rename.sh
   741  __openbox_freebsd_sound.sh
   724  __openbox_lock_zzz.sh
   694  generate-links.sh
   683  __openbox_cpufreq_dynamic.sh
   682  __openbox_delete_wallpaper.sh
   655  __openbox_restart_conky.sh
   637  backup-cfg.sh
   620  photo-movie-audio-ac3.sh
   508  __openbox_virtualbox.sh
   503  to-lower.sh
   483  desktop-pause.sh
   468  __openbox_clean_tmp.sh
   460  ncdu.sh
   434  __openbox_cpufreq.sh
   420  firefox.sh
   384  rsync-delete-checksum.sh
   377  nfs.sh
   365  __openbox_edit_screenshot.sh
   342  games-sensible-world-of-soccer-SFX.sh
   322  sumatra.sh
   291  mdconfig.sh
   286  __openbox_dmenu.sh
   285  __random.sh
   284  mouse-move.sh
   277  photo-movie-audio-copy.sh
   272  mp3-EYE3D-remove-id.sh
   231  photo-movie-audio-copy-x265.sh
   226  __openbox_restart_redshift.sh
   208  __openbox_edit_wallpaper_gimp.sh
   205  __openbox_show_screenshot.sh
   188  __openbox_current_wallpaper.sh
   184  mpv-shuffle.sh
   183  __openbox_trash_delete.sh
   182  games-baldurs-gate-II-ee-fullscreen.sh
   162  __openbox_phaseout_wallpaper.sh
   161  files-count.sh
   152  photo-movie-half-audio-copy-x265.sh
   142  rsync.sh
   142  pdf-split.sh
   135  rdesktop-mine.sh
   135  pdf-pts-scale.sh
   135  __openbox_restart_plank.sh
   118  to-ascii-all.sh
   102  battery-capacity.sh
    93  __openbox_reload_wallpaper.sh
    89  jhead.sh
    86  tile.sh
    77  photo-requality.sh
    74  photo-rename-images.sh
    68  zip.sh
    68  pdf-concat.sh
    66  colors.sh
    65  games-baldurs-gate-I-ee-fullscreen.sh
    64  thunar.sh
    57  smartwear.sh
    57  photo-rename-movies.sh
    53  tcpkill.sh
    53  fastdiff.sh
    49  __openbox_restart_compton.sh
    48  pkg-recompile.sh
    47  sensors.sh
    45  vbox-suid.sh
    45  __openbox_restart_xbindkeys.sh
    42  games-baldurs-gate-I-fullscreen.sh
    41  contacts-convert-vcf-from.sh
    40  games-baldurs-gate-I-ee-window.sh
    40  contacts-check.sh
    38  dedup.sh
    36  pdf-extract.sh
    35  photo-unsharp-mask-PNG.sh
    35  games-colin-mcrae-rally-2.0-window.sh
    32  files-big.sh
    32  epiphany.sh
    31  photo-flow.sh
    31  backup-remote-checksum.sh
    30  loop.sh
    30  firefox-clean.sh
    27  idle.sh
    24  games-icewind-dale-ee-fullscreen.sh
    23  games-sensible-world-of-soccer.sh
    23  games-heroes-of-might-and-magic-III-window.sh
    22  fc-cache.sh
    20  xnview.sh
    20  __openbox_stop_compton.sh
    19  key.sh
    18  winscp.sh
    18  games-heroes-of-might-and-magic-III-HotA-window.sh
    18  __openbox_restart_squid.sh
    17  ports-generate-distinfo.sh
    17  games-swing.sh
    16  games-diablo.sh
    15  games-baldurs-gate-II-ee-window.sh
    15  backup-sys.sh
    11  pdf-rotate-right.sh
    11  games-DOSBOX.sh
    10  nfs-clean.sh
    10  http.sh
    10  games-pro-pinball-timeshock-window.sh
    10  games-lionheart-window.sh
     9  games-heroes-of-might-and-magic-III-HotA-fullscreen.sh
     9  ff.mp3.160.sh
     9  contacts-convert-vcf-to.sh
     9  __xterm_link_open.sh
     8  sshfs.sh
     8  lsblk.sh
     8  html-strip-script.sh
     8  games-fallout-2-window.sh
     8  games-fallout-2-fullscreen.sh
     8  games-canyon-defence.sh
     8  games-all-terrain-racing.sh
     8  __openbox_monitor_off_auto.sh
     7  games-sensible-world-of-soccer-UPG.sh
     7  games-pinball-space-cadet-NATIVE.sh
     6  rdesktop_1800_1000.sh
     6  netstat.sh
     6  games-colin-mcrae-rally-2.0-fullscreen.sh
     6  games-baldurs-gate-I-window.sh
     6  __openbox_virtualbox_vmctrl.sh
     6  __openbox_stop_plank.sh
     6  __openbox_stats_top_cpu_RENICE.sh
     6  __openbox_stats_ps_KILLALL.sh
     5  vergallery.sh
     5  rsync-delete-linux.sh
     5  games-worms-armageddon-fullscreen.sh
     5  games-robokill-1.sh
     5  games-heroes-of-might-and-magic-II.sh
     5  freebsd-lists.sh
     5  detox.sh
     5  __openbox_virtualbox_reload.sh
     5  __openbox_stats_top_cpu_KILL.sh
     5  __conky_top.sh
     4  wm_names.sh
     4  photo-movie-half-audio-copy-x264.sh
     4  photo-movie-audio-ac3-CRF.sh
     4  gg-log.sh
     4  games-sensible-golf.sh
     4  games-robokill-2.sh
     4  games-pinball-short-circuit.sh
     4  games-lionheart-fullscreen.sh
     4  __xterm_set_title.sh
     4  __openbox_stop_dzen2.sh
     4  __openbox_stats_top_mem_RENICE.sh
     3  see-open.sh
     3  photo-FLOW.sh
     3  jail.sh
     3  jail-version.sh
     3  games-theme-hospital.sh
     3  games-supercars-international.sh
     3  games-governor-of-poker.sh
     3  games-carmageddon.sh
     3  ext-maxtor.sh
     3  __openbox_stop_tint2.sh
     3  __openbox_stats_top_mem_KILL.sh

The experiment ended on 2023/10/17.

This is the time I removed the known code snipped from all of the scripts.

This data helped me to tweak a little more the ones that I use the most … and especially the ones that are run by my Dzen2 info bar config or in cron(8) daemon.

Some of this input also helped me to just phase out the ones that are not needed anymore … to put them into retirement.

EOF

Failed Backup Server Build

When you read my blog articles and stuff – you may get the idea that everything I do – just happens to be right and that I succeed at every attempt. This article is here to remind you that I also often fail trying to do what was suppose to be great ‘on paper’ before doing it. Some call it experience … but the problem with experience is that you get it just after you needed it.

Out of Space

While I was relatively happy with my earlier backup box – Perfect NAS Solution – described here – it had one drawback. Space … lack of it. I did not wanted to invest in 8 TB NVMe SSD – so I used 4 TB NVMe SSD 2280 and 2 TB NVMe SSD 2230 as this AMD Ryzen based box had only two M.2 slots for storage … and getting 4 TB 2230 SSD is also very expensive.

% df -g /data
Filesystem 1G-blocks Used Avail Capacity  Mounted on
data/data      7311 4833  2478    66%    /data
 
% zpool list data
NAME    SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
data   7.27T  4.72T  2.55T        -         -     1%    64%  1.00x    ONLINE  -

As I got 2 TB and 4 TB I created two independent ZFS pools on them and then I created needed datasets for needed directories from the /data dir … but as time as passed some grew too much – like /data/download for example … so I started to manually move these datasets between these SSDs … and that just started to require too much micro management I did not wanted to waste time on.

Perfect Hardware for the Job

After checking what is available on the market I decided to get new small box – this time Intel N100 (or N150) based – with multiple M.2 slots. I was able to find even smaller then AMD Ryzen box computer that would have not only four M.2 slots but even FIVE of them.

The fifth one is hidden inside and fits nicely the 2 TB NVMe SSD 2230 that I already had – I also got four 2 TB 2280 ones and 16 GB RAM as seen on the above picture. The system is not fanless – but a small occasional fan does not hurt much – as AMD Ryzen box also had fan that almost never started – and it had much larger TDP then the 6 W TDP of Intel N100 CPU.

This little gem even have additional USB-A slot inside – so you can fit Lexar S47 32 GB USB pendrive there – not to mention TWO Intel 2.5 GB network cards.

Here is how Maiyunda M1S compares against previous GenMachine solution.

Keep it Cool

The only thing that I was worried about was cooling of the NVMe SSDs – to make them not hot enough – and while the box has two 2.5 GbE ports (supported on FreeBSD by igc(4) driver) – speeds like 50-70MB/s are more then enough for my needs (assuming that LAN would be used) – as I also am used to 10-11 MB/s when WiFi is involved … and I came prepared when it comes to cooling.

I attached radiators to all of the SSDs – the internal one had smaller heatsink (and it was more hot) but the top ones got really nice piece of aluminum on them – attached using 15W/mK silicone thermal pad.

Huge Metal Fan

While I prefer passive cooled solutions – its not always possible to get all the features in decent prices in fanless mode.

After tweaking various BIOS settings I came to Hardware Monitor for thermal related stuff … and it seems that even that small Intel N100 with 6W TDP can be REALLY hot. After messing with the settings of the internal fan – and keeping it running all the time at about 3000 RPM – I settles on about 60oC temperature.

The temperatures reported with sensors(8) were high but not problematic. As you can expect the internal NVMe SSD was little warmer.

# sensors
 
            BATTERY/AC/TIME/FAN/SPEED 
 ------------------------------------ 
               dev.cpu.0.cx_supported: C1/1/0 
                   dev.cpu.0.cx_usage: 100.00% last 6353us
                       dev.cpu.0.freq: 800 
                hw.acpi.cpu.cx_lowest: C1 
                            powerd(8): running
 
                  SYSTEM/TEMPERATURES 
 ------------------------------------ 
      hw.acpi.thermal.tz0.temperature: 27.9C (max: 110.1C)
                dev.cpu.0.temperature: 68.0C (max: 105.0C)
                dev.cpu.1.temperature: 67.0C (max: 105.0C)
                dev.cpu.2.temperature: 67.0C (max: 105.0C)
                dev.cpu.3.temperature: 67.0C (max: 105.0C)
 
                   DISKS/TEMPERATURES 
 ------------------------------------ 
              smart.nvme0.temperature: 74.0C
              smart.nvme1.temperature: 39.0C
              smart.nvme2.temperature: 38.0C
              smart.nvme3.temperature: 39.0C
              smart.nvme4.temperature: 38.0C

I am Speed

This is how all the disks looked like using lsblk(8) command.

# lsblk -d
DEVICE SIZE MODEL
da0     29G Lexar USB Flash Drive
nda0   1.9T WD PC SN740 SDDPTQE-2T00
nda1   1.9T ADATA SX8200PNP
nda2   1.9T ADATA SX8200PNP
nda3   1.9T ADATA SX8200PNP
nda4   1.9T ADATA SX8200PNP
-       10T TOTAL SYSTEM STORAGE

Quick ‘benchmark’ of the NVMe SSD drives using diskinfo(8) is shown below.

# for I in 0 1 2 3 4; do diskinfo -vt nda${I}; echo; done | grep -e nda -e side
nda0
        outside:       102400 kbytes in   0.137933 sec =   742389 kbytes/sec
        inside:        102400 kbytes in   0.136937 sec =   747789 kbytes/sec
nda1
        outside:       102400 kbytes in   0.136848 sec =   748275 kbytes/sec
        inside:        102400 kbytes in   0.135698 sec =   754617 kbytes/sec
nda2
        outside:       102400 kbytes in   0.136665 sec =   749277 kbytes/sec
        inside:        102400 kbytes in   0.135783 sec =   754144 kbytes/sec
nda3
        outside:       102400 kbytes in   0.190700 sec =   536969 kbytes/sec
        inside:        102400 kbytes in   0.135555 sec =   755413 kbytes/sec
nda4
        outside:       102400 kbytes in   0.136825 sec =   748401 kbytes/sec
        inside:        102400 kbytes in   0.135868 sec =   753673 kbytes/sec

I forgot to mention one important thing – the Intel N100 CPU maximum number of PCIe lanes is 9.


    SPEC       LANE         X1         X2         X4       X8          X16
PCIe 1.x   2.5 GT/s    0.5GB/s    1.0GB/s    2.0GB/s    4.0GB/s    8.0GB/s
PCIe 2.x   5.0 GT/s    1.0GB/s    2.0GB/s    4.0GB/s    8.0GB/s   16.0GB/s
PCIe 3.x   8.0 GT/s    2.0GB/s    4.0GB/s    8.0GB/s   16.0GB/s   32.0GB/s
PCIe 4.x  16.0 GT/s    4.0GB/s    8.0GB/s   16.0GB/s   32.0GB/s   64.0GB/s
PCIe 5.x  32.0 GT/s    8.0GB/s   16.0GB/s   32.0GB/s   64.0GB/s  128.0GB/s
PCIe 6.x  64.0 GT/s   16.0GB/s   32.0GB/s   64.0GB/s  128.0GB/s  256.0GB/s

That means that all these NVMe SSDs work not at their maximum speed like up to 8000MB/s with PCIe 3.0 4x lanes. Each of these NVMe have only ONE (1) PCIe 3.0 lane – that means the maximum speed each of them would be quarter of their normal operation – this thing alone would make heat generated by them in quarter.

ZFS Part

So … I had the system running – I had the drives attached – I created ZFS pool … and for the first time I decided that ZFS based encryption is good enough – so I did not used geli(8) this time. The plan was to use RAID5 (raidz) setup here – so I will have some redundancy again.

# zpool create data raidz nda0 nda1 nda2 nda3 nda4

# zpool list data
NAME    SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
data   9.31T   912K  9.31T        -         -     0%     0%  1.00x    ONLINE  -
 
# zpool status data
  pool: data
 state: ONLINE
config:
 
        NAME        STATE     READ WRITE CKSUM
        data        ONLINE       0     0     0
          raidz1-0  ONLINE       0     0     0
            nda0    ONLINE       0     0     0
            nda1    ONLINE       0     0     0
            nda2    ONLINE       0     0     0
            nda3    ONLINE       0     0     0
            nda4    ONLINE       0     0     0
 
errors: No known data errors

# zfs set recordsize=1m data

# zfs set compression=zstd data

# zfs set atime=off data

# zfs set mountpoint=none data

# zfs set mountpoint=/data data/data

# zfs create -o encryption=on -o keyformat=passphrase -o keylocation=prompt data/data

# zfs mount -a

… but one of the NVMe SSD 2280 drives came broken – lots of read/write errors and entirely ‘broken’ S.M.A.R.T report.

Broken Drive and Resilver

That allowed me to test the ZFS resilver on these drives – you can see for yourself how it went below.

# zpool status
  pool: data
 state: DEGRADED
status: One or more devices could not be used because the label is missing or
        invalid.  Sufficient replicas exist for the pool to continue
        functioning in a degraded state.
action: Replace the device using 'zpool replace'.
   see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-4J
  scan: scrub repaired 768K in 00:02:50 with 0 errors on Sun May 18 13:29:47 2025
config:
 
        NAME                      STATE     READ WRITE CKSUM
        data                      DEGRADED     0     0     0
          raidz1-0                DEGRADED     0     0     0
            nda0                  ONLINE       0     0     0
            13389973369551797347  UNAVAIL      0     0     0  was /dev/nda1
            nda2                  ONLINE       0     0     0
            nda3                  ONLINE       0     0     0
            nda4                  ONLINE       0     0     0
 
errors: No known data errors
 
# zpool replace data 13389973369551797347 /dev/nda1
 
# zpool status data
  pool: data
 state: DEGRADED
status: One or more devices is currently being resilvered.  The pool will
        continue to function, possibly in a degraded state.
action: Wait for the resilver to complete.
  scan: resilver in progress since Wed May 21 20:33:21 2025
        198G / 198G scanned, 3.95G / 197G issued at 1011M/s
        806M resilvered, 2.00% done, 00:03:15 to go
config:
 
        NAME                        STATE     READ WRITE CKSUM
        data                        DEGRADED     0     0     0
          raidz1-0                  DEGRADED     0     0     0
            nda0                    ONLINE       0     0     0
            replacing-1             DEGRADED     0     0     0
              13389973369551797347  UNAVAIL      0     0     0  was /dev/nda1/old
              nda1                  ONLINE       0     0     0  (resilvering)
            nda2                    ONLINE       0     0     0
            nda3                    ONLINE       0     0     0
            nda4                    ONLINE       0     0     0
 
errors: No known data errors
 
# zpool status data
  pool: data
 state: DEGRADED
status: One or more devices is currently being resilvered.  The pool will
        continue to function, possibly in a degraded state.
action: Wait for the resilver to complete.
  scan: resilver in progress since Wed May 21 20:33:21 2025
        198G / 198G scanned, 95.0G / 197G issued at 1.22G/s
        19.1G resilvered, 48.16% done, 00:01:23 to go
config:
 
        NAME                        STATE     READ WRITE CKSUM
        data                        DEGRADED     0     0     0
          raidz1-0                  DEGRADED     0     0     0
            nda0                    ONLINE       0     0     0
            replacing-1             DEGRADED     0     0     0
              13389973369551797347  UNAVAIL      0     0     0  was /dev/nda1/old
              nda1                  ONLINE       0     0     0  (resilvering)
            nda2                    ONLINE       0     0     0
            nda3                    ONLINE       0     0     0
            nda4                    ONLINE       0     0     0
 
errors: No known data errors
 
# gstat -p -I 1s
dT: 1.009s  w: 1.000s
 L(q)  ops/s    r/s   kBps   ms/r    w/s   kBps   ms/w   %busy Name
    0   1171   1171 274041  0.451      0      0  0.000   41.3| nda0
    0   1235      0      0  0.000   1235 275531  0.362   36.9| nda1
    0   1164   1164 274283  0.407      0      0  0.000   38.4| nda2
    0   1159   1159 274295  0.410      0      0  0.000   38.5| nda3
    0   1161   1161 274263  0.409      0      0  0.000   38.4| nda4
    0      2      2     16  0.901      0      0  0.000    0.2| da0
 
dT: 1.002s  w: 1.000s
 L(q)  ops/s    r/s   kBps   ms/r    w/s   kBps   ms/w   %busy Name
    0   1165   1132 265890  0.450     31    148  0.038   39.9| nda0
    2   1214      0      0  0.000   1212 265882  0.352   36.1| nda1
    1   1172   1137 265942  0.407     33    152  0.038   37.7| nda2
    1   1166   1133 265902  0.408     31    148  0.042   37.7| nda3
    1   1171   1129 265698  0.411     40    180  0.041   37.7| nda4
    0      0      0      0  0.000      0      0  0.000    0.0| da0
 
# zpool status data
  pool: data
 state: ONLINE
  scan: resilvered 39.6G in 00:02:50 with 0 errors on Wed May 21 20:36:11 2025
config:
 
        NAME        STATE     READ WRITE CKSUM
        data        ONLINE       0     0     0
          raidz1-0  ONLINE       0     0     0
            nda0    ONLINE       0     0     0
            nda1    ONLINE       0     0     0
            nda2    ONLINE       0     0     0
            nda3    ONLINE       0     0     0
            nda4    ONLINE       0     0     0
 
errors: No known data errors

So it went pretty fast while the temperatures remained close to what have You seen earlier.

The Ugly

… but after some changes in the BIOS – like disabling the Integrated GPU – I needed to reset the BIOS settings altogether … and this is the part when things went fast south really hard.

After the reset I went into BIOS to setup the fan to run at about 3000 RPM … but it seems it went entirely gone … and that small box while doing nothing – started to be as warm as 90oC now … which I consider really bad – I was not even able to hold that computer case without any gloves on my hands.

When I entered the BIOS this is what I saw.

I was out of ideas and really disappointed – so I took a picture of that BIOS and created a ‘send item back and get money back’ issue on Aliexpress portal – where I got it. To be honest I did not expected much – more like a long battle to prove that something is really wrong.

Mine ‘problem report’ was not long – just a simple description on what is wrong:

“Hello. The FAN will just not start and I get some crazy temperatures like 89/82 Celsius – this Mini PC is hot as fuck – and its doing nothing – its crazy for a 6W TDP Intel N100 CPU.”

Get Money Back

I was trying to be polite – while I was also very angry because such high temperatures on a 6W TDP CPU are insane …

… and to my surprise the request was positively accepted the next day – they offered a free send back was of the hardware and promised to send me all the money back – at least that part of the story is successful.

Summary

When You want to do something ambitions – there is bigger chance that you fail … and I failed here … or should I say the hardware failed me.

Some say that if you learn from a failure it is not really a failure but a valuable lesson – and I treat that one exactly like that.

Next plans? I already ordered another Intel N100 box (actually N150 as they run out of N100 devices) with 4-5 M.2 slots and I will share with you in other article how that story went …

UPDATE 1 – High Hopes

After initial failure I have had really High Hopes (great Ping Floyd track) for the next X86 P6 Tiny NAS box I ordered … and I got disappointed again.

I first prepared all needed parts for the build as shown below.

Now – after trying to fit the NVMe adapter with 2230 2TB SSD … it was obvious that the ‘hat’ and the ‘adapter’ will not fit both together … so I was limited to ‘only’ FOUR NVMe SSDs each of 2TB size.

That was still OK – after RAM installation it looked more or less like that above.

All of my hopes were killed during the boot cycle – also seen in dmesg(8) later.

These nvmeX: timeouts above does not look that bad at first – not to mention that the box booted to BIOS POST message in 6-7 minutes – like a regular RACK server – but after the login: prompt it was obvious that a timeout for nvmeX: controller means … that a drive attached to it will NOT be available in the system.

The first (or maybe second) time it booted the drives (and controllers) were there and even the temperatures were ‘right’ – everything seemed cool … until several reboots later.

Before everything went south I was able to at least do some things as shown below.

But after that everything just broke … again.

After thinking about it I had two choices.

I could orderΒ Terramaster F8 SSD Intel N95 based NAS or more expensiveΒ Terramaster F8 SSD Plus Intel N305 powered version.

But I have decided something entirely different.

As I still got 8TB Samsung 2.5 SATA SSD I decided to get some simple AMD Ryzen based Mini PC with ONE 2.5 slot for that SSD and go that route. That AMD Ryzen based box still did not arrived at my lawn – so I will have to wait for it a little longer.

Fortunately the ‘seller’ of that ‘broken’ NAS was also kind enough to sent me the money back after I filled all needed ‘resignation’ docs.

… and do not get me wrong here – I will still seek for a usable and predictable multiple NVMe SSD NAS case – it just that it seems its not that easy and obvious to find a reasonable one …

UPDATE 2 – Interim Solution

While searching for next possible hardware solution that would allow what I want – in the mean time I got something that would ‘just work’ with what I have – I picked some used Minisforum UM350 mini PC for $230 with 4-CORE AMD Ryzen 5 3550H CPU.

While it does not offer any redundancy – mine 8 TB Samsung 870 QVO SSD will work well with it – while FreeBSD system will reside in the NVMe SSD.

One of the things I set in BIOS was the lowest possible power consumption.

In the real world – when idle – and with FreeBSD’s powerd(8) enabled – it consumes about 7W of power.

It works really well with FreeBSD and even the internal WiFi card worked out of the box was working reliably with 14.3-RELEASE version.

From the other boring stuff – that 8 TB Samsung 870 QVO SSD was earlier taken off my ThinkPad W520 – so the only thing I needed to do was to attach GELI target – import ZFS pool – and update the files with rsync(1) command – nothing fancy.

I need to confess that my next solution already arrived at my door step … I will add another update (or article) when I will have time to check it.

EOF

Perfect NAS Solution

One of my favorite measures for hardware is the ‘price/performance ratio’ – to do as much as possible but for as less resources as possible.

Hardware

Not so long ago I switched to Silent Fanless Dell Wyse 3030 LT FreeBSD Server for both of my ‘local’ backup and ‘remotew52’ backup boxes … but rules of the game changed.

dell-wyse-3030

Recently I also need some horsepower for FreeBSD Poudriere/Bhyve stuff.

I often use my gaming PC – AMD Based FreeBSD Desktop – for that … but it takes 40W of power even at idle state – not very efficient … of course if you consider the fact that it has AMD Ryzen CPU with 8C/16T and powerful AMD Radeon 5700XT GPU its not that much … but still – far from perfect.

case-outside-1

I was looking at some modern alternatives – mostly AMD Ryzen based solutions as Intel seems to have big problem with keeping up – to use them as a replacement … but nothing spectacular showed up on the radar.

For a start – I got HP EliteDesk 705 G4 mini PC with AMD Ryzen CPU … but after all tests and tweaking it uses about 14W doing nothing at idle state.

hp-705-g4

While its quite small mini PC with dimensions that fit in 18cm x 18cm x 3.5cm box the current solution Dell Wyse 3030 LT uses less then 4W of power … 10W less. Not to mention price – as I was able to get used Dell Wyse 3030 LT for about $20 and I was able to get used HP EliteDesk 705 G4 for about $120 about 6 times more … and with several times higher power draw.

After some wait I got notification from one of the auction platforms I use – that a AMD Ryzen mini PC is available to buy for about $165.

gen-machine-ext-1

Its GenMachine model Ren5000.

gen-machine-ext-2

It comes with newer AMD Ryzen 3 5300U CPU.

gen-machine-lscpu

… and with three (3) M.2 slots for storage expansion. One (1) of the M.2 slots is occupied with WiFi card – the two (2) remaining M.2 slots are 2280 and 2242 NVMe ones. For the record – the image below shows the GenMachine mini PC from below – not top πŸ™‚

gen-machine-ext-4-slots

Picture above shows interior of GenMachine with the SSD NVMe 256GB drives that I bought it with.

Nice I thought … and its a lot smaller then HP EliteDesk 705 G4 mini PC. Take a look.

gen-machine-ext-3-hp

The power draw is also a lot smaller – it uses less then 6W when idle. Having 4C/8T of AMD Ryzen performance and 16 GB RAM its more then acceptable.

… but the NVMe storage is really expensive I thought … or not that much?

I got used to buy and use slow SMR 2TB/5TB traditional 2.5 drives – but this time – as this is suppose to also be my lab – I thought – lets invest a little more.

I need storage for about 4TB of data and in my ‘daily driver’ ThinkPad W520 laptop – and I use Samsung 870 QVO 8TB drive for that.

With slots sizes limitations I was thinking about getting some used SSD NVMe 2280 drive in 4TB size and 2242 (or 2230) NVMe 2TB drives – to fulfill my storage needs … and that is exactly what I have done. It was more expensive then using slow SMR drives but not Rolls Royce prices either.

To fulfill my needs in SSD NVMe M.2 terms I got Crucial P3 Plus 4TB 2280 disk for about $160 and WD SN740 2TB 2230 for about $110 drives.

nvme-ssd-4tb-2tb

With 6TB of storage its more then enough for me – the first question you are gonna ask is – ‘Where is redundancy?’ – and that is very good question – its in multiple boxes – not in the ‘same’ system – some prefer to call this scale out approach.

The '4.1 - 2 - 1' Backup Rule

I use an extended version of the well known 3 - 2 - 1 backup rule. I keep ‘1’ (one) primary source for data in my ThinkPad W520 laptop.

This data I then rsync(1) into my local backup system – that would be new GenMachine box we are talking here – for ‘2’ (two) copies.

Then I also rsync(1) the same data into ‘Offsite’ location (using low power Dell Wyse 3030 LT box) for ‘3’ copies.

The ‘2’ part of the rule is now also respected as I keep backups on two medium types – HDDs and SSDs.

… and last but not least – once in a week or so I also attach additional drives for ‘4’ (four) copy of data for ‘Offline’ backup. Same plain and cheap SMR 5TB/2TB 2.5 USB drives.

So its more like 4 - 2 - 1Β enhanced with additional Offline copy. Nothing fancy – but serves its purpose …

To make the backup policy even more ‘flexible’ and complete I also rclone(1) most important subset of my data into some cloud provider.

That would make it something like 4.1 - 2 - 1Β rule πŸ™‚

One last thing – keep in mind to NOT use SSDs for Offline storage as it may lose your precious data – How Long Can SSD Hold Data without Power – seriously.

FreeBSD

One important thing I need to add here as for FreeBSD configuration.

logo-freebsd

I of course applied all known to me settings regarding power – The Power to Serve – FreeBSD Power Management – gathered here – but one is less standard one.

I added the graphics/drm-kmod package and loaded the amdgpu.ko kernel module – to enable GPU power consumption savings.

Without the amdgpu.ko kernel module loaded the GenMachine used about 8.6W when idle.

After loading the kernel module it went down to 5.8W of used power.

UPS

I also used EATON 3S Mini 36W 2200mAh UPS described in details here – Tiny UPS for Tiny NAS Reloaded – to protect the Dell Wyse 3030 LT server … but for my great surprise and happiness – it also works perfectly with new GenMachine box – its powerful enough.

eaton-top

Summary

I believe I explained everything but if not – you know how to reach me.

EOF

Keycloak Identity and Access Management on FreeBSD

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

keycloak.logo

My earlier FreeIPA/IDM attempts are below.

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

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

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

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

host # cd /vm/keycloak

host # rm -f disk0.img

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

host # truncate -s 10G disk0.img

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

host # vm console keycloak

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

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

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

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

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

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

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

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

root@freebsd:~ # service netif restart

root@freebsd:~ # service routing restart

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

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

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

root@keycloak:~ # service sshd enable

root@keycloak:~ # service sshd start

root@keycloak:~ # exit

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

host % ssh [email protected]

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

root@keycloak:~ # service postgresql enable

root@keycloak:~ # service postgresql initdb

root@keycloak:~ # service postgresql start

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

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

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

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

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

postgres=# \q

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

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

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

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

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

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

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

root@keycloak:~ # service keycloak enable

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

        kc.sh show-config

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

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

keycloak-0-initial-admin-user

Now back to the patch.

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

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

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

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

root@keycloak:~ # service keycloak start

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

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

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

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

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

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

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

keycloak-1-self-cert

Next click the Administration Console link.

keycloak-2-main-page

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

keycloak-3-admin-login

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

keycloak-4-admin-console

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

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

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

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

pam-dev

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

pam-kc

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

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

EOF

Connect FreeBSD 14.0-STABLE to FreeIPA/IDM

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

FreeIPA-logo

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

FreeIPA/IDM Server – Installation

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

LAB.IDM.Server.ROOT

After reboot its network is configured as shown below.

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

Some more basic setup commands below.


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

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

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

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

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

[root@idm ~]# yum update -y

[root@idm ~]# reboot

Continuation after reboot.

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

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

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

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

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

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

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

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

[root@idm ~]# systemctl disable firewalld

[root@idm ~]# systemctl stop    firewalld

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

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

[nss]
  homedir_substring = /home
  memcache_timeout  = 600

[pam]

[sudo]

[autofs]

[ssh]

[pac]

[ifp]
  allowed_uids = ipaapi, root

[session_recording]

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

We have our FreeIPA/IDM server installed.

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

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

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

FreeIPA-login-1

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

FreeIPA/IDM Server – Configuration

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

FreeIPA-login-2

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

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

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

The more important configuration is in HBAC and Sudo rules.

Here are HBAC related settings.

idm-1-hbac-rules-menu

idm-2-hbac-rules-menu

idm-3-hbac-rules-freebsd-details

… and the Sudo part.

idm-4-sudo-rules-menu

idm-5-sudo-rules-freebsd

idm-6-sudo-rules-freebsd-details

Poudriere Server – Setup

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

This is the template I used for Bhyve VMs.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Now internally inside VM.

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

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

Wed Mar  6 08:23:03 UTC 2024

FreeBSD/amd64 (freebsd) (ttyu0)

login: 


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

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

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

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

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

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

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

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

Now some basic configuration.

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

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

root@freebsd:~ # service sshd start

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

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

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

root@freebsd:~ # reboot

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

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

We will now setup actual Poudriere server.

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

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

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

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

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

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

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

[ CAUTION: BEGIN ]

Because of the ZROOTFS /usr/local bug I have switched the ZROOTFS variable to /dev/null and Poudriere still works well.

[ CAUTION: END ]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


Poudriere Server – Build FreeIPA/IDM Client Packages

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

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

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

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

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

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

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


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

xterm-poudriere

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

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

xterm-htop

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

poudriere-devel-100-latest-builds

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

poudriere-devel-70-latest-builds

And below are the details about our build job.

poudriere-devel-70-build-complete

Poudriere Server – Update Repo/Packages

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

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

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

You may as well update the FreeBSD Jail when needed.

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

FreeBSD 14.0-STABLE Client – Setup

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

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

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

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

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

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

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

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

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

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

[root@idm ~]# kinit admin

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

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

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

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

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

Now lets get back to our FreeBSD client.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

idm-hosts

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

host # ssh [email protected]
([email protected]) Password:
Last login: Wed Mar  6 07:04:42 2024

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

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

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

vermaden@idm-client:~ $ sudo -i
Password for [email protected]:

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

FreeBSD 14.0-STABLE Client – Debug Commands

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

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

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

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






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

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

# numResponses: 1





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

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

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

# search result
search: 4
result: 0 Success

# numResponses: 3
# numEntries: 2


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

Summary

Let me know in comments how it went.

EOF

FreeBSD UNIX Wallpapers

About 5 years ago I have shared some ‘oldschool’ computers/machines wallpaper pack – Wallpapers from Tech Pron – available here. I believe this time the wallpapers I will share with You will be similar or even more interesting – the FreeBSD UNIX wallpapers pack πŸ™‚

There are 91 of them – as gathered thru all of my FreeBSD years. Some are kinda special – at least for me – as for example the ones from the (now defunct) Polish BSD User Group ones.

Here are their miniatures.

Use the following link to download them all wallpapers-freebsd.tar.gz here.

If you are interested how these ‘sets’ images were created – then its these commands below:

% which montage 
/usr/local/bin/montage

% pkg which -o $( which montage )
/usr/local/bin/montage was installed by package graphics/ImageMagick6

% montage ${LIST_OF_30_IMAGES} -tile 6x5 -geometry '130x75!+0+0' -background "#666666" -borderwidth 1 OUT-1-3.png

UPDATE 1 – Wallpapers Based on Michael W. Lucas Absolute XxxxBSD Books

The Absolute FreeBSD and Absolute OpenBSD book covers – while being great books on the topic – have also really great covers – so I made wallpapers out of them πŸ™‚

I added them to the original wallpapers-freebsd.tar.gz file.

Here they are:

UPDATE 2 – FreeBSD loader.4th(8) Wallpaper

EOF

FreeBSD 13.2 on ThinkPad T14 (GEN1)

I used to run FreeBSD on older laptops – some more then a decade old – like my favorite ThinkPad W520 daily driver or ThinkPad X220 mobile companion. Today I will share with you my experiences of running latest production ready FreeBSD 13.2-RELEASE system on a quite modern ThinkPad T14 (GEN1) from 2021/2022 (depending on the source of the information) – which is quite new I would say.

… do not interpret this article wrong – The W520 and X220 (sometimes T420s) are still my daily/mobile/… drivers and my points explained in the Epitaph to Laptops article remain the same. I just had an opportunity to use ThinkPad T14 for several days so I thought it would be a good idea to check and document FreeBSD behavior on it.

In many parts this article will be a copy cat of the earlier FreeBSD 13.1 on ThinkPad W520 article – as the topic and configs are mostly the same – you have been warned πŸ™‚

ThinkPad T14 (GEN1)

As the ThinkPad T490 was released Lenovo needed to rethink their naming convention as the next one could have been ThinkPad T4100 (like 100 is after 90) or something different as T500 was already taken by older model … their new naming scheme is not bad – definitely better then their idea of newer keyboard layout after ditching the 7-row keyboard from 2011 and earlier models.

The model I was able to test on had quad core Intel i5-10210U model CPU which is somewhere between 25-35% faster (according to benchmarks) then the Intel i7-2860QM CPU from my ThinkPad W520. Not bad – especially knowing that the time span between their releases is 9 years … but to be honest – in real usage I do not feel that 25-35% more speed.

T14 % lscpu
Architecture:            amd64
Byte Order:              Little Endian
Total CPU(s):            8
Thread(s) per core:      2
Core(s) per socket:      4
Socket(s):               1
Vendor:                  GenuineIntel
CPU family:              6
Model:                   142
Model name:              Intel(R) Core(TM) i5-10210U CPU @ 1.60GHz
Stepping:                12
L1d cache:               32K
L1i cache:               32K
L2 cache:                256K
L3 cache:                6M
Flags:                   fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36
                         cflsh ds acpi mmx fxsr sse sse2 ss htt tm pbe sse3 pclmulqdq dtes64
                         monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1
                         sse4_2 x2apic movbe popcnt tsc_deadline aes xsave osxsave avx f16c rdrnd
                         fsgsbase tsc_adjust sgx bmi1 avx2 smep bmi2 erms invpcid fpcsds mpx rdseed
                         adx smap clflushopt intel_pt syscall nx pdpe1gb rdtscp lm lahf_lm lzcnt

Below you can see how ThinkPad T14 (GEN1) looks like.

thinkpad-t14

To be honest I would even prefer to use ThinkPad SK-8855 USB keyboard as showed here below.

T14s-keyboard-upgraded

Specifications

Below You will find specs of this machine.

CPU: Intel Core i5-10210U (4C/8T) 14nm
RAM: 16 GB (2 * 8GB DDR4)
HDD0: 256GB WD Black SN750 M.2 [nvd(4)]
GFX0: Intel UHD Graphics (integrated) [graphics/drm-kmod]
SCR: 14.1 1920x1080 Touch Screen
USB: 2 x USB-A 3.0 + 1 x USB-C 3.0 [ehci(4) + xhci(4)]
AUDIO: Realtek ALC257 [snd_hda(4)]
PORTS: 1 x HDMI
SD: microSD Card Reader [sdhci(4)]
LAN: 10/100/1000 Intel I219-V Gigabit [em(4)]
WIFI: Intel Comet Lake PCH-LP CNVi WiFi 802.11ax [iwlwifi(4)]
CAM: Webcam 720p [multimedia/webcamd]

I have uploaded the https://bsd-hardware.info/ probe of that ThinkPad T14 to their database and its available – https://bsd-hardware.info/?probe=8aede62ca8 – here.

Internals show can be also seen below.

T14-internals

After messing with this laptop for a while I can tell you that in most areas its on par with mine ThinkPad W520 laptop. The battery time is similar (about 5 hours). The suspend/resume works when you use X11 with graphics/drm-kmod package. Even the touch screen works like a charm – the same as my other ThinkPad X220t (tablet) … and even no additional configuration was needed – I just used the configuration that I use daily on my ThinkPad W520 laptop. But … the WiFi does not work πŸ™‚ While iwlwifi(4) properly attaches to this card the wpa_supplicant(8) is just not able to connect to the Access Point. There are at least several ways on how to Cope with WiFi Fuckup on FreeBSD – feel free to check them out. I used my favorite fallback solution – Realtek RTL8188CUS USB dongle and that one worked really well with rtwn(4) driver.

FreeBSD System Configuration

From many things that I really like about FreeBSD (more here – Quare FreeBSD? – in separate article) is that it can be entirely configured using just 3 files. This configuration already features all power management settings that I described in the The Power to Serve – FreeBSD Power Management article.

I installed FreeBSD in a pretty standard way with GELI encryption enabled and with ZFS as the filesystem. When in doubt the installation procedure is described in the FreeBSD Desktop – Part 2.1 – Install FreeBSD 12 article.

Main FreeBSD configuration files.

  • /etc/rc.conf – to system services
  • /etc/sysctl.conf – for runtime parameters
  • /boot/loader.conf – for parameters configurable at boot

I will also include these as their are also crucial for the configuration:

  • /etc/devfs.rules – devices configuration/li>
  • /etc/fstab – filesystems configuration
  • /etc/ttys – terminal initialization configuration
  • /etc/wpa_supplicant.conf – WiFi configuration
  • /usr/local/etc/automount.confautomount(8) configuration
  • /usr/local/etc/doas.confdoas(1) configuration
  • Groups membership.

First the main /etc/rc.conf configuration file.

% cat /etc/rc.conf
# SILENCE # ------------------------------------------------------------------
  rc_startmsgs=NO

# NETWORK # ------------------------------------------------------------------
  hostname=t14.local
  background_dhclient=YES
  extra_netfs_types=NFS
  wlans_rtwn0=wlan0
  create_args_wlan0="country PL regdomain FCC4"
  ifconfig_wlan0="WPA SYNCDHCP"
  defaultroute_delay=3
  defaultroute_carrier_delay=3
  gateway_enable=YES
  harvest_mask=351
  rtsol_flags="-i"
  rtsold_flags="-a -i"

# MODULES/COMMON/BASE # ------------------------------------------------------
  kld_list="${kld_list} /boot/modules/i915kms.ko"
  kld_list="${kld_list} fusefs coretemp sem cpuctl ichsmb cuse"
  kld_list="${kld_list} libiconv cd9660_iconv msdosfs_iconv udf_iconv"

# MODULES/VIRTUALBOX # -------------------------------------------------------
  vboxnet_enable=YES
  kld_list="${kld_list} vboxdrv vboxnetadp vboxnetflt"

# POWER
  performance_cx_lowest=C1
  economy_cx_lowest=Cmax
  powerd_enable=YES
  powerd_flags="-n adaptive -a hiadaptive -b adaptive -m 800 -M 2000"

# DAEMONS | yes # ------------------------------------------------------------
  zfs_enable=YES
  xdm_enable=YES
  xdm_tty=ttyv4
  nfs_client_enable=YES
  ubuntu_enable=YES
  moused_enable=YES
  syslogd_flags='-s -s'
  sshd_enable=YES
  local_unbound_enable=YES
  webcamd_enable=YES
  rctl_enable=YES

# DAEMONS | no # -------------------------------------------------------------
  linux_enable=NO
  sendmail_enable=NONE
  sendmail_submit_enable=NO
  sendmail_outbound_enable=NO
  sendmail_msp_queue_enable=NO

# FS # -----------------------------------------------------------------------
  fsck_y_enable=YES
  clear_tmp_enable=YES
  clear_tmp_X=YES
  growfs_enable=YES

# OTHER # --------------------------------------------------------------------
  keyrate=fast
  keymap=pl.kbd
  virecover_enable=NO
  update_motd=NO
  devfs_system_ruleset=desktop
  hostid_enable=NO
  savecore_enable=NO

Now the runtime parameters /etc/sysctl.conf file.

% cat /etc/sysctl.conf
# SECURITY
  security.bsd.see_jail_proc=0
  security.bsd.unprivileged_proc_debug=0

# SECURITY/RANDOM PID
  kern.randompid=1

# ANNOYING THINGS
  vfs.usermount=1
  kern.coredump=0
  hw.syscons.bell=0
  kern.vt.enable_bell=0

# ZFS DELETE FUCKUP TRIM (DEFAULT: 64)
  vfs.zfs.vdev.trim_max_active=1

# ZFS ARC TUNING
  vfs.zfs.arc.min=134217728
  vfs.zfs.arc.max=536870912

# ZFS ARC FREE ENFORCE @ 1024 \* 1024 \* 3
  vfs.zfs.arc_free_target=3145728

# JAILS/ALLOW UPGRADES IN JAILS
  security.jail.chflags_allowed=1

# JAILS/ALLOW RAW SOCKETS
  security.jail.allow_raw_sockets=1

# DESKTOP/INTERACTIVITY
  kern.sched.preempt_thresh=224

# DESKTOP QUANTUM FOR TIMESHARE THREADS IN stathz TICKS (12) NomadBSD
  kern.sched.slice=3

# DESKTOP/IRIDIUM/CHROMIUM
  kern.ipc.shm_allow_removed=1

# SAMPLE RATE CONVERTER QUALITY (0=low .. 4=high) (1) NomadBSD
  hw.snd.feeder_rate_quality=3

# PERFORMANCE/ALL SHARED MEMORY SEGMENTS WILL BE MAPPED TO UNPAGEABLE RAM
  kern.ipc.shm_use_phys=1

# VIRTUALBOX aio(4) SETTINGS
  vfs.aio.max_buf_aio=8192
  vfs.aio.max_aio_queue_per_proc=65536
  vfs.aio.max_aio_per_proc=8192
  vfs.aio.max_aio_queue=65536

# POWER CONSUMPTION / SILENT FANS Intel 6th GEN+ / ONE LINE FOR EACH TH
# DETAILS IN THE hwpstate_intel(4) MAN PAGE
  dev.hwpstate_intel.0.epp=100
  dev.hwpstate_intel.1.epp=100
  dev.hwpstate_intel.2.epp=100
  dev.hwpstate_intel.3.epp=100
  dev.hwpstate_intel.4.epp=100
  dev.hwpstate_intel.5.epp=100
  dev.hwpstate_intel.6.epp=100
  dev.hwpstate_intel.7.epp=100

# NETWORK/DO NOT SEND RST ON SEGMENTS TO CLOSED PORTS
  net.inet.tcp.blackhole=2

# NETWORK/DO NOT SEND PORT UNREACHABLES FOR REFUSED CONNECTS
  net.inet.udp.blackhole=1

# NETWORK/LIMIT ON SYN/ACK RETRANSMISSIONS (3)
  net.inet.tcp.syncache.rexmtlimit=0

# NETWORK/USE TCP SYN COOKIES IF THE SYNCACHE OVERFLOWS (1)
  net.inet.tcp.syncookies=0

# NETWORK/ASSIGN RANDOM ip_id VALUES (0)
  net.inet.ip.random_id=1

# NETWORK/ENABLE SENDING IP REDIRECTS (1)
  net.inet.ip.redirect=0

# NETWORK/IGNORE ICMP REDIRECTS (0)
  net.inet.icmp.drop_redirect=1

# NETWORK/DROP TCP PACKETS WITH SYN+FIN SET (0)
  net.inet.tcp.drop_synfin=1

# NETWORK/RECYCLE CLOSED FIN_WAIT_2 CONNECTIONS FASTER (0)
  net.inet.tcp.fast_finwait2_recycle=1

# NETWORK/CERTAIN ICMP UNREACHABLE MESSAGES MAY ABORT CONNECTIONS IN SYN_SENT (1)
  net.inet.tcp.icmp_may_rst=0

The biggest difference for ThinkPad T14 against the ThinkPad W520 is this part below.

# POWER CONSUMPTION / SILENT FANS Intel 6th GEN+ / ONE LINE FOR EACH TH
# DETAILS IN THE hwpstate_intel(4) MAN PAGE
  dev.hwpstate_intel.0.epp=100
  dev.hwpstate_intel.1.epp=100
  dev.hwpstate_intel.2.epp=100
  dev.hwpstate_intel.3.epp=100
  dev.hwpstate_intel.4.epp=100
  dev.hwpstate_intel.5.epp=100
  dev.hwpstate_intel.6.epp=100
  dev.hwpstate_intel.7.epp=100

It was not needed/non existent on the ThinkPad W520 hardware.

Now the boot parameters /boot/loader.conf file.

% cat /boot/loader.conf
# CONSOLE COMMON
  autoboot_delay=2       # OPT. '-1' => NO WAIT | OPT. 'NO' => INFINITE WAIT
  hw.usb.no_boot_wait=1  # DO NOT WAIT FOR USB DEVICES FOR ROOT (/) FILESYSTEM
  boot_mute=YES          # LIKE '-m' IN LOADER - MUTE CONSOLE WITH FreeBSD LOGO
  loader_logo=none       # DESIRED LOGO OPTIONS: fbsdbw beastiebw beastie none
  loader_menu_frame="none"
  screen.font="6x12"

# CONSOLE RESOLUTION
  kern.vt.fb.default.mode="1920x1080"
  efi_max_resolution="1920x1080"

# WINE FIX
  machdep.max_ldt_segment=2048

# MODULES - BOOT
  aesni_load=YES
  geom_eli_load=YES
  cryptodev_load=YES
  zfs_load=YES

# drm-kmod PACKAGE - USE SEMAPHORES FOR INTER-RING SYNC
  compat.linuxkpi.semaphores=1

# drm-kmod PACKAGE - ENABLE POWER-SAVING RENDER C-STATE 6
  compat.linuxkpi.enable_rc6=7

# drm-kmod PACKAGE - ENABLE POWER-SAVING DISPLAY C-STATES
  compat.linuxkpi.enable_dc=2

# drm-kmod PACKAGE - ENABLE FRAME BUFFER COMPRESSION FOR POWER SAVINGS
  compat.linuxkpi.enable_fbc=1

# ENABLE SYNAPTICS
  hw.psm.synaptics_support=1

# DISABLE /dev/diskid/* ENTRIES FOR DISKS
  kern.geom.label.disk_ident.enable=0

# DISABLE /dev/gptid/* ENTRIES FOR DISKS
  kern.geom.label.gptid.enable=0

# TERMINAL vt(4) COLORS
  kern.vt.color.0.rgb="#000000"
  kern.vt.color.1.rgb="#dc322f"
  kern.vt.color.2.rgb="#859900"
  kern.vt.color.3.rgb="#b58900"
  kern.vt.color.4.rgb="#268bd2"
  kern.vt.color.5.rgb="#ec0048"
  kern.vt.color.6.rgb="#2aa198"
  kern.vt.color.7.rgb="#94a3a5"
  kern.vt.color.8.rgb="#586e75"
  kern.vt.color.9.rgb="#cb4b16"
  kern.vt.color.10.rgb="#859900"
  kern.vt.color.11.rgb="#b58900"
  kern.vt.color.12.rgb="#268bd2"
  kern.vt.color.13.rgb="#d33682"
  kern.vt.color.14.rgb="#2aa198"
  kern.vt.color.15.rgb="#6c71c4"

# RACCT/RCTL RESOURCE LIMITS
  kern.racct.enable=1

# DISABLE ZFS PREFETCH
  vfs.zfs.prefetch_disable=1

# POWER MGMT / POWER OFF DEVICES WITHOUT ATTACHED DRIVER
  hw.pci.do_power_nodriver=3

# POWER MANAGEMENT FOR EVERY USED AHCI CHANNEL (ahcich 0-7)
  hint.ahcich.0.pm_level=5
  hint.ahcich.1.pm_level=5
  hint.ahcich.2.pm_level=5
  hint.ahcich.3.pm_level=5
  hint.ahcich.4.pm_level=5
  hint.ahcich.5.pm_level=5
  hint.ahcich.6.pm_level=5
  hint.ahcich.7.pm_level=5

# GELI THREADS
  kern.geom.eli.threads=4

Now the mentioned /etc/devfs.rules file.

% cat /etc/devfs.rules
[desktop=10]
add path 'acd*'      mode 0660 group operator
add path 'cd*'       mode 0660 group operator
add path 'da*'       mode 0660 group operator
add path 'pass*'     mode 0660 group operator
add path 'xpt*'      mode 0660 group operator
add path 'fd*'       mode 0660 group operator
add path 'md*'       mode 0660 group operator
add path 'uscanner*' mode 0660 group operator
add path 'lpt*'      mode 0660 group cups
add path 'ulpt*'     mode 0660 group cups
add path 'unlpt*'    mode 0660 group cups
add path 'ugen*'     mode 0660 group operator
add path 'usb/*'     mode 0660 group operator
add path 'video*'    mode 0660 group operator
add path 'cuse*'     mode 0660 group operator

Filesystems and SWAP configuration.

% cat /etc/fstab
# SWAP
  /dev/gpt/swap0  none  swap  sw  0 0

# FreeBSD PSEUDO - NEEDED BY wine(1)
  procfs  /proc  procfs  rw  0 0

# Ubuntu Linux PSEUDO
  linprocfs  /compat/ubuntu/proc     linprocfs  rw,late                    0 0
  linsysfs   /compat/ubuntu/sys      linsysfs   rw,late                    0 0
  devfs      /compat/ubuntu/dev      devfs      rw,late                    0 0
  fdescfs    /compat/ubuntu/dev/fd   fdescfs    rw,late,linrdlnk           0 0
  tmpfs      /compat/ubuntu/dev/shm  tmpfs      rw,late,size=1g,mode=1777  0 0
  /home      /compat/ubuntu/home     nullfs     rw,late                    0 0
  /tmp       /compat/ubuntu/tmp      nullfs     rw,late                    0 0

Terminals configuration under /etc/ttys file. Important part is the ttyv4 entry to match the xdm_tty=ttyv4 value from /etc/rc.conf file.

% grep '^[^#]' /etc/ttys | cat
console none                            unknown off insecure
ttyv0   "/usr/libexec/getty Pc"         xterm   onifexists secure
ttyv1   "/usr/libexec/getty Pc"         xterm   onifexists secure
ttyv2   "/usr/libexec/getty Pc"         xterm   onifexists secure
ttyv3   "/usr/libexec/getty Pc"         xterm   onifexists secure
ttyv4   "/usr/libexec/getty Pc"         xterm   off secure
ttyv5   "/usr/libexec/getty Pc"         xterm   off secure
ttyv6   "/usr/libexec/getty Pc"         xterm   off secure
ttyv7   "/usr/libexec/getty Pc"         xterm   off secure
ttyv4   "/usr/local/bin/xdm -nodaemon"  xterm   off secure
ttyu0   "/usr/libexec/getty 3wire"      vt100   onifconsole secure
ttyu1   "/usr/libexec/getty 3wire"      vt100   onifconsole secure
ttyu2   "/usr/libexec/getty 3wire"      vt100   onifconsole secure
ttyu3   "/usr/libexec/getty 3wire"      vt100   onifconsole secure
dcons   "/usr/libexec/getty std.9600"   vt100   off secure
xc0     "/usr/libexec/getty Pc"         xterm   onifconsole secure
rcons   "/usr/libexec/getty std.9600"   vt100   onifconsole secure

I kept wireless config in /etc/rc.conf file this time – it does conflicts with my own network.sh solution to connect to various both wire and wireless networks – FreeBSD Network Management with network.sh Script – described in details here.

# cat /etc/wpa_supplicant.conf
# GENERAL
eapol_version=2
ap_scan=1
fast_reauth=1

# OPEN NETWORKS
network={
  key_mgmt=NONE
  priority=0
}

# NETWORK WITH HIDDEN SSID
network={
  scan_ssid=1
  ssid="hidden-network"
  psk="12341234"
  priority=0
}

# NAMED OPEN NETWORK
network={
  ssid="Free_Internet"
  key_mgmt=NONE
  priority=0
}

# NORMAL WPA/WPA2 SECURED NETWORK
network={
  ssid="SECURED"
  psk="12345678"
}

The automount(8) config.

% cat /usr/local/etc/automount.conf
  USERUMOUNT=YES
  USER=vermaden
  FM='caja --no-desktop'
  NICENAMES=YES

The doas(1) configuration.

# cat /usr/local/etc/doas.conf
# CORE
  permit nopass keepenv root     as root
  permit nopass keepenv vermaden as root

# THE network.sh SCRIPT
  # pw groupmod network -m YOURUSERNAME
  # cat /usr/local/etc/doas.conf
  permit nopass :network as root cmd /etc/rc.d/netif args onerestart
  permit nopass :network as root cmd /usr/sbin/service args squid onerestart
  permit nopass :network as root cmd dhclient
  permit nopass :network as root cmd ifconfig
  permit nopass :network as root cmd killall args -9 dhclient
  permit nopass :network as root cmd killall args -9 ppp
  permit nopass :network as root cmd killall args -9 wpa_supplicant
  permit nopass :network as root cmd ppp
  permit nopass :network as root cmd route
  permit nopass :network as root cmd tee args -a /etc/resolv.conf
  permit nopass :network as root cmd tee args /etc/resolv.conf
  permit nopass :network as root cmd umount
  permit nopass :network as root cmd wpa_supplicant

Groups I am member of.

% id vermaden | tr ' ' '\n' | tr ',' '\n'
uid=1000(vermaden)
gid=1000(vermaden)
groups=1000(vermaden)
0(wheel)
5(operator)
44(video)
69(network)
145(webcamd)
920(vboxusers)

I also do not rely on ‘stock’ fan speeds and set my own speeds according to CPU temperature with acpi-thinkpad-fan.sh script.

X11

While X11 did not need any custom configuration and it worked out of the box – I have done two things to make it work slightly differently.

First one is to allow CTRL+ALT+BACKSPACE fast way to restart X11.

t14 % cat /usr/local/etc/X11/xorg.conf.d/flags.conf
Section "ServerFlags"
  Option "DontZap" "off"
EndSection

The other one is to enable Tap to Click and Natural Scrolling on a Synaptics touchpad.

t14 % cat /usr/local/etc/X11/xorg.conf.d/touchpad.conf
Section "InputClass"
  Identifier "touchpad"
  MatchIsTouchpad "on"
  Driver "libinput"
  Option "Tapping" "on"
  Option "NaturalScrolling" "on"
EndSection

Comparison to ThinkPad W520

I compared the two laptops. While ThinkPad W520 is heavy and bulky the ThinkPad T14 (GEN1) is light and slim. They both have similar 5 hours battery time on FreeBSD.

You can see the screen brightness comparison between these two below.

LARGE-compare-screen-brightness

The ThinkPad T14 (GEN1) has several flavors of the FullHD screen – check reviews and specs for details. For the record – ThinkPad W520 is on the left.

Below you will find size comparisons.

The view from the top.

LARGE-compare-top

View from the side.

LARGE-compare-side

… and from the side one over another.

LARGE-compare-over

Desktop Environment

Openbox

As for the ‘desktop environment’ that I use – its my custom setup with Openbox along with tools like Tint2 and Dzen2 – for the most basic setup. The screenshot is from FreeBSD 11.1 but it looks exactly the same today.

freebsd-desktop-2019-04

I described this setup in details in the entire FreeBSD Desktop series.

XFCE

I have also tried XFCE – I liked it especially with the Global Menu appmenu plugin. You go this way with this XFCE Cupertino Way handy guide.

xfce-ghostbsd

GNOME

I also tried GNOME for a test – it did not suit me well so I went back to my Openbox setup – but You may find it more comfortable to use. Here is the FreeBSD GNOME 3 Fast Track article that will help you with that.

gnome-8-fixed

Temperatures

I used mine sensors.sh script for that – results below.

t14 # sensors.sh

            BATTERY/AC/TIME/FAN/SPEED
 ------------------------------------
             dev.acpi_ibm.0.fan_level: 1
             dev.acpi_ibm.0.fan_speed: 65535
                   dev.acpi_ibm.0.fan: 0
               dev.cpu.0.cx_supported: C1/1/1 C2/2/151 C3/3/1034
                   dev.cpu.0.cx_usage: 9.02% 35.95% 55.02% last 35us
                       dev.cpu.0.freq: 802
                       hw.acpi.acline: 0
                 hw.acpi.battery.life: 99
                 hw.acpi.battery.time: 275
                hw.acpi.cpu.cx_lowest: C8
                            powerd(8): running

                  SYSTEM/TEMPERATURES
 ------------------------------------
                dev.cpu.0.temperature: 38.0C (max: 100.0C)
                dev.cpu.1.temperature: 39.0C (max: 100.0C)
                dev.cpu.2.temperature: 39.0C (max: 100.0C)
                dev.cpu.3.temperature: 39.0C (max: 100.0C)
                dev.cpu.4.temperature: 40.0C (max: 100.0C)
                dev.cpu.5.temperature: 41.0C (max: 100.0C)
                dev.cpu.6.temperature: 38.0C (max: 100.0C)
                dev.cpu.7.temperature: 38.0C (max: 100.0C)
           dev.pchtherm.0.temperature: 46.0C
      hw.acpi.thermal.tz0.temperature: 46.1C (max: 128.1C)

                   DISKS/TEMPERATURES
 ------------------------------------
             smart.nvme0.temperature:: 44.0C

Accessories

There are some accessories that are very handy with the ThinkPad T14 laptop – I will describe them below.

Power Supply

You can use the default ThinkPad T14 power supply and you can also use any USB-C power delivery charger – that is nice addition.

Mouse Companion

After checking many mouse models – as described in the UNIX Mouse Shootout article – I finally settled with Logitech Triathlon M720 mouse. I have plugged the Lenovo USB Receiver into the back ‘powered’ USB port. While I use that mouse over the USB receiver you can also connect it using Bluetooth – also to other computers. This mouse has a special dedicated button to switch between 3 different computers. Unfortunately the copy-paste between them does not work πŸ™‚

mouse-M720

Battery

Some battery details below.

t14 % acpiconf -i 0
Design capacity:        50450 mWh
Last full capacity:     45760 mWh
Technology:             secondary (rechargeable)
Battery Swappable Capability:   Non-swappable
Design voltage:         11520 mV
Capacity (warn):        2288 mWh
Capacity (low):         200 mWh
Cycle Count:            204
Mesurement Accuracy:    95 %
Max Average Interval:   1000 ms
Min Average Interval:   500 ms
Low/warn granularity:   -1 mWh
Warn/full granularity:  -1 mWh
Model number:           5B10W13906
Serial number:           1071
Type:                   LiP
OEM info:               SMP
State:                  discharging
Remaining capacity:     99%
Remaining time:         4:31
Present rate:           10094 mW
Present voltage:        12681 mV

Experience

Today I ‘recognize’ three laptop keyboard layouts.

  • Best in class 7-row keyboards with INS/DEL and HOME/END and PGUP/PGDN keys block on the right top side.
  • Least PITA ThinkPad T14 like keyboards where PGUP/PGDN keys are in the ARROWS area and HOME/END/INS/DEL block is provided on the top right part.
  • Everything else that I treat like shit.

My fingers do not remember this HOME/END/INS/DEL block that much well – but at its still several ways of magnitude better then any Macbook keyboard layout.

Summary

I will still use mine ThinkPad W520 daily – I still do not need to move to other/less old laptop.

As you can see FreeBSD works quite well with modern laptops – hope someone can find that article useful.

UPDATE 1 – WiFi Works with FreeBSD 14.0-BETA1

As the FreeBSD 14.0-RELEASE is approaching completion I checked again the ThinkPad T14 WiFi with newer FreeBSD version. I am happy to report that now – with 14.0-BETA1 version of FreeBSD – the WiFi works. The iwlwifi(4) driver now successfully works. There is only one downside – its very slow – usable for browsing the Internet and stuff – but slow.

My ThinkPad W520 has Intel Centrino Ultimate-N 6300 WiFi card supported by the iwn(4) driver. This card was introduced in 2011 – 12 years ago. With that old Intel 6300 card I am able to reach 12 MB/s speed both for upload and download speeds on FreeBSD – using 802.11g mode as 802.11n is not (yet) supported on FreeBSD.

The Intel Comet Lake CNVi WiFi card from 2019 on ThinkPad T14 with current state of iwlwifi(4) driver allows about 500 KB/s for upload and 2.5 MB/s for download.

Still better then attaching the additional USB WiFi adapter or device passthru to Bhyve hypervisor for wifibox workaround πŸ™‚

EOF

Connect FreeBSD 13.2 to FreeIPA/IDM

About half a year ago I wrote about how to Connect FreeBSD to FreeIPA/Red Hat Identity Management with available then FreeBSD 13.1-RELEASE version. Time flies and we have newer FreeBSD release around the corner. FreeBSD 13.2 is currently at RC5 level and I believe we should see 13.2-RELEASE official announcement within hours – but even if it would take RC6 and RELEASE being available in weeks later – the instructions will not change for this setup.

This guide will focus only on FreeBSD part of configuring and building packages with needed options to make it connect (and work with) FreeIPA/IDM properly. To have a working FreeIPA/IDM server you need to do instructions from the FreeIPA section of the mentioned above article – up to the FreeBSD Client section. Then – when specified in the article – also the Finish Setup with Web Browser in FreeIPA/IDM Page section needs to be done from the earlier article.

In other words – this article updates the FreeBSD Client section with instructions to use latest upcoming FreeBSD 13.2-RELEASE and newer up-to-date packages versions.

One note about conventions (and colors).

% command                            // command executed on local system
[root@idm ~]# command                // command executed on FreeIPA/IDM server
# diff Makefile.OLD Makefile         // command executed on FreeBSD client system
< krb5>=1.10:security/krb5 \         // parts of configs/commands are colored for better visibility
> krb5-119>=1.10:security/krb5-119 \ // parts of configs/commands are colored for better visibility

FreeBSD Client

We will use these software versions as shown below.

# pkg info | grep -e krb -e sudo -e sssd -e openldap -e samba -e cyrus -e mkhomedir
cyrus-sasl-2.1.28           RFC 2222 SASL (Simple Authentication and Security Layer)
cyrus-sasl-gssapi-2.1.28    SASL GSSAPI authentication plugin
krb5-119-1.19.4             MIT implementation of RFC 4120 network authentication service
openldap26-client-2.6.4     Open source LDAP client implementation
pam_mkhomedir-0.2           Create HOME with a PAM module on demand
samba413-4.13.17_4          Free SMB/CIFS and AD/DC server and client for Unix
sssd-1.16.5_8               System Security Services Daemon
sudo-1.9.13p3               Allow others to run commands as root

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

# cat /etc/rc.conf
  hostname="fbsd132.vercorp.org"
  ifconfig_em0="inet 10.0.0.50/24"
  defaultrouter="10.0.0.1"
  clear_tmp_enable=YES
  syslogd_flags="-ss"
  sshd_enable=YES
  dumpdev=AUTO
  zfs_enable=YES
  ntpd_enable=YES
  sssd_enable="YES"
  rc_info=NO
  rc_startmsgs=NO

FreeBSD Packages

UPDATE: Instead of building these package by hand you may use the latest FreeBSD on FreeIPA/IDM with Poudriere Repo guide instead.

We will fetch up-to-date FreeBSD Ports tree.

# portsnap auto

We will also configure make(1) to store all its compilation results under /usr/ports/obj dir.

# cat << EOF > /etc/make.conf
WRKDIRPREFIX=/usr/ports/obj
EOF

We will switch to latest branch of pkg(8) packages.

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

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

We will install packages that are needed for compilation and also essential pam_mkhomedir package.

# pkg install -y \
    autoconf \
    automake \
    bind-tools \
    c-ares \
    cmocka \
    dialog4ports \
    ding-libs \
    docbook-xsl \
    gettext-tools \
    gmake \
    ldb22 \
    libtool \
    libxslt \
    m4 \
    nss \
    pcre \
    pkgconf \
    pam_mkhomedir

Now we will install our ‘core’ packages – and delete them right after – to waste less time on compilation.

# pkg install   -y krb5-119 sudo cyrus-sasl cyrus-sasl-gssapi openldap26-client samba413

# pkg delete -f -y krb5-119 sudo cyrus-sasl cyrus-sasl-gssapi openldap26-client samba413

# pkg install   -y krb5-119

By default the security/krb5-119 package is built without LDAP option. This is what we need for this step. We will later rebuild it with LDAP option.

In case something changed between posting that article and LDAP option being included or not in the security/krb5-119 package – below are instructions to rebuild it without LDAP option.

# cd /usr/ports/security/krb5-119

# make config
[ ] LDAP

# make build deinstall install

Now we need to rebuild security/cyrus-sasl2-gssapi package with GSSAPI_MIT option enabled.

# cd /usr/ports/security/cyrus-sasl2-gssapi

# make config
(x) GSSAPI_MIT

# make build deinstall install

Next rebuild the net/openldap26-client package with GSSAPI option enabled.

# cd /usr/ports/net/openldap26-client

# make config
[x] GSSAPI

# make build deinstall install

Next we are back to security/krb5-119 package and now it needs to be rebuilt with LDAP option.

# cd /usr/ports/security/krb5-119

# make config
[x] LDAP

# make build deinstall install

Now with security/sssd we will need a small patch because without it security/sssd will try to use newer security/krb5-120 package – which does not work with FreeIPA/IDM for now.

# cd /usr/ports/security/sssd

# cp Makefile Makefile.OLD

# sed -i '' 's|krb5>=1.10:security/krb5|krb5-119>=1.10:security/krb5-119|g' Makefile

# diff Makefile.OLD Makefile
32c32
<               krb5>=1.10:security/krb5 \
---
>               krb5-119>=1.10:security/krb5-119 \


Now the rebuild instructions.

# cd /usr/ports/security/sssd

# make config
[x] SMB

# make build deinstall install

Now we need to delete security/sssd and security/sudo packages to rebuild them again … yes its stupid.

# pkg delete -f sudo sssd

We now need to build and install security/sudo without PAM option and with SSSD option and with GSSAPI_MIT option enabled.

# cd /usr/ports/security/sudo

# make config
[ ] PAM
[x] SSSD
--- Kerberos 5 Authentication
(*) GSSAPI_MIT

# make build deinstall install

FreeBSD Setup

We now move to the configuration process as we have our packages installed.

Create needed dirs.

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

Set system hostname.

# grep hostname /etc/rc.conf
  hostname="fbsd132.vercorp.org"

# hostname fbsd132.vercorp.org

# hostname
fbsd132.vercorp.org

# cat << EOF > /etc/hosts
::1             localhost localhost.my.domain
127.0.0.1       localhost localhost.my.domain
10.0.0.50       fbsd132.vercorp.org fbsd132
10.0.0.40       idm.vercorp.org idm
EOF

# cat /etc/hosts
::1             localhost localhost.my.domain
127.0.0.1       localhost localhost.my.domain
10.0.0.50       fbsd132.vercorp.org fbsd132
10.0.0.40       idm.vercorp.org idm

Fetch the FreeIPA/IDM certificate.

# fetch -o /usr/local/etc/ipa/ca.crt http://10.0.0.40/ipa/config/ca.crt
/usr/local/etc/ipa/ca.crt                             1635  B 8227 kBps    00s

FreeIPA/IDM Setup Part

We now need to execute instructions on /IDM to connect FreeBSD to it.

Add A and PTR DNS records for our 10.0.0.50 IP address with fbsd132.vercorp.org hostname.

We also need to generate key for fbsd132.vercorp.org system.

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

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

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

[root@idm ~]# ipa-getkeytab -s idm.vercorp.org \
                            -p host/[email protected] \
                            -k /root/fbsd132.vercorp.org.keytab
Keytab successfully retrieved and stored in: /root/fbsd132.vercorp.org.keytab

[root@idm ~]# cp \
                /root/fbsd132.vercorp.org.keytab \
                /usr/share/ipa/html/fbsd132.vercorp.org.keytab

[root@idm ~]# chmod 644 /usr/share/ipa/html/fbsd132.vercorp.org.keytab

Now we will get fbsd132.vercorp.org system key from FreeIPA/IDM server.

# fetch -o /usr/local/etc/ipa/krb5.keytab http://10.0.0.40/ipa/config/fbsd132.vercorp.org.keytab
/usr/local/etc/ipa/krb5.keytab                         176  B  975 kBps    00s

# chmod 600 /usr/local/etc/ipa/krb5.keytab

Now we will move to creating needed config files.

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/
#SIZELIMIT  12
#TIMELIMIT  15
#DEREF      never
SASL_MECH   GSSAPI
SASL_REALM  VERCORP.ORG
ssl         start_tls
TLS_CACERT  /usr/local/etc/ipa/ca.crt
EOF

… and /etc/krb5.conf file.

# cat << EOF > /etc/krb5.conf
[libdefaults]
  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

[realms]
  VERCORP.ORG = {
    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
}

[domain_realm]
  .vercorp.org = VERCORP.ORG
  vercorp.org = VERCORP.ORG

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

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

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

[domain/vercorp.org]
# 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 = fbsd132.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

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

[nss]
filter_users = root,toor
homedir_substring = /usr/home/%u

[pam]

[sudo]
# debug_level = 0x3ff0

[ssh]
EOF

# 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

Now we need modify several FreeBSD Base System files such as /etc/nsswitch.conf or PAM and SSH configuration.

# cat << EOF > /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
EOF

The /etc/pam.d/system file.

# cat << EOF > /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
EOF

The /etc/pam.d/sshd file.

# cat << EOF > /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
EOF

The /etc/ssh/ssh_config file.

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

The /etc/ssh/sshd_config file.

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

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

# service sssd enable
# service sssd start

Now … go to the original Connect FreeBSD to FreeIPA/Red Hat Identity Management article and ‘do’ the Finish Setup with Web Browser in FreeIPA/IDM Page section instructions – all the way up to the FreeBSD FreeIPA Login Test section.

FreeBSD FreeIPA Login Test

Now we can try to login to our FreeBSD client … but first several other things.

If you just created your ‘regular’ FreeIPA/IDM user – you need to set a permanent password for it. Its not possible by first logging to the FreeBSD system. You will get following error on the FreeBSD client.

# grep sshd /var/log/messages
(...)
Mar 24 20:51:46 fbsd132 [sssd[krb5_child[779]]][779]: Password has expired
(...)

You need to change this password by logging into the FreeIPA/IDM Linux system. Here is how.

% ssh 10.0.0.40 -l vermaden
([email protected]) Password:
([email protected]) Password expired. Change your password now.
Current Password:
([email protected]) New password:
([email protected]) Retype new password:
Could not chdir to home directory /home/vermaden: No such file or directory
[vermaden@idm /]$ exit

Another thing – make sure that time is synchronized between the client and FreeIPA/IDM systems – you will get following error on the FreeBSD client if they are not in sync.

# grep sssd /var/log/messages
(...)
Mar 24 20:51:46 fbsd132 [sssd[krb5_child[779]]][779]: Clock skew too great
(...)

… or …

PAM: User account has expired for vermaden from 10.0.0.3

Here is fast way to sync their times against pool.ntp.org host.

Feel free to setup some permanent time sync solution on both of them. You can also enable NTP server on FreeIPA/IDM during its configuration and sync all FreeIPA/IDM clients against it.

# ntpdate pool.ntp.org

# date
Wed Mar 29 10:34:14 CEST 2023

[root@idm ~]# chronyd -q 'server pool.ntp.org iburst' || chronyc -a 'burst 4/4'

[root@idm ~]# date
Wed Mar 29 10:34:14 CEST 2023

Now we can finally login to our FreeBSD client.

% ssh 10.0.0.50 -l vermaden
([email protected]) Password:

vermaden@fbsd132:~ $ uname -prism
FreeBSD 13.2-RC3 amd64 amd64 GENERIC

vermaden@fbsd132:~ $ grep $( whoami ) /etc/passwd

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


Done. Seems to work properly.

Latest Samba 4.16

You can also use latest Samba 4.16 version instead of the 4.13 default one.

The needed changes are below – to be executed before package building.

# cat << EOF >> /etc/make.conf
# net/samba416
DEFAULT_VERSIONS+=samba=4.16
EOF

Rebuilding process for net/samba416 package.

# cd /usr/ports/net/samba416

# make config
(*) GSSAPI_MIT

# make build deinstall install

Feel free to share your thoughts on this in the comments section.

EOF

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).

FreeIPA-logo

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

logo-freebsd

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

FreeIPA

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
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
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.

RAM: 4GB
CPU: 2
HDD: 10GB
DNS: fully qualified domain name for FreeIPA
     must be resolvable from DNS server configured in system

For this installation I have used the 10.0.0.0/24 network.

The FreeIPA/IDM server will get the 10.0.0.40 IP.

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

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

The FreeIPA/IDM FreeBSD client fbsdjail.vercorp.org will get the 10.0.0.43 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.

      IP: 10.0.0.40/24
      GW: 10.0.0.1
     DNS: 1.1.1.1
hostname: idm.vercorp.org
  domain: vercorp.org
   realm: VERCORP.ORG

FreeBSD fbsd.vercorp.org system.

      IP: 10.0.0.42/24
      GW: 10.0.0.1
hostname: fbsd.vercorp.org

FreeBSD Jail fbsdjail.vercorp.org system.

      IP: 10.0.0.43/24
      GW: 10.0.0.1
hostname: fbsdjail.vercorp.org

If you are curious what is hidden in the 10.0.0.42 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
NAME=enp0s3
DEVICE=enp0s3
TYPE=Ethernet
BOOTPROTO=none
UUID=b49cd1ab-d3eb-421d-b408-c052acc077da
ONBOOT=yes
IPADDR=10.0.0.40
NETMASK=255.255.255.0
GATEWAY=10.0.0.1
IPV6INIT=no
DNS1=1.1.1.1
PROXY_METHOD=none
BROWSER_ONLY=no
DEFROUTE=yes
IPV4_FAILURE_FATAL=no

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
# DISABLE IPv6 FOR MAIN enp0s3 INTERFACE
net.ipv6.conf.enp0s3.disable_ipv6=1
EOF

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
10.0.0.40   idm.vercorp.org idm

[root@idm ~]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
10.0.0.40   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
=====================================================================================================

Complete!

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.
Complete!

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] \
    --unattended

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): 10.0.0.40
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
Done.
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..
Done.
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
Realm: 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
[email protected]                          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
[domain/vercorp.org]

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
[sssd]
services = nss, pam, ifp, ssh, sudo

domains = vercorp.org
[nss]
homedir_substring = /home
memcache_timeout = 600

[pam]

[sudo]

[autofs]

[ssh]

[pac]

[ifp]
allowed_uids = ipaapi, root

[session_recording]

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 http://10.0.0.40 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.

FreeIPA-login-page

FreeIPA-login

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

FreeBSD Client

UPDATE: Newer instructions for FreeBSD 13.2-RELEASE are available at the Connect FreeBSD 13.2 to FreeIPA/IDM article.

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
hostname="fbsd"
ifconfig_vtnet0="inet 10.0.0.42 netmask 255.255.255.0"
defaultrouter="10.0.0.1"
sshd_enable="YES"
moused_enable="YES"
dumpdev="AUTO"
zfs_enable="YES"
syslogd_flags="-ss"
sssd_enable="YES"

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*
        PYTHON2 PYTHON3 RUBY RUST SAMBA SSL TCLTK VARNISH
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
WRKDIRPREFIX=${PORTSDIR}/obj

OPTIONS_UNSET=       DOCS EXAMPLES DEBUG X11
OPTIONS_UNSET+=      DBUS GSSAPI_BASE GSSAPI_HEIMDAL
OPTIONS_SET+=        GSSAPI_MIT
WITH_GSSAPI=         yes
WANT_OPENLDAP_SASL=  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 \
         /usr/ports/net/openldap26-client
do
  make -C ${I} rmconfig
done

# \
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 \
         /usr/ports/net/openldap26-client
do
  make -C ${I} config-recursive
done

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
_OPTIONS_READ=sudo-sssd-1.9.11p3
_FILE_COMPLETE_OPTIONS_LIST=AUDIT DISABLE_AUTH DISABLE_ROOT_SUDO DOCS EXAMPLES INSULTS LDAP NLS NOARGS_SHELL OPIE PAM PYTHON SSSD GSSAPI_BASE GSSAPI_HEIMDAL GSSAPI_MIT
OPTIONS_FILE_SET+=AUDIT
OPTIONS_FILE_SET+=GSSAPI_MIT
OPTIONS_FILE_SET+=LDAP
OPTIONS_FILE_SET+=NLS
OPTIONS_FILE_SET+=SSSD
OPTIONS_FILE_UNSET+=DISABLE_AUTH
OPTIONS_FILE_UNSET+=DISABLE_ROOT_SUDO
OPTIONS_FILE_UNSET+=DOCS
OPTIONS_FILE_UNSET+=EXAMPLES
OPTIONS_FILE_UNSET+=GSSAPI_BASE
OPTIONS_FILE_UNSET+=GSSAPI_HEIMDAL
OPTIONS_FILE_UNSET+=INSULTS
OPTIONS_FILE_UNSET+=NOARGS_SHELL
OPTIONS_FILE_UNSET+=OPIE
OPTIONS_FILE_UNSET+=PAM
OPTIONS_FILE_UNSET+=PYTHON

# cat /var/db/ports/security_sssd/options
_OPTIONS_READ=sssd-1.16.5_6
_FILE_COMPLETE_OPTIONS_LIST=DOCS SMB
OPTIONS_FILE_UNSET+=DOCS
OPTIONS_FILE_SET+=SMB

# cat /var/db/ports/security_cyrus-sasl2/options
_OPTIONS_READ=cyrus-sasl-2.1.28
_FILE_COMPLETE_OPTIONS_LIST=ALWAYSTRUE AUTHDAEMOND DOCS KEEP_DB_OPEN  OBSOLETE_CRAM_ATTR OBSOLETE_DIGEST_ATTR  SASLDB_IN_VAR BDB1 BDB GDBM LMDB ANONYMOUS CRAM DIGEST LOGIN NTLM OTP PLAIN SCRAM
OPTIONS_FILE_SET+=ANONYMOUS
OPTIONS_FILE_SET+=AUTHDAEMOND
OPTIONS_FILE_SET+=BDB1
OPTIONS_FILE_SET+=CRAM
OPTIONS_FILE_SET+=DIGEST
OPTIONS_FILE_SET+=LOGIN
OPTIONS_FILE_SET+=NTLM
OPTIONS_FILE_SET+=OBSOLETE_CRAM_ATTR
OPTIONS_FILE_SET+=OBSOLETE_DIGEST_ATTR
OPTIONS_FILE_SET+=OTP
OPTIONS_FILE_SET+=PLAIN
OPTIONS_FILE_SET+=SCRAM
OPTIONS_FILE_UNSET+=ALWAYSTRUE
OPTIONS_FILE_UNSET+=BDB
OPTIONS_FILE_UNSET+=DOCS
OPTIONS_FILE_UNSET+=GDBM
OPTIONS_FILE_UNSET+=KEEP_DB_OPEN
OPTIONS_FILE_UNSET+=LMDB
OPTIONS_FILE_UNSET+=SASLDB_IN_VAR

# cat /var/db/ports/net_openldap26-client/options
_OPTIONS_READ=openldap26-client-2.6.3
_FILE_COMPLETE_OPTIONS_LIST=DEBUG DOCS FETCH GSSAPI
OPTIONS_FILE_SET+=GSSAPI
OPTIONS_FILE_UNSET+=DEBUG
OPTIONS_FILE_UNSET+=DOCS
OPTIONS_FILE_UNSET+=FETCH

# cat /var/db/ports/security_krb5/options
# This file is auto-generated by 'make config'.
# Options for krb5-1.20
_OPTIONS_READ=krb5-1.20
_FILE_COMPLETE_OPTIONS_LIST=DNS_FOR_REALM EXAMPLES KRB5_HTML KRB5_PDF LDAP LMDB NLS READLINE LIBEDIT
OPTIONS_FILE_UNSET+=DNS_FOR_REALM
OPTIONS_FILE_UNSET+=EXAMPLES
OPTIONS_FILE_SET+=KRB5_HTML
OPTIONS_FILE_SET+=KRB5_PDF
OPTIONS_FILE_SET+=LDAP
OPTIONS_FILE_UNSET+=LMDB
OPTIONS_FILE_SET+=NLS
OPTIONS_FILE_SET+=READLINE
OPTIONS_FILE_UNSET+=LIBEDIT

… and build them.

# \
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 \
         /usr/ports/net/openldap26-client \
do
  make -C ${I} build
done

… unsinstall them and create their packages.

# \
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 \
         /usr/ports/net/openldap26-client \
do
  make -C ${I} deinstall package
done

After some time we have our built packages.

# find /usr/ports/obj/ -name \*.pkg
/usr/ports/obj/usr/ports/lang/perl5.32/work/perl-5.32.1/symbian/ext/Moped/Msg/Msg.pkg
/usr/ports/obj/usr/ports/security/pam_mkhomedir/work/pkg/pam_mkhomedir-0.2.pkg
/usr/ports/obj/usr/ports/security/cyrus-sasl2-gssapi/work/pkg/cyrus-sasl-gssapi-2.1.28.pkg
/usr/ports/obj/usr/ports/security/krb5/work/pkg/krb5-1.20.pkg
/usr/ports/obj/usr/ports/security/sudo/work/pkg/sudo-1.9.11p3.pkg
/usr/ports/obj/usr/ports/security/sssd/work-default/pkg/sssd-1.16.5_6.pkg
/usr/ports/obj/usr/ports/net/openldap26-client/work/pkg/openldap26-client-2.6.3.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
cyrus-sasl-gssapi-2.1.28.pkg
krb5-1.20.pkg
openldap26-client-2.6.3.pkg
pam_mkhomedir-0.2.pkg
sssd-smb4-1.16.5_6.pkg
sudo-sssd-1.9.11p3.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 \
    /var/db/sss

Set system hostname.

# hostname fbsd.vercorp.org

# hostname
fbsd.vercorp.org

Fetch the FreeIPA/IDM certificate.

# fetch -o /usr/local/etc/ipa/ca.crt http://10.0.0.40/ipa/config/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 10.0.0.42 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=10.0.0.42 --a-create-reverse
  Record name: fbsd
  A record: 10.0.0.42

[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/[email protected] -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 [email protected]:/root/fbsd.vercorp.org.keytab /usr/local/etc/ipa/krb5.keytab

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

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/
#SIZELIMIT  12
#TIMELIMIT  15
#DEREF      never
SASL_MECH   GSSAPI
SASL_REALM  VERCORP.ORG
ssl         start_tls
TLS_CACERT  /usr/local/etc/ipa/ca.crt
EOF

… and /etc/krb5.conf file.

# cat << EOF > /etc/krb5.conf
[libdefaults]
  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

[realms]
  VERCORP.ORG = {
    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
}

[domain_realm]
  .vercorp.org = VERCORP.ORG
  vercorp.org = VERCORP.ORG

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

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

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

[domain/vercorp.org]
# 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

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

[nss]
filter_users = root,toor
homedir_substring = /usr/home/%u

[pam]

[sudo]
# debug_level = 0x3ff0

[ssh]
EOF

# 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
EOF

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

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.

idm-1-hbac-rules-menu

idm-2-hbac-rules-freebsd

idm-3-hbac-rules-freebsd-details

… and the Sudo Rule named freebsd name.

idm-4-sudo-rules-menu

idm-5-sudo-rules-freebsd

idm-6-sudo-rules-freebsd-details

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 10.0.0.42
([email protected]) Password:
Last login: Mon Oct 24 21:06:36 2022 from 10.0.0.3
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
/home/vermaden

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 10.0.0.43 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
# GLOBAL
  exec.start = "/bin/sh /etc/rc";
  exec.stop = "/bin/sh /etc/rc.shutdown";
  exec.clean;
  exec.consolelog = "/var/log/jail_${name}_console.log";
  mount.devfs;
  host.hostname = ${name};
  path = /jail/${name};

# JAILS
  fbsdjail {
    ip4.addr = 10.0.0.43;
    host.hostname = fbsdjail.vercorp.org;
    interface = wlan0;
    allow.raw_sockets;
    allow.sysvipc;
  }
EOF

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

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

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

# cat << EOF > /jail/fbsdjail/etc/rc.conf
# DAEMONS | yes
  syslogd_flags="-ss"
  sshd_enable=YES

# OTHER
  clear_tmp_enable=YES
  clear_tmp_X=YES
  dumpdev=NO
  update_motd=NO
EOF

# 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  10.0.0.43       fbsdjail.vercorp.org          /jail/fbsdjail

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

# 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.

      IP: 10.0.0.41/24
      GW: 10.0.0.1
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 [email protected]:

[root@idm ~]# klist
Ticket cache: KCM:0
Default principal: [email protected]

Valid starting       Expires              Service principal
10/19/2022 13:33:52  10/20/2022 13:11:28  krbtgt/[email protected]

[root@idm ~]# ipa user-find
---------------
2 users matched
---------------
  User login: admin
  Last name: Administrator
  Home directory: /home/admin
  Login shell: /bin/bash
  Principal alias: [email protected], [email protected]
  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: [email protected]
  Principal alias: [email protected]
  Email address: [email protected]
  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 10.0.0.41
  Record name: rhlike
  A record: 10.0.0.41

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 "10.0.0.40   idm.vercorp.org"    >> /etc/hosts

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

client # hostnamectl set-hostname rhlike.vercorp.org

client # cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
10.0.0.40   idm.vercorp.org
10.0.0.41   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
Realm: 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: 10.0.0.41.
Missing reverse record(s) for address(es): 10.0.0.41.
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 10.0.0.41
([email protected]) Password:
([email protected]) Password expired. Change your password now.
Current Password:
([email protected]) New password:
([email protected]) Retype new password:
Last failed login: Wed Oct 19 00:47:57 CEST 2022 from 10.0.0.3 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    10.0.0.3         00:40   58.00s  0.03s  0.03s -bash
vermaden pts/1    10.0.0.3         00:48    0.00s  0.02s  0.01s w

[vermaden@rhlike ~]$ sudo su -

[root@rhlike ~]# getent passwd admin
admin:*:1896600000:1896600000:Administrator:/home/admin:/bin/bash

[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 πŸ™‚

Regards.

EOF

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.

mp3splt

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.

Brasero

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.

brasero.1

brasero.2

… 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.

mp3split

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
      do
        seq 0 10 50 \
          | while read SEC
            do
              echo ${MIN}:${SEC}
            done
      done > list.txt

% head list.txt
0:0
0:10
0:20
0:30
0:40
0:50
10:0
10:10
10:20
10:30

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
#!/bin/bash

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: -
Usage:
  mp3split [OPTIONS] inputaudio tracklist
Options:
  -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
^C

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 @@
   outfile="$tracktitle.$ext"

   # 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
^C

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.

code.fixed

Here is the __usage() contents by the way.

help

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
LARGE-AUDIO-FILE/LARGE-AUDIO-FILE - 001.mp3
LARGE-AUDIO-FILE/LARGE-AUDIO-FILE - 002.mp3
LARGE-AUDIO-FILE/LARGE-AUDIO-FILE - 003.mp3
LARGE-AUDIO-FILE/LARGE-AUDIO-FILE - 004.mp3
LARGE-AUDIO-FILE/LARGE-AUDIO-FILE - 005.mp3

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

% du -smc LARGE-AUDIO-FILE/*
13      LARGE-AUDIO-FILE/LARGE-AUDIO-FILE - 001.mp3
13      LARGE-AUDIO-FILE/LARGE-AUDIO-FILE - 002.mp3
13      LARGE-AUDIO-FILE/LARGE-AUDIO-FILE - 003.mp3
13      LARGE-AUDIO-FILE/LARGE-AUDIO-FILE - 004.mp3
7       LARGE-AUDIO-FILE/LARGE-AUDIO-FILE - 005.mp3
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 πŸ™‚

EOF