BSD Pt. 2

They did it again. Those inglorious bastards over at Jupiter Broadcasting gave me an excuse to build another BSD machine. I already had a couple running (this website beingone), but I now have the opportunity to use a machine that wasn’t built in the last century.

First, the rules.

As I type this, the date is 27 Apr 2026. The results are due by Linux Unplugged episode 666 on the 10th of May and will be judged on-air. Prerequisites are simple: to enter the competition, just install BSD. Any BSD. I regretted my decision to install Ghost-BSD for the last challenge, since it wasn’t a pure ground-up freebsd install and could be considered cheating (the rules were different then). Because of this, I took a different route and installed from base, but now I’m worried that having this installed before the challenge may be considered cheating as well. To rememdy this, I’m going to take my previous FX-8350 based home BSD machine and re-install a BSD of my choice on it as well as my primary BSD machine. I don’t want to use FreeBSD on that one, being that it’s the Ubuntu of the BSD world and variety is the spice of life. More on that machine later.

For now, I want to concentrate on the primary box; a previously donated Nixos machine that I was kindly forcing family members to do mundane tasks on to prove a point about Linux’s usability. It was originally part of the Olypia, Washington Computer Upcycle project, but didn’t have the appropriate hardware for mass consumption. I gave it a new home; first for testing random peoples’ reactions to the OS, though the last person I wanted to have test it was my grandmother who announced on the same day that her cancer was back and she was going back for chemotherapy. This followed my wife having to escort a worker out of her job for smoking meth at work.

Finally accepting that this machine as it stood was some kind of evil bad-luck horcrux, I decided to re-format it as part of the BSD challenge. There are four levels: Survive, Drive, Power, and Bonus. Survive is an almost given, essentailly summing up to sit down and do the most basic things on the system. The second, the Daily Driver level simply steps up the level to “do normal stuff” like having a desktop and make noises. Level 3 is called the “superuser” level, though I believe this is bad nomenclature. The challenge’s tasks include “update the computer” and “start a service”. Finally, Level 4 is the “Bonus Round”. This involves starting a container, and using what’s init. Beyond that, there’s using the firewall, using a virtual machine, and using a zfs snapshot. This is the only thing that I would have trouble doing by memory. For a moment, I wondered if disabling pf counted as “using” the firewall; but hey, where’s my game spirit? No. I’ve decided to do something a little more true-to-life, like blocking a california IP address.

First, though, the early stages:

Level 1 — Survival (0–7 points) Can you get a usable system? Task Points Successfully boot into a fresh BSD install (VM, bare metal, or… somewhere interesting) 2 Connect to the internet and confirm with a ping or curl 2 Install at least one package using the native package manager 2 Find and read a man page for something you didn’t already know 1 Gotcha for Linux users: The package manager isn’t apt or pacman. Finding it and understanding the difference between ports and packages is part of the fun.

This is incredibly simple. As I’m typing this on my freebsd machine now, I’d say that having an install of a bsd is covered. I needed to connect to the internet to get this rule set on this machine, so that’s complete as well. I’m typing this in libreoffice writer, so I’ll count that as installing something, and; just for future reference, I’ll read the manpage on PF… Done. 7 points

Next, we have level 2:

Level 2 — Daily Driver (8–14 points) Can you do normal desktop human things? Task Points Get a graphical desktop environment running 3 Get a web browser open and load a webpage 2 Create a user account (not root!) and log in as that user 1 Mount and read from an external drive or USB stick 1 🎵 Bonus: Get audio working — even a test tone counts 1 Gotcha for Linux users: Display stack differences will likely humble you here. Also, doas may be your friend depending on your BSD — and it’s not sudo by default.

