Things I couldn’t find elsewhere

Bluetooth and Home Assistant in rootless docker

AI-generated image of a bus with PCB-looking signal traces around it
If I remember correctly, at one point my Home Assistant (H-A from now on) installation started complaining on the Bluetooth component not starting up correctly. Since I wasn’t using Bluetooth (the server doesn’t even have the hardware for it) I just ignored it.

Until a few days ago. I wanted to start playing with ESPHome, and that integration has the Bluetooth component as a required dependency.

Lots of searching later, I did have some clues. It seems others had run into the same issue, with the only suggested solution being to add –privileged to the containers. Now that’s no good, I run all my services rootless for security reasons and so should you. I realized I would need to figure out that actual root cause myself.

The key information gleaned from the log was that it had to do with dbus authentication getting rejected:

File "/usr/local/lib/python3.10/site-packages/dbus_next/auth.py", line 78, in _receive_line
    raise AuthError(f'authentication failed: {response.value}: {args}')
dbus_next.errors.AuthError: authentication failed: REJECTED: ['EXTERNAL']

This lead to some additional guidance from similar issues being solved with keeping the user namespace between host and container, again, not something you want to do with rootless containers. At this point it seemed clear I needed to figure out what made dbus reject the authentication - and after I while I ended up at a non-resolved five year old libdbus issue thanks to a discussion on the Qt issues board: Simply don’t add the user id to the authentication request since the host and container ids don’t match. It’s not needed according to the spec anyway!

This seemed promising! I got to work setting up a VM with Alpine Linux, patching libdbus and then transfering that lib over to my H-A container only to find out that … it made no difference whatsoever. This had me stumped for a while, until I looked into the actual Python libraries used:

“dbus-fast: A faster version of dbus-next originally from the great DBus next library. dbus-fast is a Python library for DBus that aims to be a performant fully featured high level library primarily geared towards integration of applications into Linux desktop and mobile environments. dbus-fast plans to improve over other DBus libraries for Python in the following ways: Zero dependencies and pure Python 3

https://pypi.org/project/dbus-fast/

Zero dependencies? Not using libdbus? I jumped into the live Python code in my container and found where authentication was made. Indeed the code was able to handle both the case with a supplied user id and without, so I assumed that somewhere in the H-A code or parent component dependency one was supplied even when running within rootless containers. I made an ugly patch to always enforce the no-id case and restarted my container.

ESPHome loaded up perfectly fine. I even dug up a USB Bluetooth adapter and plugged into the server and was greeted by H-A immediately recognizing and configuring it.

I added the ugly patch to my existing H-A container Dockerfile and it’s been working since. Now, maybe I should go find out whether dbus-fast, or the bluetooth-adapters component that pulls it in within H-A, should make a change - but I’ll leave it here having documented it both on Mastodon, on my blog and also as a comment on the H-A community forums.

And if you’ve run into this issue, here’s how you can solve it in your Dockerfile too. Make sure to copy the contents, there’s a bunch of whitespace needed to align the code correctly.

# patch dbus-fast to not use AUTH EXTERNAL ID  
RUN /bin/sed -i '/self\.negotiate_unix_fd = negotiate_unix_fd/a \        self.uid = UID_NOT_SPECIFIED' /usr/local/lib/python3.11/site-packages/dbus_fast/auth.py