Creating a Hollistic Work Environment

A walkthrough of my personal OpenBSD configuration and utilized software

In this post, I provide details on my after-installation OpenBSD configuration, software I use, and details on my Firefox configuration.

afterboot(8) Extras — On Openbsd

OpenBSD 5.6

These are some things I do after a clean installation of OpenBSD for desktop use. As the title alludes to, these are things I do after reading the afterboot man page. All of this info is in the man pages and FAQ already, but this document should lay out some other things you may want to have up and running in a dissectable manner.

Root Permissions For user

# echo "permit persist keepenv :wheel" >/etc/doas.conf

In case you did not add your user to the :wheel group during the installation, you can do so like this:

# usermod -G wheel user

Now you can do your whole system configuration as your user provided that you use the doas command.

WIFI

Identify your network card:

$ ifconfig

Then, scan your local networks with:

$ ifconfig iwn0 scan # change "iwn0" for your network card

Once you’ve identified your network card, edit the file /etc/hostname.iwn0 adjusting the final iwn0 with your card. Finally, add your WIFI ssid and wpakey:

join wifiname wpakey wifipassword
join anotherwifi wpakey "anotherpass$123"

# randomize mac address on untrusted networks
lladdr random join wifi-name-cool wpakey "password-cool"

# ipv4
inet autoconf

# ipv6
inet6 autoconf

up

Audio

This is not necessary, but if you have a USB audio device, this is what you would use for sndiod to recognize which audio device to use:

# echo "sndiod_flags=-f rsnd/0 -F rsnd/1" >/etc/rc.conf.local

It may come useful when you least expect it.

Firewall

The following is a sane firewall configuration for your average desktop user and it will be placed in /etc/pf.conf:

set block-policy drop
set skip on lo

match in all scrub (no-df random-id max-mss 1440)
antispoof quick for egress

# block all traffic
block

# access ipv4 and ipv6
pass out quick inet
pass out quick inet6

# for use with mail transfer agents
pass in proto icmp

Test your config and then apply:

# pfctl -fn /etc/pf.conf && pfctl -f /etc/pf.conf

Performance Optimizations

Since OpenBSD is more security oriented, the default performance can be lacking even on newer hardware. These steps should alleviate the speed issues.

Becoming a Staff Member

Add your user to the :staff group in order to access more of your system resources:

# usermod -L staff user
# usermod -G staff user

Hyper Threading

One thing that will actually increase your performance is enabling hyper threading. It is disabled by default due to some security concerns. My laptop at the time of writing is a relatively slow computer, so I can tell the difference. If your laptop is newer, say 2016 and up, you might not need it. You can test it with:

# sysctl hw.smt=1

On a thinkpad x61, the performance is immediately noticeable. firefox becomes usable with it enabled.

Enable it permanently on next boot:

# echo hw.smt=1 >>/etc/sysctl.conf

For further performance optimizations, watch this video.

Laptop Lid

I prefer to close the lid and work on my monitor. To close the lid without sending the laptop to sleep, you do the following:

# echo machdep.lidaction=0 >>/etc/sysctl.conf

You can always run zzz if you enabled apmd whenever if you want to put your device to sleep, which does not require root permission in any case.

Sending mail with OpenSMTPD

OpenBSD comes with OpenSMTPD as the smtpd server and client. The following configuration will be used to send mail to the web from any accounts you wish to configure. Note that this configuration does not handle local mail. Read smtpd.conf(5) for that info.

In /etc/mail/smtpd.conf:

# your credentials for your accounts go in this file (the "passwd" bit can be named anything):
table passwd file:/etc/mail/passwd

# configure your accounts' email, authentication protocol, port, and credentials (which
# are held in the "passwd" table) for opensmtpd to use when sending mail:
action "outbound_user" relay host smtp+tls://user@example.com:587 auth <passwd>
action "outbound_gmail" relay host smtp+tls://gmail@smtp.gmail.com:587 auth <passwd>

# tell smtpd to use those actions when sending mail with the following emails
match mail-from "user@example.com" for any action "outbound_user"
match mail-from "username@gmail.com" for any action "outbound_gmail"

Now, to edit /etc/mail/passwd, you need to create the file and edit its permissions.

