Skip to main content

Why BSDs?

Every week or two, a post seems to pop up on one of the BSD-related sub-reddits where I hang out (FreeBSD, OpenBSD, NetBSD, & BSD) asking why folks would choose a BSD over a Linux distribution. Having answered the same question multiple times, I figured the time had come to post my "why" here.

Skip the history and jump to the push/pull

Early Unix experiences (1987–1994)

I'd grown up on Apple DOS 3.3 & ProDOS, then moved to MS-DOS 4.x and following. But then I had taste of Unix via our local college's dial-in shell servers and Unix labs. Using a Unix command-line felt similar, but as if crafted with design and intent. Pieces played together nicely. Programs multitasked in ways that made sense (and I could never do on DOS). Countless late nights via 1200 baud dial-up. I became hooked.

Initial installation & exploration (1995–1996 school year)

After downloading umpty-gazillion 3½" floppies and schlepping them back to my dorm, an older CompSci classmate helped me install Slackware on my computer. That powerhouse 486DX/100 with 32MB of RAM and two 512MB hard-drives (a whole GIGABYTE, baby!). To this day, I still have a dislike of Emacs that might stem from the E-series Slackware floppies getting corrupted, driving me back to the lab to download and write fresh disks just so Emacs would install.

Meanwhile, my favorite campus computer lab held networked DEC Ultrix workstations running X at mind-blowing resolutions and color-depth compared to the 800x600 SVGA graphics on my personal computer. A real Unix.

While I enjoyed having Slackware, the lack of internet access in the dorm room made it a challenge to make productive use of it. DOS (with Windows 3.1 on demand) at least let me write papers in WordPerfect 5.1 and take the files to labs to print them out. But then I discovered HTML. It felt like WordPerfect's Reveal Codes functionality, letting me clearly see what my document contained under the hood. No hidden stray markup, causing images to misalign or change the spacing or bold/italicize/underline the wrong thing. I could also write it in a normal text editor, whether on DOS, in Windows, or in my Slackware install (modulo line-ending concerns), letting it become more useful. In addition to those benefits, while the computer labs charged $0.07 per page to print, I discovered that the college library let me print "web resources" for free. Guess who could point the web-browser at his paper on the floppy drive, open it as a "web resource" and print it for free?

College experimentation

As college progressed, I tried installing and reinstalling other flavors of Linux. Red Hat 8 ("Psyche") & Mandrake had a great install experience, but RPM had issues that required me to manually install package dependencies. Download the .rpm file, try to install it, discover missing dependencies, download those .rpm files, install, rinse, repeat until things finally installed.

I also tried installing FreeBSD (Walnut Creek CD-ROMs, around version 2.x) in this time-frame. However I failed to figure out the installer. With the benefit of hindsight, I know the primary issue stemmed from "partition" meaning one thing in DOS & Linux, while meaning a different thing in FreeBSD (where "slices" referred to what I knew as MBR "partitions" in DOS, while FreeBSD referred to subdivisions of one of those "slices" as "partitions"). Had I understood the differing terminology at the time, I might have successfully installed FreeBSD.

Post college Linux

Now out of college and married, we ordered a new Gateway Solo 1200 laptop. An 800MHz Celeron processor, 128MB of RAM, and 10GB of disk-space! It came with Windows ME, a horrible OS, but with WinModem drivers that worked where Knoppix and other attempts at Linux refused to get online. Once we had a DSL connection in the apartment, I maxed out the RAM to 320MB, swapped in a 120GB hard-drive, and installed Debian which served us well for many years.

Curious about Apple hardware & operating systems, we picked up an Apple iBook G4, the last of their PPC line, running at 1.3GHz, maxed out with 1.5GB of RAM, and a 30GB hard-drive.

The Mac drove me bonkers.

I imagine that folks exist who think the way Apple does. And I imagine that OSX works fabulously for them. I am not such a person. Without support for new OS versions (PPC support stopped with 10.4 or 10.5), the laptop rapidly became a useless brick, unsafe to use on the open internet.

I found a good deal on some Lenovo laptops at (the now-defunct) Fry's. I installed Debian on mine, and Ubuntu on my sweetheart's. They served us fairly well for years of web-browsing, email, light gaming, remoting into machines at work, and software development for me.

The Push: the slow decline of Linux

