Knowledge Base

Preserving for the future: Shell scripts, AoC, and more

Record outbound clicks on web page with small redirect project

I have built a new project which I call outbound. I designed it to redirect users to any outbound links on my blog or elsewhere on my site. This project requires modifying an outbound link to visit a configured location, e.g., /outbound/

As a minimal effort to reduce pointless traffic, a link will only redirect if the referer is in a whitelist configured by the admin.

The idea is to log to regular web server logs (apache, nginx, etc.) redirects. The admin can just view all http response 307 visits for path /outbound/.

To build a link, the page author needs to include the protocol after the prefix, so /outbound/ is good, but /outbound/ makes the link invalid.

I plan on using links like this in the future, so I can get some insights into what outbound links my audience uses, that is, if I have an audience.

For testing purposes, here are some outbound links in different formats, for testing my CMS (Nikola):

Custom search url in Firefox with bookmark

You can make a custom "search engine" with a bookmark in the web browser. Doing so makes it possible to type in the keyword followed by space and then the search query.

Make a custom bookmark with a keyword and with %s in the url that represents the placement of the search expression.

Then, when you visit your new "search engine" bookmark, it sends you to the url!

Supporting Linux desktop support clients with x11vnc, Wireguard, and Remmina

I have a Linux desktop support customer! (Read: I have a friend for whom I set up a Ubuntu desktop system. It's not ideal I realize, but it's better than Windows.)

On his Ubuntu desktop, I set up Wireguard as a peer to my main wg peer on my network. When his computer is on, it automatically connects. If he needs help where I need to see his screen, I connect over ssh and forward a port:

ssh -L 5900:localhost:5900

And then once there I su - customername and start x11vnc.

x11vnc -display :0 -once -localhost

And now on my client side I run Remmina and connect to localhost as type vnc. And then I can work on the same console session that my customer sees, while we're on the phone together.


I already had a wireguard peer set up on my network for a multitude of reasons. Adding wireguard to autostart Ubuntu is well-established and outside the scope of this document. I remember reading in the past about some way to connect to an existing X11 console session, and x11vnc is the solution for that type of operation. Teamviewer is not FLOSS, and I gave it up years ago. Before that, I used LogMeIn.

I finally started using autofs for my network mounts!

In the past, I wrote about my ripped-off myautomount program which was a bash rewrite of a Go tool from TridentOS.

One main use of autofs is to automount network locations. I of course have my own nfs server and several mounts that are useful on all my clients. Here is what I set up for myself:

File /etc/autofs.internal-wireless.

* -fstype=nfs,noatime,rw,nosuid,rsize=262144,wsize=262144,soft storage3:/var/storage3/shares/&

And file /etc/auto.master.d/internal-wireless.autofs.

/net  /etc/autofs.internal-wireless --timeout=5

I also set the user's xfe bookmarks to include /net/$USERNAME manually. I don't currently use nfs-mounted home directories, but each user has a primary export on the file server. For future reference, an Xfe bookmark is simply in file ~/.config/xfe/xferc:


Where $USERNAME is of course fully evaluated already, so /mnt/bgstack15.

Use "Remote Printer" driver for cups-shared printer in cups client

I use a cups print server to share a USB-connected printer. One of my new network clients needed the printer set up, and of course my client runs cups too. An existing cups client uses the printer with a "remote printer" driver that works well, and the closest model number in the built-in list after installing the generic, distro-provided package for this brand printed the page incredibly wrong.

So, I spent time learning how to set up the cups client to use "Remote Printer (grayscale, 2-sided printing)" driver, which presumably then lets the cups server use the correct driver I would have set up at least once on the real print server.

On the cups client, visit the cups web interface, normally http://localhost:631, and navigate to Administration -> add printer.

Select ipp printer type, and add your network printer: Mine was ipp:// Add name, etc. Now, on the cups page where you select make and model or PPD file, select "Raw" -> IPP Everywhere. Then select button "Add Printer."


  1. CUPS: Share printer with generic driver - Unix & Linux Stack Exchange

Fluxbox show "(on $HOSTNAME)" if X11 forwarded program

I solved my problem from last time! I wrote a patch for Fluxbox to add the "(on $CLIENT)" message to titlebars of X11-forwarded client windows. See the source, and the debian/ for building a dpkg on my cgit instance (master branch).