# touch /etc/mail/passwd
# chmod 640 /etc/mail/passwd
# chown root:_smtpd /etc/mail/passwd

The credentials themselves /etc/mail/passwd:

# the first argument matches the name you gave it: smtp+tls://user@example.com:587
# the second is the username for the mail server
# also, some email servers do not acclimate your username to the server. see example
# with the first email server, and gmail
user user@.example.com:yourpassword
gmail username:yourapppassword

Everything should be in working order now. Test the configuration and restart the daemon to load your changes:

# smtpd -n && rcctl restart smtpd

Test your configuration:

$ echo world | mail -r your@mail.org -s hello your@mail.org

Now you should have OpenSMTPD working in order to send mail even when offline!

My preferred mail client is listed in the software section.

Virtual Machines: vmd

To use software not supported in OpenBSD, Windows programs with wine, or maybe even test software you are not sure whether you trust, you cat use virtual machines as a secondary environment. The native hyper visor has no graphical support, meaning it can only connect to the console and control it through ssh with your private interfaces. The substitute for using graphical applications is to use ssh with X11 Forwarding enabled or vnc. The latter is not worth the trouble to setup in my opinion.

I will not go into much detail, for this you best visit the faq. To get networking working, add this to the firewall at /etc/pf.conf:

match out on egress from 100.64.0.0/10 to any nat-to (egress)
pass in proto { udp tcp } from 100.64.0.0/10 to any port domain \
	rdr-to 9.9.9.9 port domain

For our pf.conf the “9.9.9.9” part is the DNS server, Quad9’s to be specific. This could be changed to your ISPs DNS servers which are located at /etc/resolv.conf and or any other DNS server.

Next, we modify our VM settings at /etc/vm.conf:

vm "alpine" {
        disable                                                 # don't start up at boot
        memory 4096M                                            # max that can be used
        disk "/home/user/vm/alpine.qcow2"                       # disk
        cdrom "/home/user/isos/alpine-virt-3.17.3-x86_64.iso"   # this cannot be a .img
        owner user:user                                         # control vm without root privs
        local interface                                         # give networking to the vm
}

Add the following lines to /etc/sysctl.conf to allow the VM to use the internet:

net.inet.ip.forwarding=1
net.inet6.ip6.forwarding=1

VM Guests

For my choice of VM operating system, I use Alpine Linux as it is plenty sufficient for my needs. If you need something more feature-full, I would recommend Debian Linux.

I usually like to configure X11 Forwarding on the VM so that I can use GUI programs on the native OS via any ssh connection. It is not instant, but it is good for basic tasks. Now, to setup X11 Forwarding on your VM’s, you need to have Xorg installed, and you must activate it in /etc/ssh/sshd_config on the VM side. Uncomment or add the following line to the mentioned file:

X11Forwarding yes

And test on your local machine with:

$ ssh -X user@100.64.1.3 gui-program # 100.64.1.3 is the local ip your vm was given

In case it asks you that the host is missing some keys, run on your local machine:

$ ssh-keygen -R 100.64.1.3

Notes on Alpine Linux for Virtualization

Add this to /boot/extlinux.conf:

console=ttyS0,115200

It should be placed in the following highlighted section of the /boot/extlinux.conf file:

...
TIMEOUT 5
LABEL lts
	...
	APPEND root=.......... console=ttyS0,115200
...

This allows the VM’s console mode to be matched with the VM guest, making the console mode much snappier.

If you want to do X11 Forwarding, then on the VM running alpine, setup xorg:

# setup-xorg-base

Next, install some packages:

# apk add wine git

Using wine

wine is a Windows program emulator that works well in alpine linux for 64 bit programs.

Firstly, wine can create separate environments to store your data and Windows programs on that folder. To create these environments for you to actually run .exe programs, you will need to run an environmental variable before executing your program or installer:

$ WINEPREFIX="$HOME/.wine/program-folder-name" WINEARCH=win32 wine setup.exe

To further explain, the WINEPREFIX is where the setup will extract its files and where everything will be saved from there on (except for .desktop files), and the WINEARCH=win32 specifies that the program is 32-bit. The latter only needs to be done once to specify that the WINEPREFIX is a 32-bit Windows system per se. After that, depending on whether it is a simple .exe or a setup wizard, you can launch it in various ways. I launch the programs by finding the local .exe in the WINEPREFIX folder and creating an alias for it for easy launching.

