Configuring VLAN adapters on Home Assistant Yellow

Perhaps foolishly, I thought it would be clever to segregate my home network with VLAN’s, to limit the way some of my home automation devices could access my network/the internet. This has largely turned out to be more trouble than it could possible be worth, particularly when it comes to my Home Assistant Yellow.

In theory, the goal would be to have my Yellow connect to two different VLAN’s. I’ve tried two main approaches - using the serial console to issue IP link commands creating the necessary virtual interface and hunting around with the SSH add-on to find some file I can configure this in. The closest I got was the serial console route, but I could never get the adapter assigned an DHCP address, and none of it would be persistent in any case, given the read-only filesystem.

Does anyone have any leads on how I might do this, or is just just too much network complexity to ask from the Yellow as configured?

HA is not designed like that and what you might see as HA is probably a lot more than what it really is, so the task is bigger than you might think.
HA is running on port 8123, but you might have a supervisor integration running on another port, which is another program.
You also have an observer port and then HA uses integrations like SSDP, mDNS and uPNP för discoveries that needs to be configured too.
On top of that comes what other integrations you might have that also uses the network.

HA is probably best suited to run on the IoT VLAN with port opened for access from your normal LAN to access the ports needed.

The control of IoT devices access to the internet should be handled by the firewall and is really not depending on VLANs.

Yeah-I thought as much. My prior setup simply had two virtual adapters on it to the necessary VLAN’s. But the introduction of Docker and the supervisor adds all the complexity you mention, and this may just not work. My options sound like flattening my network and abandoning the VLAN idea or going back to the non-containerized/supervised HA setup I already had.

I run my HA in a VLAN with my other Ioat devices.
This works pretty good.
Not many ports to open up for my main VLAN and my VPN is just using the same openings.
Discovery works on the IoT VLAN and the few devices I have else is added manually and managed in the firewall and maybe in combination with the VPN.
The firewall is set up to default drop all connection to and from the IoT VLAN.

If all devices was handled without discovery then the HA could be move to it own VLAN.

The thing with these setups is to let the router handle the routing and the firewall handle the blocking and allowing.
It is stupid to try and leave that to HA, especially when you try to run the same service on multiple interfaces.

Does anyone have any leads on how I might do this, or is just just too much network complexity to ask from the Yellow as configured?

My network is segregated into VLANs as well, and previously could just add network interfaces via Proxmox to the HAOS VM. So to HA, there two interfaces, they handled the VLAN traffic correctly (under the hood), and I was able to configure the interfaces within HA to whatever I wanted (DHCP, static, etc).
This worked perfectly for me, because I have some stuff on my “public” VLAN (XBox, Plex, other media stuff, etc), and IoT stuff on the IoT VLAN (Chinese switches, cameras, etc).

Then I got a Yellow and realized I couldn’t do this anymore. This is the only thread I found that came close to figuring it out, but just like every other thread, instead of directly answering your question, you got a lot of noise about how your network SHOULD be set up, and how HA can’t do this (I have no clue what @WallyR is saying in this thread, I literally can’t follow).

Guess what, it can be set up like how you want. Here’s the answer:

  • Get SSH/console access to your Yellow
  • Use nmcli to set up a 802.1Q VLAN interface
    • You were close, but HA uses NetworkManager to handle network (ahem) management
    • nmcli con add type vlan ifname <vlan name> dev <physical dev> id <vlan id>
    • e.g. for me, that command is nmcli con add type vlan ifname eth1 dev eth0 id 5
    • After this completes, the output of nmcli con show looks like this:
    • If the new VLAN is yellow, check nmcli dev status. Odds are, you’re not sending it VLAN tagged packets, so it’s sitting there not receiving any data. Once I fixed my managed switch to send tagged VLAN packets to that Ethernet port, it turned green and worked right away
  • Set new interface to DHCP
    • It might default to DHCP, but just in case it doesn’t:
    • nmcli device modify eth1 ipv4.method auto
    • nmcli device modify eth1 ipv6.method auto
    • If you want a static IP set at this level, I’d just google it. My rational is that I’ll never remember that I set a static IP way down in the HA host OS, or the minutia of how I got into the OS, so I set it to DHCP and reserve it up in my router.
  • Reboot the host

After a reboot, this is what I see in the OS:


This is what I see in HA:

And I verified all my VLAN 5 stuff is now reachable from HA. No fiddling with exclusive firewall rules and crap.

Hopefully this is what you were looking for.

7 Likes

Update 10-13-2023:

Because of the breaking change in the OS version 11.0, this broke my VLAN interface. It wasn’t showing up in HA → system → Network ETH1 anymore, so all my IoT VLAN stuff wasn’t showing up in HA.
Instead, the interface was showing up as:

To get the interface working again (the following commands are for my VLAN tagged “5”, tailor to your config):

  • nmcli con delete id "Supervisor eth1.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5"
  • nmcli con add type vlan ifname end1 dev end0 id 5
  • Now it shows
    image
  • Reboot
  • After a reboot it shows as
    image

And I’m good again

image

All the IoT stuff has reappeared, and we’re back online.
Maybe some day VLAN configurations could happen from HA via the Supervisor, but for now, this worked for me!

6 Likes

@justynnuff thanks for sharing this tutorial. I think that I will follow you, but wanted to double check what is the required setup on the switch side. Is the port connected to HA Yellow tagged for VLAN 5 and untagged for the trusted LAN VLAN?

1 Like

Sorry it took so long to reply, but to answer your question (and for myself when I forget in the future), yes. That is exactly how my switch is configured on the HA port.

It will get much worse with multi-home setups on HA.
Matter require IPv6 and you can not control it with that setup, because HA is lacking certain functions for such setup.
You will have the same network (fe80::slight_smile: on all your interfaces and only one of them will work with Matter, so you need to specify interface ID in your bindings and connections which is not possible.

Hey there, thanks for these tips – it’s exactly what I was looking for! However, it didn’t get me the whole way there, as I did not have access to the nmcli tool inside my ssh environment.

I tried installing the networkmanager-cli package inside the ssh container, but was met with failure. I’m using the “Advanced SSH & Web Terminal” add-on, but it’s based on a different version of Alpine than the host OS (3.20 instead of 3.19), so resulted in:

~ # nmcli con add type vlan ifname end1 dev end0 id 80
Warning: nmcli (1.46.2) and NetworkManager (1.44.2) versions don't match. Restarting NetworkManager is advised.
Error: Failed to add 'vlan-end1' connection: connection.autoconnect-ports: unknown property

Ultimately, what I needed to do was execute nmcli in the namespace of the host OS, which did the trick:

docker run --privileged --pid=host -it alpine:latest \
  nsenter -t 1 -m -u -n -i \
  nmcli con add type vlan ifname end1 dev end0 id 80

After a reboot, i now have a second interface available in the HA Web UI. After this, I’m now able to attach homekit devices which are on my IoT VLAN. Woohoo:

docker run --privileged --pid=host -it alpine:latest \
    nsenter -t 1 -m -u -n -i nmcli con show

Gives me this output:

NAME                UUID                                  TYPE      DEVICE
Supervisor eth0     df809884-d85a-305a-ad70-9212f80b0aa7  ethernet  end0
Supervisor end1.80  ba0e4c8a-3c7c-4761-9dc1-71d00f89b22a  vlan      end1
lo                  c93289ac-e43b-42f0-ae50-809470732de9  loopback  lo

Thank you!

Ah, and a small addition. This may not be required, but I didn’t want the IoT vlan connection to have a default gateway configured. This did the trick (using the connection name as reported in nmcli con show):

docker run --privileged --pid=host -it alpine:latest \
    nsenter -t 1 -m -u -n -i \
    nmcli con modify 'Supervisor end1.80' \
    ipv4.never-default yes ipv6.never-default yes

Ultimately, what I needed to do was execute nmcli in the namespace of the host OS, which did the trick:

That’s interesting, I didn’t even know you could do that from the HA instance itself. The “Terminal & SSH” addon is only to get SSH access inside the HA instance. To gain SSH access to the host, I followed these instructions.

I too didn’t know you could do that inside a docker container.
I think docker run --privileged --pid=host -it alpine:latest \ will download a Docker alpine linux image and runs nmcli from there.

Anyway, I run nmcli from either the console or ssh via -p22222

While that is true, since you’re running privileged and (importantly) in the host PID namespace, one can use nsenter to switch to the namespace of an arbitrary process on the host OS. By using nsenter -t 1, we get access to the namespaces of the host’s init process. In other words, the nsenter command is coming from the downloaded alpine image, but the subsequent command is, instead, executing from the host OS. Here are a couple examples using the debian:bookworm image:

~ # docker run --privileged --pid=host -it debian:bookworm grep PRETTY_NAME /etc/os-release
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
~ # docker run --privileged --pid=host -it debian:bookworm nsenter -t 1 -m -u -n -i grep PRETTY_NAME /etc/os-release
PRETTY_NAME="Home Assistant OS 13.2"

Here’s a random blog post I found with more details: Docker Tips : get a shell on the host | by Luc Juggery | @lucjuggery | Medium