However, grey clouds started rolling in. Debian started introducing changes that drifted farther and farther from the Unix I started with, and I did not care for it.

Sound systems churned leading to frustration. I lived through OSS, libao, ESD, aRTS, ALSA, Pulse, Jack, and now Pipewire. Each one promised to fix all the problems of the previous standards. Similarly, I lived through a plurality of firewall tech.

Then programs I'd used for years/decades began to issue deprecation warnings. "Don't use ifconfig to manage your wireless connection use iwconfig, and to manage your bridge devices use brctl, except don't use either of those, use ip instead. Fresh installs of most popular distributions lacked ed(1) in the base system, so when things went sideways, you might not have a $EDITOR to rescue your system.

I would open a man page to read documentation, only to find a useless placeholder stub redirecting me to a GNU info page where you had to navigate to different parts to see them, and you couldn't read the whole thing in one place. I've since learned to use info program | less to force info to render the entire document into less where I can comfortably read the whole thing.

I'd reach for netstat only to hear that I should use ss instead. Or that I should stop using nslookup that I'd used for years on *nix and Windows and instead use host or dig/drill. EDIT: A note from author Michael W. Lucas informs me that the developers of nslookup deprecated their own application, not Linux distro-builders mandating change.

Then came the big ones: systemd and the threat of Wayland replacing Xorg. systemd broke detaching in tmux and rudely expected the tmux team to fix the problems that systemd had caused. I would issue shutdown/reboot commands with the power of root (sudo shutdown -r now) only to have systemd balk and refuse to actually shutdown/reboot, hanging indefinitely on some process over which I had no control. Thank goodness for the ability to hold down the power-button and kill it properly. No choice whether I wanted systemd vs some other init system. I could no longer grep my log files because systemd kept them in binary formats.

Meanwhile, I've heard strong rumblings that Xorg will get supplanted by Wayland in most Linux distributions. My window-manager of preference (fluxbox) does not work in Wayland. Many of the GUI applications that I use do not work in Wayland. I continue to hear that a lot of things don't currently work in Wayland. Maybe it will meet my needs someday, but not any time in the imminent future.

The Pull: the BSDs (2012–)

Meanwhile, amid all those pushes in the Linux world I found myself drawn to features that FreeBSD & OpenBSD offered.

While FreeBSD does offer several firewalls, those choices include pf which quickly became my favorite firewall syntax. Originating in OpenBSD, it gives me one sensible syntax to manage my firewalls on all my machines.

ZFS frees me from getting locked into a particular partition layout, pooling my available storage and making it available to all datasets. It checksums my data before writing and after reading to ensure that my data hasn't bitrotted. It gives me transparent compression. I can do instant snapshots of my data. I can clone datasets and send/receive that data efficiently across to other machines for backup. Copy-on-write meant that even if my system experienced abrupt power-loss the file-system remained consistent and didn't require a fsck upon reboot.

FreeBSD gives me jails which make a lot more sense to me than containerization in Linux-land. As an added benefit, FreeBSD has offered jails far longer (March of 2000) than Linux containers, giving them more time to bake.

Meanwhile, OpenBSD gives me a system that feels good. Applications and services play well together like dhcpd talking to pf, unbound, or relayd. And it includes xenodm/xenocara with a base install, and includes three window managers: fvwm (the default), twm (old school), and cwm (my favorite of the three).

Finally switching from Debian to FreeBSD/OpenBSD (2019)

The final nail in the coffin came from a Debian upgrade where systemd took down my audio subsystem completely and started having problems booting reliably.

I backed up my data to an external drive along with a list of the major software I use, sent a copy to my VPS, and installed FreeBSD on my daily driver. I copied all my data back, installed the major software on FreeBSD, and went on with life largely as I had before.

I also set up some other junker laptops with OpenBSD, including that now-dead Gateway Solo 1200, and that iBook G4, as well as my writer-deck, a Dell Mini10 netbook. Additionally, my VPS instances run a mix of FreeBSD & OpenBSD.

Epilogue

Is everything perfect? I still experience minor issues, most notably the audio on FreeBSD doesn't automatically cut over between speakers and headphones when I plug/unplug headphones.

But it feels like the Unix I grew up using.

It feels like home.


