Setting up Home Assistant in a virtual environment on Intel NUC (or any other x86 machine)

Setting up Home Assistant in a virtual environment on Intel NUC
(with mqtt, ssh, samba, docker…)
based on Ubuntu Server 17.10 / Intel NUC7i3BNH

by cvoid

Originally for Taymurf (Taymurf#0781 on DiscordHA)

Big thanks to him for beta testing and motivating me to do this!

Keybase ID

cvoid on GitHub

cvoid#4858 on Discord HA Server

V 0.1 (Jan 2018) tested on HomeAssistant Release 0.62.1

Main reason for writing this “How-to” is to give a helping hand to those willing to switch their working appliance to something more powerful.

I recently moved from a Raspberry Pi 3 to an Intel NUC and these were the initial steps I took…

I changed some (imho) basic settings in the system to ensure a basic level of minimum security.

I am not a Linux Guru nor a nationwide “Security Consultant” so any constructive criticism or advice on how I can improve this guide is greatly appreciated.

I mainly use “vim” for editing files.

Feel free to use any other editor of your choice (i.e. nano). The following wildcards (placeholders) will be used throughout the text:

EDITOR – Replace with whatever editing program you prefer to use.
USER – Replace with your main user account
HAUSER – Replace with your Home Assistant user account

Greetings to the whole community (especially the devs!) and thanks for making this stunning project so vital and awesome.

0.) PREAMBLE

If anything isn’t working as it should, contact me on any of my mentioned channels.
I try to respond as soon as possible!
If you need general help visit https://home-assistant.io/help/

PLEASE KEEP IN MIND:
THIS IS NOT AN OFFICIAL DOCUMENT MAINTAINED BY HOME ASSISTANT!
This is a written account of what has worked for me and tested by another user of
Home Assistant making the switch from a Raspberry Pi 3 to an Intel NUC.

1.) BEFORE INSTALL

Update to the latest BIOS Version and adjusting it

Download the appropriate Version for your System from https://downloadcenter.intel.com/.
Detailed instructions how to update are found here: https://www.intel.com/content/www/us/en/support/articles/000005636/mini-pcs.html

Initial upgrade failed for me with any USB Stick larger 64GB.

Basically, format any USB Stick with exFAT (respectively FAT32) and copy the *.bio file onto it.

Insert the Stick into a USB Port of your choice and shutdown the PC.
Reboot into the BIOS Updater by pressing “F7” while starting up the NUC.

Select the stick and file you copied earlier and wait for it to complete.

Reboot to the BIOS (Press F2)

Changes I made to the BIOS include selecting the “Quiet” model for the fans and disabled any lighting for HDD activity. I prefer a quiet and stealthy device on my shelf.

2.) INSTALLATION

