Category Archives: Technology

Cloning OpenWrt

OpenWrt is very versatile and very modular. For that reason, OpenWrt setups can be hard to replicate. While configurations are easy to export and import, the packages present on the source system may or may not be present on the target  system. To get around this, we can use a two-step process described below.

Step One: get a list of packages installed on the source system. Log in to the source system and run the following from the command line:

opkg list-installed | awk '{ printf "%s ",$1 }' && echo

This will generate a list of packages installed on the system in one big blob of text. The echo command will make sire that this blob ends in a line break (otherwise, the command prompt will appear right after the package list). Anyway, copy that blob into your computer’s clipboard or a text file

Step Two: get prepackaged firmware for the target system. Go to OpenWrt Firmware Selector:

Find your target system in the list (for example, if you need firmware for an x86 system, start typing x86 into the selection line and see what falls out). When you found your system, click on its name. In the window that opens, click on Customize installed packages. This will open a textbox with a list of packages in it. Replace that list with the one  you generated in Step One, click on Request Build, wait for the firmware to be compiled, and when it’s ready, download it and install it on your target system.

If the target system already has a base OpenWrt system running, you can do an alternative Step Two: simply feed the list of packages you generated in Step One to opkg on your target system:

opkg update && opkg install [paste the list here]

After that, you can import configuration exported from the source system.

Webmin on Ubuntu 22.04 LTS

Some time ago, Debian and Ubuntu changed their security key management architecture. As a result, the procedure for setting up Webmin using a signed repository also changed. Here’s what Webmin developers recommend.

First, set up the Webmin repository by adding the following line into the /etc/apt/sources.list file:

deb sarge contrib

Then, run the following commands as root:

cd /root
cat jcameron-key.asc | gpg --dearmor > /usr/share/keyrings/jcameron-key.gpg
apt-get install apt-transport-https
apt-get update
apt-get install webmin

On my Ubuntu Server 22.04 LTS, however, this didn’t work; apt-get, when invoked, complained about unsigned Webmin repository and refused to download Webmin. This is because on my installation (and probably on others as well, as mine is pretty generic), apt-get looks for keys not in /usr/share/keyrings, but in /etc/apt/trusted.gpg.d. So the commands that would have worked on my Ubuntu Server are:

cd /root
cat jcameron-key.asc | gpg --dearmor > /etc/apt/trusted.gpg.d/jcameron-key.gpg
apt-get install apt-transport-https
apt-get update
apt-get install webmin

The only command that’s different is the third one that starts with cat. The rest is perfectly fine as is.

Alternatively, after doing what Webmin developers suggest and encountering the error, we could simply copy /usr/share/keyrings/jcameron-key.gpg, into /etc/apt/trusted.gpg.d and then run the apt-get commands again… (This is what I ended up doing, since I already had the key on my system, it just needed to be in the right place.)

Even more alternatively, rather than put the key where apt-get expects is to be, we could explicitly tell apt-get where the key actually is. To do that, we would go back to /etc/apt/sources.list and edit the line we added at the beginning of the setup procedure:

deb [signed-by=/usr/share/keyrings/jcameron-key.gpg] sarge contrib

This should point  apt-get in the right direction…

Fireboxing (X750e Core edition)

On hand: a gracefully aging Watchguard Firebox X750e Core network appliance running the manufacturer’s proprietary Fireware 10 firmware.

The problem: both the box and the firmware are past end of life set by the manufacturer. Also, Fireware is rather impractical for small and/or heterogeneous deployments.

The question: can this unit still work?

The short answer: yes. Continue reading

Ripping a CD, old-school style

I recently needed to rip an audio CD (yes, those things still exist). Here’s what it took using Linux command line on an Ubuntu derivative distribution.

Step 1. Install the necessary software:

sudo apt-get install cdparanoia lame

There are two pieces of software being installed here; cdparanoia will copy audio tracks from the CD into *.wav files, while lame will convert *.wav files to a more compact *.mp3 format.

Step 2. Insert the CD into the drive and see if cdparanoia can read it:

cdparanoia -vsQ

If the CD is readable, a bunch of data about the disk and a listing of tracks will be output.

Step 3. The actual ripping of the CD:

cdparanoia -B