Just in case that ever goes away (and somehow this blog doesn't), here's the source:

Author: bgstack15
Date: 2022-11-09
Version: fluxbox 1.4.0
Source: original
Summary: Add "(on $CLIENT)" to titlebar for forwarded windows
Inspired by xfwm4's ability to display the remote host running an X11 window. This fails on xfe which somehow lacks the WM_CLIENT_MACHINE property.
--- a/src/
+++ b/src/
@@ -43,6 +43,51 @@ using std::endl;

 namespace Xutil {

+FbTk::FbString getWMClientMachine(Window window) {
+    if (window == None)
+        return FbTk::FbString("");
+    Display *display = FbTk::App::instance()->display();
+    XTextProperty text_prop;
+    text_prop.value = 0;
+    char **list = 0;
+    int num = 0;
+    _FB_USES_NLS;
+    FbTk::FbString name;
+    if (XGetWMClientMachine(display, window, &text_prop)) {
+        if (text_prop.value && text_prop.nitems > 0) {
+            if (text_prop.encoding != XA_STRING) {
+                text_prop.nitems = strlen((char *) text_prop.value);
+                XmbTextPropertyToTextList(display, &text_prop, &list, &num);
+                if (num > 0 && list != 0)
+                    name = FbTk::FbStringUtil::LocaleStrToFb(static_cast<char *>(*list));
+                else
+                    name = text_prop.value ? FbTk::FbStringUtil::XStrToFb((char *)text_prop.value) : "";
+                if (list)
+                    XFreeStringList(list);
+            } else
+                name = text_prop.value ? FbTk::FbStringUtil::XStrToFb((char *)text_prop.value) : "";
+            XFree(text_prop.value);
+        } else { // default name
+            name = _FB_XTEXT(Window, Unnamed, "Unnamed", "Default name for a window without a WM_NAME");
+        }
+    } else {
+        // default name
+        name = _FB_XTEXT(Window, Unnamed, "Unnamed", "Default name for a window without a WM_NAME");
+    }
+    return name;
 FbTk::FbString getWMName(Window window) {

     if (window == None)
--- a/src/Xutil.hh
+++ b/src/Xutil.hh
@@ -28,6 +28,7 @@

 namespace Xutil {

+FbTk::FbString getWMClientMachine(Window window);
 FbTk::FbString getWMName(Window window);

 FbTk::FbString getWMClassName(Window win);
--- a/src/
+++ b/src/
@@ -49,6 +49,7 @@
   #include <string.h>

 using std::string;
 using std::list;
@@ -217,6 +218,10 @@ bool WinClient::getAttrib(XWindowAttribu
     return XGetWindowAttributes(display(), window(), &attr);

+bool WinClient::getWMClientMachine(XTextProperty &textprop) const {
+    return XGetWMClientMachine(display(), window(), &textprop);
 bool WinClient::getWMName(XTextProperty &textprop) const {
     return XGetWMName(display(), window(), &textprop);
@@ -319,7 +324,14 @@ void WinClient::updateTitle() {
     if (m_title_override)

-    m_title.setLogical(FbTk::FbString(Xutil::getWMName(window()), 0, 512));
+    FbTk::FbString fullname = FbTk::FbString(Xutil::getWMName(window()), 0, 512);
+    FbTk::FbString clientmachine = FbTk::FbString(Xutil::getWMClientMachine(window()), 0, 512);
+    char *host = new char[512]; gethostname(host, 512);
+    FbTk::FbString hostname = FbTk::FbString(host);
+    if (clientmachine != "Unnamed" && clientmachine != "" && clientmachine != hostname) {
+        fullname += " (on " + clientmachine + ")";
+    }
+    m_title.setLogical(fullname);

@@ -328,7 +340,14 @@ void WinClient::emitTitleSig() {

 void WinClient::setTitle(const FbTk::FbString &title) {
-    m_title.setLogical(title);
+    FbTk::FbString fullname = title;
+    FbTk::FbString clientmachine = FbTk::FbString(Xutil::getWMClientMachine(window()), 0, 512);
+    char *host = new char[512]; gethostname(host, 512);
+    FbTk::FbString hostname = FbTk::FbString(host);
+    if (clientmachine != "Unnamed" && clientmachine != "" && clientmachine != hostname) {
+        fullname += " (on " + clientmachine + ")";
+    }
+    m_title.setLogical(fullname);
     m_title_override = true;
--- a/src/WinClient.hh
+++ b/src/WinClient.hh
@@ -91,6 +91,7 @@ public:

     bool getAttrib(XWindowAttributes &attr) const;
+    bool getWMClientMachine(XTextProperty &textprop) const;
     bool getWMName(XTextProperty &textprop) const;
     bool getWMIconName(XTextProperty &textprop) const;
     std::string getWMRole() const;

And here's the readme:

Readme for fluxbox


This is for my customized dpkg of Fluxbox which exists quite happily in vanilla form in Debian Sid.

fluxbox upstream

I modified the debian/ from

This set of overlay patches probably will not be maintained, so user beware! That being said, upstream is frozen so you won't get behind here either.

Reason for being in stackrpms

I wrote exactly one patch: debian/patches/add-clientmachine-if-forwarded.patch Also by using the custom package here I can incorporate all the useful patches added in what appears to be a neo-upstream on github which has neat patches like toolbar: allow labeled general action buttons and document iconified title deco which are not present in the Debian Fluxbox 1.3.5 release.

I chose Fluxbox as my daily driver desktop environment/window manager because it is stable. And it is stable, with a few minor flaws!

So this one patch I wrote adds to the titlebar of a forwarded window "(on $CLIENT)" which was inspired by Xfwm4.


  • Add a configurable option for "Show (on $CLIENT)" so users can decide if they like it.
  • Some programs do not properly maintain WM_CLIENT_MACHINE X property, like xfe(1) so that could be misleading.
  • Maybe store local hostname on the Display, like Xfwm4 so we do not need to keep calling gethostname()
  • Find way to rearrange the iconbar window entries (issue #94 in original repo) which was also requested in one of the github forks (luebking/fluxbox#1 with comments:

If you however mean to drag around the icon, that's probably not too hard to do in src/Icon{Button,barTool}*


Just use the native package fluxbox for the given distro.

Github indicates a large number of forks exist of the source. Almost all of them do not provide substantive improvements.


Exact same as native package fluxbox.


Every link in this document. Official upstream link?:

Differences from upstream

Only one d/p/series and d/p/add-clientmachine-if-forwarded.patch

Call for help: Fluxbox display "(on $HOSTNAME)" for X11 forwarding

I recently discovered that my X11-forwarded client windows do not display the appended string "(on $CLIENT)" like I recall seeing in the past.

Upon some research, including a Unix Stack Exchange question, I learned that it depends on the window manager! It's not a built-in of Xorg.

Xfwm4 file client.c#215 adds this bit inside function clientCreateTitleName().

Fluxbox file in function WinClient::updateTitle() would be where you add the logic for adding "(on $CLIENT)" string.

If anybody likes C++ development and wants to write me a custom patch and earn my dying thanks, I would greatly appreciate it! Maybe someday I'll learn how to do this part. If a patch for this ever gets written, I would have to build fluxbox myself with the patch, which I am willing to do.


krb5-auth-dialog and the news

With the most recent month's OS updates for Devuan GNU+Linux, I discovered that krb5-auth-dialog has now been updated for the first time in 4+ years!

The GNOME people have now removed the tray icon, which is the entire reason I wanted the software! So I downgraded to krb5-auth-plugin=3.26.1-4 and that now behaves like I want it to.

I was perusing /r/linux (that's a subreddit, if the syntax is unfamiliar to you) and came across Kerberos authentication on the Librem 5 which links to a Purism blog post by Guido Günter, one of the maintainers of krb5-auth-dialog. The screenshots in his article about kerberos on a Purism phone show krb5-auth-dialog, updated for a GTK4 and mobile world! I'm sure his changes fit nicely with that paradigm, and it's good that the software is still maintained.

That being said, its modern incarnation is useless on a real workstation so I reverted it. I had to download it and store it in a local apt repository.

Maybe someday I will fork krb5-auth-dialog into krb5-auth-trayicon and merge any changes (such as build with meson instead of GNU Make) that do not relate to deleting the tray icon. There are 122 commits and 119029 lines in the git diff between branches.

Devuan updates for November 2022 and sssd error

After running OS updates on Devuan unstable, I got this failure.

(2022-10-31 10:09:50): [be[]] [dp_load_module] (0x0400): About to load module [ipa].
(2022-10-31 10:09:50): [be[]] [dp_module_open_lib] (0x1000): Loading module [ipa] with path [/usr/lib/x86_64-linux-gnu/sssd/]
(2022-10-31 10:09:50): [be[]] [dp_module_open_lib] (0x0010): Unable to load module [ipa] with path [/usr/lib/x86_64-linux-gnu/sssd/]: cannot open shared object file: No such file or directory
(2022-10-31 10:09:50): [be[]] [dp_load_module] (0x0020): Unable to create DP module.
(2022-10-31 10:09:50): [be[]] [dp_target_init] (0x0010): Unable to load module ipa
(2022-10-31 10:09:50): [be[]] [dp_load_targets] (0x0020): Unable to load target [id] [80]: Accessing a corrupted shared library.
(2022-10-31 10:09:50): [be[]] [dp_init_done] (0x0020): Unable to initialize DP targets [1432158209]: Internal Error

Needed to add file /etc/apt/sources.list.d/temp.list with contents.

deb [check-valid-until=no] unstable main contrib

And then downgrade samba-libs, either with aptitude which can dynamically identify other dependencies to also downgrade, or just with apt-get.

sudo apt-get install libsmbclient=2:4.16.5+dfsg-1 samba-libs=2:4.16.5+dfsg-1

Downgrading sssd to 2.7.4-1 from 2.7.4-1+b1 is not necessary.

I could have avoided this this time by running this first:

sudo apt-mark hold samba-libs

Send https request with openssl s_client

Inspired by

To send a simple http get with openssl s_client, use this template.

sed -r -e 's/$/\r/;' <<EOF | openssl s_client -connect -ign_eof
GET /internal/directory.html HTTP/1.1
Connection: close


Or with printf.

printf 'GET /internal/directory.html HTTP/1.1\r\nHost:\r\nConnection: close\r\n\r\n' | openssl s_client -connect -ign_eof

Here is a sample post:

sed -r -e 's/$/\r/;' <<EOF | openssl s_client -connect -ign_eof
POST /coupons/search/ HTTP/1.0
Connection: close
Content-Type: text/plain;charset=UTF-8
Accept: text/plain