Download the Ubuntu Server (https://www.ubuntu.com/download/server)

Use Etcher or rufus (Etcher: https://etcher.io/ / rufus: http://rufus.akeo.ie/) on Windows to flash the image to an USB Stick of your choice.

Any Stick should work.

On Linux: Stick to: https://help.ubuntu.com/community/Installation/FromUSBStick
On MacOS: Etcher is also available.
In general any *NIX based system with “dd” should work.

Connect a Keyboard, a monitor and an ethernet cable to your PC. Initial networking setup is done via DHCP, most routers will assign an IPv4/IPv6. If not, assign a static ip and gateway manually (If DHCP fails, the installer will tell you).

Insert the Stick and reboot, the Ubuntu Installer should come up (if not, enter the Boot Menu from the BIOS and select your stick).

Select your prefered Language/Region and choose a username/password of your choice.

Later we will set a strong password to this user. Main configuration and maintenance of the system is done by that user via sudo. By default, Ubuntu does not allow any direct logins with the “root” user (which makes sense imho).

I decided NOT to setup an encrypted home container. Please keep in mind that all information stored on the harddrive could easily be read by anyone with physical access to the system (I.e. if it gets stolen).

Maybe I will add the Setup of LUKS/LVM in a future version or update this how-to if there is some public demand.

Check the determined Timezone and correct the Settings if necessary.

In my setup I select “Guided – use entire disk and set up LVM” for the server.
LVM makes it easy to add some hard drive space in the future if needed.
LVM means “Logical Volume Manager” and is more powerful than playing around with “parted” and “mkfs.X”

Read more about LVM and why it is good here: https://wiki.ubuntu.com/Lvm

Wait for “apt” to finish. I’ve decided to let the system maintain it’s security updates automatically.
If you are the natural born sysadmin feel free to keep updating in your hand.

Install OpenSSH Server and Samba in the next dialogue simply by marking it with an asterisk.

SSH will handle our remote connection and Samba is used for editing the HASS config in a Windows share.

Install GRUB to the MBR if you don’t want to setup a multi-OS system (what i guess you don’t want to).

Remove the Stick, hit <Continue> and watch your server come to life!

Login in with the user and password created earlier.

3.) INITIAL SYSTEM CONFIG

After logging in for the first time, use

 sudo -s 

and enter your password to become the root user.

Remember this command, you will need it many times…

First we will do some updates. Use

apt-get update && apt-get full-upgrade -y

to update all packages installed at this point.

sudo:

As seen before working as the root user is vital. Later, we will change the password for the user to something more complex and secure.

The Login to System with your default user will later be strengthened with an openssh key login. I decided to give this user the permission to use “sudo” without typing the password all the time.

PLEASE KEEP IN MIND:
Everybody with your password (or ssh key) is able to modify, read or delete anything on that system!

type

cd /etc/sudoers.d && EDITOR 010_USER-nopasswd

to change the directory and create an empty config file (replace USER with your own user).

BE VERY CAREFUL ON THIS STEP:
if you enter anything wrong in this file and save it (giving you a syntax error) you will most likely have to rnstall your server. It only takes about 10 minutes to do over, but it’s a hassle.
It is possible to regain access with any “Linux Live Media” but that would go beyond the scope of the document.

Enter

USER ALL=(ALL) NOPASSWD: ALL

and save the file and after that

sudo -k

for applying the changes.

Next time any use of the sudo command won’t prompt you for a password. If you want to, logout with “logout” (or Ctrl + D ) an re-login.
The command “sudo whoami” should output “root” without any password requested.

Sample output:

root@hostname:~# cd /etc/sudoers.d
root@hostname:/etc/sudoers.d# nano 010_USER-nopasswd
root@hostname:/etc/sudoers.d# cat 010_USER-nopasswd
USER ALL=(ALL) NOPASSWD: ALL

Setting up a static IP for the system:

I don’t want to rely on any DHCP Daemon for assigning a IP to my HASS server. If for whatever reason your DHCP server fails or the static route in your router is lost you won’t be able to connect to it.

Type

ip link show

to find out the device name of your ethernet card.

root@hostname:~# ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000

.

.

In my case the network device is named “eno1”. Yours may differ.

My server will listen to the Address “192.168.0.10” and use the Google DNS Servers (8.8.8.8,8.8.4.4).

IMPORTANT!
Change those to whatever you want but KEEP IN MIND this address has be unique and should not appear in your DHCP daemons ip pool.
Usually every DHCP Daemon reservers a “pool” for assigning IP Addresses.
In my case I configured the DHCP service with a static address 192.168.0.10 for HomeAssistant and a pool range from 192.168.0.200 to 192.168.0.254.

If unsure about your net settings use “ifconfig” to display the actual settings of your network card and “ip route |grep default” for the gateway address

Sample for my network:

root@hostname:~# ifconfig eno1
eno1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.0.10 netmask 255.255.255.0 broadcast 192.168.0.255
ether ff:ff:ff:ff:ff:ff txqueuelen 1000 (Ethernet)
RX packets 31680033 bytes 40287320994 (40.2 GB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 17808340 bytes 2638877725 (2.6 GB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

root@hostname:~# ip route |grep default
default via 192.168.0.1 dev eno1 proto static

In previous Ubuntu Version static interfaces were configured in “/etc/network/interfaces”. This changed in Ubuntu 17.10.

Use “cd /etc/netplan” to change to config directory as root (“sudo -s” if you are not already root).

*NOTE:
.yaml files are very sensitive to indenting properly so make sure you follow the spacing of the file and don’t just copy and paste what I have here.

For an example of what it should look like with proper indents,use

wget -O 01-netcfg.yaml https://chris.0x711.de/01-netcfg.yaml

to store a local copy of my config.

Use

EDITOR 01-netcfg.yaml

to alter the configuration.

Change to the following (altered to match your config) and save:

# This file describes the network interfaces available on your system
# For more information, see netplan(5).
network:
  version: 2
  renderer: networkd
  ethernets:
    eno1:
      dhcp4: no
      dhcp6: no
      addresses: [192.168.0.27/24]
      gateway4: 192.168.0.1
      nameservers:
        addresses: [8.8.8.8,8.8.4.4]

use

netplan apply

to execute the changes.Check if everything works:
type

ip addr|grep inet

the output should be something like:

root@hostname:~# ip addr|grep inet
inet 127.0.0.1/8 scope host lo
inet 192.168.0.10/24 brd 192.168.0.255 scope global eno1

use

ping -c 5 home-assistant.io

to test the internet connectivity:

root@metis:~# ping -c 5 home-assistant.io
PING home-assistant.io (104.31.87.190) 56(84) bytes of data.
64 bytes from 104.31.87.190 (104.31.87.190): icmp_seq=1 ttl=57 time=11.1 ms
64 bytes from 104.31.87.190 (104.31.87.190): icmp_seq=2 ttl=57 time=10.3 ms
64 bytes from 104.31.87.190 (104.31.87.190): icmp_seq=3 ttl=57 time=10.5 ms
64 bytes from 104.31.87.190 (104.31.87.190): icmp_seq=4 ttl=57 time=11.6 ms
64 bytes from 104.31.87.190 (104.31.87.190): icmp_seq=5 ttl=57 time=10.6 ms

— home-assistant.io ping statistics —
5 packets transmitted, 5 received, 0% packet loss, time 4004ms
rtt min/avg/max/mdev = 10.320/10.872/11.683/0.501 ms

The ping command send 5 packets to the Home Assistant homepage. You could use any domain for this test (google.com, nasa.gov, xkcd.com….)

More information about netplan is found here: https://wiki.ubuntu.com/Netplan

Time for the first reboot of your machine using “sudo reboot” (Apply the kernel updates and see if the static ip setup works).

After rebooting you could remotely connect to your server.
For doing that in my case (replace the IP with the one you’ve set up above):

Linux/MacOS: ssh -l USER 192.168.0.10

Windows: Use putty (https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html) and enter in hostname your address.

Congratulations! You’ve just set up a Ubuntu server with a static IP-Address on your NUC!

4.) SETTING UP SSHD AND KEY LOGIN

Login to your box and become the “root user” with “sudo -s”.
Use

apt-get install -y pwgen

pwgen is a handy tool for generating passwords.

Use “pwgen 40” to generate some random passwords with the length of 40 characters. Default settings use a-z, 0-9 and some capitalized characters.
If you want to you could mix in some special characters. See “man pwgen”.
For those of you how want to learn more about security and complexity of passwords start with this (very popular) comic:

https://xkcd.com/936/

root@ubuntu:~# pwgen 40
mohFiwie1ilix7aox8maiThid4xeb7goj1eedail
uvohchoo4exa4YaeBei0Deiy9ieh4shaigicheec
Ailiu7Thaisai7ahvei9Eez5ru4IeruChaiceibu
ooShii8eeWieg0saiweeghaeph2cheerae9ieBai
johc4cai7du8ahP5ae1peeSh7eeZu1WaiLohtahP
aiz0shaeshiezeihu1Uneexee5vohcaipaow2nah
Faet5phiesiuQuohzo5dienge5OhMu7gool7ahJa
aighoo0ui2echoovooci4suoti6AeYie3ie1epai
toobiangai8Einguac2phue5Aej0ii1shaeRaaph
feoBoongashii5chaesh4chaedieDohc7ooyeej4
IdoeHa3Ailaeca7luK8etheegee3ooraiF9geeme
Yee3bucei0eghizohthei5aJoquahX7iejeediev
teesohmiiRaeshietheemai9Uungae8no8uguveu
iw7xeiC8phuomahngee5iech9rielodoh1te1ohL
chahKohsai2jie5oohaereiviP6ne8Aixuez2shi
yah2ZooBookoo8egherohJah8otoofahziek4Ohw
ae7ahYiech0uzooc0reipaen2zaiToo2weiru2ai
xoosohra7ahPaiwahf4ieshaiz9uibahVah6ujei
die2booxeaz2ea3euruk0Be0zees4iexeeyoo1oh
ti4seinaefoosaib9ohloo0eilooShuph9chuCh6

Time to change the “installer password” (i had chosen “password” (ultra secure)) to something more complex.

Choose one from your list (NOT MINE!) and type “passwd USER”.

After submitting that command, copy and paste a password of your choice and hit “Enter”.

Ensure you did it right with a new ssh/Putty session and login with your new password.

WARNING: Note down the password in a safe place! You won’t be able to login to your server with the old one anymore!

 

For Windows I use “Keepass” (https://keepass.info/).

A Beginner’s guide can be found here: http://www.petersmittenaar.com/keepass-why-and-how-to-use-it-effectively.php

Continue as USER (if you are still root enter “exit” or press Ctrl + D).

Use

 mkdir .ssh && cd .ssh 

to create a “hidden” directory and change to it.

Create a ssh key with

ssh-keygen -t rsa -b 4096 -C USER2nuc

and save it to USER2nuc (or any other distinct name of your choice).

You could leave the passphrase password empty. Again it is your personal choice and it would without a doubt be more secure to add one.

My server is only in my local network and I store all of my keys on an encrypted drive, so I left it blank for convenience of logging in.

If you ever going to expose the machine (or to be more precise the ssh port) to the open internet do yourself a favor and increase the security with this simple “two factor mechanism”.

(OT: you could use the autotype function in keepass to launch a putty profile and autotype the password)

Next we add the keyfile to a file called “authorized_keys”. To do so:

cat USER2nuc.pub >> authorized_keys

*Note: The command won’t generate any output

USER@ubuntu:~/.ssh$ cat USER2nuc.pub >> authorized_keys
USER@ubuntu:~/.ssh$

Use

 cat USER2nuc 

to display the private key and copy & paste it to some secure space.

If you want to connect from a linux shell to the nuc (assumed you saved the key to /path/to/USER2nuc-keyfile and the remote ip is ..0.10) use this command:

chmod 600 /path/to/keyfile (makes the file only readable by the owner)

and after that

ssh -l USER -i path/to/USER2nuc-keyfile <your-server-ip>

On Windows download and open “putty keygen” from https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html

Use “File” → “Load private key” and select the private key you saved before.
Click on “Save private key” and choose again a safe location.
Putty keygen will create a .ppk file which is needed.

Next step will be editing the openssh daemon config file:

Use “sudo -s” to become root, change the directory and edit the config with

 cd /etc/ssh && EDITOR sshd_config 

Changes I made (remove the leading # to “activate” the options):

Port 2222
.
.
.
# Authentication:

#LoginGraceTime 2m
PermitRootLogin no
StrictModes yes
MaxAuthTries 2
.
.
.
DenyUsers homeassistant

Add the “DenyUsers” line at the bottom of the document.

Save the file and exit the EDITOR.

I changed the port to something not typically “sshd”-associated. Many bots try to bruteforce into poorly administered remote machines. Changing the port is filed under “Security by Obscurity”.
Login for the user “root” is denied in general. Even if someone exploits your machine and changes the root password the intruder can’t login using ssh.

We deny the user “homeassistant” access to the system. In a later section we will add this user to run HASS.

One more discussable option for the config would be “PasswordAuthentication no”.

If you decide to do so please remember: If you lose your openssh/.ppk keyfile you are locked out of the system!

Use “/etc/init.d/ssh restart” to load the new settings.

Open Putty. Enter the IP Address and your new port.

Enter a session name like “HA-nuc” in the lower half of Putty window.
Click on the left side on “Data” under Connection and fill in USER under “Auto-login username”.

Click on “Auth” under “Connection SSH” and supply the path to your private keyfile.ppk created earlier.

Go back to “Session” and hit “Save” on the lower right side.

A double-click onto the profile name will now connect and auto login you to your server!

5.) Setting up the HomeAssistant User and creating a Samba share

Become “root” with “sudo -s” and type “adduser HAUSER

Enter a password of your choice. I used “homeassistant” for both HAUSER and the password because remote login to the machine via ssh is denied. More secure in a general way would be setting up a strong password (see 4.)).

All fields for name etc. are not needed. Just hit enter.

root@hostname:~# adduser HAUSER
Adding user `HAUSER …
Adding new group `HAUSER (1001) …
Adding new user `HAUSER (1001) with group `HAUSER …
Creating home directory `/home/HAUSER …
Copying files from `/etc/skel’ …
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
Changing the user information for homeassistant
Enter the new value, or press ENTER for the default
Full Name []:
Room Number []:
Work Phone []:
Home Phone []:
Other []:
Is the information correct? [Y/n]

To add the HAUSER to more system groups use “adduser HAUSER GROUPNAME”
In my case i want to use a Z-Wave stick and the HAUSER needs to be a member of the group “dialout”.

If any special Home Assistant component will need a special group it is normally documented in the official docs.

I assume samba was installed in the initial setup process if not run

apt-get install samba -y

as root.

WARNING: I’ve decided to create a “public share”. Everybody in your home network could read and modify the files inside the share!

If you don’t want a public share stick to this: Ubuntu | Creating Samba from the console

It might be also a good idea to to disable the autostart of samba and start it only up if you need to modify the configuration of HomeAssistant:

To do so enter “systemctl disable smbd” as root.

systemctl start smbd” is used via ssh to start the service and
systemctl stop smbd” to stop it

Change the Samba config directory and edit the config file with

 cd /etc/samba && EDITOR smb.conf 

I added the following at the end of the file:

[homeassistant]
path = /home/HAUSER/.homeassistant
writeable = yes
guest ok = yes
create mask = 0644
directory mask = 0755
force user = HAUSER

[winshare_USER]
path = /home/USER/winshare
writeable = yes
guest ok = yes
create mask = 0644
directory mask = 0755
force user = USER

Create the folders with

 mkdir /home/USER/winshare 

and

 mkdir -p /home/HAUSER/.homeassistant 

We need to set the correct file permissions to both folders:

Execute that with

 chown -R USER:USER /home/USER

and

 chown -R HAUSER:HAUSER /home/HAUSER

Restart samba with “service smbd restart”.

Test your shares from Windows: Press Windowsbutton + R and enter
“\\192.168.X.Y” (the static ip of your server).

Two folders should appear and you should be able to create or delete files.

6.) Installing the Virtual Environment and (finally) HomeAssistant

Detailed information is found at: https://home-assistant.io/docs/installation/virtualenv/

Start with

 sudo apt-get install python3-pip python3-venv -y 

Do all of the following commands as the HAUSER.

Use

 sudo su -s /bin/bash HAUSER 

to work as HAUSER

Change directory with “cd /home” and run

 python3 -m venv HAUSER
 cd HAUSER && source bin/activate 

actives the virtual environment.

Run

python3 -m pip install wheel

followed by

python3 -m pip install homeassistant

For a first test run

hass --open-ui

HASS is preparing the first start and you should see a lot of installing in the log. Give it some time.

Check “http://<your-ip>:8123” and hopefully there it is! =)

You should find inside the HA Windows samba share some newly generated files (e.g. the configuration.yaml)

Hit “Ctrl + C” once inside the terminal window to stop the process and continue with setting up autostart via systemd.

Enter “exit” to return to your normal user and type “sudo -s” to become root.

Change to “cd /etc/systemd/system” and run
EDITOR home-assistant@HAUSER.service” *NOTE: File will be blank.
Copy over the following and save the file:


[Unit]
Description=Home Assistant
After=network-online.target

[Service]
Type=simple
User=%i
ExecStart=/home/HAUSER/bin/hass -c "/home/HAUSER/.homeassistant"

[Install]
WantedBy=multi-user.target

Run “systemctl –system daemon-reload” to reload the systemd configs and “systemctl enable home-assistant@HAUSER

Sample output:

root@hostname:/etc/systemd/system# systemctl –system daemon-reload
root@hostname:/etc/systemd/system# systemctl enable home-assistant@HAUSER
Created symlink /etc/systemd/system/multi-user.target.wants/home-assistant@HAUSER.service → /etc/systemd/system/home-assistant@HAUSER.service.

Reboot your Machine and wait for HA to come up under “http://<your-ip>:8123”

Congratulations! You’ve just setup your own Ubuntu Server with HASS!

7.) UPDATING AND MANAGEMENT OF THE SERVICE