Notes On My $HOME

I try to keep things simple and rely on defaults whenever possible. Most of my programs are installed via the OpenBSD package manager. This configuration is universal for most unix systems that can build the following programs.

From here on out, it is basically a poor man’s git server. I do not modify my system enough to justify trusting GitHub or setting up a git server. So this will do.

X Configuration

Because OpenBSD’s xorg fork has a built-in login screen, I do not go into the console directly, so, what you might place in a .xinitrc and .profile I condensed here into $HOME/.xsession:

export PATH="$PATH:$HOME/.local/bin"

# make our oksh configuration visible in our X session
export ENV=$HOME/.kshrc

# Default programs:
export EDITOR="vim"
export TERMINAL="st"
export BROWSER="firefox"
export READER="zathura"

# ~/ Clean-up:
export XDG_CONFIG_HOME="$HOME/.config"
export XDG_DATA_HOME="$HOME/.local/share"
export XDG_CACHE_HOME="$HOME/.cache"
export PASSWORD_STORE_DIR="$XDG_DATA_HOME/passwords"

# UTF-8 everywhere
export LC_CTYPE=en_US.UTF-8
export LANG=en_US.UTF-8

# firefox
export MOZ_X11_EGL=1
export MOZ_ACCELERATED=1
export MOZ_WEBRENDER=1
export DBUS_SESSION_BUS_ADDRESS="no" # this might break stuff

# Commands go after environment variables

# Disable caps and change it to compose key.
setxkbmap -option compose:caps,compose:nocaps
# Turn off caps lock if on since there is no longer a key for it.
xset -q | grep -q "Caps Lock:\s*on" && xdotool key Caps_Lock

# Decrease key repeat delay to 300ms and increase key repeat rate to 50 per second.
xset r rate 300 50

# Blue light filter. Modify "-l" flag to your coordinates
redshift -l 1.0:-1.0 -t 4800:2700 -g 0.8 -m randr -v >/dev/null 2>&1 &

# Disable core dumps
ulimit -Sc 0 &

# no more bell sound
xset b off

# when X is loaded, check for external monitor on displayport.
# If detected, switch to it and shutdown laptop screen
xrandr | grep 'DP-2 connected' >/dev/null 2>&1 &&
xrandr --output DP-2 --auto --output LVDS-1 --off >/dev/null 2>&1

# Dwm status bar
slstatus &

# Wallpaper
xwallpaper --zoom ~/pics/bg &

# Exec WM
exec dwm

Shell: oksh

oksh is the default shell for OpenBSD. There is a port to run on other operating systems. oksh has a default configuration which can be found at /etc/ksh.kshrc that has some nice aliases to manage your jobs and a nice title bar configured.

Source the file locally in $HOME/.kshrc:

. /etc/ksh.kshrc

This is my configuration:

set -o vi

alias \
        v="$EDITOR" \
        dv="doas $EDITOR" \
        p="nsxiv" \
        z="zathura" \
        news='newsraft' \
        t="transmission-remote" \
        mpa="mpv --no-video" \
        mpb="mpv --save-position-on-quit" \
        yt='yt-dlp --embed-metadata -i -f "bestvideo[height<=?1080][fps<=?60]+bestaudio/best[height<=?1080][fps<=?60]"' \
        yta="yt -f bestaudio/best -x --audio-format mp3 --embed-metadata --embed-thumbnail --audio-quality 320k" \
        wttr='curl wttr.in/$LOCATION' \
        ipp='curl ifconfig.me' \
        sdn="doas shutdown -h now"

# Bash-like syntax
PS1='$(print -n "`logname`@`hostname -s`:"; [[ "${PWD#$HOME}" != "$PWD" ]] && print -n "~${PWD#$HOME}" || print -n "$PWD"; print "$ ")'

Software

Web Browser: firefox

This browser does not truly respect your privacy until you tweak a couple of things. I go in depth in below in Working with Firefox.

Mail Client: aerc

aerc’s defaults are quite sensible, so most of my configuration comes from how I send and receive mail. The following account configuration example is using aerc’s built-in mail fetching and sending protocols:

[john]
source        = imaps://user:PasswordExample123@mail.example.com
outgoing      = smtps://user:PasswordExample123@mail.example.com
default       = INBOX
from          = "John Doe" <john@example.com>
cache-headers = true

[cath]
source        = imaps://cath:PasswordExample123@mail.example.com
outgoing      = smtps://cath:PasswordExample123@mail.example.com
default       = INBOX
from          = "Cath Doe" <cath@example.com>
cache-headers = true

The passwords are encrypted by default if you follow the wizard on startup.

If you have OpenSMTPD setup, or an equivalent like Postfix, you can send mail with sendmail linked in aerc’s account.conf file. Just change the outgoing section to the following for one or multiple accounts. And for offline mail, use your Maildir folder to access your offline mail. Modify the source section and add your mail fetch command for aerc to run automatically:

[john]
check-mail-cmd = fdm fetch
source         = maildir://~/mail
outgoing       = /usr/sbin/sendmail
default        = INBOX
from           = "John Doe" <john@example.com>
cache-headers  = true

Mail Fetcher: fdm

fdm is easier to use than the more popular alternative mbsync/isync and is developed by a tmux developer which was first developed for OpenBSD.

The default config file is found in $HOME/.fdm.conf:

# define your maildir location
action "inbox" maildir "%h/mail"

# configure which accounts to fetch mail from
account "example" imaps server "example.com" user "user@example.com" pass "yourpassword"
account "gmail" imaps server "imap.gmail.com" user "yourGmail@gmail.com" pass "yourgmailapppassword"

# every mail fetched goes to the defined maildir folder
match all action "inbox"

To set the proper permissions on the file, run:

$ chmod 600 .fdm.conf

And that should be it. Beware though, by default, fdm fetches your mail from your server onto your device, meaning mail will be deleted on your server and stored locally. You can now fetch and manage your mail with fdm and your preferred mail client. To fetch your mail:

$ fdm fetch

Video/Music Player: mpv

The configuration file can be found in $HOME/.config/mpv/mpv.conf:

# choose english audio if available
alang=eng
# turn 5.1 surround to 2.0 stereo
audio-channels=stereo

# set the highest quality video to 1080p 60fps
ytdl-format=bestvideo[height<=?1080][fps<=?60]+bestaudio/best[height<=?1080][fps<=?60]

# sane beginning size
autofit=50%

# less output
quiet

And to change a couple of keyboard bindings, change $HOME/.config/mpv/input.conf:

# vim bindings
l seek 5
h seek -5
j seek -60
k seek 60

Other Software

Here I will put software that I do not modify or have personal configurations as such.

Window Manager: dwm

A very small and concise window manager. I run dwm with no patches. Just bindings and default to floating mode.

Terminal: st

A very feature-less terminal that just works. For st, I use the scrollback patch to enable scrolling.

Dynamic Menu: dmenu

Highly versatile menu used for scripting. Look at the dmenu scripts section for inspiration.

Text Editing and Text Composer: vi and vim

vim for composing text as it supports utf-8 and vi for everything else.

Music/Audio Player: cmus and mpv

I use cmus for local storage and mpv for web based music or podcast.

Checkout SomaFM if you haven’t already. You can stream the radio stations on the terminal with mpv.

RSS Reader: newsraft

Great tool to keep you off the browser.

Torrent Client: Transmission

There are GUI and TUI interfaces out there, but the terminal client transmission-remote works for me.

Presentations: sent

The easiest way to make presentations; just a paragraph per page. It also supports images. I use the pdf patch in order to compile it into a pdf and be able to send it to another person.

Document/PDF Viewer: zathura

A great document reader that remembers your reading progress, shows tabs, and reloads files automatically for work with TeX. After installing some plugins you can open PDF, Postscript, DJVU, EPUB, and more!

Writing Documents: TeX

To write documents in PDF format, I use TeX, the precursor of the popular LaTeX. OpTeX is a great addition to use more advanced features with the same small footprint of TeX.

Office 365 Replacement: Libreoffice

The open source, free alternative to Office 365. I do not create content with this, but this will take care of the occasional Microsoft document you have to open.

Image Viewer: nsxiv

Simple Image viewer with a nice thumbnail mode.

