Tag Archives: freebsd

FreeBSD Desktop – Part 27 – Configuration – Netflix Signal Telegram

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

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

The Table of Contents for the article:

Netflix

logo-netflix

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

logo-widevine

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

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

# pkg install git-lite

# exit

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

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

logo-ubuntu

Lets run it then.

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

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

% cd linux-browser-installer

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

% ./linux-browser-installer install chrome

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

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

% /usr/local/bin/linux-chrome

app-linux-chrome

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

% doas chroot /compat/ubuntu bash

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

root@w520:/# vi /etc/hosts

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

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

app-linux-chrome-netflix

Signal

logo-signal

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

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

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

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

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

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

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

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

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

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

(...)
Errors were encountered while processing:
 libfprint-2-2:amd64
 fprintd
 libpam-fprintd:amd64
(...)

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

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

root@w520:/# apt autoremove

root@w520:/# apt install signal-desktop

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

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

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

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

app-signal-desktop

Telegram

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

logo-telegram

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

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

Here is Telegram Desktop working flawlessly under FreeBSD.

app-telegram-desktop

Summary

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

EOF

FreeBSD Desktop – Part 26 – Configuration – Conferencing and Meetings

For years I thought that online video conferencing and/or meetings would not be possible on FreeBSD. One of the first things I done on each of my laptops was to disable Camera and Microphone (along with Bluetooth) to save some battery time. While the Microphone would probably work I did not even tried to use it – did not had such needs to record anything with my laptop.

As time passed by I thought that maybe I will try what is the state of using Camera on FreeBSD and also how it is doing in the video conferencing/meetings space.

thinkpad-meet-800

I was really astonished by the results … at least on my ThinkPad W520.

The Table of Contents for the article:

  • Camera Setup
  • Microphone Setup
    • ThinkPad Microphone Easter Egg
  • Meetings
  • Closing Thoughts

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

Camera Setup

I enabled Camera and Microphone in the BIOS (leaving Bluetooth disabled) and booted up my FreeBSD 13.0 as usual.

I then installed needed packages which are:

  • multimedia/v4l-utils – Video4Linux utilities
  • multimedia/v4l_compat – Video4Linux IOCTL header files
  • multimedia/pwcview – Video4Linux PWC webcam viewer
  • multimedia/webcamd – port of Linux USB webcam and DVB drivers

We will also need to load cuse.ko kernel module at each boot. We will use /etc/rc.conf for that.

# pkg install v4l-utils v4l_compat webcamd pwcview

# vi /etc/rc.conf

  kld_list="${kld_list} cuse"

:wq

My Camera is listed at the end of the usbconfig(8) command.

% usbconfig 
ugen1.1: <0x1912 XHCI root HUB> at usbus1, cfg=0 md=HOST spd=SUPER (5.0Gbps) pwr=SAVE (0mA)
ugen2.1: <0x1033 XHCI root HUB> at usbus2, cfg=0 md=HOST spd=SUPER (5.0Gbps) pwr=SAVE (0mA)
ugen3.1: <intel ehci="" root="" hub=""> at usbus3, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=SAVE (0mA)
ugen0.1: <intel ehci="" root="" hub=""> at usbus0, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=SAVE (0mA)
ugen3.2: <vendor 0x8087="" product="" 0x0024=""> at usbus3, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=SAVE (0mA)
ugen0.2: <vendor 0x8087="" product="" 0x0024=""> at usbus0, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=SAVE (0mA)
ugen0.3: <vendor 0x0765="" product="" 0x5001=""> at usbus0, cfg=0 md=HOST spd=LOW (1.5Mbps) pwr=ON (100mA)
ugen0.4: <logitech usb="" receiver=""> at usbus0, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON (98mA)
ugen0.5: <chicony electronics="" co.,="" ltd.="" integrated="" camera=""> at usbus0, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=ON (200mA)

We can also use webcamd(8) to list available cameras in the system.

% webcamd -l
Available device(s):
webcamd [-d ugen1.1] -N 0x1912-XHCI-root-HUB -S unknown -M 0
webcamd [-d ugen2.1] -N 0x1033-XHCI-root-HUB -S unknown -M 0
webcamd [-d ugen3.1] -N Intel-EHCI-root-HUB -S unknown -M 0
webcamd [-d ugen0.1] -N Intel-EHCI-root-HUB -S unknown -M 1
webcamd [-d ugen3.2] -N vendor-0x8087-product-0x0024 -S unknown -M 0
webcamd [-d ugen0.2] -N vendor-0x8087-product-0x0024 -S unknown -M 1
webcamd [-d ugen0.3] -N vendor-0x0765-product-0x5001 -S unknown -M 0
webcamd [-d ugen0.4] -N Logitech-USB-Receiver -S unknown -M 0
webcamd [-d ugen0.5] -N Chicony-Electronics-Co---Ltd--Integrated-Camera -S unknown -M 0
Show webcamd usage:
webcamd -h

We will use above webcamd(8) output to add needed webcamd_0_flags in the /etc/rc.conf file.

# vi /etc/rc.conf

  webcamd_enable=YES
  webcamd_0_flags="-d ugen0.5"

:wq

We also need to add ourselves to the webcamd group.

# pw groupmod webcamd -m vermaden

# grep webcamd /etc/group 
webcamd:*:145:vermaden

We can now start the webcamd(8) daemon.

# service webcamd start
Starting webcamd.
webcamd 99884 - - Attached to ugen0.5[0]

# ls -l /dev/video*
crw-rw---- 1 webcamd operator 2, 5 2021-05-09 11:36 /dev/video0
crw-rw---- 1 webcamd operator 2, 6 2021-05-09 11:36 /dev/video1

We will now use pwcview(1) to check how the Camera works.

% pwcview
Webcam set to: 320x240 (sif) at 5 fps

Here is how it looks.

pwcview

Works! I pixelised the output as I do not have an instagrammer soul …

You can start pwcview(1) with larger resolution when needed.

Camera at mine ThinkPad W520 tops at 1280×720 resolution (HD) and 30 fps for refresh rate.

% pwcview -d /dev/video0 -f 30 -s uxga
Webcam set to: 1280x720 (uxga) at 30 fps

Here is the list of most popular resolutions.

FORMAT    RESOLUTION (NOTES)
========= ========== ===============
CGA        320x200
SIF        352x240
CIF        352x288
EGA        640x350
VGA        640x480
4SIF/QSIF  704x480   (Quad SIC)
4CIF/QCIF  704x576   (Quad CIF)
SVGA       800x600
XGA       1024x768
720p      1280x720   (HD)
SXGA      1280x1024  (1.3 Megapixel)
WXGA      1366x768   (HD+)
SXGA+     1400x1050
16CIF 	  1408x1152 
WSXGA     1600x1024
UXGA      1600x1200  (2.0 Megapixel)
WSXGA+    1680x1050
1080p     1920x1080  (FullHD)
WUXGA     1920x1200
QXGA      2048x1536  (3.0 Megapixel)
QSXGA     2560x2048  (5.0 Megapixel)
WQSXGA    3200x2048
QUXGA     3200x2400
2160p     3840x2160  (4K)
WQUXGA	  3840x2400

You may also try multimedia/cheese which has more ‘desktop’ interface when plain and simple pwcview(1) tool.

# pkg install multimedia/cheese
% cheese

cheese

You may also test your camera online – https://www.onlinemictest.com/webcam-test/ – for example here.

online-test-webcam

Microphone Setup

You may test your microphone with audio/audacity or multimedia/ffmpeg for example.

You as well use the – https://www.onlinemictest.com/ – online test for your mic.

online-test-mic

You can also use audio/sox to record your sound in the terminal.

# pkg install sox celluloid

% pkg which -o $( which rec )
/usr/local/bin/rec was installed by package audio/sox

% rec test.wav

Input File     : 'default' (ossdsp)
Channels       : 2
Sample Rate    : 48000
Precision      : 16-bit
Sample Encoding: 16-bit Signed Integer PCM

In:0.00% 00:00:06.66 [00:00:00.00] Out:315k  [ =====|===== ] Hd:1.9 Clip:0    ^C
Aborted.

% celluloid test.wav

You hear your recording for example in the celluloid(1) player.

celluloid

ThinkPad Microphone Easter Egg

After I successfully tested the Camera on my ThinkPad W520 I then moved to Microphone testing … to just find out that my microphone is totally deaf. I could not record any sound with audacity(1) or ffmpeg(1).

At the beginning I first suspected it was a FreeBSD problem … unjustifiably fortunately.

Switching Microphone to [Enabled] in the ThinkPad W520 BIOS requires special procedure as shown on the BIOS screenshot below πŸ™‚

thinkpad-bios

1. Set the Microphone to [Enabled].
2. Select Save and Exit option in BIOS.
3. Power off laptop.
4. Disconnect AC power for at least 10 seconds (battery can be attached).
5. Power on laptop.
6. Boot FreeBSD as usual and now recording on Microphone works like a charm πŸ™‚

Why so strange enabling procedure? Some people suggested that it needs to be that complicated to make sure that any third party will not enable your Microphone without your knowledge. Security concerns. Makes sense.

Meetings

I was able to successfully start/join Google Meet and Zoom and also Teams meetings with this setup. I have also tested and added Jitsi Meet.

Sometimes it just required to use www/chromium instead of my default www/firefox browser.

Here is the detailed list of what works where.

Closing Thoughts

Hope that will helps some of you to use join your meetings on FreeBSD system.

EOF

FreeBSD Desktop – Part 25 – Configuration – Random Terminal Theme

Some time ago when I was mostly writing about Openbox setup I also showed how to setup xterm(1) so it will start with new random theme with each start. Since then I reworked that feature a little and also added random theme and background selection for urxvt(1) terminal. This post will guide you through the needed steps to make that setup working.

terminal

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

I already once wrote about random xterm(1) themes in the FreeBSD Desktop – Part 12 – Configuration – Openbox part – but I really wanted to expand that topic and also include other terminals.

After trying many terminal emulators – some more bulky like Konsole/GNOME Terminal/XFCE Terminal/MATE Terminal – some more lightweight like st(1)/rox-term(1)/eterm(1)/… – I always went back to the most old-school and basic one – good old xterm(1) terminal. Mostly because of its good compatibility with all UNIX systems – especially the older ones like IBM AIX or HP-UX. I do not remember last time when I had to manage these archaic systems but the respect for xterm(1) remains.

xterm

The other one that always got my attention was urxvt(1) terminal. Unfortunately it has some issues with fonts rendering – making larger spaces between the lines and making fonts bigger for example – but as I also like bitmap fonts like CLEAN or FIXED – so I use bitmap fonts for urxvt(1).

Recently also sakura(1) got my attention – but it’s theming possibilities are even more limited then xterm(1) with themes/colors hardcoded directly into the source code. That is why I will omit it in this article – but I mention it since its also nice terminal.