A few such sample posts: here, here, here, here, here, here, here, here, here, here, here, here, and here.

Assorted less(1) tips

In a recent discussion on Reddit I shared a number of tips about the common utility less(1) that others found helpful so I figured I'd aggregate some of those tips here.

Operating on multiple files

While most folks invoke less at the tail of a pipeline like

 command | less
Invoking less in a pipeline
you can directly provide one or more files to open
 less README.txt file.c *.md
Invoking less directly

Adding files after starting

When reading a document, sometimes you want to view another file, adding it to the file list. Perhaps while reading some C source code you want to also look over the corresponding header-file. You can add that header-file to the argument list with :e file.h

You can navigate between multiple files using :n to go to the next file in the argument-list, and :p for the previous file. You can also use :x to rewind to the first file in the argument-list similar to how :rewind behaves in vi/vim.

Removing files after starting

While I rarely feel the need to, if you have finished with a file and want to keep your argument list clean, you can use :d to delete the current file from the argument-list.

Jumping to a particular line-number

Use «count»G to jump to a particular line-number. So using 3141G will jump to line 3141. It helps to display line numbers.

Jumping to a particular percentage-offset

Similarly, using «count»% jumps to that percentage-offset of the file. So if you want to go to ¾ of the way through the file, you can type 75% to jump right there.

Searching

While many folks know you can search forward with /«pattern» and some people know you can use ?«pattern» to search backwards, or use n/N to search again for the next/previous match, less provides modifiers you can specify before the pattern to modify its behavior:

!
Find the next line that doesn't match the pattern
*
search across multiple files, starting from the current location in the current file
@
rewind to the first file and search from there
@*
rewind to the first file and search from there across multiple files

Thus you would use /@*«pattern» to search for "pattern" starting with the first file.

Filtering lines

Using & lets you specify a pattern and filter the displayed lines to only those matching the pattern, much like an internal grep command. If you modify it with !, so it will display only those lines that do not match the pattern, like &!«pattern». I find this particularly helpful for browsing log-files.

Bookmarking

You can bookmark points in a file with m followed by a letter, then jump back to that bookmark with ' followed by the same letter. These apply globally across all open files, so if you ma in the third file, then navigate away to other files, using 'a will take you back to the marked location in that third file. I use marks most when reading man-pages, dropping one mark at the OPTIONS section such as mo, and another at the EXAMPLES section, such as me, then bounce back and forth between them with 'o and 'e. While you can use any of the 26 lowercase or uppercase letters (for a total of 52 marks), I rarely use more than two or three either in alphabetical order ("a", "b", "c"), or assigning mnemonics like in the man-page example above.

Bracket matching

If the first line on the screen contains a (, [, or {, typing that character will jump to the matching/closing character, putting it on the bottom line of the screen. Similarly, if a closing ), ], or }, character appears on the last line, typing that closing character will jump to the matching/opening character, putting it at the top of the screen. I find it a little disorienting if they fall less than a screen-height apart because what feels like a forward motion to find the next matching close-bracket might actually result in shifting the screen down rather than up which feels backwards.

While I don't use it much, you can also specify match-pairs using alt+ctrl+f or alt+ctrl+b followed by the opening/closing pair of characters such as alt+ctrl+f<> to define a "<"…">" pair and jump between them in a manner similar to the (/), [/], and {/) motions.

Toggling options without restarting

While the man-page documents many flags you can pass on the command-line, you can also toggle boolean options from inside less. I find this particularly helpful when I've fed the output of a long-running process to less and don't want to re-run it because it will take a long time. Instead of quitting, you can type a literal - followed by the option you want to change. I most commonly want to toggle word-wrap for long lines, so instead of quitting and adding -S at the end of my pipeline, I can type -S directly in less. Options I commonly toggle:

-S
word-wrap (mnemonic "splitting long lines")
-G
search-highlighting
-i/-I
smart-case/case-sensitivity for searches
-R
ANSI-color escaping
-N/-n
show/hide line-numbers

Running external commands

The ! lets you invoke an external command. I don't do this often, but occasionally I want some simple reference like the current date (!date) or to do some simple math (!bc).

Default options with $LESS

You might find yourself regularly setting a common group of options so you can put those in your environment (usually in your shell startup file like ~/.bashrc) like LESS="-RNe" if you want to show ANSI colors, show line-numbers, and exit automatically when you reach the end of the file.