dale3h made a great command line tool for controlling and managing HomeAssistant

See https://github.com/dale3h/hassctl for more information.

Install it with:

 sudo curl -o /usr/local/bin/hassctl https://raw.githubusercontent.com/dale3h/hassctl/master/hassctl && sudo chmod +x /usr/local/bin/hassctl

Run “hassctl log” once to auto-generate the config files. The program will terminate with an error but we fix that in the next step.

Use “sudo EDITOR /etc/hassctl.conf” and change the paths:

VIRTUAL_ENV= to “/home/HAUSER”
HASS_CONFIG=/home/HAUSER/.homeassistant
HASS_USER=HAUSER

Now test it with “hassctl restart && hassctl log”. You should see Home Assistant rebooting.

To stop the process use “Ctrl + C”.

As a backup (if hassctl stops working for whatever reason) you could manually start, stop or update HomeAssistant with those commands:

Stop: “sudo systemctl stop home-assistant@HAUSER.service
Start: “sudo systemctl start home-assistant@HAUSER.service
Logfile: “sudo journalctl -fu home-assistant@HAUSER.service

Update:

First stop the service (see above) then become the HAUSER:

sudo su -s /bin/bash HAUSER

Change to the homedir and activate the VENV:

cd /home/HAUSER/ && source bin/activate