This is the Table of Contents for this article.

  • xterm(1)
    • Proper Font Selection
    • Selecting Text for Copy/Paste
    • Selection Buffers and Keyboard Shortcuts
    • Increase/Decrease Font Size on the Fly
    • Copy/Paste with [CTRL]+[SHIFT]+[C/V]
    • Interactive Menus
    • Random xterm(1) Theme
  • urxvt(1)
    • Tabbed Interface
    • Daemon and Client Mode
    • Random urxvt(1) Theme and Background
  • sakura(1)
    • Different sakura(1) Themes
  • RAM Usage Comparison
  • CPU Time Usage Comparison

xterm(1)

First lest start with some reasonable configuration in the ~/.Xdefaults file. Alternatively some people use ~/.Xresources file. You can use any of them. Just pick one and stick to it.

! XTERM
! -----------------------------------------------------------------------------
  xterm*allowBoldFonts:     true
  xterm*allowWindowOps:     true
  xterm*boldMode:           false
  xterm*charClass:          33:48,35:48,37:48,43:48,45-47:48,64:48,95:48,126:48,35:48,58:48,63:48,61:48,44:48,38:48,59:48
  xterm*cursorBlink:        false
  xterm*cutNewline:         true
  xterm*faceName:           consolas
  xterm*faceSize:           11
  xterm*fastScroll:         true
  xterm*fullscreen:         false
  xterm*iconHint:           /home/vermaden/.icons/vermaden/xterm.xpm
  xterm*internalBorder:     1
  xterm*jumpScroll:         true
  xterm*keepSelection:      true
  xterm*loginShell:         true
  xterm*metaSendsEscape:    true
  xterm*multiScroll:        true
  xterm*omitTranslation:    fullscreen
  xterm*on4Clicks:          group
  xterm*on5Clicks:          page
  xterm*saveLines:          1024000
  xterm*scaleHeight:        1.0
  xterm*scrollKey:          true
  xterm*scrollTtyOutput:    false
  xterm*selectToClipboard:  true
  xterm*SimpleMenu*font:    -*-clean-*-*-*-*-*-*-*-*-*-*-iso8859-2
  xterm*termName:           xterm-256color
  xterm*title:              xterm
  xterm*veryBoldColors:     14
  xterm*VT100*geometry:     150x40
  xterm*VT100*translations: #override                                             \n\
                            <btn1up>: select-end(PRIMARY, CLIPBOARD, CUT_BUFFER0) \n\
                            Ctrl <key> minus: smaller-vt-font()                   \n\
                            Ctrl <key> plus: larger-vt-font()                     \n\
                            Ctrl Shift <key> C: copy-selection(CLIPBOARD)         \n\
                            Ctrl Shift <key> V: insert-selection(CLIPBOARD)

I will not discuss all possible settings as they are well described in the xterm(1) man page but I will comment some more useful and interesting ones.

Proper Font Selection

This advice is not limited to xterm(1) but its worth to mention it. Many times after adding fonts to my system – and renaming them to my ‘standard’ which looks like that one below I was asking myself how to properly specify the variant I need.

% ls -1 ~/.fonts/ubuntu-mono*
/home/vermaden/.fonts/ubuntu-mono-bold-italic.ttf
/home/vermaden/.fonts/ubuntu-mono-bold.ttf
/home/vermaden/.fonts/ubuntu-mono-italic.ttf
/home/vermaden/.fonts/ubuntu-mono.ttf

The answer to that question comes with fc-match(1) from fontconfig package. Check my ‘queries’ below.

% fc-match consolas:bold
consolas-bold.ttf: "Consolas" "Bold"

% fc-match consolas     
consolas.ttf: "Consolas" "Regular"

% fc-match consolas:bold:italic
consolas-bold-italic.ttf: "Consolas" "Bold Italic"

Selecting Text for Copy/Paste

The xterm*charClass defines which sets of characters should be treated the same when doing cut and paste. Especially with double-clicking the text. The setting above I use is based on 15 years of experience and seems to work best. You are of course encouraged to investigate the CHARACTER CLASSES section of the xterm(1) man page to read more on this topic.

The xterm*on4Clicks and xterm*on5Clicks are not used by default while xterm*on2Clicks are predefined as word and xterm*on3Clicks as line values. This is why I added them so you can select entire group with xterm*on4Clicks and entire page with xterm*on5Clicks option. Alternatively you can also use some fancy regex for some of these ‘CLICKS’ but I never thought about a REGEX that would be useful here – maybe you will come with something sensible.

Here are these ‘CLICKS’ in action.

First the xterm*on2Clicks with word selection. This is when the xterm*charClass is taken into account – what is word and that is not πŸ™‚

xterm.2.clicks

Then xterm*on3Clicks with line selection.

xterm.3.clicks

Now xterm*on4Clicks with group selection.

xterm.4.clicks

Finally the xterm*on5Clicks entire page selection.

xterm.5.clicks

Selection Buffers and Keyboard Shortcuts

The last interesting option is xterm.VT100.translations which is used for keyboard shortcuts.

The first one select-end(PRIMARY, CLIPBOARD, CUT_BUFFER0) is better described in the https://davidsimmons.com/soft/xtermhacks/ page from 2005. I will try to short the meritum here. The X11 applications have two different selection buffers:

CLIPBOARD – selection buffer used for cut/paste functions – you select/highlight text and then select Copy from context menu or use [CTRL]+[C] shortcut. Then you use Paste or [CTRL]+[C] shortcut.

PRIMARY – this one receives data when user selects/highlights text with mouse. None other operations such as Copy or Paste are needed. You end selecting the text and its already in PRIMARY buffer. You then paste it with MIDDLE mouse button.

Using the option above selecting/highlighting the text in xterm(1) copies the text into both selection buffers simultaneously. You can now either Paste it info Firefox or hit MIDDLE mouse button to paste it in other xterm(1) terminal. Best of both worlds.

If that setting does not suit you then use the xterm*selectToClipboard instead. When set to true it copies selected text to CLIPBOARD buffer and when set to false it copies selection to the PRIMARY one.

Increase/Decrease Font Size on the Fly

I always missed the shortcuts to decrease or increase font size on the fly in xterm(1) and for many years I believed that its just not possible and then I found some blog post (do not remember which one now of course) in which I found these settings and started to use them.

They are smaller-vt-font() and larger-vt-font() for decrease and increase respectively with [CTRL]+[-] and [CTRL]+[+] shortcuts – keep in mind that [SHIFT] is not used here.

Copy/Paste with [CTRL]+[SHIFT]+[C/V]

If by some reason you prefer to copy and paste by using [CTRL]+[SHIFT]+[C] and [CTRL]+[SHIFT]+[V] shortcuts then copy-selection(CLIPBOARD) and insert-selection(CLIPBOARD) will do the needed job here. As you probably guessed you can use PRIMARY instead of CLIPBOARD here if that is what you desire.

Interactive Menus

The xterm(1) comes with three different interactive menus. I will now show all three of them here with screenshots.

Menu displayed with clicking [CTRL]+[LEFT-MOUSE-BUTTON] in the terminal area.

xterm.menu.mouse.LEFT

Menu displayed with clicking [CTRL]+[MIDDLE-MOUSE-BUTTON] in the terminal area.

xterm.menu.mouse.MIDDLE

Menu displayed with clicking [CTRL]+[RIGHT-MOUSE-BUTTON] in the terminal area.

xterm.menu.mouse.RIGHT

Random xterm(1) Theme

To have random xterm(1) theme on every startup you need four things:

I gathered all these themes all over the Internet, only the VERMADEN and VERMADEN-OLD themes are created by me.

Little preview of some of the included xterm(1) themes.

xterm.random

From now on to have random xterm(1) theme at each start always start it with ~/scripts/xterm.sh script. The script itself is not very complicated. It just draws random theme from the ~/.config/Xdefaults/themes dir – then loads the ~/.Xdefaults config – then merges the colors from chosen random theme – and finally starts new xterm(1) instance.

xterm.sh

urxvt(1)

I use urxvt(1) less often but still sometimes I want to use bitmap fonts instead.

urxvt.single

For a start here is the urxvt(1) configuration in the ~/.Xdefaults file.

! URXVT
! -----------------------------------------------------------------------------
  urxvt.letterSpace:    0.0
! urxvt.font:           xft:monaco:pixelsize=9,style=regular,minspace=True
  urxvt.font:           -*-clean-*-*-*-*-*-*-*-*-*-*-iso8859-2
  urxvt.boldFont:       -*-clean-*-*-*-*-*-*-*-*-*-*-iso8859-2
  urxvt.iconFile:       /home/vermaden/.icons/vermaden/xterm.xpm
  urxvt.geometry:       150x40
  urxvt.cutchars:       ,;
  urxvt.scrollBar:      false
  urxvt.imLocale:       en_US.UTF-8
  urxvt.loginShell:     true
  urxvt.saveLines:      1024000
  urxvt.inheritPixmap:  false
  urxvt.shading:        20
  urxvt.xftAntialias:   true
  urxvt.jumpScroll:     true
  urxvt.tintColor:      black
  urxvt.internalBorder: 2
  urxvt.cursorBlink:    false
  urxvt.cursorColor:    #dd9900
  urxvt.cursorColor2:   #000000
  urxvt.colorBD:        #dddddd
  urxvt.colorIT:        #bbbbbb
  urxvt.colorUL:        #999999
  urxvt.underlineColor: #999999

Tabbed Interface

To get tabs in urxvt(1) add the following option to the ~/.Xdefaults configuration file.

  urxvt.perl-ext-common:   default,tabbed

With this option you will open new tab with [SHIFT]+[DOWN] shortcut.

To switch between the tabs left and right use [CTRL]+[SHIFT]+[LEFT] and [CTRL]+[SHIFT]+[RIGHT] shortcut respectively.

You can also use [CTRL]+[LEFT] and [CTRL]+[RIGHT] to move current tab left and right.

The timeless [CTRL]+[D] – which of course is not a strictly urxvt(1) shortcut but a general shortcut for closing all terminals.

urxvt.tabbed

Daemon and Client Mode

The urxvt(1) can be run in special daemon mode where you start one urxvtd(1) server and many urxvtc(1) clients.

% urxvtd
rxvt-unicode daemon listening on /home/vermaden/.urxvt/urxvtd-w520.local.

Now you will start each new urxvt(1) terminal with urxvtc(1) command.

The drawback of that approach is that when urxvtd(1) dies or crashes then also all your urxvtc(1) client terminals disappear πŸ™‚

Random urxvt(1) Theme and Background

To have random urxvt(1) theme and background on every startup you need four things:

Little preview of some of the included urxvt(1) themes and backgrounds.

urxvt.random