Other misc

less has a few other corners that I've never really used, but figured I'd document here:

Tags

While I've used tags in vi/vim to easily jump between definitions. However, even though less provides support for tags generated by ctags. I've never found cause to use them.

Editing the current document

The v command will open your $VISUAL editor on the current document.

"Log" output

less lets you redirect the output it has gathered from stdin to a file using the o command (or the O command to overwrite an existing file). This might come in handy because less won't let you edit stdin in an external editor but you can write it directly to a file.

Blog Question Challenge 2025

Why did you start blogging in the first place?

Part of me wants to just record my thought-process and solidify my thinking.

Another part like sharing things I learn in case they help others.

And sometimes I just want to rant.

What platform are you using to manage your blog, and why do you use it

In the late 90s, I wrote raw HTML files and just posted them on the RedHat web-server that my college CS department offered. Good ol' table-based layout and all that.

Once I got my own domain, I looked around at Static Site Generators (SSGs) and Nikola, topped my list. I wanted an SSG that

  • could ingest pure HTML fragments (which I prefer) rather than forcing me to use something like Markdown or AsciiDoc. I don't mind using them for casual prose (like this) but for technical work, I prefer the markup-control that I get from raw HTML

  • was written in Python (which I use as part of $DAYJOB, so I felt more comfortable poking under the hood)

  • ran on all the platforms I used (Linux at the time, now FreeBSD, and OpenBSD

  • had metadata features that fit my requirements

  • had a built-in web-server for viewing the site locally

  • was easy to create an rsync deploy hook to send my files up to my web-server

However, Nikola has a lot of churn, meaning I frequently have to revisit my configuration files or regularly suffer the wrath of warnings and errors at every upgrade. It also processes my HTML source through lxml which in turn mangles certain cromulent markup, meaning my input doesn't show up in output. And system upgrades of Python seem to throw my virtual-env into a bit of a frenzy.

So I've started a Makefile-based SSG that largely sticks to BSD make and POSIX awk. Stay tuned when that comes to fruition.

How do you write your posts?

A plain ol' text editor.

Sometimes vi/vim, sometimes ed(1).

Do you normally publish immediately after writing, or do you let it simmer a bit?

Most posts take me a while to compose, so those get set to Draft status, and the publishing process uploads the static files but doesn't include them in indexing or the RSS feed. This allows me to read them on my site (optionally sharing the pre-release URL with others) and revise them accordingly. However, once I feel it's done, I go ahead and remove the Draft status to publish it.

Have you blogged on other platforms before?

If you count "microblogging", then I've blogged on Twitter/X and have largely moved my microblogging participation to Mastodon.

However, for the most part, it's just been my own site/blog.

When do you feel most inspired to write?

A couple triggers:

  • I'm working through something complex and want to document it for myself

  • I've found a fun little shell trick and want to share it

  • I've experienced some frustration and just need to rant

What’s your favorite post on your blog?

Probably my post on using remind. However, it's starting to show its age, so I should revisit the article and update it.

Any future plans for the blog?

Keep on emitting a steady trickle of whatever interests me.

The fall of the User Agent

In the beginning

Similar to some Mail User Agents (MUAs) and NNTP clients, the specification for HTTP since at least version 0.9 have included User-Agent headers that still exist in modern HTTP standards.

This header lets the server know what software made the request. But it also provides a reminder that the software existed to act on behalf of the user.

Abuse

Sadly, server-side software started to abuse the User-Agent header. Based on the value, a web-server would respond with different output depending on what it thought the other side could handle. By accommodating a broken client and making presumptions about how it would behave, this User-Agent sniffing led to a fractured web.

Lowe's rant

Sigh. Lowe's doesn't seem to be able to competently ship a part that still shows as in-stock on their site. Rant documenting the drama follows.

tl;dr order online, they cancel. order online again, they cancel. Call support, get told to place the order with the local store. Call local store, get told they can't. Call support, get told to physically go into the store to order. Order gets placed. Order arrives, installer notes it's missing parts. Call support, get told they'll rush out a replacement. Replacement arrives. Check box, still missing same parts. Call support, rush delivery of another replacement with notes for the shipper to check the contents. Third order arrives with the same contents as the previous two. To be continued…

Read more…

Planning the day on the CLI with tsort

I had a bunch of items on the todo list for the day and wanted to arrange them in order, but I needed to certain items before others:

  • Drop donations off at the resale store, but can't do that before 10:00 when they open
  • Get the daughter ready for soccer camp before dropping her off
  • Drop the daughter off at camp before taking paperwork up to her school
  • cut the son's hair before he takes a shower and cleans his bathroom
  • pick up daughter at camp after she's started camp (duh) and before 10:45
  • take the kids to the library after picking up daughter at camp
  • for obvious reasons, 8:30 → 8:45 → 9:00 → 10:00 → 10:30 → 10:45
So I expressed this in a file where each row contains "X needs to come before Y":
cat todo.txt
10:00 resale
resale 10:30
sunblock take_to_camp
pack_snack take_to_camp
pack_water take_to_camp
pack_towel take_to_camp
take_to_camp 8:30
8:30 soccer_camp
soccer_camp 8:45 
soccer_camp paperwork
8:45 home
home 9:00
paperwork home
home cut_hair
home clean_bathroom
home shower
cut_hair shower
cut_hair pick_up
shower pick_up
clean_bathroom pick_up
cut_hair clean_bathroom
clean_bathroom 10:00
10:45 pick_up
8:30 8:45 
8:45 9:00 
9:00 10:00 
10:00 10:30 
10:30 10:45 
pick_up library

Now it just became a matter of passing these requirements to tsort

tsort todo.txt
pack_towel
pack_water
pack_snack
sunblock
take_to_camp
8:30
soccer_camp
paperwork
8:45
home
cut_hair
9:00
shower
clean_bathroom
10:00
resale
10:30
10:45
pick_up
library
to sift them into the required order of my todo list for the day.

Old Computer Challenge

History

This is the third year in which Solene has run the Old Computer Challenge and I've tried to participate in each of them.

Participating in these requires a little flexibility since I work remotely for $DAYJOB. The low-end computer challenges posed less issue since neither the VPN nor rdesktop required much in the way of resources. Using the smaller screen-dimensions on the older laptops made it a bit more challenging, but I made it work.

None of these challenges shifted any usage to my phone. I prefer not to use my phone for anything beyond the barest of essentials: phone-calls, texting, podcasts, timers, lists, and weather.

First year (2021)

The first year and third year both focused on limited hardware,

I chose a Gateway Solo 1200 as my primary machine for the first year. Boasting an 800MHz Celeron processor, a 120GB spinning-rust HDD, a 10mbit wired LAN connection (it also had an internal wi0 wireless card and a PCMCIA Intel wifi option, but both only supported WEP rather than WPA2 so I stuck with the wired option), and upgraded to its maximum of 320MB of RAM. This machine infamously arrived on 9/11 with the UPS driver delivering it as I watched the twin towers fall on TV.

The machine ran the latest release of OpenBSD without issue. The limited CPU & RAM limited my choice of software notably. Fortunately, other than web-browsing, much of what I do happens at the command-line.

Email
I had used Claws Mail (a GUI mail program) for many years but it started using more and more system resources. So I had aspired to switch to mutt or neomutt. The Old Computer Challenge gave me the kick I needed. Dealing with multiple accounts and catch-all mailboxes posed the worst pain-points. Otherwise, it ran fine within the limited system resources. And they provide a lot of power to mow through piles of email.
Music
I've long used cmus for playing my music collection, and pianobar for streaming. Both ran fine even on this ancient hardware.
Calendar
I've moved my calendaring to remind and it runs fine at the CLI. It did have a noticeable lag on startup but I suspect that my 3000+ reminders/events cause that. When I winnow it down to a much more sensible volume of reminders, it runs in a blink.
Coding
All my coding happens at the CLI using a mix of vi, vim, and ed for editing, and doing version-control with git or rcs so not much changed here. I did find notable startup lag both in starting vim and executing Python code. It made me appreciate the fast startup times for utilities that compiled down to native code. I also found myself using awk in a lot of places since it had a faster startup time than Python.
RSS
I've long used rss2email to gather my RSS feeds and deliver them to my inbox, reducing the RSS-reader issue to a mail issue. I experienced no disruption here, since mutt let me keep reading my feeds just as I had done in Claws.
Social media
I accessed Twitter with Rainbowstream, Mastodon with Tootstream, and rtv (now obsolete) for Reddit. For text posts and commenting, I loved them all. But for image/video posts, they fell short. I wish I had a quality CLI interface for Facebook to keep in touch with friends & family who only share things there.
Office stuff
Thankfully, I don't have to deal with Office documents often. And almost never outside of $DAYJOB so I could use Word or Excel remotely. I did install Abiword for the occasional MS-Word document and Gnumeric for the occasional spreadsheet. Both provided reasonable fidelity and speed while running within the confines of the limited hardware.
Gaming
I don't game much, so this didn't impact me much. I think I played a couple rounds of cribbage(6) and atc(6) as a proof-of-concept, but certainly no high-end FPS games here.

Web browsing hurt the most. Firefox & Chromium? Completely unusable without gobs of RAM. For some basic browsing, lynx and dillo provided lightweight options, while Epiphany clocked in at barely-usable (but still better than Firefox & Chromium) for sites requiring JavaScript.

Second year (2022)

The second year focused more on limiting network usage (both total-time and bandwidth).

I had to segregate life here since $DAYJOB requires remoting into my work machine so I didn't count that time against my allotted 1hr.

I didn't know how to count my cron job that downloads my podcasts nightly since I don't have much control over how long they run or how much data they download. I decided that, since the challenge only ran for a week, and I batch podcasts roughly every three weeks, I could load a fresh batch to my player before the challenge, disable the cron job for the week, and then re-enable the cron job after completing the challenge. Not quite the spirit of the challenge, but also a lot like how I would download things in high-school, where I would walk to the local campus library to download large files and bring them home.

Email didn't pose a great concern, since OfflineIMAP let me batch download my emails from the server, and my local MTA would batch up outbound emails until I reconnected, sending them all to my smart-host mail-server in one go.

However, the second year really cut into social-media usage. Its model simply doesn't accommodate offline use well.

Third year (2023)

Similar to the first year the tools remained largely the same. However this year I did the challenge while on vacation. Cheating? Maybe. But also enforcing since I didn't take any other laptop. This time I took a Dell Mini10 netbook with me. This hand-me-down came to me with 2GB of RAM, but I'd made a few upgrades:

  • replaced the 120MB HDD with a 60GB SSD giving a bit of extra pep
  • replaced the rubbish Broadcom wireless half-height PCI card with an Atheros chipset
  • installed OpenBSD 7.3 in place of Windows Vista

The netbook has no fan, relying on passive cooling instead. This meant that using apm -L kept the system running cool. I could manually apm -H to get the full 1.x GHz but it came with a warm price, discouraging me from doing so.

The tiny 1024×600 screen resolution gave even greater constraints when remoting into $DAYJOB but, that helped me stay in vacation-mode rather than try to sneak in hours. Additionally, X seemed to think the display offered 1024×768 resolution, so everything rendered with a squishing/scaling that ruined friends' pictures. And equally bad, the Poulsbo chipset lacked support in X, so it rendered very slowly using VESA. But I had times where I could watch text render character-by-character, and could type full paragraphs of text before the first couple words appeared on the screen. With better graphics-support, I suspect it would have felt notably snappier.

Future challenges

After returning from that vacation, I purchased a new laptop for travel, and got rid of four of my old junker laptops (my beloved rejoices at fewer laptops on my desk). I still have the Mini10 and a PPC iBook G4 running OpenBSD, so I can participate in future challenges.

Closing out the books in ledger(1)

I put this here mostly because I forget how to do it and have to make multiple starts to get it right.

ledger -f ledger.txt  print \
  -e 2022-1-1 > 2021.txt

ledger -f ledger.txt equity
  -e 2022-1-1 > tempfile.txt

 echo >> tempfile.txt

ledger -f ledger.txt print \
  -b 2022-1-1 >> tempfile.txt

mv tempfile.txt ledger.txt
Closing out the books for 2021

Read more…

Using mail(1)

Intro

CONGRATULATIONS! Your OpenBSD install has been successfully completed!

When you login to your new system the first time, please read your mail
using the 'mail' command.
OpenBSD's post-install message

Oh, no! You have a fresh install and the only way to read your welcome message from Theo requires using mail.

Read more…