Running Home Assistant on a Raspberry Pi 3 from an external hard drive
After testing out Home Assistant on my Raspberry Pi 3 for a few weeks, I've decided to try out a fresh installation on an external hard drive attached to my Pi. I've read a few horror stories about SD cards burning out easily from the reads/writes, and wanted something that would be a bit more stable, with more free space for serving video and music files.
I picked up a 2TB My Passport external hard drive, which should be plenty of storage space for now.
Instead of flashing the drive with the Home Assistant image, I decided that I want to run Home Assistant in a virtual environment inside of Raspberry Pi OS. This way, I still have access to the file system for future development. I also plan to run the scripts for my fan hack from this device.
Index
- Preparing the Pi
- Flashing Raspberry Pi OS on the drive
- Booting from the drive
- Installing packages and Python 3.9
- Creating a Home Assistant virtual environment
- Adding a daemon to start Home Assistant automatically
Preparing the Pi
First off, I had a Raspberry Pi already running Raspberry Pi OS off of an SD card, so the first thing to do is to enable USB boot mode.
From the terminal on the Pi, I ran this command:
echo program_usb_boot_mode=1 | sudo tee -a /boot/config.txt
This sets a bit in the Raspberry Pi's memory that allows it to be booted from a USB device. From what I read, it's not required from 3+ forward, but because I'm working with a Pi 3, I needed to set that bit.
Then, I rebooted with sudo reboot
and after rebooting, checked that the boot mode has been set with vcgencmd otp_dump | grep 17
. The value should be 3020000a.
I then removed the SD card from my Pi, because it will still boot from the SD card instead of the USB drive if it finds the card.
Flashing Raspberry Pi OS on the drive
These next steps are being done from my Linux desktop machine, not the Raspberry Pi.
I downloaded Raspberry Pi OS Lite from raspberrypi.org. I decided that I'm going to run the Pi headless (without an attached screen, keyboard, or mouse), so I don't need the larger desktop version. After the download finished, I extracted the OS image.
Then, I downloaded Etcher to flash the OS image to the drive. After connecting the drive to my Linux computer, I opened Etcher, selected the Pi OS image, selected the external drive, then clicked the button to flash. A few seconds later, I had Raspberry Pi OS Lite on my external drive.
However, before I can attach the drive to the Pi, I needed to do a few more things to be able to log in to the Pi through SSH.
First, I navigated to the boot partition of the drive. For me, this was under /media/maryknize/boot
. To enable SSH on boot, there needs to be an empty file called "ssh" in the boot partition. So simply touch ssh
, and there's the file!
Since I'm not using an ethernet cable to access the internet on my Pi, I also need to configure wireless networking per these instructions in the same partition. I typed vim wpa_supplicant.conf
into the terminal and added this to the file:
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=<Insert 2 letter ISO 3166-1 country code here>
network={
ssid="<Name of your wireless LAN>"
psk="<Password for your wireless LAN>"
}
Booting from the drive
After all of that was done, I could eject the two partitions from my Linux computer and unplug the USB drive. I plugged the drive into my Raspberry Pi, then connected the power supply. I could see the light flashing on the drive and hear it clicking a bit, but until I could get logged in via SSH, I wouldn't know for sure if it worked. It needs a few minutes on the first startup before you can log in.
To log in to SSH, you need to know the local IP address of the Pi. To find that, I like to use a free app called Fing. I started using Fing a few years ago to check out an AirBnB's wireless network to make sure there weren't any hidden cameras, and now I use it to check the health of devices on my home network.
After finding the local IP address, I logged in with ssh pi@192.168.0.47
and the default password raspberry
.
Installing packages and Python 3.9
Raspberry Pi OS Lite comes with very little as far as packages, so the first thing I did was sudo apt-get install vim
so I have a text editor.
Then, I installed additional packages that I knew Home Assistant was going to need sudo apt-get install python3-pip python3-dev python3-venv autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev pkg-config libavformat-dev libavcodec-dev libavdevice-dev libavutil-dev libswscale-dev libavresample-dev libavfilter-dev libsqlite3-dev ffmpeg
.
To install Home Assistant in a virtual environment I need Python 3.8 or later, but python3 -V
tells me that the default version of Python on my Pi is 3.7.3. So, I have to install the latest version of Python.
To download Python 3.9.1: curl https://www.python.org/ftp/python/3.9.1/Python-3.9.1.tar.xz --output Python-3.9.1.tar.xz
.
Then,
tar xf Python-3.9.1.tar.xz
cd Python-3.9.1/
./configure --enable-optimizations
make
sudo make install
Note that make
takes a very long time, so just be patient and eat a piece of leftover pizza.
Now, python3 -V
still says 3.7.3, but python3.9 -V
says 3.9.1, and I'm good with that.
Creating a Home Assistant virtual environment
cd ~
python3.9 -m venv homeassistant
cd homeassistant/
source bin/activate
python3 -m pip install homeassistant
The final command to start Home Assistant is hass --open-ui
. The next step is onboarding Home Assistant.
Adding a daemon to start Home Assistant automatically
If my Pi ends up losing power for some reason, I want Home Assistant to be able to restart automatically. For that, I'm going to create a system daemon, and then start Home Assistant.
sudo vim /etc/systemd/system/home-assistant@pi.service
Inside of the file, type:
[Unit]
Description=Home Assistant
After=network-online.target
[Service]
Type=simple
User=%i
WorkingDirectory=/home/%i/.homeassistant
ExecStart=/home/pi/homeassistant/bin/hass -c "/home/%i/.homeassistant"
[Install]
WantedBy=multi-user.target
Then, reload systemd, enable the script to start on boot, and then start the service.
sudo systemctl --system daemon-reload
sudo systemctl enable home-assistant@pi
sudo systemctl start home-assistant@pi