From now on to have random urxvt(1) theme at each start always start it with ~/scripts/urxvt.sh script. The script for urxvt(1) is little more advanced. First it draws random theme from the ~/.config/Xdefaults/themes dir – then checks if its DARK or LIGHT theme – then draws either random LIGHT or DARK background from the ~/.config/Xdefaults/urxvt dir – finally loads the ~/.Xdefaults config and then merges the colors from chosen LIGHT or DARK theme. Of course then it finally starts new urxvt(1) instance.

urxvt.sh

sakura(1)

The more modern and GTK based sakura(1) also supports tabs. To open new tab use [CTRL]+[SHIFT]+[T] shortcut. To switch between the tabs use [CTRL]+[ALT]+[LEFT] and [CTRL]+[ALT]+[RIGHT] shortcuts. You can also move tab between left and right with [CTRL]+[SHIFT]+[LEFT] and [CTRL]+[SHIFT]+[RIGHT].

sakura.single

One things that sakura(1) impresses me is that you can scale down its window and then scale that window up and the contents that did not fit in the window after downscalling are back again in the terminal. Doing the same operation in xterm(1) or urxvt(1) terminals will result in these characters being lost. The output is also dynamically ‘fit’ into the new larger window while maintaining the new lines etc. Besides that nice feature it is small and fast and uses relatively small amount of RAM.

sakura.tabbed

Different sakura(1) Themes

If you would also like to start sakura(1) with different theme everytime the options are quite limited here. The palettes and color sets are hardcoded into the sakura(1) source code.

I will not show you how to modify them using the FreeBSD Ports system.

The sakura(1) port is located at /usr/ports/x11/sakura directory. For the record – I use WRKDIRPREFIX option in the /etc/make.conf file. This means that when I type make extract in the /usr/ports/x11/sakura dir the work directory will not be created at /usr/ports/x11/sakura/work directory but at /usr/ports/obj/usr/ports/x11/sakura/work instead. That way I can clean my Ports tree fast by removing the /usr/ports/obj directory.

We will now extract and patch the sakura(1) port on FreeBSD.

% grep WRKDIRPREFIX /etc/make.conf
WRKDIRPREFIX=${PORTSDIR}/obj

# cd /usr/ports/x11/sakura

# make patch

# cd /usr/ports/obj/$( pwd )/work/*/src || cd work/*/src

# pwd
/usr/ports/obj/usr/ports/x11/sakura/work/sakura-3.7.1/src

# grep -m 1 DEFAULT_PALETTE sakura.c
#define DEFAULT_PALETTE "tango"

# grep -o -E '[a-z]+_palette\[PALETTE_SIZE\]' sakura.c
gruvbox_palette[PALETTE_SIZE]
tango_palette[PALETTE_SIZE]
linux_palette[PALETTE_SIZE]
dark_palette[PALETTE_SIZE]
xterm_palette[PALETTE_SIZE]
rxvt_palette[PALETTE_SIZE]

As you can see the default sakura(1) palette is Tango. Fortunately you can use palette=solarized_dark option in the ~/.config/sakura/sakura.conf config file to change it into Solarized Dark for example.

Besides hardcoded palettes sakura(1) also has several Color Sets.

If you would like to make random theme (from the hardcoded ones) for each start you would have to use this syntax with prepared dedicated config files for each palette.

% sakura --config-file ~/.config/sakura/sakura.solarized_dark.conf --colorset 1 
% sakura --config-file ~/.config/sakura/sakura.tango.conf          --colorset 3

I do not use sakura(1) that much so I was too lazy to write random startup theme script also for it πŸ™‚

Changing sakura(1) palette or color set manually is shown below.

sakura.colors.menu

sakura.colors.window

sakura.palette

RAM Usage Comparison

Just started xterm(1) terminal takes about 16 MB or RAM as you have seen on the urxvt(1) screenshots. The urxvt(1) started without tabs uses more then 2 TIMES of xterm(1) terminal RAM usage. The urxvt(1) started in tabbed mode uses more then 3 TIMES of xterm(1) terminal RAM usage. The sakura(1) also uses more then 3 TIMES of xterm(1) terminal RAM usage.

Table below shows RAM usage comparison. I have added more feature packed mate-terminal(1) to the list and also added the st(1) minimalistic terminal from Suckless project for compassion.

RAM/MB  TERMINAL  
    64  mate-terminal
    53  sakura
    52  urxvt (tabbed)
    38  urxvt
    16  xterm
    12  st

CPU Time Usage Comparison

I also made simple benchmark of the CPU used. The ‘benchmark’ was to check how much time each terminal would take to print output ofΒ  dmesg | lolcat -b -r command. Here xterm(1) does not shine that much.

   TIME  TERMINAL
0:00.93  xterm
0:00.82  mate-terminal
0:00.52  sakura
0:00.43  urxvt
0:00.23  st

The above ‘benchmark’ was was quite ‘hard’ because of all the colors generated by lolcat(1) command. Lets try something more practical now. We will measure CPU time used to display out of the find find /usr/local/share/doc command.

   TIME  TERMINAL
0:01.34  xterm
0:01.18  mate-terminal
0:00.85  sakura
0:00.32  urxvt
0:00.28  st

Seems that lolcat(1) was not that ‘hard’. The st(1) minimalistic terminal really seems to suck less here πŸ™‚

EOF

FreeBSD Desktop – Part 24 – Configuration – Universal File Opener

More then a decade ago when I started to use X11 as a desktop – on Linux then with KDE3 and later with Fluxbox. At first I thought that files are opened by appropriate applications not by their extension as in Windows systems but according to their Magic Numbers. I do not have to tell you how much disappointed I was when I learned the truth πŸ™‚

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

TL;DR

Its a short story about cleaning the mess that XDG does and also using custom *.desktop handlers to open the files in the way you want. It know its in the FreeBSD Desktop series but actually it will work on any X11 desktop like Linux or Illumos.

The Table of Contents for the article is right below here.

  • XDG Utils
  • Now You See Me
  • Mime Apps Handlers
  • Generation of Handlers
  • Alternatives

Lets start then.

XDG Utils

After years of using X11 on FreeBSD now with Openbox as my daily driver I used so called xdg-utils package with its *.desktop files. That sometimes driven me nuts. Mess everywhere with doubled ‘the same’ applications listed as possible choices to open a file … almost randomly generated new *.desktop handlers with ‘new’ applications specified to open some files … another dozen of generated *.desktop files from WINE installations … it can only challenge the bullshit and mess of Windows Registry … not sure which one is more messed up (of course its Windows Registry but still).

The xdg-mime(1) is often not useful at all then determining the file type.

$ xdg-mime query filetype FILE.pdf
application/pdf

$ xdg-mime query default application/pdf
mupdf.sh.desktop

If minimalistic mupdf approach is not for you then you can select Atril for example … but you first need to know that is the handler name for the Atril application. You can find that out fast like that.

% find ~/.local/share/applications /usr/local/share/applications | grep atril
/usr/local/share/applications/atril.desktop

We now have the Atril handler name. To set it as new default application for PDF files type the following.

$ xdg-mime default atril.desktop application/pdf

$ xdg-mime query default application/pdf
atril.desktop

But this is rather unique moment when XDG works as designed. More often it looks like that.

$ xdg-mime query filetype FILE.doc
application/octet-stream

$ xdg-mime query filetype FILE.docx
application/zip

$ xdg-mime query filetype FILE.xls
application/octet-stream

$ xdg-mime query filetype FILE.xlsx
application/zip

So when you now ask for application/zip type then what should pop up? LibreOffice for Word/Excel documents or Engrampa for ZIP files?

% xdg-mime query default application/zip                                     
engrampa.desktop

Not very helpful …

Now You See Me

After almost accepting the current ‘tragic’ state of it I came with other idea – to create mine simplified launcher for many of these file types. It started small and is still quite small. The only thing I do now is that I only add new apps for file extensions that are not yet defined.

Its called see.sh and its function is dual:
– to easily replace XDG settings in one place as file opener
– as command line opener for single or multiple files

The construction of see.sh is really simple. It utilizes the idea behind the quote of Antoine de Saint-Exupery which goes like that – “Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.” – its really simple and has nothing to remove from it.

I really appreciate that idea that I now do not have to remember which application is needed (and how its spelled besides the zsh(1) TAB completion) to open any file in command line. Its also faster to type then xdg-open(1) and I am sure that its settings were not modified by some third party app that I just installed because its hardcoded in it.

I also really like see.sh for being very elastic for the environment variables with which the needed application can be started. For example my default DPI for X11 session since more then a decade is 75. That makes fonts little smaller – more information fits on the available screen space. The GTK2/GTK3 applications do not need any tweaks and always look decent or even great but QT5 (and QT4 not so long ago) apps are real bitches when you want to force them to look the way you want (look nice) – especially when run without fully fledged KDE or PLASMA environment. One of such applications is LibreOffice. It looked great when it used GTK framework but after they moved to QT it started to look very ugly with my 75 DPI setting. This is how it looks with its environment unmodified.

Thanks to see.sh I can start LibreOffice with different DPI environment setting then 75 and it looks little better with DPI set to 80. LibreOffice started with QT_FONT_DPI=80 option does not look that bad now – its fonts are not that small and ugly anymore.

Now the text labels on LibreOffice menus are more readable but also not too large.

You may also customize see.sh to first create a backup copy before editing certain files or email them – only your imagination limits you here.

I also wanted its see.sh name to be short and fast to type so with completions its just see[TAB] and then a filename. Of course you may want to rename it to shorter version (or create alias) as see without extension but i like to keep my scripts with extension to distinguish them from native commands – but that is me.

First see.sh detects if one or multiple arguments (files) have been passed to it. If its just a single file then see.sh detects its extension and launches the configured application for it.

If file does not have extension then it checks file’s Magic Number. Currently only detection for plain text files is implemented with file(1) command.

If you pass multiple arguments (files) to see.sh then separate see.sh processes will be launched against each given file in parallel. Recursion generally.

Every time you select new application in graphical mode the new *.desktop file is created as a result with userapp-${APPNAME}-${RANDOM_STRING}.desktop name under ~/.local/share/applications directory. I am not sure that its the tidiest way possible. Often very ugly and strange handler filenames are generated – with spaces or quotation marks. Its really far from UNIX way of doing things and its philosophy.

This is how ~/.local/share/applications directory looked on my machine after some time. Notice the selected file.

After some cleanup and modifications it looks little better.

The XDG keeps its associations in the ~/.config/mimeapps.list file. Have a look how messed it gets after some usage.

After some more cleanup and removal of all unneeded userapp-${APPNAME}-${RANDOM_STRING}.desktop entries it starts to look more organized.

Every time see.sh will find out that it does not have handler for a file it will gracefully remind one to configure it.

Mime Apps Handlers