This will create a series of *.wav files in the current directory. The files will be named track01.cdda.wavtrack02.cdda.wav, and so forth. They can be renamed if necessary, but for now, we’ll just let them be.

Step 4. Make the *.mp3 files using lame.

There’s a small problem with lame; it expects to work with one file at a time, like this:

lame track01.cdda.wav

To work around it, we can ask lame to work inside a loop. Say, we have a bunch of *.wav files in a directory and we want encode them all into *.mp3. This can be accomplished using a shell loop:

for t in *.wav; do lame $t; done

If we only want to encode, say, first three tracks we just ripped, we can specify a more restrictive track selection pattern:

for t in track{01..03}*.wav; do lame $t; done

When the command completes, the current directory will contain *.mp3 files with names matching the names of *.wav files we asked lame to encode. For example, there will be track01.cdda.mp3 next to track01.cdda.wavtrack02.cdda.mp3 next to  track02.cdda.wav, and so on.

Concluding note. Both cdparanoia and lame have plenty of command-line options not covered here. Using those options, one can rip selected tracks or even parts of a track, specify bitrate and mode for the encoding, and lots of other things…

Another networking adventure…


A no-name mini-PC is being prepared for use as a “headless” development/testing environment running Debian. The machine must connect to the local network using Wi-Fi.


The machine does not appear to have a Wi-Fi controller. Running

lspci -nn

provides no information about a Wi-Fi device of any kind. At the same time, a look into BIOS reveals that a Wi-Fi card is present; BIOS identifies it as AP6255. A quick Internet search later, another revelation: this is a Broadcom product licensed to a variety of third parties to sell under white labels. I should have known… Welcome to another Broadcom-themed adventure in networking!

Cause of the problem

The Wi-Fi controller is indeed present, but it does not communicate to the rest of the system via the customary PCI, so lspci cannot detect it. Rather, it uses an alternate communication method called “SDIO/USB”, aka “SDIO over USB”. So our system must have the firmware/drivers that support this method, rather than those that support the more conventional PCI.


We begin by connecting the machine to the local network (and the Internet) with an Ethernet cable; the machine will need an Internet connection to download the necessary software. Also, the administrator will need root-level access to the system. Commands given below assume that root access is available, but they can be used with sudo if necessary, and it shouldn’t make any difference.

STEP 0 (wasn’t necessary in my case, but may be needed if other solutions were tried before to no avail). Uninstall potentially conflicting packages:

apt-get remove broadcom-sta-common broadcom-sta-source firmware-b43*

Note the star symbol at the end; it tells apt-get to uninstall all packages whose names start with firmware-b43.

STEP 1. Install the package containing the appropriate firmware/driver:

apt-get install broadcom-sta-dkms

(Note: in Ubuntu, the equivalent package is named differently, so you should do apt-get install bcmwl-kernel-source instead.)

STEP 2. Enable the kernel module responsible for SDIO/USB communication between the Wi-Fi card and the rest of the system:

modprobe brcmfmac

STEP 3. Test the progress:


The output of this command should contain at least a mention of a Wi-Fi device (wlan0 or something similar). This will indicate that the system has recognized the Wi-Fi device. Note the name of the Wi-Fi device; it will be used in later steps. For the remainder of this solution, we will use wlan0.

STEP 4. Install WPA Supplicant:

apt-get install wpasupplicant

STEP 5. Edit the configuration file /etc/network/interfaces; add the following to the end of the file:

allow-hotplug wlan0
iface wlan0 inet dhcp
    wpa-ssid MyNetworkName
    wpa-psk MyNetworkPassword

Obviously, MyNetworkName and MyNetworkPassword should be replaced with the SSID name for the local wireless network and the password for this network, respectively. Also, remember to replace wlan0 with the name you learned in Step 3.

STEP 6. Bring up the Wi-Fi interface (again, remember to replace wlan0 with the name you learned in Step 3):

ifup wlan0

STEP 7. Verify that the system operates as desired. To do that, shut the system down:

shutdown now

When the system shuts down, disconnect the Ethernet cable and start the system again. It should connect to the specified local network and obtain a local IP address assigned to it by the local DHCP server. If you have a keyboard and monitor temporarily attached to the system, run ip a to see connection status, including the local IP address; if not, scan the network to determine your machine’s local IP address and use it to log in remotely.

The simplest URL rewrite ever?