Getting a graphical desktop was as easy as following a youtube video (specifically this one: https://www.youtube.com/watch?v=TmFl7QTvWPs&t=425s). The interesting part of all this is that the tutor integrates his own home-grown desktop into the tutorial. I got a little exited when I first heard him say “cargo build” as part of the instructions, but it seems that he has since ported from Rust to Zig. I personally think this was a good move, but I really wanted to hear those horns. Disappointment aside, I have a tiling wm with drun for software selection and a wallpaper setup I’ll get to later.

The web browser was a simple pkg install away, so I can’t say much on that, outside of wanting a maintainer to step up for the ladybird port (this is a reoccuring issue with FreeBSD packages). Creating a user account was literally the first thing I did when I got a shell. Nothing to report there. Mounting and reading has happened several times. I took it one step further by getting an sshfs mount going so I could move this document around easily (I eventually dropped it for tailscale send).

Audio worked out of the box with no work needed to get it going. This machine has an internal speaker that required no setup. I noticed it when I started playing xonotic with my son over our lan. 15 points

Can you do the kinds of things a Linux nerd actually cares about? Task Points Update all installed packages using the native tool 1 Perform a full OS update (e.g., freebsd-update, syspatch, etc.) 2 Configure and enable SSH — connect from another machine 2 Stop, start, and check the status of a service using your BSD’s native init system (rc.d on FreeBSD/NetBSD, rcctl on OpenBSD — no systemctl here!) 2 Edit a config file to make a service start at boot, the BSD way 1 Write a short shell script and set it executable 1 Gotcha for Linux users: There is no systemctl. The rc system will feel alien. Reading rc.conf is not optional — it is the system.

Update is as easy as

sudo pkg update && sudo pkg upgrade -y 

Eerily similar to ubuntu. Performing a full OS update was again extremely simple, simply running

freebsd-update fetch freebsd-update install

and waiting on it to complete. This was actually more intuitive to me than updating a nixos machine. The worst part was rebooting to see if anything broke. It didn’t. Configuring and enabling ssh was as easy as

sudo nvim /etc/ssh/sshd_config

and

sudo service sshd restart

Now, I have ssh running on a port that I will absolutely not need to run out to my shop to remember when I set this up as a headless machine. Last, I’ll need to write a script and have it run. That’s fine; I already did this on my old i3 Arch (btw) machine.

#!/usr/local/bin/bash
while true; do feh --randomize --bg-fill /home/nolan/.wallpapers/; sleep 5; done

Now, the (not anymore Rust) oxwm has randomly changing backgrounds. I actually have several scripts in this directory, all doing random things. Either way, 24 poonts. Also, why do the rules say I can only get up to 20 points here? I’ve counted three times now. I can’t be this bad at math.

Finally, the bonus round:

Level 4 — Bonus Round 🏆 (21+ points) Go to Jail. Task Points Create and start a BSD Jail (or container equivalent) 3 Get a service running inside the jail 2 Access that service from the host 1

Creating and starting a Jail is extremely easy with iocage. This can be thought of as the icus of the bsd world, and the command is very straightforward, if a bit lengthy:

nolan@666 ~> sudo iocage create -r 15.0-RELEASE 
-n poop 
vnet=on 
bpf=yes 
allow_raw_sockets=1 
dhcp=on 
boot=on Password: poop successfully created! No default gateway found for ipv6.
    • Starting poop
        ◦ Started OK
        ◦ Using devfs_ruleset: 1002 (iocage generated default)
        ◦ Configuring VNET OK
        ◦ Using IP options: vnet
        ◦ Starting services OK
        ◦ Executing poststart OK
        ◦ DHCP Address: 10.0.0.13/24 nolan@666 ~>

Now, any services provied by the jail “poop” can be found at 10.0.0.13 on the local LAN. While Jails don’t have access to tailscale, this can be routed through the tailnet pretty easily. To make the point, I installed nginx and editted the default page.

VICTORY

Unfortunately, I can’t access it from anywhere outside of my home network because I can’t get tailscale running in a jail. It doesn’t have access to the base kernel or something. I don’t know. I have other things to do right now.

Unscored stretch goals (no points, but eternal glory): • Set up pf (BSD’s packet filter) with a basic ruleset • Get Bhyve or QEMU running a Linux VM inside your BSD • Set up ZFS snapshots and roll one back

PF was easy. Just edit the pf.conf file to block all those evil californian IP addresses and that’s it! Make sure /etc/rc.conf is enabled so we can get it on boot.

sudo echo “block in quick from 206.117.31.142 to any” >> /etc/pf.conf

Now, for the virtualization of it all. Freebsd has its own native VM hypervisor called bhyve; and qemu is also available if needed. I’ll be sticking with bhyve for now. Experementation beyond that is a stretch, stretch goal. Checking the internet tells me that there’s a graphical manager called bhyvemgr. Installing this and running it left me with a soft lock. Instead of running the configurated machine, the gui says “Trying create test virtual machine…” and never moves on. I’m going to call it here, since it’s 2AM on the night before the episode 665 “start line” and I’ve got to get this published.

Below are future plans and some pictures for the sake of context:

Fragging Fetch VMM

Plans before episode 666:

  1. Picom and other prettyfication on the window manager.
  2. Get my Bulldozer machine running DragonFly BSD
  3. Finish the stretch goals
  4. Get Tailscale working on Jails