Many of these *.desktop handlers are not present anymore … but which one? Here is a handy one liner that will either show you the full path of the handler or ‘NOPE’ when one does not exists. This will also tell you if its your ‘custom’ handlers at ~/.local/share/applications or the ‘default’ ones that come with packages and installed software located at /usr/local/share/applications location.

% awk -F'=' '{print $2}' ~/.config/mimeapps.list \
    | tr ';' '\n' \
    | sort -u \
    | sed 1d \
    | while read I
      do
        echo ${I}
        find \
          ~/.local/share/applications \
          /usr/local/share/applications \
            | grep "/${I}" || echo NOPE
        echo
      done

Well … maybe not exactly ONE liner but a useful command that will do it πŸ™‚

Here is its output.

(...)

mupdf.sh.desktop
/home/vermaden/.local/share/applications/mupdf.sh.desktop

planmaker-free18.desktop
NOPE

presentations-free18.desktop
NOPE

see.sh.desktop
/home/vermaden/.local/share/applications/see.sh.desktop

sumatra.sh.desktop
/home/vermaden/.local/share/applications/sumatra.sh.desktop

textmaker-free18.desktop
NOPE

(...)

If you just want to check which ones are missed then add grep -B 1 NOPE at the end.

% awk -F'=' '{print $2}' ~/.config/mimeapps.list \
    | tr ';' '\n' \
    | sort -u \
    | sed 1d \
    | while read I
      do
        echo ${I}
        find \
          ~/.local/share/applications \
          /usr/local/share/applications \
            | grep "/${I}" || echo NOPE
        echo 
      done | grep -B 1 NOPE

Here is the (un)expected output.

You can safely remove all missing *.desktop handlers from the ~/.config/mimeapps.list file. You may use sed(1) or graphical editor if that suits you better. The logic behind it is to remove all instances of for example presentations-free18.desktop and then find and replace all instances of doubled semicolons ‘;;‘ into single one ‘;‘.

Generation of Handlers

To generate new *.desktop handlers in orderly fashion you can use mine generate-desktop-handler.sh script. It will create new handler in the ~/.local/share/applications directory and it will make sure you are creating one with an application that actually exists. Here is how it works. I have created new handler for my random-wallpaper-always.sh for setting up random wallpaper from specified directory or to set wallpaper from exact specified file as argument.

% generate-desktop-handler.sh                                       
usage: generate-desktop-handler.sh FILE

% generate-desktop-handler.sh non-existing-executable
NOPE: executable 'non-existing-executable' not found in ${PATH}

% generate-desktop-handler.sh random-wallpaper-always.sh 
INFO: handler '~/.local/share/applications/random-wallpaper-always.sh.desktop' was successfully generated

% cat ~/.local/share/applications/random-wallpaper-always.sh.desktop
[Desktop Entry]
Encoding=UTF-8
Version=1.0
Type=Application
NoDisplay=true
Exec=random-wallpaper-always.sh %f
Name=random-wallpaper-always.sh
Comment=random-wallpaper-always.sh

After you have created new random-wallpaper-always.sh.desktop handler you may want to add it to some image file type like JPG or PNG. In the example below I will add it to JPG file.

First right click on a JPG file with mouse and select Open With and then Other Application….

The select random-wallpaper-always.sh.desktop handler on the list. Make sure to UNCHECK the Remember this application for … files option. If you do not do that it will be the DEFAULT application from now and everytime you would want to open JPG file you will set it as wallpaper πŸ™‚

You may verify that new option is added by right clicking the JPG file and selecting Properties and then go to Open With tab. The random-wallpaper-always.sh.desktop handler will be one of the configured handlers for JPG files – but not the default one.

Now you can see that random-wallpaper-always.sh.desktop handler is available to use when selecting the Open With submenu.

As simple as that – and with tidiness as well.

Alternatives

There are some other alternatives to XDG but I am more then sure that most or all X11 applications support XDG way of doing things while not support the other alternative ones. Thus its far less hustle with just making XDG work as desired by generating needed handlers and using see.sh instead of using them and wasting even more time on the topic – at least that is my current experience.

Feel free to share your thoughts on the topic – maybe you will show me even better approach to this.

EOF

FreeBSD Desktop – Part 23 – Configuration – Herbe Notifications

I do not use notifications. Dunno really why – seems I just did not needed them. The idea of Do Not Disturb Mode on the desktop/laptop is very strange to me as I ALWAYS work in the Do Not Disturb Mode since I do not use any notifications. Today I came across very small and compact solution for notifications on X11 desktop – herbe – as its author describes it – its daemon-less notifications without D-Bus. Minimal and lightweight.

I was curious if it works on FreeBSD and apparently it is πŸ™‚

Today I will show you how to build, configure and use herbe as part of FreeBSD Desktop series.

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

Fetch

We will use the compact git-lite package from FreeBSD which has less dependencies then the default git package. Then we will clone the herbe repository.

# pkg install git-lite
% git clone https://github.com/dudik/herbe
Cloning into 'herbe'...
remote: Enumerating objects: 228, done.
remote: Counting objects: 100% (42/42), done.
remote: Compressing objects: 100% (38/38), done.
remote: Total 228 (delta 21), reused 11 (delta 4), pack-reused 186
Receiving objects: 100% (228/228), 152.95 KiB | 272.00 KiB/s, done.
Resolving deltas: 100% (118/118), done.
$ cd herbe
% ls -l
total 23K
-rw-r--r-- 1 vermaden vermaden  650 2021-04-18 19:18 config.def.h
-rw-r--r-- 1 vermaden vermaden 5268 2021-04-18 19:18 herbe.c
-rw-r--r-- 1 vermaden vermaden 1070 2021-04-18 19:18 LICENSE
-rw-r--r-- 1 vermaden vermaden  425 2021-04-18 19:18 Makefile
-rw-r--r-- 1 vermaden vermaden 5578 2021-04-18 19:18 README.md

Patch

We will need a tiny one line patch to make it build on FreeBSD.

This FreeBSD patch for Makefile file is available here:
https://github.com/dudik/herbe/pull/16

… or diff(1) directly here:
https://patch-diff.githubusercontent.com/raw/dudik/herbe/pull/16.diff

We will now apply that patch.

% fetch https://patch-diff.githubusercontent.com/raw/dudik/herbe/pull/16.diff
% patch < 16.diff 
Hmm...  Looks like a unified diff to me...
The text leading up to this was:
--------------------------
|diff --git a/Makefile b/Makefile
|index 3225e36..69c8efc 100644
|--- a/Makefile
|+++ b/Makefile
--------------------------
Patching file Makefile using Plan A...
Hunk #1 succeeded at 1.
done

The herbe is now buildable on FreeBSD.

There are also other available patches – herbe patches – available here.

From all of them I find Vertical Stacking patch the most interesting. We will also apply it.

% fetch https://patch-diff.githubusercontent.com/raw/dudik/herbe/pull/19.diff
% patch < 19.diff 
Hmm...  Looks like a unified diff to me...
The text leading up to this was:
--------------------------
|diff --git a/herbe.c b/herbe.c
|index 51d3990..8bfdbc1 100644
|--- a/herbe.c
|+++ b/herbe.c
--------------------------
Patching file herbe.c using Plan A...
Hunk #1 succeeded at 7.
Hunk #2 succeeded at 80.
Hunk #3 succeeded at 162.
Hunk #4 succeeded at 188.
Hunk #5 succeeded at 218.
Hunk #6 succeeded at 230.
done


Config

You can additionally patch herbe so it will be configurable by using ~/.Xresources or ~/.Xdefaults files. IMHO its so small and compiles in second that its not needed but if you would like to also apply it then its available here – Xresources – in the patches section.

I have chosen to configure it using the config.def.h file. Here are my values.

% cat config.def.h
static const char *background_color    = "#222222";
static const char *border_color        = "#666666";
static const char *font_color          = "#eeeeee";
static const char *font_pattern        = "Ubuntu Mono:size=10";
static const unsigned line_spacing     = 5;
static const unsigned int padding      = 15;

static const unsigned int width       = 550;
static const unsigned int border_size = 4;
static const unsigned int pos_x       = 15;
static const unsigned int pos_y       = 45;

enum corners { TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT };
enum corners corner = TOP_RIGHT;

static const unsigned int duration = 5; /* in seconds */

#define DISMISS_BUTTON Button1
#define ACTION_BUTTON Button3

Build

The build process could not be simpler. Just type make and you are done.

% make 
cp config.def.h config.h
cc herbe.c -Wall -Wextra -pedantic -I/usr/local/include -L/usr/local/lib -lX11 -lXft -I/usr/local/include/freetype2 -pthread -o herbe

% file -s herbe | tr ',' '\n'
herbe: ELF 64-bit LSB executable
 x86-64
 version 1 (FreeBSD)
 dynamically linked
 interpreter /libexec/ld-elf.so.1
 for FreeBSD 13.0 (1300139)
 FreeBSD-style
 with debug_info
 not stripped

% ./herbe 
Usage: ./herbe body

Test

I did not yet implemented herbe anywhere on my scripts so I will use this simple ‘mockup’ to show you what to expect.

% \
  herbe "Wifi connection 'wireless' is not connected." \
& herbe "Removable storage /dev/da0 automounted at /media/da0 with exFAT filesystem." \
&

Here is how it looks in real life X11 session.

As you can see it works very well and its ultra fast. Its also very light on system resources.

% ps aux | grep -e RSS -e herbe -e sshd
USER       PID  %CPU %MEM      VSZ     RSS TT  STAT STARTED        TIME COMMAND
vermaden 41909   0.0  0.1    19568    9128  3  S+   20:22       0:00.02 herbe Message.
root        38   0.0  0.1    20948    8340  -  Is   Thu23       0:00.00 /usr/sbin/sshd

As you can see its RAM usage is very little – as little as sshd daemon.

EOF

UFS Boot Environments for ARM

Several days ago I introduced UFS Boot Environments that work great on AMD64 (or 64-bit PC if you prefer). I was interested it it will also work on less powerful devices that ZFS is not always the best idea – ARM based devices. After some testing I found out that after one simple modification the UFS Boot Environments work like a charm on ARM devices.

The Table of Contents is as follows.

  • ARM Testing
  • Setup UFS Boot Environments
  • Needed Fix to Make FreeBSD bootme Flags Work
  • Reboot into Other Boot Environment Test

There is not suitable TL;DR here – you will have to read it all or not at all this time πŸ™‚

ARM Testing

I currently do not own 64-bit ARM device … so I thought I will try the qemu(1) emulator and ready to download and use ARM images provided by the FreeBSD project.

First we will install needed packages and fetch the ARM64 (also known as aarch64) images.

host # pkg install -y qemu u-boot-qemu-arm64

host % fetch https://download.freebsd.org/ftp/releases/VM-IMAGES/13.0-RC4/aarch64/Latest/FreeBSD-13.0-RC4-arm64-aarch64.raw.xz

