---
author:
    email: mail@petermolnar.net
    image: https://petermolnar.net/favicon.jpg
    name: Peter Molnar
    url: https://petermolnar.net
lang: en
published: '2024-09-26T21:30:00+01:00'
summary: My current, FreeBSD based server for self-hosting and home automation - now with a touchscreen!
tags:
title: FreeBSD "kiosk" for home automation dashboard
---

## Background

For quite a few years now I have been looking for a small touchscreen, because I wanted a local (no network involved) interface  for my home automation server. I tried the following which didn't work:

- A Raspberry Pi (3b) with the official touchscreen. The official screen is 800*600, which is sad in 2024 _(it was sad in the early 2000s already)_, and I ended up with severe realibility issues due to the horrors of the Pi's USB architecture and the Sonoff Zigbee adapter I'm using.
- Cheap, Chinese, HDMI display: 1024*600, without any decent feature of a display, like power management: it just kept telling me there's no signal without going to sleep.
- Mimo displays - driver horrors on linux, I haven't had that for decades. They are not useful as a general displays at all becase they need the OS to boot first, so no picture until the OS boots. 
- ELO POS terminal (1215L) which, apart from being way too large and heavy, also needs it's own, picky, horribly drivers for the touch part to work. It's also ancient, with a foil based touch solution, that feels rather horrible.