Image Editing: gimp and ImageMagick

gimp for photoshop-like image editing and magick for simple edits in the command line.

Working with Firefox

firefox is known to phone home back to their servers. We can mitigate the tracking by customizing our profile through a user.js file.

Note that you should be able to configure your firefox straight from this document without having to fall back to other resources. Of course, I encourage you to read the documentation for these projects, but, if you are in a hurry, this will do fine.

user.js

For this configuration, you will need the arkenfox user.js file in your profile. Your profile is your advanced configuration for firefox. If you do not know where your profile is stored, go to about:profiles in the url bar. Once you’re in that directory, fetch the user.js file:

$ curl -sL "https://raw.githubusercontent.com/arkenfox/user.js/master/user.js" > user.js

Read the arkenfox wiki, it details the important bits about the user.js file and what problems you might be faced with in the future. Personally, I’ve done everything with this user.js without any issues, what might break stuff is any further privacy configurations added to the user.js file, which will be explained in a bit.

Now, I append more settings to the user.js from these sources:

Here is my extra.js which you can put in the original user.js. If you do not have a router of some sort with dns blocking capabilities, uncomment the last line and change the second-to-last value to 2. This will help route your dns queries through a more trustworthy source.

If the additional user.js configurations cause some mishap on your browsing, you can do without the extra.js.

Extensions

uBlock Origin

If you could only have one extension installed to your browser, uBlock Origin would be the one. It is, as the description says, a wide-spectrum blocker.

Set up your preferred blocking mode. There are a couple of them, ranging from very easy, to hard mode. I opt for the Easy mode.

Skip Redirect

This add-on skips intermediary pages found in redirect links to go straight to the target. These type of links are solely used to track you.

If you use the web archive, you need to add an exception rule, which can be done so in the No-skip-urls-list section of the extension:

web.archive.org/

True Sight

Used to find out what content delivery network (CDN) is serving your content. This is a great tool for informational purposes.

Vimium

Adds vim-like bindings to your browsing experience. This is one of the most minimal and functional vim keybinding add-on for firefox.

Privacy-Oriented Origin Policy

This add-on replaces disabling Referrer Headers in the user.js allowing you to whitelist affected pages. I run it in aggressive mode with rare site breakage. The P.O.O.P website explains it clearly, though.

Flagfox

Another great informational add-on that shows you a flag in the url bar with the country of origin of where the server is being hosted. It can also pipe the current url to many services.

LocalCDN

Loads CDN resources locally to speed up load times and connect to these external resources less often.

play-with

I use this add-on to pipe videos, including YouTube and audio to mpv.

List Feeds

Searches for RSS and Atom feeds in a page and lists them in the url icon.

Open in Sci-Hub

Puts a Sci-Hub icon in the url bar when visiting paywalled academic articles to easily view it in the Sci-Hub database.

OpenBSD Specifics

Unveil directories

If you are using OpenBSD, you would know that firefox can only see directories in which you give it access to. To edit this website locally, I do:

# echo "~/content r" >>/etc/firefox/unveil.content

Once you restart firefox you should be able to have read access to everything in the content folder.

Unveil Software

If you want to read pdf’s directly from a document viewer instead of the firefox pdf viewer, you need to unveil(2) the package itself, as well as making it a “default application”.

To unveil your preferred document reader, do the following:

# echo "/usr/local/bin/zathura rx" >>/etc/firefox/unveil.main

Notice the file we are writing to. It will be unveil.main instead of unveil.content.

firefox is now able to read and execute zathura, but it does not know it to be the pdf viewer. To make firefox understand so, we do the following:

$ echo "application/pdf; /usr/local/bin/zathura %s" >~/.mailcap

Restart firefox, go to the settings page, search for default applications, and you can now choose the option that says Use system default application next to the pdf section. You should now be able to open pdf docs directly from firefox with a document viewer.

Video Conferences

If this is something you must do, it can be setup quite easily. You need to permit video and audio recording down to the kernel and make your webcam usable by your user:

# sysctl kern.audio.record=1
# sysctl kern.video.record=1
# chown user /dev/video0

The chown bit only needs to be done once for your device. After a reboot, the only steps you would need to take are the first two commands. Also, the webcam can also be /dev/video1 for example.

Resources