Eric Radman : a Journal

An OpenBSD Workstation

I first posted my notes on using OpenBSD as my workstation in July of 2013, but I probably switched in about 2005. The following categories cover some of long-term customizations I have made as well as some hints for using more modern features.

Terminal

The most important feature of any workstation is good terminal. By default most terminals render text with a heavier weight than I would like. To solve this select a font with a light or book variation. Here is my invocation for the simple terminal

st -f 'Hermit:light:pixelsize=14:antialias=true:autohint=true'

My st port includes

The really compelling feature of st is that it automatically substitutes glyphs from the default font if the one you've selected does not contain them. This enables me to use the really excellent Hermit font while retaining the extended character set of DejaVu Sans.

utf-8 and colors

To ensure you get full Unicode support from applications such as mutt or tmux set your language type using

LC_CTYPE=en_US.UTF-8
export LC_CTYPE

Resource Limits

The default process limits on OpenBSD are not nearly generous enough to run applications such as Gimp or Chromium Be sure to raise the limits for memory by modifying /etc/login.conf

staff:\
    :datasize-cur=16384M:\
    :openfiles=16384:\

Terminate your X session with Ctrl+Alt+Backspace to ensure settings have taken effect.

Suspend & Resume

zzz and ZZZ are shortcuts for suspend and hibernate if apmd is run at startup. The -A flag will automatically scale the CPU frequency to save power.

Another feature of apmd(8) is to react to a low battery by hibernating or sleeping. This change to rc.conf.local reacts to a battery level of 8% or less

apmd_flags="-A -Z 8"

X Configuration: .xsession

xset -b

while true; do
    batt="$(sysctl -n hw.sensors.acpibat0.watthour3 | cut -f1,2 -d" ")"
    xsetroot -name "$batt"
    sleep 60
done &
xsetroot -solid gray40
exec dwm

xset -b disables the annoying beep that terminals sometimes make.

I run a loop in the background that read the available battery life (Wh) and updates the window manager's display area. Any sensor data can be included in such output.

Finally set the background color and start your favorite window manager.

DWM status bar

X Configuration: scaling

If xenodm_flags= is set in rc.conf.local then you can set the initial X display DPI at startup by modifying /etc/X11/xenodm/Xservers

:0 local /usr/X11R6/bin/X :0 vt05 -dpi 144

After your window manager is started you can change the DPI for X applications that are started using xrandr

xrandr --dpi 144

Switch to an External Monitor

As far as I know, OpenBSD does not have a native way of reacting to display plug events. When connecting an external monitor I run a little script to adjust the display

 #!/bin/sh
 xrandr --output DP-1 --auto --primary
 xrandr --output eDP-1 --off
 xrandr --output HDMI-1 --off

Where eDP-1 is the LCD pannel on my laptop.

tmux

There's only a few tweaks I make to my terminal multiplexor's configuration. I frequently run entr in a smaller pane on the bottom

bind-key C-t split-window -p 25

I don't know of a terminal color picker, but they can be printed with a shell loop.

for i in `jot 255`; do
  printf "\033[38;5;${i}mcolour${i}\n"
done

printf "\033[0m"  # reset

Then I set status background and active border to bright green

set -g status-bg colour118
set -g pane-active-border-fg colour118
set -g pane-border-fg colour30

Most importantly, clean up the status bar so that only the window names are displayed:

# remove status debris
set -g status-left ''
set -g status-right ''

Using Disk Encryption