I nearly gave up: the machine I choose, the Lenovo M600 tiny (I have an unneeded on I'm currently selling, if anyone wants a fanless mini pc[^4]) only has 2 DisplayPort connectors, and DP -> HDMI adapters are not great. Then suddenly, I found the HP L7010t 10.1-inch Retail Touch Monitor[^2]: Displayport + touch, no special drivers, and even FreeBSD's kernel can use the touch features out of the box.

## Minimal X to run a single browser session on FreeBSD

On FreeBSD 14.1, the base system needed the following:


```sh
pkg install xorg xorg-server drm-kmod xf86-video-intel gsed epiphany openbox
```

`xf86-video-intel` is not in the official documentation, but it's needed[^1].

Tried `twm`, `tinywm`: they had issues with window size. Tried `dwm` but the menubar is annoying. Settled with `openbox`.

Tried `midori`, but wasn't working smooth, `firefox-esr`, but it consumed too much CPU and touch scrolling wasn't working fine, `chromium` which worked perfectly but had too much Google in it for this scenario, `surf-browser` which didn't work at all. settled with `epiphany`.

These are needed to enable graphics and auto-power off the screen:

```bash
sysrc kld_list+=i915kms
sysrc blanktime=300
```

Create a user that will be logged in automaticaly:

```bash
pw adduser -n kioskuser -d /home/kioskuser -s /bin/sh
```

Set up auto login for this user:

```bash
cp /etc/gettytab /etc/gettytab.backup
gsed -ri 's/root/kioskuser/g' /etc/gettytab
```

In `/etc/ttys` change 

```apache
ttyv0 "/usr/libexec/getty Pc"   xterm onifexists secure
```

to

```apache
ttyv0 "/usr/libexec/getty autologin"   xterm onifexists secure
```

Then create:

`/home/kioskuser/.profile`

```bash
ENV=$HOME/.shrc; export ENV

if [ "$PWD" != "$HOME" ] && [ "$PWD" -ef "$HOME" ] ; then cd ; fi

XPID=`pgrep xinit`
if [ -z "$XPID" ] && [ `tty` == "/dev/ttyv0" ]; then
  startx
fi

```

And:

`/home/kioskuser/.xinitrc`


```bash
#!/bin/sh

userresources=$HOME/.Xresources
usermodmap=$HOME/.Xmodmap
sysresources=/usr/local/etc/X11/xinit/.Xresources
sysmodmap=/usr/local/etc/X11/xinit/.Xmodmap

# merge in defaults and keymaps
if [ -f $sysresources ]; then
  xrdb -merge $sysresources
fi

if [ -f $sysmodmap ]; then
  xmodmap $sysmodmap
fi

if [ -f "$userresources" ]; then
  xrdb -merge "$userresources"
fi

if [ -f "$usermodmap" ]; then
  xmodmap "$usermodmap"
fi

xset +dpms
xset s on
xset s blank
openbox &
exec /usr/local/bin/epiphany
```

Which should auto-start X with `epiphany`. 

**Note: this is not hardened, if the browser is closed, the user will be in the shell, X and epiphany will not auto-restart.**

## Extra: home automation jail on `lo0` with PF firewall routing

I moved my services onto a single machine which now runs 3 jail: one for web and exposed to the world services, one for home automation, and one for minidlna. The first two listen on an extra 127.0.0.x on `lo0`, while the last has it's own IP. This also makes it quite simple to create a backup of them: I found zrepl[^5] and I can sync the jails onto a virtual machine on my laptop. Backup problem solved without needing to run yet another computer at home. 

I ended up with this setup because my router - a FRITZ!Box 7530 AX - is surprisingly dumb, and can't comprehend the idea of multiple IPs on the same node, so to overcome any possible routing issue I decided to use a single IP initially and route everything with `pf` locally. 

I mostly works, except for DLNA. I can't make the DLNA broascast packets work with this setup, so that jail is the exception, but I won't get into details with that now.

Zigbee2MQTT needs access to raw sockets, so that has to be reflected in the jail setup:

`/etc/jail.conf`

```apache
domoticz {
  exec.start = "/bin/sh /etc/rc";
  exec.poststart = "/bin/sh /usr/local/jails/domoticz/usr/local/etc/jail_dev_symlinks.sh";
  exec.poststart += "/usr/sbin/service pf reload";
  exec.stop = "/bin/sh /etc/rc.shutdown";
  exec.consolelog = "/var/log/jail_console_${name}.log";

  # PERMISSIONS
  allow.raw_sockets;
  allow.read_msgbuf;
  exec.clean;
  mount.devfs;
  devfs_ruleset = 3;
  allow.reserved_ports;

  # HOSTNAME/PATH
  host.hostname = "${name}";
  path = "/usr/local/jails/${name}";

  # NETWORK
  ip4.addr = 127.0.0.2;
  interface = lo0;
}
```

And to avoid issues with tty namings, I run a script to create the symlinks. I tried doing this properly with devd, but it's virtually impossible inside the jails to do it right. 

`/usr/local/jails/domoticz/usr/local/etc/jail_dev_symlinks.sh`

```bash
#!/bin/sh

rootdir="/usr/local/jails/domoticz"
vendor="0x10c4"
product="0xea60"
ttyname=`sysctl dev.uslcom | grep "vendor=$vendor product=$product" | sed -r 's/.*ttyname=([^\s]+) .*/\1/'`
chgrp dialer $rootdir/dev/tty$ttyname
chown zigbee2mqtt $rootdir/dev/tty$ttyname 
chmod g+rw $rootdir/dev/tty$ttyname 
/bin/ln -s /dev/tty$ttyname $rootdir/dev/ttyUzigbee
```

As I mentioned, the two main jails listen on `lo0` so they don't have issues of not having 127.0.0.1 resolved and so only what PF allows will be exposed this way.

`/usr/local/etc/pf.conf`

```apache
# vim: set ft=pf
# /usr/local/etc/pf.conf
 
lan="re0"
lo="lo0"
localnet = $lan:network
jail_domoticz="127.0.0.2"
local_ip="192.168.1.2"

# 8800: node-red
# 8880: zigbee2mqtt
# 8088: domoticz
# 1883: mqtt
rdr on $lan inet proto {tcp, udp} from any to $lan port {8800, 8880, 8088, 1883} -> $jail_domoticz
nat on $lan from { $jail_domoticz } to any -> $local_ip

block in all
block return

pass inet proto icmp icmp-type echoreq
pass quick proto pfsync
pass proto carp

# for jail
pass proto tcp from any to $jail_domoticz port { 8800, 8880, 8088, 1883 } keep state

# ssh - you probably want this
pass proto tcp from any to $lan port { 22 } keep state

pass from {$lan, $lo} to any keep state

pass out all keep state
```



## Thoughts on Home Assistant 

I gave Home Assistant yet another go. Every once in a while I try it out to see if it got simpler, but no: it's not even slowly becoming a bloated monster. It started as heaviweight, but it's just ridiculous now. 

First and foremost their idea of supporting the last 2 versions of Python is already not true: I wasn't able to install the current version on 3.11, which FreeBSD 14.1 comes with. Not supporting stable Debian Python[^3] is a shitty decision. 

In the end I wasn't able to install it at all. It's one thing that pip install needs to compile half the universe because it's not actually Python but C or Rust and it's not distributed for FreeBSD, but once it all looked good and I started `hass` is started to install **even more** Python modules.

This thing is badly designed, going entirely against ideas of simplicity and robustness, and I'm genuinely losing my belief in anything Python these days. So many projects out there will tell you "just use docker" thinking you want one more layer of complexity, or that it's available for you at all. 

Dated or not, Domoticz is staying true to it's simle philosophy of it just works, and I'm going to stay loyal to it in the foreseable future.

## Other notes

Don't try to run anything DLNA, like `minidlna` behind a firewall. It doesn't work.



[^1]: https://forums.freebsd.org/threads/unable-to-start-anything-x.95048/#post-672721
[^3]: https://wiki.debian.org/DebianBookworm
[^2]: https://www.ebay.co.uk/itm/155788268323
[^4]: https://www.ebay.co.uk/itm/186603942366
[^5]: https://zrepl.github.io/