This simple code snippet, if placed into an .htaccess file, would rewrite an alphanumerical “tail” of a URL into a variable accessible to an index.php residing in the same directory:

RewriteEngine On
RewriteRule ^([a-zA-Z0-9]+)$ index.php?tail=$1

For example, let’s say the the two files reside inside this directory:

Then, a user accessing this URL:

would see the output of this script:

Note that the “tail” must be alphanumerical (i.e., contain only letters and numbers).

AnyDesk on Linux, with a twist


A remote machine is running Ubuntu Desktop. The machine is accessible via SSH. It is necessary to ensure remote desktop access using AnyDesk.

Solution, step by step

Step 1. Log into the remote system and switch to root (alternatively, do not switch to root, but use the commands below with sudo).

Step 2. Install AnyDesk. (There’s more than one way to do it; we’ll set up a repository, so AnyDesk can be updated along with the rest of the software on the machine.)

wget -qO - | apt-key add -
echo "deb all main" > /etc/apt/sources.list.d/anydesk-stable.list
apt update
apt install anydesk

Step 3. Retrieve AnyDesk installation ID (it will be required for remote connections):

anydesk --get-id

As of this writing, the installation ID us a string of nine digits (e.g., 123456789). You will need this string to connect to the newly installed AnyDesk, so you should write it down at this stage.

Step 4. Configure AnyDesk to run as a service and set up a password (let’s say, the password will be MyNewPassword) for unattended remote access:

anydesk --stop-service
echo MyNewPassword | anydesk --set-password
anydesk --service --silent

The first command stops AnyDesk service (may not be necessary, but hey, why not?). The second command sets the password by piping it to the AnyDesk utility (this is how AnyDesk recommends doing it). The third command starts the AnyDesk service in the silent mode (no pop-up messages).

Step 5. Connect to the new remote AnyDesk installation using the existing local installation.

a. Use the ID obtained in Step 3 to connect:

b. When asked, enter the password you set in Step 4:

At this stage, you should be able to see the Ubuntu desktop of the remote machine and control it the same way you would control it locally.

Navigating the insides of LibreOffice

LibreOffice has Indent and Unindent functionality built-in. But what if you want to manage hanging indent the way it’s done in Microsoft Word, with Ctrl-T and Ctrl-Shift-T keystrokes? Here’s a pair of macro functions that do the work (they will need to be assigned to keystrokes using the Customize functionality in LibreOffice):

Sub HangingMore()
  oCursor = ThisComponent.CurrentController.getViewCursor()
  oCursor.ParaLeftMargin = oCursor.ParaLeftMargin + 1270
  oCursor.ParaFirstLineIndent = oCursor.ParaFirstLineIndent - 1270
End Sub

Sub HangingLess()
  oCursor = ThisComponent.CurrentController.getViewCursor()
  oCursor.ParaLeftMargin = oCursor.ParaLeftMargin - 1270
  oCursor.ParaFirstLineIndent = oCursor.ParaFirstLineIndent + 1270
End Sub

The macros are basically mirror images of each other. Each begins by capturing the properties of wherever the text cursor is into the oCursor variable. Those properties are then manipulated directly. The names of those properties should be self-explaining; the only trick is, margins and  indents are stored in 100ths of a millimeter. In other words, the number 1270 corresponds to 1.27 cm, or half-inch. Metrically-minded users may want to change this to the nice round 1000…

Restoring lost Wi-Fi connectivity on Linux

Situation: an aging Dell Optiplex machine running Pop!_OS has lost its Wi-Fi connectivity following a kernel upgrade.

A piece of background knowledge: Pop!_OS relies on Network Manager to manage Wi-Fi connectivity. This will be important in the later stages (steps 4 and 5 below), but has no bearing on the earlier stages.

Step-by-step solution: connect the computer to the LAN by cable, log in as root (or use sudo if you prefer), and complete the following steps.

STEP 1. Get the list of PCI devices installed on the machine:

# lspci -nn

Review the output and identify the line that describes the Wi-Fi card. In our case, the relevant line is:

03:00.0 Network controller [0280]: Broadcom Inc. and subsidiaries 
  BCM4312 802.11b/g LP-PHY [14e4:4315] (rev 01)