OpenBSD provides software RAID by way of a virtual host bus adapter called softraid0. This HBA is also used for setting up disk encryption. To set use a disklabel (in my case for sd0g /home set the partition type to RAID

# disklabel -E /dev/sd0c
Label editor (enter '?' for help at any prompt)
/dev/sd0c> m
partition to modify: [] l
offset: [141362304]
size: [358755776]
FS type: [4.2BSD] RAID
/dev/sd0c*> q
Write new label?: [y]

Now configure it for crypto using -c C

# bioctl -c C -l /dev/sd0j softraid0
New passphrase:
Re-type passphrase:
softraid0: CRYPTO volume attached as sd1

Mount it using the same command. The kernel log will show a new virtual device appear

sd1 at scsibus3 targ 1 lun 0: <OPENBSD, SR CRYPTO, 006>
sd1: 175173MB, 512 bytes/sector, 358755248 sectors

Now add a disklabel and format the encrypted volume

$ doas disklabel -E /dev/sd1c
$ doas newfs /dev/rsd1a

Devices in OpenBSD may be mounted by device name or by disklabel UID which is a random id generated when the label is created.

$ disklabel /dev/sd1c | grep uid
duid: 5005bf4c398ff7b9

It's this ID that we'll to mount the volume, in this way plugging in other drives won't confuse mount after we prompt the user for a password on boot. Adding the following to rc.local will ask for a password four times before giving up

#/etc/rc.local
for attept in 1 2 3 4; do
  bioctl -c C -l 6bce88736e499a49.j softraid0 && break
  sleep 1
done
fsck -y 5005bf4c398ff7b9.a
mount -o nodev,nosuid,softdep,wxallowed 5005bf4c398ff7b9.a /home

That last mount parameter wxallowed is important because it will allow you to run certain interpreters such as Python from a virtualenv in your home directory.

If you would like to enable crypto on the entire boot volume see this post by Ted Unangst.

Screen Lock

Add the following to your .xsession to automatically lock the screen after 5 minutes of activity

xidle -ne -delay 1 -timeout 7200 -program /usr/local/bin/slock &

To trigger this action when the system is suspended, create /etc/apm/suspend with an instruction to signal xidle to run the lock program

#!/bin/sh
pkill -USR1 xidle

Kerberos

If your workplace uses Kerberos there is a good chance that they provide the list of KDC servers via DNS SRV records

$ host -t srv _kerberos._udp.eradman.com

Heimdal Kerberos will do this lookup automatically. A basic configuration for /etc/heimdal/krb5.conf appears as such

 [libdefaults]
     ignore_acceptor_hostname = true
     rdns = false
     default_realm = ERADMAN.COM

 [realms]
     ERADMAN.COM = {
             default_domain = ERADMAN.COM
     }

 [domain_realm]
 .ERADMAN.COM = ERADMAN.COM
 ERADMAN.COM = ERADMAN.COM

Now get a ticket

$ kinit
radman@ERADMAN.COM's Password: *********
$ klist
Credentials cache: FILE:/tmp/krb5cc_1000
        Principal: eradman@ERADMAN.COM

  Issued                Expires               Principal
Oct 31 10:02:30 2017  Oct 31 20:02:30 2017  krbtgt/ERADMAN.COM@ERADMAN.COM

Firefox

To enable Firefox to pick use Kerberos we need to point it to the GSSAPI library from the heimdal package. For automated configuration this means installing /usr/local/lib/firefox/browser/defaults/preferences/openbsd.js

pref("network.negotiate-auth.allow-non-fqdn", true);
pref("network.negotiate-auth.gsslib", "/usr/local/heimdal/lib/libgssapi.so.9.0");
pref("network.negotiate-auth.trusted-uris", "eradman.com");
pref("network.negotiate-auth.using-native-gsslib", false);

Since the OpenBSD build of Firefox is patched to use unveil(2), add an entry to /etc/firefox/unveil.main for allowing read of the Heimdal shared libraries

# kerberos
/usr/lib r
/usr/local/heimdal/lib r

# home directory
~/ rwc

Chromium

Chromium is not built with Kerberos support on OpenBSD, but it can be added by modifying /usr/ports/www/chromium/Makefile

120c120
<    use_kerberos=false \
-
>    use_kerberos=true \
131
<    extra_cppflags=\"-idirafter ... \"
-
>    extra_cppflags=\"-idirafter /usr/local/heimdal/include ... \"

Run make install and a mere 24 hours later the build should be complete. A policy file can be applied for installing the file /etc/chromium/policies/managed/openbsd.json

{
  "AuthServerWhitelist": "*.eradman.com",
  "GSSAPILibraryName": "/usr/local/heimdal/lib/libgssapi.so.9.0"
}

The OpenBSD build of Chromium is patched to use unveil(2), add an entry to /etc/chromium/unveil.main

# kerberos
/usr/local/heimdal/lib r
/usr/lib r

# home directory
~/ rwc

As well as /etc/chromium/unveil.utility_network

# kerberos
/usr/local/heimdal/lib r
/usr/local/lib r
/usr/lib r

After installing this file, navigate to chrome://policy to see if all settings applied.

Printers

The magic behind printing is not widely understood or documented. I always opt for a network printer that supports PostScript. The following example is from /etc/printcap

lp|mfc-9340cdw:\
  :lp=:rm=192.168.0.4:rp=lp:sd=/var/spool/output/lpd:lf=/var/log/lpd-errs:
office-printer:\
  :lp=:rm=10.240.20.10:rp=office-printer:sd=/var/spool/output/office-printer:lf=/var/log/lpd-errs:

Be sure also to create spool directories

install -o root:daemon -m 775 /var/spool/output/office-printer

Now I can print from Firefox and other applications using lpr -Poffice-printer or just lpr at home.

Wireless/Wired

Since 6.9 dhcpleased(8) handles route updates based on DHCP offers, enabling automatic transition between wired and wireless networks

# /etc/hostname.iwm0
join radnet2 mode 11g
join Verizon-MiFi8800L wpa wpakey **********
inet autoconf
# /etc/hostname.em0
inet autoconf

Multiple default routes may be installed in this way, but link-layer protocols use the route with the highest priority.

Corporate VPN

Since 7.0 updates to /etc/resolv.conf are handled by resolvd(8). If you use a custom vpnc script use route(8) to make changes to routes and to nameservers

#!/bin/sh
#/etc/vpnc-script

case "$action" in
    pre-init)
        ;;
    connect)
        route nameserver $TUNDEV $INTERNAL_IP4_DNS $INTERNAL_IP6_DNS
        ifconfig $TUNDEV inet $INTERNAL_IP4_ADDRESS/$INTERNAL_IP4_NETMASKLEN
        route add -inet 10.0.0.0/8 $INTERNAL_IP4_ADDRESS
        ;;
    disconnect)
        route nameserver $TUNDEV
        ;;
    reconnect)
        ;;
    *)
        echo "unknown action '$action'"
        exit 1
        ;;
esac