Running Home Assistant on Windows in Docker

I wanted to move HA to my home server, I can run Hyper-V images as needed but most service I run these days are in Docker, so looked up how to do this for Home Assistant.

Introduction

This was originally taken from [Guide] Hass.IO on Windows 10 WSL2 (No more VMs!) and updated as needed for how I run it on Windows.

Basically this is HASS.IO running on Docker in Windows 10 WSL2

Setting up WSL 2

  1. Install WSL (Don’t install a linux distro yet): Open PowerShell as Administrator and run Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux

  2. Restart your computer when prompted.

  3. Enable WSL2 Open PowerShell as Administrator and run:

    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
    
  4. Restart computer to apply changes

  5. Open PowerShell as Administrator and the following command, leave it open after doing so. wsl --set-default-version 2

  6. Open the Microsoft Store and install Ubuntu, launch it and let it install, it will prompt to set a username and password.

  7. Verify ubuntu is using WSL2 via the Powershell from before using wsl --list --verbose or wsl -l -v

  8. Start the WSL shell by running wsl in the powershell window.

  9. Run sudo apt-get update in Ubuntu

Prepare for Home Assistant Install

If you want to upgrade this is helpful How to Upgrade Ubuntu 18.04 LTS to 20.04 LTS on WSL (Windows 10)

For Ubuntu 18.04:

wget https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb

For Ubuntu 19.04:

wget -q https://packages.microsoft.com/config/ubuntu/19.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb

For Ubuntu 20.04 (This appears to be the version that is installed from the store currently for “Ubuntu”)

wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb

The rest should be the same for all of them

sudo dpkg -i packages-microsoft-prod.deb
sudo apt-get update
sudo apt-get install apt-transport-https
sudo apt-get update
sudo apt-get install dotnet-runtime-3.1
curl -s https://packagecloud.io/install/repositories/arkane-systems/wsl-translinux/script.deb.sh | sudo bash
sudo apt install systemd-genie

System restart might be needed, try running genie -s in ubuntu terminal, if you get an error run genie -c bash

Install Home Assistant

References

Install the dependencies below first.

sudo apt-get install \
    bash \
    jq \
    curl \
    avahi-daemon \
    dbus \
    apparmor-utils \
    network-manager

Run as root (sudo su)

curl -Lo installer.sh https://raw.githubusercontent.com/home-assistant/supervised-installer/master/installer.sh
bash installer.sh --machine qemux86-64

Within a few minutes you’ll be able to access HASS.IO on localhost:8123

Unfortunately, WSL2 does not yet support bridged networking

So in order to be able to access HASS from outside the local machine we’ll need to run this workaround script at startup, it will also run HASS with the “genie -i” command.

Save this script somewhere on your PC with a .ps1 ending, note that you can add/remove/edit the ports you want forwarded from WSL


bash.exe -c "genie -i"
$remoteport = bash.exe -c "ifconfig eth0 | grep 'inet '"
$found = $remoteport -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}';

if( $found ){
  $remoteport = $matches[0];
} else{
  echo "The Script Exited, the ip address of WSL 2 cannot be found";
  exit;
}

# [Ports]

# All the ports you want to forward separated by coma

$ports=@(80,443,8123,1880,1883,1884,8883,8884);

# [Static ip]

# You can change the addr to your ip config to listen to a specific address

$addr='0.0.0.0';
$ports_a = $ports -join ",";

# Remove Firewall Exception Rules

iex "Remove-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' ";

# adding Exception Rules for inbound and outbound Rules

iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Outbound -LocalPort $ports_a -Action Allow -Protocol TCP";
iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Inbound -LocalPort $ports_a -Action Allow -Protocol TCP";

for( $i = 0; $i -lt $ports.length; $i++ ){
  $port = $ports[$i];
  iex "netsh interface portproxy delete v4tov4 listenport=$port listenaddress=$addr";
  iex "netsh interface portproxy add v4tov4 listenport=$port listenaddress=$addr connectport=$port connectaddress=$remoteport";
}

Open Task Scheduler and add click “Create Task” Under General - “Check run whether user is logged in or not” and “Run with the highest privileges” Under triggers click New, Begin the task at logon of any user Under Actions click New, Select Start a program and type in program/script ‘Powershell.exe’ in arguments type ‘-ExecutionPolicy Bypass c:\Users\User\hass.ps1’ (Change the path to your saved script file)

(Optional: Under settings you can check “if the task fails, restart every X minutes” if you’re having issues)

hit OK.

Unfortunately, WSL2 does not yet support bridged networking

So in order to be able to access HASS from outside the local machine we’ll need to run this workaround script at startup, it will also run HASS with the “genie -i” command.

Save this script somewhere on your PC with a .ps1 ending, note that you can add/remove/edit the ports you want forwarded from WSL


bash.exe -c "genie -i"
$remoteport = bash.exe -c "ifconfig eth0 | grep 'inet '"
$found = $remoteport -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}';

if( $found ){
  $remoteport = $matches[0];
} else{
  echo "The Script Exited, the ip address of WSL 2 cannot be found";
  exit;
}

# [Ports]

# All the ports you want to forward separated by coma

$ports=@(80,443,8123,1880,1883,1884,8883,8884);

# [Static ip]

# You can change the addr to your ip config to listen to a specific address

$addr='0.0.0.0';
$ports_a = $ports -join ",";

# Remove Firewall Exception Rules

iex "Remove-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' ";

# adding Exception Rules for inbound and outbound Rules

iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Outbound -LocalPort $ports_a -Action Allow -Protocol TCP";
iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Inbound -LocalPort $ports_a -Action Allow -Protocol TCP";

for( $i = 0; $i -lt $ports.length; $i++ ){
  $port = $ports[$i];
  iex "netsh interface portproxy delete v4tov4 listenport=$port listenaddress=$addr";
  iex "netsh interface portproxy add v4tov4 listenport=$port listenaddress=$addr connectport=$port connectaddress=$remoteport";
}

Open Task Scheduler and add click “Create Task” Under General - “Check run whether user is logged in or not” and “Run with the highest privileges” Under triggers click New, Begin the task at logon of any user Under Actions click New, Select Start a program and type in program/script ‘Powershell.exe’ in arguments type ‘-ExecutionPolicy Bypass c:\Users\User\hass.ps1’ (Change the path to your saved script file)

(Optional: Under settings you can check “if the task fails, restart every X minutes” if you’re having issues)

hit OK.