STEP 1 RESULT: we know that our Wi-Fi card is manufactured by Broadcom and its hardware ID is 14e4:4315.  (incidentally, 14e4 is the code for Broadcom and 4315 is the code for the model of the device.)

STEP 2. Figure out what driver and firmware are required for the Wi-Fi card identified in Step 1. Start at Linux Wireless:

One by one, open pages for products made by the relevant manufacturer until you find the page for the driver that matches the hardware ID determined in Step 1 (or simply search the site for the hardware ID). In our case, the driver for the 14e4:4315 card is b43. A quick Internet search further reveals that the driver b43 is a part of package firmware-b43-installer, which needs a companion package, linux-firmware, to work.

STEP 2 RESULT: we know what driver and firmware we need .

STEP 3. Purge the package bcmwl-kernel-source (it’s probably the culprit that broke the system in the first place), install the driver and the firmware, and reboot the machine:

# apt-get purge bcmwl-kernel-source
# apt-get install firmware-b43-installer
# apt-get install linux-firmware
# reboot

STEP 3 RESULT: the necessary driver and firmware are now installed on the machine.

Up tp this point, we did not rely on any specific network management software. Steps 4 and 5 below are  specific to Network Manager; other network management utilities, such as connman, wicd, or wpa_supplicant, would have their own procedures to achieve the same end: connection to a wireless network.

STEP 4. Check if the Wi-Fi is working:

# nmcli dev wifi

STEP 4 RESULT: a list of available wireless networks is displayed. in the terminal

STEP 5. Connect to the desired wireless network:

# nmcli dev wifi connect [SSID] password [PASSWORD] ifname [INTERFACE]


  • [SSID] is the name of the wireless network
  • [PASSWORD] is the password to access the network
  • [INTERFACE] the name of wireless network interface (in our case, wlan0)

The actual command would look something like this:

# nmcli dev wifi connect MyWiFi password 1234567890 ifname wlan0

STEP 5 RESULT: we have a working WiFi connection.

STEP 6. Reboot to verify that the connection persists.

# reboot

STEP 6 RESULT: we have a working WiFi connection that persisted over a reboot.

Make Samba servers visible

Many system administrators have grown to love Samba, a piece of Linux software that allows to use Linux machines as file and print servers compatible with Windows networking. There is, however, an annoying problem with Samba machines: they are not automatically discovered on a Windows network (in other words, when a user clicks on the Network icon in File Explorer, Samba machines do not appear on the list, although they are accessible via “manual” addressing). To fix this problem, administrators can use wsdd:

To install wsdd on Debian and derivatives, follow these simple steps.

Before installing, check for the latest version of the package by going to As of this writing, the latest version available there is wsdd_0.6.1_all.deb, so we will install it on our system

Once you know which version you are about to install, issue these commands from the terminal (assuming you are logged in as root; if not, simply add sudo at the beginning of each command):

dpkg --install wsdd_0.6.1_all.deb
systemctl start wsdd
systemctl enable wsdd
systemctl status wsdd

Assuming everything went well, the last command will produce output that looks like this:

● wsdd.service - Web Services Dynamic Discovery host daemon
   Loaded: loaded (/lib/systemd/system/wsdd.service; enabled; vendor preset: enabled)
   Active: active (running) since Fri 2020-09-28 15:46:16 PDT; 22h ago
 Main PID: 16146 (python3)
    Tasks: 1 (limit: 4915)
   Memory: 7.8M
   CGroup: /system.slice/wsdd.service
           └─16146 python3 /usr/bin/wsdd

Be sure that the Loaded: line contains the word enabled; it indicates that the service you just installed will start again when the entire system restarts.

A few months later…

WSDD can be started with a variety of command-line options. Those options are specified in /etc/wsdd.conf. Here’s what I ended up using based on my local situation:

# command line parameters for wsdd 
WSDD_PARAMS="-i wlan0 -p -4 -w MYWORKGROUP"

-i wlan0 tells WSDD to listen on the wireless interface (my Samba server sits on a wireless network)

-p instructs WSDD to announce the server’s name as is (i.e., without converting it to upper or lower case)

-4 tells WSDD to work with IPv4 addresses only (i.e., not to worry about IPv6)

-w MYWORKGROUP indicates that the server belongs to MYWORKGROUP (obviously, the name of the actual workgroup has been changed to protect the innocent…)