Upgrade HASS with:

python3 -m pip install --upgrade homeassistant

Use “exit” to leave the virtual environment and use the start command.

8.) OTHER USEFUL SERVICES AND HELPFUL HINTS

Services I would personally advise are mosquitto as a mqtt broker and docker-io.

Mosquitto:

Mqtt offers a widespread and reliable way for communicating with plenty of devices.

See the official component page for further information:

https://home-assistant.io/components/mqtt/

Become root with “sudo -s”.
Use “apt-get install mosquitto mosquitto-clients -y” to install the server and useful tools.

Stop the service with “service mosquitto stop
Change to the configuration directory with “cd /etc/mosquitto

The configuration file (mosquitto.conf) is mainly self explaining.

If you are lazy grab a copy of my config with

wget -O mosquitto.conf https://chris.0x711.de/mosquitto.conf

Use “mosquitto_passwd -c /etc/mosquitto/pwfile MQTTUSERNAME” to create a user called MQTTUSERNAME with a corresponding password.

Restart the service with “service mosquitto restart

Subscribe to your server with “mosquitto_sub -h <your-ip> -p 1883 -t ‘#’ -u MQTTUSERNAME -P MQTT_PASSWORD -v -R

Send a test message from another shell (or Putty session) with:

mosquitto_pub -h <mosquitto-server-ip> -p 1883 -u MQTTUSERNAME -P MQTT_PASSWORD -t test/hello -m world

The output of the stream should display

root@hostname:~# mosquitto_sub -h 192.168.0.10 -p 1883 -t ‘#’ -u test -P test -v -R
test/hello world

Your server is ready to use! For adding another user use “mosquitto_passwd /etc/mosquitto/pwfile ANOTHERUSERNAME” and restart the service.

*Note: You could use the same user on multiple devices but please keep in mind that the “client-id” has to be different.

Docker:

I mainly use docker to generate some neat looking statistics for my sensor data.

To install docker use the command “apt-get install docker.io -y” as root.

Phil Hawthorne made some great articles on how to and why using docker in combination with Home Assistant is a great idea.

See his blog for more information:
https://philhawthorne.com/getting-started-with-grafana-influxdb-for-home-assistant/

Thank you for reading and if this document has helped you in any way let me know it if it was worth the effort and time 😉