host % xz -d FreeBSD-13.0-RC4-arm64-aarch64.raw.xz

We will now increase the image size to add additional boot environment partition.

host % ls -lh FreeBSD-13.0-RC4-arm64-aarch64.raw 
-rw-r--r-- 1 vermaden vermaden 5.1G 2021-04-04 12:37 FreeBSD-13.0-RC4-arm64-aarch64.raw

host % truncate -s +9G FreeBSD-13.0-RC4-arm64-aarch64.raw

host % ls -lh FreeBSD-13.0-RC4-arm64-aarch64.raw
-rw-r--r-- 1 vermaden vermaden 15G 2021-04-04 12:38 FreeBSD-13.0-RC4-arm64-aarch64.raw

Using qemu(1) emulator we can boot using either UEFI or U-BOOT option. We will test both as some ARM devices use UEFI and some (like Raspberry Pi devices) use U-BOOT mode.

host % export VMDISK=FreeBSD-13.0-RC4-arm64-aarch64.raw

// UEFI
host % qemu-system-aarch64 \
         -m 4096M \
         -cpu cortex-a57 \
         -M virt \
         -bios edk2-aarch64-code.fd \
         -serial telnet::4444,server \
         -nographic \
         -drive if=none,file=${VMDISK},format=raw,id=hd0 \
         -device virtio-blk-device,drive=hd0 \
         -device virtio-net-device,netdev=net0 \
         -netdev user,id=net0

// U-BOOT
host % qemu-system-aarch64 \
         -m 4096M \
         -cpu cortex-a57 \
         -M virt \
         -bios /usr/local/share/u-boot/u-boot-qemu-arm64/u-boot.bin \
         -serial telnet::4444,server \
         -nographic \
         -drive if=none,file=${VMDISK},format=raw,id=hd0 \
         -device virtio-blk-device,drive=hd0 \
         -device virtio-net-device,netdev=net0 \
         -netdev user,id=net0

After starting the qemu(1) process it will display the following information.

(...)
QEMU 5.0.1 monitor - type 'help' for more information
(qemu) qemu-system-aarch64: -serial telnet::4444,server: info: QEMU waiting for connection on: disconnected:telnet::::4444,server

We can now use telnet(1) to connect to our serial console on emulated ARM64 system. We will add additional freebsd-ufs partition for our second boot environment.

host % telnet localhost 4444
(...)

login: root

ARM # pkg install -y lsblk

ARM # lsblk
DEVICE         MAJ:MIN SIZE TYPE                              LABEL MOUNT
vtbd0            0:62   14G GPT                                   - -
  vtbd0p1        0:63   33M efi                          gpt/efiesp /boot/efi
  vtbd0p2        0:64  1.0G freebsd-swap                 gpt/swapfs -
  vtbd0p3        0:65  4.0G freebsd-ufs                  ufs/rootfs /

ARM # gpart show
=>       3  10552344  vtbd0  GPT  (14G) [CORRUPT]
         3     66584      1  efi  (33M)
     66587   2097152      2  freebsd-swap  (1.0G)
   2163739   8388608      3  freebsd-ufs  (4.0G)

ARM # gpart recover vtbd0
vtbd0 recovered

ARM # gpart add -s 4G -t freebsd-ufs vtbd0
vtbd0p4 added

ARM # gpart show
=>       3  29426709  vtbd0  GPT  (14G)
         3     66584      1  efi  (33M)
     66587   2097152      2  freebsd-swap  (1.0G)
   2163739   8388608      3  freebsd-ufs  (4.0G)
  10552347   8388608      4  freebsd-ufs  (4.0G)
  18940955  10485757         - free -  (5.0G)

We will now make some manual preparations for ufsbe.sh to work.

For example the FreeBSD images come with GPT labels used in /etc/fstab file which are currently not supported by UFS Boot Environments so we will modify the /etc/fstab file to mount root filesystem from raw devices and partitions.

ARM # mkdir -p /ufsbe/3 /ufsbe/4

ARM # cat /etc/fstab
# Custom /etc/fstab for FreeBSD VM images
/dev/gpt/rootfs  /          ufs      rw  1 1
/dev/gpt/efiesp  /boot/efi  msdosfs  rw  2 2
/dev/gpt/swapfs  none       swap     sw  0 0

ARM # vi /etc/fstab

ARM # cat /etc/fstab
# Custom /etc/fstab for FreeBSD VM images
/dev/vtbd0p3     /          ufs      rw  1 1
/dev/vtbd0p4     /ufsbe/4   ufs      rw  1 1
/dev/gpt/efiesp  /boot/efi  msdosfs  rw  2 2
/dev/gpt/swapfs  none       swap     sw  0 0

ARM # newfs /dev/vtbd0p4
/dev/vtbd0p4: 4096.0MB (8388608 sectors) block size 32768, fragment size 4096
        using 7 cylinder groups of 625.22MB, 20007 blks, 80128 inodes.
super-block backups (for fsck_ffs -b #) at:
 192, 1280640, 2561088, 3841536, 5121984, 6402432, 7682880

We now have second boot environment ready and /etc/fstab file modified to boot from raw devices instead of GPT labels. We will now reboot(8) to make these changes apply.

ARM # reboot

Setup UFS Boot Environments

We will not fetch the ufsbe.sh command and finish the setup process.

ARM # fetch https://raw.githubusercontent.com/vermaden/ufsbe/main/ufsbe.sh

ARM # chmod +x ./ufsbe.sh

ARM # ./ufsbe.sh

NOPE: did not found boot environment setup with 'ufsbe' label

INFO: setup each boot environment partition with appropriate label

HELP: list all 'freebsd-ufs' partitions type:

  # gpart show -p | grep freebsd-ufs
      2098216   33554432  ada0p3  freebsd-ufs  [bootme]  (16G)
     35652648   33554432  ada0p4  freebsd-ufs  (16G)
     69207080   33554432  ada0p5  freebsd-ufs  (16G)

HELP: to setup partitions 3/4/5 as boot environments type:

  # gpart modify -i 3 -l ufsbe/3 ada0
  # gpart modify -i 4 -l ufsbe/4 ada0
  # gpart modify -i 5 -l ufsbe/5 ada0

ARM # gpart show
=>       3  29426709  vtbd0  GPT  (14G)
         3     66584      1  efi  (33M)
     66587   2097152      2  freebsd-swap  (1.0G)
   2163739   8388608      3  freebsd-ufs  (4.0G)
  10552347   8388608      4  freebsd-ufs  (4.0G)
  18940955  10485757         - free -  (5.0G)

ARM # gpart modify -i 3 -l ufsbe/3 vtbd0
vtbd0p3 modified

ARM # gpart modify -i 4 -l ufsbe/4 vtbd0
vtbd0p4 modified

ARM # ./ufsbe.sh 
INFO: flag 'bootme' successfully set on / filesystem
usage:
  ufsbe.sh (l)ist
  ufsbe.sh (a)ctivate
  ufsbe.sh (s)ync

The UFS Boot Environments are now properly deployed on this ARM64 test system.

Needed Fix to Make FreeBSD bootme Flags Work

At the first try I was not able to use UFS Boot Environments as the bootme flag was ignored.

I then submitted a FreeBSD bug – 254764 – GPT ‘bootme’ flag is not respected on AARCH64 – to make sure I am doing everything well on my side. As it turns out the bootme flag is a FreeBSD specific extension and nobody else uses it. The needed fix is to copy /boot/gptboot.efi in place of bootaa64.efi file.

Lets now make that fix.

ARM # cp /boot/gptboot.efi /boot/efi/EFI/BOOT/bootaa64.efi

Reboot into Other Boot Environment Test

We will now synchronize boot environments 3 and 4 and then reboot into the 4 boot environments.

ARM # ./ufsbe.sh list
PROVIDER LABEL        ACTIVE
vtbd0p3  ufsbe/3      NR  
vtbd0p4  ufsbe/4      -  

ARM # ./ufsbe.sh sync 3 4
INFO: syncing '3' (source) => '4' (target) boot environments ...
INFO: boot environments '3' (source) => '4' (target) synced

ARM # ./ufsbe.sh activate 4
INFO: boot environment '4' now activated

ARM # reboot

After the reboot the currently active boot environment is 4. It means that UFS Boot Environments work properly on ARM devices.

ARM # ./ufsbe.sh list
PROVIDER LABEL        ACTIVE
vtbd0p3  ufsbe/3      -   
vtbd0p4  ufsbe/4      NR  

ARM # df -h
Filesystem         Size    Used   Avail Capacity  Mounted on
/dev/vtbd0p4       3.9G    2.6G    935M    74%    /
devfs              1.0K    1.0K      0B   100%    /dev
/dev/vtbd0p3       3.9G    2.6G    932M    74%    /ufsbe/3
/dev/gpt/efiesp     32M    1.3M     31M     4%    /boot/efi

I have tested both U-BOOT and UEFI boot modes and they both allow to use UFS Boot Environments.

EOF

UFS Boot Environments

Yes you read it correctly. The fabulous ZFS Boot Environments – more about them here – https://is.gd/BECTL – if you are not familiar with this concept – are now also possible on UFS filesystems on FreeBSD. Of course in little different form and without using snapshots and clones but the idea and solution remains. You can now have bootable backups of your system before major changes and/or upgrades. This solution does not use UFS snapshots. All bootable UFS variants are supported with and without Soft Updates or Soft Updates Journaling. The idea behind UFS Boot Environments lays in several additional root (/) partitions that will be used as alternate boot environments.

If you are interested in ARM more then in X86 then also check UFS Boot Environments for ARM article.

Concept is similar to Solaris Live Upgrade mechanism which used lucreate/luupgrade/lustatus commands and also to AIX Alternate Disk Cloning and Install with alt_disk_copy/alt_disk_install commands.

In this article I will show you how to setup new FreeBSD system with 3 of such partitions. In my honest opinion its more then enough for most purposes. On my desktop/workstation I have more then 1000 packages installed. With FreeBSD Base System it takes about 11 GB of space with ZFS compression and 15 GB without it. Thus I propose 16 GB partitions. Your needs may of course be different. You may as well create 4 GB or 64 GB partitions.

The UFS Boot Environments would not exist without the inspiration from FreeBSD Upgrade Procedure Using GPT blog post by Mariusz Zaborski (also known as oshogbo) who describes the concept of bootme flags for GPT partitions. That is the heart of this solution. By selecting activate for boot environment the bootme flag is removed from all existing boot environments and set for the new desired one. The ufsbe(8) tool was tested on FreeBSD 12.x and 13.x currently.

FreeBSD Install for UFS Boot Environments

Generally only GPT partitioning is needed to use UFS Boot Environments. Below I will show example install process with 3 root partitions of 16 GB each.

In the FreeBSD Installer select Install.

The select Auto (UFS) option.

Then use Entire Disk option.

Then select GPT partition table.

The FreeBSD Installer will propose the following solution.

Change it into 3 partitions 16 GB each to make it look like that one below and hit Finish.

Then Commit your choice.

… and then the install process will continue as usual.

Besides these option you may select whatever you choose in the install process.

After the system reboots its gpart(8) will look like that one below.

root@fbsd13:~ # gpart show
=>       40  134217648  ada0  GPT  (64G)
         40       1024     1  freebsd-boot  (512K)
       1064    2097152     2  freebsd-swap  (1.0G)
    2098216   33554432     3  freebsd-ufs  (16G)
   35652648   33554432     4  freebsd-ufs  (16G)
   69207080   33554432     5  freebsd-ufs  (16G)
  102761512   31456176        - free -  (15G)

Now fetch(1) the ufsbe.sh script from its GitHub page.

# fetch https://raw.githubusercontent.com/vermaden/ufsbe/main/ufsbe.sh
# chmod +x ./ufsbe.sh
# ./ufsbe.sh

NOPE: did not found boot environment setup with 'ufsbe' label

INFO: setup each boot environment partition with appropriate label

HELP: list all 'freebsd-ufs' partitions type:

  # gpart show -p | grep freebsd-ufs
      2098216   33554432  ada0p3  freebsd-ufs  [bootme]  (16G)
     35652648   33554432  ada0p4  freebsd-ufs  (16G)
     69207080   33554432  ada0p5  freebsd-ufs  (16G)

HELP: to setup partitions 3/4/5 as boot environments type:

  # gpart modify -i 3 -l ufsbe/3 ada0
  # gpart modify -i 4 -l ufsbe/4 ada0
  # gpart modify -i 5 -l ufsbe/5 ada0

It will welcome you with information about needed setup steps.

We will now make these steps marking all boot environment partitions with appropriate ufsbe labels.

# gpart modify -i 3 -l ufsbe/3 ada0
ada0p3 modified
# gpart modify -i 4 -l ufsbe/4 ada0
ada0p4 modified
# gpart modify -i 5 -l ufsbe/5 ada0
ada0p5 modified

Now ufsbe.sh will setup bootme flag for currently used root (/) partition.

# ./ufsbe.sh
INFO: flag 'bootme' successfully set on / filesystem
usage:
  ufsbe.sh list
  ufsbe.sh activate
  ufsbe.sh sync  

Setup is complete.

All three root partitions have the ufsbe label. To make it more simple the /dev/ada0p3 device gets the ufsbe/3 label and /dev/ada0p4 device gets the ufsbe/4 … you see the pattern.

# gpart show -p -l
=>       40  134217648    ada0  GPT  (64G)
         40       1024  ada0p1  (null)  (512K)
       1064    2097152  ada0p2  swap  (1.0G)
    2098216   33554432  ada0p3  ufsbe/3  [bootme]  (16G)
   35652648   33554432  ada0p4  ufsbe/4  (16G)
   69207080   33554432  ada0p5  ufsbe/5  (16G)
  102761512   31456176          - free -  (15G)

You can now use our UFS Boot Environments on this system.

Using UFS Boot Environments

Lets list our boot environments with list command. The short ‘l‘ option also works.

# ./ufsbe.sh list
PROVIDER LABEL        ACTIVE
ada0p3   ufsbe/3      NR  
ada0p4   ufsbe/4      -   
ada0p5   ufsbe/5      -  

Its output is similar to mine ZFS Boot Environments tools beadm(8). The N flag shows that this is the boot environments we are using NOW. The R flag shows which one we will use after the reboot(8).

Currently only the 3 boot environments is populated (by FreeBSD Installer that is). The 4 and 5 boot environments are empty filesystems.

You can either extract your own FreeBSD version there with base.txz and kernel.txz or use the sync option of ufsbe.sh which will use rsync(1) for the process. Below is an example of syncing boot environment 3 (the one we installed) with currently empty boot environment 4.

# ./ufsbe.sh sync 3 4
NOPE: rsync(1) is not available in ${PATH}
INFO: install 'net/rsync' package or port

# pkg install net/rsync

# ./ufsbe.sh sync 3 4
INFO: syncing '3' (source) => '4' (target) boot environments ...
INFO: boot environments '3' (source) => '4' (target) synced

You can now see that boot environment 3 and 4 have same size.

# df -h
Filesystem     Size    Used   Avail Capacity  Mounted on
/dev/ada0p3     15G    1.3G     13G     9%    /
devfs          1.0K    1.0K      0B   100%    /dev
/dev/ada0p4     15G    1.2G     13G     9%    /ufsbe/4
/dev/ada0p5     15G     32M     14G     0%    /ufsbe/5

If we would like to activate an empty boot environment 5 then ufsbe.sh will not let us do that because that will make our system unbootable. Of course is quote fast/naive check but at least makes sure some files exists on the soon to be active boot environment. Currently these files are checked but this list may be increased in the future:

  • /boot/kernel/kernel
  • /boot/loader.conf
  • /etc/rc.conf
  • /rescue/ls
  • /bin/ls
  • /sbin/fsck
  • /usr/bin/su
  • /usr/sbin/chroot
  • /lib/libc.so.*
  • /usr/lib/libpam.so.*

Below this ‘protection’ in action.

# ./ufsbe.sh activate 5
NOPE: boot environment '5' is not complete
INFO: critical file '/ufsbe/5/boot/kernel/kernel' is missing
INFO: use 'sync' option or copy file manually

The boot environment 4 activation process works as desired as we populated it with files from boot environment 3 first.

# ./ufsbe.sh activate 4
INFO: boot environment '4' now activated

Same as with beadm(8) the ufsbe.sh also checks if boot environment is already activated.

# ./ufsbe.sh activate 4
INFO: boot environment '4' is already active

The list of our boot environments looks like that now.

# ./ufsbe.sh list
PROVIDER LABEL        ACTIVE
ada0p3   ufsbe/3      N   
ada0p4   ufsbe/4      R   
ada0p5   ufsbe/5      -   

… and that is how output of gpart(8) looks like.

# gpart show -p -l
=>       40  134217648    ada0  GPT  (64G)
         40       1024  ada0p1  (null)  (512K)
       1064    2097152  ada0p2  swap  (1.0G)
    2098216   33554432  ada0p3  ufsbe/3  (16G)
   35652648   33554432  ada0p4  ufsbe/4  [bootme]  (16G)
   69207080   33554432  ada0p5  ufsbe/5  (16G)
  102761512   31456176          - free -  (15G)

We will now reboot into the activated boot environment 4.

# shutdown -r now

After the reboot(8) we see that we are now booted from the 4 boot environment.

# ./ufsbe.sh list
PROVIDER LABEL        ACTIVE
ada0p3   ufsbe/3      -   
ada0p4   ufsbe/4      NR  
ada0p5   ufsbe/5      -   

Closing Notes

Keep in mind that this is only first 0.1 version of ufsbe.sh. Do not use it in production or important systems and make sure you have restorable backups. Like with beadm(8) in the past I plan to improve it with more useful options and also add it to the Ports tree in the future.

Feel free to share your thoughts about this tool.

I must wait till midnight to make it shown as posted on 2nd of April because if I would post it on 1st of April it would be taken as April Fool Joke which is definitely not.

Enjoy.

Updating or Upgrading

You may use the Upgrade FreeBSD with ZFS Boot Environments method with these UFS Boot Environments as well but now you will chroot(8) into /ufsbe/4 for example.

EOF

GlusterFS 8 on FreeBSD 13

About two years ago I have made a guide for really old GlusterFS 3.11 version that was available back then on FreeBSD 12.0. Recently I noticed that GlusterFS version in FreeBSD Ports (and packages) is not finally up-to-date with upstream GlusterFS versions.

gluster-logo

This guide will show you how to create GlusterFS 8 distributed filesystem on latest FreeBSD 13. At the moment of writing this article FreeBSD 13 is at RC1 state but it will be released within a month.

While in the earlier guide I created dispersed volume with redundancy comparably to RAID6 but between 6 nodes not disks. This means that 2 of 6 nodes can crash and that GlusterFS would still work without a problem. Today I will show you more minimalistic approach with 3 node setup and a volume that takes space only on nodes node0 and node1 while node2 will be used as an arbiter only and does not hold any data. The arbiter greatly improves split brain problems because instead of vulnerable two node cluster we have a three nodes in the cluster so even if any of them fails we still have 2 of 3 votes.

I will not repeat all ‘initial’ steps needed to prepare these three FreeBSD hosts as it was already described here – GlusterFS Cluster on FreeBSD with Ansible and GNU Parallel – in the older article about that topic. I will focus on the GlusterFS commands that need to be executed to achieve our goal.

We will use several prompts in this guide to show which commands will be executed on which nodes.

  [ALL] # command that will be executed on all node0/node1/node2 nodes
[node0] # command that will be executed on node0 only

GlusterFS

We have three nodes on our lab.

  • node0 - 10.0.10.200 - DATA NODE 'A'
  • node1 - 10.0.10.201 - DATA NODE 'B'
  • node2 - 10.0.10.202 - ARBITER NODE

Install and then enable and start the GlusterFS.

[ALL] # pkg install glusterfs

[ALL] # sysrc glusterd_enable=YES
glusterd_enable:  -> YES

[ALL] # service glusterd start
Starting glusterd.

Enable and mount the /proc filesystem and create needed directories for GlusterFS bricks.

[ALL] # grep procfs /etc/fstab
proc  /proc  procfs  rw  0 0

[ALL] # mount /proc

[ALL] # mkdir -p /bricks/data/{01,02,03,04}

Now connect all these nodes into one cluster and create GlusterFS volume.

[node0] # gluster peer status
Number of Peers: 0

[node0] # gluster peer probe node1
peer probe: success

[node0] # gluster peer probe node2
peer probe: success

[node0] # gluster peer status
Number of Peers: 2

Hostname: node1
Uuid: b5bc1602-a7bb-4f62-8149-98ca97be1784
State: Peer in Cluster (Connected)

Hostname: node2
Uuid: 2bfa0c71-04b4-4660-8a5c-373efc5da15c
State: Peer in Cluster (Connected)

[node0] # gluster volume create data \
  replica 2 \
  arbiter 1 \
  node0:/bricks/data/01 \
  node1:/bricks/data/01 \
  node2:/bricks/data/01 \
  node0:/bricks/data/02 \
  node1:/bricks/data/02 \
  node2:/bricks/data/02 \
  node0:/bricks/data/03 \
  node1:/bricks/data/03 \
  node2:/bricks/data/03 \
  node0:/bricks/data/04 \
  node1:/bricks/data/04 \
  node2:/bricks/data/04 \
  force
volume create: data: success: please start the volume to access data

[node0] # gluster volume start data
volume start: data: success

[node0] # gluster volume info
 
Volume Name: data
Type: Distributed-Replicate
Volume ID: f73d57ea-6f10-4840-86e7-f8178540e948
Status: Started
Snapshot Count: 0
Number of Bricks: 4 x (2 + 1) = 12
Transport-type: tcp
Bricks:
Brick1: node0:/bricks/data/01
Brick2: node1:/bricks/data/01
Brick3: node2:/bricks/data/01 (arbiter)
Brick4: node0:/bricks/data/02
Brick5: node1:/bricks/data/02
Brick6: node2:/bricks/data/02 (arbiter)
Brick7: node0:/bricks/data/03
Brick8: node1:/bricks/data/03
Brick9: node2:/bricks/data/03 (arbiter)
Brick10: node0:/bricks/data/04
Brick11: node1:/bricks/data/04
Brick12: node2:/bricks/data/04 (arbiter)
Options Reconfigured:
storage.fips-mode-rchecksum: on
transport.address-family: inet
nfs.disable: on
performance.client-io-threads: off

[node0] # gluster volume status
Status of volume: data
Gluster process                             TCP Port  RDMA Port  Online  Pid
------------------------------------------------------------------------------
Brick node0:/bricks/data/01                 49152     0          Y       4595 
Brick node1:/bricks/data/01                 49152     0          Y       1022 
Brick node2:/bricks/data/01                 49152     0          Y       3356 
Brick node0:/bricks/data/02                 49153     0          Y       4597 
Brick node1:/bricks/data/02                 49153     0          Y       1024 
Brick node2:/bricks/data/02                 49153     0          Y       3358 
Brick node0:/bricks/data/03                 49154     0          Y       4599 
Brick node1:/bricks/data/03                 49154     0          Y       1026 
Brick node2:/bricks/data/03                 49154     0          Y       3360 
Brick node0:/bricks/data/04                 49155     0          Y       4601 
Brick node1:/bricks/data/04                 49155     0          Y       1028 
Brick node2:/bricks/data/04                 49155     0          Y       3362 
Self-heal Daemon on localhost               N/A       N/A        Y       4604 
Self-heal Daemon on node1                   N/A       N/A        Y       1031 
Self-heal Daemon on node2                   N/A       N/A        Y       3365 
 
Task Status of Volume data
------------------------------------------------------------------------------
There are no active volume tasks
 
[node0] # ps aux | grep -e gluster -e RSS | cut -d ' ' -f 1-27
USER   PID %CPU %MEM   VSZ   RSS TT  STAT STARTED       TIME COMMAND
root  4604  4.0  0.7 64364 22520  -  Rs   21:15     53:50.30 /usr/local/sbin/glusterfs -s localhost --volfile-id shd/data -p
root  4585  3.0  0.7 48264 21296  -  Rs   21:14     56:13.25 /usr/local/sbin/glusterd --pid-file=/var/run/glusterd.pid (glusterfsd)
root  4597  3.0  0.7 66472 22484  -  Rs   21:15     48:54.63 /usr/local/sbin/glusterfsd -s node0 --volfile-id data.node0.bricks-data-02 -p
root  4599  3.0  0.7 62376 22464  -  Rs   21:15     48:23.41 /usr/local/sbin/glusterfsd -s node0 --volfile-id data.node0.bricks-data-03 -p
root  4595  2.0  0.8 66864 23724  -  Rs   21:15     49:03.23 /usr/local/sbin/glusterfsd -s node0 --volfile-id data.node0.bricks-data-01 -p
root  4601  2.0  0.7 62376 22444  -  Rs   21:15     49:17.01 /usr/local/sbin/glusterfsd -s node0 --volfile-id data.node0.bricks-data-04 -p
root  6748  0.0  0.1 12868  2560  2  S+   19:59      0:00.00 grep -e gluster -e

The GlusterFS data volume is now created and started. You can mount it and use it the way you like.

[node2] # mkdir /data

[node2] # kldload fusefs

[node2] # mount_glusterfs node0:/data /data

[node2] # echo $?
0

[node2] # df -h /data
Filesystem    Size    Used   Avail Capacity  Mounted on
/dev/fuse     123G    2.5G    121G     2%    /data

Voila! Mounted and ready to serve.

Tuning

GlusterFS comes without any tuning applied so I suggest something to start with.

[node0] # gluster volume set data client.event-threads 8
[node0] # gluster volume set data cluster.lookup-optimize on
[node0] # gluster volume set data cluster.readdir-optimize on
[node0] # gluster volume set data features.cache-invalidation on
[node0] # gluster volume set data group metadata-cache
[node0] # gluster volume set data network.inode-lru-limit 200000
[node0] # gluster volume set data performance.cache-invalidation on
[node0] # gluster volume set data performance.cache-refresh-timeout 10
[node0] # gluster volume set data performance.cache-size 1GB
[node0] # gluster volume set data performance.io-thread-count 16
[node0] # gluster volume set data performance.parallel-readdir on
[node0] # gluster volume set data performance.stat-prefetch on
[node0] # gluster volume set data performance.write-behind-trickling-writes on
[node0] # gluster volume set data performance.write-behind-window-size 100MB
[node0] # gluster volume set data server.event-threads 8
[node0] # gluster volume set data server.outstanding-rpc-limit 256

That is all in this rather short guide.

Treat it as an addendum to the original GlusterFS article linked earlier.

EOF

Upgrade FreeBSD with ZFS Boot Environments

I am known as a strong ZFS Boot Environment supporter … and not without a reason. I have stated the reasons ‘why’ many times but most (or all) of them are condensed here – https://is.gd/BECTL – in my presentation about it.

The upcoming FreeBSD 13.0-RELEASE looks very promising. In many tests it is almost TWICE as fast as the 12.2-RELEASE. Ouch!

The detailed tests are available on the phoronix.com site.

Having 12.2-RELEASE installed I wanted to check 13.0-BETA* to check if things that are important for me – like working suspend/resume for example – work as advertised on the newer version. It is the perfect task that can be achieved by using ZFS Boot Environments.

In the example below we will create entire new ZFS Boot Environment with clone of our current 12.2-RELEASE system and upgrade it there (in BE) to the 13.0-BETA3 version … and there will only be required on reboot – not three as in typical freebsd-update(8) upgrade procedure.

I assume that you have FreeBSD 12.2-RELEASE installed with ZFS (default ZFS FreeBSD install) and its installed in UEFI or UEFI+BIOS mode.

Here are the steps that will be needed.

(host) # beadm create 13                        # create new '13' ZFS Boot Environment
       Created successfully
(host) # beadm mount 13 /var/tmp/BE-13          # mount new '13' BE somewhere
       Mounted successfully on '/var/tmp/BE-13'
(host) # chroot /var/tmp/BE-13                  # make chroot(8) into that place
  (BE) # mount -t devfs devfs /dev              # mount the devfs(8) in that BE
  (BE) # rm -rf /var/db/freebsd-update          # remove any old patches
  (BE) # mkdir /var/db/freebsd-update           # create fresh dir for patches
  (BE) # freebsd-update upgrade -r 13.0-BETA3   # fetch the patches needed for upgrade
  (BE) # freebsd-update install                 # install kernel and kernel modules
  (BE) # freebsd-update install                 # install userspace/binaries/libraries
  (BE) # pkg upgrade                            # upgrade all packages with pkg(8)
  (BE) # freebsd-update install                 # remove old libraries and files
Β  (BE) # exit                                   # leave chroot(8) environment
(host) # umount /var/tmp/BE-13/dev              # umount the devfs(8) in that BE
(host) # beadm activate 13                      # activate new '13' BE
       Activated successfully

I am using mine sysutils/beadm for the process but you as well may use the bectl(8)Β from FreeBSD base system.

We will also need new FreeBSD loader(8) which will be updated this way – thanks to @JeffSipek for pointing that out.

On my system FreeBSD is installed on ada1 device.

(host) # gpart show -p ada1 | grep efi                # find UEFI msdosfs(5) partition
               40     409600  ada1p1  efi  (200M)     # <-- this one
(host) # mount_msdosfs /dev/ada1p1 /mnt               # mount it under /mnt
(host) # find /mnt                                    # display its contents
       /mnt
       /mnt/efi
       /mnt/efi/boot
       /mnt/efi/boot/bootx64.efi                      # update bootx64.efi file
(host) # cp /boot/boot1.efi /mnt/efi/boot/bootx64.efi # copy from /boot/boot1.efi file
(host) # umount /mnt                                  # unmount /mnt filesystem

There is small chance that you will not be able to mount the efi partition. Even fsck(8) is not able to help here.

Typical errors that some users faced look like that:

(host) # mount_msdosfs /dev/ada1p1 /mnt # error when trying to mount efi partition
       mount_msdosfs: /dev/ada1p1: Invalid argument

(host) # fsck_msdosfs -y /dev/ada1p1    # error when trying to fsck(8) that partition
       ** /dev/ada1p1
       Invalid signature in boot block: 0b6a

If you hit that problem then first backup your current efi partition to for example /BACKUP.ada1p1 file.

(host) # dd < /dev/ada1p1 > /BACKUP.ada1p1 bs=1m

Now we will create fresh efi partition from scratch.

(host) # newfs_msdos -F 32 -c 1 /dev/ada0p1            # create new FAT32 partition
(host) # mount_msdosfs /dev/ada0p1 /mnt                # mount it under /mnt
(host) # mkdir -p /mnt/efi/boot                        # create needed directories
(host) # cp /boot/loader.efi /mnt/efi/boot/bootx64.efi # copy from /boot/loader.efi file
(host) # umount /mnt                                   # unmount /mnt filesystem

Now you should have new ‘working’ efi partition.

The last step is to reboot(8) into the new 13.0-BETA3 system.

(host) # reboot

If you find any problems with new bootloader not being able to load your new FreeBSD then you may alternatively copy the /boot/boot1.efi instead of /boot/loader.efi into the /mnt/efi/boot/bootx64.efi place.

Keep in mind that if you boot from geli(8)encrypted system then /boot/loader.efi is mandatory and you will not be able to boot if you would use /boot/boot1.efi file instead.

Done.

You should now see the new FreeBSD loader(8) in all its glory πŸ™‚

You may now enjoy latest FreeBSD 13.0-BETA3 installation.

Same steps will be required to update to soon to be available FreeBSD 13.0-RC* (RC1/RC2/RC3) version and finally FreeBSD 13.0-RELEASE hopefully somewhere in March 2021.

UPDATE 1 – What if Everything Went Fine

You now have most up to date FreeBSD system that should work faster then 12.2-RELEASE and you still has your older 12.2-RELEASE Boot Environment that you can go back to if you find any problems with 13.0 version.

On my system it looks like that:

(host) # beadm list
       BE   Active Mountpoint Space Created
       12.2 -      -           6.5G 2021-02-12 10:15
       13   NR     /          18.8G 2021-02-13 11:32

The Space column is little misleading as it takes into account snapshots space used for example. To get exact information each Boot Environment takes use -D option. This way you will get information about each Boot Environment space separately.

(host) # beadm list -D
       BE   Active Mountpoint  Space Created
       12.2 -      -            9.8G 2021-02-12 10:15
       13   NR     /            9.6G 2021-02-13 11:32

I will be keeping the 12.2-RELEASE Boot Environment for a while – maybe I will delete it a month or so after 13.0-RELEASE is available but if you tested all your needs and feel that 13.0 fulfills all your needs the same way or better then 12.2-RELEASE then you may delete that older Boot Environment with below command.

(host) # beadm destroy 12.2

UPDATE 2 – What if Something Goes Wrong

Generally if the new BE named ‘13‘ does not boot (or hangs at boot) then just select your earlier Boot Environment that you used before the upgrade – the one that has 12.2-RELEASE inside it.

You now have the system that worked for you before we proceed to the upgrade process.

If that fails (or bootloader is broken) then grab the FreeBSD-13.0-BETA3-amd64-memstick.img image and write it on some pendrive with dd(8) command.

# dd if=FreeBSD-13.0-BETA3-amd64-memstick.img of=/dev/da0 bs=1M status=progress

As you now have the pendrive with FreeBSD 13.0-BETA3 then you may boot from it and fix your installation. Pick LiveCD after its loaded. Then type root at login: prompt and hit [ENTER] for empty password.

The list of tasks that can be done now depends on what is broken and I can not guess every possible error and fix scenario so if you hit any problems during that upgrade process then just contact me with your preferred way and we will figure something out.

EOF

FreeBSD Desktop – Part 22 – Configuration – Aero Snap Extended

I like to post new articles and solutions when I think they are ready. Production tested and stable. Well thought and tested … or at least trying to make things as good as possible in the available time window. Perfectionism definitely does not help making often articles on the blog.

Today’s solution is not perfect but I will ‘ship it’ anyway because good and done is better then perfect. I wanted to rework it so many times that I stopped counting … and I really would like to continue the series – thus I have made a conscious decision to finally release it and hope that maybe someone else will have better ideas to make it better. I really wanted to provide pixel perfect solution with as much screen space used as possible but to deliver it as it is I tested it only on the resolution I use the most – the FullHD one with 1920×1080 pixels.

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

Aero Snap

Today I would like to share with You what I call Aero Snap Extended. The original Aero Snap was introduced in Windows 7 and this is how it is described in the Wikipedia page – “Dragging a window to the right or left side of the desktop causes the window to fill the respective half of the screen. Snapping a window to the top of the screen maximizes it. Windows can be resized by stretching them to touch the top or bottom of the screen, which fully increases their vertical screen estate, while retaining their width, these windows can then slide horizontally if moved by the title bar, or pulled off, which returns the window to its original height. In spite of the “Aero” moniker, this feature is available if one uses the Classic theme. This feature is also available on Windows 10.”

This is like the original Aero Snap looks like.

aero

The idea behind original Aero Snap was pretty simple. Its basically these four shortcuts.

[WIN] + [LEFT] – will place window on the left half of the screen.
[WIN] + [RIGHT] – will place window on the right half of the screen.
[WIN] + [UP] – will maximize the window.
[WIN] + [DOWN] – will minimize the window.

Aero Snap Extended

Mine Aero Snap Extended is … well more extended πŸ™‚

As usual its just a small POSIX /bin/sh compatible shell script. There are only two dependencies for it – the /usr/local/bin/xdpyinfo from xdpyinfo package and /usr/local/bin/wmctrl from wmctrl package. At the beginning of the script you will find several ‘settings’ that you may find needed to be tuned to your needs. Most important ones are MARGIN_TOP/MARGIN_LEFT/MARGIN_RIGHT options. Unfortunately MARGIN_BOTTOM is not implemented. Sorry.

geany-aero

Here are the shortcuts that I use for mine version but You may of course use other key then [WIN] for it.

(L) [WIN] + [LEFT] – will place window on the left half of the screen.
(R) [WIN] + [RIGHT] – will place window on the right half of the screen.
(U) [WIN] + [UP] – will place window on the upper half of the screen.
(D) [WIN] + [DOWN] – will place window on the lower half of the screen.

Here is ASCII diagram for its graphical visualization.

+------+------+  +-------------+
|      |      |  |     (U)     |
|      |      |  |             |
| (L)  |  (R) |  +-------------+
|      |      |  |             |
|      |      |  |     (D)     |
+------+------+  +-------------+

… and also a live screenshots.

aero.800.2a

aero.800.2b

(SL) [WIN] + [SHIFT] + [LEFT] – will place window on the left half of the screen taking 2/3 space of the screen.
(SR) [WIN] + [SHIFT] + [RIGHT] – will place window on the right half of the screen taking 1/3 space of the screen.
(SU) [WIN] + [SHIFT] + [UP] – will place window on the upper half of the screen taking 2/3 space of the screen.
(SD) [WIN] + [SHIFT] + [DOWN] – will place window on the lower half of the screen taking 1/3 space of the screen.

Here is ASCII diagram for its graphical visualization.

+--------+----+  +-------------+
|        |    |  |    (SU)     |
|        |    |  |             |
|  (SL)  |(SR)|  |             |
|        |    |  +-------------+
|        |    |  |    (SD)     |
+--------+----+  +-------------+

… and also a live screenshots.

aero.800.3a

aero.800.3b

The above shortcuts are quite simple and easy to remember.

Now here comes when this is more interesting.

Most keyboards – at least those with the best possible keyboard layout in the world – the ANSI standard keyboard (includes 7-row ThinkPad keyboards – have these three keys one next to another – [CTRL] [WIN] [ALT] – some call the [WIN] key as [SUPER] instead. I use [WIN] as it takes shorter to write and it shows where this key came from.

The 87 keys ANSI stand alone keyboard.

keyboard-ansi

The ThinkPad T420s keyboard.

keyboard-ansi-thinkpad

Now back to topic.

How to use these three keys to send windows to various places of the screen to make it easy to memorize and also not to break existing shortcuts … I think I found a way.

{ [CTRL] [WIN] } [ALT] – these two will send windows to the left side of the screen.

[CTRL] { [WIN] [ALT] } – these two will send windows to the right side of the screen.

Now to the point …

(Q1) [CTRL] + [WIN] + [UP] – will take window to the left and upper part of the screen – taking 1/4 of its space.
(Q2) [CTRL] + [WIN] + [DOWN] – will take window to the left and lower part of the screen – taking 1/4 of its space.
(Q3) [WIN] + [ALT] + [UP] – will take window to the right and upper part of the screen – taking 1/4 of its space.
(Q4) [WIN] + [ALT] + [DOWN] – will take window to the right and lower part of the screen – taking 1/4 of its space.

Now for some the exact 1/4 screen for each of these windows may be not suitable.

Thus I also added a modified versions with [SHIFT] key.

(S1) [SHIFT] + [CTRL] + [WIN] + [UP] – will take window to the left and upper part of the screen – taking 2/3 of horizontal and 2/3 vertical space of the screen.
(S2) [SHIFT] + [CTRL] + [WIN] + [DOWN] – will take window to the left and lower part of the screen – taking 2/3 of horizontal and 1/3 vertical space of the screen.
(S3) [SHIFT] + [WIN] + [ALT] + [UP] – will take window to the right and upper part of the screen – taking 1/3 of horizontal and 2/3 vertical space of the screen.
(S4) [SHIFT] + [WIN] + [ALT] + [DOWN] – will take window to the right and lower part of the screen – taking 1/3 of horizontal and 1/3 vertical space of the screen.

Here is ASCII diagram for its graphical visualization.

+------+------+  +--------+----+
| (Q1) | (Q3) |  |  (S1)  |(S3)|
|      |      |  |        |    |
+------+------+  |        |    |
|      |      |  +--------+----+
| (Q2) | (Q4) |  |  (S2)  |(S4)|
+------+------+  +--------+----+

… and also a live screenshots.

aero.800.1a

aero.800.1b

Now you have about 95% variations of needed windows places in the keyboard shortcuts.

There are also several complementary addons like making the window centered on the screen but without making it cover the whole screen. As I already use other originated from Windows [ALT] + [ESC] shortcut to send the current windows to the ‘back’ I also added [WIN] + [ESC] for this feature.

(C) [WIN] + [ESC] – place current window centered on screen covering about 2/3 of its space.

As it was relatively easy and fast I also added fullscreen option.

(F) [CTRL] + [ALT] + [F] – make current window go fullscreen

+-------------+  +-------------+
|             |  | +---------+ |
|             |  | |         | |
|     (F)     |  | |   (C)   | |
|             |  | |         | |
|             |  | +---------+ |
+-------------+  +-------------+

… and also a live screenshot.

aero.800.4

Usage

The Aero Snap Extended has the following options.

% aero-snap.sh
usage:

  aero-snap.sh OPTION

OPTION(s):

  L - place window on left  half of screen
  R - place window on right half of screen
  T - place window on upper half of screen
  B - place window on lower half of screen

  SHIFT-L - place window on left  half of screen taking 2/3 space
  SHIFT-R - place window on right half of screen taking 1/3 space
  SHIFT-T - place window on upper half of screen taking 2/3 space
  SHIFT-B - place window on lower half of screen taking 1/3 space

  TL - place window to left/upper  part of screen
  TR - place window to left/lower  part of screen
  BL - place window to right/upper part of screen
  BR - place window to right/lower part of screen

  SHIFT-TL - use left/upper  part with 2/3 of H. and 2/3 V. space
  SHIFT-TR - use left/lower  part with 2/3 of H. and 1/3 V. space
  SHIFT-BL - use right/upper part with 1/3 of H. and 2/3 V. space
  SHIFT-BR - use right/lower part with 1/3 of H. and 1/3 V. space

  C - center window covering about 2/3 of screen
  F - make current window go fullscreen
  Q - remove fullscreen property from window

The Aero Snap Extended can be downloaded from here – aero-snap.sh – the usual place for my scripts.

Openbox Integration

Because of WordPress limitation I will not post Openbox configuration here but You will also find a link to that content in the text form below.

openbox-config

Here is this configuration in text form – rc.xml.openbox.aero.config – from the same location.

More then a year after I implemented this way of tiling on Openbox I found out that its also possible to use that ‘natively’ on Openbox using ‘direct’ Openbox configuration rules.

openbox-native

It definitely should be faster and easier to implement – not to mention that external dependencies will not be available – but a script allows more tuning and flexibility.

Other Window Managers

If you are not into Openbox then you may create these shortcuts using xbindkeys for example.

Future Work

Mine Aero Snap Extended could use some polish and especially testing in the other resolutions the the well tested 1920×1080.

Regards.

EOF